*: format non-generated nix files with nixfmt 1.0

This commit is contained in:
oxalica
2025-07-21 01:43:49 -04:00
committed by oxalica
parent e7bb2a4cae
commit cdf4e51314
12 changed files with 975 additions and 587 deletions

View File

@@ -3,6 +3,7 @@
"editor.tabSize": 2,
"files.trimFinalNewlines": true,
"files.insertFinalNewline": true,
"files.trimTrailingWhitespace": true
"files.trimTrailingWhitespace": true,
"editor.formatOnSave": true
}
}

View File

@@ -21,15 +21,19 @@ let
inherit (rust-bin) distRoot;
};
in {
rust-bin = (prev.rust-bin or { }) // {
# The overridable dist url for fetching.
distRoot = import ./lib/dist-root.nix;
} // import ./lib/rust-bin.nix {
inherit lib manifests;
inherit (rust-bin) nightly;
pkgs = final;
};
in
{
rust-bin =
(prev.rust-bin or { })
// {
# The overridable dist url for fetching.
distRoot = import ./lib/dist-root.nix;
}
// import ./lib/rust-bin.nix {
inherit lib manifests;
inherit (rust-bin) nightly;
pkgs = final;
};
# All attributes below are for compatibility with mozilla overlay.
@@ -45,17 +49,24 @@ in {
Select a toolchain from `rust-bin` or using `rustChannelOf` instead.
See also README at https://github.com/oxalica/rust-overlay
'';
fromManifestFile = manifestFilePath: { stdenv, fetchurl, patchelf }@deps: builtins.trace ''
`fromManifestFile` is deprecated.
Select a toolchain from `rust-bin` or using `rustChannelOf` instead.
See also README at https://github.com/oxalica/rust-overlay
'' (overrideToolchain deps (toolchainFromManifestFile manifestFilePath));
fromManifestFile =
manifestFilePath:
{
stdenv,
fetchurl,
patchelf,
}@deps:
builtins.trace ''
`fromManifestFile` is deprecated.
Select a toolchain from `rust-bin` or using `rustChannelOf` instead.
See also README at https://github.com/oxalica/rust-overlay
'' (overrideToolchain deps (toolchainFromManifestFile manifestFilePath));
};
};
rustChannelOf = manifestArgs: toolchainFromManifest (selectManifest manifestArgs);
latest = (prev.latest or {}) // {
latest = (prev.latest or { }) // {
rustChannels = {
stable = rust-bin.stable.latest;
beta = rust-bin.beta.latest;
@@ -63,9 +74,9 @@ in {
};
};
rustChannelOfTargets = channel: date: targets:
(final.rustChannelOf { inherit channel date; })
.rust.override { inherit targets; };
rustChannelOfTargets =
channel: date: targets:
(final.rustChannelOf { inherit channel date; }).rust.override { inherit targets; };
rustChannels = final.latest.rustChannels;
}

View File

@@ -3,18 +3,28 @@
(import <nixpkgs> {
crossSystem = "aarch64-linux";
overlays = [ (import ../..) ];
}).callPackage (
{ mkShell, stdenv, rust-bin, pkg-config, openssl, qemu }:
mkShell {
nativeBuildInputs = [
rust-bin.stable.latest.minimal
pkg-config
];
}).callPackage
(
{
mkShell,
stdenv,
rust-bin,
pkg-config,
openssl,
qemu,
}:
mkShell {
nativeBuildInputs = [
rust-bin.stable.latest.minimal
pkg-config
];
depsBuildBuild = [ qemu ];
depsBuildBuild = [ qemu ];
buildInputs = [ openssl ];
buildInputs = [ openssl ];
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER = "${stdenv.cc.targetPrefix}cc";
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER = "qemu-aarch64";
}) {}
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER = "${stdenv.cc.targetPrefix}cc";
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER = "qemu-aarch64";
}
)
{ }

View File

@@ -4,16 +4,25 @@
config = "x86_64-w64-mingw32";
};
overlays = [ (import ../..) ];
}).callPackage (
{ mkShell, stdenv, rust-bin, windows, wine64 }:
mkShell {
nativeBuildInputs = [
rust-bin.stable.latest.minimal
];
}).callPackage
(
{
mkShell,
stdenv,
rust-bin,
windows,
wine64,
}:
mkShell {
nativeBuildInputs = [
rust-bin.stable.latest.minimal
];
depsBuildBuild = [ wine64 ];
buildInputs = [ windows.pthreads ];
depsBuildBuild = [ wine64 ];
buildInputs = [ windows.pthreads ];
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER = "${stdenv.cc.targetPrefix}cc";
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_RUNNER = "wine64";
}) {}
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER = "${stdenv.cc.targetPrefix}cc";
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_RUNNER = "wine64";
}
)
{ }

View File

@@ -15,18 +15,25 @@
useLLVM = true;
};
overlays = [ (import ../..) ];
}).callPackage (
# We don't need WASI C compiler from nixpkgs, so use `mkShellNoCC`.
{ mkShellNoCC, stdenv, rust-bin, wasmtime }:
mkShellNoCC {
nativeBuildInputs = [ rust-bin.stable.latest.minimal ];
}).callPackage
(
# We don't need WASI C compiler from nixpkgs, so use `mkShellNoCC`.
{
mkShellNoCC,
stdenv,
rust-bin,
wasmtime,
}:
mkShellNoCC {
nativeBuildInputs = [ rust-bin.stable.latest.minimal ];
depsBuildBuild = [ wasmtime ];
depsBuildBuild = [ wasmtime ];
# This is optional for wasm32-like targets, since rustc will automatically use
# the bundled `lld` for linking.
# CARGO_TARGET_WASM32_WASIP1_LINKER =
CARGO_TARGET_WASM32_WASIP1_RUNNER = "wasmtime run";
}) {}
# This is optional for wasm32-like targets, since rustc will automatically use
# the bundled `lld` for linking.
# CARGO_TARGET_WASM32_WASIP1_LINKER =
CARGO_TARGET_WASM32_WASIP1_RUNNER = "wasmtime run";
}
)
{ }

View File

@@ -1,10 +1,15 @@
{ channel ? "stable", profile ? "default" }:
{
channel ? "stable",
profile ? "default",
}:
with import <nixpkgs> { overlays = [ (import ../..) ]; };
mkShell {
nativeBuildInputs = [
(if channel == "nightly" then
rust-bin.selectLatestNightlyWith (toolchain: toolchain.${profile})
else
rust-bin.${channel}.latest.${profile})
(
if channel == "nightly" then
rust-bin.selectLatestNightlyWith (toolchain: toolchain.${profile})
else
rust-bin.${channel}.latest.${profile}
)
];
}

150
flake.nix
View File

@@ -8,83 +8,91 @@
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
};
outputs = { self, nixpkgs }@inputs: let
inherit (nixpkgs) lib;
inherit (lib) filterAttrs mapAttrs' replaceStrings;
outputs =
{ self, nixpkgs }@inputs:
let
inherit (nixpkgs) lib;
inherit (lib) filterAttrs mapAttrs' replaceStrings;
forEachSystem = lib.genAttrs lib.systems.flakeExposed;
forEachSystem = lib.genAttrs lib.systems.flakeExposed;
overlay = import ./.;
overlay = import ./.;
defaultDistRoot = import ./lib/dist-root.nix;
mkManifests = distRoot: import ./lib/manifests.nix { inherit lib distRoot; };
defaultDistRoot = import ./lib/dist-root.nix;
mkManifests = distRoot: import ./lib/manifests.nix { inherit lib distRoot; };
# Builder to construct `rust-bin` interface on an existing `pkgs`.
# This would be immutable, non-intrusive and (hopefully) can benefit from
# flake eval-cache.
#
# Note that this does not contain compatible attrs for mozilla-overlay.
mkRustBin =
{ distRoot ? defaultDistRoot }:
pkgs:
lib.fix (rust-bin: import ./lib/rust-bin.nix {
inherit lib pkgs;
inherit (rust-bin) nightly;
manifests = mkManifests distRoot;
});
# Builder to construct `rust-bin` interface on an existing `pkgs`.
# This would be immutable, non-intrusive and (hopefully) can benefit from
# flake eval-cache.
#
# Note that this does not contain compatible attrs for mozilla-overlay.
mkRustBin =
{
distRoot ? defaultDistRoot,
}:
pkgs:
lib.fix (
rust-bin:
import ./lib/rust-bin.nix {
inherit lib pkgs;
inherit (rust-bin) nightly;
manifests = mkManifests distRoot;
}
);
in {
lib = {
# Internal use only!
_internal = {
defaultManifests = mkManifests defaultDistRoot;
in
{
lib = {
# Internal use only!
_internal = {
defaultManifests = mkManifests defaultDistRoot;
};
inherit mkRustBin;
};
inherit mkRustBin;
overlays = {
default = overlay;
rust-overlay = overlay;
};
# TODO: Flake outputs except `overlay[s]` are not stabilized yet.
packages =
let
select =
version: comps:
if comps ? default then
comps.default
// {
minimal = comps.minimal or (throw "missing profile 'minimal' for ${version}");
}
else
null;
result =
rust-bin:
mapAttrs' (version: comps: {
name = if version == "latest" then "rust" else "rust_${replaceStrings [ "." ] [ "_" ] version}";
value = select version comps;
}) rust-bin.stable
// mapAttrs' (version: comps: {
name = if version == "latest" then "rust-nightly" else "rust-nightly_${version}";
value = select version comps;
}) rust-bin.nightly
// mapAttrs' (version: comps: {
name = if version == "latest" then "rust-beta" else "rust-beta_${version}";
value = select version comps;
}) rust-bin.beta;
result' = rust-bin: filterAttrs (name: drv: drv != null) (result rust-bin);
in
forEachSystem (
system:
result' (mkRustBin { } nixpkgs.legacyPackages.${system})
// {
default = self.packages.${system}.rust;
}
);
checks = forEachSystem (import ./tests inputs);
};
overlays = {
default = overlay;
rust-overlay = overlay;
};
# TODO: Flake outputs except `overlay[s]` are not stabilized yet.
packages =
let
select = version: comps:
if comps ? default then
comps.default // {
minimal = comps.minimal or (throw "missing profile 'minimal' for ${version}");
}
else
null;
result = rust-bin:
mapAttrs' (version: comps: {
name = if version == "latest"
then "rust"
else "rust_${replaceStrings ["."] ["_"] version}";
value = select version comps;
}) rust-bin.stable //
mapAttrs' (version: comps: {
name = if version == "latest"
then "rust-nightly"
else "rust-nightly_${version}";
value = select version comps;
}) rust-bin.nightly //
mapAttrs' (version: comps: {
name = if version == "latest"
then "rust-beta"
else "rust-beta_${version}";
value = select version comps;
}) rust-bin.beta;
result' = rust-bin: filterAttrs (name: drv: drv != null) (result rust-bin);
in
forEachSystem (system:
result' (mkRustBin {} nixpkgs.legacyPackages.${system})
// { default = self.packages.${system}.rust; }
);
checks = forEachSystem (import ./tests inputs);
};
}

View File

@@ -4,13 +4,22 @@ let
inherit (builtins) match isString toString;
inherit (lib)
attrNames concatMap elemAt filter hasAttr mapAttrs mapAttrs' removeSuffix;
attrNames
concatMap
elemAt
filter
hasAttr
mapAttrs
mapAttrs'
removeSuffix
;
targets = import ../manifests/targets.nix // { _ = "*"; };
targets = import ../manifests/targets.nix // {
_ = "*";
};
renamesList = import ../manifests/renames.nix;
profilesList = import ../manifests/profiles.nix;
# Extensions for mixed `rust` pkg.
components = [
"rustc"
@@ -32,85 +41,121 @@ let
"rustc-docs"
"rust-src" # This has only one special target `*`
];
rustPkgExtra = pkgs: target: let
singleTargetTups = map
(pkg: { inherit pkg target; })
(filter (p: hasAttr p pkgs && hasAttr target pkgs.${p}.target) singleTargetExtensions);
multiTargetTups = concatMap
(pkg: map (target: { inherit pkg target; }) (attrNames pkgs.${pkg}.target))
(filter (p: hasAttr p pkgs) multiTargetExtensions);
in {
components = map (pkg: { inherit pkg target; }) components;
extensions = singleTargetTups ++ multiTargetTups;
};
rustPkgExtra =
pkgs: target:
let
singleTargetTups = map (pkg: { inherit pkg target; }) (
filter (p: hasAttr p pkgs && hasAttr target pkgs.${p}.target) singleTargetExtensions
);
multiTargetTups = concatMap (
pkg: map (target: { inherit pkg target; }) (attrNames pkgs.${pkg}.target)
) (filter (p: hasAttr p pkgs) multiTargetExtensions);
in
{
components = map (pkg: { inherit pkg target; }) components;
extensions = singleTargetTups ++ multiTargetTups;
};
# Uncompress the compressed manifest to the original one
# (not complete but has enough information to make up the toolchain).
uncompressManifest = channel: version: {
v, # Rustc version
d, # Date
r, # Renames index
p ? null, # Profiles index
...
}@manifest: rec {
uncompressManifest =
channel: version:
{
v, # Rustc version
d, # Date
r, # Renames index
p ? null, # Profiles index
...
}@manifest:
rec {
# Version used for derivation.
version = if match ".*(nightly|beta).*" v != null
then "${v}-${d}" # 1.51.0-nightly-2021-01-01, 1.52.0-beta.2-2021-03-27
else v; # 1.51.0
# Version used for derivation.
version =
if match ".*(nightly|beta).*" v != null then
"${v}-${d}" # 1.51.0-nightly-2021-01-01, 1.52.0-beta.2-2021-03-27
else
v; # 1.51.0
date = d;
renames = mapAttrs (from: to: { inherit to; }) (elemAt renamesList r);
date = d;
renames = mapAttrs (from: to: { inherit to; }) (elemAt renamesList r);
pkg =
mapAttrs (pkgName: { u ? null /* Version appears in URL */, ... }@hashes: {
# We use rustc version for all components to reduce manifest size.
# This version is just used for component derivation name.
version = "${v} (000000000 ${d})"; # "<version> (<commit-hash> yyyy-mm-dd)"
target = let
results = mapAttrs' (targetIdx: hash: let
target = targets.${targetIdx};
pkgNameStripped = removeSuffix "-preview" pkgName;
targetTail = if targetIdx == "_" then "" else "-" + target;
urlVersion =
if u != null then u # Use specified version for URL if exists.
else if channel == "stable" then v # For stable channel, default to be rustc version.
else channel; # Otherwise, for beta/nightly channel, default to be "beta"/"nightly".
in {
name = target;
value =
# Normally, hash is just the hash.
if isString hash then
{
xz_url = "${distRoot}/${date}/${pkgNameStripped}-${urlVersion}${targetTail}.tar.xz";
xz_hash = hash;
} // (if pkgName == "rust" then rustPkgExtra pkg target else {})
# But hash can be an integer to forward to another URL.
# This occurs in aarch64-apple-darwin rust-docs on 2022-02-02.
else
results.${targets."_${toString hash}"};
}) (removeAttrs hashes ["u"]);
in
results;
}) (removeAttrs manifest ["v" "d" "r" "p"]);
pkg =
mapAttrs
(
pkgName:
{
# Version appears in URL
u ? null,
...
}@hashes:
{
# We use rustc version for all components to reduce manifest size.
# This version is just used for component derivation name.
version = "${v} (000000000 ${d})"; # "<version> (<commit-hash> yyyy-mm-dd)"
target =
let
results = mapAttrs' (
targetIdx: hash:
let
target = targets.${targetIdx};
pkgNameStripped = removeSuffix "-preview" pkgName;
targetTail = if targetIdx == "_" then "" else "-" + target;
urlVersion =
if u != null then
u # Use specified version for URL if exists.
else if channel == "stable" then
v # For stable channel, default to be rustc version.
else
channel; # Otherwise, for beta/nightly channel, default to be "beta"/"nightly".
in
{
name = target;
value =
# Normally, hash is just the hash.
if isString hash then
{
xz_url = "${distRoot}/${date}/${pkgNameStripped}-${urlVersion}${targetTail}.tar.xz";
xz_hash = hash;
}
// (if pkgName == "rust" then rustPkgExtra pkg target else { })
# But hash can be an integer to forward to another URL.
# This occurs in aarch64-apple-darwin rust-docs on 2022-02-02.
else
results.${targets."_${toString hash}"};
}
) (removeAttrs hashes [ "u" ]);
in
results;
}
)
(
removeAttrs manifest [
"v"
"d"
"r"
"p"
]
);
profiles = if p == null
then {}
else elemAt profilesList p;
profiles = if p == null then { } else elemAt profilesList p;
targetComponentsList = [
"rust-std"
"rustc-dev"
"rustc-docs"
];
};
targetComponentsList = [
"rust-std"
"rustc-dev"
"rustc-docs"
];
};
uncompressManifestSet = channel: set: let
ret = mapAttrs (uncompressManifest channel) (removeAttrs set ["latest"]);
in ret // { latest = ret.${set.latest}; };
uncompressManifestSet =
channel: set:
let
ret = mapAttrs (uncompressManifest channel) (removeAttrs set [ "latest" ]);
in
ret // { latest = ret.${set.latest}; };
in {
stable = uncompressManifestSet "stable" (import ../manifests/stable);
beta = uncompressManifestSet "beta" (import ../manifests/beta);
in
{
stable = uncompressManifestSet "stable" (import ../manifests/stable);
beta = uncompressManifestSet "beta" (import ../manifests/beta);
nightly = uncompressManifestSet "nightly" (import ../manifests/nightly);
}

View File

@@ -1,5 +1,19 @@
{ lib, stdenv, symlinkJoin, pkgsTargetTarget, bash, curl, rustc }:
{ pname, version, date, selectedComponents, availableComponents ? selectedComponents }:
{
lib,
stdenv,
symlinkJoin,
pkgsTargetTarget,
bash,
curl,
rustc,
}:
{
pname,
version,
date,
selectedComponents,
availableComponents ? selectedComponents,
}:
let
inherit (lib) optional;
inherit (stdenv) targetPlatform;
@@ -34,12 +48,10 @@ symlinkJoin {
# CC for crate linking.
# Workaround: should be `pkgsHostTarget.cc` but `stdenv`'s cc itself have -1 offset.
# N.B. WASM targets don't need our CC.
propagatedBuildInputs =
optional (!targetPlatform.isWasm) pkgsTargetTarget.stdenv.cc;
propagatedBuildInputs = optional (!targetPlatform.isWasm) pkgsTargetTarget.stdenv.cc;
# Link dependency for target, required by darwin std.
depsTargetTargetPropagated =
optional (targetPlatform.isDarwin) pkgsTargetTarget.libiconv;
depsTargetTargetPropagated = optional (targetPlatform.isDarwin) pkgsTargetTarget.libiconv;
# If rustc or rustdoc is in the derivation, we need to copy their
# executable into the final derivation. This is required

View File

@@ -1,36 +1,53 @@
# 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
{
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
{
# 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 (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
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}";
@@ -41,15 +58,24 @@ let
# entire unpacked contents after just a little twiddling.
preferLocalBuild = true;
nativeBuildInputs = [ gnutar ] ++
nativeBuildInputs = [
gnutar
]
++
# Darwin doesn't use ELF, and they usually just work due to relative RPATH.
optional (!dontFixup && !hostPlatform.isDarwin) autoPatchelfHook ++
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;
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
@@ -66,8 +92,7 @@ let
# 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;
depsHostHost = optional (!dontFixup && !hostPlatform.isDarwin) gccForLibs.lib;
dontConfigure = true;
dontBuild = true;
@@ -102,86 +127,117 @@ let
'';
# Only contain tons of html files. Don't waste time scanning files.
dontFixup = elem pname [ "rust-docs" "rustc-docs" ];
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
''
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"
}
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
'';
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
''
}
env = lib.optionalAttrs (pname == "rustc") ({
inherit (stdenv.cc.bintools) expandResponseParams shell suffixSalt wrapperName coreutils_bin;
hardening_unsupported_flags = "";
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
'';
# 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;
});
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;
});
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)
removeNulls (self // mapAttrs (alias: { to }: self.${to} or null) renames)

View File

@@ -7,20 +7,44 @@
nightly,
}:
let
inherit (builtins) compareVersions fromTOML match readFile tryEval;
inherit (builtins)
compareVersions
fromTOML
match
readFile
tryEval
;
inherit (lib)
any attrNames attrValues concatStringsSep elem elemAt filter flatten foldl'
hasPrefix head isString length listToAttrs makeOverridable mapAttrs
mapAttrsToList optional optionalAttrs replaceStrings substring trace unique;
any
attrNames
attrValues
concatStringsSep
elem
elemAt
filter
flatten
foldl'
hasPrefix
head
isString
length
listToAttrs
makeOverridable
mapAttrs
mapAttrsToList
optional
optionalAttrs
replaceStrings
substring
trace
unique
;
inherit (pkgs) stdenv callPackage fetchurl;
# Remove keys from attrsets whose value is null.
removeNulls = set:
removeAttrs set
(filter (name: set.${name} == null)
(attrNames set));
removeNulls = set: removeAttrs set (filter (name: set.${name} == null) (attrNames set));
toRustTarget = platform: platform.rust.rustcTarget;
@@ -33,36 +57,50 @@ let
inherit removeNulls toRustTarget;
};
mkAggregated = callPackage ./mk-aggregated.nix {};
mkAggregated = callPackage ./mk-aggregated.nix { };
# Manifest selector.
selectManifest = { channel, date ? null }: let
assertWith = cond: msg: body: if cond then body else throw msg;
selectManifest =
{
channel,
date ? null,
}:
let
assertWith =
cond: msg: body:
if cond then body else throw msg;
# https://rust-lang.github.io/rustup/concepts/toolchains.html#toolchain-specification
# <channel> = stable|beta|nightly|<major.minor>|<major.minor.patch>
# https://rust-lang.github.io/rustup/concepts/toolchains.html#toolchain-specification
# <channel> = stable|beta|nightly|<major.minor>|<major.minor.patch>
asVersion = match "[0-9]+\\.[0-9]+(\\.[0-9]+)?" channel;
asNightlyDate = let m = match "nightly-([0-9]+-[0-9]+-[0-9]+)" channel; in
if m == null then null else elemAt m 0;
asBetaDate = let m = match "beta-([0-9]+-[0-9]+-[0-9]+)" channel; in
if m == null then null else elemAt m 0;
asVersion = match "[0-9]+\\.[0-9]+(\\.[0-9]+)?" channel;
asNightlyDate =
let
m = match "nightly-([0-9]+-[0-9]+-[0-9]+)" channel;
in
if m == null then null else elemAt m 0;
asBetaDate =
let
m = match "beta-([0-9]+-[0-9]+-[0-9]+)" channel;
in
if m == null then null else elemAt m 0;
maxWith = zero: f: foldl' (lhs: rhs: if lhs == zero || f lhs rhs < 0 then rhs else lhs) zero;
maxWith = zero: f: foldl' (lhs: rhs: if lhs == zero || f lhs rhs < 0 then rhs else lhs) zero;
latestStableWithMajorMinor =
maxWith "" compareVersions
(filter (hasPrefix (channel + "."))
(attrNames manifests.stable));
latestStableWithMajorMinor = maxWith "" compareVersions (
filter (hasPrefix (channel + ".")) (attrNames manifests.stable)
);
in
in
# "stable"
if channel == "stable" then
assertWith (date == null) "Stable version with specific date is not supported"
manifests.stable.latest
assertWith (
date == null
) "Stable version with specific date is not supported" manifests.stable.latest
# "nightly"
else if channel == "nightly" then
manifests.nightly.${if date != null then date else "latest"} or (throw "Nightly ${date} is not available")
manifests.nightly.${if date != null then date else "latest"}
or (throw "Nightly ${date} is not available")
# "beta"
else if channel == "beta" then
manifests.beta.${if date != null then date else "latest"} or (throw "Beta ${date} is not available")
@@ -74,7 +112,8 @@ let
manifests.stable.${latestStableWithMajorMinor} or (throw "No stable ${channel}.* is available")
# "1.49.0"
else
manifests.stable.${channel} or (throw "Stable ${channel} is not available"))
manifests.stable.${channel} or (throw "Stable ${channel} is not available")
)
# "beta-2021-01-01"
else if asBetaDate != null then
assertWith (date == null) "Cannot specify date in both `channel` and `date`"
@@ -84,20 +123,32 @@ let
assertWith (date == null) "Cannot specify date in both `channel` and `date`"
manifests.nightly.${asNightlyDate} or (throw "Nightly ${asNightlyDate} is not available")
# Otherwise
else throw "Unknown channel: ${channel}";
else
throw "Unknown channel: ${channel}";
# Select a toolchain and aggregate components by rustup's `rust-toolchain` file format.
# See: https://rust-lang.github.io/rustup/concepts/profiles.html
# Or see source: https://github.com/rust-lang/rustup/blob/84974df1387812269c7b29fa5f3bb1c6480a6500/doc/src/overrides.md#the-toolchain-file
fromRustupToolchain = { path ? null, channel ? null, profile ? null, components ? [], targets ? [] }:
if path != null then throw "`path` is not supported, please directly add it to your PATH instead"
else if channel == null then throw "`channel` is required"
fromRustupToolchain =
{
path ? null,
channel ? null,
profile ? null,
components ? [ ],
targets ? [ ],
}:
if path != null then
throw "`path` is not supported, please directly add it to your PATH instead"
else if channel == null then
throw "`channel` is required"
else
let
toolchain = toolchainFromManifest (selectManifest { inherit channel; });
toolchain = toolchainFromManifest (selectManifest {
inherit channel;
});
profile' = if profile == null then "default" else profile;
pkg =
if toolchain._profiles != {} then
if toolchain._profiles != { } then
toolchain._profiles.${profile'} or (throw ''
Rust ${toolchain._version} doesn't have profile `${profile'}`.
Available profiles are: ${concatStringsSep ", " (attrNames toolchain._profiles)}
@@ -107,27 +158,36 @@ let
toolchain.rust
else
throw "Cannot select profile `${profile'}` since rust ${toolchain._version} is too early to support profiles";
in pkg.override {
in
pkg.override {
extensions = components;
inherit targets;
};
# Same as `fromRustupToolchain` but read from a `rust-toolchain` file (legacy one-line string or in TOML).
fromRustupToolchainFile = path: let
content = readFile path;
legacy = match "([^\r\n]+)\r?\n?" content;
in if legacy != null
then fromRustupToolchain { channel = head legacy; }
else fromRustupToolchain (fromTOML content).toolchain;
mkComponentSrc = { url, sha256 }:
fromRustupToolchainFile =
path:
let
url' = replaceStrings [" "] ["%20"] url; # This is required or download will fail.
content = readFile path;
legacy = match "([^\r\n]+)\r?\n?" content;
in
if legacy != null then
fromRustupToolchain { channel = head legacy; }
else
fromRustupToolchain (fromTOML content).toolchain;
mkComponentSrc =
{ url, sha256 }:
let
url' = replaceStrings [ " " ] [ "%20" ] url; # This is required or download will fail.
# Filter names like `llvm-tools-1.34.2 (6c2484dc3 2019-05-13)-aarch64-unknown-linux-gnu.tar.xz`
matchParenPart = match ".*/([^ /]*) [(][^)]*[)](.*)" url;
name = if matchParenPart == null then "" else (elemAt matchParenPart 0) + (elemAt matchParenPart 1);
in
fetchurl { inherit name sha256; url = url'; };
fetchurl {
inherit name sha256;
url = url';
};
# Resolve final components to install from mozilla-overlay style `extensions`, `targets` and `targetExtensions`.
#
@@ -137,76 +197,94 @@ let
#
# Returns a list of component derivations, or throw if failed.
resolveComponents =
{ name
, componentSet
, allComponentSet
, allPlatformSet
, targetComponentsList
, profileComponents
, extensions
, targets
, targetExtensions
{
name,
componentSet,
allComponentSet,
allPlatformSet,
targetComponentsList,
profileComponents,
extensions,
targets,
targetExtensions,
}:
let
# Components for target platform like `rust-std`.
collectTargetComponents = allowMissing: name:
collectTargetComponents =
allowMissing: name:
let
targetSelected = flatten (map (tgt: componentSet.${tgt}.${name} or []) targets);
in if !allowMissing -> targetSelected != [] then
targetSelected = flatten (map (tgt: componentSet.${tgt}.${name} or [ ]) targets);
in
if !allowMissing -> targetSelected != [ ] then
targetSelected
else
"Component `${name}` doesn't support any of targets: ${concatStringsSep ", " targets}";
collectComponents = allowMissing: name:
collectComponents =
allowMissing: name:
if elem name targetComponentsList then
collectTargetComponents allowMissing name
else
# Components for host platform like `rustc`.
componentSet.${rustHostPlatform}.${name} or (
if allowMissing then []
else "Host component `${name}` doesn't support `${rustHostPlatform}`");
componentSet.${rustHostPlatform}.${name}
or (if allowMissing then [ ] else "Host component `${name}` doesn't support `${rustHostPlatform}`");
# Profile components can be skipped silently when missing.
# Eg. `rust-mingw` on non-Windows platforms, or `rust-docs` on non-tier1 platforms.
result =
flatten (map (collectComponents true) profileComponents) ++
flatten (map (collectComponents false) extensions) ++
flatten (map (collectTargetComponents false) targetExtensions);
flatten (map (collectComponents true) profileComponents)
++ flatten (map (collectComponents false) extensions)
++ flatten (map (collectTargetComponents false) targetExtensions);
isTargetUnused = target:
isTargetUnused =
target:
!any (name: componentSet ? ${target}.${name})
# FIXME: Get rid of the legacy component `rust`.
(filter (name: name == "rust" || elem name targetComponentsList)
(profileComponents ++ extensions)
++ targetExtensions);
(
filter (name: name == "rust" || elem name targetComponentsList) (profileComponents ++ extensions)
++ targetExtensions
);
# Fail-fast for typo in `targets`, `extensions`, `targetExtensions`.
fastErrors =
flatten (
map (tgt: optional (!(allPlatformSet ? ${tgt}))
"Unknown target `${tgt}`, typo or not supported by this version?")
targets ++
map (name: optional (!(allComponentSet ? ${name}))
"Unknown component `${name}`, typo or not support by this version?")
(profileComponents ++ extensions ++ targetExtensions));
fastErrors = flatten (
map (
tgt:
optional (
!(allPlatformSet ? ${tgt})
) "Unknown target `${tgt}`, typo or not supported by this version?"
) targets
++ map (
name:
optional (
!(allComponentSet ? ${name})
) "Unknown component `${name}`, typo or not support by this version?"
) (profileComponents ++ extensions ++ targetExtensions)
);
errors =
if fastErrors != [] then
if fastErrors != [ ] then
fastErrors
else
filter isString result ++
map (tgt: "Target `${tgt}` is not supported by any components or extensions")
(filter isTargetUnused targets);
filter isString result
++ map (tgt: "Target `${tgt}` is not supported by any components or extensions") (
filter isTargetUnused targets
);
notes = [
"note: profile components: ${toString profileComponents}"
] ++ optional (targets != []) "note: selected targets: ${toString targets}"
++ optional (extensions != []) "note: selected extensions: ${toString extensions}"
++ optional (targetExtensions != []) "note: selected targetExtensions: ${toString targetExtensions}"
++ flatten (map (platform:
optional (componentSet ? ${platform})
"note: components available for ${platform}: ${toString (attrNames componentSet.${platform})}"
) (unique ([ rustHostPlatform ] ++ targets)))
]
++ optional (targets != [ ]) "note: selected targets: ${toString targets}"
++ optional (extensions != [ ]) "note: selected extensions: ${toString extensions}"
++ optional (
targetExtensions != [ ]
) "note: selected targetExtensions: ${toString targetExtensions}"
++ flatten (
map (
platform:
optional (componentSet ? ${platform})
"note: components available for ${platform}: ${toString (attrNames componentSet.${platform})}"
) (unique ([ rustHostPlatform ] ++ targets))
)
++ [
''
note: check here to see all targets and which components are available on each targets:
@@ -215,8 +293,10 @@ let
];
in
if errors == [] then result
else throw ''
if errors == [ ] then
result
else
throw ''
Component resolution failed for ${name}
${concatStringsSep "\n" (errors ++ notes)}
'';
@@ -251,32 +331,41 @@ let
# All extensions in this list will be installed for the target architectures.
# *Attention* If you want to install an extension like rust-src, that has no fixed architecture (arch *),
# you will need to specify this extension in the extensions options or it will not be installed!
toolchainFromManifest = manifest: let
# platform -> true
# For fail-fast test.
allPlatformSet =
listToAttrs (
toolchainFromManifest =
manifest:
let
# platform -> true
# For fail-fast test.
allPlatformSet = listToAttrs (
flatten (
mapAttrsToList (compName: { target, ... }:
map (platform: { name = platform; value = true; })
(attrNames target)
) manifest.pkg));
mapAttrsToList (
compName:
{ target, ... }:
map (platform: {
name = platform;
value = true;
}) (attrNames target)
) manifest.pkg
)
);
# componentName -> true
# May also contains unavailable components. Just for fail-fast test.
allComponentSet =
mapAttrs (compName: _: true)
(manifest.pkg // manifest.renames);
# componentName -> true
# May also contains unavailable components. Just for fail-fast test.
allComponentSet = mapAttrs (compName: _: true) (manifest.pkg // manifest.renames);
# componentSet.x86_64-unknown-linux-gnu.cargo = <derivation>;
componentSet =
mapAttrs (platform: _:
# componentSet.x86_64-unknown-linux-gnu.cargo = <derivation>;
componentSet = mapAttrs (
platform: _:
mkComponentSet {
inherit (manifest) version renames;
inherit platform;
srcs = removeNulls
(mapAttrs (compName: { target, ... }:
let content = target.${platform} or target."*" or null; in
srcs = removeNulls (
mapAttrs (
compName:
{ target, ... }:
let
content = target.${platform} or target."*" or null;
in
if content == null then
null
else
@@ -284,61 +373,82 @@ let
url = content.xz_url;
sha256 = content.xz_hash;
}
) manifest.pkg);
) manifest.pkg
);
}
) allPlatformSet;
mkProfile = name: profileComponents:
makeOverridable ({ extensions, targets, targetExtensions }:
mkAggregated {
pname = "rust-${name}";
inherit (manifest) version date;
availableComponents = componentSet.${rustHostPlatform};
selectedComponents = resolveComponents {
name = "rust-${name}-${manifest.version}";
inherit allPlatformSet allComponentSet componentSet profileComponents targetExtensions;
inherit (manifest) targetComponentsList;
extensions = extensions;
targets = unique ([
rustHostPlatform # Build script requires host std.
rustTargetPlatform
] ++ targets);
mkProfile =
name: profileComponents:
makeOverridable
(
{
extensions,
targets,
targetExtensions,
}:
mkAggregated {
pname = "rust-${name}";
inherit (manifest) version date;
availableComponents = componentSet.${rustHostPlatform};
selectedComponents = resolveComponents {
name = "rust-${name}-${manifest.version}";
inherit
allPlatformSet
allComponentSet
componentSet
profileComponents
targetExtensions
;
inherit (manifest) targetComponentsList;
extensions = extensions;
targets = unique (
[
rustHostPlatform # Build script requires host std.
rustTargetPlatform
]
++ targets
);
};
}
)
{
extensions = [ ];
targets = [ ];
targetExtensions = [ ];
};
}
) {
extensions = [];
targets = [];
targetExtensions = [];
};
profiles = mapAttrs mkProfile manifest.profiles;
profiles = mapAttrs mkProfile manifest.profiles;
result =
# Individual components.
componentSet.${rustHostPlatform} //
# Profiles.
profiles // {
# Legacy support for special pre-aggregated package.
# It has more components than `default` profile but less than `complete` profile.
rust =
let
pkg = mkProfile "legacy" [ "rust" ];
in if profiles != {} then
trace ''
Rust ${manifest.version}:
Pre-aggregated package `rust` is not encouraged for stable channel since it contains almost all and uncertain components.
Consider use `default` profile like `rust-bin.stable.latest.default` and override it with extensions you need.
See README for more information.
'' pkg
else
pkg;
};
result =
# Individual components.
componentSet.${rustHostPlatform}
//
# Profiles.
profiles
// {
# Legacy support for special pre-aggregated package.
# It has more components than `default` profile but less than `complete` profile.
rust =
let
pkg = mkProfile "legacy" [ "rust" ];
in
if profiles != { } then
trace ''
Rust ${manifest.version}:
Pre-aggregated package `rust` is not encouraged for stable channel since it contains almost all and uncertain components.
Consider use `default` profile like `rust-bin.stable.latest.default` and override it with extensions you need.
See README for more information.
'' pkg
else
pkg;
};
in
in
# If the platform is not supported for the current version, return nothing here,
# so others can easily check it by `toolchain ? default`.
optionalAttrs (componentSet ? ${rustHostPlatform}) result //
{
optionalAttrs (componentSet ? ${rustHostPlatform}) result
// {
# Internal use.
_components = componentSet;
_profiles = profiles;
@@ -349,33 +459,38 @@ let
# From a git revision of rustc.
# This does the same thing as crate `rustup-toolchain-install-master`.
# But you need to manually provide component hashes.
fromRustcRev = {
# Package name of the derivation.
pname ? "rust-custom",
# Git revision of rustc.
rev,
# Version of the built package.
version ? substring 0 7 rev,
# Attrset with component name as key and its SRI hash as value.
components,
# Rust target to download.
target ? rustTargetPlatform
}: let
hashToSrc = compName: hash:
fetchurl {
url = if compName == "rust-src"
then "https://ci-artifacts.rust-lang.org/rustc-builds/${rev}/${compName}-nightly.tar.xz"
else "https://ci-artifacts.rust-lang.org/rustc-builds/${rev}/${compName}-nightly-${target}.tar.xz";
inherit hash;
fromRustcRev =
{
# Package name of the derivation.
pname ? "rust-custom",
# Git revision of rustc.
rev,
# Version of the built package.
version ? substring 0 7 rev,
# Attrset with component name as key and its SRI hash as value.
components,
# Rust target to download.
target ? rustTargetPlatform,
}:
let
hashToSrc =
compName: hash:
fetchurl {
url =
if compName == "rust-src" then
"https://ci-artifacts.rust-lang.org/rustc-builds/${rev}/${compName}-nightly.tar.xz"
else
"https://ci-artifacts.rust-lang.org/rustc-builds/${rev}/${compName}-nightly-${target}.tar.xz";
inherit hash;
};
components' = mkComponentSet {
inherit version;
platform = target;
srcs = mapAttrs hashToSrc components;
# We cannot know aliases in this case.
renames = { };
};
components' = mkComponentSet {
inherit version;
platform = target;
srcs = mapAttrs hashToSrc components;
# We cannot know aliases in this case.
renames = { };
};
in
in
mkAggregated {
inherit pname version;
date = null;
@@ -386,12 +501,16 @@ let
# Some components are missing in some nightly releases.
# Usage:
# `selectLatestNightlyWith (toolchain: toolchain.default.override { extensions = ["llvm-tools-preview"]; })`
selectLatestNightlyWith = selector:
selectLatestNightlyWith =
selector:
let
nightlyDates = attrNames (removeAttrs nightly [ "latest" ]);
dateLength = length nightlyDates;
go = idx:
let ret = selector (nightly.${elemAt nightlyDates idx}); in
go =
idx:
let
ret = selector (nightly.${elemAt nightlyDates idx});
in
if idx == 0 then
ret
else if dateLength - idx >= 256 then
@@ -401,7 +520,7 @@ let
else
go (idx - 1);
in
go (length nightlyDates - 1);
go (length nightlyDates - 1);
in
# For each channel:
@@ -420,8 +539,8 @@ in
#
# For a specific date of nightly:
# rust-bin.nightly."2020-01-01".default
mapAttrs (channel: mapAttrs (version: toolchainFromManifest)) manifests //
{
mapAttrs (channel: mapAttrs (version: toolchainFromManifest)) manifests
// {
inherit fromRustupToolchain fromRustupToolchainFile;
inherit selectLatestNightlyWith;
inherit fromRustcRev;

View File

@@ -13,20 +13,31 @@ let
pkgs = inputs.nixpkgs.legacyPackages.${system};
rustHostPlatform = pkgs.hostPlatform.rust.rustcTarget;
rust-bin = inputs.self.lib.mkRustBin {} pkgs;
inherit (rust-bin) fromRustupToolchain fromRustupToolchainFile stable beta nightly;
rust-bin = inputs.self.lib.mkRustBin { } pkgs;
inherit (rust-bin)
fromRustupToolchain
fromRustupToolchainFile
stable
beta
nightly
;
assertEq = lhs: rhs:
if lhs == rhs
then pkgs.emptyFile
else derivation {
inherit system;
name = "assert-failure";
builder = "/bin/sh";
args = [ "-c" ''echo "LHS: $lhs"; echo "RHS: $rhs"; exit 1'' ];
lhs = toJSON lhs;
rhs = toJSON rhs;
};
assertEq =
lhs: rhs:
if lhs == rhs then
pkgs.emptyFile
else
derivation {
inherit system;
name = "assert-failure";
builder = "/bin/sh";
args = [
"-c"
''echo "LHS: $lhs"; echo "RHS: $rhs"; exit 1''
];
lhs = toJSON lhs;
rhs = toJSON rhs;
};
assertUrl = drv: url: assertEq (head drv.src.urls) url;
testNightly = {
@@ -40,93 +51,187 @@ let
in
# Check only tier 1 targets.
optionalAttrs (elem system [ "aarch64-linux" "x86_64-linux" ]) {
url-no-arch = assertUrl stable."1.48.0".rust-src "https://static.rust-lang.org/dist/2020-11-19/rust-src-1.48.0.tar.xz";
url-kind-nightly = assertUrl nightly.${testNightly.date}.rustc "https://static.rust-lang.org/dist/${testNightly.date}/rustc-nightly-${rustHostPlatform}.tar.xz";
url-kind-beta = assertUrl beta.${testBeta.date}.rustc "https://static.rust-lang.org/dist/${testBeta.date}/rustc-beta-${rustHostPlatform}.tar.xz";
optionalAttrs
(elem system [
"aarch64-linux"
"x86_64-linux"
])
{
url-no-arch =
assertUrl stable."1.48.0".rust-src
"https://static.rust-lang.org/dist/2020-11-19/rust-src-1.48.0.tar.xz";
url-kind-nightly =
assertUrl nightly.${testNightly.date}.rustc
"https://static.rust-lang.org/dist/${testNightly.date}/rustc-nightly-${rustHostPlatform}.tar.xz";
url-kind-beta =
assertUrl beta.${testBeta.date}.rustc
"https://static.rust-lang.org/dist/${testBeta.date}/rustc-beta-${rustHostPlatform}.tar.xz";
name-stable = assertEq stable."1.48.0".rustc.name "rustc-1.48.0-${rustHostPlatform}";
name-beta = assertEq beta.${testBeta.date}.rustc.name "rustc-${testBeta.version}-${rustHostPlatform}";
name-nightly = assertEq nightly.${testNightly.date}.rustc.name "rustc-${testNightly.version}-${rustHostPlatform}";
name-stable-profile-default = assertEq stable."1.51.0".default.name "rust-default-1.51.0";
name-stable-profile-minimal = assertEq stable."1.51.0".minimal.name "rust-minimal-1.51.0";
name-stable = assertEq stable."1.48.0".rustc.name "rustc-1.48.0-${rustHostPlatform}";
name-beta =
assertEq beta.${testBeta.date}.rustc.name
"rustc-${testBeta.version}-${rustHostPlatform}";
name-nightly =
assertEq nightly.${testNightly.date}.rustc.name
"rustc-${testNightly.version}-${rustHostPlatform}";
name-stable-profile-default = assertEq stable."1.51.0".default.name "rust-default-1.51.0";
name-stable-profile-minimal = assertEq stable."1.51.0".minimal.name "rust-minimal-1.51.0";
url-kind-2 = assertUrl stable."1.48.0".cargo "https://static.rust-lang.org/dist/2020-11-19/cargo-1.48.0-${rustHostPlatform}.tar.xz";
url-kind-0 = assertUrl stable."1.47.0".cargo "https://static.rust-lang.org/dist/2020-10-08/cargo-0.48.0-${rustHostPlatform}.tar.xz";
url-kind-1 = assertUrl stable."1.34.2".llvm-tools-preview "https://static.rust-lang.org/dist/2019-05-14/llvm-tools-1.34.2%20(6c2484dc3%202019-05-13)-${rustHostPlatform}.tar.xz";
url-kind-2 =
assertUrl stable."1.48.0".cargo
"https://static.rust-lang.org/dist/2020-11-19/cargo-1.48.0-${rustHostPlatform}.tar.xz";
url-kind-0 =
assertUrl stable."1.47.0".cargo
"https://static.rust-lang.org/dist/2020-10-08/cargo-0.48.0-${rustHostPlatform}.tar.xz";
url-kind-1 =
assertUrl stable."1.34.2".llvm-tools-preview
"https://static.rust-lang.org/dist/2019-05-14/llvm-tools-1.34.2%20(6c2484dc3%202019-05-13)-${rustHostPlatform}.tar.xz";
# 1.30.0 has `rustfmt` still in preview state.
rename-unavailable = assertEq (stable."1.30.0" ? rustfmt) false;
rename-available = assertEq stable."1.48.0".rustfmt stable."1.48.0".rustfmt-preview;
# 1.30.0 has `rustfmt` still in preview state.
rename-unavailable = assertEq (stable."1.30.0" ? rustfmt) false;
rename-available = assertEq stable."1.48.0".rustfmt stable."1.48.0".rustfmt-preview;
latest-stable-legacy = assertEq latest.rustChannels.stable.rustc stable.latest.rustc;
latest-beta-legacy = assertEq latest.rustChannels.beta.rustc beta.latest.rustc;
latest-nightly-legacy = assertEq latest.rustChannels.nightly.rustc nightly.latest.rustc;
latest-stable-legacy = assertEq latest.rustChannels.stable.rustc stable.latest.rustc;
latest-beta-legacy = assertEq latest.rustChannels.beta.rustc beta.latest.rustc;
latest-nightly-legacy = assertEq latest.rustChannels.nightly.rustc nightly.latest.rustc;
rust-channel-of-stable = assertEq (rustChannelOf { channel = "stable"; }).rustc stable.latest.rustc;
rust-channel-of-beta = assertEq (rustChannelOf { channel = "beta"; }).rustc beta.latest.rustc;
rust-channel-of-nightly = assertEq (rustChannelOf { channel = "nightly"; }).rustc nightly.latest.rustc;
rust-channel-of-version = assertEq (rustChannelOf { channel = "1.48.0"; }).rustc stable."1.48.0".rustc;
rust-channel-of-nightly-date = assertEq (rustChannelOf { channel = "nightly"; date = testNightly.date; }).rustc nightly.${testNightly.date}.rustc;
rust-channel-of-beta-date = assertEq (rustChannelOf { channel = "beta"; date = testBeta.date; }).rustc beta.${testBeta.date}.rustc;
rust-channel-of-stable = assertEq (rustChannelOf { channel = "stable"; }).rustc stable.latest.rustc;
rust-channel-of-beta = assertEq (rustChannelOf { channel = "beta"; }).rustc beta.latest.rustc;
rust-channel-of-nightly =
assertEq (rustChannelOf { channel = "nightly"; }).rustc
nightly.latest.rustc;
rust-channel-of-version =
assertEq (rustChannelOf { channel = "1.48.0"; }).rustc
stable."1.48.0".rustc;
rust-channel-of-nightly-date =
assertEq
(rustChannelOf {
channel = "nightly";
date = testNightly.date;
}).rustc
nightly.${testNightly.date}.rustc;
rust-channel-of-beta-date =
assertEq
(rustChannelOf {
channel = "beta";
date = testBeta.date;
}).rustc
beta.${testBeta.date}.rustc;
rustup-toolchain-stable = assertEq (fromRustupToolchain { channel = "stable"; }) stable.latest.default;
rustup-toolchain-beta = assertEq (fromRustupToolchain { channel = "beta"; }) beta.latest.default;
# rustup-toolchain-nightly = assertEq (fromRustupToolchain { channel = "nightly"; }) nightly.latest.default; # Not always available
rustup-toolchain-version = assertEq (fromRustupToolchain { channel = "1.51.0"; }) stable."1.51.0".default;
rustup-toolchain-nightly-date = assertEq (fromRustupToolchain { channel = "nightly-${testNightly.date}"; }) nightly.${testNightly.date}.default;
rustup-toolchain-beta-date = assertEq (fromRustupToolchain { channel = "beta-${testBeta.date}"; }) beta.${testBeta.date}.default;
rustup-toolchain-customization = assertEq
(fromRustupToolchain {
rustup-toolchain-stable = assertEq (fromRustupToolchain {
channel = "stable";
}) stable.latest.default;
rustup-toolchain-beta = assertEq (fromRustupToolchain { channel = "beta"; }) beta.latest.default;
# rustup-toolchain-nightly = assertEq (fromRustupToolchain { channel = "nightly"; }) nightly.latest.default; # Not always available
rustup-toolchain-version = assertEq (fromRustupToolchain {
channel = "1.51.0";
components = [ "rustfmt" "rustc-dev" ];
targets = [ "wasm32-unknown-unknown" "aarch64-unknown-linux-gnu" ];
})
(stable."1.51.0".default.override {
extensions = [ "rustfmt" "rustc-dev" ];
targets = [ "wasm32-unknown-unknown" "aarch64-unknown-linux-gnu" ];
});
}) stable."1.51.0".default;
rustup-toolchain-nightly-date = assertEq (fromRustupToolchain {
channel = "nightly-${testNightly.date}";
}) nightly.${testNightly.date}.default;
rustup-toolchain-beta-date = assertEq (fromRustupToolchain {
channel = "beta-${testBeta.date}";
}) beta.${testBeta.date}.default;
rustup-toolchain-customization =
assertEq
(fromRustupToolchain {
channel = "1.51.0";
components = [
"rustfmt"
"rustc-dev"
];
targets = [
"wasm32-unknown-unknown"
"aarch64-unknown-linux-gnu"
];
})
(
stable."1.51.0".default.override {
extensions = [
"rustfmt"
"rustc-dev"
];
targets = [
"wasm32-unknown-unknown"
"aarch64-unknown-linux-gnu"
];
}
);
rustup-toolchain-profile-missing = assertEq (tryEval (fromRustupToolchain { channel = "1.51.0"; profile = "non_existent"; })).success false;
rustup-toolchain-profile-too-early = assertEq (tryEval (fromRustupToolchain { channel = "1.29.0"; profile = "minimal"; })).success false;
rustup-toolchain-profile-fallback = assertEq (fromRustupToolchain { channel = "1.29.0"; }) stable."1.29.0".rust;
rustup-toolchain-profile-missing =
assertEq
(tryEval (fromRustupToolchain {
channel = "1.51.0";
profile = "non_existent";
})).success
false;
rustup-toolchain-profile-too-early =
assertEq
(tryEval (fromRustupToolchain {
channel = "1.29.0";
profile = "minimal";
})).success
false;
rustup-toolchain-profile-fallback = assertEq (fromRustupToolchain {
channel = "1.29.0";
}) stable."1.29.0".rust;
rustup-toolchain-file-toml = assertEq
(fromRustupToolchainFile (toFile "rust-toolchain-toml" ''
[toolchain]
channel = "nightly-${testNightly.date}"
components = [ "rustfmt", "rustc-dev" ]
targets = [ "wasm32-unknown-unknown", "aarch64-unknown-linux-gnu" ]
''))
(nightly.${testNightly.date}.default.override {
extensions = [ "rustfmt" "rustc-dev" ];
targets = [ "wasm32-unknown-unknown" "aarch64-unknown-linux-gnu" ];
});
rustup-toolchain-file-legacy = assertEq
(fromRustupToolchainFile (toFile "rust-toolchain-legacy" ''
nightly-${testNightly.date}
''))
nightly.${testNightly.date}.default;
rustup-toolchain-file-minimal = assertEq
(fromRustupToolchainFile (toFile "rust-toolchain-minimal" ''
[toolchain]
channel = "nightly-${testNightly.date}"
profile = "minimal"
components = [ "rustfmt", "rustc-dev" ]
targets = [ "aarch64-unknown-linux-gnu" ]
''))
(nightly.${testNightly.date}.minimal.override {
extensions = [ "rustfmt" "rustc-dev" ];
targets = [ "aarch64-unknown-linux-gnu" ];
});
rustup-toolchain-file-toml =
assertEq
(fromRustupToolchainFile (
toFile "rust-toolchain-toml" ''
[toolchain]
channel = "nightly-${testNightly.date}"
components = [ "rustfmt", "rustc-dev" ]
targets = [ "wasm32-unknown-unknown", "aarch64-unknown-linux-gnu" ]
''
))
(
nightly.${testNightly.date}.default.override {
extensions = [
"rustfmt"
"rustc-dev"
];
targets = [
"wasm32-unknown-unknown"
"aarch64-unknown-linux-gnu"
];
}
);
rustup-toolchain-file-legacy = assertEq (fromRustupToolchainFile (
toFile "rust-toolchain-legacy" ''
nightly-${testNightly.date}
''
)) nightly.${testNightly.date}.default;
rustup-toolchain-file-minimal =
assertEq
(fromRustupToolchainFile (
toFile "rust-toolchain-minimal" ''
[toolchain]
channel = "nightly-${testNightly.date}"
profile = "minimal"
components = [ "rustfmt", "rustc-dev" ]
targets = [ "aarch64-unknown-linux-gnu" ]
''
))
(
nightly.${testNightly.date}.minimal.override {
extensions = [
"rustfmt"
"rustc-dev"
];
targets = [ "aarch64-unknown-linux-gnu" ];
}
);
latest-nightly-default = rust-bin.selectLatestNightlyWith (toolchain: toolchain.default);
latest-nightly-default = rust-bin.selectLatestNightlyWith (toolchain: toolchain.default);
# Darwin specific tests.
} // optionalAttrs (system == "aarch64-darwin") {
url-forward = assertUrl
nightly.${testNightly.date}.rust-docs
"https://static.rust-lang.org/dist/${testNightly.date}/rust-docs-nightly-x86_64-apple-darwin.tar.xz";
# Darwin specific tests.
}
// optionalAttrs (system == "aarch64-darwin") {
url-forward =
assertUrl nightly.${testNightly.date}.rust-docs
"https://static.rust-lang.org/dist/${testNightly.date}/rust-docs-nightly-x86_64-apple-darwin.tar.xz";
aarch64-darwin-use-x86-docs = rust-bin.stable."1.51.0".default.override {
targets = [ "x86_64-apple-darwin" ];
targetExtensions = [ "rust-docs" ];