push sheeet
Some checks failed
Periodic Merges (6h) / master → staging-nixos (push) Failing after 12m50s
Periodic Merges (6h) / master → staging-next (push) Failing after 12m54s
Periodic Merges (24h) / merge-base(master,staging) → haskell-updates (push) Failing after 11m54s
Periodic Merges (6h) / staging-next → staging (push) Failing after 12m13s
Periodic Merges (24h) / staging-next-25.05 → staging-25.05 (push) Failing after 13m24s
Periodic Merges (24h) / release-25.05 → staging-next-25.05 (push) Failing after 14m28s

This commit is contained in:
Dark Steveneq
2025-10-09 14:15:47 +02:00
commit 646b892680
49168 changed files with 5897842 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
{
rust-bindgen-unwrapped,
zlib,
bash,
runCommand,
runCommandCC,
}:
let
clang = rust-bindgen-unwrapped.clang;
self =
runCommand "rust-bindgen-${rust-bindgen-unwrapped.version}"
{
#for substituteAll
inherit bash;
unwrapped = rust-bindgen-unwrapped;
meta = rust-bindgen-unwrapped.meta // {
longDescription = rust-bindgen-unwrapped.meta.longDescription + ''
This version of bindgen is wrapped with the required compiler flags
required to find the c and c++ standard library, as well as the libraries
specified in the buildInputs of your derivation.
'';
};
passthru.tests = {
simple-c = runCommandCC "simple-c-bindgen-tests" { } ''
echo '#include <stdlib.h>' > a.c
${self}/bin/bindgen a.c --allowlist-function atoi | tee output
grep atoi output
touch $out
'';
simple-cpp = runCommandCC "simple-cpp-bindgen-tests" { } ''
echo '#include <cmath>' > a.cpp
${self}/bin/bindgen a.cpp --allowlist-function erf -- -xc++ | tee output
grep erf output
touch $out
'';
with-lib = runCommandCC "zlib-bindgen-tests" { buildInputs = [ zlib ]; } ''
echo '#include <zlib.h>' > a.c
${self}/bin/bindgen a.c --allowlist-function compress | tee output
grep compress output
touch $out
'';
};
}
# if you modify the logic to find the right clang flags, also modify rustPlatform.bindgenHook
''
mkdir -p $out/bin
export cincludes="$(< ${clang}/nix-support/cc-cflags) $(< ${clang}/nix-support/libc-cflags)"
export cxxincludes="$(< ${clang}/nix-support/libcxx-cxxflags)"
substituteAll ${./wrapper.sh} $out/bin/bindgen
chmod +x $out/bin/bindgen
'';
in
self

View File

@@ -0,0 +1,58 @@
{
lib,
fetchCrate,
rustPlatform,
clang,
rustfmt,
}:
let
# bindgen hardcodes rustfmt outputs that use nightly features
rustfmt-nightly = rustfmt.override { asNightly = true; };
in
rustPlatform.buildRustPackage rec {
pname = "rust-bindgen-unwrapped";
version = "0.72.0";
src = fetchCrate {
pname = "bindgen-cli";
inherit version;
hash = "sha256-0hIxXKq7zu/gq0QAs2Ffuq584a9w1RWctPs9SBfc0/I=";
};
cargoHash = "sha256-K/iM79RfNU+3f2ae6wy/FMFAD68vfqzSUebqALPJpJY=";
preConfigure = ''
export LIBCLANG_PATH="${lib.getLib clang.cc}/lib"
'';
# Disable the "runtime" feature, so libclang is linked.
buildNoDefaultFeatures = true;
buildFeatures = [ "logging" ];
checkNoDefaultFeatures = buildNoDefaultFeatures;
checkFeatures = buildFeatures;
doCheck = true;
nativeCheckInputs = [ clang ];
RUSTFMT = "${rustfmt-nightly}/bin/rustfmt";
preCheck = ''
# for the ci folder, notably
patchShebangs .
'';
passthru = { inherit clang; };
meta = with lib; {
description = "Automatically generates Rust FFI bindings to C (and some C++) libraries";
longDescription = ''
Bindgen takes a c or c++ header file and turns them into
rust ffi declarations.
'';
homepage = "https://github.com/rust-lang/rust-bindgen";
license = with licenses; [ bsd3 ];
maintainers = with maintainers; [ johntitor ];
mainProgram = "bindgen";
platforms = platforms.unix;
};
}

View File

@@ -0,0 +1,34 @@
#!@bash@/bin/bash
sep='--' # whether to add -- before new options
cxx=0 # whether cxx was explicitly requested
lastWasx=0 # whether the last argument passed was -x
for e in "$@"; do
if [[ "$e" == "--" ]]; then
sep=
fi;
if [[ "$sep" == "" ]]; then
# we look for -x c++ after -- only
if [[ "$e" == "-x" ]]; then
lastWasx=1
fi;
if [[ $lastWasx -eq 1 && "$e" == "c++" ]]; then
lastWasx=0
cxx=1
fi;
if [[ "$e" == "-xc++" || "$e" == -std=c++* ]]; then
cxx=1
fi;
fi;
done;
cxxflags=
if [[ $cxx -eq 1 ]]; then
cxxflags="@cxxincludes@"
fi;
if [[ -n "$NIX_DEBUG" ]]; then
set -x;
fi;
# shellcheck disable=SC2086
# cxxflags and NIX_CFLAGS_COMPILE should be word-split
exec -a "$0" @unwrapped@/bin/bindgen "$@" $sep $cxxflags @cincludes@ $NIX_CFLAGS_COMPILE
# note that we add the flags after $@ which is incorrect. This is only for the sake
# of simplicity.

View File

@@ -0,0 +1,194 @@
# preBuildAndTest and some small other bits
# taken from https://github.com/tcdi/pgrx/blob/v0.9.4/nix/extension.nix
# (but now heavily modified)
# which uses MIT License with the following license file
#
# MIT License
#
# Portions Copyright 2019-2021 ZomboDB, LLC.
# Portions Copyright 2021-2022 Technology Concepts & Design, Inc. <support@tcdi.com>.
# All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
{
lib,
pkg-config,
rustPlatform,
stdenv,
writeShellScriptBin,
}:
# The idea behind: Use it mostly like rustPlatform.buildRustPackage and so
# we hand most of the arguments down.
#
# Additional arguments are:
# - `postgresql` postgresql package of the version of postgresql this extension should be build for.
# Needs to be the build platform variant.
# - `useFakeRustfmt` Whether to use a noop fake command as rustfmt. cargo-pgrx tries to call rustfmt.
# If the generated rust bindings aren't needed to use the extension, its a
# unnecessary and heavy dependency. If you set this to true, you also
# have to add `rustfmt` to `nativeBuildInputs`.
# - `usePgTestCheckFeature` Whether to enable the `pg_test` feature during the check phase.
lib.extendMkDerivation {
constructDrv = rustPlatform.buildRustPackage;
excludeDrvArgNames = [
"postgresql"
"useFakeRustfmt"
"usePgTestCheckFeature"
];
extendDrvArgs =
finalAttrs:
{
buildAndTestSubdir ? null,
buildType ? "release",
buildFeatures ? [ ],
cargoBuildFlags ? [ ],
cargoPgrxFlags ? [ ],
# pinned dependencies
cargo-pgrx,
postgresql,
# cargo-pgrx calls rustfmt on generated bindings, this is not strictly necessary, so we avoid the
# dependency here. Set to false and provide rustfmt in nativeBuildInputs, if you need it, e.g.
# if you include the generated code in the output via postInstall.
useFakeRustfmt ? true,
usePgTestCheckFeature ? true,
...
}@args:
let
rustfmtInNativeBuildInputs = lib.lists.any (dep: lib.getName dep == "rustfmt") (
args.nativeBuildInputs or [ ]
);
in
assert lib.asserts.assertMsg (
(args.installPhase or "") == ""
) "buildPgrxExtension overwrites the installPhase, so providing one does nothing";
assert lib.asserts.assertMsg (
(args.buildPhase or "") == ""
) "buildPgrxExtension overwrites the buildPhase, so providing one does nothing";
assert lib.asserts.assertMsg (useFakeRustfmt -> !rustfmtInNativeBuildInputs)
"The parameter useFakeRustfmt is set to true, but rustfmt is included in nativeBuildInputs. Either set useFakeRustfmt to false or remove rustfmt from nativeBuildInputs.";
assert lib.asserts.assertMsg (!useFakeRustfmt -> rustfmtInNativeBuildInputs)
"The parameter useFakeRustfmt is set to false, but rustfmt is not included in nativeBuildInputs. Either set useFakeRustfmt to true or add rustfmt from nativeBuildInputs.";
let
fakeRustfmt = writeShellScriptBin "rustfmt" ''
exit 0
'';
maybeDebugFlag = lib.optionalString (buildType != "release") "--debug";
maybeEnterBuildAndTestSubdir = lib.optionalString (buildAndTestSubdir != null) ''
export CARGO_TARGET_DIR="$(pwd)/target"
pushd "${buildAndTestSubdir}"
'';
maybeLeaveBuildAndTestSubdir = lib.optionalString (buildAndTestSubdir != null) "popd";
pgrxPostgresMajor = lib.versions.major postgresql.version;
preBuildAndTest = ''
export PGRX_HOME="$(mktemp -d)"
export PGDATA="$PGRX_HOME/data-${pgrxPostgresMajor}/"
cargo-pgrx pgrx init "--pg${pgrxPostgresMajor}" ${postgresql.pg_config}/bin/pg_config
# unix sockets work in sandbox, too.
export PGHOST="$(mktemp -d)"
cat > "$PGDATA/postgresql.conf" <<EOF
listen_addresses = ''\''
unix_socket_directories = '$PGHOST'
EOF
# This is primarily for Mac or other Nix systems that don't use the nixbld user.
export USER="$(whoami)"
pg_ctl start
createuser --superuser --createdb "$USER" || true
pg_ctl stop
'';
cargoPgrxFlags' = lib.escapeShellArgs cargoPgrxFlags;
in
{
buildInputs = (args.buildInputs or [ ]);
nativeBuildInputs =
(args.nativeBuildInputs or [ ])
++ [
cargo-pgrx
postgresql
pkg-config
rustPlatform.bindgenHook
]
++ lib.optionals useFakeRustfmt [ fakeRustfmt ];
buildPhase = ''
runHook preBuild
echo "Executing cargo-pgrx buildPhase"
${preBuildAndTest}
${maybeEnterBuildAndTestSubdir}
PGRX_BUILD_FLAGS="--frozen -j $NIX_BUILD_CORES ${builtins.concatStringsSep " " cargoBuildFlags}" \
${lib.optionalString stdenv.hostPlatform.isDarwin ''RUSTFLAGS="''${RUSTFLAGS:+''${RUSTFLAGS} }-Clink-args=-Wl,-undefined,dynamic_lookup"''} \
cargo pgrx package \
${cargoPgrxFlags'} \
--pg-config ${postgresql.pg_config}/bin/pg_config \
${maybeDebugFlag} \
--features "${builtins.concatStringsSep " " buildFeatures}" \
--out-dir "$out"
${maybeLeaveBuildAndTestSubdir}
runHook postBuild
'';
preCheck = preBuildAndTest + args.preCheck or "";
installPhase = ''
runHook preInstall
echo "Executing buildPgrxExtension install"
${maybeEnterBuildAndTestSubdir}
cargo-pgrx pgrx stop all ${cargoPgrxFlags'}
mv $out/${postgresql}/* $out
rm -rf $out/nix
${maybeLeaveBuildAndTestSubdir}
runHook postInstall
'';
PGRX_PG_SYS_SKIP_BINDING_REWRITE = "1";
CARGO_BUILD_INCREMENTAL = "false";
RUST_BACKTRACE = "full";
checkNoDefaultFeatures = true;
checkFeatures =
(args.checkFeatures or [ ])
++ (lib.optionals usePgTestCheckFeature [ "pg_test" ])
++ [ "pg${pgrxPostgresMajor}" ];
meta = (args.meta or { }) // {
# See comment in postgresql's generic.nix doInstallCheck section
broken = (args.meta.broken or false) || stdenv.hostPlatform.isDarwin;
};
};
}

View File

@@ -0,0 +1,68 @@
{
fetchCrate,
lib,
openssl,
pkg-config,
rustPlatform,
}:
let
generic =
{
version,
hash,
cargoHash,
}:
rustPlatform.buildRustPackage {
pname = "cargo-pgrx";
inherit version;
src = fetchCrate {
inherit version hash;
pname = "cargo-pgrx";
};
inherit cargoHash;
nativeBuildInputs = [
pkg-config
];
buildInputs = [
openssl
];
preCheck = ''
export PGRX_HOME=$(mktemp -d)
'';
checkFlags = [
# requires pgrx to be properly initialized with cargo pgrx init
"--skip=command::schema::tests::test_parse_managed_postmasters"
];
meta = {
description = "Build Postgres Extensions with Rust";
homepage = "https://github.com/pgcentralfoundation/pgrx";
changelog = "https://github.com/pgcentralfoundation/pgrx/releases/tag/v${version}";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [
happysalada
matthiasbeyer
];
mainProgram = "cargo-pgrx";
};
};
in
{
# Default version for direct usage.
# Not to be used with buildPgrxExtension, where it should be pinned.
# When you make an extension use the latest version, *copy* this to a separate pinned attribute.
cargo-pgrx = generic {
version = "0.16.1";
hash = "sha256-AjoBr+/sEPdzbD0wLUNVm2syCySkGaFOFQ70TST1U9w=";
cargoHash = "sha256-95DHq5GLnAqb3bbKwwaeBeKEmkfRh81ZTRaJ7L59DAg=";
};
}
// lib.mapAttrs (_: generic) (import ./pinned.nix)

View File

@@ -0,0 +1,26 @@
# nixpkgs-update: no auto update
{
cargo-pgrx_0_12_0_alpha_1 = {
version = "0.12.0-alpha.1";
hash = "sha256-0m9oaqjU42RYyttkTihADDrRMjr2WoK/8sInZALeHws=";
cargoHash = "sha256-zYjqE7LZLnTaVxWAPWC1ncEjCMlrhy4THtgecB7wBYY=";
};
cargo-pgrx_0_12_6 = {
version = "0.12.6";
hash = "sha256-7aQkrApALZe6EoQGVShGBj0UIATnfOy2DytFj9IWdEA=";
cargoHash = "sha256-pnMxWWfvr1/AEp8DvG4awig8zjdHizJHoZ5RJA8CL08=";
};
cargo-pgrx_0_14_1 = {
version = "0.14.1";
hash = "sha256-oMToAhKkRiCyC8JYS0gmo/XX3QVcVtF5mUV0aQjd+p8=";
cargoHash = "sha256-RawGAQGtG2QVDCMbwjmUEaH6rDeRiBvvJsGCY8wySw0=";
};
cargo-pgrx_0_16_0 = {
version = "0.16.0";
hash = "sha256-emNR7fXNVD9sY/Mdno7mwpH6l/7AD28cBUsFRn9je50=";
cargoHash = "sha256-3eyBDWDoCzSU0tbab8qbjSnBkkN0oOgd7YbuyHLEHYw=";
};
}

View File

@@ -0,0 +1,61 @@
diff --git a/src/main.rs b/src/main.rs
index 3cb6896..7f070e0 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -275,7 +275,9 @@ fn install_single_toolchain(
// install
if maybe_dry_client.is_some() {
- rename(&toolchain.dest, toolchain_path)?;
+ rename(&toolchain.dest, toolchain_path.clone())?;
+ nix_patchelf(toolchain_path)
+ .expect("failed to patch toolchain for NixOS");
eprintln!(
"toolchain `{}` is successfully installed!",
toolchain.dest.display()
@@ -291,6 +293,45 @@ fn install_single_toolchain(
Ok(())
}
+fn nix_patchelf(mut toolchain_path: PathBuf) -> Result<(), Error> {
+ toolchain_path.push("bin");
+
+ for entry in toolchain_path.read_dir()? {
+ let entry = entry?;
+ if !entry.file_type()?.is_file() {
+ continue;
+ }
+
+ eprintln!("info: you seem to be running NixOS. Attempting to patch {}",
+ entry.path().to_str().unwrap());
+ let _ = ::std::process::Command::new("@patchelf@/bin/patchelf")
+ .arg("--set-interpreter")
+ .arg("@dynamicLinker@")
+ .arg(entry.path())
+ .output();
+ }
+
+ toolchain_path.pop();
+ toolchain_path.push("lib");
+
+ for entry in toolchain_path.read_dir()? {
+ let entry = entry?;
+ if !entry.file_type()?.is_file() {
+ continue;
+ }
+
+ eprintln!("info: you seem to be running NixOS. Attempting to patch {}",
+ entry.path().to_str().unwrap());
+ let _ = ::std::process::Command::new("@patchelf@/bin/patchelf")
+ .arg("--set-rpath")
+ .arg("@libPath@")
+ .arg(entry.path())
+ .output();
+ }
+
+ Ok(())
+}
+
fn fetch_master_commit(client: &Client, github_token: Option<&str>) -> Result<String, Error> {
eprintln!("fetching master commit hash... ");
fetch_master_commit_via_git()

View File

@@ -0,0 +1,51 @@
{
lib,
rustPlatform,
fetchFromGitHub,
stdenv,
patchelf,
zlib,
pkg-config,
openssl,
xz,
replaceVars,
}:
rustPlatform.buildRustPackage (finalAttrs: {
pname = "rustup-toolchain-install-master";
version = "1.9.0";
src = fetchFromGitHub {
owner = "kennytm";
repo = "rustup-toolchain-install-master";
tag = "v${finalAttrs.version}";
hash = "sha256-0ayc4rzlZ9sLKzRhVr1fpRD7bmwQL69rkQ2jXBAdUPI=";
};
cargoHash = "sha256-VxrtkZbi9BprQOQFxOIAYEoAtg0kqyL3C4ih/5RobZI=";
patches = lib.optional stdenv.hostPlatform.isLinux (
replaceVars ./0001-dynamically-patchelf-binaries.patch {
inherit patchelf;
dynamicLinker = "${stdenv.cc.libc}/lib/ld-linux-x86-64.so.2";
libPath = lib.makeLibraryPath [
zlib
(placeholder "out" + "/lib")
];
}
);
nativeBuildInputs = [ pkg-config ];
buildInputs = [
openssl
xz
];
meta = with lib; {
description = "Install a rustc master toolchain usable from rustup";
mainProgram = "rustup-toolchain-install-master";
homepage = "https://github.com/kennytm/rustup-toolchain-install-master";
license = licenses.mit;
maintainers = [ ];
};
})

View File

@@ -0,0 +1,189 @@
diff --git a/src/dist/component/package.rs b/src/dist/component/package.rs
index dfccc661..85233f3b 100644
--- a/src/dist/component/package.rs
+++ b/src/dist/component/package.rs
@@ -113,6 +113,7 @@ impl Package for DirectoryPackage {
} else {
builder.move_file(path.clone(), &src_path)?
}
+ nix_patchelf_if_needed(&target.prefix().path().join(path.clone()))
}
"dir" => {
if self.copy {
@@ -135,6 +136,176 @@ impl Package for DirectoryPackage {
}
}
+fn nix_wrap_lld(dest_lld_path: &Path) -> Result<()> {
+ use std::fs;
+ use std::io::Write;
+ use std::os::unix::fs::PermissionsExt;
+
+ let path = dest_lld_path.parent().unwrap();
+ let mut unwrapped_name = path.file_name().unwrap().to_string_lossy().to_string();
+ unwrapped_name.push_str("-unwrapped");
+ let unwrapped_dir = path.with_file_name(unwrapped_name);
+ fs::create_dir_all(&unwrapped_dir).context("failed to create unwrapped directory")?;
+ let mut unwrapped_lld = unwrapped_dir;
+ unwrapped_lld.push(dest_lld_path.file_name().unwrap());
+ fs::rename(dest_lld_path, &unwrapped_lld).context("failed to move file")?;
+ let mut ld_wrapper_path = std::env::current_exe()?
+ .parent()
+ .ok_or(anyhow!("failed to get parent directory"))?
+ .with_file_name("nix-support");
+ let mut file = std::fs::File::create(dest_lld_path)?;
+ ld_wrapper_path.push("ld-wrapper.sh");
+
+ let wrapped_script = format!(
+ "#!/usr/bin/env bash
+set -eu -o pipefail +o posix
+shopt -s nullglob
+export PROG=\"{}\"
+\"{}\" $@",
+ unwrapped_lld.to_string_lossy().to_string(),
+ ld_wrapper_path.to_string_lossy().to_string(),
+ );
+ file.write_all(wrapped_script.as_bytes())?;
+ let mut permissions = file.metadata()?.permissions();
+ permissions.set_mode(0o755);
+ file.set_permissions(permissions)?;
+ Ok(())
+}
+
+fn nix_patchelf_if_needed(dest_path: &Path) {
+ use std::fs::File;
+ use std::os::unix::fs::FileExt;
+ use tracing::{debug, warn};
+
+ struct ELFReader<'a> {
+ file: &'a mut File,
+ is_32bit: bool,
+ is_little_end: bool,
+ }
+
+ impl<'a> ELFReader<'a> {
+ const MAGIC_NUMBER: &'static [u8] = &[0x7F, 0x45, 0x4c, 0x46];
+ const ET_EXEC: u16 = 0x2;
+ const ET_DYN: u16 = 0x3;
+ const PT_INTERP: u32 = 0x3;
+
+ fn new(file: &'a mut File) -> Option<Self> {
+ let mut magic_number = [0; 4];
+ file.read_exact(&mut magic_number).ok()?;
+ if Self::MAGIC_NUMBER != magic_number {
+ return None;
+ }
+ let mut ei_class = [0; 1];
+ file.read_exact_at(&mut ei_class, 0x4).ok()?;
+ let is_32bit = ei_class[0] == 1;
+ let mut ei_data = [0; 1];
+ file.read_exact_at(&mut ei_data, 0x5).ok()?;
+ let is_little_end = ei_data[0] == 1;
+ Some(Self {
+ file,
+ is_32bit,
+ is_little_end,
+ })
+ }
+
+ fn is_exec_or_dyn(&self) -> bool {
+ let e_type = self.read_u16_at(0x10);
+ e_type == Self::ET_EXEC || e_type == Self::ET_DYN
+ }
+
+ fn e_phoff(&self) -> u64 {
+ if self.is_32bit {
+ self.read_u32_at(0x1C) as u64
+ } else {
+ self.read_u64_at(0x20)
+ }
+ }
+
+ fn e_phentsize(&self) -> u64 {
+ let offset = if self.is_32bit { 0x2A } else { 0x36 };
+ self.read_u16_at(offset) as u64
+ }
+
+ fn e_phnum(&self) -> u64 {
+ let offset = if self.is_32bit { 0x2C } else { 0x38 };
+ self.read_u16_at(offset) as u64
+ }
+
+ fn has_interp(&self) -> bool {
+ let e_phoff = self.e_phoff();
+ let e_phentsize = self.e_phentsize();
+ let e_phnum = self.e_phnum();
+ for i in 0..e_phnum {
+ let p_type = self.read_u32_at(e_phoff + i * e_phentsize);
+ if p_type == Self::PT_INTERP {
+ return true;
+ }
+ }
+ false
+ }
+
+ fn read_u16_at(&self, offset: u64) -> u16 {
+ let mut data = [0; 2];
+ self.file.read_exact_at(&mut data, offset).unwrap();
+ if self.is_little_end {
+ u16::from_le_bytes(data)
+ } else {
+ u16::from_be_bytes(data)
+ }
+ }
+
+ fn read_u32_at(&self, offset: u64) -> u32 {
+ let mut data = [0; 4];
+ self.file.read_exact_at(&mut data, offset).unwrap();
+ if self.is_little_end {
+ u32::from_le_bytes(data)
+ } else {
+ u32::from_be_bytes(data)
+ }
+ }
+
+ fn read_u64_at(&self, offset: u64) -> u64 {
+ let mut data = [0; 8];
+ self.file.read_exact_at(&mut data, offset).unwrap();
+ if self.is_little_end {
+ u64::from_le_bytes(data)
+ } else {
+ u64::from_be_bytes(data)
+ }
+ }
+ }
+
+ let Some(mut dest_file) = File::open(dest_path).ok() else {
+ return;
+ };
+ let Some(elf) = ELFReader::new(&mut dest_file) else {
+ return;
+ };
+ if !elf.is_exec_or_dyn() {
+ return;
+ }
+ let mut patch_command = std::process::Command::new("@patchelf@/bin/patchelf");
+ if elf.has_interp() {
+ patch_command
+ .arg("--set-interpreter")
+ .arg("@dynamicLinker@");
+ }
+ if Some(std::ffi::OsStr::new("rust-lld")) == dest_path.file_name() || !elf.has_interp() {
+ patch_command.arg("--add-rpath").arg("@libPath@");
+ }
+
+ debug!("patching {dest_path:?} using patchelf");
+ if let Err(err) = patch_command.arg(dest_path).output() {
+ warn!("failed to execute patchelf: {err:?}");
+ }
+
+ if Some(std::ffi::OsStr::new("ld.lld")) == dest_path.file_name() {
+ if let Err(err) = nix_wrap_lld(dest_path) {
+ warn!("failed to wrap `ld.lld`: {err:?}");
+ }
+ }
+}
+
#[derive(Debug)]
pub(crate) struct TarPackage<'a>(DirectoryPackage, temp::Dir<'a>);

View File

@@ -0,0 +1,166 @@
{
stdenv,
lib,
runCommand,
patchelf,
fetchFromGitHub,
rustPlatform,
makeBinaryWrapper,
pkg-config,
openssl,
curl,
writableTmpDirAsHomeHook,
installShellFiles,
zlib,
libiconv,
xz,
buildPackages,
}:
let
libPath = lib.makeLibraryPath [
zlib # libz.so.1
];
in
rustPlatform.buildRustPackage (finalAttrs: {
pname = "rustup";
version = "1.28.2";
src = fetchFromGitHub {
owner = "rust-lang";
repo = "rustup";
tag = finalAttrs.version;
hash = "sha256-iX5hEaQwCW9MuyafjXml8jV3EDnxRNUlOoy3Cur/Iyw=";
};
cargoHash = "sha256-KljaAzYHbny7KHOO51MotdmNpHCKWdt6kc/FIpFN6c0=";
nativeBuildInputs = [
makeBinaryWrapper
pkg-config
writableTmpDirAsHomeHook
installShellFiles
];
buildInputs = [
openssl
curl
zlib
]
++ lib.optionals stdenv.hostPlatform.isDarwin [
libiconv
xz
];
buildFeatures = [ "no-self-update" ];
checkFeatures = [ "test" ];
patches = lib.optionals stdenv.hostPlatform.isLinux [
(runCommand "0001-dynamically-patchelf-binaries.patch"
{
CC = stdenv.cc;
patchelf = patchelf;
libPath = "${libPath}";
}
''
export dynamicLinker=$(cat $CC/nix-support/dynamic-linker)
substitute ${./0001-dynamically-patchelf-binaries.patch} $out \
--subst-var patchelf \
--subst-var dynamicLinker \
--subst-var libPath
''
)
];
# Random tests fail nondeterministically on macOS.
# TODO: Investigate this.
doCheck = !stdenv.hostPlatform.isDarwin;
# Random failures when running tests in parallel.
preCheck = ''
export NIX_BUILD_CORES=1
'';
# skip failing tests
checkFlags = [
# auto-self-update mode is set to 'disable' for nix rustup
"--skip=suite::cli_exact::check_updates_none"
"--skip=suite::cli_exact::check_updates_some"
"--skip=suite::cli_exact::check_updates_with_update"
# rustup-init is not used in nix rustup
"--skip=suite::cli_ui::rustup_init_ui_doc_text_tests"
];
postInstall = ''
pushd $out/bin
mv rustup-init rustup
binlinks=(
cargo rustc rustdoc rust-gdb rust-lldb rls rustfmt cargo-fmt
cargo-clippy clippy-driver cargo-miri rust-gdbgui rust-analyzer
)
for link in ''${binlinks[@]}; do
ln -s rustup $link
done
popd
wrapProgram $out/bin/rustup --prefix "LD_LIBRARY_PATH" : "${libPath}"
# tries to create .rustup
mkdir -p "$out/share/"{bash-completion/completions,fish/vendor_completions.d,zsh/site-functions}
${lib.optionalString (stdenv.hostPlatform.emulatorAvailable buildPackages) (
let
emulator = stdenv.hostPlatform.emulator buildPackages;
in
''
# generate completion scripts for rustup
installShellCompletion --cmd rustup \
--bash <(${emulator} $out/bin/rustup completions bash rustup) \
--fish <(${emulator} $out/bin/rustup completions fish rustup) \
--zsh <(${emulator} $out/bin/rustup completions zsh rustup)
# generate completion scripts for cargo
# Note: fish completion script is not supported.
installShellCompletion --cmd cargo \
--bash <(${emulator} $out/bin/rustup completions bash cargo) \
--zsh <(${emulator} $out/bin/rustup completions zsh cargo)
''
)}
# add a wrapper script for ld.lld
mkdir -p $out/nix-support
substituteAll ${../../../../../pkgs/build-support/wrapper-common/utils.bash} $out/nix-support/utils.bash
substituteAll ${../../../../../pkgs/build-support/wrapper-common/darwin-sdk-setup.bash} $out/nix-support/darwin-sdk-setup.bash
substituteAll ${../../../../../pkgs/build-support/bintools-wrapper/add-flags.sh} $out/nix-support/add-flags.sh
substituteAll ${../../../../../pkgs/build-support/bintools-wrapper/add-hardening.sh} $out/nix-support/add-hardening.sh
export prog='$PROG'
export use_response_file_by_default=0
substituteAll ${../../../../../pkgs/build-support/bintools-wrapper/ld-wrapper.sh} $out/nix-support/ld-wrapper.sh
chmod +x $out/nix-support/ld-wrapper.sh
'';
env = {
inherit (stdenv.cc.bintools)
expandResponseParams
shell
suffixSalt
wrapperName
coreutils_bin
;
hardening_unsupported_flags = "";
};
meta = {
description = "Rust toolchain installer";
homepage = "https://www.rustup.rs/";
license = with lib.licenses; [
asl20 # or
mit
];
maintainers = with lib.maintainers; [
mic92
];
mainProgram = "rustup";
};
})