diff options
Diffstat (limited to 'pkgs/build-support')
22 files changed, 416 insertions, 94 deletions
diff --git a/pkgs/build-support/appimage/appimage-exec.sh b/pkgs/build-support/appimage/appimage-exec.sh index 82ebdd0bbe4a..7986c589667b 100755 --- a/pkgs/build-support/appimage/appimage-exec.sh +++ b/pkgs/build-support/appimage/appimage-exec.sh @@ -1,4 +1,6 @@ #!@shell@ +# shellcheck shell=bash + if [ -n "$DEBUG" ] ; then set -x fi @@ -13,8 +15,10 @@ unpack() { local out="$2" # https://github.com/AppImage/libappimage/blob/ca8d4b53bed5cbc0f3d0398e30806e0d3adeaaab/src/libappimage/utils/MagicBytesChecker.cpp#L45-L63 - local appimageSignature=$(readelf -h "$src" | awk 'NR==2{print $10$11;}') - local appimageType=$(readelf -h "$src" | awk 'NR==2{print $12;}') + local appimageSignature; + appimageSignature="$(LC_ALL=C readelf -h "$src" | awk 'NR==2{print $10$11;}')" + local appimageType; + appimageType="$(LC_ALL=C readelf -h "$src" | awk 'NR==2{print $12;}')" # check AppImage signature if [ "$appimageSignature" != "4149" ]; then @@ -35,7 +39,7 @@ unpack() { # multiarch offset one-liner using same method as AppImage # see https://gist.github.com/probonopd/a490ba3401b5ef7b881d5e603fa20c93 - offset=$(readelf -h "$src" | awk 'NR==13{e_shoff=$5} NR==18{e_shentsize=$5} NR==19{e_shnum=$5} END{print e_shoff+e_shentsize*e_shnum}') + offset=$(LC_ALL=C readelf -h "$src" | awk 'NR==13{e_shoff=$5} NR==18{e_shentsize=$5} NR==19{e_shnum=$5} END{print e_shoff+e_shentsize*e_shnum}') echo "Uncompress $(basename "$src") of type $appimageType @ offset $offset" unsquashfs -q -d "$out" -o "$offset" "$src" chmod go-w "$out" diff --git a/pkgs/build-support/bintools-wrapper/default.nix b/pkgs/build-support/bintools-wrapper/default.nix index 786f0f9c5983..6da0e58436d0 100644 --- a/pkgs/build-support/bintools-wrapper/default.nix +++ b/pkgs/build-support/bintools-wrapper/default.nix @@ -167,7 +167,7 @@ stdenv.mkDerivation { else if targetPlatform.isWindows then "pe" else "elf" + toString targetPlatform.parsed.cpu.bits; endianPrefix = if targetPlatform.isBigEndian then "big" else "little"; - sep = optionalString (!targetPlatform.isMips && !targetPlatform.isPower) "-"; + sep = optionalString (!targetPlatform.isMips && !targetPlatform.isPower && !targetPlatform.isRiscV) "-"; arch = /**/ if targetPlatform.isAarch64 then endianPrefix + "aarch64" else if targetPlatform.isAarch32 then endianPrefix + "arm" @@ -179,12 +179,15 @@ stdenv.mkDerivation { mips64 = "btsmip"; mips64el = "ltsmip"; }.${targetPlatform.parsed.cpu.name} + else if targetPlatform.isMmix then "mmix" else if targetPlatform.isPower then if targetPlatform.isBigEndian then "ppc" else "lppc" else if targetPlatform.isSparc then "sparc" else if targetPlatform.isMsp430 then "msp430" else if targetPlatform.isAvr then "avr" else if targetPlatform.isAlpha then "alpha" else if targetPlatform.isVc4 then "vc4" + else if targetPlatform.isOr1k then "or1k" + else if targetPlatform.isRiscV then "lriscv" else throw "unknown emulation for platform: ${targetPlatform.config}"; in if targetPlatform.useLLVM or false then "" else targetPlatform.platform.bfdEmulation or (fmt + sep + arch); @@ -252,7 +255,7 @@ stdenv.mkDerivation { # Ensure consistent LC_VERSION_MIN_MACOSX and remove LC_UUID. + optionalString stdenv.targetPlatform.isMacOS '' - echo "-macosx_version_min 10.12 -sdk_version 10.12 -no_uuid" >> $out/nix-support/libc-ldflags-before + echo "-sdk_version 10.12 -no_uuid" >> $out/nix-support/libc-ldflags-before '' ## diff --git a/pkgs/build-support/build-fhs-userenv-bubblewrap/default.nix b/pkgs/build-support/build-fhs-userenv-bubblewrap/default.nix index 83d5d371b397..3a3c9e932fdb 100644 --- a/pkgs/build-support/build-fhs-userenv-bubblewrap/default.nix +++ b/pkgs/build-support/build-fhs-userenv-bubblewrap/default.nix @@ -50,7 +50,7 @@ let "ssl/certs" "pki" ]; - in concatStringsSep " \\\n " + in concatStringsSep "\n " (map (file: "--ro-bind-try /etc/${file} /etc/${file}") files); init = run: writeShellScriptBin "${name}-init" '' @@ -59,21 +59,21 @@ let ''; bwrapCmd = { initArgs ? "" }: '' - blacklist="/nix /dev /proc /etc" - ro_mounts="" + blacklist=(/nix /dev /proc /etc) + ro_mounts=() for i in ${env}/*; do path="/''${i##*/}" if [[ $path == '/etc' ]]; then continue fi - ro_mounts="$ro_mounts --ro-bind $i $path" - blacklist="$blacklist $path" + ro_mounts+=(--ro-bind "$i" "$path") + blacklist+=("$path") done if [[ -d ${env}/etc ]]; then for i in ${env}/etc/*; do path="/''${i##*/}" - ro_mounts="$ro_mounts --ro-bind $i /etc$path" + ro_mounts+=(--ro-bind "$i" "/etc$path") done fi @@ -81,24 +81,27 @@ let # loop through all directories in the root for dir in /*; do # if it is a directory and it is not in the blacklist - if [[ -d "$dir" ]] && grep -v "$dir" <<< "$blacklist" >/dev/null; then + if [[ -d "$dir" ]] && [[ ! "''${blacklist[@]}" =~ "$dir" ]]; then # add it to the mount list auto_mounts+=(--bind "$dir" "$dir") fi done - exec ${bubblewrap}/bin/bwrap \ - --dev-bind /dev /dev \ - --proc /proc \ - --chdir "$(pwd)" \ - --unshare-all \ - --share-net \ - --die-with-parent \ - --ro-bind /nix /nix \ - ${etcBindFlags} \ - $ro_mounts \ - "''${auto_mounts[@]}" \ + cmd=( + ${bubblewrap}/bin/bwrap + --dev-bind /dev /dev + --proc /proc + --chdir "$(pwd)" + --unshare-all + --share-net + --die-with-parent + --ro-bind /nix /nix + ${etcBindFlags} + "''${ro_mounts[@]}" + "''${auto_mounts[@]}" ${init runScript}/bin/${name}-init ${initArgs} + ) + exec "''${cmd[@]}" ''; bin = writeShellScriptBin name (bwrapCmd { initArgs = ''"$@"''; }); diff --git a/pkgs/build-support/docker/default.nix b/pkgs/build-support/docker/default.nix index ba76ce2b817d..b30ac5c77655 100644 --- a/pkgs/build-support/docker/default.nix +++ b/pkgs/build-support/docker/default.nix @@ -1,4 +1,5 @@ { + bashInteractive, buildPackages, cacert, callPackage, @@ -15,7 +16,6 @@ moreutils, nix, pigz, - referencesByPopularity, rsync, runCommand, runtimeShell, @@ -25,12 +25,14 @@ storeDir ? builtins.storeDir, substituteAll, symlinkJoin, - utillinux, + util-linux, vmTools, writeReferencesToFile, writeScript, writeText, + writeTextDir, writePython3, + system, # Note: This is the cross system we're compiling for }: # WARNING: this API is unstable and may be subject to backwards-incompatible changes in the future. @@ -48,7 +50,7 @@ let # A user is required by nix # https://github.com/NixOS/nix/blob/9348f9291e5d9e4ba3c4347ea1b235640f54fd79/src/libutil/util.cc#L478 export USER=nobody - ${nix}/bin/nix-store --load-db < ${closureInfo {rootPaths = contentsList;}}/registration + ${buildPackages.nix}/bin/nix-store --load-db < ${closureInfo {rootPaths = contentsList;}}/registration mkdir -p nix/var/nix/gcroots/docker/ for i in ${lib.concatStringsSep " " contentsList}; do @@ -56,11 +58,21 @@ let done; ''; + # Map nixpkgs architecture to Docker notation + # Reference: https://github.com/docker-library/official-images#architectures-other-than-amd64 + getArch = nixSystem: { + aarch64-linux = "arm64v8"; + armv7l-linux = "arm32v7"; + x86_64-linux = "amd64"; + powerpc64le-linux = "ppc64le"; + i686-linux = "i386"; + }.${nixSystem} or "Can't map Nix system ${nixSystem} to Docker architecture notation. Please check that your input and your requested build are correct or update the mapping in Nixpkgs."; + in rec { examples = callPackage ./examples.nix { - inherit buildImage pullImage shadowSetup buildImageWithNixDb; + inherit buildImage buildLayeredImage fakeNss pullImage shadowSetup buildImageWithNixDb; }; pullImage = let @@ -72,7 +84,7 @@ rec { , imageDigest , sha256 , os ? "linux" - , arch ? buildPackages.go.GOARCH + , arch ? getArch system # This is used to set name to the pulled image , finalImageName ? imageName @@ -194,7 +206,7 @@ rec { }; inherit fromImage fromImageName fromImageTag; - nativeBuildInputs = [ utillinux e2fsprogs jshon rsync jq ]; + nativeBuildInputs = [ util-linux e2fsprogs jshon rsync jq ]; } '' mkdir disk mkfs /dev/${vmTools.hd} @@ -443,7 +455,7 @@ rec { runCommand "${name}.tar.gz" { inherit (stream) imageName; passthru = { inherit (stream) imageTag; }; - buildInputs = [ pigz ]; + nativeBuildInputs = [ pigz ]; } "${stream} | pigz -nT > $out"; # 1. extract the base image @@ -488,7 +500,7 @@ rec { baseJson = let pure = writeText "${baseName}-config.json" (builtins.toJSON { inherit created config; - architecture = buildPackages.go.GOARCH; + architecture = getArch system; os = "linux"; }); impure = runCommand "${baseName}-config.json" @@ -674,6 +686,33 @@ rec { in result; + # Provide a /etc/passwd and /etc/group that contain root and nobody. + # Useful when packaging binaries that insist on using nss to look up + # username/groups (like nginx). + # /bin/sh is fine to not exist, and provided by another shim. + fakeNss = symlinkJoin { + name = "fake-nss"; + paths = [ + (writeTextDir "etc/passwd" '' + root:x:0:0:root user:/var/empty:/bin/sh + nobody:x:65534:65534:nobody:/var/empty:/bin/sh + '') + (writeTextDir "etc/group" '' + root:x:0: + nobody:x:65534: + '') + (runCommand "var-empty" {} '' + mkdir -p $out/var/empty + '') + ]; + }; + + # This provides /bin/sh, pointing to bashInteractive. + binSh = runCommand "bin-sh" {} '' + mkdir -p $out/bin + ln -s ${bashInteractive}/bin/bash $out/bin/sh + ''; + # Build an image and populate its nix database with the provided # contents. The main purpose is to be able to use nix commands in # the container. @@ -715,7 +754,7 @@ rec { streamScript = writePython3 "stream" {} ./stream_layered_image.py; baseJson = writeText "${name}-base.json" (builtins.toJSON { inherit config; - architecture = buildPackages.go.GOARCH; + architecture = getArch system; os = "linux"; }); @@ -761,8 +800,8 @@ rec { then tag else lib.head (lib.strings.splitString "-" (baseNameOf conf.outPath)); - paths = referencesByPopularity overallClosure; - buildInputs = [ jq ]; + paths = buildPackages.referencesByPopularity overallClosure; + nativeBuildInputs = [ jq ]; } '' ${if (tag == null) then '' outName="$(basename "$out")" @@ -826,7 +865,7 @@ rec { # take images can know in advance how the image is supposed to be used. isExe = true; }; - buildInputs = [ makeWrapper ]; + nativeBuildInputs = [ makeWrapper ]; } '' makeWrapper ${streamScript} $out --add-flags ${conf} ''; diff --git a/pkgs/build-support/docker/examples.nix b/pkgs/build-support/docker/examples.nix index 4a611add8a12..85ddeb257405 100644 --- a/pkgs/build-support/docker/examples.nix +++ b/pkgs/build-support/docker/examples.nix @@ -7,7 +7,7 @@ # $ nix-build '<nixpkgs>' -A dockerTools.examples.redis # $ docker load < result -{ pkgs, buildImage, pullImage, shadowSetup, buildImageWithNixDb }: +{ pkgs, buildImage, buildLayeredImage, fakeNss, pullImage, shadowSetup, buildImageWithNixDb, pkgsCross }: rec { # 1. basic example @@ -44,7 +44,7 @@ rec { nginx = let nginxPort = "80"; nginxConf = pkgs.writeText "nginx.conf" '' - user nginx nginx; + user nobody nobody; daemon off; error_log /dev/stdout info; pid /dev/null; @@ -64,10 +64,13 @@ rec { <html><body><h1>Hello from NGINX</h1></body></html> ''; in - buildImage { + buildLayeredImage { name = "nginx-container"; tag = "latest"; - contents = pkgs.nginx; + contents = [ + fakeNss + pkgs.nginx + ]; extraCommands = '' # nginx still tries to read this directory even if error_log @@ -75,12 +78,6 @@ rec { mkdir -p var/log/nginx mkdir -p var/cache/nginx ''; - runAsRoot = '' - #!${pkgs.stdenv.shell} - ${shadowSetup} - groupadd --system nginx - useradd --system --gid nginx nginx - ''; config = { Cmd = [ "nginx" "-c" nginxConf ]; @@ -407,4 +404,16 @@ rec { contents = [ pkgs.bash pkgs.coreutils ] ++ nonRootShadowSetup { uid = 999; user = "somebody"; }; }; + # basic example, with cross compilation + cross = let + # Cross compile for x86_64 if on aarch64 + crossPkgs = + if pkgs.system == "aarch64-linux" then pkgsCross.gnu64 + else pkgsCross.aarch64-multiplatform; + in crossPkgs.dockerTools.buildImage { + name = "hello-cross"; + tag = "latest"; + contents = crossPkgs.hello; + }; + } diff --git a/pkgs/build-support/docker/nix-prefetch-docker b/pkgs/build-support/docker/nix-prefetch-docker index 1b6785189c28..5798ab5984f1 100755 --- a/pkgs/build-support/docker/nix-prefetch-docker +++ b/pkgs/build-support/docker/nix-prefetch-docker @@ -127,7 +127,7 @@ trap "rm -rf \"$tmpPath\"" EXIT tmpFile="$tmpPath/$(get_name $finalImageName $finalImageTag)" if test -z "$QUIET"; then - skopeo --insecure-policy --tmpdir=$TMPDIR --override-os ${os} --override-arch ${arch} copy "$sourceUrl" "docker-archive://$tmpFile:$finalImageName:$finalImageTag" + skopeo --insecure-policy --tmpdir=$TMPDIR --override-os ${os} --override-arch ${arch} copy "$sourceUrl" "docker-archive://$tmpFile:$finalImageName:$finalImageTag" >&2 else skopeo --insecure-policy --tmpdir=$TMPDIR --override-os ${os} --override-arch ${arch} copy "$sourceUrl" "docker-archive://$tmpFile:$finalImageName:$finalImageTag" > /dev/null fi @@ -139,12 +139,12 @@ imageHash=$(nix-hash --flat --type $hashType --base32 "$tmpFile") finalPath=$(nix-store --add-fixed "$hashType" "$tmpFile") if test -z "$QUIET"; then - echo "-> ImageName: $imageName" - echo "-> ImageDigest: $imageDigest" - echo "-> FinalImageName: $finalImageName" - echo "-> FinalImageTag: $finalImageTag" - echo "-> ImagePath: $finalPath" - echo "-> ImageHash: $imageHash" + echo "-> ImageName: $imageName" >&2 + echo "-> ImageDigest: $imageDigest" >&2 + echo "-> FinalImageName: $finalImageName" >&2 + echo "-> FinalImageTag: $finalImageTag" >&2 + echo "-> ImagePath: $finalPath" >&2 + echo "-> ImageHash: $imageHash" >&2 fi if [ "$format" == "nix" ]; then diff --git a/pkgs/build-support/fetchfirefoxaddon/default.nix b/pkgs/build-support/fetchfirefoxaddon/default.nix new file mode 100644 index 000000000000..3426743b2cf1 --- /dev/null +++ b/pkgs/build-support/fetchfirefoxaddon/default.nix @@ -0,0 +1,37 @@ +{stdenv, lib, coreutils, unzip, jq, zip, fetchurl,writeScript, ...}: +{ name +, url +, md5 ? "" +, sha1 ? "" +, sha256 ? "" +, sha512 ? "" +}: +stdenv.mkDerivation rec { + + inherit name; + extid = "${src.outputHash}@${name}"; + passthru = { + exitd=extid; + }; + + builder = writeScript "xpibuilder" '' + source $stdenv/setup + + header "firefox addon $name into $out" + + UUID="${extid}" + mkdir -p "$out/$UUID" + unzip -q ${src} -d "$out/$UUID" + NEW_MANIFEST=$(jq '. + {"applications": { "gecko": { "id": "${extid}" }}, "browser_specific_settings":{"gecko":{"id": "${extid}"}}}' "$out/$UUID/manifest.json") + echo "$NEW_MANIFEST" > "$out/$UUID/manifest.json" + cd "$out/$UUID" + zip -r -q -FS "$out/$UUID.xpi" * + rm -r "$out/$UUID" + ''; + src = fetchurl { + url = url; + inherit md5 sha1 sha256 sha512; + }; + nativeBuildInputs = [ coreutils unzip zip jq ]; +} + diff --git a/pkgs/build-support/fetchfossil/default.nix b/pkgs/build-support/fetchfossil/default.nix index 27933b47178a..3a4876bc5de3 100644 --- a/pkgs/build-support/fetchfossil/default.nix +++ b/pkgs/build-support/fetchfossil/default.nix @@ -1,11 +1,11 @@ -{stdenv, fossil}: +{stdenv, fossil, cacert}: {name ? null, url, rev, sha256}: stdenv.mkDerivation { name = "fossil-archive" + (if name != null then "-${name}" else ""); builder = ./builder.sh; - nativeBuildInputs = [fossil]; + nativeBuildInputs = [fossil cacert]; # Envvar docs are hard to find. A link for the future: # https://www.fossil-scm.org/index.html/doc/trunk/www/env-opts.md diff --git a/pkgs/build-support/fetchzip/default.nix b/pkgs/build-support/fetchzip/default.nix index c61df8ceb001..a1744b48deb9 100644 --- a/pkgs/build-support/fetchzip/default.nix +++ b/pkgs/build-support/fetchzip/default.nix @@ -44,8 +44,20 @@ mv "$unpackDir/$fn" "$out" '' else '' mv "$unpackDir" "$out" - '') #*/ - + extraPostFetch; + '') + + extraPostFetch + # Remove write permissions for files unpacked with write bits set + # Fixes https://github.com/NixOS/nixpkgs/issues/38649 + # + # However, we should (for the moment) retain write permission on the directory + # itself, to avoid tickling https://github.com/NixOS/nix/issues/4295 in + # single-user Nix installations. This is because in sandbox mode we'll try to + # move the path, and if we don't have write permissions on the directory, + # then we can't update the ".." entry. + + '' + chmod -R a-w "$out" + chmod u+w "$out" + ''; } // removeAttrs args [ "stripRoot" "extraPostFetch" ])).overrideAttrs (x: { # Hackety-hack: we actually need unzip hooks, too nativeBuildInputs = x.nativeBuildInputs ++ [ unzip ]; diff --git a/pkgs/build-support/make-desktopitem/default.nix b/pkgs/build-support/make-desktopitem/default.nix index 8e51dc1b8480..329286bd3628 100644 --- a/pkgs/build-support/make-desktopitem/default.nix +++ b/pkgs/build-support/make-desktopitem/default.nix @@ -12,16 +12,16 @@ , mimeType ? null , categories ? null , startupNotify ? null -, extraDesktopEntries ? {} # Extra key-value pairs to add to the [Desktop Entry] section. This may override other values +, extraDesktopEntries ? { } # Extra key-value pairs to add to the [Desktop Entry] section. This may override other values , extraEntries ? "" # Extra configuration. Will be appended to the end of the file and may thus contain extra sections , fileValidation ? true # whether to validate resulting desktop file. }: - let # like builtins.toString, but null -> null instead of null -> "" - nullableToString = value: if value == null then null - else if builtins.isBool value then lib.boolToString value - else builtins.toString value; + nullableToString = value: + if value == null then null + else if builtins.isBool value then lib.boolToString value + else builtins.toString value; # The [Desktop entry] section of the desktop file, as attribute set. mainSection = { @@ -39,16 +39,19 @@ let # Map all entries to a list of lines desktopFileStrings = - ["[Desktop Entry]"] + [ "[Desktop Entry]" ] ++ builtins.filter (v: v != null) (lib.mapAttrsToList (name: value: if value != null then "${name}=${value}" else null) mainSection ) - ++ (if extraEntries == "" then [] else ["${extraEntries}"]); + ++ (if extraEntries == "" then [ ] else [ "${extraEntries}" ]); in -runCommandLocal "${name}.desktop" {} +runCommandLocal "${name}.desktop" +{ + nativeBuildInputs = [ desktop-file-utils ]; +} ('' mkdir -p "$out/share/applications" cat > "$out/share/applications/${name}.desktop" <<EOF @@ -56,5 +59,5 @@ runCommandLocal "${name}.desktop" {} EOF '' + lib.optionalString fileValidation '' echo "Running desktop-file validation" - ${desktop-file-utils}/bin/desktop-file-validate "$out/share/applications/${name}.desktop" + desktop-file-validate "$out/share/applications/${name}.desktop" '') diff --git a/pkgs/build-support/rust/build-rust-crate/build-crate.nix b/pkgs/build-support/rust/build-rust-crate/build-crate.nix index 142109cef49f..84d1b2300f14 100644 --- a/pkgs/build-support/rust/build-rust-crate/build-crate.nix +++ b/pkgs/build-support/rust/build-rust-crate/build-crate.nix @@ -15,7 +15,7 @@ ++ [(mkRustcDepArgs dependencies crateRenames)] ++ [(mkRustcFeatureArgs crateFeatures)] ++ extraRustcOpts - ++ lib.optional (stdenv.hostPlatform != stdenv.buildPlatform) "--target ${rust.toRustTarget stdenv.hostPlatform} -C linker=${stdenv.hostPlatform.config}-gcc" + ++ lib.optional (stdenv.hostPlatform != stdenv.buildPlatform) "--target ${rust.toRustTargetSpec stdenv.hostPlatform} -C linker=${stdenv.hostPlatform.config}-gcc" # since rustc 1.42 the "proc_macro" crate is part of the default crate prelude # https://github.com/rust-lang/cargo/commit/4d64eb99a4#diff-7f98585dbf9d30aa100c8318e2c77e79R1021-R1022 ++ lib.optional (lib.elem "proc-macro" crateType) "--extern proc_macro" diff --git a/pkgs/build-support/rust/build-rust-crate/configure-crate.nix b/pkgs/build-support/rust/build-rust-crate/configure-crate.nix index 18587f7047c4..5ada40b3b9bb 100644 --- a/pkgs/build-support/rust/build-rust-crate/configure-crate.nix +++ b/pkgs/build-support/rust/build-rust-crate/configure-crate.nix @@ -135,8 +135,8 @@ in '' export CARGO_MANIFEST_DIR=$(pwd) export DEBUG="${toString (!release)}" export OPT_LEVEL="${toString optLevel}" - export TARGET="${rust.toRustTarget stdenv.hostPlatform}" - export HOST="${rust.toRustTarget stdenv.buildPlatform}" + export TARGET="${rust.toRustTargetSpec stdenv.hostPlatform}" + export HOST="${rust.toRustTargetSpec stdenv.buildPlatform}" export PROFILE=${if release then "release" else "debug"} export OUT_DIR=$(pwd)/target/build/${crateName}.out export CARGO_PKG_VERSION_MAJOR=${lib.elemAt version 0} diff --git a/pkgs/build-support/rust/build-rust-crate/default.nix b/pkgs/build-support/rust/build-rust-crate/default.nix index 9d98e0851780..e605c9550e53 100644 --- a/pkgs/build-support/rust/build-rust-crate/default.nix +++ b/pkgs/build-support/rust/build-rust-crate/default.nix @@ -54,6 +54,10 @@ let }; installCrate = import ./install-crate.nix { inherit stdenv; }; + + # Allow access to the rust attribute set from inside buildRustCrate, which + # has a parameter that shadows the name. + rustAttrs = rust; in /* The overridable pkgs.buildRustCrate function. @@ -250,7 +254,7 @@ stdenv.mkDerivation (rec { depsMetadata = lib.foldl' (str: dep: str + dep.metadata) "" (dependencies ++ buildDependencies); hashedMetadata = builtins.hashString "sha256" (crateName + "-" + crateVersion + "___" + toString (mkRustcFeatureArgs crateFeatures) + - "___" + depsMetadata); + "___" + depsMetadata + "___" + rustAttrs.toRustTarget stdenv.hostPlatform); in lib.substring 0 10 hashedMetadata; build = crate.build or ""; diff --git a/pkgs/build-support/rust/default.nix b/pkgs/build-support/rust/default.nix index f6177ce198da..8e47a2b0bf25 100644 --- a/pkgs/build-support/rust/default.nix +++ b/pkgs/build-support/rust/default.nix @@ -4,6 +4,10 @@ , cargo , diffutils , fetchCargoTarball +, runCommandNoCC +, rustPlatform +, callPackage +, remarshal , git , rust , rustc @@ -26,12 +30,15 @@ , cargoBuildFlags ? [] , buildType ? "release" , meta ? {} -, target ? null +, target ? rust.toRustTargetSpec stdenv.hostPlatform , cargoVendorDir ? null , checkType ? buildType , depsExtraArgs ? {} , cargoParallelTestThreads ? true +# Toggles whether a custom sysroot is created when the target is a .json file. +, __internal_dontAddSysroot ? false + # Needed to `pushd`/`popd` into a subdir of a tarball if this subdir # contains a Cargo.toml, but isn't part of a workspace (which is e.g. the # case for `rustfmt`/etc from the `rust-sources). @@ -69,13 +76,26 @@ let cargoDepsCopy="$sourceRoot/${cargoVendorDir}" ''; - rustTarget = if target == null then rust.toRustTarget stdenv.hostPlatform else target; + targetIsJSON = stdenv.lib.hasSuffix ".json" target; + useSysroot = targetIsJSON && !__internal_dontAddSysroot; + + # see https://github.com/rust-lang/cargo/blob/964a16a28e234a3d397b2a7031d4ab4a428b1391/src/cargo/core/compiler/compile_kind.rs#L151-L168 + # the "${}" is needed to transform the path into a /nix/store path before baseNameOf + shortTarget = if targetIsJSON then + (stdenv.lib.removeSuffix ".json" (builtins.baseNameOf "${target}")) + else target; + + sysroot = (callPackage ./sysroot {}) { + inherit target shortTarget; + RUSTFLAGS = args.RUSTFLAGS or ""; + originalCargoToml = src + /Cargo.toml; # profile info is later extracted + }; ccForBuild="${buildPackages.stdenv.cc}/bin/${buildPackages.stdenv.cc.targetPrefix}cc"; cxxForBuild="${buildPackages.stdenv.cc}/bin/${buildPackages.stdenv.cc.targetPrefix}c++"; ccForHost="${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc"; cxxForHost="${stdenv.cc}/bin/${stdenv.cc.targetPrefix}c++"; - releaseDir = "target/${rustTarget}/${buildType}"; + releaseDir = "target/${shortTarget}/${buildType}"; tmpDir = "${releaseDir}-tmp"; # Specify the stdenv's `diff` by abspath to ensure that the user's build @@ -85,7 +105,13 @@ let in -stdenv.mkDerivation ((removeAttrs args ["depsExtraArgs"]) // { +# Tests don't currently work for `no_std`, and all custom sysroots are currently built without `std`. +# See https://os.phil-opp.com/testing/ for more information. +assert useSysroot -> !(args.doCheck or true); + +stdenv.mkDerivation ((removeAttrs args ["depsExtraArgs"]) // stdenv.lib.optionalAttrs useSysroot { + RUSTFLAGS = "--sysroot ${sysroot} " + (args.RUSTFLAGS or ""); +} // { inherit cargoDeps; patchRegistryDeps = ./patch-registry-deps; @@ -115,7 +141,7 @@ stdenv.mkDerivation ((removeAttrs args ["depsExtraArgs"]) // { [target."${rust.toRustTarget stdenv.buildPlatform}"] "linker" = "${ccForBuild}" ${stdenv.lib.optionalString (stdenv.buildPlatform.config != stdenv.hostPlatform.config) '' - [target."${rustTarget}"] + [target."${shortTarget}"] "linker" = "${ccForHost}" ${# https://github.com/rust-lang/rust/issues/46651#issuecomment-433611633 stdenv.lib.optionalString (stdenv.hostPlatform.isMusl && stdenv.hostPlatform.isAarch64) '' @@ -185,7 +211,7 @@ stdenv.mkDerivation ((removeAttrs args ["depsExtraArgs"]) // { "CXX_${rust.toRustTarget stdenv.hostPlatform}"="${cxxForHost}" \ cargo build -j $NIX_BUILD_CORES \ ${stdenv.lib.optionalString (buildType == "release") "--release"} \ - --target ${rustTarget} \ + --target ${target} \ --frozen ${concatStringsSep " " cargoBuildFlags} ) @@ -205,7 +231,7 @@ stdenv.mkDerivation ((removeAttrs args ["depsExtraArgs"]) // { ''; checkPhase = args.checkPhase or (let - argstr = "${stdenv.lib.optionalString (checkType == "release") "--release"} --target ${rustTarget} --frozen"; + argstr = "${stdenv.lib.optionalString (checkType == "release") "--release"} --target ${target} --frozen"; threads = if cargoParallelTestThreads then "$NIX_BUILD_CORES" else "1"; in '' ${stdenv.lib.optionalString (buildAndTestSubdir != null) "pushd ${buildAndTestSubdir}"} diff --git a/pkgs/build-support/rust/sysroot/Cargo.lock b/pkgs/build-support/rust/sysroot/Cargo.lock new file mode 100644 index 000000000000..61fcef61744e --- /dev/null +++ b/pkgs/build-support/rust/sysroot/Cargo.lock @@ -0,0 +1,29 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "alloc" +version = "0.0.0" +dependencies = [ + "compiler_builtins", + "core", +] + +[[package]] +name = "compiler_builtins" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd0782e0a7da7598164153173e5a5d4d9b1da094473c98dce0ff91406112369" +dependencies = [ + "rustc-std-workspace-core", +] + +[[package]] +name = "core" +version = "0.0.0" + +[[package]] +name = "rustc-std-workspace-core" +version = "1.99.0" +dependencies = [ + "core", +] diff --git a/pkgs/build-support/rust/sysroot/cargo.py b/pkgs/build-support/rust/sysroot/cargo.py new file mode 100644 index 000000000000..09f6fba6d1c8 --- /dev/null +++ b/pkgs/build-support/rust/sysroot/cargo.py @@ -0,0 +1,45 @@ +import os +import toml + +rust_src = os.environ['RUSTC_SRC'] +orig_cargo = os.environ['ORIG_CARGO'] if 'ORIG_CARGO' in os.environ else None + +base = { + 'package': { + 'name': 'alloc', + 'version': '0.0.0', + 'authors': ['The Rust Project Developers'], + 'edition': '2018', + }, + 'dependencies': { + 'compiler_builtins': { + 'version': '0.1.0', + 'features': ['rustc-dep-of-std', 'mem'], + }, + 'core': { + 'path': os.path.join(rust_src, 'libcore'), + }, + }, + 'lib': { + 'name': 'alloc', + 'path': os.path.join(rust_src, 'liballoc/lib.rs'), + }, + 'patch': { + 'crates-io': { + 'rustc-std-workspace-core': { + 'path': os.path.join(rust_src, 'tools/rustc-std-workspace-core'), + }, + }, + }, +} + +if orig_cargo is not None: + with open(orig_cargo, 'r') as f: + src = toml.loads(f.read()) + if 'profile' in src: + base['profile'] = src['profile'] + +out = toml.dumps(base) + +with open('Cargo.toml', 'x') as f: + f.write(out) diff --git a/pkgs/build-support/rust/sysroot/default.nix b/pkgs/build-support/rust/sysroot/default.nix new file mode 100644 index 000000000000..4db7cf0dc392 --- /dev/null +++ b/pkgs/build-support/rust/sysroot/default.nix @@ -0,0 +1,41 @@ +{ stdenv, rust, rustPlatform, buildPackages }: + +{ shortTarget, originalCargoToml, target, RUSTFLAGS }: + +let + cargoSrc = stdenv.mkDerivation { + name = "cargo-src"; + preferLocalBuild = true; + phases = [ "installPhase" ]; + installPhase = '' + RUSTC_SRC=${rustPlatform.rustcSrc.override { minimalContent = false; }} ORIG_CARGO=${originalCargoToml} \ + ${buildPackages.python3.withPackages (ps: with ps; [ toml ])}/bin/python3 ${./cargo.py} + mkdir -p $out + cp Cargo.toml $out/Cargo.toml + cp ${./Cargo.lock} $out/Cargo.lock + ''; + }; +in rustPlatform.buildRustPackage { + inherit target RUSTFLAGS; + + name = "custom-sysroot"; + src = cargoSrc; + + RUSTC_BOOTSTRAP = 1; + __internal_dontAddSysroot = true; + cargoSha256 = "0y6dqfhsgk00y3fv5bnjzk0s7i30nwqc1rp0xlrk83hkh80x81mw"; + + doCheck = false; + + installPhase = '' + export LIBS_DIR=$out/lib/rustlib/${shortTarget}/lib + mkdir -p $LIBS_DIR + for f in target/${shortTarget}/release/deps/*.{rlib,rmeta}; do + cp $f $LIBS_DIR + done + + export RUST_SYSROOT=$(rustc --print=sysroot) + host=${rust.toRustTarget stdenv.buildPlatform} + cp -r $RUST_SYSROOT/lib/rustlib/$host $out + ''; +} diff --git a/pkgs/build-support/rust/sysroot/update-lockfile.sh b/pkgs/build-support/rust/sysroot/update-lockfile.sh new file mode 100755 index 000000000000..83d29832384f --- /dev/null +++ b/pkgs/build-support/rust/sysroot/update-lockfile.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i bash -p python3 python3.pkgs.toml cargo + +set -e + +HERE=$(dirname "${BASH_SOURCE[0]}") +NIXPKGS_ROOT="$HERE/../../../.." + +# https://unix.stackexchange.com/a/84980/390173 +tempdir=$(mktemp -d 2>/dev/null || mktemp -d -t 'update-lockfile') + +cd "$tempdir" +nix-build -E "with import (/. + \"${NIXPKGS_ROOT}\") {}; pkgs.rustPlatform.rustcSrc.override { minimalContent = false; }" +RUSTC_SRC="$(pwd)/result" python3 "$HERE/cargo.py" +RUSTC_BOOTSTRAP=1 cargo build || echo "Build failure is expected. All that's needed is the lockfile." + +cp Cargo.lock "$HERE" + +rm -rf "$tempdir" + + diff --git a/pkgs/build-support/setup-hooks/copy-desktop-items.sh b/pkgs/build-support/setup-hooks/copy-desktop-items.sh new file mode 100644 index 000000000000..f96a10f33d5c --- /dev/null +++ b/pkgs/build-support/setup-hooks/copy-desktop-items.sh @@ -0,0 +1,42 @@ +# shellcheck shell=bash + +# Setup hook that installs specified desktop items. +# +# Example usage in a derivation: +# +# { …, makeDesktopItem, copyDesktopItems, … }: +# +# let desktopItem = makeDesktopItem { … }; in +# stdenv.mkDerivation { +# … +# nativeBuildInputs = [ copyDesktopItems ]; +# +# desktopItems = [ desktopItem ]; +# … +# } +# +# This hook will copy files which are either given by full path +# or all '*.desktop' files placed inside the 'share/applications' +# folder of each `desktopItems` argument. + +postInstallHooks+=(copyDesktopItems) + +copyDesktopItems() { + if [ "${dontCopyDesktopItems-}" = 1 ]; then return; fi + + if [ -z "$desktopItems" ]; then + return + fi + + for desktopItem in $desktopItems; do + if [[ -f "$desktopItem" ]]; then + echo "Copying '$f' into '$out/share/applications'" + install -D -m 444 -t "$out"/share/applications "$f" + else + for f in "$desktopItem"/share/applications/*.desktop; do + echo "Copying '$f' into '$out/share/applications'" + install -D -m 444 -t "$out"/share/applications "$f" + done + fi + done +} diff --git a/pkgs/build-support/setup-hooks/reproducible-builds.sh b/pkgs/build-support/setup-hooks/reproducible-builds.sh new file mode 100644 index 000000000000..2d8db6ff7d3c --- /dev/null +++ b/pkgs/build-support/setup-hooks/reproducible-builds.sh @@ -0,0 +1,4 @@ +# Use the last part of the out path as hash input for the build. +# This should ensure that it is deterministic across rebuilds of the same +# derivation and not easily collide with other builds. +export NIX_CFLAGS_COMPILE+=" -frandom-seed=${out##*/}" diff --git a/pkgs/build-support/singularity-tools/default.nix b/pkgs/build-support/singularity-tools/default.nix index d937ec626682..4a54498d117c 100644 --- a/pkgs/build-support/singularity-tools/default.nix +++ b/pkgs/build-support/singularity-tools/default.nix @@ -7,7 +7,7 @@ , bash , vmTools , gawk -, utillinux +, util-linux , runtimeShell , e2fsprogs }: @@ -47,7 +47,7 @@ rec { runScriptFile = shellScript "run-script.sh" runScript; result = vmTools.runInLinuxVM ( runCommand "singularity-image-${name}.img" { - buildInputs = [ singularity e2fsprogs utillinux gawk ]; + buildInputs = [ singularity e2fsprogs util-linux gawk ]; layerClosure = writeReferencesToFile layer; preVM = vmTools.createEmptyImage { size = diskSize; diff --git a/pkgs/build-support/vm/default.nix b/pkgs/build-support/vm/default.nix index 909cdc6da044..2f18e96e4ce2 100644 --- a/pkgs/build-support/vm/default.nix +++ b/pkgs/build-support/vm/default.nix @@ -151,7 +151,7 @@ rec { # Set the system time from the hardware clock. Works around an # apparent KVM > 1.5.2 bug. - ${pkgs.utillinux}/bin/hwclock -s + ${pkgs.util-linux}/bin/hwclock -s export NIX_STORE=${storeDir} export NIX_BUILD_TOP=/tmp @@ -270,7 +270,7 @@ rec { defaultCreateRootFS = '' mkdir /mnt ${e2fsprogs}/bin/mkfs.ext4 /dev/${hd} - ${utillinux}/bin/mount -t ext4 /dev/${hd} /mnt + ${util-linux}/bin/mount -t ext4 /dev/${hd} /mnt if test -e /mnt/.debug; then exec ${bash}/bin/sh @@ -317,7 +317,7 @@ rec { with pkgs; runInLinuxVM ( stdenv.mkDerivation { name = "extract-file"; - buildInputs = [ utillinux ]; + buildInputs = [ util-linux ]; buildCommand = '' ln -s ${kernel}/lib /lib ${kmod}/bin/modprobe loop @@ -342,7 +342,7 @@ rec { with pkgs; runInLinuxVM ( stdenv.mkDerivation { name = "extract-file-mtd"; - buildInputs = [ utillinux mtdutils ]; + buildInputs = [ util-linux mtdutils ]; buildCommand = '' ln -s ${kernel}/lib /lib ${kmod}/bin/modprobe mtd @@ -417,7 +417,7 @@ rec { # Make the Nix store available in /mnt, because that's where the RPMs live. mkdir -p /mnt${storeDir} - ${utillinux}/bin/mount -o bind ${storeDir} /mnt${storeDir} + ${util-linux}/bin/mount -o bind ${storeDir} /mnt${storeDir} # Newer distributions like Fedora 18 require /lib etc. to be # symlinked to /usr. @@ -427,7 +427,7 @@ rec { ln -s /usr/sbin /mnt/sbin ln -s /usr/lib /mnt/lib ln -s /usr/lib64 /mnt/lib64 - ${utillinux}/bin/mount -t proc none /mnt/proc + ${util-linux}/bin/mount -t proc none /mnt/proc ''} echo "unpacking RPMs..." @@ -445,7 +445,7 @@ rec { PATH=/usr/bin:/bin:/usr/sbin:/sbin $chroot /mnt \ rpm --initdb - ${utillinux}/bin/mount -o bind /tmp /mnt/tmp + ${util-linux}/bin/mount -o bind /tmp /mnt/tmp echo "installing RPMs..." PATH=/usr/bin:/bin:/usr/sbin:/sbin $chroot /mnt \ @@ -456,8 +456,8 @@ rec { rm /mnt/.debug - ${utillinux}/bin/umount /mnt${storeDir} /mnt/tmp ${lib.optionalString unifiedSystemDir "/mnt/proc"} - ${utillinux}/bin/umount /mnt + ${util-linux}/bin/umount /mnt${storeDir} /mnt/tmp ${lib.optionalString unifiedSystemDir "/mnt/proc"} + ${util-linux}/bin/umount /mnt ''; passthru = { inherit fullName; }; @@ -587,9 +587,9 @@ rec { # Make the Nix store available in /mnt, because that's where the .debs live. mkdir -p /mnt/inst${storeDir} - ${utillinux}/bin/mount -o bind ${storeDir} /mnt/inst${storeDir} - ${utillinux}/bin/mount -o bind /proc /mnt/proc - ${utillinux}/bin/mount -o bind /dev /mnt/dev + ${util-linux}/bin/mount -o bind ${storeDir} /mnt/inst${storeDir} + ${util-linux}/bin/mount -o bind /proc /mnt/proc + ${util-linux}/bin/mount -o bind /dev /mnt/dev # Misc. files/directories assumed by various packages. echo "initialising Dpkg DB..." @@ -635,10 +635,10 @@ rec { rm /mnt/.debug - ${utillinux}/bin/umount /mnt/inst${storeDir} - ${utillinux}/bin/umount /mnt/proc - ${utillinux}/bin/umount /mnt/dev - ${utillinux}/bin/umount /mnt + ${util-linux}/bin/umount /mnt/inst${storeDir} + ${util-linux}/bin/umount /mnt/proc + ${util-linux}/bin/umount /mnt/dev + ${util-linux}/bin/umount /mnt ''; passthru = { inherit fullName; }; |