diff options
author | Alyssa Ross <hi@alyssa.is> | 2023-12-15 19:32:38 +0100 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2023-12-15 19:32:38 +0100 |
commit | 6b8e2555ef013b579cda57025b17d662e0f1fe1f (patch) | |
tree | 5a83c673af26c9976acd5a5dfa20e09e06898047 /nixpkgs/pkgs/build-support | |
parent | 66ca7a150b5c051f0728f13134e6265cc46f370c (diff) | |
parent | 02357adddd0889782362d999628de9d309d202dc (diff) | |
download | nixlib-6b8e2555ef013b579cda57025b17d662e0f1fe1f.tar nixlib-6b8e2555ef013b579cda57025b17d662e0f1fe1f.tar.gz nixlib-6b8e2555ef013b579cda57025b17d662e0f1fe1f.tar.bz2 nixlib-6b8e2555ef013b579cda57025b17d662e0f1fe1f.tar.lz nixlib-6b8e2555ef013b579cda57025b17d662e0f1fe1f.tar.xz nixlib-6b8e2555ef013b579cda57025b17d662e0f1fe1f.tar.zst nixlib-6b8e2555ef013b579cda57025b17d662e0f1fe1f.zip |
Merge branch 'nixos-unstable-small' of https://github.com/NixOS/nixpkgs
Diffstat (limited to 'nixpkgs/pkgs/build-support')
27 files changed, 380 insertions, 779 deletions
diff --git a/nixpkgs/pkgs/build-support/appimage/default.nix b/nixpkgs/pkgs/build-support/appimage/default.nix index 7b9bb239402b..078570ec7aea 100644 --- a/nixpkgs/pkgs/build-support/appimage/default.nix +++ b/nixpkgs/pkgs/build-support/appimage/default.nix @@ -173,6 +173,7 @@ rec { libpulseaudio libsamplerate libmikmod + libthai libtheora libtiff pixman diff --git a/nixpkgs/pkgs/build-support/bintools-wrapper/default.nix b/nixpkgs/pkgs/build-support/bintools-wrapper/default.nix index dd6032fc52cf..525b44fe0480 100644 --- a/nixpkgs/pkgs/build-support/bintools-wrapper/default.nix +++ b/nixpkgs/pkgs/build-support/bintools-wrapper/default.nix @@ -316,10 +316,10 @@ stdenv.mkDerivation { '' ### - ### Remove LC_UUID + ### Remove certain timestamps from final binaries ### + optionalString (stdenv.targetPlatform.isDarwin && !(bintools.isGNU or false)) '' - echo "-no_uuid" >> $out/nix-support/libc-ldflags-before + echo "export ZERO_AR_DATE=1" >> $out/nix-support/setup-hook '' + '' diff --git a/nixpkgs/pkgs/build-support/build-fhsenv-bubblewrap/default.nix b/nixpkgs/pkgs/build-support/build-fhsenv-bubblewrap/default.nix index 3500e5e9216f..b6b5f13bba97 100644 --- a/nixpkgs/pkgs/build-support/build-fhsenv-bubblewrap/default.nix +++ b/nixpkgs/pkgs/build-support/build-fhsenv-bubblewrap/default.nix @@ -16,6 +16,7 @@ , extraInstallCommands ? "" , meta ? {} , passthru ? {} +, extraPreBwrapCmds ? "" , extraBwrapArgs ? [] , unshareUser ? false , unshareIpc ? false @@ -23,6 +24,7 @@ , unshareNet ? false , unshareUts ? false , unshareCgroup ? false +, privateTmp ? false , dieWithParent ? true , ... } @ args: @@ -38,8 +40,8 @@ let buildFHSEnv = callPackage ./buildFHSEnv.nix { }; fhsenv = buildFHSEnv (removeAttrs (args // { inherit name; }) [ - "runScript" "extraInstallCommands" "meta" "passthru" "extraBwrapArgs" "dieWithParent" - "unshareUser" "unshareCgroup" "unshareUts" "unshareNet" "unsharePid" "unshareIpc" + "runScript" "extraInstallCommands" "meta" "passthru" "extraPreBwrapCmds" "extraBwrapArgs" "dieWithParent" + "unshareUser" "unshareCgroup" "unshareUts" "unshareNet" "unsharePid" "unshareIpc" "privateTmp" "pname" "version" ]); @@ -116,7 +118,8 @@ let indentLines = str: lib.concatLines (map (s: " " + s) (filter (s: s != "") (lib.splitString "\n" str))); bwrapCmd = { initArgs ? "" }: '' - ignored=(/nix /dev /proc /etc) + ${extraPreBwrapCmds} + ignored=(/nix /dev /proc /etc ${lib.optionalString privateTmp "/tmp"}) ro_mounts=() symlinks=() etc_ignored=() @@ -150,10 +153,8 @@ let if [[ "''${etc_ignored[@]}" =~ "$i" ]]; then continue fi - if [[ -L $i ]]; then - symlinks+=(--symlink "$(${coreutils}/bin/readlink "$i")" "$i") - else - ro_mounts+=(--ro-bind-try "$i" "$i") + if [[ -e $i ]]; then + symlinks+=(--symlink "/.host-etc/''${i#/etc/}" "$i") fi done @@ -192,6 +193,8 @@ let ${lib.optionalString unshareCgroup "--unshare-cgroup"} ${lib.optionalString dieWithParent "--die-with-parent"} --ro-bind /nix /nix + --ro-bind /etc /.host-etc + ${lib.optionalString privateTmp "--tmpfs /tmp"} # Our glibc will look for the cache in its own path in `/nix/store`. # As such, we need a cache to exist there, because pressure-vessel # depends on the existence of an ld cache. However, adding one @@ -200,6 +203,7 @@ let # Also, the cache needs to go to both 32 and 64 bit glibcs, for games # of both architectures to work. --tmpfs ${glibc}/etc \ + --tmpfs /etc \ --symlink /etc/ld.so.conf ${glibc}/etc/ld.so.conf \ --symlink /etc/ld.so.cache ${glibc}/etc/ld.so.cache \ --ro-bind ${glibc}/etc/rpc ${glibc}/etc/rpc \ diff --git a/nixpkgs/pkgs/build-support/build-graalvm-native-image/default.nix b/nixpkgs/pkgs/build-support/build-graalvm-native-image/default.nix index e5fe1abe1d11..0612db2ad79b 100644 --- a/nixpkgs/pkgs/build-support/build-graalvm-native-image/default.nix +++ b/nixpkgs/pkgs/build-support/build-graalvm-native-image/default.nix @@ -49,6 +49,13 @@ stdenv.mkDerivation ({ nativeImageBuildArgs = nativeImageBuildArgs ++ extraNativeImageBuildArgs ++ [ graalvmXmx ]; + # Workaround GraalVM issue where the builder does not have access to the + # environment variables since 21.0.0 + # https://github.com/oracle/graal/pull/6095 + # https://github.com/oracle/graal/pull/6095 + # https://github.com/oracle/graal/issues/7502 + env.NATIVE_IMAGE_DEPRECATED_BUILDER_SANITATION = "true"; + buildPhase = args.buildPhase or '' runHook preBuild diff --git a/nixpkgs/pkgs/build-support/build-setupcfg/default.nix b/nixpkgs/pkgs/build-support/build-setupcfg/default.nix deleted file mode 100644 index 5737989249af..000000000000 --- a/nixpkgs/pkgs/build-support/build-setupcfg/default.nix +++ /dev/null @@ -1,26 +0,0 @@ -# Build a python package from info made available by setupcfg2nix. -# -# * src: The source of the package. -# * info: The package information generated by setupcfg2nix. -# * meta: Standard nixpkgs metadata. -# * application: Whether this package is a python library or an -# application which happens to be written in python. -# * doCheck: Whether to run the test suites. -lib: pythonPackages: -{ src, info, meta ? {}, application ? false, doCheck ? true}: let - build = if application - then pythonPackages.buildPythonApplication - else pythonPackages.buildPythonPackage; -in build { - inherit (info) pname version; - - inherit src meta doCheck; - - nativeBuildInputs = map (p: pythonPackages.${p}) ( - (info.setup_requires or []) ++ - (lib.optionals doCheck (info.tests_require or [])) - ); - - propagatedBuildInputs = map (p: pythonPackages.${p}) - (info.install_requires or []); -} diff --git a/nixpkgs/pkgs/build-support/dotnet/build-dotnet-module/default.nix b/nixpkgs/pkgs/build-support/dotnet/build-dotnet-module/default.nix index f8ed3a38890c..573b270ee408 100644 --- a/nixpkgs/pkgs/build-support/dotnet/build-dotnet-module/default.nix +++ b/nixpkgs/pkgs/build-support/dotnet/build-dotnet-module/default.nix @@ -165,7 +165,7 @@ stdenvNoCC.mkDerivation (args // { components = lib.pipe args.version [ lib.splitVersion (lib.filter (x: (lib.strings.match "[0-9]+" x) != null)) - (lib.filter (x: (lib.toInt x) < 65535)) # one version component in dotnet has to fit in 16 bits + (lib.filter (x: (lib.toIntBase10 x) < 65535)) # one version component in dotnet has to fit in 16 bits ]; in if (lib.length components) == 0 then null diff --git a/nixpkgs/pkgs/build-support/dotnet/make-nuget-source/default.nix b/nixpkgs/pkgs/build-support/dotnet/make-nuget-source/default.nix index a23a143ab246..48de65e8a881 100644 --- a/nixpkgs/pkgs/build-support/dotnet/make-nuget-source/default.nix +++ b/nixpkgs/pkgs/build-support/dotnet/make-nuget-source/default.nix @@ -6,10 +6,9 @@ }: let - nuget-source = stdenvNoCC.mkDerivation rec { + nuget-source = stdenvNoCC.mkDerivation { inherit name; - meta.description = description; nativeBuildInputs = [ python3 ]; buildCommand = '' @@ -18,17 +17,22 @@ let # use -L to follow symbolic links. When `projectReferences` is used in # buildDotnetModule, one of the deps will be a symlink farm. find -L ${lib.concatStringsSep " " deps} -type f -name '*.nupkg' -exec \ - cp --no-clobber '{}' $out/lib ';' + ln -s '{}' -t $out/lib ';' # Generates a list of all licenses' spdx ids, if available. # Note that this currently ignores any license provided in plain text (e.g. "LICENSE.txt") python ${./extract-licenses-from-nupkgs.py} $out/lib > $out/share/licenses ''; + + meta.description = description; } // { # We need data from `$out` for `meta`, so we have to use overrides as to not hit infinite recursion. - meta.licence = let - depLicenses = lib.splitString "\n" (builtins.readFile "${nuget-source}/share/licenses"); - in (lib.flatten (lib.forEach depLicenses (spdx: - lib.optionals (spdx != "") (lib.getLicenseFromSpdxId spdx) - ))); + meta = nuget-source.meta // { + licenses = let + # TODO: avoid IFD + depLicenses = lib.splitString "\n" (builtins.readFile "${nuget-source}/share/licenses"); + in lib.flatten (lib.forEach depLicenses (spdx: + lib.optionals (spdx != "") (lib.getLicenseFromSpdxId spdx) + )); + }; }; in nuget-source diff --git a/nixpkgs/pkgs/build-support/node/build-npm-package/hooks/npm-install-hook.sh b/nixpkgs/pkgs/build-support/node/build-npm-package/hooks/npm-install-hook.sh index a2f77bdc6d43..1e446bb1b051 100644 --- a/nixpkgs/pkgs/build-support/node/build-npm-package/hooks/npm-install-hook.sh +++ b/nixpkgs/pkgs/build-support/node/build-npm-package/hooks/npm-install-hook.sh @@ -5,16 +5,14 @@ npmInstallHook() { runHook preInstall - # `npm pack` writes to cache - npm config delete cache - local -r packageOut="$out/lib/node_modules/$(@jq@ --raw-output '.name' package.json)" + # `npm pack` writes to cache so temporarily override it while IFS= read -r file; do local dest="$packageOut/$(dirname "$file")" mkdir -p "$dest" cp "${npmWorkspace-.}/$file" "$dest" - done < <(@jq@ --raw-output '.[0].files | map(.path) | join("\n")' <<< "$(npm pack --json --dry-run --loglevel=warn --no-foreground-scripts ${npmWorkspace+--workspace=$npmWorkspace} $npmPackFlags "${npmPackFlagsArray[@]}" $npmFlags "${npmFlagsArray[@]}")") + done < <(@jq@ --raw-output '.[0].files | map(.path) | join("\n")' <<< "$(npm_config_cache="$HOME/.npm" npm pack --json --dry-run --loglevel=warn --no-foreground-scripts ${npmWorkspace+--workspace=$npmWorkspace} $npmPackFlags "${npmPackFlagsArray[@]}" $npmFlags "${npmFlagsArray[@]}")") # Based on code from Python's buildPythonPackage wrap.sh script, for # supporting both the case when makeWrapperArgs is an array and a diff --git a/nixpkgs/pkgs/build-support/node/fetch-npm-deps/src/main.rs b/nixpkgs/pkgs/build-support/node/fetch-npm-deps/src/main.rs index 2b28e290ad51..dc20c7297049 100644 --- a/nixpkgs/pkgs/build-support/node/fetch-npm-deps/src/main.rs +++ b/nixpkgs/pkgs/build-support/node/fetch-npm-deps/src/main.rs @@ -246,7 +246,9 @@ fn main() -> anyhow::Result<()> { packages.into_par_iter().try_for_each(|package| { eprintln!("{}", package.name); - let tarball = package.tarball()?; + let tarball = package + .tarball() + .map_err(|e| anyhow!("couldn't fetch {} at {}: {e:?}", package.name, package.url))?; let integrity = package.integrity().map(ToString::to_string); cache diff --git a/nixpkgs/pkgs/build-support/node/fetch-npm-deps/src/parse/lock.rs b/nixpkgs/pkgs/build-support/node/fetch-npm-deps/src/parse/lock.rs index e3580cfca0d3..c6e77153a0b8 100644 --- a/nixpkgs/pkgs/build-support/node/fetch-npm-deps/src/parse/lock.rs +++ b/nixpkgs/pkgs/build-support/node/fetch-npm-deps/src/parse/lock.rs @@ -214,29 +214,35 @@ fn to_new_packages( } if let UrlOrString::Url(v) = &package.version { - for (scheme, host) in [ - ("github", "github.com"), - ("bitbucket", "bitbucket.org"), - ("gitlab", "gitlab.com"), - ] { - if v.scheme() == scheme { - package.version = { - let mut new_url = initial_url.clone(); - - new_url.set_host(Some(host))?; - - if v.path().ends_with(".git") { - new_url.set_path(v.path()); - } else { - new_url.set_path(&format!("{}.git", v.path())); - } - - new_url.set_fragment(v.fragment()); - - UrlOrString::Url(new_url) - }; - - break; + if v.scheme() == "npm" { + if let Some(UrlOrString::Url(ref url)) = &package.resolved { + package.version = UrlOrString::Url(url.clone()); + } + } else { + for (scheme, host) in [ + ("github", "github.com"), + ("bitbucket", "bitbucket.org"), + ("gitlab", "gitlab.com"), + ] { + if v.scheme() == scheme { + package.version = { + let mut new_url = initial_url.clone(); + + new_url.set_host(Some(host))?; + + if v.path().ends_with(".git") { + new_url.set_path(v.path()); + } else { + new_url.set_path(&format!("{}.git", v.path())); + } + + new_url.set_fragment(v.fragment()); + + UrlOrString::Url(new_url) + }; + + break; + } } } } @@ -266,7 +272,8 @@ fn get_initial_url() -> anyhow::Result<Url> { #[cfg(test)] mod tests { use super::{ - get_initial_url, to_new_packages, Hash, HashCollection, OldPackage, Package, UrlOrString, + get_initial_url, packages, to_new_packages, Hash, HashCollection, OldPackage, Package, + UrlOrString, }; use std::{ cmp::Ordering, @@ -328,4 +335,36 @@ mod tests { Some(Hash(String::from("sha512-foo"))) ); } + + #[test] + fn parse_lockfile_correctly() { + let packages = packages( + r#"{ + "name": "node-ddr", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } + } + }"#).unwrap(); + + assert_eq!(packages.len(), 1); + assert_eq!( + packages[0].resolved, + Some(UrlOrString::Url( + Url::parse("https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz") + .unwrap() + )) + ); + } } diff --git a/nixpkgs/pkgs/build-support/php/hooks/composer-install-hook.sh b/nixpkgs/pkgs/build-support/php/hooks/composer-install-hook.sh index 6fe1c4e5f7dd..6e7fb5d7503b 100644 --- a/nixpkgs/pkgs/build-support/php/hooks/composer-install-hook.sh +++ b/nixpkgs/pkgs/build-support/php/hooks/composer-install-hook.sh @@ -155,7 +155,7 @@ composerInstallInstallHook() { cp -r . "$out"/share/php/"${pname}"/ # Create symlinks for the binaries. - jq -r -c 'try .bin[]' composer.json | while read -r bin; do + jq -r -c 'try (.bin[] | select(test(".bat$")? | not) )' composer.json | while read -r bin; do mkdir -p "$out"/share/php/"${pname}" "$out"/bin makeWrapper "$out"/share/php/"${pname}"/"$bin" "$out"/bin/"$(basename "$bin")" done diff --git a/nixpkgs/pkgs/build-support/rust/rustc-wrapper/default.nix b/nixpkgs/pkgs/build-support/rust/rustc-wrapper/default.nix new file mode 100644 index 000000000000..d6034c08af47 --- /dev/null +++ b/nixpkgs/pkgs/build-support/rust/rustc-wrapper/default.nix @@ -0,0 +1,30 @@ +{ lib, runCommand, rustc-unwrapped, sysroot ? null }: + +runCommand "${rustc-unwrapped.pname}-wrapper-${rustc-unwrapped.version}" { + preferLocalBuild = true; + strictDeps = true; + inherit (rustc-unwrapped) outputs; + + env = { + prog = "${rustc-unwrapped}/bin/rustc"; + sysroot = lib.optionalString (sysroot != null) "--sysroot ${sysroot}"; + }; + + passthru = { + inherit (rustc-unwrapped) pname version src llvm llvmPackages; + unwrapped = rustc-unwrapped; + }; + + meta = rustc-unwrapped.meta // { + description = "${rustc-unwrapped.meta.description} (wrapper script)"; + priority = 10; + }; +} '' + mkdir -p $out/bin + ln -s ${rustc-unwrapped}/bin/* $out/bin + rm $out/bin/rustc + substituteAll ${./rustc-wrapper.sh} $out/bin/rustc + chmod +x $out/bin/rustc + ${lib.concatMapStrings (output: "ln -s ${rustc-unwrapped.${output}} \$${output}\n") + (lib.remove "out" rustc-unwrapped.outputs)} +'' diff --git a/nixpkgs/pkgs/build-support/rust/rustc-wrapper/rustc-wrapper.sh b/nixpkgs/pkgs/build-support/rust/rustc-wrapper/rustc-wrapper.sh new file mode 100644 index 000000000000..a62e35b8736f --- /dev/null +++ b/nixpkgs/pkgs/build-support/rust/rustc-wrapper/rustc-wrapper.sh @@ -0,0 +1,16 @@ +#!@shell@ + +extraBefore=(@sysroot@) +extraAfter=($NIX_RUSTFLAGS) + +# Optionally print debug info. +if (( "${NIX_DEBUG:-0}" >= 1 )); then + echo "extra flags before to @prog@:" >&2 + printf " %q\n" "${extraBefore[@]}" >&2 + echo "original flags to @prog@:" >&2 + printf " %q\n" "$@" >&2 + echo "extra flags after to @prog@:" >&2 + printf " %q\n" "${extraAfter[@]}" >&2 +fi + +exec @prog@ "${extraBefore[@]}" "$@" "${extraAfter[@]}" diff --git a/nixpkgs/pkgs/build-support/setup-hooks/auto-patchelf.py b/nixpkgs/pkgs/build-support/setup-hooks/auto-patchelf.py index 261f55854808..4769179167b3 100644 --- a/nixpkgs/pkgs/build-support/setup-hooks/auto-patchelf.py +++ b/nixpkgs/pkgs/build-support/setup-hooks/auto-patchelf.py @@ -336,9 +336,12 @@ def main() -> None: ) parser.add_argument( "--extra-args", - nargs="*", + # Undocumented Python argparse feature: consume all remaining arguments + # as values for this one. This means this argument should always be passed + # last. + nargs="...", type=str, - help="Extra arguments to pass to patchelf" + help="Extra arguments to pass to patchelf. This argument should always come last." ) print("automatically fixing dependencies for ELF files") diff --git a/nixpkgs/pkgs/build-support/setup-hooks/separate-debug-info.sh b/nixpkgs/pkgs/build-support/setup-hooks/separate-debug-info.sh index 3a16ac4fee90..197e8a920b70 100644 --- a/nixpkgs/pkgs/build-support/setup-hooks/separate-debug-info.sh +++ b/nixpkgs/pkgs/build-support/setup-hooks/separate-debug-info.sh @@ -1,7 +1,7 @@ export NIX_SET_BUILD_ID=1 export NIX_LDFLAGS+=" --compress-debug-sections=zlib" export NIX_CFLAGS_COMPILE+=" -ggdb -Wa,--compress-debug-sections" -export RUSTFLAGS+=" -g" +export NIX_RUSTFLAGS+=" -g" fixupOutputHooks+=(_separateDebugInfo) diff --git a/nixpkgs/pkgs/build-support/templaterpm/default.nix b/nixpkgs/pkgs/build-support/templaterpm/default.nix deleted file mode 100644 index 56c543e8a930..000000000000 --- a/nixpkgs/pkgs/build-support/templaterpm/default.nix +++ /dev/null @@ -1,25 +0,0 @@ -{lib, stdenv, makeWrapper, python, toposort, rpm}: - -stdenv.mkDerivation { - pname = "nix-template-rpm"; - version = "0.1"; - - nativeBuildInputs = [ makeWrapper ]; - buildInputs = [ python toposort rpm ]; - - dontUnpack = true; - - installPhase = '' - mkdir -p $out/bin - cp ${./nix-template-rpm.py} $out/bin/nix-template-rpm - wrapProgram $out/bin/nix-template-rpm \ - --set PYTHONPATH "${rpm}/lib/${python.libPrefix}/site-packages":"${toposort}/lib/${python.libPrefix}/site-packages" - ''; - - meta = with lib; { - description = "Create templates of nix expressions from RPM .spec files"; - maintainers = with maintainers; [ ]; - platforms = platforms.unix; - hydraPlatforms = []; - }; -} diff --git a/nixpkgs/pkgs/build-support/templaterpm/nix-template-rpm.py b/nixpkgs/pkgs/build-support/templaterpm/nix-template-rpm.py deleted file mode 100755 index db8c0f2064c2..000000000000 --- a/nixpkgs/pkgs/build-support/templaterpm/nix-template-rpm.py +++ /dev/null @@ -1,518 +0,0 @@ -#!/bin/env python - -import sys -import os -import subprocess -import argparse -import re -import shutil -import rpm -import urlparse -import traceback -import toposort - - - - - -class SPECTemplate(object): - def __init__(self, specFilename, outputDir, inputDir=None, buildRootInclude=None, translateTable=None, repositoryDir=None, allPackagesDir=None, maintainer="MAINTAINER"): - rpm.addMacro("buildroot","$out") - rpm.addMacro("_libdir","lib") - rpm.addMacro("_libexecdir","libexec") - rpm.addMacro("_sbindir","sbin") - rpm.addMacro("_sysconfdir","etc") - rpm.addMacro("_topdir","SPACER_DIR_FOR_REMOVAL") - rpm.addMacro("_sourcedir","SOURCE_DIR_SPACER") - - self.packageGroups = [ "ocaml", "python" ] - - ts = rpm.TransactionSet() - - self.specFilename = specFilename - self.spec = ts.parseSpec(specFilename) - - self.inputDir = inputDir - self.buildRootInclude = buildRootInclude - self.repositoryDir = repositoryDir - self.allPackagesDir = allPackagesDir - self.maintainer = maintainer - - self.translateTable = translateTable - - self.facts = self.getFacts() - self.key = self.getSelfKey() - - tmpDir = os.path.join(outputDir, self.rewriteName(self.spec.sourceHeader['name'])) - if self.translateTable is not None: - self.relOutputDir = self.translateTable.path(self.key,tmpDir) - else: - self.relOutputDir = tmpDir - - self.final_output_dir = os.path.normpath( self.relOutputDir ) - - if self.repositoryDir is not None: - self.potential_repository_dir = os.path.normpath( os.path.join(self.repositoryDir,self.relOutputDir) ) - - - - def rewriteCommands(self, string): - string = string.replace('SPACER_DIR_FOR_REMOVAL/','') - string = string.replace('SPACER_DIR_FOR_REMOVAL','') - string = '\n'.join(map(lambda line: ' '.join(map(lambda x: x.replace('SOURCE_DIR_SPACER/',('${./' if (self.buildRootInclude is None) else '${buildRoot}/usr/share/buildroot/SOURCES/'))+('}' if (self.buildRootInclude is None) else '') if x.startswith('SOURCE_DIR_SPACER/') else x, line.split(' '))), string.split('\n'))) - string = string.replace('\n','\n ') - string = string.rstrip() - return string - - - def rewriteName(self, string): - parts = string.split('-') - parts = filter(lambda x: not x == "devel", parts) - parts = filter(lambda x: not x == "doc", parts) - if len(parts) > 1 and parts[0] in self.packageGroups: - return parts[0] + '-' + ''.join(parts[1:2] + map(lambda x: x.capitalize(), parts[2:])) - else: - return ''.join(parts[:1] + map(lambda x: x.capitalize(), parts[1:])) - - - def rewriteInputs(self,target,inputs): - camelcase = lambda l: l[:1] + map(lambda x: x.capitalize(), l[1:]) - filterDevel = lambda l: filter(lambda x: not x == "devel", l) - filterDoc = lambda l: filter(lambda x: not x == "doc", l) - rewrite = lambda l: ''.join(camelcase(filterDoc(filterDevel(l)))) - - def filterPackageGroup(target): - if target is None: - return [ rewrite(x.split('-')) for x in inputs if (not x.split('-')[0] in self.packageGroups) or (len(x.split('-')) == 1) ] - elif target in self.packageGroups: - return [ target + '_' + rewrite(x.split('-')[1:]) for x in inputs if (x.split('-')[0] == target) and (len(x.split('-')) > 1)] - else: - raise Exception("Unknown target") - return [] - - if target is None: - packages = filterPackageGroup(None) - packages.sort() - elif target in self.packageGroups: - packages = filterPackageGroup(target) - packages.sort() - elif target == "ALL": - packages = [] - for t in [None] + self.packageGroups: - tmp = filterPackageGroup(t) - tmp.sort() - packages += tmp - else: - raise Exception("Unknown target") - packages = [] - - return packages - - - def getBuildInputs(self,target=None): - inputs = self.rewriteInputs(target,self.spec.sourceHeader['requires']) - if self.translateTable is not None: - return map(lambda x: self.translateTable.name(x), inputs) - else: - return inputs - - def getSelfKey(self): - name = self.spec.sourceHeader['name'] - if len(name.split('-')) > 1 and name.split('-')[0] in self.packageGroups: - key = self.rewriteInputs(name.split('-')[0], [self.spec.sourceHeader['name']])[0] - else: - key = self.rewriteInputs(None, [self.spec.sourceHeader['name']])[0] - return key - - def getSelf(self): - if self.translateTable is not None: - return self.translateTable.name(self.key) - else: - return self.key - - - - - def copyPatches(self, input_dir, output_dir): - patches = [source for (source, _, flag) in self.spec.sources if flag==2] - for filename in patches: - shutil.copyfile(os.path.join(input_dir, filename), os.path.join(output_dir, filename)) - - - def copySources(self, input_dir, output_dir): - filenames = [source for (source, _, flag) in self.spec.sources if flag==1 if not urlparse.urlparse(source).scheme in ["http", "https"] ] - for filename in filenames: - shutil.copyfile(os.path.join(input_dir, filename), os.path.join(output_dir, filename)) - - - def getFacts(self): - facts = {} - facts["name"] = self.rewriteName(self.spec.sourceHeader['name']) - facts["version"] = self.spec.sourceHeader['version'] - - facts["url"] = [] - facts["sha256"] = [] - sources = [source for (source, _, flag) in self.spec.sources if flag==1 if urlparse.urlparse(source).scheme in ["http", "https"] ] - for url in sources: - p = subprocess.Popen(['nix-prefetch-url', url], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - output, err = p.communicate() - sha256 = output[:-1] #remove new line - facts["url"].append(url) - facts["sha256"].append(sha256) - - patches = [source for (source, _, flag) in self.spec.sources if flag==2] - if self.buildRootInclude is None: - facts["patches"] = map(lambda x: './'+x, patches) - else: - facts["patches"] = map(lambda x: '"${buildRoot}/usr/share/buildroot/SOURCES/'+x+'"', reversed(patches)) - - return facts - - - @property - def name(self): - out = ' name = "' + self.facts["name"] + '-' + self.facts["version"] + '";\n' - out += ' version = "' + self.facts['version'] + '";\n' - return out - - - @property - def src(self): - sources = [source for (source, _, flag) in self.spec.sources if flag==1 if urlparse.urlparse(source).scheme in ["http", "https"] ] - out = '' - for (url,sha256) in zip(self.facts['url'],self.facts['sha256']): - out += ' src = fetchurl {\n' - out += ' url = "' + url + '";\n' - out += ' sha256 = "' + sha256 + '";\n' - out += ' };\n' - return out - - - @property - def patch(self): - out = ' patches = [ ' + ' '.join(self.facts['patches']) + ' ];\n' - return out - - - @property - def buildInputs(self): - out = ' buildInputs = [ ' - out += ' '.join(self.getBuildInputs("ALL")) - out += ' ];\n' - return out - - - @property - def configure(self): - out = ' configurePhase = \'\'\n ' + self.rewriteCommands(self.spec.prep) + '\n \'\';\n'; - return out - - - @property - def build(self): - out = ' buildPhase = \'\'\n ' + self.rewriteCommands(self.spec.build) + '\n \'\';\n'; - return out - - - @property - def install(self): - out = ' installPhase = \'\'\n ' + self.rewriteCommands(self.spec.install) + '\n \'\';\n'; - return out - - @property - def ocamlExtra(self): - if "ocaml" in self.getBuildInputs("ALL"): - return ' createFindlibDestdir = true;\n' - else: - return '' - - - @property - def meta(self): - out = ' meta = with lib; {\n' - out += ' homepage = ' + self.spec.sourceHeader['url'] + ';\n' - out += ' description = "' + self.spec.sourceHeader['summary'] + '";\n' - out += ' license = lib.licenses.' + self.spec.sourceHeader['license'] + ';\n' - out += ' platforms = [ "i686-linux" "x86_64-linux" ];\n' - out += ' maintainers = with lib.maintainers; [ ' + self.maintainer + ' ];\n' - out += ' };\n' - out += '}\n' - return out - - - def __str__(self): - head = '{lib, stdenv, fetchurl, ' + ', '.join(self.getBuildInputs("ALL")) + '}:\n\n' - head += 'stdenv.mkDerivation {\n' - body = [ self.name, self.src, self.patch, self.buildInputs, self.configure, self.build, self.ocamlExtra, self.install, self.meta ] - return head + '\n'.join(body) - - - def getTemplate(self): - head = '{lib, stdenv, buildRoot, fetchurl, ' + ', '.join(self.getBuildInputs("ALL")) + '}:\n\n' - head += 'let\n' - head += ' buildRootInput = (import "${buildRoot}/usr/share/buildroot/buildRootInput.nix") { fetchurl=fetchurl; buildRoot=buildRoot; };\n' - head += 'in\n\n' - head += 'stdenv.mkDerivation {\n' - head += ' inherit (buildRootInput.'+self.rewriteName(self.spec.sourceHeader['name'])+') name version src;\n' - head += ' patches = buildRootInput.'+self.rewriteName(self.spec.sourceHeader['name'])+'.patches ++ [];\n\n' - body = [ self.buildInputs, self.configure, self.build, self.ocamlExtra, self.install, self.meta ] - return head + '\n'.join(body) - - - def getInclude(self): - head = self.rewriteName(self.spec.sourceHeader['name']) + ' = {\n' - body = [ self.name, self.src, self.patch ] - return head + '\n'.join(body) + '};\n' - - - def __cmp__(self,other): - if self.getSelf() in other.getBuildInputs("ALL"): - return 1 - else: - return -1 - - - def callPackage(self): - callPackage = ' ' + self.getSelf() + ' = callPackage ' + os.path.relpath(self.final_output_dir, self.allPackagesDir) + ' {' - newline = False; - for target in self.packageGroups: - tmp = self.getBuildInputs(target) - if len(tmp) > 0: - newline = True; - callPackage += '\n ' + 'inherit (' + target + 'Packages) ' + ' '.join(tmp) + ';' - if newline: - callPackage += '\n };' - else: - callPackage += ' };' - return callPackage - - - - def generateCombined(self): - if not os.path.exists(self.final_output_dir): - os.makedirs(self.final_output_dir) - - if self.inputDir is not None: - self.copySources(self.inputDir, self.final_output_dir) - self.copyPatches(self.inputDir, self.final_output_dir) - - nixfile = open(os.path.join(self.final_output_dir,'default.nix'), 'w') - nixfile.write(str(self)) - nixfile.close() - - shutil.copyfile(self.specFilename, os.path.join(self.final_output_dir, os.path.basename(self.specFilename))) - - - - def generateSplit(self): - if not os.path.exists(self.final_output_dir): - os.makedirs(self.final_output_dir) - - nixfile = open(os.path.join(self.final_output_dir,'default.nix'), 'w') - nixfile.write(self.getTemplate()) - nixfile.close() - - return self.getInclude() - - - - - - -class NixTemplate(object): - def __init__(self, nixfile): - self.nixfile = nixfile - self.original = { "name":None, "version":None, "url":None, "sha256":None, "patches":None } - self.update = { "name":None, "version":None, "url":None, "sha256":None, "patches":None } - self.matchedLines = {} - - if os.path.isfile(nixfile): - with file(nixfile, 'r') as infile: - for (n,line) in enumerate(infile): - name = re.match(r'^\s*name\s*=\s*"(.*?)"\s*;\s*$', line) - version = re.match(r'^\s*version\s*=\s*"(.*?)"\s*;\s*$', line) - url = re.match(r'^\s*url\s*=\s*"?(.*?)"?\s*;\s*$', line) - sha256 = re.match(r'^\s*sha256\s*=\s*"(.*?)"\s*;\s*$', line) - patches = re.match(r'^\s*patches\s*=\s*(\[.*?\])\s*;\s*$', line) - if name is not None and self.original["name"] is None: - self.original["name"] = name.group(1) - self.matchedLines[n] = "name" - if version is not None and self.original["version"] is None: - self.original["version"] = version.group(1) - self.matchedLines[n] = "version" - if url is not None and self.original["url"] is None: - self.original["url"] = url.group(1) - self.matchedLines[n] = "url" - if sha256 is not None and self.original["sha256"] is None: - self.original["sha256"] = sha256.group(1) - self.matchedLines[n] = "sha256" - if patches is not None and self.original["patches"] is None: - self.original["patches"] = patches.group(1) - self.matchedLines[n] = "patches" - - - def generateUpdated(self, nixOut): - nixTemplateFile = open(os.path.normpath(self.nixfile),'r') - nixOutFile = open(os.path.normpath(nixOut),'w') - for (n,line) in enumerate(nixTemplateFile): - if self.matchedLines.has_key(n) and self.update[self.matchedLines[n]] is not None: - nixOutFile.write(line.replace(self.original[self.matchedLines[n]], self.update[self.matchedLines[n]], 1)) - else: - nixOutFile.write(line) - nixTemplateFile.close() - nixOutFile.close() - - - def loadUpdate(self,orig): - if orig.has_key("name") and orig.has_key("version"): - self.update["name"] = orig["name"] + '-' + orig["version"] - self.update["version"] = orig["version"] - if orig.has_key("url") and orig.has_key("sha256") and len(orig["url"])>0: - self.update["url"] = orig["url"][0] - self.update["sha256"] = orig["sha256"][0] - for url in orig["url"][1:-1]: - sys.stderr.write("WARNING: URL has been dropped: %s\n" % url) - if orig.has_key("patches"): - self.update["patches"] = '[ ' + ' '.join(orig['patches']) + ' ]' - - -class TranslationTable(object): - def __init__(self): - self.tablePath = {} - self.tableName = {} - - def update(self, key, path, name=None): - self.tablePath[key] = path - if name is not None: - self.tableName[key] = name - - def readTable(self, tableFile): - with file(tableFile, 'r') as infile: - for line in infile: - match = re.match(r'^(.+?)\s+(.+?)\s+(.+?)\s*$', line) - if match is not None: - if not self.tablePath.has_key(match.group(1)): - self.tablePath[match.group(1)] = match.group(2) - if not self.tableName.has_key(match.group(1)): - self.tableName[match.group(1)] = match.group(3) - else: - match = re.match(r'^(.+?)\s+(.+?)\s*$', line) - if not self.tablePath.has_key(match.group(1)): - self.tablePath[match.group(1)] = match.group(2) - - def writeTable(self, tableFile): - outFile = open(os.path.normpath(tableFile),'w') - keys = self.tablePath.keys() - keys.sort() - for k in keys: - if self.tableName.has_key(k): - outFile.write( k + " " + self.tablePath[k] + " " + self.tableName[k] + "\n" ) - else: - outFile.write( k + " " + self.tablePath[k] + "\n" ) - outFile.close() - - def name(self, key): - if self.tableName.has_key(key): - return self.tableName[key] - else: - return key - - def path(self, key, orig): - if self.tablePath.has_key(key): - return self.tablePath[key] - else: - return orig - - - - - -if __name__ == "__main__": - #Parse command line options - parser = argparse.ArgumentParser(description="Generate .nix templates from RPM spec files") - parser.add_argument("specs", metavar="SPEC", nargs="+", help="spec file") - parser.add_argument("-o", "--output", metavar="OUT_DIR", required=True, help="output directory") - parser.add_argument("-b", "--buildRoot", metavar="BUILDROOT_DIR", default=None, help="buildroot output directory") - parser.add_argument("-i", "--inputSources", metavar="IN_DIR", default=None, help="sources input directory") - parser.add_argument("-m", "--maintainer", metavar="MAINTAINER", default="__NIX_MAINTAINER__", help="package maintainer") - parser.add_argument("-r", "--repository", metavar="REP_DIR", default=None, help="nix repository to compare output against") - parser.add_argument("-t", "--translate", metavar="TRANSLATE_TABLE", default=None, help="path of translation table for name and path") - parser.add_argument("-u", "--translateOut", metavar="TRANSLATE_OUT", default=None, help="output path for updated translation table") - parser.add_argument("-a", "--allPackages", metavar="ALL_PACKAGES", default=None, help="top level dir to call packages from") - args = parser.parse_args() - - allPackagesDir = os.path.normpath( os.path.dirname(args.allPackages) ) - if not os.path.exists(allPackagesDir): - os.makedirs(allPackagesDir) - - buildRootContent = {} - nameMap = {} - - newTable = TranslationTable() - if args.translate is not None: - table = TranslationTable() - table.readTable(args.translate) - newTable.readTable(args.translate) - else: - table = None - - for specPath in args.specs: - try: - sys.stderr.write("INFO: generate nix file from: %s\n" % specPath) - - spec = SPECTemplate(specPath, args.output, args.inputSources, args.buildRoot, table, args.repository, allPackagesDir, args.maintainer) - if args.repository is not None: - if os.path.exists(os.path.join(spec.potential_repository_dir,'default.nix')): - nixTemplate = NixTemplate(os.path.join(spec.potential_repository_dir,'default.nix')) - nixTemplate.loadUpdate(spec.facts) - if not os.path.exists(spec.final_output_dir): - os.makedirs(spec.final_output_dir) - nixTemplate.generateUpdated(os.path.join(spec.final_output_dir,'default.nix')) - else: - sys.stderr.write("WARNING: Repository does not contain template: %s\n" % os.path.join(spec.potential_repository_dir,'default.nix')) - if args.buildRoot is None: - spec.generateCombined() - else: - buildRootContent[spec.key] = spec.generateSplit() - else: - if args.buildRoot is None: - spec.generateCombined() - else: - buildRootContent[spec.key] = spec.generateSplit() - - newTable.update(spec.key,spec.relOutputDir,spec.getSelf()) - nameMap[spec.getSelf()] = spec - - except Exception, e: - sys.stderr.write("ERROR: %s failed with:\n%s\n%s\n" % (specPath,e.message,traceback.format_exc())) - - if args.translateOut is not None: - if not os.path.exists(os.path.dirname(os.path.normpath(args.translateOut))): - os.makedirs(os.path.dirname(os.path.normpath(args.translateOut))) - newTable.writeTable(args.translateOut) - - graph = {} - for k, v in nameMap.items(): - graph[k] = set(v.getBuildInputs("ALL")) - - sortedSpecs = toposort.toposort_flatten(graph) - sortedSpecs = filter( lambda x: x in nameMap.keys(), sortedSpecs) - - allPackagesFile = open(os.path.normpath( args.allPackages ), 'w') - allPackagesFile.write( '\n\n'.join(map(lambda x: x.callPackage(), map(lambda x: nameMap[x], sortedSpecs))) ) - allPackagesFile.close() - - if args.buildRoot is not None: - buildRootFilename = os.path.normpath( args.buildRoot ) - if not os.path.exists(os.path.dirname(buildRootFilename)): - os.makedirs(os.path.dirname(buildRootFilename)) - buildRootFile = open(buildRootFilename, 'w') - buildRootFile.write( "{ fetchurl, buildRoot }: {\n\n" ) - keys = buildRootContent.keys() - keys.sort() - for k in keys: - buildRootFile.write( buildRootContent[k] + '\n' ) - buildRootFile.write( "}\n" ) - buildRootFile.close() - - diff --git a/nixpkgs/pkgs/build-support/trivial-builders/test/default.nix b/nixpkgs/pkgs/build-support/trivial-builders/test/default.nix index cbd1b388ef66..59dbba3f1841 100644 --- a/nixpkgs/pkgs/build-support/trivial-builders/test/default.nix +++ b/nixpkgs/pkgs/build-support/trivial-builders/test/default.nix @@ -14,21 +14,24 @@ { callPackage, lib, stdenv }: let inherit (lib) recurseIntoAttrs; + references = callPackage ./references {}; in recurseIntoAttrs { concat = callPackage ./concat-test.nix {}; linkFarm = callPackage ./link-farm.nix {}; overriding = callPackage ../test-overriding.nix {}; + # VM test not supported beyond linux yet references = - # VM test not supported beyond linux yet if stdenv.hostPlatform.isLinux - then callPackage ./references.nix {} - else null; + then references + else {}; writeCBin = callPackage ./writeCBin.nix {}; writeShellApplication = callPackage ./writeShellApplication.nix {}; writeScriptBin = callPackage ./writeScriptBin.nix {}; writeShellScript = callPackage ./write-shell-script.nix {}; writeShellScriptBin = callPackage ./writeShellScriptBin.nix {}; - writeStringReferencesToFile = callPackage ./writeStringReferencesToFile.nix {}; + writeStringReferencesToFile = callPackage ./writeStringReferencesToFile.nix { + inherit (references) samples; + }; writeTextFile = callPackage ./write-text-file.nix {}; } diff --git a/nixpkgs/pkgs/build-support/trivial-builders/test/invoke-writeDirectReferencesToFile.nix b/nixpkgs/pkgs/build-support/trivial-builders/test/invoke-writeDirectReferencesToFile.nix deleted file mode 100644 index ead3f7a2f571..000000000000 --- a/nixpkgs/pkgs/build-support/trivial-builders/test/invoke-writeDirectReferencesToFile.nix +++ /dev/null @@ -1,4 +0,0 @@ -{ pkgs ? import ../../../.. { config = {}; overlays = []; } }: -pkgs.lib.mapAttrs - (k: v: pkgs.writeDirectReferencesToFile v) - (import ./sample.nix { inherit pkgs; }) diff --git a/nixpkgs/pkgs/build-support/trivial-builders/test/invoke-writeReferencesToFile.nix b/nixpkgs/pkgs/build-support/trivial-builders/test/invoke-writeReferencesToFile.nix deleted file mode 100644 index 99c6c2f7dcc4..000000000000 --- a/nixpkgs/pkgs/build-support/trivial-builders/test/invoke-writeReferencesToFile.nix +++ /dev/null @@ -1,4 +0,0 @@ -{ pkgs ? import ../../../.. { config = {}; overlays = []; } }: -pkgs.lib.mapAttrs - (k: v: pkgs.writeReferencesToFile v) - (import ./sample.nix { inherit pkgs; }) diff --git a/nixpkgs/pkgs/build-support/trivial-builders/test/references-test.sh b/nixpkgs/pkgs/build-support/trivial-builders/test/references-test.sh deleted file mode 100755 index 473ca6e10769..000000000000 --- a/nixpkgs/pkgs/build-support/trivial-builders/test/references-test.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env bash - -# -------------------------------------------------------------------------- # -# -# trivial-builders test -# -# -------------------------------------------------------------------------- # -# -# This file can be run independently (quick): -# -# $ pkgs/build-support/trivial-builders/references-test.sh -# -# or in the build sandbox with a ~20s VM overhead -# -# $ nix-build -A tests.trivial-builders.references -# -# -------------------------------------------------------------------------- # - -# strict bash -set -euo pipefail - -# debug -# set -x -# PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }' - -cd "$(dirname ${BASH_SOURCE[0]})" # nixpkgs root - -if [[ -z ${SAMPLE:-} ]]; then - echo "Running the script directly is currently not supported." - echo "If you need to iterate, remove the raw path, which is not returned by nix-build." - exit 1 -# sample=( `nix-build --no-out-link sample.nix` ) -# directRefs=( `nix-build --no-out-link invoke-writeDirectReferencesToFile.nix` ) -# references=( `nix-build --no-out-link invoke-writeReferencesToFile.nix` ) -# echo "sample: ${#sample[@]}" -# echo "direct: ${#directRefs[@]}" -# echo "indirect: ${#references[@]}" -else - # Injected by Nix (to avoid evaluating in a derivation) - # turn them into arrays - sample=($SAMPLE) - directRefs=($DIRECT_REFS) - references=($REFERENCES) -fi - -echo >&2 Testing direct references... -for i in "${!sample[@]}"; do - echo >&2 Checking '#'$i ${sample[$i]} ${directRefs[$i]} - diff -U3 \ - <(sort <${directRefs[$i]}) \ - <(nix-store -q --references ${sample[$i]} | sort) -done - -echo >&2 Testing closure... -for i in "${!sample[@]}"; do - echo >&2 Checking '#'$i ${sample[$i]} ${references[$i]} - diff -U3 \ - <(sort <${references[$i]}) \ - <(nix-store -q --requisites ${sample[$i]} | sort) -done - -echo 'OK!' diff --git a/nixpkgs/pkgs/build-support/trivial-builders/test/references.nix b/nixpkgs/pkgs/build-support/trivial-builders/test/references.nix deleted file mode 100644 index 7c8ea83f3c8b..000000000000 --- a/nixpkgs/pkgs/build-support/trivial-builders/test/references.nix +++ /dev/null @@ -1,52 +0,0 @@ -{ lib, testers, pkgs, writeText, hello, figlet, stdenvNoCC }: - -# -------------------------------------------------------------------------- # -# -# trivial-builders test -# -# -------------------------------------------------------------------------- # -# -# This file can be run independently (quick): -# -# $ pkgs/build-support/trivial-builders/references-test.sh -# -# or in the build sandbox with a ~20s VM overhead -# -# $ nix-build -A tests.trivial-builders.references -# -# -------------------------------------------------------------------------- # - -let - invokeSamples = file: - lib.concatStringsSep " " ( - lib.attrValues (import file { inherit pkgs; }) - ); -in -testers.nixosTest { - name = "nixpkgs-trivial-builders"; - nodes.machine = { ... }: { - virtualisation.writableStore = true; - - # Test runs without network, so we don't substitute and prepare our deps - nix.settings.substituters = lib.mkForce []; - environment.etc."pre-built-paths".source = writeText "pre-built-paths" ( - builtins.toJSON [hello figlet stdenvNoCC] - ); - environment.variables = { - SAMPLE = invokeSamples ./sample.nix; - REFERENCES = invokeSamples ./invoke-writeReferencesToFile.nix; - DIRECT_REFS = invokeSamples ./invoke-writeDirectReferencesToFile.nix; - }; - }; - testScript = - '' - machine.succeed(""" - ${./references-test.sh} 2>/dev/console - """) - ''; - meta = { - maintainers = with lib.maintainers; [ - roberth - ]; - }; -} diff --git a/nixpkgs/pkgs/build-support/trivial-builders/test/references/default.nix b/nixpkgs/pkgs/build-support/trivial-builders/test/references/default.nix new file mode 100644 index 000000000000..3e21c905321e --- /dev/null +++ b/nixpkgs/pkgs/build-support/trivial-builders/test/references/default.nix @@ -0,0 +1,124 @@ +{ lib +, stdenvNoCC +, testers +, callPackage +, writeText + # nativeBuildInputs +, shellcheck-minimal + # Samples +, samples ? cleanSamples (callPackage ./samples.nix { }) + # Filter out the non-string-like attributes such as <pkg>.override added by + # callPackage. +, cleanSamples ? lib.filterAttrs (n: lib.isStringLike) + # Test targets +, writeDirectReferencesToFile +, writeReferencesToFile +}: + +# -------------------------------------------------------------------------- # +# +# trivial-builders test +# +# -------------------------------------------------------------------------- # +# +# Execute this build script directly (quick): +# +# * Classic +# $ NIX_PATH="nixpkgs=$PWD" nix-shell -p tests.trivial-builders.references.testScriptBin --run references-test +# +# * Flake-based +# $ nix run .#tests.trivial-builders.references.testScriptBin +# +# or in the build sandbox with a ~20s VM overhead: +# +# * Classic +# $ nix-build --no-out-link -A tests.trivial-builders.references +# +# * Flake-based +# $ nix build -L --no-link .#tests.trivial-builders.references +# +# -------------------------------------------------------------------------- # + +let + # Map each attribute to an element specification of Bash associative arrary + # and concatenate them with white spaces, to be used to define a + # one-line Bash associative array. + samplesToString = attrs: + lib.concatMapStringsSep " " (name: "[${name}]=${lib.escapeShellArg "${attrs.${name}}"}") (builtins.attrNames attrs); + + references = lib.mapAttrs (n: v: writeReferencesToFile v) samples; + directReferences = lib.mapAttrs (n: v: writeDirectReferencesToFile v) samples; + + testScriptBin = stdenvNoCC.mkDerivation (finalAttrs: { + name = "references-test"; + + src = ./references-test.sh; + dontUnpack = true; + dontBuild = true; + + installPhase = '' + runHook preInstall + mkdir -p "$out/bin" + substitute "$src" "$out/bin/${finalAttrs.meta.mainProgram}" \ + --replace "@SAMPLES@" ${lib.escapeShellArg (samplesToString samples)} \ + --replace "@REFERENCES@" ${lib.escapeShellArg (samplesToString references)} \ + --replace "@DIRECT_REFS@" ${lib.escapeShellArg (samplesToString directReferences)} + runHook postInstall + chmod +x "$out/bin/${finalAttrs.meta.mainProgram}" + ''; + + doInstallCheck = true; + nativeInstallCheckInputs = [ + shellcheck-minimal + ]; + installCheckPhase = '' + runHook preInstallCheck + shellcheck "$out/bin/${finalAttrs.meta.mainProgram}" + runHook postInstallCheck + ''; + + passthru = { + inherit + directReferences + references + samples + ; + }; + + meta = with lib; { + mainProgram = "references-test"; + }; + }); +in +testers.nixosTest { + name = "nixpkgs-trivial-builders"; + nodes.machine = { ... }: { + virtualisation.writableStore = true; + + # Test runs without network, so we don't substitute and prepare our deps + nix.settings.substituters = lib.mkForce [ ]; + environment.etc."pre-built-paths".source = writeText "pre-built-paths" ( + builtins.toJSON [ testScriptBin ] + ); + }; + testScript = + '' + machine.succeed(""" + ${lib.getExe testScriptBin} 2>/dev/console + """) + ''; + passthru = { + inherit + directReferences + references + samples + testScriptBin + ; + }; + meta = { + maintainers = with lib.maintainers; [ + roberth + ShamrockLee + ]; + }; +} diff --git a/nixpkgs/pkgs/build-support/trivial-builders/test/references/references-test.sh b/nixpkgs/pkgs/build-support/trivial-builders/test/references/references-test.sh new file mode 100755 index 000000000000..1b8f8e1504ec --- /dev/null +++ b/nixpkgs/pkgs/build-support/trivial-builders/test/references/references-test.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +# -------------------------------------------------------------------------- # +# +# trivial-builders test +# +# -------------------------------------------------------------------------- # +# +# Execute this build script directly (quick): +# +# * Classic +# $ NIX_PATH="nixpkgs=$PWD" nix-shell -p tests.trivial-builders.references.testScriptBin --run references-test +# +# * Flake-based +# $ nix run .#tests.trivial-builders.references.testScriptBin +# +# or in the build sandbox with a ~20s VM overhead: +# +# * Classic +# $ nix-build --no-out-link -A tests.trivial-builders.references +# +# * Flake-based +# $ nix build -L --no-link .#tests.trivial-builders.references +# +# -------------------------------------------------------------------------- # + +# strict bash +set -euo pipefail + +# debug +# set -x +# PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }' + +cd "$(dirname "${BASH_SOURCE[0]}")" # nixpkgs root + + # Injected by Nix (to avoid evaluating in a derivation) + # turn them into arrays + # shellcheck disable=SC2206 # deliberately unquoted + declare -A samples=( @SAMPLES@ ) + # shellcheck disable=SC2206 # deliberately unquoted + declare -A directRefs=( @DIRECT_REFS@ ) + # shellcheck disable=SC2206 # deliberately unquoted + declare -A references=( @REFERENCES@ ) + +echo >&2 Testing direct references... +for i in "${!samples[@]}"; do + echo >&2 Checking "$i" "${samples[$i]}" "${directRefs[$i]}" + diff -U3 \ + <(sort <"${directRefs[$i]}") \ + <(nix-store -q --references "${samples[$i]}" | sort) +done + +echo >&2 Testing closure... +for i in "${!samples[@]}"; do + echo >&2 Checking "$i" "${samples[$i]}" "${references[$i]}" + diff -U3 \ + <(sort <"${references[$i]}") \ + <(nix-store -q --requisites "${samples[$i]}" | sort) +done + +echo 'OK!' diff --git a/nixpkgs/pkgs/build-support/trivial-builders/test/references/samples.nix b/nixpkgs/pkgs/build-support/trivial-builders/test/references/samples.nix new file mode 100644 index 000000000000..3afb970c08ae --- /dev/null +++ b/nixpkgs/pkgs/build-support/trivial-builders/test/references/samples.nix @@ -0,0 +1,30 @@ +{ lib +, runCommand +, writeText +, emptyFile +, emptyDirectory +, figlet +, hello +, zlib +}: +{ + inherit + figlet + hello + zlib + ; + zlib-dev = zlib.dev; + norefs = writeText "hi" "hello"; + norefsDup = writeText "hi" "hello"; + helloRef = writeText "hi" "hello ${hello}"; + helloRefDup = writeText "hi" "hello ${hello}"; + path = ./samples.nix; + pathLike.outPath = ./samples.nix; + helloFigletRef = writeText "hi" "hello ${hello} ${figlet}"; + selfRef = runCommand "self-ref-1" { } "echo $out >$out"; + selfRef2 = runCommand "self-ref-2" { } ''echo "${figlet}, $out" >$out''; + inherit + emptyFile + emptyDirectory + ; +} diff --git a/nixpkgs/pkgs/build-support/trivial-builders/test/sample.nix b/nixpkgs/pkgs/build-support/trivial-builders/test/sample.nix deleted file mode 100644 index a4eedce8417e..000000000000 --- a/nixpkgs/pkgs/build-support/trivial-builders/test/sample.nix +++ /dev/null @@ -1,29 +0,0 @@ -{ pkgs ? import ../../../.. { config = { }; overlays = [ ]; } }: -let - inherit (pkgs) - figlet - zlib - hello - writeText - runCommand - ; -in -{ - hello = hello; - figlet = figlet; - zlib = zlib; - zlib-dev = zlib.dev; - norefs = writeText "hi" "hello"; - norefsDup = writeText "hi" "hello"; - helloRef = writeText "hi" "hello ${hello}"; - helloRefDup = writeText "hi" "hello ${hello}"; - path = ./invoke-writeReferencesToFile.nix; - pathLike.outPath = ./invoke-writeReferencesToFile.nix; - helloFigletRef = writeText "hi" "hello ${hello} ${figlet}"; - selfRef = runCommand "self-ref-1" {} "echo $out >$out"; - selfRef2 = runCommand "self-ref-2" {} ''echo "${figlet}, $out" >$out''; - inherit (pkgs) - emptyFile - emptyDirectory - ; -} diff --git a/nixpkgs/pkgs/build-support/trivial-builders/test/writeStringReferencesToFile.nix b/nixpkgs/pkgs/build-support/trivial-builders/test/writeStringReferencesToFile.nix index b93b43b74aa4..dedd7e183a17 100644 --- a/nixpkgs/pkgs/build-support/trivial-builders/test/writeStringReferencesToFile.nix +++ b/nixpkgs/pkgs/build-support/trivial-builders/test/writeStringReferencesToFile.nix @@ -1,14 +1,13 @@ -{ callPackage, lib, pkgs, runCommand, writeText, writeStringReferencesToFile }: +{ callPackage, lib, pkgs, runCommand, samples, writeText, writeStringReferencesToFile }: let - sample = import ./sample.nix { inherit pkgs; }; - samplePaths = lib.unique (lib.attrValues sample); + samplePaths = lib.unique (lib.attrValues samples); stri = x: "${x}"; sampleText = writeText "sample-text" (lib.concatStringsSep "\n" (lib.unique (map stri samplePaths))); stringReferencesText = writeStringReferencesToFile ((lib.concatMapStringsSep "fillertext" stri - (lib.attrValues sample)) + '' + (lib.attrValues samples)) + '' STORE=${builtins.storeDir};\nsystemctl start bar-foo.service ''); in |