{ lib, stdenv, pkgsBuildHost, pkgsBuildTarget, pkgsTargetTarget }: rec { # These environment variables must be set when using `cargo-c` and # several other tools which do not deal well with cross # compilation. The symptom of the problem they fix is errors due # to buildPlatform CFLAGS being passed to the # hostPlatform-targeted compiler -- for example, `-m64` being # passed on a build=x86_64/host=aarch64 compilation. envVars = let # As a workaround for https://github.com/rust-lang/rust/issues/89626 use lld on pkgsStatic aarch64 shouldUseLLD = platform: platform.isAarch64 && platform.isStatic && !stdenv.isDarwin; ccForBuild = "${pkgsBuildHost.stdenv.cc}/bin/${pkgsBuildHost.stdenv.cc.targetPrefix}cc"; cxxForBuild = "${pkgsBuildHost.stdenv.cc}/bin/${pkgsBuildHost.stdenv.cc.targetPrefix}c++"; linkerForBuild = ccForBuild; ccForHost = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc"; cxxForHost = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}c++"; linkerForHost = if shouldUseLLD stdenv.targetPlatform && !stdenv.cc.bintools.isLLVM then "${pkgsBuildHost.llvmPackages.bintools}/bin/${stdenv.cc.targetPrefix}ld.lld" else ccForHost; # Unfortunately we must use the dangerous `pkgsTargetTarget` here # because hooks are artificially phase-shifted one slot earlier # (they go in nativeBuildInputs, so the hostPlatform looks like # a targetPlatform to them). ccForTarget = "${pkgsTargetTarget.stdenv.cc}/bin/${pkgsTargetTarget.stdenv.cc.targetPrefix}cc"; cxxForTarget = "${pkgsTargetTarget.stdenv.cc}/bin/${pkgsTargetTarget.stdenv.cc.targetPrefix}c++"; linkerForTarget = if shouldUseLLD pkgsTargetTarget.stdenv.targetPlatform && !pkgsTargetTarget.stdenv.cc.bintools.isLLVM # whether stdenv's linker is lld already then "${pkgsBuildTarget.llvmPackages.bintools}/bin/${pkgsTargetTarget.stdenv.cc.targetPrefix}ld.lld" else ccForTarget; rustBuildPlatform = stdenv.buildPlatform.rust.rustcTarget; rustBuildPlatformSpec = stdenv.buildPlatform.rust.rustcTargetSpec; rustHostPlatform = stdenv.hostPlatform.rust.rustcTarget; rustHostPlatformSpec = stdenv.hostPlatform.rust.rustcTargetSpec; rustTargetPlatform = stdenv.targetPlatform.rust.rustcTarget; rustTargetPlatformSpec = stdenv.targetPlatform.rust.rustcTargetSpec; in { inherit ccForBuild cxxForBuild linkerForBuild rustBuildPlatform rustBuildPlatformSpec ccForHost cxxForHost linkerForHost rustHostPlatform rustHostPlatformSpec ccForTarget cxxForTarget linkerForTarget rustTargetPlatform rustTargetPlatformSpec; # Prefix this onto a command invocation in order to set the # variables needed by cargo. # setEnv = '' env \ '' # Due to a bug in how splicing and pkgsTargetTarget works, in # situations where pkgsTargetTarget is irrelevant # pkgsTargetTarget.stdenv.cc is often simply wrong. We must omit # the following lines when rustTargetPlatform collides with # rustHostPlatform. + lib.optionalString (rustTargetPlatform != rustHostPlatform) '' "CC_${stdenv.targetPlatform.rust.cargoEnvVarTarget}=${ccForTarget}" \ "CXX_${stdenv.targetPlatform.rust.cargoEnvVarTarget}=${cxxForTarget}" \ "CARGO_TARGET_${stdenv.targetPlatform.rust.cargoEnvVarTarget}_LINKER=${linkerForTarget}" \ '' + '' "CC_${stdenv.hostPlatform.rust.cargoEnvVarTarget}=${ccForHost}" \ "CXX_${stdenv.hostPlatform.rust.cargoEnvVarTarget}=${cxxForHost}" \ "CARGO_TARGET_${stdenv.hostPlatform.rust.cargoEnvVarTarget}_LINKER=${linkerForHost}" \ '' + '' "CC_${stdenv.buildPlatform.rust.cargoEnvVarTarget}=${ccForBuild}" \ "CXX_${stdenv.buildPlatform.rust.cargoEnvVarTarget}=${cxxForBuild}" \ "CARGO_TARGET_${stdenv.buildPlatform.rust.cargoEnvVarTarget}_LINKER=${linkerForBuild}" \ "CARGO_BUILD_TARGET=${rustBuildPlatform}" \ "HOST_CC=${pkgsBuildHost.stdenv.cc}/bin/cc" \ "HOST_CXX=${pkgsBuildHost.stdenv.cc}/bin/c++" \ ''; }; } // lib.mapAttrs (old: new: platform: # TODO: enable warning after 23.05 is EOL. # lib.warn "`rust.${old} platform` is deprecated. Use `platform.rust.${new}` instead." lib.getAttrFromPath new platform.rust) { toTargetArch = [ "platform" "arch" ]; toTargetOs = [ "platform" "os" ]; toTargetFamily = [ "platform" "target-family" ]; toTargetVendor = [ "platform" "vendor" ]; toRustTarget = [ "rustcTarget" ]; toRustTargetSpec = [ "rustcTargetSpec" ]; toRustTargetSpecShort = [ "cargoShortTarget" ]; toRustTargetForUseInEnvVars = [ "cargoEnvVarTarget" ]; IsNoStdTarget = [ "isNoStdTarget" ]; }