1{ lib
2, stdenv
3, pkgsBuildHost
4, pkgsBuildTarget
5, pkgsTargetTarget
6}:
7
8rec {
9 # These environment variables must be set when using `cargo-c` and
10 # several other tools which do not deal well with cross
11 # compilation. The symptom of the problem they fix is errors due
12 # to buildPlatform CFLAGS being passed to the
13 # hostPlatform-targeted compiler -- for example, `-m64` being
14 # passed on a build=x86_64/host=aarch64 compilation.
15 envVars = let
16
17 # As a workaround for https://github.com/rust-lang/rust/issues/89626 use lld on pkgsStatic aarch64
18 shouldUseLLD = platform: platform.isAarch64 && platform.isStatic && !stdenv.isDarwin;
19
20 ccForBuild = "${pkgsBuildHost.stdenv.cc}/bin/${pkgsBuildHost.stdenv.cc.targetPrefix}cc";
21 cxxForBuild = "${pkgsBuildHost.stdenv.cc}/bin/${pkgsBuildHost.stdenv.cc.targetPrefix}c++";
22 linkerForBuild = ccForBuild;
23
24 ccForHost = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc";
25 cxxForHost = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}c++";
26 linkerForHost = if shouldUseLLD stdenv.targetPlatform
27 && !stdenv.cc.bintools.isLLVM
28 then "${pkgsBuildHost.llvmPackages.bintools}/bin/${stdenv.cc.targetPrefix}ld.lld"
29 else ccForHost;
30
31 # Unfortunately we must use the dangerous `pkgsTargetTarget` here
32 # because hooks are artificially phase-shifted one slot earlier
33 # (they go in nativeBuildInputs, so the hostPlatform looks like
34 # a targetPlatform to them).
35 ccForTarget = "${pkgsTargetTarget.stdenv.cc}/bin/${pkgsTargetTarget.stdenv.cc.targetPrefix}cc";
36 cxxForTarget = "${pkgsTargetTarget.stdenv.cc}/bin/${pkgsTargetTarget.stdenv.cc.targetPrefix}c++";
37 linkerForTarget = if shouldUseLLD pkgsTargetTarget.stdenv.targetPlatform
38 && !pkgsTargetTarget.stdenv.cc.bintools.isLLVM # whether stdenv's linker is lld already
39 then "${pkgsBuildTarget.llvmPackages.bintools}/bin/${pkgsTargetTarget.stdenv.cc.targetPrefix}ld.lld"
40 else ccForTarget;
41
42 rustBuildPlatform = stdenv.buildPlatform.rust.rustcTarget;
43 rustBuildPlatformSpec = stdenv.buildPlatform.rust.rustcTargetSpec;
44 rustHostPlatform = stdenv.hostPlatform.rust.rustcTarget;
45 rustHostPlatformSpec = stdenv.hostPlatform.rust.rustcTargetSpec;
46 rustTargetPlatform = stdenv.targetPlatform.rust.rustcTarget;
47 rustTargetPlatformSpec = stdenv.targetPlatform.rust.rustcTargetSpec;
48 in {
49 inherit
50 ccForBuild cxxForBuild linkerForBuild rustBuildPlatform rustBuildPlatformSpec
51 ccForHost cxxForHost linkerForHost rustHostPlatform rustHostPlatformSpec
52 ccForTarget cxxForTarget linkerForTarget rustTargetPlatform rustTargetPlatformSpec;
53
54 # Prefix this onto a command invocation in order to set the
55 # variables needed by cargo.
56 #
57 setEnv = ''
58 env \
59 ''
60 # Due to a bug in how splicing and pkgsTargetTarget works, in
61 # situations where pkgsTargetTarget is irrelevant
62 # pkgsTargetTarget.stdenv.cc is often simply wrong. We must omit
63 # the following lines when rustTargetPlatform collides with
64 # rustHostPlatform.
65 + lib.optionalString (rustTargetPlatform != rustHostPlatform) ''
66 "CC_${stdenv.targetPlatform.rust.cargoEnvVarTarget}=${ccForTarget}" \
67 "CXX_${stdenv.targetPlatform.rust.cargoEnvVarTarget}=${cxxForTarget}" \
68 "CARGO_TARGET_${stdenv.targetPlatform.rust.cargoEnvVarTarget}_LINKER=${linkerForTarget}" \
69 '' + ''
70 "CC_${stdenv.hostPlatform.rust.cargoEnvVarTarget}=${ccForHost}" \
71 "CXX_${stdenv.hostPlatform.rust.cargoEnvVarTarget}=${cxxForHost}" \
72 "CARGO_TARGET_${stdenv.hostPlatform.rust.cargoEnvVarTarget}_LINKER=${linkerForHost}" \
73 '' + ''
74 "CC_${stdenv.buildPlatform.rust.cargoEnvVarTarget}=${ccForBuild}" \
75 "CXX_${stdenv.buildPlatform.rust.cargoEnvVarTarget}=${cxxForBuild}" \
76 "CARGO_TARGET_${stdenv.buildPlatform.rust.cargoEnvVarTarget}_LINKER=${linkerForBuild}" \
77 "CARGO_BUILD_TARGET=${rustBuildPlatform}" \
78 "HOST_CC=${pkgsBuildHost.stdenv.cc}/bin/cc" \
79 "HOST_CXX=${pkgsBuildHost.stdenv.cc}/bin/c++" \
80 '';
81 };
82} // lib.mapAttrs (old: new: platform:
83 # TODO: enable warning after 23.05 is EOL.
84 # lib.warn "`rust.${old} platform` is deprecated. Use `platform.rust.${new}` instead."
85 lib.getAttrFromPath new platform.rust)
86{
87 toTargetArch = [ "platform" "arch" ];
88 toTargetOs = [ "platform" "os" ];
89 toTargetFamily = [ "platform" "target-family" ];
90 toTargetVendor = [ "platform" "vendor" ];
91 toRustTarget = [ "rustcTarget" ];
92 toRustTargetSpec = [ "rustcTargetSpec" ];
93 toRustTargetSpecShort = [ "cargoShortTarget" ];
94 toRustTargetForUseInEnvVars = [ "cargoEnvVarTarget" ];
95 IsNoStdTarget = [ "isNoStdTarget" ];
96}