NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
18.21k stars 14.21k forks source link

swift on nixos can't compile hello world: error: undefined reference to '__dso_handle' #242779

Open n8henrie opened 1 year ago

n8henrie commented 1 year ago

Describe the bug

I'm trying swift on NixOS for the first time but I get a linker error. I imagine it's reported elsewhere, but I didn't find this specific error searching open issues or the discourse, so I thought I'd post.

I know swift is mostly MacOS focused, but should this be expected to work?

Steps To Reproduce

$ nix shell github:nixos/nixpkgs#swift -c bash -c "echo 'print(\"hello from swift\")' > hello.swift; swiftc hello.swift"
[0/1 built, 1/56/58 copied (2350.9/2640.2 MiB), 444.1/494.1 MiB DL] fetching swift-5.8 from http
error: link command failed with exit code 1 (use -v to see invocation)
/nix/store/zkjq96ik8cbv6ijh1lylnkk2bni9qvas-binutils-2.40/bin/ld.gold: error: cannot open Scrt1.o: No such file or directory
/nix/store/zkjq96ik8cbv6ijh1lylnkk2bni9qvas-binutils-2.40/bin/ld.gold: error: cannot open crti.o: No such file or directory
/nix/store/zkjq96ik8cbv6ijh1lylnkk2bni9qvas-binutils-2.40/bin/ld.gold: error: cannot open crtbeginS.o: No such file or directory
/nix/store/zkjq96ik8cbv6ijh1lylnkk2bni9qvas-binutils-2.40/bin/ld.gold: error: cannot open crtendS.o: No such file or directory
/nix/store/zkjq96ik8cbv6ijh1lylnkk2bni9qvas-binutils-2.40/bin/ld.gold: error: cannot open crtn.o: No such file or directory
/nix/store/w10qql6406k4g3rbpp8m9nziwsqqh1pv-swift-5.8-lib/lib/swift/linux/x86_64/swiftrt.o:function swift_image_constructor(): error: undefined reference to '__dso_handle'

Expected behavior

I think the above should compile without errors.

Additional context

I tried adding a few different linkers to my nix shell, using nix-locate to find some packages containing the above files (like crtendS.o) and including them in my nix shell, no luck.

I see few posts about swift on NixOS on the discourse, so I suspect it may just not be common to use on non-Darwin?

Notify maintainers

@dtzWill @trepetti @dduan @trundle @stephank

Metadata

Please run nix-shell -p nix-info --run "nix-info -m" and paste the result.

[user@system:~]$ nix-shell -p nix-info --run "nix-info -m"
 - system: `"x86_64-linux"`
 - host os: `Linux 6.1.36, NixOS, 23.05 (Stoat), 23.05.20230709.8df7a67`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.13.3`
 - channels(root): `""`
 - channels(n8henrie): `""`
 - nixpkgs: `/nix/store/qwg77kl125qzjzv9lklfcv48x9jhb0hz-source`
nrhtr commented 1 year ago

That command also fails for me with a slightly different error (probably because I'm on aarch64-darwin), but this command works:

$ nix-shell -E 'with import <nixpkgs> { }; mkShell { packages = [ swift ]; }' --run "echo 'print(\"hello from swift\")' > hello.swift; swiftc hello.swift; ./hello"
hello from swift
n8henrie commented 1 year ago

@nrhtr does it still work with --pure or is there a chance something on Darwin is polluting your env?

nrhtr commented 1 year ago

It does, but I think you're right that something is polluting my env, regardless:

$ otool -L hello
hello:
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.60.1)
    /nix/store/jaz1mic7ss4ka3ln779sam02mmgw1msp-libcxxabi-11.1.0/lib/libc++abi.1.dylib (compatibility version 1.0.0, current version 1.0.0)
    /nix/store/ykbdajlwk2klq5p4wj28jrs8vzsbxyar-libcxx-11.1.0/lib/libc++.1.0.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/swift/libswiftCore.dylib (compatibility version 1.0.0, current version 0.0.0)
    /usr/lib/swift/libswiftSwiftOnoneSupport.dylib (compatibility version 1.0.0, current version 0.0.0)

I tested on my NixOS machine and get the same error as you. It looks like the linker is only searching $CWD for those glibc dependencies, but I don't understand why. Out of curiosity, I managed to symlink things in and compile a binary but it had an unresolvable reference to libdispatch.so (not using a nix store path).

Trundle commented 1 year ago

The swift package relies on setup hooks and nix shell github:nixos/nixpkgs#swift doesn't execute setup hooks, in contrast to nix-shell

n8henrie commented 1 year ago

@nrhtr @Trundle the nix-shell command from above fails for me with the same error:

$ nix-shell --pure -E 'with import <nixpkgs> { }; mkShell { packages = [ swift ]; }' --run "echo 'print(\"hello from swift\")' > hello.swift; swiftc hello.swift; ./hello"
error: link command failed with exit code 1 (use -v to see invocation)
/nix/store/zkjq96ik8cbv6ijh1lylnkk2bni9qvas-binutils-2.40/bin/ld.gold: error: cannot open Scrt1.o: No such file or directory
/nix/store/zkjq96ik8cbv6ijh1lylnkk2bni9qvas-binutils-2.40/bin/ld.gold: error: cannot open crti.o: No such file or directory
/nix/store/zkjq96ik8cbv6ijh1lylnkk2bni9qvas-binutils-2.40/bin/ld.gold: error: cannot open crtbeginS.o: No such file or directory
/nix/store/zkjq96ik8cbv6ijh1lylnkk2bni9qvas-binutils-2.40/bin/ld.gold: error: cannot open crtendS.o: No such file or directory
/nix/store/zkjq96ik8cbv6ijh1lylnkk2bni9qvas-binutils-2.40/bin/ld.gold: error: cannot open crtn.o: No such file or directory
/nix/store/whhpqj3s0zh899j2wpm305cbrcngpaya-swift-5.8-lib/lib/swift/linux/x86_64/swiftrt.o:function swift_image_constructor(): error: undefined reference to '__dso_handle'
clang-15: error: linker command failed with exit code 1 (use -v to see invocation)
/tmp/nix-shell-11378-0/rc: line 3: ./hello: No such file or directory
bitmappergit commented 1 year ago

This is also a problem for me, with the same errors as above on both nixpkgs master and release-23.05. Regardless of if I use flakes or nix-shell.

donn commented 1 year ago

Problem persists when attempting to compile:


This hack at least allows compilation to proceed:

with import <nixpkgs> {}; mkShell.override { stdenv = swift.stdenv; } {
    buildInputs = [
        swift
    ];
}

Unfortunately, there's immediately another problem; as mentioned by @nrhtr, binaries compiled by swiftc are linked against libdispatch.so without a /nix/store path:

libdispatch.so => not found

This can be worked around with an LD_LIBRARY_PATH export/patchelf in a derivation, but then, when attempting to run a file in interpreter mode, this happens:

% swift <(echo "import Foundation")
<unknown>:0: warning: glibc not found for 'x86_64-unknown-linux-gnu'; C stdlib may be unavailable
/proc/self/fd/12:1:8: error: no such module 'Foundation'
import Foundation
       ^

Curiously, the REPL and -e both work fine:

% swift -e "import Foundation; print(\"Hi\")"
Hi
% swift repl
Welcome to Swift version 5.8 (swift-5.8-RELEASE).
Type :help for assistance.
  1> import Foundation
  2>  
donn commented 1 year ago

I can also confirm that using the swift derivation in 0218941ea68b4c625533bead7bbb94ccce52dceb, everything works as expected. It's 5.6 but what are ya gonna do.

stephank commented 1 year ago

Apologies for not responding here sooner.

Swift requires a Clang stdenv. That's the default on Darwin (hence why the command works), but not on Linux. I don't know how you'd select a different stdenv using nix shell or nix-shell.

Maybe we can guard against non-clang stdenv in our wrapper, but I haven't tried.

It does, but I think you're right that something is polluting my env, regardless:

These /usr/lib/ references are normal (and required) on macOS, they're part of ABI stability. They're like system frameworks in that regard. (Trying to link your own libswiftCore results in warnings about duplicate ObjC class definitions and then crashes.)

Unfortunately, there's immediately another problem; as mentioned by @nrhtr, binaries compiled by swiftc are linked against libdispatch.so without a /nix/store path:

That's strange. I used your shell.nix snippet, but added Foundation like so:

with import <nixpkgs> {}; mkShell.override { stdenv = swift.stdenv; } {
    buildInputs = [
        swift
        swiftPackages.Foundation
    ];
}

Then did the following:

$ nix-shell --run 'swiftc -' <<< 'import Foundation; print("Hi")'
$ ldd main 
    linux-vdso.so.1 (0x00007ffd27780000)
    libFoundation.so => /nix/store/dyvnpq6aqbgm0v7yxdqm1adnaf5jr8cs-swift-corelibs-foundation-5.8/lib/swift/linux/libFoundation.so (0x00007f9bcbda3000)
    libswiftGlibc.so => /nix/store/zcpg3gb4nv3i2bn9xs607w8rwab4zx5v-swift-5.8-lib/lib/swift/linux/libswiftGlibc.so (0x00007f9bcbd8e000)
    libm.so.6 => /nix/store/aw2fw9ag10wr9pf0qk4nk5sxi0q0bn56-glibc-2.37-8/lib/libm.so.6 (0x00007f9bcbcae000)
    libpthread.so.0 => /nix/store/aw2fw9ag10wr9pf0qk4nk5sxi0q0bn56-glibc-2.37-8/lib/libpthread.so.0 (0x00007f9bcbca9000)
    libutil.so.1 => /nix/store/aw2fw9ag10wr9pf0qk4nk5sxi0q0bn56-glibc-2.37-8/lib/libutil.so.1 (0x00007f9bcbca2000)
    libdl.so.2 => /nix/store/aw2fw9ag10wr9pf0qk4nk5sxi0q0bn56-glibc-2.37-8/lib/libdl.so.2 (0x00007f9bcbc9d000)
    libswiftDispatch.so => /nix/store/vag67kycn8q6yr7zss991dvyba4vqp9c-swift-corelibs-libdispatch-5.8/lib/libswiftDispatch.so (0x00007f9bcbc6a000)
    libdispatch.so => /nix/store/vag67kycn8q6yr7zss991dvyba4vqp9c-swift-corelibs-libdispatch-5.8/lib/libdispatch.so (0x00007f9bcbc0b000)
    libBlocksRuntime.so => /nix/store/vag67kycn8q6yr7zss991dvyba4vqp9c-swift-corelibs-libdispatch-5.8/lib/libBlocksRuntime.so (0x00007f9bcbc06000)
    libswift_StringProcessing.so => /nix/store/zcpg3gb4nv3i2bn9xs607w8rwab4zx5v-swift-5.8-lib/lib/swift/linux/libswift_StringProcessing.so (0x00007f9bcbb39000)
    libswift_Concurrency.so => /nix/store/zcpg3gb4nv3i2bn9xs607w8rwab4zx5v-swift-5.8-lib/lib/swift/linux/libswift_Concurrency.so (0x00007f9bcbace000)
    libswiftCore.so => /nix/store/zcpg3gb4nv3i2bn9xs607w8rwab4zx5v-swift-5.8-lib/lib/swift/linux/libswiftCore.so (0x00007f9bcb487000)
    libswiftSwiftOnoneSupport.so => /nix/store/zcpg3gb4nv3i2bn9xs607w8rwab4zx5v-swift-5.8-lib/lib/swift/linux/libswiftSwiftOnoneSupport.so (0x00007f9bcb444000)
    libc.so.6 => /nix/store/aw2fw9ag10wr9pf0qk4nk5sxi0q0bn56-glibc-2.37-8/lib/libc.so.6 (0x00007f9bcb25e000)
    libicuuc.so.73 => /nix/store/a0wi3gpccqkr05g454xazcc7c40s8k5c-icu4c-73.2/lib/libicuuc.so.73 (0x00007f9bcb052000)
    libicui18n.so.73 => /nix/store/a0wi3gpccqkr05g454xazcc7c40s8k5c-icu4c-73.2/lib/libicui18n.so.73 (0x00007f9bcad0a000)
    libicudata.so.73 => /nix/store/a0wi3gpccqkr05g454xazcc7c40s8k5c-icu4c-73.2/lib/libicudata.so.73 (0x00007f9bc8e7c000)
    libgcc_s.so.1 => /nix/store/xpxln7rqi3pq4m0xpnawhxb2gs0mn1s0-gcc-12.3.0-lib/lib/libgcc_s.so.1 (0x00007f9bc8e5b000)
    libstdc++.so.6 => /nix/store/xpxln7rqi3pq4m0xpnawhxb2gs0mn1s0-gcc-12.3.0-lib/lib/libstdc++.so.6 (0x00007f9bc8c33000)
    /nix/store/aw2fw9ag10wr9pf0qk4nk5sxi0q0bn56-glibc-2.37-8/lib/ld-linux-x86-64.so.2 => /nix/store/aw2fw9ag10wr9pf0qk4nk5sxi0q0bn56-glibc-2.37-8/lib64/ld-linux-x86-64.so.2 (0x00007f9bcc600000)
    librt.so.1 => /nix/store/aw2fw9ag10wr9pf0qk4nk5sxi0q0bn56-glibc-2.37-8/lib/librt.so.1 (0x00007f9bc8c2c000)
    libswift_RegexParser.so => /nix/store/zcpg3gb4nv3i2bn9xs607w8rwab4zx5v-swift-5.8-lib/lib/swift/linux/libswift_RegexParser.so (0x00007f9bc8b09000)

Looks okay, I think?

n8henrie commented 1 year ago

Interestingly I can run this just fine:

$ nix shell github:nixos/nixpkgs#swift -c swift - <<<'let name = "n8henrie"; print("hello \(name)")'
hello n8henrie

but I get the error with:

$ nix shell github:nixos/nixpkgs#swift -c swiftc - <<<'let name = "n8henrie"; print("hello \(name)")' && ./main
./main: error while loading shared libraries: libdispatch.so: cannot open shared object file: No such file or directory

Using the topmost example straight from the manual doesn't even compile (at least on x86 NixOS):

$ nix-shell -p swift --run 'swiftc -' <<< 'print("Hello world!")'
error: link command failed with exit code 1 (use -v to see invocation)
/nix/store/zkjq96ik8cbv6ijh1lylnkk2bni9qvas-binutils-2.40/bin/ld.gold: error: cannot open Scrt1.o: No such file or directory
/nix/store/zkjq96ik8cbv6ijh1lylnkk2bni9qvas-binutils-2.40/bin/ld.gold: error: cannot open crti.o: No such file or directory
/nix/store/zkjq96ik8cbv6ijh1lylnkk2bni9qvas-binutils-2.40/bin/ld.gold: error: cannot open crtbeginS.o: No such file or directory
/nix/store/zkjq96ik8cbv6ijh1lylnkk2bni9qvas-binutils-2.40/bin/ld.gold: error: cannot open crtendS.o: No such file or directory
/nix/store/zkjq96ik8cbv6ijh1lylnkk2bni9qvas-binutils-2.40/bin/ld.gold: error: cannot open crtn.o: No such file or directory
/nix/store/65f8bphn3caiqykr15nsy8xnikb3b7lk-swift-5.8-lib/lib/swift/linux/x86_64/swiftrt.o:function swift_image_constructor(): error: undefined reference to '__dso_handle'
clang-15: error: linker command failed with exit code 1 (use -v to see invocation)

I can also confirm that using the swift derivation in 0218941

@donn is correct, changing nothing but the nixpkgs version:

$ nix-shell \
    -I nixpkgs=flake:github:nixos/nixpkgs/0218941ea68b4c625533bead7bbb94ccce52dceb \
    -p swift --run 'swiftc -' <<< 'print("Hello world!")'
$ ./main 
Hello world!

Will try running a bisect.

n8henrie commented 1 year ago

Hmm, using swift instead of swiftc gets somewhere:

$ nix shell nixpkgs#swift --command swift - <<< 'print("Hello world!")'
<unknown>:0: warning: glibc not found for 'x86_64-unknown-linux-gnu'; C stdlib may be unavailable
Hello world!

and I can confirm that including using Foundation and overriding stdenv also gets me a working nix develop environment (without the above error).

The nix-shell version:

$ nix-shell -E "with import <nixpkgs> {}; pkgs.mkShell.override { inherit (pkgs.swift) stdenv; } { buildInputs = [ swift swiftPackages.Foundation ]; }" \
    --run "swift -" <<<'import Foundation; print("hello")'
$ ./main
hello

So I guess this can be closed? I mean it would be nice to be able to nix shell nixpkgs#swift and be off to the races, but this isn't too bad.

n8henrie commented 1 year ago

Will try running a bisect.

Ran out of disk space and crashed 😆 Guess I should turn off zfs-auto-snapshot for that directory.

Mathnerd314 commented 1 year ago

I think it is a bit premature to close this without at least documenting the proper command in the manual. The manual currently says that just running swiftc should work.

Mathnerd314 commented 1 year ago

Also when I try to run swift or swiftc on my (recent NixOS-unstable) system, with the nix-shell command in https://github.com/NixOS/nixpkgs/issues/242779#issuecomment-1734561750, I get an illegal instruction. I don't get that with the old 0218941ea68b4c625533bead7bbb94ccce52dceb commit.

ink-splatters commented 11 months ago

Just in case it helps anyone:

Given the latest nixpkgs-unstable on the date:

I'm having success building rather "demanding" https://github.com/jesse-c/AppearanceNotifier which requires among other things, swift package to work:

1. using nix-shell

( corrected: it was initially stated nix shell but that was wrong as it evaluates flake package attributes, being not related to development shells (AFAIK). In fact, this part has how become redundant, as it effectively matches other people's solutions from this thread)

# shell.nix
with import <nixpkgs> { }; mkShell.override { stdenv = swift.stdenv; } {
  buildInputs = with swiftPackages;[
    swift
    swiftpm
    Foundation
    darwin.apple_sdk.frameworks.AppKit
  ];
}
% nix-instantiate --eval '<nixpkgs>' --attr lib.version
"24.05pre554642.f5c27c6136db"

II. using flakes' development shell (nix develop)

# flake.nix
{
  outputs = { self, nixpkgs, flake-utils, }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
      in
      {
        devShells.default = pkgs.mkShell.override { stdenv = pkgs.swift.stdenv; } {
          buildInputs = with pkgs;[
            swift
            swiftpm
            swiftPackages.Foundation
            darwin.apple_sdk.frameworks.AppKit
          ];

          # https://github.com/NixOS/nix/issues/6677
          shellHook = ''
            export PS1='\n\[\033[1;32m\][nix-shell:\w]\$\[\033[0m\] '
          '';
        };
      });
}
$ cat flake.lock | jq '.nodes."nixpkgs".locked.rev'
"0c6d8c783336a59f4c59d4a6daed6ab269c4b361"
nixos-discourse commented 11 months ago

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

https://discourse.nixos.org/t/devenv-nixpkgs-mkshell-override-alternative/36533/1