NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
16.43k stars 12.93k forks source link

pkgsCross.mingw32.stdenv.cc provides slightly incomplete linking environment: `cannot find -lmcfgthread` #156343

Open trofi opened 2 years ago

trofi commented 2 years ago

I was trying to install a few cross-compilers to be available in parallel in a single environment as ${target}-gcc. Looks like mingw one are slightly broken currently. Here is a minimal reproducer:

// $ cat a.c
int main(){}

Porblematic attempt mingw32:

$ nix build -f ~/nm pkgsCross.mingw32.stdenv.cc
$ ./result/bin/i686-w64-mingw32-gcc a.c -o a
/nix/store/wlcxwq9ll6jprhjfn5iwv6mk5ip9g8d1-i686-w64-mingw32-binutils-2.35.2/bin/i686-w64-mingw32-ld: cannot find -lmcfgthread
collect2: error: ld returned 1 exit status

Working gnu32 attempt:

$ nix build -f ~/nm pkgsCross.gnu32.stdenv.cc
$ ./result/bin/i686-unknown-linux-gnu-gcc a.c -o a

Expected behavior

I expect both cases of compiler to be able to link minimal int main(){} example without extra environment settings.

Metadata

$ nix-shell -p nix-info --run "nix-info -m"
 - system: `"x86_64-linux"`
 - host os: `Linux 5.16.0, NixOS, 22.05 (Quokka)`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.6.0pre20211217_6e6e998`
 - channels(root): `"nixos"`
 - nixpkgs: `/nix/var/nix/profiles/per-user/root/channels/nixos`
trofi commented 2 years ago

The following workaround seems to be enough to get working cc:

pkgsCross.mingw32.stdenv.cc.override ({
  extraBuildCommands = ''printf '%s' '-L${pkgsCross.mingw32.windows.mcfgthreads}/lib' >> $out/nix-support/cc-ldflags'';
})
skvadrik commented 2 years ago

A slightly fixed workaround by @trofi that also patches include flags (fixed system-wide Mingw):

pkgsCross.mingw32.stdenv.cc.override ({
    extraBuildCommands = ''
        printf '%s' '-L${pkgsCross.mingw32.windows.mcfgthreads}/lib' >> $out/nix-support/cc-ldflags
        printf '%s' '-I${pkgsCross.mingw32.windows.mcfgthreads.dev}/include' >> $out/nix-support/cc-cflags
    '';
})
yihuang commented 2 years ago

I have the same issue when trying to cross-build golang applications, how do you think we should patch the nixpkgs? it seems not easy to override gcc locally.

alexshpilkin commented 2 years ago

Note that this does not happen if you use the compiler (ostensibly the same one) from a stdenv derivation:

$ nix build --impure --expr '
let pkgs = (builtins.getFlake "nixpkgs").legacyPackages.${builtins.currentSystem};
in pkgs.pkgsCross.mingw32.stdenv.mkDerivation {
name = "a"; src = ./.;
buildPhase = "$CC -o a a.c";
installPhase = "cp a.exe $out";
}'
$ file -L result
result: PE32 executable (console) Intel 80386, for MS Windows

or via a development shell (damn these commands are unpleasant):

$ nix develop --impure --expr '
let pkgs = (builtins.getFlake "nixpkgs").legacyPackages.${builtins.currentSystem};
in pkgs.mkShell.override { stdenv = pkgs.pkgsCross.mingw32.stdenv; } { }'
$ $CC -o a a.c
$ file a.exe
a.exe: PE32 executable (console) Intel 80386, for MS Windows
$ which $CC
/nix/store/pl1qhrxnf33s0my900pnnpbp08xhfdyz-i686-w64-mingw32-stage-final-gcc-debug-wrapper-10.3.0/bin/i686-w64-mingw32-gcc
$ ^D

even though that same (wrapped) compiler outside such a shell is nonfunctional:

$ /nix/store/pl1qhrxnf33s0my900pnnpbp08xhfdyz-i686-w64-mingw32-stage-final-gcc-debug-wrapper-10.3.0/bin/i686-w64-mingw32-gcc -o a a.c
/nix/store/mv3bssklr1g1zwby7bkr62njdh70413s-i686-w64-mingw32-binutils-2.38/bin/i686-w64-mingw32-ld: cannot find -lmcfgthread: No such file or directory
collect2: error: ld returned 1 exit status

Are cross compilers even supposed to be usable that way?

trofi commented 2 years ago

Why not? There might be no other alternative if one wants 5 cross-compilers simultaneously in a single derivation (or more realistically two: 32-bit and 64-bit mingw at the same time).

I personally like to install native compiler and a bunch of cross-compilers system-wide so my ./configure --build=... --host=... && make just works without nix shells on simple projects. I install native compiler as gcc_latest. I'd say pkgsCross.mingw32.stdenv.cc should do exactly the same thing.

milahu commented 1 year ago

printf '%s' '-L${pkgsCross.mingw32.windows.mcfgthreads}/lib' >> $out/nix-support/cc-ldflags

should add whitespace → printf '%s\n' or printf '%s ' or echo

nixos-discourse commented 5 months ago

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/statically-linked-mingw-binaries/38395/1

W1M0R commented 3 weeks ago

This comment of mine should probably belong to this issue instead.