Files
rust-overlay/lib/mk-component-set.nix

245 lines
8.1 KiB
Nix

# Define component derivations and special treatments.
{
lib,
stdenv,
stdenvNoCC,
gnutar,
autoPatchelfHook,
bintools,
zlib,
gccForLibs,
apple-sdk ? null,
pkgsHostHost,
# The path to nixpkgs root.
path,
toRustTarget,
removeNulls,
}:
{
# Release version of the whole set.
version,
# The host platform of this set.
platform,
# Set of pname -> src
srcs,
# { clippy.to = "clippy-preview"; }
renames,
}:
let
inherit (lib)
elem
mapAttrs
optional
optionalString
;
inherit (stdenv) hostPlatform targetPlatform;
mkComponent =
pname: src:
let
# These components link to `librustc_driver*.so` or `libLLVM*.so`.
linksToRustc = elem pname [
"clippy-preview"
"miri-preview"
"rls-preview"
"rust-analyzer-preview"
"rustc-codegen-cranelift-preview"
"rustc-dev"
"rustfmt-preview"
];
in
stdenvNoCC.mkDerivation rec {
inherit pname version src;
name = "${pname}-${version}-${platform}";
passthru.platform = platform;
# No point copying src to a build server, then copying back the
# entire unpacked contents after just a little twiddling.
preferLocalBuild = true;
nativeBuildInputs = [
gnutar
]
++
# Darwin doesn't use ELF, and they usually just work due to relative RPATH.
optional (!dontFixup && !hostPlatform.isDarwin) autoPatchelfHook
++
# For `install_name_tool`.
optional (hostPlatform.isDarwin && linksToRustc) bintools;
buildInputs =
optional (elem pname [
"rustc"
"cargo"
"llvm-tools-preview"
"rust"
]) zlib
++ optional linksToRustc self.rustc;
# Most of binaries links to `libgcc.so` on Linux, which lives in `gccForLibs.libgcc`
# since https://github.com/NixOS/nixpkgs/pull/209870
# See https://github.com/oxalica/rust-overlay/issues/121
#
# Nightly `rustc` since 2022-02-17 links to `libstdc++.so.6` on Linux,
# which lives in `gccForLibs.lib`.
# https://github.com/oxalica/rust-overlay/issues/73
# See https://github.com/oxalica/rust-overlay/issues/73
#
# FIXME: `libstdc++.so` is not necessary now. Figure out the time point
# of it so we can use `gccForLibs.libgcc` instead.
#
# N.B. `gcc` is a compiler which is sensitive to `targetPlatform`.
# We use `depsHostHost` instead of `buildInputs` to force it ignore the target,
# since binaries produced by `rustc` don't actually relies on this gccForLibs.
depsHostHost = optional (!dontFixup && !hostPlatform.isDarwin) gccForLibs.lib;
dontConfigure = true;
dontBuild = true;
installPhase = ''
runHook preInstall
installerVersion=$(< ./rust-installer-version)
if [[ "$installerVersion" != 3 ]]; then
echo "Unknown installer version: $installerVersion"
fi
mkdir -p "$out"
while read -r comp; do
echo "Installing component $comp"
# We don't want to parse the file and invoking cp in bash due to slow forking.
cut -d: -f2 <"$comp/manifest.in" | tar -cf - -C "$comp" --files-from - | tar -xC "$out"
done <./components
runHook postInstall
'';
postInstall = ''
# Function moves well-known files from etc/
handleEtc() {
if [[ -d "$1" ]]; then
mkdir -p "$(dirname "$2")"
mv -T "$1" "$2"
fi
}
if [[ -e "$out/etc" ]]; then
handleEtc "$out/etc/bash_completion.d" "$out/share/bash-completion/completions"
# Remove if empty. Skip if produced `/etc/target-spec-json-schema.json`.
rmdir --ignore-fail-on-non-empty $out/etc
fi
'';
# Only contain tons of html files. Don't waste time scanning files.
dontFixup = elem pname [
"rust-docs"
"rustc-docs"
];
# Darwin binaries usually just work... except for these linking to rustc from another drv.
postFixup =
optionalString (hostPlatform.isDarwin && linksToRustc) ''
for f in $out/bin/*; do
install_name_tool -add_rpath "${self.rustc}/lib" "$f" || true
done
''
# Wrap the shipped `rust-lld` (lld), which is used by default on some targets.
# Unfortunately there is no hook to conveniently wrap CC tools inside
# derivation and `wrapBintools` is designed for wrapping a standalone
# bintools derivation. We hereby copy minimal of their implementation.
# The `wrap()` is from:
# https://github.com/NixOS/nixpkgs/blob/bfb7a882678e518398ce9a31a881538679f6f092/pkgs/build-support/bintools-wrapper/default.nix#L178
+ optionalString (pname == "rustc") ''
wrap() {
local dst="$1"
local wrapper="$2"
export prog="$3"
export use_response_file_by_default=0
substituteAll "$wrapper" "$dst"
chmod +x "$dst"
}
dsts=( "$out"/lib/rustlib/*/bin/gcc-ld/ld.lld )
if [[ ''${#dsts} -ne 0 ]]; then
mkdir -p $out/nix-support
substituteAll ${
path + "/pkgs/build-support/wrapper-common/utils.bash"
} $out/nix-support/utils.bash
substituteAll ${
path + "/pkgs/build-support/bintools-wrapper/add-flags.sh"
} $out/nix-support/add-flags.sh
substituteAll ${
path + "/pkgs/build-support/bintools-wrapper/add-hardening.sh"
} $out/nix-support/add-hardening.sh
${
let
# This script exists on all platforms, but only in recent nixpkgs.
p = path + "/pkgs/build-support/wrapper-common/darwin-sdk-setup.bash";
in
optionalString (builtins.pathExists p) ''
substituteAll ${p} $out/nix-support/darwin-sdk-setup.bash
''
+ optionalString targetPlatform.isDarwin ''
substituteAll \
${path + "/pkgs/build-support/bintools-wrapper/add-darwin-ldflags-before.sh"} \
$out/nix-support/add-local-ldflags-before.sh
''
}
for dst in "''${dsts[@]}"; do
# The ld.lld is path/name sensitive because itself is a wrapper. Keep its original name.
unwrapped="$(dirname "$dst")-unwrapped/ld.lld"
mkdir -p "$(dirname "$unwrapped")"
mv "$dst" "$unwrapped"
wrap "$dst" ${path + "/pkgs/build-support/bintools-wrapper/ld-wrapper.sh"} "$unwrapped"
done
fi
''
+ optionalString (stdenv.isLinux && pname == "cargo") ''
patchelf --add-needed ${pkgsHostHost.libsecret}/lib/libsecret-1.so.0 $out/bin/cargo
'';
env = lib.optionalAttrs (pname == "rustc") (
{
inherit (stdenv.cc.bintools)
expandResponseParams
shell
suffixSalt
wrapperName
coreutils_bin
;
hardening_unsupported_flags = "";
# These envvars are used by darwin specific scripts.
# See: https://github.com/NixOS/nixpkgs/blob/0a14706530dcb90acecb81ce0da219d88baaae75/pkgs/build-support/bintools-wrapper/default.nix
fallback_sdk = optionalString (apple-sdk != null && targetPlatform.isDarwin) (
apple-sdk.__spliced.buildTarget or apple-sdk
);
}
// lib.mapAttrs (_: lib.optionalString targetPlatform.isDarwin) {
inherit (targetPlatform)
darwinPlatform
darwinSdkVersion
darwinMinVersion
darwinMinVersionVariable
;
}
);
dontStrip = true;
meta =
lib.optionalAttrs
(elem pname [
"rustc"
"rustfmt-preview"
"rust-analyzer-preview"
"cargo"
])
({
mainProgram = lib.removeSuffix "-preview" pname;
});
};
self = mapAttrs mkComponent srcs;
in
removeNulls (self // mapAttrs (alias: { to }: self.${to} or null) renames)