wip/nixpkgs-raku
oxalica 3 years ago
commit 815fa068bc
No known key found for this signature in database
GPG Key ID: CED392DE0C483D00
  1. 3
      .gitignore
  2. 8
      .vscode/settings.json
  3. 72
      default.nix
  4. 197
      fetch.py
  5. 40
      flake.lock
  6. 40
      flake.nix
  7. 1
      manifests/stable/1.48.0.nix
  8. 1
      manifests/stable/1.49.0.nix
  9. 5
      manifests/stable/default.nix
  10. 93
      manifests/targets.nix
  11. 301
      rust-overlay.nix

3
.gitignore vendored

@ -0,0 +1,3 @@
result
result-*
*.tmp

@ -0,0 +1,8 @@
{
"[nix]": {
"editor.tabSize": 2,
"files.trimFinalNewlines": true,
"files.insertFinalNewline": true,
"files.trimTrailingWhitespace": true
}
}

@ -0,0 +1,72 @@
final: prev:
let
inherit (prev.lib) filter hasAttr attrNames mapAttrs concatMap mapAttrs' replaceStrings;
targets = import ./manifests/targets.nix // { _ = "*"; };
distServer = "https://static.rust-lang.org";
# Extensions for mixed `rust` pkg.
components = [
"rustc"
"rust-std"
"cargo"
];
singleTargetExtensions = [
"clippy-preview"
"miri-preview"
"rls-preview"
"rust-analyzer-preview"
"rustfmt-preview"
"llvm-tools-preview"
"rust-analysis"
];
multiTargetExtensions = [
"rust-std"
"rustc-dev"
"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;
};
# version -> { pkgName = { _1 = "..."; } } -> { pkgName = { x86_64-unknown-linux-gnu = fetchurl { .. }; } }
uncompressManifest = version: { date, ... }@manifest: rec {
inherit date;
pkg =
mapAttrs (pkgName: { v, ... }@hashes: {
version = v;
target =
mapAttrs' (targetIdx: hash: let
target = targets.${targetIdx};
pkgNameStripped = replaceStrings ["-preview"] [""] pkgName;
targetTail = if targetIdx == "_" then "" else "-" + target;
in {
name = target;
value = {
xz_url = "${distServer}/dist/${date}/${pkgNameStripped}-${version}${targetTail}.tar.xz";
xz_hash = hash;
} // (if pkgName == "rust" then rustPkgExtra pkg target else {});
}) (removeAttrs hashes ["v"]);
}) (removeAttrs manifest ["date"]);
};
uncompressManifestSet = set: let
ret = mapAttrs uncompressManifest (removeAttrs set ["latest"]);
in ret // { latest = ret.${set.latest}; };
manifests = {
stable = uncompressManifestSet (import ./manifests/stable);
};
# in { inherit manifests; }
in import ./rust-overlay.nix final prev manifests

@ -0,0 +1,197 @@
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages (ps: with ps; [ toml requests ])"
import base64
import json
import re
import string
import sys
import time
from pathlib import Path
import toml
import requests
MAX_TRIES = 3
RETRY_DELAY = 3.0
SYNC_MAX_FETCH = 5
STABLE_VERSION_FILTER = lambda v: parse_version(v) >= (1, 29, 0)
DIST_SERVER = 'https://static.rust-lang.org'
NIX_KEYWORDS = {'', 'if', 'then', 'else', 'assert', 'with', 'let', 'in', 'rec', 'inherit', 'or'}
MANIFEST_TMP_PATH = Path('manifest.tmp')
TARGETS_PATH = Path('manifests/targets.nix')
RE_STABLE_VERSION = re.compile(r'^\d+\.\d+\.\d+$')
def to_base64(hash: str) -> str:
assert len(hash) == 64
return base64.b64encode(bytes.fromhex(hash)).decode()
def is_valid_nix_ident(name: str) -> bool:
return name not in NIX_KEYWORDS and \
(name[0] == '_' or name[0].isalpha()) and \
all(c in "_-'" or c.isalnum() for c in name)
def escape_nix_string(s: str) -> str:
return '"' + s.replace('\\', '\\\\').replace('"', '\\"') + '"'
def escape_nix_key(name: str) -> str:
if is_valid_nix_ident(name):
return name
return escape_nix_string(name)
def parse_version(ver: str) -> tuple:
return tuple(map(int, ver.split('.')))
def version_less(a: str, b: str):
return parse_version(a) < parse_version(b)
target_map = dict((line.split('"')[1], i) for i, line in enumerate(TARGETS_PATH.read_text().strip().split('\n')[1:-1]))
def compress_target(target: str) -> str:
assert '"' not in target
if target == '*':
return '_'
if target in target_map:
return f'_{target_map[target]}'
idx = len(target_map)
target_map[target] = idx
with open(str(TARGETS_PATH), 'w') as f:
f.write('{\n')
for i, target in sorted((v, k) for k, v in target_map.items()):
f.write(f' _{i} = "{target}";\n')
f.write('}\n')
return f'_{idx}'
def retry_with(f):
i = 0
while True:
try:
return f()
except requests.exceptions.RequestException as e:
i += 1
if i >= MAX_TRIES:
raise
print(e)
time.sleep(RETRY_DELAY)
def translate_dump_manifest(manifest: str, f):
manifest = toml.loads(manifest)
date = manifest['date']
version = manifest['pkg']['rustc']['version'].split()[0]
strip_tail = '-preview'
f.write('{')
f.write(f'date={escape_nix_string(date)};')
for pkg_name in sorted(manifest['pkg'].keys()):
pkg = manifest['pkg'][pkg_name]
pkg_name_stripped = pkg_name[:-len(strip_tail)] if pkg_name.endswith(strip_tail) else pkg_name
pkg_targets = sorted(pkg['target'].keys())
pkg_version = version
for target_name in pkg_targets:
target = pkg['target'][target_name]
if not target['available']:
continue
url = target['xz_url']
target_tail = '' if target_name == '*' else '-' + target_name
start = f'https://static.rust-lang.org/dist/{date}/{pkg_name_stripped}-'
end = f'{target_tail}.tar.xz'
assert url.startswith(start) and url.endswith(end), f'Unexpected url: {url}'
pkg_version = url[len(start):-len(end)]
f.write(f'{pkg_name}={{')
f.write(f'v={escape_nix_string(pkg["version"])};')
for target_name in pkg_targets:
target = pkg['target'][target_name]
if not target['available']:
continue
url = target['xz_url']
hash = to_base64(target['xz_hash']) # Hash must not contains quotes.
target_tail = '' if target_name == '*' else '-' + target_name
expect_url = f'https://static.rust-lang.org/dist/{date}/{pkg_name_stripped}-{pkg_version}{target_tail}.tar.xz'
assert url == expect_url, f'Unexpected url: {url}, expecting: {expect_url}'
f.write(f'{compress_target(target_name)}="{hash}";')
f.write('};')
f.write('}\n')
def fetch_stable_manifest(version: str, out_path: Path):
tmp_path = out_path.with_suffix('.tmp')
print(f'Fetching {version}')
manifest = retry_with(lambda: requests.get(f'{DIST_SERVER}/dist/channel-rust-{version}.toml'))
manifest.raise_for_status()
manifest = manifest.text
MANIFEST_TMP_PATH.write_text(manifest)
with open(tmp_path, 'w') as fout:
translate_dump_manifest(manifest, fout)
tmp_path.rename(out_path)
def update_stable_index():
dir = Path('manifests/stable')
versions = sorted(
(file.stem for file in dir.iterdir() if file.stem != 'default' and file.suffix == '.nix'),
key=parse_version,
)
with open(str(dir / 'default.nix'), 'w') as f:
f.write('{\n')
for v in versions:
f.write(f' {escape_nix_key(v)} = import ./{v}.nix;\n')
f.write(f' latest = {escape_nix_string(versions[-1])};\n')
f.write('}\n')
def sync_stable_channel(*, stop_if_exists, max_fetch=None):
GITHUB_RELEASES_URL = 'https://api.github.com/repos/rust-lang/rust/releases'
page = 0
count = 0
try:
while True:
page += 1
print(f'Fetching release page {page}')
release_page = retry_with(lambda: requests.get(GITHUB_RELEASES_URL, params={'page': page}))
release_page.raise_for_status()
release_page = release_page.json()
if not release_page:
return
for release in release_page:
version = release['tag_name']
if not RE_STABLE_VERSION.match(version) or not STABLE_VERSION_FILTER(version):
continue
out_path = Path(f'manifests/stable/{version}.nix')
if out_path.exists():
if stop_if_exists:
print('Stopped on existing version')
return
continue
fetch_stable_manifest(version, out_path)
count += 1
if max_fetch is not None and count >= max_fetch:
print('Reached max fetch count')
exit(1)
finally:
update_stable_index()
def init_sync_all():
sync_stable_channel(stop_if_exists=False)
def main():
args = sys.argv[1:]
if len(args) == 0:
print('Synchronizing channels')
sync_stable_channel(stop_if_exists=True, max_fetch=SYNC_MAX_FETCH)
elif len(args) == 1:
version = args[0]
assert RE_STABLE_VERSION.match(version), 'Invalid version'
fetch_stable_manifest(version, Path(f'manifests/stable/{version}.nix'))
update_stable_index()
else:
print(f'''
Usage: {sys.argv[0]} [version]
Run without arguments to auto-sync new versions from channels.
Run with version to fetch a specific version.
''')
exit(1)
if __name__ == '__main__':
main()

@ -0,0 +1,40 @@
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1609246779,
"narHash": "sha256-eq6ZXE/VWo3EMC65jmIT6H/rrUc9UWOWVujkzav025k=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "08c7ad4a0844adc4a7f9f5bb3beae482e789afa4",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1609079092,
"narHash": "sha256-KhyKfxBHtZlAgudpZ0EJVzeuqROjKfVOwj8j0cuhU50=",
"path": "/nix/store/5pmay8rdvgw5ml1xi6189xhdbygc850k-source",
"rev": "2f47650c2f28d87f86ab807b8a339c684d91ec56",
"type": "path"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

@ -0,0 +1,40 @@
{
description = ''
Pure and reproducible overlay for binary distributed rust toolchains.
A better replacement for github:mozilla/nixpkgs-mozilla
'';
inputs = {
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils, ... }@inputs: let
inherit (nixpkgs) lib;
overlay = import ./default.nix;
allSystems = [
"aarch64-linux"
"armv6l-linux"
"armv7a-linux"
"armv7l-linux"
"x86_64-linux"
"x86_64-darwin"
# "aarch64-darwin"
];
in {
overlay = final: prev: overlay final prev;
} // flake-utils.lib.eachSystem allSystems (system: let
pkgs = import nixpkgs { inherit system; overlays = [ overlay ]; };
in rec {
defaultApp = {
type = "app";
program = "${defaultPackage}/bin/rustc";
};
defaultPackage = packages.rust-stable;
packages = {
rust-stable = pkgs.latest.rustChannels.stable.rust;
};
});
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,5 @@
{
"1.48.0" = import ./1.48.0.nix;
"1.49.0" = import ./1.49.0.nix;
latest = "1.49.0";
}

@ -0,0 +1,93 @@
{
_0 = "aarch64-apple-darwin";
_1 = "aarch64-pc-windows-msvc";
_2 = "aarch64-unknown-linux-gnu";
_3 = "aarch64-unknown-linux-musl";
_4 = "arm-unknown-linux-gnueabi";
_5 = "arm-unknown-linux-gnueabihf";
_6 = "armv7-unknown-linux-gnueabihf";
_7 = "i686-pc-windows-gnu";
_8 = "i686-pc-windows-msvc";
_9 = "i686-unknown-linux-gnu";
_10 = "mips-unknown-linux-gnu";
_11 = "mips64-unknown-linux-gnuabi64";
_12 = "mips64el-unknown-linux-gnuabi64";
_13 = "mipsel-unknown-linux-gnu";
_14 = "powerpc-unknown-linux-gnu";
_15 = "powerpc64-unknown-linux-gnu";
_16 = "powerpc64le-unknown-linux-gnu";
_17 = "riscv64gc-unknown-linux-gnu";
_18 = "s390x-unknown-linux-gnu";
_19 = "x86_64-apple-darwin";
_20 = "x86_64-pc-windows-gnu";
_21 = "x86_64-pc-windows-msvc";
_22 = "x86_64-unknown-freebsd";
_23 = "x86_64-unknown-illumos";
_24 = "x86_64-unknown-linux-gnu";
_25 = "x86_64-unknown-linux-musl";
_26 = "x86_64-unknown-netbsd";
_27 = "aarch64-apple-ios";
_28 = "aarch64-fuchsia";
_29 = "aarch64-linux-android";
_30 = "arm-linux-androideabi";
_31 = "armv7-linux-androideabi";
_32 = "armv7-unknown-linux-gnueabi";
_33 = "armv7-unknown-linux-musleabi";
_34 = "i586-pc-windows-msvc";
_35 = "i686-linux-android";
_36 = "i686-unknown-freebsd";
_37 = "nvptx64-nvidia-cuda";
_38 = "sparcv9-sun-solaris";
_39 = "thumbv7neon-linux-androideabi";
_40 = "wasm32-unknown-unknown";
_41 = "wasm32-wasi";
_42 = "x86_64-apple-ios";
_43 = "x86_64-fortanix-unknown-sgx";
_44 = "x86_64-fuchsia";
_45 = "x86_64-linux-android";
_46 = "x86_64-sun-solaris";
_47 = "x86_64-unknown-linux-gnux32";
_48 = "aarch64-unknown-none";
_49 = "aarch64-unknown-none-softfloat";
_50 = "arm-unknown-linux-musleabi";
_51 = "arm-unknown-linux-musleabihf";
_52 = "armebv7r-none-eabi";
_53 = "armebv7r-none-eabihf";
_54 = "armv5te-unknown-linux-gnueabi";
_55 = "armv5te-unknown-linux-musleabi";
_56 = "armv7-unknown-linux-musleabihf";
_57 = "armv7a-none-eabi";
_58 = "armv7r-none-eabi";
_59 = "armv7r-none-eabihf";
_60 = "asmjs-unknown-emscripten";
_61 = "i586-unknown-linux-gnu";
_62 = "i586-unknown-linux-musl";
_63 = "i686-unknown-linux-musl";
_64 = "mips-unknown-linux-musl";
_65 = "mips64-unknown-linux-muslabi64";
_66 = "mips64el-unknown-linux-muslabi64";
_67 = "mipsel-unknown-linux-musl";
_68 = "riscv32i-unknown-none-elf";
_69 = "riscv32imac-unknown-none-elf";
_70 = "riscv32imc-unknown-none-elf";
_71 = "riscv64gc-unknown-none-elf";
_72 = "riscv64imac-unknown-none-elf";
_73 = "sparc64-unknown-linux-gnu";
_74 = "thumbv6m-none-eabi";
_75 = "thumbv7em-none-eabi";
_76 = "thumbv7em-none-eabihf";
_77 = "thumbv7m-none-eabi";
_78 = "thumbv7neon-unknown-linux-gnueabihf";
_79 = "thumbv8m.base-none-eabi";
_80 = "thumbv8m.main-none-eabi";
_81 = "thumbv8m.main-none-eabihf";
_82 = "wasm32-unknown-emscripten";
_83 = "x86_64-rumprun-netbsd";
_84 = "x86_64-unknown-redox";
_85 = "i686-apple-darwin";
_86 = "armv7-apple-ios";
_87 = "armv7s-apple-ios";
_88 = "i386-apple-ios";
_89 = "x86_64-unknown-cloudabi";
_90 = "wasm32-unknown-wasi";
}

@ -0,0 +1,301 @@
# Modified from: https://github.com/mozilla/nixpkgs-mozilla/blob/8c007b60731c07dd7a052cce508de3bb1ae849b4/rust-overlay.nix
# This file provide a Rust overlay, which provides pre-packaged bleeding edge versions of rustc
# and cargo.
self: super:
manifests:
let
# Manifest selector.
fromManifest = { channel }: { stdenv, fetchurl, patchelf }: let
inherit (builtins) match;
byVersion = match "([0-9]+\\.[0-9]+\\.[0-9]+)" channel != null;
manifest =
if channel == "stable" then manifests.stable.latest
else if byVersion then manifests.stable.${channel} or (throw "Version ${channel} is not available")
else throw "Unknown channel: ${channel}";
in fromManifestFile manifest { inherit stdenv fetchurl patchelf; };
getComponentsWithFixedPlatform = pkgs: pkgname: stdenv:
let
pkg = pkgs.${pkgname};
srcInfo = pkg.target.${super.rust.toRustTarget stdenv.targetPlatform} or pkg.target."*";
components = srcInfo.components or [];
componentNamesList =
builtins.map (pkg: pkg.pkg) (builtins.filter (pkg: (pkg.target != "*")) components);
in
componentNamesList;
getExtensions = pkgs: pkgname: stdenv:
let
inherit (super.lib) unique;
pkg = pkgs.${pkgname};
rustTarget = super.rust.toRustTarget stdenv.targetPlatform;
srcInfo = pkg.target.${rustTarget} or pkg.target."*" or (throw "${pkgname} is no available");
extensions = srcInfo.extensions or [];
extensionNamesList = unique (builtins.map (pkg: pkg.pkg) extensions);
in
extensionNamesList;
hasTarget = pkgs: pkgname: target:
pkgs ? ${pkgname}.target.${target};
getTuples = pkgs: name: targets:
builtins.map (target: { inherit name target; }) (builtins.filter (target: hasTarget pkgs name target) targets);
# In the manifest, a package might have different components which are bundled with it, as opposed as the extensions which can be added.
# By default, a package will include the components for the same architecture, and offers them as extensions for other architectures.
#
# This functions returns a list of { name, target } attribute sets, which includes the current system package, and all its components for the selected targets.
# The list contains the package for the pkgTargets as well as the packages for components for all compTargets
getTargetPkgTuples = pkgs: pkgname: pkgTargets: compTargets: stdenv:
let
inherit (builtins) elem;
inherit (super.lib) intersectLists;
components = getComponentsWithFixedPlatform pkgs pkgname stdenv;
extensions = getExtensions pkgs pkgname stdenv;
compExtIntersect = intersectLists components extensions;
tuples = (getTuples pkgs pkgname pkgTargets) ++ (builtins.map (name: getTuples pkgs name compTargets) compExtIntersect);
in
tuples;
getFetchUrl = pkgs: pkgname: target: stdenv: fetchurl:
let
pkg = pkgs.${pkgname};
srcInfo = pkg.target.${target};
in
(super.fetchurl { url = srcInfo.xz_url; sha256 = srcInfo.xz_hash; });
checkMissingExtensions = pkgs: pkgname: stdenv: extensions:
let
inherit (builtins) head;
inherit (super.lib) concatStringsSep subtractLists;
availableExtensions = getExtensions pkgs pkgname stdenv;
missingExtensions = subtractLists availableExtensions extensions;
extensionsToInstall =
if missingExtensions == [] then extensions else throw ''
While compiling ${pkgname}: the extension ${head missingExtensions} is not available.
Select extensions from the following list:
${concatStringsSep "\n" availableExtensions}'';
in
extensionsToInstall;
getComponents = pkgs: pkgname: targets: extensions: targetExtensions: stdenv: fetchurl:
let
inherit (builtins) head map;
inherit (super.lib) flatten remove subtractLists unique;
targetExtensionsToInstall = checkMissingExtensions pkgs pkgname stdenv targetExtensions;
extensionsToInstall = checkMissingExtensions pkgs pkgname stdenv extensions;
hostTargets = [ "*" (super.rust.toRustTarget stdenv.hostPlatform) (super.rust.toRustTarget stdenv.targetPlatform) ];
pkgTuples = flatten (getTargetPkgTuples pkgs pkgname hostTargets targets stdenv);
extensionTuples = flatten (map (name: getTargetPkgTuples pkgs name hostTargets targets stdenv) extensionsToInstall);
targetExtensionTuples = flatten (map (name: getTargetPkgTuples pkgs name targets targets stdenv) targetExtensionsToInstall);
pkgsTuples = pkgTuples ++ extensionTuples ++ targetExtensionTuples;
missingTargets = subtractLists (map (tuple: tuple.target) pkgsTuples) (remove "*" targets);
pkgsTuplesToInstall =
if missingTargets == [] then pkgsTuples else throw ''
While compiling ${pkgname}: the target ${head missingTargets} is not available for any package.'';
in
map (tuple: { name = tuple.name; src = (getFetchUrl pkgs tuple.name tuple.target stdenv fetchurl); }) pkgsTuplesToInstall;
installComponents = stdenv: namesAndSrcs:
let
inherit (builtins) map;
installComponent = name: src:
stdenv.mkDerivation {
inherit name;
inherit src;
# No point copying src to a build server, then copying back the
# entire unpacked contents after just a little twiddling.
preferLocalBuild = true;
# (@nbp) TODO: Check on Windows and Mac.
# This code is inspired by patchelf/setup-hook.sh to iterate over all binaries.
installPhase = ''
patchShebangs install.sh
CFG_DISABLE_LDCONFIG=1 ./install.sh --prefix=$out --verbose
setInterpreter() {
local dir="$1"
[ -e "$dir" ] || return 0
header "Patching interpreter of ELF executables and libraries in $dir"
local i
while IFS= read -r -d ''$'\0' i; do
if [[ "$i" =~ .build-id ]]; then continue; fi
if ! isELF "$i"; then continue; fi
echo "setting interpreter of $i"
if [[ -x "$i" ]]; then
# Handle executables
patchelf \
--set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
--set-rpath "${super.lib.makeLibraryPath [ self.zlib ]}:$out/lib" \
"$i" || true
else
# Handle libraries
patchelf \
--set-rpath "${super.lib.makeLibraryPath [ self.zlib ]}:$out/lib" \
"$i" || true
fi
done < <(find "$dir" -type f -print0)
}
setInterpreter $out
'';
postFixup = ''
# Function moves well-known files from etc/
handleEtc() {
local oldIFS="$IFS"
# Directories we are aware of, given as substitution lists
for paths in \
"etc/bash_completion.d","share/bash_completion/completions","etc/bash_completions.d","share/bash_completions/completions";
do
# Some directoties may be missing in some versions. If so we just skip them.
# See https://github.com/mozilla/nixpkgs-mozilla/issues/48 for more infomation.
if [ ! -e $paths ]; then continue; fi
IFS=","
set -- $paths
IFS="$oldIFS"
local orig_path="$1"
local wanted_path="$2"
# Rename the files
if [ -d ./"$orig_path" ]; then
mkdir -p "$(dirname ./"$wanted_path")"
fi
mv -v ./"$orig_path" ./"$wanted_path"
# Fail explicitly if etc is not empty so we can add it to the list and/or report it upstream
rmdir ./etc || {
echo Installer tries to install to /etc:
find ./etc
exit 1
}
done
}
if [ -d "$out"/etc ]; then
pushd "$out"
handleEtc
popd
fi
'';
dontStrip = true;
};
in
map (nameAndSrc: (installComponent nameAndSrc.name nameAndSrc.src)) namesAndSrcs;
# Manifest files are organized as follow:
# { date = "2017-03-03";
# pkg.cargo.version= "0.18.0-nightly (5db6d64 2017-03-03)";
# pkg.cargo.target.x86_64-unknown-linux-gnu = {
# available = true;
# hash = "abce..."; # sha256
# url = "https://static.rust-lang.org/dist/....tar.gz";
# xz_hash = "abce..."; # sha256
# xz_url = "https://static.rust-lang.org/dist/....tar.xz";
# };
# }
#
# The packages available usually are:
# cargo, rust-analysis, rust-docs, rust-src, rust-std, rustc, and
# rust, which aggregates them in one package.
#
# For each package the following options are available:
# extensions - The extensions that should be installed for the package.
# For example, install the package rust and add the extension rust-src.
# targets - The package will always be installed for the host system, but with this option
# extra targets can be specified, e.g. "mips-unknown-linux-musl". The target
# will only apply to components of the package that support being installed for
# a different architecture. For example, the rust package will install rust-std
# for the host system and the targets.
# targetExtensions - If you want to force extensions to be installed for the given targets, this is your option.
# 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!
fromManifestFile = pkgs: { stdenv, fetchurl, patchelf }:
let
inherit (builtins) elemAt;
inherit (super) makeOverridable;
inherit (super.lib) flip mapAttrs;
in
flip mapAttrs pkgs.pkg (name: pkg:
makeOverridable ({extensions, targets, targetExtensions}:
let
version' = builtins.match "([^ ]*) [(]([^ ]*) ([^ ]*)[)]" pkg.version;
version = if version' == null then pkg.version else "${elemAt version' 0}-${elemAt version' 2}-${elemAt version' 1}";
namesAndSrcs = getComponents pkgs.pkg name targets extensions targetExtensions stdenv fetchurl;
components = installComponents stdenv namesAndSrcs;
componentsOuts = builtins.map (comp: (super.lib.strings.escapeNixString (super.lib.getOutput "out" comp))) components;
in
super.pkgs.symlinkJoin {
name = name + "-" + version;
paths = components;
postBuild = ''
# If rustc or rustdoc is in the derivation, we need to copy their
# executable into the final derivation. This is required
# for making them find the correct SYSROOT.
for target in $out/bin/{rustc,rustdoc}; do
if [ -e $target ]; then
cp --remove-destination "$(realpath -e $target)" $target
fi
done
'';
# Add the compiler as part of the propagated build inputs in order
# to run:
#
# $ nix-shell -p rustChannels.stable.rust
#
# And get a fully working Rust compiler, with the stdenv linker.
propagatedBuildInputs = [ stdenv.cc ];
meta.platforms = stdenv.lib.platforms.all;
}
) { extensions = []; targets = []; targetExtensions = []; }
);
in
rec {
lib = super.lib // {
rustLib = {
inherit fromManifest fromManifestFile;
};
};
rustChannelOf = manifest_args: fromManifest
manifest_args
{ inherit (self) stdenv fetchurl patchelf; };
# Set of packages which are automagically updated. Do not rely on these for
# reproducible builds.
latest = (super.latest or {}) // {
rustChannels = {
nightly = rustChannelOf { channel = "nightly"; };
beta = rustChannelOf { channel = "beta"; };
stable = rustChannelOf { channel = "stable"; };
};
};
# Helper builder
rustChannelOfTargets = channel: date: targets:
(rustChannelOf { inherit channel date; })
.rust.override { inherit targets; };
# For backward compatibility
rustChannels = latest.rustChannels;
# For each channel:
# latest.rustChannels.nightly.cargo
# latest.rustChannels.nightly.rust # Aggregate all others. (recommended)
# latest.rustChannels.nightly.rustc
# latest.rustChannels.nightly.rust-analysis
# latest.rustChannels.nightly.rust-docs
# latest.rustChannels.nightly.rust-src
# latest.rustChannels.nightly.rust-std
# For a specific date:
# (rustChannelOf { date = "2017-06-06"; channel = "beta"; }).rust
}
Loading…
Cancel
Save