Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nodejs: fix cross-compilation from aarch64-linux to x86_64-linux #238377

Merged
merged 13 commits into from
Aug 28, 2023
Merged
64 changes: 36 additions & 28 deletions pkgs/development/web/nodejs/nodejs.nix
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{ lib, stdenv, fetchurl, openssl, python, zlib, libuv, util-linux, http-parser
{ lib, stdenv, fetchurl, openssl, python, zlib, libuv, util-linux, http-parser, bash
, pkg-config, which, buildPackages
# for `.pkgs` attribute
, callPackage
Expand All @@ -14,6 +14,8 @@
let
inherit (darwin.apple_sdk.frameworks) CoreServices ApplicationServices;

isCross = stdenv.hostPlatform != stdenv.buildPlatform;

majorVersion = lib.versions.major version;
minorVersion = lib.versions.minor version;

Expand Down Expand Up @@ -48,12 +50,17 @@ let
inherit sha256;
};

strictDeps = true;

CC_host = "cc";
CXX_host = "c++";
depsBuildBuild = [ buildPackages.stdenv.cc openssl libuv zlib ];
depsBuildBuild = [ buildPackages.stdenv.cc openssl libuv zlib icu ];

# NB: technically, we do not need bash in build inputs since all scripts are
# wrappers over the corresponding JS scripts. There are some packages though
# that use bash wrappers, e.g. polaris-web.
buildInputs = lib.optionals stdenv.isDarwin [ CoreServices ApplicationServices ]
++ [ zlib libuv openssl http-parser icu ];
++ [ zlib libuv openssl http-parser icu bash ];

nativeBuildInputs = [ which pkg-config python ]
++ lib.optionals stdenv.isDarwin [ xcbuild ];
Expand All @@ -63,14 +70,11 @@ let
moveToDev = false;

configureFlags = let
isCross = stdenv.hostPlatform != stdenv.buildPlatform;
inherit (stdenv.hostPlatform) gcc isAarch32;
in sharedConfigureFlags ++ lib.optionals (lib.versionOlder version "19") [
"--without-dtrace"
] ++ (lib.optionals isCross [
"--cross-compiling"
"--without-intl"
"--without-snapshot"
"--dest-cpu=${let platform = stdenv.hostPlatform; in
if platform.isAarch32 then "arm"
else if platform.isAarch64 then "arm64"
Expand Down Expand Up @@ -116,32 +120,28 @@ let

inherit patches;

postPatch = ''
patchShebangs .

# fix tests
for a in test/parallel/test-child-process-env.js \
test/parallel/test-child-process-exec-env.js \
test/parallel/test-child-process-default-options.js \
test/fixtures/syntax/good_syntax_shebang.js \
test/fixtures/syntax/bad_syntax_shebang.js ; do
substituteInPlace $a \
--replace "/usr/bin/env" "${coreutils}/bin/env"
done
'' + lib.optionalString stdenv.isDarwin ''
sed -i -e "s|tr1/type_traits|type_traits|g" \
-e "s|std::tr1|std|" src/util.h
'';
doCheck = lib.versionAtLeast version "16"; # some tests fail on v14

nativeCheckInputs = [ procps ];
doCheck = false; # fails 4 out of 1453 tests
# Some dependencies required for tools/doc/node_modules (and therefore
# test-addons, jstest and others) target are not included in the tarball.
# Run test targets that do not require network access.
checkTarget = lib.concatStringsSep " " [
"build-js-native-api-tests"
"build-node-api-tests"
"tooltest"
"cctest"
];

# Do not create __pycache__ when running tests.
checkFlags = [ "PYTHONDONTWRITEBYTECODE=1" ];

postInstall = ''
PATH=$out/bin:$PATH patchShebangs $out
HOST_PATH=$out/bin patchShebangs --host $out

${lib.optionalString (enableNpm && stdenv.hostPlatform == stdenv.buildPlatform) ''
mkdir -p $out/share/bash-completion/completions/
HOME=$TMPDIR $out/bin/npm completion > $out/share/bash-completion/completions/npm
${lib.optionalString (enableNpm) ''
mkdir -p $out/share/bash-completion/completions
ln -s $out/lib/node_modules/npm/lib/utils/completion.sh \
$out/share/bash-completion/completions/npm
for dir in "$out/lib/node_modules/npm/man/"*; do
mkdir -p $out/share/man/$(basename "$dir")
for page in "$dir"/*; do
Expand Down Expand Up @@ -203,6 +203,14 @@ let
platforms = platforms.linux ++ platforms.darwin;
mainProgram = "node";
knownVulnerabilities = optional (versionOlder version "18") "This NodeJS release has reached its end of life. See https://nodejs.org/en/about/releases/.";

# Node.js build system does not have separate host and target OS
# configurations (architectures are defined as host_arch and target_arch,
# but there is no such thing as host_os and target_os).
#
# We may be missing something here, but it doesn’t look like it is
# possible to cross-compile between different operating systems.
broken = stdenv.buildPlatform.parsed.kernel.name != stdenv.hostPlatform.parsed.kernel.name;
};

passthru.python = python; # to ensure nodeEnv uses the same version
Expand Down
76 changes: 76 additions & 0 deletions pkgs/development/web/nodejs/trap-handler-backport.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
Backport V8_TRAP_HANDLER_SUPPORTED conditional compilation for trap
handler implementation.

See https://github.com/v8/v8/commit/e7bef8d4cc4f38cc3d5a532fbcc445dc62adc08f

E.g. when cross-compiling from aarch64-linux for x86_64-linux target,
handler-inside-posix.cc is built on aarch64-linux even though it is not
supported; see src/trap-handler/trap-handler.h in v8 for (host, target)
combinations where trap handler is supported.

Note that handler-inside-posix.cc fails to build in the case above.

diff --git a/deps/v8/src/trap-handler/handler-inside-posix.cc b/deps/v8/src/trap-handler/handler-inside-posix.cc
index e4454c378f..17af3d75dc 100644
--- a/deps/v8/src/trap-handler/handler-inside-posix.cc
+++ b/deps/v8/src/trap-handler/handler-inside-posix.cc
@@ -47,6 +47,8 @@ namespace v8 {
namespace internal {
namespace trap_handler {

+#if V8_TRAP_HANDLER_SUPPORTED
+
#if V8_OS_LINUX
#define CONTEXT_REG(reg, REG) &uc->uc_mcontext.gregs[REG_##REG]
#elif V8_OS_DARWIN
@@ -181,6 +183,8 @@ void HandleSignal(int signum, siginfo_t* info, void* context) {
// TryHandleSignal modifies context to change where we return to.
}

+#endif
+
} // namespace trap_handler
} // namespace internal
} // namespace v8
diff --git a/deps/v8/src/trap-handler/handler-inside-win.cc b/deps/v8/src/trap-handler/handler-inside-win.cc
index fcccc78ee5..3d7a2c416a 100644
--- a/deps/v8/src/trap-handler/handler-inside-win.cc
+++ b/deps/v8/src/trap-handler/handler-inside-win.cc
@@ -38,6 +38,8 @@ namespace v8 {
namespace internal {
namespace trap_handler {

+#if V8_TRAP_HANDLER_SUPPORTED
+
// The below struct needed to access the offset in the Thread Environment Block
// to see if the thread local storage for the thread has been allocated yet.
//
@@ -129,6 +131,8 @@ LONG HandleWasmTrap(EXCEPTION_POINTERS* exception) {
return EXCEPTION_CONTINUE_SEARCH;
}

+#endif
+
} // namespace trap_handler
} // namespace internal
} // namespace v8
diff --git a/deps/v8/src/trap-handler/handler-outside-simulator.cc b/deps/v8/src/trap-handler/handler-outside-simulator.cc
index 179eab0659..5e58719e7f 100644
--- a/deps/v8/src/trap-handler/handler-outside-simulator.cc
+++ b/deps/v8/src/trap-handler/handler-outside-simulator.cc
@@ -4,6 +4,9 @@

#include "include/v8config.h"
#include "src/trap-handler/trap-handler-simulator.h"
+#include "src/trap-handler/trap-handler.h"
+
+#if V8_TRAP_HANDLER_SUPPORTED

#if V8_OS_DARWIN
#define SYMBOL(name) "_" #name
@@ -35,3 +38,5 @@ asm(
SYMBOL(v8_probe_memory_continuation) ": \n"
// If the trap handler continues here, it wrote the landing pad in %rax.
" ret \n");
+
+#endif
11 changes: 9 additions & 2 deletions pkgs/development/web/nodejs/v18.nix
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
{ callPackage, openssl, python3, enableNpm ? true }:
{ callPackage, fetchpatch, openssl, python3, enableNpm ? true }:

let
buildNodejs = callPackage ./nodejs.nix {
inherit openssl;
python = python3;
};

in
buildNodejs {
inherit enableNpm;
Expand All @@ -16,5 +15,13 @@ buildNodejs {
./bypass-darwin-xcrun-node16.patch
./revert-arm64-pointer-auth.patch
./node-npm-build-npm-package-logic.patch
./trap-handler-backport.patch
# Fixes target toolchain arguments being passed to the host toolchain when
# cross-compiling. For example, -m64 is not available on aarch64.
(fetchpatch {
name = "common-gypi-cross.patch";
url = "https://github.com/nodejs/node/pull/48597.patch";
hash = "sha256-FmHmwlTxPw5mTW6t4zuy9vr4FxopjU4Kx+F1aqabG1s=";
})
];
}
1 change: 0 additions & 1 deletion pkgs/development/web/nodejs/v20.nix
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ let
inherit openssl;
python = python3;
};

in
buildNodejs {
inherit enableNpm;
Expand Down