How to change `RUSTFLAGS` in `build-rust-package` -- list / string merging problem?

I don’t think nix supports cross-compilation from linux to darwin in general, does it?

If it’s any use, I made a macos runner for GitHub - n8henrie/nix-rust-debug-info: Demo of using rust-lldb to debug nix-built rust binaries that uses my fork of nixpkgs and runs my test script on both linux and macos.

If you wanted to check the output of the CI:

1 Like

I think the infinite recursion happened because RUSTFLAGS needs to be inherited from args, else it will try to infinitely inherit form itself. Does this work?

  lib.optionalAttrs (args ? env.RUSTFLAGS) { env.RUSTFLAGS = args.env.RUSTFLAGS; } //
  lib.optionalAttrs (args ? RUSTFLAGS) { inherit (args) RUSTFLAGS; } // {

I don’t really know, but I wasn’t successful in my attempts. Making a macos runner is a great idea, though.

With the changes above it evaluates on darwin but again fails to provide the debug symbols:

Still running on linux, but seems to have evaluated without infinite recursion: Don't fail due to exit status 42 · n8henrie/nix-rust-debug-info@6d33006 · GitHub

A clue –

Trying to sort out why the darwin outputs aren’t giving me the .dSYM files, I can see in the build logs

nix-rust-debug-info> Running /nix/store/68k7fpwpq6jw7z1ka5zk3g315kbxp018-cargo-auditable-0.6.2/bin/cargo-auditable rustc --crate-name nix_rust_debug_info --edition=2021 src/main.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --crate-type bin --emit=dep-info,link -C embed-bitcode=no -C debuginfo=2 -C split-debuginfo=unpacked -C metadata=6884f6cc803d1e86 -C extra-filename=-6884f6cc803d1e86 --out-dir /private/tmp/nix-build-nix-rust-debug-info.drv-0/source/target/aarch64-apple-darwin/debug/deps --target aarch64-apple-darwin -C linker=/nix/store/k8mrxviw965lv59hqbln3297jwfffm2w-clang-wrapper-16.0.6/bin/cc -C incremental=/private/tmp/nix-build-nix-rust-debug-info.drv-0/source/target/aarch64-apple-darwin/debug/incremental -L dependency=/private/tmp/nix-build-nix-rust-debug-info.drv-0/source/target/aarch64-apple-darwin/debug/deps -L dependency=/private/tmp/nix-build-nix-rust-debug-info.drv-0/source/target/debug/deps -Cpanic=abort

Special attention to:

debuginfo=2 -C split-debuginfo=unpacked

How is it getting -C split-debuginfo=unpacked when we’re explicitly setting split-debuginfo=packed? Where is this being overridden?

Probably because split-debuginfo=packed was not being included in RUSTFLAGS. In your successful attempt, we can see that it’s there at the end, thus overwriting the unpacked flag.

That said, after a few trial and errors, I was able to get it working by adding split-debuginfo=packed only when isDarwinDebug is true. This way, the default behavior for Linux is untouched and we successfully get debug symbols for both systems:

Here is the patch to get this all working:

darwin-debug-symbols.patch
---
 pkgs/build-support/rust/build-rust-package/default.nix | 4 ++++
 pkgs/build-support/rust/hooks/cargo-install-hook.sh    | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/pkgs/build-support/rust/build-rust-package/default.nix b/pkgs/build-support/rust/build-rust-package/default.nix
index a1727c91ba36..bc4ebcf589e4 100644
--- a/pkgs/build-support/rust/build-rust-package/default.nix
+++ b/pkgs/build-support/rust/build-rust-package/default.nix
@@ -82,6 +82,8 @@ let
   targetIsJSON = lib.hasSuffix ".json" target;
   useSysroot = targetIsJSON && !__internal_dontAddSysroot;
 
+  isDarwinDebug = stdenv.isDarwin && buildType == "debug";
+
   sysroot = callPackage ./sysroot { } {
     inherit target;
     shortTarget = stdenv.hostPlatform.rust.cargoShortTarget;
@@ -97,6 +99,8 @@ assert useSysroot -> !(args.doCheck or true);
 
 stdenv.mkDerivation ((removeAttrs args [ "depsExtraArgs" "cargoUpdateHook" "cargoLock" ]) // lib.optionalAttrs useSysroot {
   RUSTFLAGS = "--sysroot ${sysroot} " + (args.RUSTFLAGS or "");
+} // lib.optionalAttrs isDarwinDebug {
+  RUSTFLAGS = "-C split-debuginfo=packed " + (args.RUSTFLAGS or "");
 } // {
   inherit buildAndTestSubdir cargoDeps;
 
diff --git a/pkgs/build-support/rust/hooks/cargo-install-hook.sh b/pkgs/build-support/rust/hooks/cargo-install-hook.sh
index 24a6e6fa9eb3..7dd2c112e3fd 100644
--- a/pkgs/build-support/rust/hooks/cargo-install-hook.sh
+++ b/pkgs/build-support/rust/hooks/cargo-install-hook.sh
@@ -39,6 +39,10 @@ cargoInstallHook() {
     rmdir --ignore-fail-on-non-empty $out/lib $out/bin
     runHook postInstall
 
+    # If present, copy any .dSYM directories for debugging on darwin
+    # https://github.com/NixOS/nixpkgs/issues/330036
+    find "${releaseDir}" -maxdepth 1 -name '*.dSYM' -exec cp -RLt $out/bin/ {} +
+
     echo "Finished cargoInstallHook"
 }
 
-- 
2.45.2

Note: Since the attrset from isDarwinDebug overwrites the previous RUSTFLAGS attrset (when both isDarwinDebug and useSysroot are true), we should probably add a condition for useSysroot:

lib.optionalAttrs isDarwinDebug {
  RUSTFLAGS = "-C split-debuginfo=packed " + lib.optionalString useSysroot "--sysroot ${sysroot} " + (args.RUSTFLAGS or "");
}
1 Like

Wow, that seems to have done it.

Thank you so much for all the time and support, I’m truly grateful!

1 Like