nodejs: fix cross compilation for armv7l#220204
Conversation
alyssais
left a comment
There was a problem hiding this comment.
If we truly need to force a 32-bit build system, I think a cleaner way to do it would be to do it in the callPackage invocation. Then we could just do something like
nodejs = (if stdenv.buildPlatform.isx86_64 && stdenv.is32bit then pkgsi686Linux else pkgs).callPackage …
which is nice because then there's one less package set involved in the actual expression, and it prevents adding 64-bit dependencies as well by mistake.
Either way, this needs a comment explaining what's going on, with a link to documentation or reference to the source code so people can understand what's going on, and where to check to see if it can be removed.
I tweaked it a bit. It is probably reasonable requirement.
I added comment but I am unable to find that this is actually required in the documentation. At the same time build really fails with missing 32bit stubs and thus it for sure tries to use 32bit build somewhere inside. The upstream builds it on Ubuntu and thus they might expect that 32bit libraries are just available while that is not the case with nixpkgs. |
alyssais
left a comment
There was a problem hiding this comment.
LGTM but I'd really like there to be an upstream issue about this. They shouldn't be passing -m32 to the native compiler just because they're cross compiling for 32 bit.
|
I only just now saw this, but I do wonder if it may also be fixed by #238377? |
|
@lilyinstarlight I just tested it, and it doesn't help my issue. The issue here is with cross-compilation from amd64 to 32-bit systems. Node requires bitness to match it seems, and for that reason, we need to build it not in an amd64 environment but instead in an x86 one. I suspect that, especially on new Macs that do not have 32-bit arm support (if I remember correctly) it won't even be possible to cross-compile Node to armv7l. |
I create an issue upstream but I am not expecting much nodejs/node#48612. This is a common issue I saw with other bytecode compilers (for example luajit). |
|
FWIW I think this is the relevant code that sets -m32 when cross-compiling in your case. host_cxx_is_biarch is defined at https://github.com/nodejs/node/blob/3205b1936a5c3c21b0c8c568a57b0d2bada366b1/tools/v8_gypfiles/toolchain.gypi#L107-L118 That is, it assumes that x86(-64) (and some other systems) have bi-arch capable toolchains (probably for a reason, see below, but maybe not, this is technical decision is really weird). With the following patch, we successfully get a meaningful error (instead of vague compilation failure due to the missing headers) that leads us to https://github.com/nodejs/node/blob/3205b1936a5c3c21b0c8c568a57b0d2bada366b1/deps/v8/include/v8config.h#L863-L892 (or Detailsdiff --git a/tools/v8_gypfiles/toolchain.gypi b/tools/v8_gypfiles/toolchain.gypi
index 26c6866fa9..658ebd6e86 100644
--- a/tools/v8_gypfiles/toolchain.gypi
+++ b/tools/v8_gypfiles/toolchain.gypi
@@ -109,7 +109,7 @@
host_arch=="s390x" or \
clang==1', {
'variables': {
- 'host_cxx_is_biarch%': 1,
+ 'host_cxx_is_biarch%': 0,
},
}, {
'variables': {
So this seems like an issue with v8 rather than Node.js. At this point I don’t really want to dive deeper into this rabbit hole 🥲 |
|
@Cynerd Could you rebase and resolve merge conflicts on this? If this is what we have to do, I'm mostly alright with this, but it is rather unfortunate |
|
Yes, should be targeting staging given the number of rebuilds. |
|
Rebase and retargeting is done (I am not sure if GitHub sends an email about it). |
There was a problem hiding this comment.
Are there any changes from the buildroot patch? Can we use fetchpatch2 to fetch the patch?
There was a problem hiding this comment.
No changes in the end. I will switch it to fetchpatch.
There was a problem hiding this comment.
I’m not really a fan of conditional patches. Can we apply the patch unconditionally (and replace MAYBE_WRAPPER with an empty string if we are not using an emulator)?
There was a problem hiding this comment.
Ok.. in my eyes, it makes it a bit more complex, but ok. There is also an option to just always use a wrapper because, for the native build, it will work as well.
There was a problem hiding this comment.
Hm, I think a symlink should be enough? IIRC emulator contains additional arguments iff canExecute. Is it the case here?
nixpkgs/lib/systems/default.nix
Lines 285 to 295 in 5d49679
There was a problem hiding this comment.
Ah, OK.
nix-repl> (lib.systems.elaborate "x86_64-linux").canExecute (lib.systems.elaborate "i686-linux")
true
There was a problem hiding this comment.
Yeah for i686 it needs to be a script.
There was a problem hiding this comment.
FWIW I’ve opened PR #324071 to make an emulator a simple executable path in native case.
There was a problem hiding this comment.
With that it should be possible to use only just symlink 👍
There was a problem hiding this comment.
Can we proceed with this PR and update it just once #324071 is merged. It should be later only a minor change in postPath. What do you think?
There was a problem hiding this comment.
Are we using $NIX_CC instead of $NIX_CC_FOR_BUILD in this case? If we don’t need C compiler for build platform, perhaps it makes sense to omit depsBuildBuild entirely if isCrossBitness?
There was a problem hiding this comment.
Yes it should be possible to just drop depsBuildBuild in case of isCrossBitness.
Would it even make sense to always use this magic for cross-compilation and not just when bitness differed? The issue with isCrossBitness is that as far as I can see, this is only extraction for the Nix-supported platforms, but as you linked, v8 actually supports only limited build platforms not actually matching bitness.
There was a problem hiding this comment.
Would it even make sense to always use this magic for cross-compilation and not just when bitness differed?
Yes, sounds reasonable to me. Always using an emulator instead of cross-compiling should make Node.js build faster, see also #321847.
There was a problem hiding this comment.
It is now converted to build always with the patch and with wrapper.
I tested it on amd64 and cross build from amd64 to armv7.
|
This needs a rebase. |
The v8 library supports only limited number of build platforms based on the host architecture. The rule there is the bitness (the mixing of 32bit and 64bit architectures seems to be in most cases disallowed). Thus this adds usage of the emulator of the host platform and builds tools for that.
| patches = patches ++ [ | ||
| (fetchpatch2 { | ||
| name = "add-qemu-wrapper-support.patch"; | ||
| url = "https://github.com/buildroot/buildroot/raw/ecf060a2ff93626fb5fbe1c52b8d42b6ee0fbb5b/package/nodejs/nodejs-src/0001-add-qemu-wrapper-support.patch"; |
There was a problem hiding this comment.
GitHub repository is a mirror, the official Git repository is at https://gitlab.com/buildroot.org/buildroot.
| url = "https://github.com/buildroot/buildroot/raw/ecf060a2ff93626fb5fbe1c52b8d42b6ee0fbb5b/package/nodejs/nodejs-src/0001-add-qemu-wrapper-support.patch"; | |
| url = "https://gitlab.com/buildroot.org/buildroot/-/raw/ecf060a2ff93626fb5fbe1c52b8d42b6ee0fbb5b/package/nodejs/nodejs-src/0001-add-qemu-wrapper-support.patch"; |
| find . -path "./torque_*/**/*.o" -or -path "./v8*/**/*.o" | sort -u >files | ||
| ${if stdenv.buildPlatform.isGnu then '' | ||
| ar -cqs $libv8/lib/libv8.a @files | ||
| $AR -cqs $libv8/lib/libv8.a @files |
There was a problem hiding this comment.
Hm, I’m not sure why this line is conditional. I thought Nixpkgs bintools wrapper handled response files, but maybe that’s not the case here for some reason? I’ll have to double-check that.
|
@Cynerd, I’ve made a few minor adjustments based on this PR and re-implemented buildroot patch in 42fa83e (0001-nodejs-fix-cross-compilation-for-armv7l.patch) so that the emulator trick is upstreamable. What do you think? |
I am ok with that. I tried to compile it and ti seems to work so I would go with your solution. |
|
Note for reviewers: #327653 contains commits from this PR (with slight modifications, see above) and goes further on top of these changes to use ninja for build. @Cynerd, would it be OK to close this PR (since you’ve approved ninja PR)? |
|
@tie Yes. This can be closed. |
Description of changes
The cross build for armv7l requires build to be on i686 (32bit in general). This ensures that and thus fixes build for armv7l.
I am not happy with this solution but I am unable to figure out how to fix cross compilation for amv7l in better way than this.
Things done
sandbox = trueset innix.conf? (See Nix manual)nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/)