diff options
author | Katharina Fey <kookie@spacekookie.de> | 2020-01-12 01:00:12 +0000 |
---|---|---|
committer | Katharina Fey <kookie@spacekookie.de> | 2020-01-12 01:00:12 +0000 |
commit | eeaf5d25d5f6ae7ae1f5bf8a3dee4559693f8147 (patch) | |
tree | afc41ca8dde96b41089ca324533084aef570322f /nixpkgs/pkgs/build-support | |
parent | 63c4c4dda49dc69e5812faa7ef8406180998f3ae (diff) | |
parent | e4134747f5666bcab8680aff67fa3b63384f9a0f (diff) |
Merge commit 'e4134747f5666bcab8680aff67fa3b63384f9a0f'
Diffstat (limited to 'nixpkgs/pkgs/build-support')
26 files changed, 649 insertions, 335 deletions
diff --git a/nixpkgs/pkgs/build-support/agda/default.nix b/nixpkgs/pkgs/build-support/agda/default.nix index 16fe748c3e5..0d054eaa546 100644 --- a/nixpkgs/pkgs/build-support/agda/default.nix +++ b/nixpkgs/pkgs/build-support/agda/default.nix @@ -1,6 +1,4 @@ # Builder for Agda packages. Mostly inspired by the cabal builder. -# -# Contact: stdenv.lib.maintainers.fuuzetsu { stdenv, Agda, glibcLocales , writeShellScriptBin @@ -49,9 +47,9 @@ let includeDirs = self.buildDependsAgdaShareAgda ++ self.sourceDirectories ++ self.topSourceDirectories ++ [ "." ]; - buildFlags = concatStringsSep " " (map (x: "-i " + x) self.includeDirs); + buildFlags = stdenv.lib.concatMap (x: ["-i" x]) self.includeDirs; - agdaWithArgs = "${Agda}/bin/agda ${self.buildFlags}"; + agdaWithArgs = "${Agda}/bin/agda ${toString self.buildFlags}"; buildPhase = '' runHook preBuild diff --git a/nixpkgs/pkgs/build-support/bintools-wrapper/default.nix b/nixpkgs/pkgs/build-support/bintools-wrapper/default.nix index 0abce22c676..84020505a63 100644 --- a/nixpkgs/pkgs/build-support/bintools-wrapper/default.nix +++ b/nixpkgs/pkgs/build-support/bintools-wrapper/default.nix @@ -66,16 +66,16 @@ let else null; expand-response-params = - if buildPackages.stdenv.cc or null != null && buildPackages.stdenv.cc != "/dev/null" + if buildPackages ? stdenv && buildPackages.stdenv.hasCC && buildPackages.stdenv.cc != "/dev/null" then import ../expand-response-params { inherit (buildPackages) stdenv; } else ""; in stdenv.mkDerivation { - name = targetPrefix - + (if name != "" then name else "${bintoolsName}-wrapper") - + (stdenv.lib.optionalString (bintools != null && bintoolsVersion != "") "-${bintoolsVersion}"); + pname = targetPrefix + + (if name != "" then name else "${bintoolsName}-wrapper"); + version = if bintools == null then null else bintoolsVersion; preferLocalBuild = true; diff --git a/nixpkgs/pkgs/build-support/cc-wrapper/default.nix b/nixpkgs/pkgs/build-support/cc-wrapper/default.nix index d02f47fde8c..b078bf2fbbd 100644 --- a/nixpkgs/pkgs/build-support/cc-wrapper/default.nix +++ b/nixpkgs/pkgs/build-support/cc-wrapper/default.nix @@ -59,7 +59,7 @@ let infixSalt = replaceStrings ["-" "."] ["_" "_"] targetPlatform.config; expand-response-params = - if buildPackages.stdenv.cc or null != null && buildPackages.stdenv.cc != "/dev/null" + if buildPackages.stdenv.hasCC && buildPackages.stdenv.cc != "/dev/null" then import ../expand-response-params { inherit (buildPackages) stdenv; } else ""; @@ -93,9 +93,9 @@ assert nativeLibc == bintools.nativeLibc; assert nativePrefix == bintools.nativePrefix; stdenv.mkDerivation { - name = targetPrefix - + (if name != "" then name else "${ccName}-wrapper") - + (stdenv.lib.optionalString (cc != null && ccVersion != "") "-${ccVersion}"); + pname = targetPrefix + + (if name != "" then name else "${ccName}-wrapper"); + version = if cc == null then null else ccVersion; preferLocalBuild = true; @@ -132,6 +132,8 @@ stdenv.mkDerivation { src=$PWD ''; + wrapper = ./cc-wrapper.sh; + installPhase = '' mkdir -p $out/bin $out/nix-support @@ -171,42 +173,42 @@ stdenv.mkDerivation { export default_cxx_stdlib_compile="${default_cxx_stdlib_compile}" if [ -e $ccPath/${targetPrefix}gcc ]; then - wrap ${targetPrefix}gcc ${./cc-wrapper.sh} $ccPath/${targetPrefix}gcc + wrap ${targetPrefix}gcc $wrapper $ccPath/${targetPrefix}gcc ln -s ${targetPrefix}gcc $out/bin/${targetPrefix}cc export named_cc=${targetPrefix}gcc export named_cxx=${targetPrefix}g++ elif [ -e $ccPath/clang ]; then - wrap ${targetPrefix}clang ${./cc-wrapper.sh} $ccPath/clang + wrap ${targetPrefix}clang $wrapper $ccPath/clang ln -s ${targetPrefix}clang $out/bin/${targetPrefix}cc export named_cc=${targetPrefix}clang export named_cxx=${targetPrefix}clang++ fi if [ -e $ccPath/${targetPrefix}g++ ]; then - wrap ${targetPrefix}g++ ${./cc-wrapper.sh} $ccPath/${targetPrefix}g++ + wrap ${targetPrefix}g++ $wrapper $ccPath/${targetPrefix}g++ ln -s ${targetPrefix}g++ $out/bin/${targetPrefix}c++ elif [ -e $ccPath/clang++ ]; then - wrap ${targetPrefix}clang++ ${./cc-wrapper.sh} $ccPath/clang++ + wrap ${targetPrefix}clang++ $wrapper $ccPath/clang++ ln -s ${targetPrefix}clang++ $out/bin/${targetPrefix}c++ fi if [ -e $ccPath/cpp ]; then - wrap ${targetPrefix}cpp ${./cc-wrapper.sh} $ccPath/cpp + wrap ${targetPrefix}cpp $wrapper $ccPath/cpp fi '' + optionalString cc.langFortran or false '' - wrap ${targetPrefix}gfortran ${./cc-wrapper.sh} $ccPath/${targetPrefix}gfortran + wrap ${targetPrefix}gfortran $wrapper $ccPath/${targetPrefix}gfortran ln -sv ${targetPrefix}gfortran $out/bin/${targetPrefix}g77 ln -sv ${targetPrefix}gfortran $out/bin/${targetPrefix}f77 '' + optionalString cc.langJava or false '' - wrap ${targetPrefix}gcj ${./cc-wrapper.sh} $ccPath/${targetPrefix}gcj + wrap ${targetPrefix}gcj $wrapper $ccPath/${targetPrefix}gcj '' + optionalString cc.langGo or false '' - wrap ${targetPrefix}gccgo ${./cc-wrapper.sh} $ccPath/${targetPrefix}gccgo + wrap ${targetPrefix}gccgo $wrapper $ccPath/${targetPrefix}gccgo ''; strictDeps = true; @@ -235,7 +237,7 @@ stdenv.mkDerivation { fi '' - + optionalString (libc != null) '' + + optionalString (libc != null) ('' ## ## General libc support ## @@ -251,11 +253,17 @@ stdenv.mkDerivation { # compile, because it uses "#include_next <limits.h>" to find the # limits.h file in ../includes-fixed. To remedy the problem, # another -idirafter is necessary to add that directory again. - echo "-B${libc_lib}${libc.libdir or "/lib/"} -idirafter ${libc_dev}${libc.incdir or "/include"} ${optionalString isGNU "-idirafter ${cc}/lib/gcc/*/*/include-fixed"}" > $out/nix-support/libc-cflags + echo "-B${libc_lib}${libc.libdir or "/lib/"}" >> $out/nix-support/libc-cflags + echo "-idirafter ${libc_dev}${libc.incdir or "/include"}" >> $out/nix-support/libc-cflags + '' + optionalString isGNU '' + for dir in "${cc}"/lib/gcc/*/*/include-fixed; do + echo '-idirafter' ''${dir} >> $out/nix-support/libc-cflags + done + '' + '' echo "${libc_lib}" > $out/nix-support/orig-libc echo "${libc_dev}" > $out/nix-support/orig-libc-dev - '' + '') + optionalString (!nativeTools) '' ## diff --git a/nixpkgs/pkgs/build-support/docker/default.nix b/nixpkgs/pkgs/build-support/docker/default.nix index 37b25232b96..e10ff269950 100644 --- a/nixpkgs/pkgs/build-support/docker/default.nix +++ b/nixpkgs/pkgs/build-support/docker/default.nix @@ -287,10 +287,16 @@ rec { # unless there are more paths than $maxLayers. In that case, create # $maxLayers-1 for the most popular layers, and smush the remainaing # store paths in to one final layer. + # + # NOTE: the `closures` parameter is a list of closures to include. + # The TOP LEVEL store paths themselves will never be present in the + # resulting image. At this time (2019-12-16) none of these layers + # are appropriate to include, as they are all created as + # implementation details of dockerTools. mkManyPureLayers = { name, # Files to add to the layer. - closure, + closures, configJson, # Docker has a 125-layer maximum, we pick 100 to ensure there is # plenty of room for extension. @@ -303,10 +309,12 @@ rec { isExecutable = true; src = ./store-path-to-layer.sh; }; + + overallClosure = writeText "closure" (lib.concatStringsSep " " closures); in runCommand "${name}-granular-docker-layers" { inherit maxLayers; - paths = referencesByPopularity closure; + paths = referencesByPopularity overallClosure; nativeBuildInputs = [ jshon rsync tarsum ]; enableParallelBuilding = true; } @@ -317,15 +325,20 @@ rec { | jshon -d config \ | jshon -s "1970-01-01T00:00:01Z" -i created > generic.json + # WARNING! # The following code is fiddly w.r.t. ensuring every layer is # created, and that no paths are missed. If you change the # following head and tail call lines, double-check that your # code behaves properly when the number of layers equals: # maxLayers-1, maxLayers, and maxLayers+1 - head -n $((maxLayers - 1)) $paths | cat -n | xargs -P$NIX_BUILD_CORES -n2 ${storePathToLayer} - if [ $(cat $paths | wc -l) -ge $maxLayers ]; then - tail -n+$maxLayers $paths | xargs ${storePathToLayer} $maxLayers + paths() { + cat $paths ${lib.concatMapStringsSep " " (path: "| grep -v ${path}") (closures ++ [ overallClosure ])} + } + + paths | head -n $((maxLayers - 1)) | cat -n | xargs -P$NIX_BUILD_CORES -n2 ${storePathToLayer} + if [ $(paths | wc -l) -ge $maxLayers ]; then + paths | tail -n+$maxLayers | xargs ${storePathToLayer} $maxLayers fi echo "Finished building layer '$name'" @@ -528,15 +541,18 @@ rec { created ? "1970-01-01T00:00:01Z", # Optional bash script to run on the files prior to fixturizing the layer. extraCommands ? "", uid ? 0, gid ? 0, - # Docker's lowest maximum layer limit is 42-layers for an old - # version of the AUFS graph driver. We pick 24 to ensure there is - # plenty of room for extension. I believe the actual maximum is - # 128. - maxLayers ? 24 + # We pick 100 to ensure there is plenty of room for extension. I + # believe the actual maximum is 128. + maxLayers ? 100 }: let baseName = baseNameOf name; - contentsEnv = symlinkJoin { name = "bulk-layers"; paths = (if builtins.isList contents then contents else [ contents ]); }; + contentsEnv = symlinkJoin { + name = "bulk-layers"; + paths = if builtins.isList contents + then contents + else [ contents ]; + }; configJson = let pure = writeText "${baseName}-config.json" (builtins.toJSON { @@ -553,7 +569,7 @@ rec { bulkLayers = mkManyPureLayers { name = baseName; - closure = writeText "closure" "${contentsEnv} ${configJson}"; + closures = [ contentsEnv configJson ]; # One layer will be taken up by the customisationLayer, so # take up one less. maxLayers = maxLayers - 1; @@ -845,6 +861,9 @@ rec { echo " be better to only have one layer that contains a nix store." export NIX_REMOTE=local?root=$PWD + # 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 mkdir -p nix/var/nix/gcroots/docker/ diff --git a/nixpkgs/pkgs/build-support/docker/examples.nix b/nixpkgs/pkgs/build-support/docker/examples.nix index 29eea33a7e1..d7d1a693310 100644 --- a/nixpkgs/pkgs/build-support/docker/examples.nix +++ b/nixpkgs/pkgs/build-support/docker/examples.nix @@ -117,7 +117,12 @@ rec { pkgs.nix ]; config = { - Env = [ "NIX_PAGER=cat" ]; + Env = [ + "NIX_PAGER=cat" + # A user is required by nix + # https://github.com/NixOS/nix/blob/9348f9291e5d9e4ba3c4347ea1b235640f54fd79/src/libutil/util.cc#L478 + "USER=nobody" + ]; }; }; @@ -231,7 +236,6 @@ rec { name = "another-layered-image"; tag = "latest"; config.Cmd = [ "${pkgs.hello}/bin/hello" ]; - contents = [ pkgs.hello ]; }; } diff --git a/nixpkgs/pkgs/build-support/fetchgitiles/default.nix b/nixpkgs/pkgs/build-support/fetchgitiles/default.nix new file mode 100644 index 00000000000..827680992d6 --- /dev/null +++ b/nixpkgs/pkgs/build-support/fetchgitiles/default.nix @@ -0,0 +1,10 @@ +{ fetchzip, lib }: + +{ url, rev, name ? "source", ... } @ args: + +fetchzip ({ + inherit name; + url = "${url}/+archive/${rev}.tar.gz"; + stripRoot = false; + meta.homepage = url; +} // removeAttrs args [ "url" "rev" ]) // { inherit rev; } diff --git a/nixpkgs/pkgs/build-support/fetchgitlab/default.nix b/nixpkgs/pkgs/build-support/fetchgitlab/default.nix index be110cf8393..6c4d52a0533 100644 --- a/nixpkgs/pkgs/build-support/fetchgitlab/default.nix +++ b/nixpkgs/pkgs/build-support/fetchgitlab/default.nix @@ -3,8 +3,19 @@ # gitlab example { owner, repo, rev, domain ? "gitlab.com", name ? "source", group ? null , ... # For hash agility -}@args: fetchzip ({ +} @ args: + +with lib; + +let + slug = concatStringsSep "/" + ((optional (group != null) group) ++ [ owner repo ]); + + escapedSlug = replaceStrings ["." "/"] ["%2E" "%2F"] slug; +in + +fetchzip ({ inherit name; - url = "https://${domain}/api/v4/projects/${lib.optionalString (group != null) "${lib.replaceStrings ["."] ["%2E"] group}%2F"}${lib.replaceStrings ["."] ["%2E"] owner}%2F${lib.replaceStrings ["."] ["%2E"] repo}/repository/archive.tar.gz?sha=${rev}"; - meta.homepage = "https://${domain}/${lib.optionalString (group != null) "${group}/"}${owner}/${repo}/"; + url = "https://${domain}/api/v4/projects/${escapedSlug}/repository/archive.tar.gz?sha=${rev}"; + meta.homepage = "https://${domain}/${slug}/"; } // removeAttrs args [ "domain" "owner" "group" "repo" "rev" ]) // { inherit rev; } diff --git a/nixpkgs/pkgs/build-support/kernel/modules-closure.sh b/nixpkgs/pkgs/build-support/kernel/modules-closure.sh index 5658094872c..220f3b00a77 100644 --- a/nixpkgs/pkgs/build-support/kernel/modules-closure.sh +++ b/nixpkgs/pkgs/build-support/kernel/modules-closure.sh @@ -56,4 +56,12 @@ for module in $closure; do done done +# copy module ordering hints for depmod +cp $kernel/lib/modules/"$version"/modules.order $out/lib/modules/"$version"/. +cp $kernel/lib/modules/"$version"/modules.builtin $out/lib/modules/"$version"/. + depmod -b $out -a $version + +# remove original hints from final derivation +rm $out/lib/modules/"$version"/modules.order +rm $out/lib/modules/"$version"/modules.builtin diff --git a/nixpkgs/pkgs/build-support/libredirect/libredirect.c b/nixpkgs/pkgs/build-support/libredirect/libredirect.c index 8e8da00b02a..d31b7551e94 100644 --- a/nixpkgs/pkgs/build-support/libredirect/libredirect.c +++ b/nixpkgs/pkgs/build-support/libredirect/libredirect.c @@ -59,6 +59,11 @@ static const char * rewrite(const char * path, char * buf) return path; } +static int open_needs_mode(int flags) +{ + return (flags & O_CREAT) || (flags & O_TMPFILE) == O_TMPFILE; +} + /* The following set of Glibc library functions is very incomplete - it contains only what we needed for programs in Nixpkgs. Just add more functions as needed. */ @@ -67,7 +72,7 @@ int open(const char * path, int flags, ...) { int (*open_real) (const char *, int, mode_t) = dlsym(RTLD_NEXT, "open"); mode_t mode = 0; - if (flags & O_CREAT) { + if (open_needs_mode(flags)) { va_list ap; va_start(ap, flags); mode = va_arg(ap, mode_t); @@ -81,7 +86,7 @@ int open64(const char * path, int flags, ...) { int (*open64_real) (const char *, int, mode_t) = dlsym(RTLD_NEXT, "open64"); mode_t mode = 0; - if (flags & O_CREAT) { + if (open_needs_mode(flags)) { va_list ap; va_start(ap, flags); mode = va_arg(ap, mode_t); @@ -95,7 +100,7 @@ int openat(int dirfd, const char * path, int flags, ...) { int (*openat_real) (int, const char *, int, mode_t) = dlsym(RTLD_NEXT, "openat"); mode_t mode = 0; - if (flags & O_CREAT) { + if (open_needs_mode(flags)) { va_list ap; va_start(ap, flags); mode = va_arg(ap, mode_t); @@ -140,9 +145,9 @@ int stat(const char * path, struct stat * st) return __stat_real(rewrite(path, buf), st); } -int * access(const char * path, int mode) +int access(const char * path, int mode) { - int * (*access_real) (const char *, int mode) = dlsym(RTLD_NEXT, "access"); + int (*access_real) (const char *, int mode) = dlsym(RTLD_NEXT, "access"); char buf[PATH_MAX]; return access_real(rewrite(path, buf), mode); } diff --git a/nixpkgs/pkgs/build-support/make-desktopitem/default.nix b/nixpkgs/pkgs/build-support/make-desktopitem/default.nix index f8c31ed5c1d..67b82fd66db 100644 --- a/nixpkgs/pkgs/build-support/make-desktopitem/default.nix +++ b/nixpkgs/pkgs/build-support/make-desktopitem/default.nix @@ -1,4 +1,4 @@ -{stdenv, lib}: +{ lib, runCommandLocal }: { name , type ? "Application" , exec @@ -13,24 +13,20 @@ , extraEntries ? null }: -stdenv.mkDerivation { - name = "${name}.desktop"; +let + optionalEntriesList = [{k="Icon"; v=icon;} + {k="Comment"; v=comment;} + {k="GenericName"; v=genericName;} + {k="MimeType"; v=mimeType;} + {k="StartupNotify"; v=startupNotify;}]; - buildCommand = let + valueNotNull = {k, v}: v != null; + entriesToKeep = builtins.filter valueNotNull optionalEntriesList; - optionalEntriesList = [{k="Icon"; v=icon;} - {k="Comment"; v=comment;} - {k="GenericName"; v=genericName;} - {k="MimeType"; v=mimeType;} - {k="StartupNotify"; v=startupNotify;}]; - - valueNotNull = {k, v}: v != null; - entriesToKeep = builtins.filter valueNotNull optionalEntriesList; - - mkEntry = {k, v}: k + "=" + v; - optionalEntriesString = lib.concatMapStringsSep "\n" mkEntry entriesToKeep; - - in + mkEntry = {k, v}: k + "=" + v; + optionalEntriesString = lib.concatMapStringsSep "\n" mkEntry entriesToKeep; +in +runCommandLocal "${name}.desktop" {} '' mkdir -p $out/share/applications cat > $out/share/applications/${name}.desktop <<EOF @@ -44,5 +40,4 @@ stdenv.mkDerivation { ${if extraEntries == null then ''EOF'' else '' ${extraEntries} EOF''} - ''; -} + '' diff --git a/nixpkgs/pkgs/build-support/rust/build-rust-crate/build-crate.nix b/nixpkgs/pkgs/build-support/rust/build-rust-crate/build-crate.nix index db187d2ac14..4e2e2af1aa7 100644 --- a/nixpkgs/pkgs/build-support/rust/build-rust-crate/build-crate.nix +++ b/nixpkgs/pkgs/build-support/rust/build-rust-crate/build-crate.nix @@ -1,158 +1,109 @@ -{ lib, stdenv, echo_build_heading, noisily, makeDeps, rust }: +{ lib, stdenv, echo_build_heading, noisily, mkRustcDepArgs, rust }: { crateName, dependencies, crateFeatures, crateRenames, libName, release, libPath, crateType, metadata, crateBin, hasCrateBin, - extraRustcOpts, verbose, colors }: + extraRustcOpts, verbose, colors, + buildTests +}: let - - deps = makeDeps dependencies crateRenames; - rustcOpts = - lib.lists.foldl' (opts: opt: opts + " " + opt) - (if release then "-C opt-level=3" else "-C debuginfo=2") - (["-C codegen-units=$NIX_BUILD_CORES"] ++ extraRustcOpts); + baseRustcOpts = + [(if release then "-C opt-level=3" else "-C debuginfo=2")] + ++ ["-C codegen-units=$NIX_BUILD_CORES"] + ++ [(mkRustcDepArgs dependencies crateRenames)] + ++ [crateFeatures] + ++ extraRustcOpts + ++ lib.optional (stdenv.hostPlatform != stdenv.buildPlatform) "--target ${rust.toRustTarget stdenv.hostPlatform} -C linker=${stdenv.hostPlatform.config}-gcc" + ; rustcMeta = "-C metadata=${metadata} -C extra-filename=-${metadata}"; + + + # build the final rustc arguments that can be different between different + # crates + libRustcOpts = lib.concatStringsSep " " ( + baseRustcOpts + ++ [rustcMeta] + ++ (map (x: "--crate-type ${x}") crateType) + ); + + binRustcOpts = lib.concatStringsSep " " ( + baseRustcOpts + ); + + build_bin = if buildTests then "build_bin_test" else "build_bin"; in '' runHook preBuild - norm="" - bold="" - green="" - boldgreen="" - if [[ "${colors}" == "always" ]]; then - norm="$(printf '\033[0m')" #returns to "normal" - bold="$(printf '\033[0;1m')" #set bold - green="$(printf '\033[0;32m')" #set green - boldgreen="$(printf '\033[0;1;32m')" #set bold, and set green. - fi ${echo_build_heading colors} ${noisily colors verbose} - build_lib() { - lib_src=$1 - echo_build_heading $lib_src ${libName} - - noisily rustc --crate-name $CRATE_NAME $lib_src \ - ${lib.strings.concatStrings (map (x: " --crate-type ${x}") crateType)} \ - ${rustcOpts} ${rustcMeta} ${crateFeatures} --out-dir target/lib \ - --emit=dep-info,link -L dependency=target/deps ${deps} --cap-lints allow \ - $BUILD_OUT_DIR $EXTRA_BUILD $EXTRA_FEATURES --color ${colors} - - EXTRA_LIB=" --extern $CRATE_NAME=target/lib/lib$CRATE_NAME-${metadata}.rlib" - if [ -e target/deps/lib$CRATE_NAME-${metadata}${stdenv.hostPlatform.extensions.sharedLibrary} ]; then - EXTRA_LIB="$EXTRA_LIB --extern $CRATE_NAME=target/lib/lib$CRATE_NAME-${metadata}${stdenv.hostPlatform.extensions.sharedLibrary}" - fi - } - - build_bin() { - crate_name=$1 - crate_name_=$(echo $crate_name | sed -e "s/-/_/g") - main_file="" - if [[ ! -z $2 ]]; then - main_file=$2 - fi - echo_build_heading $@ - noisily rustc --crate-name $crate_name_ $main_file --crate-type bin ${rustcOpts}\ - ${crateFeatures} --out-dir target/bin --emit=dep-info,link -L dependency=target/deps \ - $LINK ${deps}$EXTRA_LIB --cap-lints allow \ - $BUILD_OUT_DIR $EXTRA_BUILD $EXTRA_FEATURES --color ${colors} \ - ${if stdenv.hostPlatform != stdenv.buildPlatform then "--target ${rust.toRustTarget stdenv.hostPlatform} -C linker=${stdenv.hostPlatform.config}-gcc" else ""} - if [ "$crate_name_" != "$crate_name" ]; then - mv target/bin/$crate_name_ target/bin/$crate_name - fi - } + # configure & source common build functions + LIB_RUSTC_OPTS="${libRustcOpts}" + BIN_RUSTC_OPTS="${binRustcOpts}" + LIB_EXT="${stdenv.hostPlatform.extensions.sharedLibrary}" + LIB_PATH="${libPath}" + LIB_NAME="${libName}" + source ${./lib.sh} + CRATE_NAME='${lib.replaceStrings ["-"] ["_"] libName}' - EXTRA_LIB="" - CRATE_NAME=$(echo ${libName} | sed -e "s/-/_/g") + setup_link_paths - if [[ -e target/link_ ]]; then - EXTRA_BUILD="$(cat target/link_) $EXTRA_BUILD" - fi - - if [[ -e "${libPath}" ]]; then - build_lib ${libPath} + if [[ -e "$LIB_PATH" ]]; then + build_lib "$LIB_PATH" + ${lib.optionalString buildTests ''build_lib_test "$LIB_PATH"''} elif [[ -e src/lib.rs ]]; then build_lib src/lib.rs - elif [[ -e src/${libName}.rs ]]; then - build_lib src/${libName}.rs + ${lib.optionalString buildTests "build_lib_test src/lib.rs"} + elif [[ -e "src/$LIB_NAME.rs" ]]; then + build_lib src/$LIB_NAME.rs + ${lib.optionalString buildTests ''build_lib_test "src/$LIB_NAME.rs"''} fi - echo "$EXTRA_LINK_SEARCH" | while read i; do - if [[ ! -z "$i" ]]; then - for library in $i; do - echo "-L $library" >> target/link - L=$(echo $library | sed -e "s#$(pwd)/target/build#$lib/lib#") - echo "-L $L" >> target/link.final - done - fi - done - echo "$EXTRA_LINK" | while read i; do - if [[ ! -z "$i" ]]; then - for library in $i; do - echo "-l $library" >> target/link - echo "-l $library" >> target/link.final - done - fi - done - - if [[ -e target/link ]]; then - sort -u target/link.final > target/link.final.sorted - mv target/link.final.sorted target/link.final - sort -u target/link > target/link.sorted - mv target/link.sorted target/link - - tr '\n' ' ' < target/link > target/link_ - LINK=$(cat target/link_) - fi - ${lib.optionalString (crateBin != "") '' - printf "%s\n" "${crateBin}" | head -n1 | tr -s ',' '\n' | while read -r BIN_NAME BIN_PATH; do + + + ${lib.optionalString (lib.length crateBin > 0) (lib.concatMapStringsSep "\n" (bin: '' mkdir -p target/bin - # filter empty entries / empty "lines" - if [[ -z "$BIN_NAME" ]]; then - continue - fi + BIN_NAME='${bin.name or crateName}' + ${if !bin ? path then '' + BIN_PATH="" + search_for_bin_path "$BIN_NAME" + '' else '' + BIN_PATH='${bin.path}' + ''} + ${build_bin} "$BIN_NAME" "$BIN_PATH" + '') crateBin)} + + ${lib.optionalString buildTests '' + # When tests are enabled build all the files in the `tests` directory as + # test binaries. + if [ -d tests ]; then + # find all the .rs files (or symlinks to those) in the tests directory, no subdirectories + find tests -maxdepth 1 \( -type f -o -type l \) -a -name '*.rs' -print0 | while IFS= read -r -d ''' file; do + mkdir -p target/bin + build_bin_test_file "$file" + done - if [[ -z "$BIN_PATH" ]]; then - # heuristic to "guess" the correct source file as found in cargo: - # https://github.com/rust-lang/cargo/blob/90fc9f620190d5fa3c80b0c8c65a1e1361e6b8ae/src/cargo/util/toml/targets.rs#L308-L325 - - # the first two cases are the "new" default IIRC - BIN_NAME_=$(echo $BIN_NAME | sed -e 's/-/_/g') - FILES=( "src/bin/$BIN_NAME.rs" "src/bin/$BIN_NAME/main.rs" "src/bin/$BIN_NAME_.rs" "src/bin/$BIN_NAME_/main.rs" "src/bin/main.rs" "src/main.rs" ) - - if ! [ -e "${libPath}" -o -e src/lib.rs -o -e "src/${libName}.rs" ]; then - # if this is not a library the following path is also valid - FILES=( "src/$BIN_NAME.rs" "src/$BIN_NAME_.rs" "''${FILES[@]}" ) - fi - - for file in "''${FILES[@]}"; - do - echo "checking file $file" - # first file that exists wins - if [[ -e "$file" ]]; then - BIN_PATH="$file" - break - fi - done - - if [[ -z "$BIN_PATH" ]]; then - echo "failed to find file for binary target: $BIN_NAME" >&2 - exit 1 - fi - fi - build_bin "$BIN_NAME" "$BIN_PATH" - done + # find all the subdirectories of tests/ that contain a main.rs file as + # that is also a test according to cargo + find tests/ -mindepth 1 -maxdepth 2 \( -type f -o -type l \) -a -name 'main.rs' -print0 | while IFS= read -r -d ''' file; do + mkdir -p target/bin + build_bin_test_file "$file" + done + + fi ''} - ${lib.optionalString (crateBin == "" && !hasCrateBin) '' + # If crateBin is empty and hasCrateBin is not set then we must try to + # detect some kind of bin target based on some files that might exist. + ${lib.optionalString (lib.length crateBin == 0 && !hasCrateBin) '' if [[ -e src/main.rs ]]; then mkdir -p target/bin - build_bin ${crateName} src/main.rs + ${build_bin} ${crateName} src/main.rs fi for i in src/bin/*.rs; do #*/ mkdir -p target/bin - build_bin "$(basename $i .rs)" "$i" + ${build_bin} "$(basename $i .rs)" "$i" done ''} # Remove object files to avoid "wrong ELF type" diff --git a/nixpkgs/pkgs/build-support/rust/build-rust-crate/configure-crate.nix b/nixpkgs/pkgs/build-support/rust/build-rust-crate/configure-crate.nix index 2c7226b0962..efc538f0fd6 100644 --- a/nixpkgs/pkgs/build-support/rust/build-rust-crate/configure-crate.nix +++ b/nixpkgs/pkgs/build-support/rust/build-rust-crate/configure-crate.nix @@ -1,4 +1,4 @@ -{ lib, stdenv, echo_build_heading, noisily, makeDeps }: +{ lib, stdenv, echo_build_heading, noisily, mkRustcDepArgs }: { build , buildDependencies , colors @@ -20,12 +20,12 @@ , verbose , workspace_member }: let version_ = lib.splitString "-" crateVersion; - versionPre = if lib.tail version_ == [] then "" else builtins.elemAt version_ 1; + versionPre = if lib.tail version_ == [] then "" else lib.elemAt version_ 1; version = lib.splitVersion (lib.head version_); - rustcOpts = lib.lists.foldl' (opts: opt: opts + " " + opt) + rustcOpts = lib.foldl' (opts: opt: opts + " " + opt) (if release then "-C opt-level=3" else "-C debuginfo=2") (["-C codegen-units=$NIX_BUILD_CORES"] ++ extraRustcOpts); - buildDeps = makeDeps buildDependencies crateRenames; + buildDeps = mkRustcDepArgs buildDependencies crateRenames; authors = lib.concatStringsSep ":" crateAuthors; optLevel = if release then 3 else 0; completeDepsDir = lib.concatStringsSep " " completeDeps; @@ -90,9 +90,9 @@ in '' export HOST="${stdenv.hostPlatform.config}" export PROFILE=${if release then "release" else "debug"} export OUT_DIR=$(pwd)/target/build/${crateName}.out - export CARGO_PKG_VERSION_MAJOR=${builtins.elemAt version 0} - export CARGO_PKG_VERSION_MINOR=${builtins.elemAt version 1} - export CARGO_PKG_VERSION_PATCH=${builtins.elemAt version 2} + export CARGO_PKG_VERSION_MAJOR=${lib.elemAt version 0} + export CARGO_PKG_VERSION_MINOR=${lib.elemAt version 1} + export CARGO_PKG_VERSION_PATCH=${lib.elemAt version 2} export CARGO_PKG_VERSION_PRE="${versionPre}" export CARGO_PKG_HOMEPAGE="${crateHomepage}" export NUM_JOBS=1 diff --git a/nixpkgs/pkgs/build-support/rust/build-rust-crate/default.nix b/nixpkgs/pkgs/build-support/rust/build-rust-crate/default.nix index edff3941636..2885b2aef51 100644 --- a/nixpkgs/pkgs/build-support/rust/build-rust-crate/default.nix +++ b/nixpkgs/pkgs/build-support/rust/build-rust-crate/default.nix @@ -13,60 +13,38 @@ let then "macos" else stdenv.hostPlatform.parsed.kernel.name; - makeDeps = dependencies: crateRenames: - (lib.concatMapStringsSep " " (dep: + # Create rustc arguments to link against the given list of dependencies and + # renames + mkRustcDepArgs = dependencies: crateRenames: + lib.concatMapStringsSep " " (dep: let - extern = lib.strings.replaceStrings ["-"] ["_"] dep.libName; - name = if builtins.hasAttr dep.crateName crateRenames then + extern = lib.replaceStrings ["-"] ["_"] dep.libName; + name = if lib.hasAttr dep.crateName crateRenames then lib.strings.replaceStrings ["-"] ["_"] crateRenames.${dep.crateName} else extern; - in (if lib.lists.any (x: x == "lib") dep.crateType then + in (if lib.any (x: x == "lib") dep.crateType then " --extern ${name}=${dep.lib}/lib/lib${extern}-${dep.metadata}.rlib" else " --extern ${name}=${dep.lib}/lib/lib${extern}-${dep.metadata}${stdenv.hostPlatform.extensions.sharedLibrary}") - ) dependencies); - - echo_build_heading = colors: '' - echo_build_heading() { - start="" - end="" - if [[ "${colors}" == "always" ]]; then - start="$(printf '\033[0;1;32m')" #set bold, and set green. - end="$(printf '\033[0m')" #returns to "normal" - fi - if (( $# == 1 )); then - echo "$start""Building $1""$end" - else - echo "$start""Building $1 ($2)""$end" - fi - } - ''; - noisily = colors: verbose: '' - noisily() { - start="" - end="" - if [[ "${colors}" == "always" ]]; then - start="$(printf '\033[0;1;32m')" #set bold, and set green. - end="$(printf '\033[0m')" #returns to "normal" - fi - ${lib.optionalString verbose '' - echo -n "$start"Running "$end" - echo $@ - ''} - $@ - } - ''; - - configureCrate = import ./configure-crate.nix { inherit lib stdenv echo_build_heading noisily makeDeps; }; - buildCrate = import ./build-crate.nix { inherit lib stdenv echo_build_heading noisily makeDeps rust; }; - installCrate = import ./install-crate.nix; - - in + ) dependencies; + + inherit (import ./log.nix { inherit lib; }) noisily echo_build_heading; + + configureCrate = import ./configure-crate.nix { + inherit lib stdenv echo_build_heading noisily mkRustcDepArgs; + }; + + buildCrate = import ./build-crate.nix { + inherit lib stdenv echo_build_heading noisily mkRustcDepArgs rust; + }; + + installCrate = import ./install-crate.nix { inherit stdenv; }; +in crate_: lib.makeOverridable ({ rust, release, verbose, features, buildInputs, crateOverrides, dependencies, buildDependencies, crateRenames, - extraRustcOpts, + extraRustcOpts, buildTests, preUnpack, postUnpack, prePatch, patches, postPatch, preConfigure, postConfigure, preBuild, postBuild, preInstall, postInstall }: @@ -77,59 +55,66 @@ let crate = crate_ // (lib.attrByPath [ crate_.crateName ] (attr: {}) crateOverr "src" "buildInputs" "crateBin" "crateLib" "libName" "libPath" "buildDependencies" "dependencies" "features" "crateRenames" "crateName" "version" "build" "authors" "colors" "edition" + "buildTests" ]; - extraDerivationAttrs = lib.filterAttrs (n: v: ! lib.elem n processedAttrs) crate; + extraDerivationAttrs = builtins.removeAttrs crate processedAttrs; buildInputs_ = buildInputs; extraRustcOpts_ = extraRustcOpts; + buildTests_ = buildTests; + + # take a list of crates that we depend on and override them to fit our overrides, rustc, release, … + makeDependencies = map (dep: lib.getLib (dep.override { inherit release verbose crateOverrides; })); + + # crate2nix has a hack for the old bash based build script that did split + # entries at `,`. No we have to work around that hack. + # https://github.com/kolloch/crate2nix/blame/5b19c1b14e1b0e5522c3e44e300d0b332dc939e7/crate2nix/templates/build.nix.tera#L89 + crateBin = lib.filter (bin: !(bin ? name && bin.name == ",")) (crate.crateBin or []); + hasCrateBin = crate ? crateBin; in stdenv.mkDerivation (rec { inherit (crate) crateName; - inherit preUnpack postUnpack prePatch patches postPatch preConfigure postConfigure preBuild postBuild preInstall postInstall; - - src = if lib.hasAttr "src" crate then - crate.src - else - fetchCrate { inherit (crate) crateName version sha256; }; - name = "rust_${crate.crateName}-${crate.version}"; + inherit + preUnpack + postUnpack + prePatch + patches + postPatch + preConfigure + postConfigure + preBuild + postBuild + preInstall + postInstall + buildTests + ; + + src = crate.src or (fetchCrate { inherit (crate) crateName version sha256; }); + name = "rust_${crate.crateName}-${crate.version}${lib.optionalString buildTests_ "-test"}"; depsBuildBuild = [ rust stdenv.cc ]; buildInputs = (crate.buildInputs or []) ++ buildInputs_; - dependencies = - builtins.map - (dep: lib.getLib (dep.override { rust = rust; release = release; verbose = verbose; crateOverrides = crateOverrides; })) - dependencies_; - - buildDependencies = - builtins.map - (dep: lib.getLib (dep.override { rust = rust; release = release; verbose = verbose; crateOverrides = crateOverrides; })) - buildDependencies_; - - completeDeps = lib.lists.unique (dependencies ++ lib.lists.concatMap (dep: dep.completeDeps) dependencies); - completeBuildDeps = lib.lists.unique ( + dependencies = makeDependencies dependencies_; + buildDependencies = makeDependencies buildDependencies_; + + completeDeps = lib.unique (dependencies ++ lib.concatMap (dep: dep.completeDeps) dependencies); + completeBuildDeps = lib.unique ( buildDependencies - ++ lib.lists.concatMap (dep: dep.completeBuildDeps ++ dep.completeDeps) buildDependencies + ++ lib.concatMap (dep: dep.completeBuildDeps ++ dep.completeDeps) buildDependencies ); - crateFeatures = if crate ? features then - lib.concatMapStringsSep " " (f: "--cfg feature=\\\"${f}\\\"") (crate.features ++ features) #" - else ""; + crateFeatures = lib.optionalString (crate ? features) + (lib.concatMapStringsSep " " (f: "--cfg feature=\\\"${f}\\\"") (crate.features ++ features)); libName = if crate ? libName then crate.libName else crate.crateName; libPath = if crate ? libPath then crate.libPath else ""; - depsMetadata = builtins.foldl' (str: dep: str + dep.metadata) "" (dependencies ++ buildDependencies); - metadata = builtins.substring 0 10 (builtins.hashString "sha256" (crateName + "-" + crateVersion + "___" + toString crateFeatures + "___" + depsMetadata )); - - crateBin = if crate ? crateBin then - builtins.foldl' (bins: bin: let - name = (if bin ? name then bin.name else crateName); - path = if bin ? path then bin.path else ""; - in - bins + (if bin == "" then "" else ",") + "${name} ${path}" - - ) "" crate.crateBin - else ""; - hasCrateBin = crate ? crateBin; + # Seed the symbol hashes with something unique every time. + # https://doc.rust-lang.org/1.0.0/rustc/metadata/loader/index.html#frobbing-symbols + metadata = let + depsMetadata = lib.foldl' (str: dep: str + dep.metadata) "" (dependencies ++ buildDependencies); + hashedMetadata = builtins.hashString "sha256" + (crateName + "-" + crateVersion + "___" + toString crateFeatures + "___" + depsMetadata); + in lib.substring 0 10 hashedMetadata; build = crate.build or ""; workspace_member = crate.workspace_member or "."; @@ -142,9 +127,13 @@ stdenv.mkDerivation (rec { if lib.attrByPath ["plugin"] false crate then ["dylib"] else (crate.type or ["lib"]); colors = lib.attrByPath [ "colors" ] "always" crate; - extraLinkFlags = builtins.concatStringsSep " " (crate.extraLinkFlags or []); + extraLinkFlags = lib.concatStringsSep " " (crate.extraLinkFlags or []); edition = crate.edition or null; - extraRustcOpts = (if crate ? extraRustcOpts then crate.extraRustcOpts else []) ++ extraRustcOpts_ ++ (lib.optional (edition != null) "--edition ${edition}"); + extraRustcOpts = + lib.optionals (crate ? extraRustcOpts) crate.extraRustcOpts + ++ extraRustcOpts_ + ++ (lib.optional (edition != null) "--edition ${edition}"); + configurePhase = configureCrate { inherit crateName buildDependencies completeDeps completeBuildDeps crateDescription @@ -155,13 +144,15 @@ stdenv.mkDerivation (rec { buildPhase = buildCrate { inherit crateName dependencies crateFeatures crateRenames libName release libPath crateType - metadata crateBin hasCrateBin verbose colors - extraRustcOpts; + metadata hasCrateBin crateBin verbose colors + extraRustcOpts buildTests; }; - installPhase = installCrate crateName metadata; + installPhase = installCrate crateName metadata buildTests; - outputs = [ "out" "lib" ]; - outputDev = [ "lib" ]; + # depending on the test setting we are either producing something with bins + # and libs or just test binaries + outputs = if buildTests then [ "out" ] else [ "out" "lib" ]; + outputDev = if buildTests then [ "out" ] else [ "lib" ]; } // extraDerivationAttrs )) { @@ -186,4 +177,5 @@ stdenv.mkDerivation (rec { dependencies = crate_.dependencies or []; buildDependencies = crate_.buildDependencies or []; crateRenames = crate_.crateRenames or {}; + buildTests = crate_.buildTests or false; } diff --git a/nixpkgs/pkgs/build-support/rust/build-rust-crate/helpers.nix b/nixpkgs/pkgs/build-support/rust/build-rust-crate/helpers.nix index 14d997b2d5c..386d0ce7084 100644 --- a/nixpkgs/pkgs/build-support/rust/build-rust-crate/helpers.nix +++ b/nixpkgs/pkgs/build-support/rust/build-rust-crate/helpers.nix @@ -3,23 +3,23 @@ kernel = stdenv.hostPlatform.parsed.kernel.name; abi = stdenv.hostPlatform.parsed.abi.name; cpu = stdenv.hostPlatform.parsed.cpu.name; - updateFeatures = f: up: functions: builtins.deepSeq f (lib.lists.foldl' (features: fun: fun features) (lib.attrsets.recursiveUpdate f up) functions); + updateFeatures = f: up: functions: lib.deepSeq f (lib.foldl' (features: fun: fun features) (lib.attrsets.recursiveUpdate f up) functions); mapFeatures = features: map (fun: fun { features = features; }); - mkFeatures = feat: lib.lists.foldl (features: featureName: + mkFeatures = feat: lib.foldl (features: featureName: if feat.${featureName} or false then [ featureName ] ++ features else features - ) [] (builtins.attrNames feat); + ) [] (lib.attrNames feat); include = includedFiles: src: builtins.filterSource (path: type: - lib.lists.any (f: + lib.any (f: let p = toString (src + ("/" + f)); in p == path || (lib.strings.hasPrefix (p + "/") path) ) includedFiles ) src; exclude = excludedFiles: src: builtins.filterSource (path: type: - lib.lists.all (f: + lib.all (f: !lib.strings.hasPrefix (toString (src + ("/" + f))) path ) excludedFiles ) src; diff --git a/nixpkgs/pkgs/build-support/rust/build-rust-crate/install-crate.nix b/nixpkgs/pkgs/build-support/rust/build-rust-crate/install-crate.nix index 934c3a03176..5ba7b69bedc 100644 --- a/nixpkgs/pkgs/build-support/rust/build-rust-crate/install-crate.nix +++ b/nixpkgs/pkgs/build-support/rust/build-rust-crate/install-crate.nix @@ -1,5 +1,6 @@ -crateName: metadata: -'' +{ stdenv }: +crateName: metadata: buildTests: +if !buildTests then '' runHook preInstall # always create $out even if we do not have binaries. We are detecting binary targets during compilation, if those are missing there is no way to only have $lib mkdir $out @@ -29,4 +30,22 @@ crateName: metadata: fi fi runHook postInstall +'' else +# for tests we just put them all in the output. No execution. +'' + runHook preInstall + + mkdir -p $out/tests + if [ -e target/bin ]; then + find target/bin/ -type f -executable -exec cp {} $out/tests \; + fi + if [ -e target/lib ]; then + find target/lib/ -type f \! -name '*.rlib' \ + -a \! -name '*${stdenv.hostPlatform.extensions.sharedLibrary}' \ + -a \! -name '*.d' \ + -executable \ + -print0 | xargs --no-run-if-empty --null install --target $out/tests; + fi + + runHook postInstall '' diff --git a/nixpkgs/pkgs/build-support/rust/build-rust-crate/lib.sh b/nixpkgs/pkgs/build-support/rust/build-rust-crate/lib.sh new file mode 100644 index 00000000000..d4d9317496f --- /dev/null +++ b/nixpkgs/pkgs/build-support/rust/build-rust-crate/lib.sh @@ -0,0 +1,138 @@ +build_lib() { + lib_src=$1 + echo_build_heading $lib_src ${libName} + + noisily rustc \ + --crate-name $CRATE_NAME \ + $lib_src \ + --out-dir target/lib \ + --emit=dep-info,link \ + -L dependency=target/deps \ + --cap-lints allow \ + $LIB_RUSTC_OPTS \ + $BUILD_OUT_DIR \ + $EXTRA_BUILD \ + $EXTRA_FEATURES \ + $EXTRA_RUSTC_FLAGS \ + --color $colors + + EXTRA_LIB=" --extern $CRATE_NAME=target/lib/lib$CRATE_NAME-$metadata.rlib" + if [ -e target/deps/lib$CRATE_NAME-$metadata$LIB_EXT ]; then + EXTRA_LIB="$EXTRA_LIB --extern $CRATE_NAME=target/lib/lib$CRATE_NAME-$metadata$LIB_EXT" + fi +} + +build_bin() { + local crate_name=$1 + local crate_name_=$(echo $crate_name | tr '-' '_') + local main_file="" + + if [[ ! -z $2 ]]; then + main_file=$2 + fi + echo_build_heading $@ + noisily rustc \ + --crate-name $crate_name_ \ + $main_file \ + --crate-type bin \ + $BIN_RUSTC_OPTS \ + --out-dir target/bin \ + --emit=dep-info,link \ + -L dependency=target/deps \ + $LINK \ + $EXTRA_LIB \ + --cap-lints allow \ + $BUILD_OUT_DIR \ + $EXTRA_BUILD \ + $EXTRA_FEATURES \ + $EXTRA_RUSTC_FLAGS \ + --color ${colors} \ + + if [ "$crate_name_" != "$crate_name" ]; then + mv target/bin/$crate_name_ target/bin/$crate_name + fi +} + +build_lib_test() { + local file="$1" + EXTRA_RUSTC_FLAGS="--test $EXTRA_RUSTC_FLAGS" build_lib "$1" "$2" +} + +build_bin_test() { + local crate="$1" + local file="$2" + EXTRA_RUSTC_FLAGS="--test $EXTRA_RUSTC_FLAGS" build_bin "$1" "$2" +} + +build_bin_test_file() { + local file="$1" + local derived_crate_name="${file//\//_}" + derived_crate_name="${derived_crate_name%.rs}" + build_bin_test "$derived_crate_name" "$file" +} + +setup_link_paths() { + EXTRA_LIB="" + if [[ -e target/link_ ]]; then + EXTRA_BUILD="$(cat target/link_) $EXTRA_BUILD" + fi + + echo "$EXTRA_LINK_SEARCH" | while read i; do + if [[ ! -z "$i" ]]; then + for library in $i; do + echo "-L $library" >> target/link + L=$(echo $library | sed -e "s#$(pwd)/target/build#$lib/lib#") + echo "-L $L" >> target/link.final + done + fi + done + echo "$EXTRA_LINK" | while read i; do + if [[ ! -z "$i" ]]; then + for library in $i; do + echo "-l $library" >> target/link + echo "-l $library" >> target/link.final + done + fi + done + + if [[ -e target/link ]]; then + sort -u target/link.final > target/link.final.sorted + mv target/link.final.sorted target/link.final + sort -u target/link > target/link.sorted + mv target/link.sorted target/link + + tr '\n' ' ' < target/link > target/link_ + LINK=$(cat target/link_) + fi +} + +search_for_bin_path() { + # heuristic to "guess" the correct source file as found in cargo: + # https://github.com/rust-lang/cargo/blob/90fc9f620190d5fa3c80b0c8c65a1e1361e6b8ae/src/cargo/util/toml/targets.rs#L308-L325 + + BIN_NAME=$1 + BIN_NAME_=$(echo $BIN_NAME | tr '-' '_') + + # the first two cases are the "new" default IIRC + FILES=( "src/bin/$BIN_NAME.rs" "src/bin/$BIN_NAME/main.rs" "src/bin/$BIN_NAME_.rs" "src/bin/$BIN_NAME_/main.rs" "src/bin/main.rs" "src/main.rs" ) + + if ! [ -e "$LIB_PATH" -o -e src/lib.rs -o -e "src/$LIB_NAME.rs" ]; then + # if this is not a library the following path is also valid + FILES=( "src/$BIN_NAME.rs" "src/$BIN_NAME_.rs" "${FILES[@]}" ) + fi + + for file in "${FILES[@]}"; + do + echo "checking file $file" + # first file that exists wins + if [[ -e "$file" ]]; then + BIN_PATH="$file" + break + fi + done + + if [[ -z "$BIN_PATH" ]]; then + echo "failed to find file for binary target: $BIN_NAME" >&2 + exit 1 + fi +} diff --git a/nixpkgs/pkgs/build-support/rust/build-rust-crate/log.nix b/nixpkgs/pkgs/build-support/rust/build-rust-crate/log.nix new file mode 100644 index 00000000000..25181c787e2 --- /dev/null +++ b/nixpkgs/pkgs/build-support/rust/build-rust-crate/log.nix @@ -0,0 +1,33 @@ +{ lib }: +{ + echo_build_heading = colors: '' + echo_build_heading() { + start="" + end="" + ${lib.optionalString (colors == "always") '' + start="$(printf '\033[0;1;32m')" #set bold, and set green. + end="$(printf '\033[0m')" #returns to "normal" + ''} + if (( $# == 1 )); then + echo "$start""Building $1""$end" + else + echo "$start""Building $1 ($2)""$end" + fi + } + ''; + noisily = colors: verbose: '' + noisily() { + start="" + end="" + ${lib.optionalString (colors == "always") '' + start="$(printf '\033[0;1;32m')" #set bold, and set green. + end="$(printf '\033[0m')" #returns to "normal" + ''} + ${lib.optionalString verbose '' + echo -n "$start"Running "$end" + echo $@ + ''} + $@ + } + ''; +} diff --git a/nixpkgs/pkgs/build-support/rust/build-rust-crate/test/default.nix b/nixpkgs/pkgs/build-support/rust/build-rust-crate/test/default.nix index 4a90cf442a4..f0f1ed4d1eb 100644 --- a/nixpkgs/pkgs/build-support/rust/build-rust-crate/test/default.nix +++ b/nixpkgs/pkgs/build-support/rust/build-rust-crate/test/default.nix @@ -29,10 +29,30 @@ let } ''; + mkTestFile = name: functionName: mkFile name '' + #[cfg(test)] + #[test] + fn ${functionName}() { + assert!(true); + } + ''; + mkTestFileWithMain = name: functionName: mkFile name '' + #[cfg(test)] + #[test] + fn ${functionName}() { + assert!(true); + } + + fn main() {} + ''; + + mkLib = name: mkFile name "pub fn test() -> i32 { return 23; }"; mkTest = crateArgs: let - crate = mkCrate crateArgs; + crate = mkCrate (builtins.removeAttrs crateArgs ["expectedTestOutput"]); + hasTests = crateArgs.buildTests or false; + expectedTestOutputs = crateArgs.expectedTestOutputs or null; binaries = map (v: ''"${v.name}"'') (crateArgs.crateBin or []); isLib = crateArgs ? libName || crateArgs ? libPath; crateName = crateArgs.crateName or "nixtestcrate"; @@ -44,16 +64,28 @@ let src = mkBinExtern "src/main.rs" libName; }; - in runCommand "run-buildRustCrate-${crateName}-test" { - nativeBuildInputs = [ crate ]; - } '' - ${lib.concatStringsSep "\n" binaries} - ${lib.optionalString isLib '' - test -e ${crate}/lib/*.rlib || exit 1 - ${libTestBinary}/bin/run-test-${crateName} - ''} - touch $out - ''; + in + assert expectedTestOutputs != null -> hasTests; + assert hasTests -> expectedTestOutputs != null; + + runCommand "run-buildRustCrate-${crateName}-test" { + nativeBuildInputs = [ crate ]; + } (if !hasTests then '' + ${lib.concatStringsSep "\n" binaries} + ${lib.optionalString isLib '' + test -e ${crate}/lib/*.rlib || exit 1 + ${libTestBinary}/bin/run-test-${crateName} + ''} + touch $out + '' else '' + for file in ${crate}/tests/*; do + $file 2>&1 >> $out + done + set -e + ${lib.concatMapStringsSep "\n" (o: "grep '${o}' $out || { echo 'output \"${o}\" not found in:'; cat $out; exit 23; }") expectedTestOutputs} + '' + ); + in rec { tests = let @@ -85,6 +117,71 @@ let dependencies = [ (mkCrate { crateName = "foo"; libName = "foolib"; src = mkLib "src/lib.rs"; }) ]; crateRenames = { "foo" = "foo_renamed"; }; }; + rustLibTestsDefault = { + src = mkTestFile "src/lib.rs" "baz"; + buildTests = true; + expectedTestOutputs = [ "test baz ... ok" ]; + }; + rustLibTestsCustomLibName = { + libName = "test_lib"; + src = mkTestFile "src/test_lib.rs" "foo"; + buildTests = true; + expectedTestOutputs = [ "test foo ... ok" ]; + }; + rustLibTestsCustomLibPath = { + libPath = "src/test_path.rs"; + src = mkTestFile "src/test_path.rs" "bar"; + buildTests = true; + expectedTestOutputs = [ "test bar ... ok" ]; + }; + rustLibTestsCustomLibPathWithTests = { + libPath = "src/test_path.rs"; + src = symlinkJoin { + name = "rust-lib-tests-custom-lib-path-with-tests-dir"; + paths = [ + (mkTestFile "src/test_path.rs" "bar") + (mkTestFile "tests/something.rs" "something") + ]; + }; + buildTests = true; + expectedTestOutputs = [ + "test bar ... ok" + "test something ... ok" + ]; + }; + rustBinTestsCombined = { + src = symlinkJoin { + name = "rust-bin-tests-combined"; + paths = [ + (mkTestFileWithMain "src/main.rs" "src_main") + (mkTestFile "tests/foo.rs" "tests_foo") + (mkTestFile "tests/bar.rs" "tests_bar") + ]; + }; + buildTests = true; + expectedTestOutputs = [ + "test src_main ... ok" + "test tests_foo ... ok" + "test tests_bar ... ok" + ]; + }; + rustBinTestsSubdirCombined = { + src = symlinkJoin { + name = "rust-bin-tests-subdir-combined"; + paths = [ + (mkTestFileWithMain "src/main.rs" "src_main") + (mkTestFile "tests/foo/main.rs" "tests_foo") + (mkTestFile "tests/bar/main.rs" "tests_bar") + ]; + }; + buildTests = true; + expectedTestOutputs = [ + "test src_main ... ok" + "test tests_foo ... ok" + "test tests_bar ... ok" + ]; + }; + }; brotliCrates = (callPackage ./brotli-crates.nix {}); in lib.mapAttrs (key: value: mkTest (value // lib.optionalAttrs (!value?crateName) { crateName = key; })) cases // { diff --git a/nixpkgs/pkgs/build-support/rust/default.nix b/nixpkgs/pkgs/build-support/rust/default.nix index 1d8e4448674..f9cf8f1f0c1 100644 --- a/nixpkgs/pkgs/build-support/rust/default.nix +++ b/nixpkgs/pkgs/build-support/rust/default.nix @@ -4,6 +4,7 @@ , cargoSha256 ? "unset" , src ? null , srcs ? null +, unpackPhase ? null , cargoPatches ? [] , patches ? [] , sourceRoot ? null @@ -29,7 +30,7 @@ assert buildType == "release" || buildType == "debug"; let cargoDeps = if cargoVendorDir == null then fetchcargo { - inherit name src srcs sourceRoot cargoUpdateHook; + inherit name src srcs sourceRoot unpackPhase cargoUpdateHook; copyLockfile = verifyCargoDeps; patches = cargoPatches; sha256 = cargoSha256; diff --git a/nixpkgs/pkgs/build-support/rust/fetchcargo.nix b/nixpkgs/pkgs/build-support/rust/fetchcargo.nix index a515ce9c6eb..7a0ba38dce7 100644 --- a/nixpkgs/pkgs/build-support/rust/fetchcargo.nix +++ b/nixpkgs/pkgs/build-support/rust/fetchcargo.nix @@ -18,19 +18,19 @@ let cargo-vendor-normalise = stdenv.mkDerivation { }; in { name ? "cargo-deps" -, src -, srcs -, patches +, src ? null +, srcs ? [] +, patches ? [] , sourceRoot , sha256 , cargoUpdateHook ? "" , # whenever to also include the Cargo.lock in the output copyLockfile ? false -}: -stdenv.mkDerivation { +, ... +} @ args: +stdenv.mkDerivation ({ name = "${name}-vendor"; nativeBuildInputs = [ cacert git cargo-vendor-normalise cargo ]; - inherit src srcs patches sourceRoot; phases = "unpackPhase patchPhase installPhase"; @@ -76,4 +76,6 @@ stdenv.mkDerivation { impureEnvVars = stdenv.lib.fetchers.proxyImpureEnvVars; preferLocalBuild = true; -} +} // (builtins.removeAttrs args [ + "name" "sha256" "cargoUpdateHook" "copyLockfile" +])) diff --git a/nixpkgs/pkgs/build-support/setup-hooks/wrap-gapps-hook.sh b/nixpkgs/pkgs/build-support/setup-hooks/wrap-gapps-hook.sh index a05d4f689db..ff0cda7eaf0 100644 --- a/nixpkgs/pkgs/build-support/setup-hooks/wrap-gapps-hook.sh +++ b/nixpkgs/pkgs/build-support/setup-hooks/wrap-gapps-hook.sh @@ -42,7 +42,9 @@ wrapGAppsHook() { fi for v in ${wrapPrefixVariables:-} GST_PLUGIN_SYSTEM_PATH_1_0 GI_TYPELIB_PATH GRL_PLUGIN_PATH; do - gappsWrapperArgs+=(--prefix "$v" : "${!v}") + if [ -n "${!v}" ]; then + gappsWrapperArgs+=(--prefix "$v" : "${!v}") + fi done if [[ -z "${dontWrapGApps:-}" ]]; then diff --git a/nixpkgs/pkgs/build-support/skaware/build-skaware-package.nix b/nixpkgs/pkgs/build-support/skaware/build-skaware-package.nix index 9b159a994c8..9e4456a3a15 100644 --- a/nixpkgs/pkgs/build-support/skaware/build-skaware-package.nix +++ b/nixpkgs/pkgs/build-support/skaware/build-skaware-package.nix @@ -18,12 +18,15 @@ in { , configureFlags # mostly for moving and deleting files from the build directory # : lines -, postInstall +, postInstall ? "" + # : lines +, postFixup ? "" # : list Maintainer , maintainers ? [] - - -}: + # : attrs +, meta ? {} +, ... +} @ args: let @@ -50,16 +53,12 @@ let "README.*" ]; -in stdenv.mkDerivation { - name = "${pname}-${version}"; - +in stdenv.mkDerivation ({ src = fetchurl { url = "https://skarnet.org/software/${pname}/${pname}-${version}.tar.gz"; inherit sha256; }; - inherit outputs; - dontDisableStatic = true; enableParallelBuilding = true; @@ -84,13 +83,11 @@ in stdenv.mkDerivation { noiseFiles = commonNoiseFiles; docFiles = commonMetaFiles; }} $doc/share/doc/${pname} - - ${postInstall} - ''; + '' + postInstall; postFixup = '' ${cleanPackaging.checkForRemainingFiles} - ''; + '' + postFixup; meta = { homepage = "https://skarnet.org/software/${pname}/"; @@ -98,6 +95,9 @@ in stdenv.mkDerivation { license = stdenv.lib.licenses.isc; maintainers = with lib.maintainers; [ pmahoney Profpatsch ] ++ maintainers; - }; + } // meta; -} +} // builtins.removeAttrs args [ + "sha256" "configureFlags" "postInstall" "postFixup" + "meta" "description" "platforms" "maintainers" +]) diff --git a/nixpkgs/pkgs/build-support/trivial-builders.nix b/nixpkgs/pkgs/build-support/trivial-builders.nix index 55df09121b4..5210b7d7ba2 100644 --- a/nixpkgs/pkgs/build-support/trivial-builders.nix +++ b/nixpkgs/pkgs/build-support/trivial-builders.nix @@ -2,11 +2,16 @@ let - runCommand' = stdenv: name: env: buildCommand: + runCommand' = runLocal: stdenv: name: env: buildCommand: stdenv.mkDerivation ({ inherit name buildCommand; passAsFile = [ "buildCommand" ]; - } // env); + } + // (lib.optionalAttrs runLocal { + preferLocalBuild = true; + allowSubstitutes = false; + }) + // env); in @@ -21,11 +26,27 @@ rec { * runCommand "name" {envVariable = true;} ''echo hello > $out'' * runCommandNoCC "name" {envVariable = true;} ''echo hello > $out'' # equivalent to prior * runCommandCC "name" {} ''gcc -o myfile myfile.c; cp myfile $out''; + * + * The `*Local` variants force a derivation to be built locally, + * it is not substituted. + * + * This is intended for very cheap commands (<1s execution time). + * It saves on the network roundrip and can speed up a build. + * + * It is the same as adding the special fields + * `preferLocalBuild = true;` + * `allowSubstitutes = false;` + * to a derivation’s attributes. */ runCommand = runCommandNoCC; - runCommandNoCC = runCommand' stdenvNoCC; - runCommandCC = runCommand' stdenv; + runCommandLocal = runCommandNoCCLocal; + + runCommandNoCC = runCommand' false stdenvNoCC; + runCommandNoCCLocal = runCommand' true stdenvNoCC; + runCommandCC = runCommand' false stdenv; + # `runCommandCCLocal` left out on purpose. + # We shouldn’t force the user to have a cc in scope. /* Writes a text file to the nix store. * The contents of text is added to the file in the store. diff --git a/nixpkgs/pkgs/build-support/vm/default.nix b/nixpkgs/pkgs/build-support/vm/default.nix index 335cab7c45e..a7050f52e52 100644 --- a/nixpkgs/pkgs/build-support/vm/default.nix +++ b/nixpkgs/pkgs/build-support/vm/default.nix @@ -430,7 +430,7 @@ rec { set +o pipefail for i in $rpms; do echo "$i..." - ${rpm}/bin/rpm2cpio "$i" | chroot /mnt ${cpio}/bin/cpio -i --make-directories --unconditional --extract-over-symlinks + ${rpm}/bin/rpm2cpio "$i" | chroot /mnt ${cpio}/bin/cpio -i --make-directories --unconditional done eval "$preInstall" diff --git a/nixpkgs/pkgs/build-support/vm/windows/default.nix b/nixpkgs/pkgs/build-support/vm/windows/default.nix index 48ee2713d1f..309241c36de 100644 --- a/nixpkgs/pkgs/build-support/vm/windows/default.nix +++ b/nixpkgs/pkgs/build-support/vm/windows/default.nix @@ -20,8 +20,7 @@ let ''; in { - runInWindowsVM = drv: let - in pkgs.lib.overrideDerivation drv (attrs: let + runInWindowsVM = drv: pkgs.lib.overrideDerivation drv (attrs: let bootstrap = bootstrapper attrs.windowsImage; in { requiredSystemFeatures = [ "kvm" ]; diff --git a/nixpkgs/pkgs/build-support/writers/default.nix b/nixpkgs/pkgs/build-support/writers/default.nix index 2cd4f1af022..b90c6490e4a 100644 --- a/nixpkgs/pkgs/build-support/writers/default.nix +++ b/nixpkgs/pkgs/build-support/writers/default.nix @@ -148,6 +148,7 @@ rec { cp $contentPath tmp.hs ${ghc.withPackages (_: libraries )}/bin/ghc tmp.hs mv tmp $out + ${pkgs.binutils-unwrapped}/bin/strip --strip-unneeded "$out" ''; } name; |