470e6130b3
If RUSTFLAGS is set in the environment, Cargo will ignore rustflags settings in its TOML configuration. So setting RUSTFLAGS=-g (like separateDebugInfo does) to generate debug info breaks dynamically-linked Rust packages on musl. This breakage is visible for any packages that call into C dynamic libraries. If the binary is linked directly to a C dynamic library, it will fail to build, and if it depends on a Rust library which links a C dynamic library, it will segfault at runtime when it tries to call a function from the C library. I noticed this because pkgsMusl.crosvm is broken for this reason, since it sets separateDebugInfo = true. It shouldn't be possible to end up with broken binaries just by using RUSTFLAGS to do something innocuous like enable debug info, so I think that, even though we liked the approach of modiyfing .cargo/config better at the time, it's become clear that it's too brittle, and we should bite the bullet and patch the compiler instead when targetting musl. It does not appear to be necessary to modify the compiler at all when cross-compiling /from/ dynamically-linked Musl to another target, so I'm only checking whether the target system is dynamically-linked Musl when deciding whether to make the modification to the compiler. This reverts commit c2eaaae50d66a933e38256bdf5a3ae43430592a3 ("cargoSetupHook: pass host config flags"), and implements the compiler patching approach instead.
110 lines
3.5 KiB
Nix
110 lines
3.5 KiB
Nix
{ buildPackages
|
|
, callPackage
|
|
, cargo
|
|
, cargo-nextest
|
|
, clang
|
|
, lib
|
|
, makeSetupHook
|
|
, maturin
|
|
, rust
|
|
, rustc
|
|
, stdenv
|
|
, target ? rust.toRustTargetSpec stdenv.hostPlatform
|
|
}:
|
|
|
|
let
|
|
targetIsJSON = lib.hasSuffix ".json" target;
|
|
|
|
# see https://github.com/rust-lang/cargo/blob/964a16a28e234a3d397b2a7031d4ab4a428b1391/src/cargo/core/compiler/compile_kind.rs#L151-L168
|
|
# the "${}" is needed to transform the path into a /nix/store path before baseNameOf
|
|
shortTarget = if targetIsJSON then
|
|
(lib.removeSuffix ".json" (builtins.baseNameOf "${target}"))
|
|
else target;
|
|
ccForBuild = "${buildPackages.stdenv.cc}/bin/${buildPackages.stdenv.cc.targetPrefix}cc";
|
|
cxxForBuild = "${buildPackages.stdenv.cc}/bin/${buildPackages.stdenv.cc.targetPrefix}c++";
|
|
ccForHost = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc";
|
|
cxxForHost = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}c++";
|
|
rustBuildPlatform = rust.toRustTarget stdenv.buildPlatform;
|
|
rustTargetPlatform = rust.toRustTarget stdenv.hostPlatform;
|
|
rustTargetPlatformSpec = rust.toRustTargetSpec stdenv.hostPlatform;
|
|
in {
|
|
cargoBuildHook = callPackage ({ }:
|
|
makeSetupHook {
|
|
name = "cargo-build-hook.sh";
|
|
propagatedBuildInputs = [ cargo ];
|
|
substitutions = {
|
|
inherit ccForBuild ccForHost cxxForBuild cxxForHost
|
|
rustBuildPlatform rustTargetPlatform rustTargetPlatformSpec;
|
|
};
|
|
} ./cargo-build-hook.sh) {};
|
|
|
|
cargoCheckHook = callPackage ({ }:
|
|
makeSetupHook {
|
|
name = "cargo-check-hook.sh";
|
|
propagatedBuildInputs = [ cargo ];
|
|
substitutions = {
|
|
inherit rustTargetPlatformSpec;
|
|
};
|
|
} ./cargo-check-hook.sh) {};
|
|
|
|
cargoInstallHook = callPackage ({ }:
|
|
makeSetupHook {
|
|
name = "cargo-install-hook.sh";
|
|
propagatedBuildInputs = [ ];
|
|
substitutions = {
|
|
inherit shortTarget;
|
|
};
|
|
} ./cargo-install-hook.sh) {};
|
|
|
|
cargoNextestHook = callPackage ({ }:
|
|
makeSetupHook {
|
|
name = "cargo-nextest-hook.sh";
|
|
propagatedBuildInputs = [ cargo cargo-nextest ];
|
|
substitutions = {
|
|
inherit rustTargetPlatformSpec;
|
|
};
|
|
} ./cargo-nextest-hook.sh) {};
|
|
|
|
cargoSetupHook = callPackage ({ }:
|
|
makeSetupHook {
|
|
name = "cargo-setup-hook.sh";
|
|
propagatedBuildInputs = [ ];
|
|
substitutions = {
|
|
defaultConfig = ../fetchcargo-default-config.toml;
|
|
|
|
# Specify the stdenv's `diff` by abspath to ensure that the user's build
|
|
# inputs do not cause us to find the wrong `diff`.
|
|
diff = "${lib.getBin buildPackages.diffutils}/bin/diff";
|
|
|
|
cargoConfig = ''
|
|
[target."${rust.toRustTarget stdenv.buildPlatform}"]
|
|
"linker" = "${ccForBuild}"
|
|
${lib.optionalString (stdenv.buildPlatform.config != stdenv.hostPlatform.config) ''
|
|
[target."${shortTarget}"]
|
|
"linker" = "${ccForHost}"
|
|
''}
|
|
"rustflags" = [ "-C", "target-feature=${if stdenv.hostPlatform.isStatic then "+" else "-"}crt-static" ]
|
|
'';
|
|
};
|
|
} ./cargo-setup-hook.sh) {};
|
|
|
|
maturinBuildHook = callPackage ({ }:
|
|
makeSetupHook {
|
|
name = "maturin-build-hook.sh";
|
|
propagatedBuildInputs = [ cargo maturin rustc ];
|
|
substitutions = {
|
|
inherit ccForBuild ccForHost cxxForBuild cxxForHost
|
|
rustBuildPlatform rustTargetPlatform rustTargetPlatformSpec;
|
|
};
|
|
} ./maturin-build-hook.sh) {};
|
|
|
|
bindgenHook = callPackage ({}: makeSetupHook {
|
|
name = "rust-bindgen-hook";
|
|
substitutions = {
|
|
libclang = clang.cc.lib;
|
|
inherit clang;
|
|
};
|
|
}
|
|
./rust-bindgen-hook.sh) {};
|
|
}
|