diff options
Diffstat (limited to 'nixpkgs/pkgs/stdenv')
41 files changed, 5177 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/stdenv/adapters.nix b/nixpkgs/pkgs/stdenv/adapters.nix new file mode 100644 index 000000000000..8f62bd24dda1 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/adapters.nix @@ -0,0 +1,212 @@ +/* This file contains various functions that take a stdenv and return + a new stdenv with different behaviour, e.g. using a different C + compiler. */ + +pkgs: + +rec { + + + # Override the compiler in stdenv for specific packages. + overrideCC = stdenv: cc: stdenv.override { allowedRequisites = null; cc = cc; }; + + + # Add some arbitrary packages to buildInputs for specific packages. + # Used to override packages in stdenv like Make. Should not be used + # for other dependencies. + overrideInStdenv = stdenv: pkgs: + stdenv.override (prev: { allowedRequisites = null; extraBuildInputs = prev.extraBuildInputs or [] ++ pkgs; }); + + + # Override the setup script of stdenv. Useful for testing new + # versions of the setup script without causing a rebuild of + # everything. + # + # Example: + # randomPkg = import ../bla { ... + # stdenv = overrideSetup stdenv ../stdenv/generic/setup-latest.sh; + # }; + overrideSetup = stdenv: setupScript: stdenv.override { inherit setupScript; }; + + + # Return a modified stdenv that tries to build statically linked + # binaries. + makeStaticBinaries = stdenv: + let stdenv' = if stdenv.hostPlatform.libc != "glibc" then stdenv else + stdenv.override (prev: { + extraBuildInputs = prev.extraBuildInputs or [] ++ [ + stdenv.glibc.static + ]; + }); + in stdenv' // + { mkDerivation = args: + if stdenv'.hostPlatform.isDarwin + then throw "Cannot build fully static binaries on Darwin/macOS" + else stdenv'.mkDerivation (args // { + NIX_CFLAGS_LINK = toString (args.NIX_CFLAGS_LINK or "") + " -static"; + configureFlags = (args.configureFlags or []) ++ [ + "--disable-shared" # brrr... + ]; + }); + }; + + + # Return a modified stdenv that builds static libraries instead of + # shared libraries. + makeStaticLibraries = stdenv: stdenv // + { mkDerivation = args: stdenv.mkDerivation (args // { + dontDisableStatic = true; + configureFlags = (args.configureFlags or []) ++ [ + "--enable-static" + "--disable-shared" + ]; + mesonFlags = (args.mesonFlags or []) ++ [ "-Ddefault_library=static" ]; + }); + static = true; + }; + + + /* Modify a stdenv so that all buildInputs are implicitly propagated to + consuming derivations + */ + propagateBuildInputs = stdenv: stdenv // + { mkDerivation = args: stdenv.mkDerivation (args // { + propagatedBuildInputs = (args.propagatedBuildInputs or []) ++ (args.buildInputs or []); + buildInputs = []; + }); + }; + + + /* Modify a stdenv so that the specified attributes are added to + every derivation returned by its mkDerivation function. + + Example: + stdenvNoOptimise = + addAttrsToDerivation + { NIX_CFLAGS_COMPILE = "-O0"; } + stdenv; + */ + addAttrsToDerivation = extraAttrs: stdenv: stdenv // + { mkDerivation = args: stdenv.mkDerivation (args // extraAttrs); }; + + + /* Return a modified stdenv that builds packages with GCC's coverage + instrumentation. The coverage note files (*.gcno) are stored in + $out/.build, along with the source code of the package, to enable + programs like lcov to produce pretty-printed reports. + */ + addCoverageInstrumentation = stdenv: + overrideInStdenv stdenv [ pkgs.enableGCOVInstrumentation pkgs.keepBuildTree ]; + + + /* Replace the meta.maintainers field of a derivation. This is useful + when you want to fork to update some packages without disturbing other + developers. + + e.g.: in all-packages.nix: + + # remove all maintainers. + defaultStdenv = replaceMaintainersField allStdenvs.stdenv pkgs []; + */ + replaceMaintainersField = stdenv: pkgs: maintainers: stdenv // + { mkDerivation = args: + stdenv.lib.recursiveUpdate + (stdenv.mkDerivation args) + { meta.maintainers = maintainers; }; + }; + + + /* Use the trace output to report all processed derivations with their + license name. + */ + traceDrvLicenses = stdenv: stdenv // + { mkDerivation = args: + let + pkg = stdenv.mkDerivation args; + printDrvPath = val: let + drvPath = builtins.unsafeDiscardStringContext pkg.drvPath; + license = pkg.meta.license or null; + in + builtins.trace "@:drv:${toString drvPath}:${builtins.toString license}:@" val; + in pkg // { + outPath = printDrvPath pkg.outPath; + drvPath = printDrvPath pkg.drvPath; + }; + }; + + + /* Abort if the license predicate is not verified for a derivation + declared with mkDerivation. + + One possible predicate to avoid all non-free packages can be achieved + with the following function: + + isFree = license: with builtins; + if license == null then true + else if isList license then lib.all isFree license + else license != "non-free" && license != "unfree"; + + This adapter can be defined on the defaultStdenv definition. You can + use it by patching the all-packages.nix file or by using the override + feature of ~/.config/nixpkgs/config.nix . + */ + validateLicenses = licensePred: stdenv: stdenv // + { mkDerivation = args: + let + pkg = stdenv.mkDerivation args; + drv = builtins.unsafeDiscardStringContext pkg.drvPath; + license = + pkg.meta.license or + # Fixed-output derivations such as source tarballs usually + # don't have licensing information, but that's OK. + (pkg.outputHash or + (builtins.trace + "warning: ${drv} lacks licensing information" null)); + + validate = arg: + if licensePred license then arg + else abort '' + while building ${drv}: + license `${builtins.toString license}' does not pass the predicate. + ''; + + in pkg // { + outPath = validate pkg.outPath; + drvPath = validate pkg.drvPath; + }; + }; + + + /* Modify a stdenv so that it produces debug builds; that is, + binaries have debug info, and compiler optimisations are + disabled. */ + keepDebugInfo = stdenv: stdenv // + { mkDerivation = args: stdenv.mkDerivation (args // { + dontStrip = true; + NIX_CFLAGS_COMPILE = toString (args.NIX_CFLAGS_COMPILE or "") + " -ggdb -Og"; + }); + }; + + + /* Modify a stdenv so that it uses the Gold linker. */ + useGoldLinker = stdenv: stdenv // + { mkDerivation = args: stdenv.mkDerivation (args // { + NIX_CFLAGS_LINK = toString (args.NIX_CFLAGS_LINK or "") + " -fuse-ld=gold"; + }); + }; + + + /* Modify a stdenv so that it builds binaries optimized specifically + for the machine they are built on. + + WARNING: this breaks purity! */ + impureUseNativeOptimizations = stdenv: stdenv // + { mkDerivation = args: stdenv.mkDerivation (args // { + NIX_CFLAGS_COMPILE = toString (args.NIX_CFLAGS_COMPILE or "") + " -march=native"; + NIX_ENFORCE_NO_NATIVE = false; + + preferLocalBuild = true; + allowSubstitutes = false; + }); + }; +} diff --git a/nixpkgs/pkgs/stdenv/booter.nix b/nixpkgs/pkgs/stdenv/booter.nix new file mode 100644 index 000000000000..1df05099fbf5 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/booter.nix @@ -0,0 +1,129 @@ +# This file defines a single function for booting a package set from a list of +# stages. The exact mechanics of that function are defined below; here I +# (@Ericson2314) wish to describe the purpose of the abstraction. +# +# The first goal is consistency across stdenvs. Regardless of what this function +# does, by making every stdenv use it for bootstrapping we ensure that they all +# work in a similar way. [Before this abstraction, each stdenv was its own +# special snowflake due to different authors writing in different times.] +# +# The second goal is consistency across each stdenv's stage functions. By +# writing each stage it terms of the previous stage, commonalities between them +# are more easily observable. [Before, there usually was a big attribute set +# with each stage, and stages would access the previous stage by name.] +# +# The third goal is composition. Because each stage is written in terms of the +# previous, the list can be reordered or, more practically, extended with new +# stages. The latter is used for cross compiling and custom +# stdenvs. Additionally, certain options should by default apply only to the +# last stage, whatever it may be. By delaying the creation of stage package sets +# until the final fold, we prevent these options from inhibiting composition. +# +# The fourth and final goal is debugging. Normal packages should only source +# their dependencies from the current stage. But for the sake of debugging, it +# is nice that all packages still remain accessible. We make sure previous +# stages are kept around with a `stdenv.__bootPackges` attribute referring the +# previous stage. It is idiomatic that attributes prefixed with `__` come with +# special restrictions and should not be used under normal circumstances. +{ lib, allPackages }: + +# Type: +# [ pkgset -> (args to stage/default.nix) or ({ __raw = true; } // pkgs) ] +# -> pkgset +# +# In english: This takes a list of function from the previous stage pkgset and +# returns the final pkgset. Each of those functions returns, if `__raw` is +# undefined or false, args for this stage's pkgset (the most complex and +# important arg is the stdenv), or, if `__raw = true`, simply this stage's +# pkgset itself. +# +# The list takes stages in order, so the final stage is last in the list. In +# other words, this does a foldr not foldl. +stageFuns: let + + /* "dfold" a ternary function `op' between successive elements of `list' as if + it was a doubly-linked list with `lnul' and `rnul` base cases at either + end. In precise terms, `dfold op lnul rnul [x_0 x_1 x_2 ... x_n-1]` is the + same as + + let + f_-1 = lnul f_0; + f_0 = op f_-1 x_0 f_1; + f_1 = op f_0 x_1 f_2; + f_2 = op f_1 x_2 f_3; + ... + f_n = op f_n-1 x_n f_n+1; + f_n+1 = rnul f_n; + in + f_0 + */ + dfold = op: lnul: rnul: list: + let + len = builtins.length list; + go = pred: n: + if n == len + then rnul pred + else let + # Note the cycle -- call-by-need ensures finite fold. + cur = op pred (builtins.elemAt list n) succ; + succ = go cur (n + 1); + in cur; + lapp = lnul cur; + cur = go lapp 0; + in cur; + + # Take the list and disallow custom overrides in all but the final stage, + # and allow it in the final flag. Only defaults this boolean field if it + # isn't already set. + withAllowCustomOverrides = lib.lists.imap1 + (index: stageFun: prevStage: + # So true by default for only the first element because one + # 1-indexing. Since we reverse the list, this means this is true + # for the final stage. + { allowCustomOverrides = index == 1; } + // (stageFun prevStage)) + (lib.lists.reverseList stageFuns); + + # Adds the stdenv to the arguments, and sticks in it the previous stage for + # debugging purposes. + folder = nextStage: stageFun: prevStage: let + args = stageFun prevStage; + args' = args // { + stdenv = args.stdenv // { + # For debugging + __bootPackages = prevStage; + __hatPackages = nextStage; + }; + }; + thisStage = + if args.__raw or false + then args' + else allPackages ((builtins.removeAttrs args' ["selfBuild"]) // { + adjacentPackages = if args.selfBuild or true then null else rec { + pkgsBuildBuild = prevStage.buildPackages; + pkgsBuildHost = prevStage; + pkgsBuildTarget = + if args.stdenv.targetPlatform == args.stdenv.hostPlatform + then pkgsBuildHost + else assert args.stdenv.hostPlatform == args.stdenv.buildPlatform; thisStage; + pkgsHostHost = + if args.stdenv.hostPlatform == args.stdenv.targetPlatform + then thisStage + else assert args.stdenv.buildPlatform == args.stdenv.hostPlatform; pkgsBuildHost; + pkgsTargetTarget = nextStage; + }; + }); + in thisStage; + + # This is a hack for resolving cross-compiled compilers' run-time + # deps. (That is, compilers that are themselves cross-compiled, as + # opposed to used to cross-compile packages.) + postStage = buildPackages: { + __raw = true; + stdenv.cc = + if buildPackages.stdenv.cc.isClang or false + then buildPackages.clang + else buildPackages.gcc; + }; + +in dfold folder postStage (_: {}) withAllowCustomOverrides diff --git a/nixpkgs/pkgs/stdenv/common-path.nix b/nixpkgs/pkgs/stdenv/common-path.nix new file mode 100644 index 000000000000..da468d56a2cd --- /dev/null +++ b/nixpkgs/pkgs/stdenv/common-path.nix @@ -0,0 +1,15 @@ +{pkgs}: [ + pkgs.coreutils + pkgs.findutils + pkgs.diffutils + pkgs.gnused + pkgs.gnugrep + pkgs.gawk + pkgs.gnutar + pkgs.gzip + pkgs.bzip2.bin + pkgs.gnumake + pkgs.bash + pkgs.patch + pkgs.xz.bin +] diff --git a/nixpkgs/pkgs/stdenv/cross/default.nix b/nixpkgs/pkgs/stdenv/cross/default.nix new file mode 100644 index 000000000000..4e5c4cc2e833 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/cross/default.nix @@ -0,0 +1,78 @@ +{ lib +, localSystem, crossSystem, config, overlays, crossOverlays ? [] +}: + +let + bootStages = import ../. { + inherit lib localSystem overlays; + + crossSystem = localSystem; + crossOverlays = []; + + # Ignore custom stdenvs when cross compiling for compatability + config = builtins.removeAttrs config [ "replaceStdenv" ]; + }; + +in lib.init bootStages ++ [ + + # Regular native packages + (somePrevStage: lib.last bootStages somePrevStage // { + # It's OK to change the built-time dependencies + allowCustomOverrides = true; + }) + + # Build tool Packages + (vanillaPackages: { + inherit config overlays; + selfBuild = false; + stdenv = + assert vanillaPackages.stdenv.buildPlatform == localSystem; + assert vanillaPackages.stdenv.hostPlatform == localSystem; + assert vanillaPackages.stdenv.targetPlatform == localSystem; + vanillaPackages.stdenv.override { targetPlatform = crossSystem; }; + # It's OK to change the built-time dependencies + allowCustomOverrides = true; + }) + + # Run Packages + (buildPackages: { + inherit config; + overlays = overlays ++ crossOverlays + ++ (if crossSystem.isWasm then [(import ../../top-level/static.nix)] else []); + selfBuild = false; + stdenv = buildPackages.stdenv.override (old: rec { + buildPlatform = localSystem; + hostPlatform = crossSystem; + targetPlatform = crossSystem; + + # Prior overrides are surely not valid as packages built with this run on + # a different platform, and so are disabled. + overrides = _: _: {}; + extraBuildInputs = [ ]; # Old ones run on wrong platform + allowedRequisites = null; + + cc = if crossSystem.useiOSPrebuilt or false + then buildPackages.darwin.iosSdkPkgs.clang + else if crossSystem.useAndroidPrebuilt or false + then buildPackages."androidndkPkgs_${crossSystem.ndkVer}".clang + else if targetPlatform.isGhcjs + then null + else if crossSystem.useLLVM or false + then buildPackages.llvmPackages_8.lldClang + else buildPackages.gcc; + + extraNativeBuildInputs = old.extraNativeBuildInputs + ++ lib.optionals + (hostPlatform.isLinux && !buildPlatform.isLinux) + [ buildPackages.patchelf ] + ++ lib.optional + (let f = p: !p.isx86 || p.libc == "musl" || p.libc == "wasilibc" || p.isiOS; in f hostPlatform && !(f buildPlatform)) + buildPackages.updateAutotoolsGnuConfigScriptsHook + # without proper `file` command, libtool sometimes fails + # to recognize 64-bit DLLs + ++ lib.optional (hostPlatform.config == "x86_64-w64-mingw32") buildPackages.file + ; + }); + }) + +] diff --git a/nixpkgs/pkgs/stdenv/custom/default.nix b/nixpkgs/pkgs/stdenv/custom/default.nix new file mode 100644 index 000000000000..4c7380118f7d --- /dev/null +++ b/nixpkgs/pkgs/stdenv/custom/default.nix @@ -0,0 +1,25 @@ +{ lib +, localSystem, crossSystem, config, overlays, crossOverlays ? [] +}: + +assert crossSystem == localSystem; + +let + bootStages = import ../. { + inherit lib localSystem crossSystem overlays; + # Remove config.replaceStdenv to ensure termination. + config = builtins.removeAttrs config [ "replaceStdenv" ]; + }; + +in bootStages ++ [ + + # Additional stage, built using custom stdenv + (vanillaPackages: { + inherit config overlays; + stdenv = + assert vanillaPackages.hostPlatform == localSystem; + assert vanillaPackages.targetPlatform == localSystem; + config.replaceStdenv { pkgs = vanillaPackages; }; + }) + +] diff --git a/nixpkgs/pkgs/stdenv/cygwin/all-buildinputs-as-runtimedep.sh b/nixpkgs/pkgs/stdenv/cygwin/all-buildinputs-as-runtimedep.sh new file mode 100644 index 000000000000..7cb6a58f180b --- /dev/null +++ b/nixpkgs/pkgs/stdenv/cygwin/all-buildinputs-as-runtimedep.sh @@ -0,0 +1,16 @@ +# On cygwin, automatic runtime dependency detection does not work +# because the binaries do not contain absolute references to store +# locations (yet) +postFixupHooks+=(_cygwinAllBuildInputsAsRuntimeDep) + +_cygwinAllBuildInputsAsRuntimeDep() { + if [ -n "$buildInputs" ]; then + mkdir -p "$out/nix-support" + echo "$buildInputs" >> "$out/nix-support/cygwin-buildinputs-as-runtime-deps" + fi + + if [ -n "$nativeBuildInputs" ]; then + mkdir -p "$out/nix-support" + echo "$nativeBuildInputs" >> "$out/nix-support/cygwin-buildinputs-as-runtime-deps" + fi +} diff --git a/nixpkgs/pkgs/stdenv/cygwin/rebase-i686.sh b/nixpkgs/pkgs/stdenv/cygwin/rebase-i686.sh new file mode 100644 index 000000000000..091c9044d93f --- /dev/null +++ b/nixpkgs/pkgs/stdenv/cygwin/rebase-i686.sh @@ -0,0 +1,24 @@ +fixupOutputHooks+=(_cygwinFixAutoImageBase) + +_cygwinFixAutoImageBase() { + if [ "$dontRebase" == 1 ] || [ ! -d "$prefix" ]; then + return + fi + find "$prefix" -name "*.dll" -type f | while read DLL; do + if [ -f /etc/rebasenix.nextbase ]; then + NEXTBASE="$(</etc/rebasenix.nextbase)" + fi + NEXTBASE=${NEXTBASE:-0x62000000} + + REBASE=(`/bin/rebase -i $DLL`) + BASE=${REBASE[2]} + SIZE=${REBASE[4]} + SKIP=$(((($SIZE>>16)+1)<<16)) + + echo "REBASE FIX: $DLL $BASE -> $NEXTBASE" + /bin/rebase -b $NEXTBASE $DLL + NEXTBASE="0x`printf %x $(($NEXTBASE+$SKIP))`" + + echo $NEXTBASE > /etc/rebasenix.nextbase + done +} diff --git a/nixpkgs/pkgs/stdenv/cygwin/rebase-x86_64.sh b/nixpkgs/pkgs/stdenv/cygwin/rebase-x86_64.sh new file mode 100644 index 000000000000..4c8f8ebd7eb2 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/cygwin/rebase-x86_64.sh @@ -0,0 +1,24 @@ +fixupOutputHooks+=(_cygwinFixAutoImageBase) + +_cygwinFixAutoImageBase() { + if [ "$dontRebase" == 1 ] || [ ! -d "$prefix" ]; then + return + fi + find "$prefix" -name "*.dll" -type f | while read DLL; do + if [ -f /etc/rebasenix.nextbase ]; then + NEXTBASE="$(</etc/rebasenix.nextbase)" + fi + NEXTBASE=${NEXTBASE:-0x200000001} + + REBASE=(`/bin/rebase -i $DLL`) + BASE=${REBASE[2]} + SIZE=${REBASE[4]} + SKIP=$(((($SIZE>>16)+1)<<16)) + + echo "REBASE FIX: $DLL $BASE -> $NEXTBASE" + /bin/rebase -b $NEXTBASE $DLL + NEXTBASE="0x`printf %x $(($NEXTBASE+$SKIP))`" + + echo $NEXTBASE > /etc/rebasenix.nextbase + done +} diff --git a/nixpkgs/pkgs/stdenv/cygwin/wrap-exes-to-find-dlls.sh b/nixpkgs/pkgs/stdenv/cygwin/wrap-exes-to-find-dlls.sh new file mode 100644 index 000000000000..d0da8c1b65c2 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/cygwin/wrap-exes-to-find-dlls.sh @@ -0,0 +1,74 @@ +postFixupHooks+=(_cygwinWrapExesToFindDlls) + +_cygwinWrapExesToFindDlls() { + find $out -type l | while read LINK; do + TARGET="$(readlink "${LINK}")" + + # fix all non .exe links that link explicitly to a .exe + if [[ ${TARGET} == *.exe ]] && [[ ${LINK} != *.exe ]]; then + mv "${LINK}" "${LINK}.exe" + LINK="${LINK}.exe" + fi + + # generate complementary filenames + if [[ ${LINK} == *.exe ]]; then + _LINK="${LINK%.exe}" + _TARGET="${TARGET%.exe}" + else + _LINK="${LINK}.exe" + _TARGET="${TARGET}.exe" + fi + + # check if sould create complementary link + DOLINK=1 + if [[ ${_TARGET} == *.exe ]]; then + # the canonical target has to be a .exe + CTARGET="$(readlink -f "${LINK}")" + if [[ ${CTARGET} != *.exe ]]; then + CTARGET="${CTARGET}.exe" + fi + + if [ ! -e "${CTARGET}" ]; then + unset DOLINK + fi + fi + + if [ -e "${_LINK}" ]; then + # complementary link seems to exist + # but could be cygwin smoke and mirrors + INO=$(stat -c%i "${LINK}") + _INO=$(stat -c%i "${_LINK}") + if [ "${INO}" -ne "${_INO}" ]; then + unset DOLINK + fi + fi + + # create complementary link + if [ -n "${DOLINK}" ]; then + ln -s "${_TARGET}" "${_LINK}.tmp" + mv "${_LINK}.tmp" "${_LINK}" + fi + done + + find $out -type f -name "*.exe" | while read EXE; do + WRAPPER="${EXE%.exe}" + if [ -e "${WRAPPER}" ]; then + # check if really exists or cygwin smoke and mirrors + INO=$(stat -c%i "${EXE}") + _INO=$(stat -c%i "${WRAPPER}") + if [ "${INO}" -ne "${_INO}" ]; then + continue + fi + fi + + mv "${EXE}" "${EXE}.tmp" + + cat >"${WRAPPER}" <<EOF +#!/bin/sh +export PATH=$_PATH${_PATH:+:}\${PATH} +exec "\$0.exe" "\$@" +EOF + chmod +x "${WRAPPER}" + mv "${EXE}.tmp" "${EXE}" + done +} diff --git a/nixpkgs/pkgs/stdenv/darwin/default.nix b/nixpkgs/pkgs/stdenv/darwin/default.nix new file mode 100644 index 000000000000..86a6e33c9424 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/darwin/default.nix @@ -0,0 +1,457 @@ +{ lib +, localSystem, crossSystem, config, overlays, crossOverlays ? [] + +# Allow passing in bootstrap files directly so we can test the stdenv bootstrap process when changing the bootstrap tools +, bootstrapFiles ? let + fetch = { file, sha256, executable ? true }: import <nix/fetchurl.nix> { + url = "http://tarballs.nixos.org/stdenv-darwin/x86_64/d5bdfcbfe6346761a332918a267e82799ec954d2/${file}"; + inherit (localSystem) system; + inherit sha256 executable; + }; in { + sh = fetch { file = "sh"; sha256 = "07wm33f1yzfpcd3rh42f8g096k4cvv7g65p968j28agzmm2s7s8m"; }; + bzip2 = fetch { file = "bzip2"; sha256 = "0y9ri2aprkrp2dkzm6229l0mw4rxr2jy7vvh3d8mxv2698v2kdbm"; }; + mkdir = fetch { file = "mkdir"; sha256 = "0sb07xpy66ws6f2jfnpjibyimzb71al8n8c6y4nr8h50al3g90nr"; }; + cpio = fetch { file = "cpio"; sha256 = "0r5c54hg678w7zydx27bzl9p3v9fs25y5ix6vdfi1ilqim7xh65n"; }; + tarball = fetch { file = "bootstrap-tools.cpio.bz2"; sha256 = "18hp5w6klr8g307ap4368r255qpzg9r0vwg9vqvj8f2zy1xilcjf"; executable = false; }; + } +}: + +assert crossSystem == localSystem; + +let + inherit (localSystem) system platform; + + commonImpureHostDeps = [ + "/bin/sh" + "/usr/lib/libSystem.B.dylib" + "/usr/lib/system/libunc.dylib" # This dependency is "hidden", so our scanning code doesn't pick it up + ]; +in rec { + commonPreHook = '' + export NIX_ENFORCE_PURITY="''${NIX_ENFORCE_PURITY-1}" + export NIX_ENFORCE_NO_NATIVE="''${NIX_ENFORCE_NO_NATIVE-1}" + export NIX_IGNORE_LD_THROUGH_GCC=1 + stripAllFlags=" " # the Darwin "strip" command doesn't know "-s" + export MACOSX_DEPLOYMENT_TARGET=10.12 + export SDKROOT= + export CMAKE_OSX_ARCHITECTURES=x86_64 + # Workaround for https://openradar.appspot.com/22671534 on 10.11. + export gl_cv_func_getcwd_abort_bug=no + ''; + + bootstrapTools = derivation { + inherit system; + + name = "bootstrap-tools"; + builder = bootstrapFiles.sh; # Not a filename! Attribute 'sh' on bootstrapFiles + args = [ ./unpack-bootstrap-tools.sh ]; + + inherit (bootstrapFiles) mkdir bzip2 cpio tarball; + reexportedLibrariesFile = + ../../os-specific/darwin/apple-source-releases/Libsystem/reexported_libraries; + + __impureHostDeps = commonImpureHostDeps; + }; + + stageFun = step: last: {shell ? "${bootstrapTools}/bin/bash", + overrides ? (self: super: {}), + extraPreHook ? "", + extraNativeBuildInputs, + extraBuildInputs, + libcxx, + allowedRequisites ? null}: + let + name = "bootstrap-stage${toString step}"; + + buildPackages = lib.optionalAttrs (last ? stdenv) { + inherit (last) stdenv; + }; + + coreutils = { name = "${name}-coreutils"; outPath = bootstrapTools; }; + gnugrep = { name = "${name}-gnugrep"; outPath = bootstrapTools; }; + + bintools = import ../../build-support/bintools-wrapper { + inherit shell; + inherit (last) stdenvNoCC; + + nativeTools = false; + nativeLibc = false; + inherit buildPackages coreutils gnugrep; + libc = last.pkgs.darwin.Libsystem; + bintools = { name = "${name}-binutils"; outPath = bootstrapTools; }; + }; + + cc = if last == null then "/dev/null" else import ../../build-support/cc-wrapper { + inherit shell; + inherit (last) stdenvNoCC; + + extraPackages = lib.optional (libcxx != null) libcxx; + + nativeTools = false; + nativeLibc = false; + inherit buildPackages coreutils gnugrep bintools; + libc = last.pkgs.darwin.Libsystem; + isClang = true; + cc = { name = "${name}-clang"; outPath = bootstrapTools; }; + }; + + thisStdenv = import ../generic { + name = "${name}-stdenv-darwin"; + + inherit config shell extraNativeBuildInputs extraBuildInputs; + allowedRequisites = if allowedRequisites == null then null else allowedRequisites ++ [ + cc.expand-response-params cc.bintools + ]; + + buildPlatform = localSystem; + hostPlatform = localSystem; + targetPlatform = localSystem; + + inherit cc; + + preHook = lib.optionalString (shell == "${bootstrapTools}/bin/bash") '' + # Don't patch #!/interpreter because it leads to retained + # dependencies on the bootstrapTools in the final stdenv. + dontPatchShebangs=1 + '' + '' + ${commonPreHook} + ${extraPreHook} + ''; + initialPath = [ bootstrapTools ]; + + fetchurlBoot = import ../../build-support/fetchurl { + inherit lib; + stdenvNoCC = stage0.stdenv; + curl = bootstrapTools; + }; + + # The stdenvs themselves don't use mkDerivation, so I need to specify this here + __stdenvImpureHostDeps = commonImpureHostDeps; + __extraImpureHostDeps = commonImpureHostDeps; + + extraAttrs = { + inherit platform; + parent = last; + }; + overrides = self: super: (overrides self super) // { fetchurl = thisStdenv.fetchurlBoot; }; + }; + + in { + inherit config overlays; + stdenv = thisStdenv; + }; + + stage0 = stageFun 0 null { + overrides = self: super: with stage0; { + darwin = super.darwin // { + Libsystem = stdenv.mkDerivation { + name = "bootstrap-stage0-Libsystem"; + buildCommand = '' + mkdir -p $out + ln -s ${bootstrapTools}/lib $out/lib + ln -s ${bootstrapTools}/include-Libsystem $out/include + ''; + }; + dyld = bootstrapTools; + }; + + llvmPackages_7 = { + libcxx = stdenv.mkDerivation { + name = "bootstrap-stage0-libcxx"; + phases = [ "installPhase" "fixupPhase" ]; + installPhase = '' + mkdir -p $out/lib $out/include + ln -s ${bootstrapTools}/lib/libc++.dylib $out/lib/libc++.dylib + ln -s ${bootstrapTools}/include/c++ $out/include/c++ + ''; + linkCxxAbi = false; + setupHook = ../../development/compilers/llvm/3.9/libc++/setup-hook.sh; + }; + + libcxxabi = stdenv.mkDerivation { + name = "bootstrap-stage0-libcxxabi"; + buildCommand = '' + mkdir -p $out/lib + ln -s ${bootstrapTools}/lib/libc++abi.dylib $out/lib/libc++abi.dylib + ''; + }; + }; + }; + + extraNativeBuildInputs = []; + extraBuildInputs = []; + libcxx = null; + }; + + stage1 = prevStage: let + persistent = self: super: with prevStage; { + cmake = super.cmake.override { + isBootstrap = true; + useSharedLibraries = false; + }; + + python = super.callPackage ../../development/interpreters/python/cpython/2.7/boot.nix { + CF = null; # use CoreFoundation from bootstrap-tools + configd = null; + }; + python2 = self.python; + + ninja = super.ninja.override { buildDocs = false; }; + darwin = super.darwin // { + cctools = super.darwin.cctools.override { + enableTapiSupport = false; + }; + }; + }; + in with prevStage; stageFun 1 prevStage { + extraPreHook = "export NIX_CFLAGS_COMPILE+=\" -F${bootstrapTools}/Library/Frameworks\""; + extraNativeBuildInputs = []; + extraBuildInputs = [ ]; + libcxx = pkgs.libcxx; + + allowedRequisites = + [ bootstrapTools ] ++ (with pkgs; [ libcxx libcxxabi ]) ++ [ pkgs.darwin.Libsystem ]; + + overrides = persistent; + }; + + stage2 = prevStage: let + persistent = self: super: with prevStage; { + inherit + zlib patchutils m4 scons flex perl bison unifdef unzip openssl python + libxml2 gettext sharutils gmp libarchive ncurses pkg-config libedit groff + openssh sqlite sed serf openldap db cyrus-sasl expat apr-util subversion xz + findfreetype libssh curl cmake autoconf automake libtool ed cpio coreutils + libssh2 nghttp2 libkrb5 python2 ninja; + + darwin = super.darwin // { + inherit (darwin) + dyld Libsystem xnu configd ICU libdispatch libclosure launchd CF; + }; + }; + in with prevStage; stageFun 2 prevStage { + extraPreHook = '' + export PATH_LOCALE=${pkgs.darwin.locale}/share/locale + ''; + + extraNativeBuildInputs = [ pkgs.xz ]; + extraBuildInputs = [ pkgs.darwin.CF ]; + libcxx = pkgs.libcxx; + + allowedRequisites = + [ bootstrapTools ] ++ + (with pkgs; [ + xz.bin xz.out libcxx libcxxabi zlib libxml2.out curl.out openssl.out libssh2.out + nghttp2.lib libkrb5 + ]) ++ + (with pkgs.darwin; [ dyld Libsystem CF ICU locale ]); + + overrides = persistent; + }; + + stage3 = prevStage: let + persistent = self: super: with prevStage; { + inherit + patchutils m4 scons flex perl bison unifdef unzip openssl python + gettext sharutils libarchive pkg-config groff bash subversion + openssh sqlite sed serf openldap db cyrus-sasl expat apr-util + findfreetype libssh curl cmake autoconf automake libtool cpio + libssh2 nghttp2 libkrb5 python2 ninja; + + # Avoid pulling in a full python and its extra dependencies for the llvm/clang builds. + libxml2 = super.libxml2.override { pythonSupport = false; }; + + llvmPackages_7 = super.llvmPackages_7 // (let + libraries = super.llvmPackages_7.libraries.extend (_: _: { + inherit (llvmPackages_7) libcxx libcxxabi; + }); + in { inherit libraries; } // libraries); + + darwin = super.darwin // { + inherit (darwin) + dyld Libsystem xnu configd libdispatch libclosure launchd libiconv locale; + }; + }; + in with prevStage; stageFun 3 prevStage { + shell = "${pkgs.bash}/bin/bash"; + + # We have a valid shell here (this one has no bootstrap-tools runtime deps) so stageFun + # enables patchShebangs above. Unfortunately, patchShebangs ignores our $SHELL setting + # and instead goes by $PATH, which happens to contain bootstrapTools. So it goes and + # patches our shebangs back to point at bootstrapTools. This makes sure bash comes first. + extraNativeBuildInputs = with pkgs; [ xz ]; + extraBuildInputs = [ pkgs.darwin.CF pkgs.bash ]; + libcxx = pkgs.libcxx; + + extraPreHook = '' + export PATH=${pkgs.bash}/bin:$PATH + export PATH_LOCALE=${pkgs.darwin.locale}/share/locale + ''; + + allowedRequisites = + [ bootstrapTools ] ++ + (with pkgs; [ + xz.bin xz.out bash libcxx libcxxabi zlib libxml2.out curl.out openssl.out libssh2.out + nghttp2.lib libkrb5 + ]) ++ + (with pkgs.darwin; [ dyld ICU Libsystem locale ]); + + overrides = persistent; + }; + + stage4 = prevStage: let + persistent = self: super: with prevStage; { + inherit + gnumake gzip gnused bzip2 gawk ed xz patch bash + ncurses libffi zlib gmp pcre gnugrep + coreutils findutils diffutils patchutils ninja; + + # Hack to make sure we don't link ncurses in bootstrap tools. The proper + # solution is to avoid passing -L/nix-store/...-bootstrap-tools/lib, + # quite a sledgehammer just to get the C runtime. + gettext = super.gettext.overrideAttrs (drv: { + configureFlags = drv.configureFlags ++ [ + "--disable-curses" + ]; + }); + + llvmPackages_7 = super.llvmPackages_7 // (let + tools = super.llvmPackages_7.tools.extend (llvmSelf: _: { + clang-unwrapped = llvmPackages_7.clang-unwrapped.override { llvm = llvmSelf.llvm; }; + llvm = llvmPackages_7.llvm.override { libxml2 = self.darwin.libxml2-nopython; }; + }); + libraries = super.llvmPackages_7.libraries.extend (llvmSelf: _: { + inherit (llvmPackages_7) libcxx libcxxabi compiler-rt; + }); + in { inherit tools libraries; } // tools // libraries); + + darwin = super.darwin // rec { + inherit (darwin) dyld Libsystem libiconv locale; + + cctools = super.darwin.cctools.override { enableTapiSupport = false; }; + libxml2-nopython = super.libxml2.override { pythonSupport = false; }; + CF = super.darwin.CF.override { + libxml2 = libxml2-nopython; + python = prevStage.python; + }; + }; + }; + in with prevStage; stageFun 4 prevStage { + shell = "${pkgs.bash}/bin/bash"; + extraNativeBuildInputs = with pkgs; [ xz ]; + extraBuildInputs = [ pkgs.darwin.CF pkgs.bash ]; + libcxx = pkgs.libcxx; + + extraPreHook = '' + export PATH_LOCALE=${pkgs.darwin.locale}/share/locale + ''; + overrides = persistent; + }; + + stdenvDarwin = prevStage: let + pkgs = prevStage; + persistent = self: super: with prevStage; { + inherit + gnumake gzip gnused bzip2 gawk ed xz patch bash + ncurses libffi zlib llvm gmp pcre gnugrep + coreutils findutils diffutils patchutils; + + llvmPackages_7 = super.llvmPackages_7 // (let + tools = super.llvmPackages_7.tools.extend (_: super: { + inherit (llvmPackages_7) llvm clang-unwrapped; + }); + libraries = super.llvmPackages_7.libraries.extend (_: _: { + inherit (llvmPackages_7) compiler-rt libcxx libcxxabi; + }); + in { inherit tools libraries; } // tools // libraries); + + # N.B: the important thing here is to ensure that python == python2 + # == python27 or you get weird issues with inconsistent package sets. + # In a particularly subtle bug, I overrode python2 instead of python27 + # here, and it caused gnome-doc-utils to complain about: + # "PyThreadState_Get: no current thread". This is because Python gets + # really unhappy if you have Python A which loads a native python lib + # which was linked against Python B, which in our case was happening + # because we didn't override python "deeply enough". Anyway, this works + # and I'm just leaving this blurb here so people realize why it matters + python27 = super.python27.override { CF = prevStage.darwin.CF; }; + + darwin = super.darwin // { + inherit (darwin) dyld ICU Libsystem libiconv; + } // lib.optionalAttrs (super.stdenv.targetPlatform == localSystem) { + inherit (darwin) binutils binutils-unwrapped cctools; + }; + } // lib.optionalAttrs (super.stdenv.targetPlatform == localSystem) { + # Need to get rid of these when cross-compiling. + inherit binutils binutils-unwrapped; + }; + in import ../generic rec { + name = "stdenv-darwin"; + + inherit config; + inherit (pkgs.stdenv) fetchurlBoot; + + buildPlatform = localSystem; + hostPlatform = localSystem; + targetPlatform = localSystem; + + preHook = commonPreHook + '' + export NIX_COREFOUNDATION_RPATH=${pkgs.darwin.CF}/Library/Frameworks + export PATH_LOCALE=${pkgs.darwin.locale}/share/locale + ''; + + __stdenvImpureHostDeps = commonImpureHostDeps; + __extraImpureHostDeps = commonImpureHostDeps; + + initialPath = import ../common-path.nix { inherit pkgs; }; + shell = "${pkgs.bash}/bin/bash"; + + cc = pkgs.llvmPackages.libcxxClang.override { + cc = pkgs.llvmPackages.clang-unwrapped; + }; + + extraNativeBuildInputs = []; + extraBuildInputs = [ pkgs.darwin.CF ]; + + extraAttrs = { + inherit platform bootstrapTools; + libc = pkgs.darwin.Libsystem; + shellPackage = pkgs.bash; + }; + + allowedRequisites = (with pkgs; [ + xz.out xz.bin libcxx libcxxabi gmp.out gnumake findutils bzip2.out + bzip2.bin llvmPackages.llvm llvmPackages.llvm.lib llvmPackages.compiler-rt llvmPackages.compiler-rt.dev + zlib.out zlib.dev libffi.out coreutils ed diffutils gnutar + gzip ncurses.out ncurses.dev ncurses.man gnused bash gawk + gnugrep llvmPackages.clang-unwrapped llvmPackages.clang-unwrapped.lib patch pcre.out gettext + binutils.bintools darwin.binutils darwin.binutils.bintools + curl.out openssl.out libssh2.out nghttp2.lib libkrb5 + cc.expand-response-params + ]) ++ (with pkgs.darwin; [ + dyld Libsystem CF cctools ICU libiconv locale libxml2-nopython.out + ]); + + overrides = lib.composeExtensions persistent (self: super: { + clang = cc; + llvmPackages = super.llvmPackages // { clang = cc; }; + inherit cc; + + darwin = super.darwin // { + xnu = super.darwin.xnu.override { python = super.python.override { configd = null; }; }; + }; + }); + }; + + stagesDarwin = [ + ({}: stage0) + stage1 + stage2 + stage3 + stage4 + (prevStage: { + inherit config overlays; + stdenv = stdenvDarwin prevStage; + }) + ]; +} diff --git a/nixpkgs/pkgs/stdenv/darwin/make-bootstrap-tools.nix b/nixpkgs/pkgs/stdenv/darwin/make-bootstrap-tools.nix new file mode 100644 index 000000000000..a299879693c8 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/darwin/make-bootstrap-tools.nix @@ -0,0 +1,350 @@ +{ pkgspath ? ../../.., test-pkgspath ? pkgspath, system ? builtins.currentSystem }: + +with import pkgspath { inherit system; }; + +let + llvmPackages = llvmPackages_7; +in rec { + coreutils_ = coreutils.override (args: { + # We want coreutils without ACL support. + aclSupport = false; + # Cannot use a single binary build, or it gets dynamically linked against gmp. + singleBinary = false; + }); + + cctools_ = darwin.cctools; + + # Avoid debugging larger changes for now. + bzip2_ = bzip2.override (args: { linkStatic = true; }); + + # Avoid messing with libkrb5 and libnghttp2. + curl_ = curl.override (args: { gssSupport = false; http2Support = false; }); + + build = stdenv.mkDerivation { + name = "stdenv-bootstrap-tools"; + + buildInputs = [nukeReferences cpio]; + + buildCommand = '' + mkdir -p $out/bin $out/lib $out/lib/system + + # We're not going to bundle the actual libSystem.dylib; instead we reconstruct it on + # the other side. See the notes in stdenv/darwin/default.nix for more information. + # We also need the .o files for various low-level boot stuff. + cp -d ${darwin.Libsystem}/lib/*.o $out/lib + cp -d ${darwin.Libsystem}/lib/system/*.dylib $out/lib/system + + # Resolv is actually a link to another package, so let's copy it properly + cp -L ${darwin.Libsystem}/lib/libresolv.9.dylib $out/lib + + cp -rL ${darwin.Libsystem}/include $out + chmod -R u+w $out/include + cp -rL ${darwin.ICU}/include* $out/include + cp -rL ${libiconv}/include/* $out/include + cp -rL ${gnugrep.pcre.dev}/include/* $out/include + mv $out/include $out/include-Libsystem + + # Copy coreutils, bash, etc. + cp ${coreutils_}/bin/* $out/bin + (cd $out/bin && rm vdir dir sha*sum pinky factor pathchk runcon shuf who whoami shred users) + + cp ${bash}/bin/bash $out/bin + cp ${findutils}/bin/find $out/bin + cp ${findutils}/bin/xargs $out/bin + cp -d ${diffutils}/bin/* $out/bin + cp -d ${gnused}/bin/* $out/bin + cp -d ${gnugrep}/bin/grep $out/bin + cp ${gawk}/bin/gawk $out/bin + cp -d ${gawk}/bin/awk $out/bin + cp ${gnutar}/bin/tar $out/bin + cp ${gzip}/bin/gzip $out/bin + cp ${bzip2_.bin}/bin/bzip2 $out/bin + cp -d ${gnumake}/bin/* $out/bin + cp -d ${patch}/bin/* $out/bin + cp -d ${xz.bin}/bin/xz $out/bin + + # This used to be in-nixpkgs, but now is in the bundle + # because I can't be bothered to make it partially static + cp ${curl_.bin}/bin/curl $out/bin + cp -d ${curl_.out}/lib/libcurl*.dylib $out/lib + cp -d ${libssh2.out}/lib/libssh*.dylib $out/lib + cp -d ${openssl.out}/lib/*.dylib $out/lib + + cp -d ${gnugrep.pcre.out}/lib/libpcre*.dylib $out/lib + cp -d ${lib.getLib libiconv}/lib/lib*.dylib $out/lib + cp -d ${gettext}/lib/libintl*.dylib $out/lib + chmod +x $out/lib/libintl*.dylib + cp -d ${ncurses.out}/lib/libncurses*.dylib $out/lib + cp -d ${libxml2.out}/lib/libxml2*.dylib $out/lib + + # Copy what we need of clang + cp -d ${llvmPackages.clang-unwrapped}/bin/clang* $out/bin + + cp -rL ${llvmPackages.clang-unwrapped}/lib/clang $out/lib + + cp -d ${llvmPackages.libcxx}/lib/libc++*.dylib $out/lib + cp -d ${llvmPackages.libcxxabi}/lib/libc++abi*.dylib $out/lib + cp -d ${llvmPackages.llvm.lib}/lib/libLLVM.dylib $out/lib + cp -d ${libffi}/lib/libffi*.dylib $out/lib + + mkdir $out/include + cp -rd ${llvmPackages.libcxx}/include/c++ $out/include + + cp -d ${darwin.ICU}/lib/libicu*.dylib $out/lib + cp -d ${zlib.out}/lib/libz.* $out/lib + cp -d ${gmpxx.out}/lib/libgmp*.* $out/lib + cp -d ${xz.out}/lib/liblzma*.* $out/lib + + # Copy binutils. + for i in as ld ar ranlib nm strip otool install_name_tool lipo; do + cp ${cctools_}/bin/$i $out/bin + done + + cp -rd ${pkgs.darwin.CF}/Library $out + + chmod -R u+w $out + + nuke-refs $out/bin/* + + rpathify() { + local libs=$(${cctools_}/bin/otool -L "$1" | tail -n +2 | grep -o "$NIX_STORE.*-\S*") || true + for lib in $libs; do + ${cctools_}/bin/install_name_tool -change $lib "@rpath/$(basename $lib)" "$1" + done + } + + # Strip executables even further + for i in $out/bin/*; do + if test -x $i -a ! -L $i; then + chmod +w $i + strip $i || true + fi + done + + for i in $out/bin/* $out/lib/*.dylib $out/lib/clang/*/lib/darwin/*.dylib $out/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation; do + if test -x "$i" -a ! -L "$i"; then + echo "Adding rpath to $i" + rpathify $i + fi + done + + nuke-refs $out/lib/* + nuke-refs $out/lib/system/* + nuke-refs $out/lib/clang/*/lib/darwin/* + nuke-refs $out/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation + + mkdir $out/.pack + mv $out/* $out/.pack + mv $out/.pack $out/pack + + mkdir $out/on-server + cp ${stdenv.shell} $out/on-server/sh + cp ${cpio}/bin/cpio $out/on-server + cp ${coreutils_}/bin/mkdir $out/on-server + cp ${bzip2_.bin}/bin/bzip2 $out/on-server + + chmod u+w $out/on-server/* + strip $out/on-server/* + nuke-refs $out/on-server/* + + (cd $out/pack && (find | cpio -o -H newc)) | bzip2 > $out/on-server/bootstrap-tools.cpio.bz2 + ''; + + allowedReferences = []; + + meta = { + maintainers = [ stdenv.lib.maintainers.copumpkin ]; + }; + }; + + dist = stdenv.mkDerivation { + name = "stdenv-bootstrap-tools"; + + buildCommand = '' + mkdir -p $out/nix-support + echo "file tarball ${build}/on-server/bootstrap-tools.cpio.bz2" >> $out/nix-support/hydra-build-products + echo "file sh ${build}/on-server/sh" >> $out/nix-support/hydra-build-products + echo "file cpio ${build}/on-server/cpio" >> $out/nix-support/hydra-build-products + echo "file mkdir ${build}/on-server/mkdir" >> $out/nix-support/hydra-build-products + echo "file bzip2 ${build}/on-server/bzip2" >> $out/nix-support/hydra-build-products + ''; + }; + + bootstrapFiles = { + sh = "${build}/on-server/sh"; + bzip2 = "${build}/on-server/bzip2"; + mkdir = "${build}/on-server/mkdir"; + cpio = "${build}/on-server/cpio"; + tarball = "${build}/on-server/bootstrap-tools.cpio.bz2"; + }; + + unpack = stdenv.mkDerivation (bootstrapFiles // { + name = "unpack"; + + reexportedLibrariesFile = + ../../os-specific/darwin/apple-source-releases/Libsystem/reexported_libraries; + + # This is by necessity a near-duplicate of unpack-bootstrap-tools.sh. If we refer to it directly, + # we can't make any changes to it due to our testing stdenv depending on it. Think of this as the + # unpack-bootstrap-tools.sh for the next round of bootstrap tools. + # TODO: think through alternate designs, such as hosting this script as an output of the process. + buildCommand = '' + # Unpack the bootstrap tools tarball. + echo Unpacking the bootstrap tools... + $mkdir $out + $bzip2 -d < $tarball | (cd $out && $cpio -i) + + # Set the ELF interpreter / RPATH in the bootstrap binaries. + echo Patching the tools... + + export PATH=$out/bin + + for i in $out/bin/*; do + if ! test -L $i; then + echo patching $i + install_name_tool -add_rpath $out/lib $i || true + fi + done + + install_name_tool \ + -id $out/lib/system/libsystem_c.dylib \ + $out/lib/system/libsystem_c.dylib + + install_name_tool \ + -id $out/lib/system/libsystem_kernel.dylib \ + $out/lib/system/libsystem_kernel.dylib + + # TODO: this logic basically duplicates similar logic in the Libsystem expression. Deduplicate them! + libs=$(cat $reexportedLibrariesFile | grep -v '^#') + + for i in $libs; do + if [ "$i" != "/usr/lib/system/libsystem_kernel.dylib" ] && [ "$i" != "/usr/lib/system/libsystem_c.dylib" ]; then + args="$args -reexport_library $i" + fi + done + + ld -macosx_version_min 10.7 \ + -arch x86_64 \ + -dylib \ + -o $out/lib/libSystem.B.dylib \ + -compatibility_version 1.0 \ + -current_version 1226.10.1 \ + -reexport_library $out/lib/system/libsystem_c.dylib \ + -reexport_library $out/lib/system/libsystem_kernel.dylib \ + $args + + ln -s libSystem.B.dylib $out/lib/libSystem.dylib + + for name in c dbm dl info m mx poll proc pthread rpcsvc util gcc_s.10.4 gcc_s.10.5; do + ln -s libSystem.dylib $out/lib/lib$name.dylib + done + + ln -s libresolv.9.dylib $out/lib/libresolv.dylib + + for i in $out/lib/*.dylib $out/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation; do + if test ! -L "$i" -a "$i" != "$out/lib/libSystem*.dylib"; then + echo "Patching $i" + + id=$(otool -D "$i" | tail -n 1) + install_name_tool -id "$(dirname $i)/$(basename $id)" $i + + libs=$(otool -L "$i" | tail -n +2 | grep -v libSystem | cat) + if [ -n "$libs" ]; then + install_name_tool -add_rpath $out/lib $i + fi + fi + done + + ln -s bash $out/bin/sh + ln -s bzip2 $out/bin/bunzip2 + + # Provide a gunzip script. + cat > $out/bin/gunzip <<EOF + #!$out/bin/sh + exec $out/bin/gzip -d "\$@" + EOF + chmod +x $out/bin/gunzip + + # Provide fgrep/egrep. + echo "#! $out/bin/sh" > $out/bin/egrep + echo "exec $out/bin/grep -E \"\$@\"" >> $out/bin/egrep + echo "#! $out/bin/sh" > $out/bin/fgrep + echo "exec $out/bin/grep -F \"\$@\"" >> $out/bin/fgrep + + cat >$out/bin/dsymutil << EOF + #!$out/bin/sh + EOF + + chmod +x $out/bin/egrep $out/bin/fgrep $out/bin/dsymutil + ''; + + allowedReferences = [ "out" ]; + }); + + test = stdenv.mkDerivation { + name = "test"; + + realBuilder = "${unpack}/bin/bash"; + + buildCommand = '' + export PATH=${unpack}/bin + ls -l + mkdir $out + mkdir $out/bin + sed --version + find --version + diff --version + patch --version + make --version + awk --version + grep --version + clang --version + xz --version + + # The grep will return a nonzero exit code if there is no match, and we want to assert that we have + # an SSL-capable curl + curl --version | grep SSL + + ${build}/on-server/sh -c 'echo Hello World' + + export flags="-idirafter ${unpack}/include-Libsystem --sysroot=${unpack} -L${unpack}/lib" + + export CPP="clang -E $flags" + export CC="clang $flags -Wl,-rpath,${unpack}/lib -Wl,-v -Wl,-sdk_version,10.10" + export CXX="clang++ $flags --stdlib=libc++ -lc++abi -isystem${unpack}/include/c++/v1 -Wl,-rpath,${unpack}/lib -Wl,-v -Wl,-sdk_version,10.10" + + echo '#include <stdio.h>' >> foo.c + echo '#include <float.h>' >> foo.c + echo '#include <limits.h>' >> foo.c + echo 'int main() { printf("Hello World\n"); return 0; }' >> foo.c + $CC -o $out/bin/foo foo.c + $out/bin/foo + + echo '#include <CoreFoundation/CoreFoundation.h>' >> bar.c + echo 'int main() { CFShow(CFSTR("Hullo")); return 0; }' >> bar.c + $CC -F${unpack}/Library/Frameworks -framework CoreFoundation -o $out/bin/bar bar.c + $out/bin/bar + + echo '#include <iostream>' >> bar.cc + echo 'int main() { std::cout << "Hello World\n"; }' >> bar.cc + $CXX -v -o $out/bin/bar bar.cc + $out/bin/bar + + tar xvf ${hello.src} + cd hello-* + ./configure --prefix=$out + make + make install + + $out/bin/hello + ''; + }; + + # The ultimate test: bootstrap a whole stdenv from the tools specified above and get a package set out of it + test-pkgs = import test-pkgspath { + inherit system; + stdenvStages = args: let + args' = args // { inherit bootstrapFiles; }; + in (import (test-pkgspath + "/pkgs/stdenv/darwin") args').stagesDarwin; + }; +} diff --git a/nixpkgs/pkgs/stdenv/darwin/portable-libsystem.sh b/nixpkgs/pkgs/stdenv/darwin/portable-libsystem.sh new file mode 100644 index 000000000000..f50ccc8d32ee --- /dev/null +++ b/nixpkgs/pkgs/stdenv/darwin/portable-libsystem.sh @@ -0,0 +1,12 @@ +# Make /nix/store/...-libSystem “portable” for static built binaries. +# This just rewrites everything in $1/bin to use the +# /usr/lib/libSystem.B.dylib that is provided on every macOS system. + +fixupOutputHooks+=('fixLibsystemRefs $prefix') + +fixLibsystemRefs() { + if [ -d "$1/bin" ]; then + find "$1/bin" -exec \ + install_name_tool -change @libsystem@ /usr/lib/libSystem.B.dylib {} \; + fi +} diff --git a/nixpkgs/pkgs/stdenv/darwin/unpack-bootstrap-tools.sh b/nixpkgs/pkgs/stdenv/darwin/unpack-bootstrap-tools.sh new file mode 100644 index 000000000000..0da80ec5ce56 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/darwin/unpack-bootstrap-tools.sh @@ -0,0 +1,89 @@ +set -e + +# Unpack the bootstrap tools tarball. +echo Unpacking the bootstrap tools... +$mkdir $out +$bzip2 -d < $tarball | (cd $out && $cpio -i) + +# Set the ELF interpreter / RPATH in the bootstrap binaries. +echo Patching the tools... + +export PATH=$out/bin + +for i in $out/bin/*; do + if ! test -L $i; then + echo patching $i + install_name_tool -add_rpath $out/lib $i || true + fi +done + +install_name_tool \ + -id $out/lib/system/libsystem_c.dylib \ + $out/lib/system/libsystem_c.dylib + +install_name_tool \ + -id $out/lib/system/libsystem_kernel.dylib \ + $out/lib/system/libsystem_kernel.dylib + +# TODO: this logic basically duplicates similar logic in the Libsystem expression. Deduplicate them! +libs=$(cat $reexportedLibrariesFile | grep -v '^#') + +for i in $libs; do + if [ "$i" != "/usr/lib/system/libsystem_kernel.dylib" ] && [ "$i" != "/usr/lib/system/libsystem_c.dylib" ]; then + args="$args -reexport_library $i" + fi +done + +ld -macosx_version_min 10.7 \ + -arch x86_64 \ + -dylib \ + -o $out/lib/libSystem.B.dylib \ + -compatibility_version 1.0 \ + -current_version 1226.10.1 \ + -reexport_library $out/lib/system/libsystem_c.dylib \ + -reexport_library $out/lib/system/libsystem_kernel.dylib \ + $args + +ln -s libSystem.B.dylib $out/lib/libSystem.dylib + +for name in c dbm dl info m mx poll proc pthread rpcsvc util gcc_s.10.4 gcc_s.10.5; do + ln -s libSystem.dylib $out/lib/lib$name.dylib +done + +ln -s libresolv.9.dylib $out/lib/libresolv.dylib + +for i in $out/lib/*.dylib $out/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation; do + if test ! -L "$i" -a "$i" != "$out/lib/libSystem*.dylib"; then + echo "Patching $i" + + id=$(otool -D "$i" | tail -n 1) + install_name_tool -id "$(dirname $i)/$(basename $id)" $i + + libs=$(otool -L "$i" | tail -n +2 | grep -v libSystem | cat) + if [ -n "$libs" ]; then + install_name_tool -add_rpath $out/lib $i + fi + fi +done + +ln -s bash $out/bin/sh +ln -s bzip2 $out/bin/bunzip2 + +# Provide a gunzip script. +cat > $out/bin/gunzip <<EOF +#!$out/bin/sh +exec $out/bin/gzip -d "\$@" +EOF +chmod +x $out/bin/gunzip + +# Provide fgrep/egrep. +echo "#! $out/bin/sh" > $out/bin/egrep +echo "exec $out/bin/grep -E \"\$@\"" >> $out/bin/egrep +echo "#! $out/bin/sh" > $out/bin/fgrep +echo "exec $out/bin/grep -F \"\$@\"" >> $out/bin/fgrep + +cat >$out/bin/dsymutil << EOF +#!$out/bin/sh +EOF + +chmod +x $out/bin/egrep $out/bin/fgrep $out/bin/dsymutil diff --git a/nixpkgs/pkgs/stdenv/default.nix b/nixpkgs/pkgs/stdenv/default.nix new file mode 100644 index 000000000000..b0db1be5f446 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/default.nix @@ -0,0 +1,63 @@ +# This file chooses a sane default stdenv given the system, platform, etc. +# +# Rather than returning a stdenv, this returns a list of functions---one per +# each bootstrapping stage. See `./booter.nix` for exactly what this list should +# contain. + +{ # Args just for stdenvs' usage + lib + # Args to pass on to the pkgset builder, too +, localSystem, crossSystem, config, overlays, crossOverlays ? [] +} @ args: + +let + # The native (i.e., impure) build environment. This one uses the + # tools installed on the system outside of the Nix environment, + # i.e., the stuff in /bin, /usr/bin, etc. This environment should + # be used with care, since many Nix packages will not build properly + # with it (e.g., because they require GNU Make). + stagesNative = import ./native args; + + # The Nix build environment. + stagesNix = import ./nix (args // { bootStages = stagesNative; }); + + stagesFreeBSD = import ./freebsd args; + + # On Linux systems, the standard build environment consists of Nix-built + # instances glibc and the `standard' Unix tools, i.e., the Posix utilities, + # the GNU C compiler, and so on. + stagesLinux = import ./linux args; + + inherit (import ./darwin args) stagesDarwin; + + stagesCross = import ./cross args; + + stagesCustom = import ./custom args; + + # Select the appropriate stages for the platform `system'. +in + if crossSystem != localSystem || crossOverlays != [] then stagesCross + else if config ? replaceStdenv then stagesCustom + else { # switch + i686-linux = stagesLinux; + x86_64-linux = stagesLinux; + armv5tel-linux = stagesLinux; + armv6l-linux = stagesLinux; + armv6m-linux = stagesLinux; + armv7a-linux = stagesLinux; + armv7l-linux = stagesLinux; + armv7r-linux = stagesLinux; + armv7m-linux = stagesLinux; + armv8a-linux = stagesLinux; + armv8r-linux = stagesLinux; + armv8m-linux = stagesLinux; + aarch64-linux = stagesLinux; + mipsel-linux = stagesLinux; + powerpc-linux = /* stagesLinux */ stagesNative; + powerpc64le-linux = stagesLinux; + x86_64-darwin = stagesDarwin; + x86_64-solaris = stagesNix; + i686-cygwin = stagesNative; + x86_64-cygwin = stagesNative; + x86_64-freebsd = stagesFreeBSD; + }.${localSystem.system} or stagesNative diff --git a/nixpkgs/pkgs/stdenv/freebsd/default.nix b/nixpkgs/pkgs/stdenv/freebsd/default.nix new file mode 100644 index 000000000000..dbb4a0564558 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/freebsd/default.nix @@ -0,0 +1,94 @@ +{ lib +, localSystem, crossSystem, config, overlays +}: + +assert crossSystem == localSystem; +let inherit (localSystem) system; in + + +[ + + ({}: { + __raw = true; + + bootstrapTools = derivation { + inherit system; + + name = "trivial-bootstrap-tools"; + builder = "/usr/local/bin/bash"; + args = [ ./trivial-bootstrap.sh ]; + + mkdir = "/bin/mkdir"; + ln = "/bin/ln"; + }; + }) + + ({ bootstrapTools, ... }: rec { + __raw = true; + + inherit bootstrapTools; + + fetchurl = import ../../build-support/fetchurl { + inherit lib; + stdenvNoCC = stdenv; + curl = bootstrapTools; + }; + + stdenv = import ../generic { + name = "stdenv-freebsd-boot-1"; + buildPlatform = localSystem; + hostPlatform = localSystem; + targetPlatform = localSystem; + inherit config; + initialPath = [ "/" "/usr" ]; + shell = "${bootstrapTools}/bin/bash"; + fetchurlBoot = null; + cc = null; + overrides = self: super: { + }; + }; + }) + + (prevStage: { + __raw = true; + + stdenv = import ../generic { + name = "stdenv-freebsd-boot-0"; + inherit config; + initialPath = [ prevStage.bootstrapTools ]; + inherit (prevStage.stdenv) + buildPlatform hostPlatform targetPlatform + shell; + fetchurlBoot = prevStage.fetchurl; + cc = null; + }; + }) + + (prevStage: { + inherit config overlays; + stdenv = import ../generic { + name = "stdenv-freebsd-boot-3"; + inherit config; + + inherit (prevStage.stdenv) + buildPlatform hostPlatform targetPlatform + initialPath shell fetchurlBoot; + + cc = import ../../build-support/cc-wrapper { + nativeTools = true; + nativePrefix = "/usr"; + nativeLibc = true; + stdenvNoCC = prevStage.stdenv; + cc = { + name = "clang-9.9.9"; + cc = "/usr"; + outPath = "/usr"; + }; + isClang = true; + }; + + preHook = ''export NIX_NO_SELF_RPATH=1''; + }; + }) + +] diff --git a/nixpkgs/pkgs/stdenv/freebsd/trivial-bootstrap.sh b/nixpkgs/pkgs/stdenv/freebsd/trivial-bootstrap.sh new file mode 100644 index 000000000000..fbff4575e5a4 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/freebsd/trivial-bootstrap.sh @@ -0,0 +1,204 @@ +set -e +set -o nounset +set -o pipefail + +echo Building the trivial bootstrap environment... +echo +echo Needed FreeBSD packages: +echo findutils gcpio gawk gnugrep coreutils bash gsed gtar gmake xar binutils gpatch lbzip2 diffutils + +$mkdir -p $out/bin + +ln () { + if [ ! -z "${2:-}" ]; then + if [ -f "$out/bin/$2" ]; then + echo "$2 exists" + exit 1 + fi + fi + if test ! -f "$1"; then + echo Target "$2" does not exist + exit 1 + fi + # TODO: check that destination directory exists + if [ ! -z "${2:-}" ]; then + $ln -s "$1" "$out/bin/$2" + else + $ln -s "$1" "$out/bin/" + fi +} + +ln /usr/local/bin/bash +ln /bin/sh + +ln /usr/local/bin/gmake make + +ln /usr/local/bin/lbzip2 + +ln /usr/local/bin/gdiff diff + +ln /usr/bin/locale + +ln /usr/bin/more + +ln /usr/bin/hexdump # for bitcoin + +ln /usr/bin/bzip2 +ln /usr/bin/bunzip2 +ln /usr/bin/bzcat +ln /usr/bin/bzip2recover + +ln /usr/bin/xz +ln /usr/bin/unxz +ln /usr/bin/xzcat +ln /usr/bin/lzma +ln /usr/bin/unlzma +ln /usr/bin/lzcat + +ln /usr/local/bin/gcp cp +ln /usr/local/bin/gdd dd +ln /usr/local/bin/gmv mv +ln /usr/local/bin/grm rm +ln /usr/local/bin/gls ls +ln /bin/ps ps +ln /usr/local/bin/gcat cat +ln /usr/local/bin/gecho echo +ln /usr/local/bin/gexpr expr +ln /usr/local/bin/gtest test +ln /usr/local/bin/gdate date +ln /usr/local/bin/gchmod chmod +ln /usr/local/bin/grmdir rmdir +ln /usr/local/bin/gsleep sleep +ln /bin/hostname hostname + +ln /usr/local/bin/gid id +ln /usr/local/bin/god od +ln /usr/local/bin/gtr tr +ln /usr/local/bin/gwc wc +ln /usr/local/bin/gcut cut +ln /usr/bin/cmp cmp +ln /usr/local/bin/gsed sed +ln /usr/local/bin/gtar tar +ln /usr/local/bin/xar xar +ln /usr/local/bin/gawk awk +ln /usr/local/bin/genv env +ln /usr/local/bin/gtee tee +ln /usr/local/bin/gcomm comm +ln /usr/local/bin/gcpio cpio +ln /usr/local/bin/curl curl +ln /usr/local/bin/gfind find +ln /usr/local/bin/grep grep # other grep is in /usr/bin +ln /usr/bin/gzip +ln /usr/bin/gunzip +ln /usr/bin/zcat +ln /usr/local/bin/ghead head +ln /usr/bin/tail tail # note that we are not using gtail!!! +ln /usr/local/bin/guniq uniq +ln /usr/bin/less less +ln /usr/local/bin/gtrue true +# ln /usr/bin/diff diff # we are using gdiff (see above) +ln /usr/local/bin/egrep egrep +ln /usr/local/bin/fgrep fgrep +ln /usr/local/bin/gpatch patch +ln /usr/local/bin/guname uname +ln /usr/local/bin/gtouch touch +ln /usr/local/bin/gsplit split +ln /usr/local/bin/gxargs xargs +ln /usr/bin/which which +ln /usr/local/bin/ginstall install +ln /usr/local/bin/gbasename basename +ln /usr/local/bin/gdirname dirname +ln /usr/local/bin/greadlink readlink + +ln /usr/local/bin/gln ln +ln /usr/local/bin/gyes yes +ln /usr/local/bin/gwhoami whoami +ln /usr/local/bin/gvdir vdir +ln /usr/local/bin/gusers users +ln /usr/local/bin/guptime uptime +ln /usr/local/bin/gunlink unlink +ln /usr/local/bin/gtty tty +ln /usr/local/bin/gunexpand unexpand +ln /usr/local/bin/gtsort tsort +ln /usr/local/bin/gtruncate truncate +ln /usr/local/bin/gtimeout timeout +ln /usr/local/bin/gtac tac +ln /usr/local/bin/gsync sync +ln /usr/local/bin/gsum sum +ln /usr/local/bin/gstty stty +ln /usr/local/bin/gstdbuf stdbuf +ln /usr/local/bin/gsort sort +ln /usr/local/bin/gruncon runcon +ln /usr/local/bin/gseq seq +ln /usr/local/bin/gsha1sum sha1sum +ln /usr/local/bin/gsha224sum sha224sum +ln /usr/local/bin/gsha256sum sha256sum +ln /usr/local/bin/gsha384sum sha384sum +ln /usr/local/bin/gsha512sum sha512sum +ln /usr/local/bin/gshred shred +ln /usr/local/bin/gshuf shuf +ln /usr/local/bin/grealpath realpath +ln "/usr/local/bin/g[" "[" +ln /usr/local/bin/gbase64 base64 +ln /usr/local/bin/gchcon chcon +ln /usr/local/bin/gchgrp chgrp +ln /usr/local/bin/gchown chown +ln /usr/local/bin/gchroot chroot +ln /usr/local/bin/gcksum cksum +ln /usr/local/bin/gcsplit csplit +ln /usr/local/bin/gdf df +ln /usr/local/bin/gdircolors dircolors +ln /usr/local/bin/gdu du +ln /usr/local/bin/gexpand expand +ln /usr/local/bin/gfactor factor +ln /usr/local/bin/gfalse false +ln /usr/local/bin/gfmt fmt +ln /usr/local/bin/gfold fold +ln /usr/local/bin/ggroups groups +ln /usr/local/bin/ghostid hostid +ln /usr/local/bin/gjoin join +ln /usr/local/bin/gkill kill +ln /usr/local/bin/glink link +ln /usr/local/bin/glogname logname +ln /usr/local/bin/gmd5sum md5sum +ln /usr/local/bin/gmkdir mkdir +ln /usr/local/bin/gmkfifo mkfifo +ln /usr/local/bin/gmknod mknod +ln /usr/local/bin/gmktemp mktemp +ln /usr/local/bin/gnice nice +ln /usr/local/bin/gnl nl +ln /usr/local/bin/gnohup nohup +ln /usr/local/bin/gnproc nproc +ln /usr/local/bin/gnumfmt numfmt +ln /usr/local/bin/gnustat nustat +ln /usr/local/bin/gpaste paste +ln /usr/local/bin/gpathchk pathchk +ln /usr/local/bin/gpinky pinky +ln /usr/local/bin/gpr pr +ln /usr/local/bin/gprintenv printenv +ln /usr/local/bin/gprintf printf +ln /usr/local/bin/gptx ptx +ln /usr/local/bin/gpwd pwd + +# binutils +# pkg info -l binutils | grep usr/local/bin +ln /usr/local/bin/addr2line +ln /usr/local/bin/ar +ln /usr/local/bin/as +ln /usr/local/bin/c++filt +ln /usr/local/bin/dwp +ln /usr/local/bin/elfedit +ln /usr/local/bin/gprof +ln /usr/local/bin/ld +ln /usr/local/bin/ld.bfd +ln /usr/local/bin/ld.gold +ln /usr/local/bin/nm +ln /usr/local/bin/objcopy +ln /usr/local/bin/objdump +ln /usr/local/bin/ranlib +ln /usr/local/bin/readelf +ln /usr/local/bin/size +ln /usr/local/bin/strings +ln /usr/local/bin/strip + +#pkg info -l llvm37 | grep usr/local/bin diff --git a/nixpkgs/pkgs/stdenv/generic/builder.sh b/nixpkgs/pkgs/stdenv/generic/builder.sh new file mode 100644 index 000000000000..79bf21ab4730 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/generic/builder.sh @@ -0,0 +1,21 @@ +export PATH= +for i in $initialPath; do + if [ "$i" = / ]; then i=; fi + PATH=$PATH${PATH:+:}$i/bin +done + +mkdir $out + +echo "export SHELL=$shell" > $out/setup +echo "initialPath=\"$initialPath\"" >> $out/setup +echo "defaultNativeBuildInputs=\"$defaultNativeBuildInputs\"" >> $out/setup +echo "defaultBuildInputs=\"$defaultBuildInputs\"" >> $out/setup +echo "$preHook" >> $out/setup +cat "$setup" >> $out/setup + +# Allow the user to install stdenv using nix-env and get the packages +# in stdenv. +mkdir $out/nix-support +if [ "$propagatedUserEnvPkgs" ]; then + printf '%s ' $propagatedUserEnvPkgs > $out/nix-support/propagated-user-env-packages +fi diff --git a/nixpkgs/pkgs/stdenv/generic/check-meta.nix b/nixpkgs/pkgs/stdenv/generic/check-meta.nix new file mode 100644 index 000000000000..b754230b0be9 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/generic/check-meta.nix @@ -0,0 +1,256 @@ +# Checks derivation meta and attrs for problems (like brokenness, +# licenses, etc). + +{ lib, config, hostPlatform }: + +let + # If we're in hydra, we can dispense with the more verbose error + # messages and make problems easier to spot. + inHydra = config.inHydra or false; + getName = attrs: attrs.name or ("${attrs.pname or "«name-missing»"}-${attrs.version or "«version-missing»"}"); + + # See discussion at https://github.com/NixOS/nixpkgs/pull/25304#issuecomment-298385426 + # for why this defaults to false, but I (@copumpkin) want to default it to true soon. + shouldCheckMeta = config.checkMeta or false; + + allowUnfree = config.allowUnfree or false + || builtins.getEnv "NIXPKGS_ALLOW_UNFREE" == "1"; + + whitelist = config.whitelistedLicenses or []; + blacklist = config.blacklistedLicenses or []; + + onlyLicenses = list: + lib.lists.all (license: + let l = lib.licenses.${license.shortName or "BROKEN"} or false; in + if license == l then true else + throw ''‘${showLicense license}’ is not an attribute of lib.licenses'' + ) list; + + areLicenseListsValid = + if lib.mutuallyExclusive whitelist blacklist then + assert onlyLicenses whitelist; assert onlyLicenses blacklist; true + else + throw "whitelistedLicenses and blacklistedLicenses are not mutually exclusive."; + + hasLicense = attrs: + attrs ? meta.license; + + hasWhitelistedLicense = assert areLicenseListsValid; attrs: + hasLicense attrs && builtins.elem attrs.meta.license whitelist; + + hasBlacklistedLicense = assert areLicenseListsValid; attrs: + hasLicense attrs && builtins.elem attrs.meta.license blacklist; + + allowBroken = config.allowBroken or false + || builtins.getEnv "NIXPKGS_ALLOW_BROKEN" == "1"; + + allowUnsupportedSystem = config.allowUnsupportedSystem or false + || builtins.getEnv "NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM" == "1"; + + isUnfree = licenses: lib.lists.any (l: !l.free or true) licenses; + + # Alow granular checks to allow only some unfree packages + # Example: + # {pkgs, ...}: + # { + # allowUnfree = false; + # allowUnfreePredicate = (x: pkgs.lib.hasPrefix "flashplayer-" x.name); + # } + allowUnfreePredicate = config.allowUnfreePredicate or (x: false); + + # Check whether unfree packages are allowed and if not, whether the + # package has an unfree license and is not explicitely allowed by the + # `allowUnfreePredicate` function. + hasDeniedUnfreeLicense = attrs: + !allowUnfree && + hasLicense attrs && + isUnfree (lib.lists.toList attrs.meta.license) && + !allowUnfreePredicate attrs; + + allowInsecureDefaultPredicate = x: builtins.elem x.name (config.permittedInsecurePackages or []); + allowInsecurePredicate = x: (config.allowInsecurePredicate or allowInsecureDefaultPredicate) x; + + hasAllowedInsecure = attrs: + (attrs.meta.knownVulnerabilities or []) == [] || + allowInsecurePredicate attrs || + builtins.getEnv "NIXPKGS_ALLOW_INSECURE" == "1"; + + showLicense = license: license.shortName or "unknown"; + + pos_str = meta: meta.position or "«unknown-file»"; + + remediation = { + unfree = remediate_whitelist "Unfree"; + broken = remediate_whitelist "Broken"; + unsupported = remediate_whitelist "UnsupportedSystem"; + blacklisted = x: ""; + insecure = remediate_insecure; + broken-outputs = remediateOutputsToInstall; + unknown-meta = x: ""; + }; + remediate_whitelist = allow_attr: attrs: + '' + a) For `nixos-rebuild` you can set + { nixpkgs.config.allow${allow_attr} = true; } + in configuration.nix to override this. + + b) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add + { allow${allow_attr} = true; } + to ~/.config/nixpkgs/config.nix. + ''; + + remediate_insecure = attrs: + '' + + Known issues: + '' + (lib.concatStrings (map (issue: " - ${issue}\n") attrs.meta.knownVulnerabilities)) + '' + + You can install it anyway by whitelisting this package, using the + following methods: + + a) for `nixos-rebuild` you can add ‘${getName attrs}’ to + `nixpkgs.config.permittedInsecurePackages` in the configuration.nix, + like so: + + { + nixpkgs.config.permittedInsecurePackages = [ + "${getName attrs}" + ]; + } + + b) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add + ‘${getName attrs}’ to `permittedInsecurePackages` in + ~/.config/nixpkgs/config.nix, like so: + + { + permittedInsecurePackages = [ + "${getName attrs}" + ]; + } + + ''; + + remediateOutputsToInstall = attrs: let + expectedOutputs = attrs.meta.outputsToInstall or []; + actualOutputs = attrs.outputs or [ "out" ]; + missingOutputs = builtins.filter (output: ! builtins.elem output actualOutputs) expectedOutputs; + in '' + The package ${getName attrs} has set meta.outputsToInstall to: ${builtins.concatStringsSep ", " expectedOutputs} + + however ${getName attrs} only has the outputs: ${builtins.concatStringsSep ", " actualOutputs} + + and is missing the following ouputs: + + ${lib.concatStrings (builtins.map (output: " - ${output}\n") missingOutputs)} + ''; + + handleEvalIssue = { meta, attrs }: { reason , errormsg ? "" }: + let + msg = if inHydra + then "Failed to evaluate ${getName attrs}: «${reason}»: ${errormsg}" + else '' + Package ‘${getName attrs}’ in ${pos_str meta} ${errormsg}, refusing to evaluate. + + '' + (builtins.getAttr reason remediation) attrs; + + handler = if config ? handleEvalIssue + then config.handleEvalIssue reason + else throw; + in handler msg; + + + metaTypes = with lib.types; rec { + # These keys are documented + description = str; + longDescription = str; + branch = str; + homepage = either (listOf str) str; + downloadPage = str; + changelog = either (listOf str) str; + license = either (listOf lib.types.attrs) (either lib.types.attrs str); + maintainers = listOf (attrsOf str); + priority = int; + platforms = listOf str; + hydraPlatforms = listOf str; + broken = bool; + # TODO: refactor once something like Profpatsch's types-simple will land + # This is currently dead code due to https://github.com/NixOS/nix/issues/2532 + tests = attrsOf (mkOptionType { + name = "test"; + check = x: x == {} || ( # Accept {} for tests that are unsupported + isDerivation x && + x ? meta.timeout + ); + merge = lib.options.mergeOneOption; + }); + timeout = int; + + # Weirder stuff that doesn't appear in the documentation? + knownVulnerabilities = listOf str; + name = str; + version = str; + tag = str; + updateWalker = bool; + executables = listOf str; + outputsToInstall = listOf str; + position = str; + available = bool; + repositories = attrsOf str; + isBuildPythonPackage = platforms; + schedulingPriority = int; + downloadURLRegexp = str; + isFcitxEngine = bool; + isIbusEngine = bool; + isGutenprint = bool; + badPlatforms = platforms; + }; + + checkMetaAttr = k: v: + if metaTypes?${k} then + if metaTypes.${k}.check v then null else "key '${k}' has a value ${toString v} of an invalid type ${builtins.typeOf v}; expected ${metaTypes.${k}.description}" + else "key '${k}' is unrecognized; expected one of: \n\t [${lib.concatMapStringsSep ", " (x: "'${x}'") (lib.attrNames metaTypes)}]"; + checkMeta = meta: if shouldCheckMeta then lib.remove null (lib.mapAttrsToList checkMetaAttr meta) else []; + + checkOutputsToInstall = attrs: let + expectedOutputs = attrs.meta.outputsToInstall or []; + actualOutputs = attrs.outputs or [ "out" ]; + missingOutputs = builtins.filter (output: ! builtins.elem output actualOutputs) expectedOutputs; + in if shouldCheckMeta + then builtins.length missingOutputs > 0 + else false; + + # Check if a derivation is valid, that is whether it passes checks for + # e.g brokenness or license. + # + # Return { valid: Bool } and additionally + # { reason: String; errormsg: String } if it is not valid, where + # reason is one of "unfree", "blacklisted" or "broken". + checkValidity = attrs: + if hasDeniedUnfreeLicense attrs && !(hasWhitelistedLicense attrs) then + { valid = false; reason = "unfree"; errormsg = "has an unfree license (‘${showLicense attrs.meta.license}’)"; } + else if hasBlacklistedLicense attrs then + { valid = false; reason = "blacklisted"; errormsg = "has a blacklisted license (‘${showLicense attrs.meta.license}’)"; } + else if !allowBroken && attrs.meta.broken or false then + { valid = false; reason = "broken"; errormsg = "is marked as broken"; } + else if !allowUnsupportedSystem && + (!lib.lists.elem hostPlatform.system (attrs.meta.platforms or lib.platforms.all) || + lib.lists.elem hostPlatform.system (attrs.meta.badPlatforms or [])) then + { valid = false; reason = "unsupported"; errormsg = "is not supported on ‘${hostPlatform.system}’"; } + else if !(hasAllowedInsecure attrs) then + { valid = false; reason = "insecure"; errormsg = "is marked as insecure"; } + else if checkOutputsToInstall attrs then + { valid = false; reason = "broken-outputs"; errormsg = "has invalid meta.outputsToInstall"; } + else let res = checkMeta (attrs.meta or {}); in if res != [] then + { valid = false; reason = "unknown-meta"; errormsg = "has an invalid meta attrset:${lib.concatMapStrings (x: "\n\t - " + x) res}"; } + else { valid = true; }; + + assertValidity = { meta, attrs }: let + validity = checkValidity attrs; + in validity // { + # Throw an error if trying to evaluate an non-valid derivation + handled = if !validity.valid + then handleEvalIssue { inherit meta attrs; } (removeAttrs validity ["valid"]) + else true; + }; + +in assertValidity diff --git a/nixpkgs/pkgs/stdenv/generic/default-builder.sh b/nixpkgs/pkgs/stdenv/generic/default-builder.sh new file mode 100644 index 000000000000..273fc55c7552 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/generic/default-builder.sh @@ -0,0 +1,2 @@ +source $stdenv/setup +genericBuild diff --git a/nixpkgs/pkgs/stdenv/generic/default.nix b/nixpkgs/pkgs/stdenv/generic/default.nix new file mode 100644 index 000000000000..2f43db9cfc24 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/generic/default.nix @@ -0,0 +1,157 @@ +let lib = import ../../../lib; in lib.makeOverridable ( + +{ name ? "stdenv", preHook ? "", initialPath, cc, shell +, allowedRequisites ? null, extraAttrs ? {}, overrides ? (self: super: {}), config + +, # The `fetchurl' to use for downloading curl and its dependencies + # (see all-packages.nix). + fetchurlBoot + +, setupScript ? ./setup.sh + +, extraNativeBuildInputs ? [] +, extraBuildInputs ? [] +, __stdenvImpureHostDeps ? [] +, __extraImpureHostDeps ? [] +, stdenvSandboxProfile ? "" +, extraSandboxProfile ? "" + + ## Platform parameters + ## + ## The "build" "host" "target" terminology below comes from GNU Autotools. See + ## its documentation for more information on what those words mean. Note that + ## each should always be defined, even when not cross compiling. + ## + ## For purposes of bootstrapping, think of each stage as a "sliding window" + ## over a list of platforms. Specifically, the host platform of the previous + ## stage becomes the build platform of the current one, and likewise the + ## target platform of the previous stage becomes the host platform of the + ## current one. + ## + +, # The platform on which packages are built. Consists of `system`, a + # string (e.g.,`i686-linux') identifying the most import attributes of the + # build platform, and `platform` a set of other details. + buildPlatform + +, # The platform on which packages run. + hostPlatform + +, # The platform which build tools (especially compilers) build for in this stage, + targetPlatform +}: + +let + defaultNativeBuildInputs = extraNativeBuildInputs ++ + [ ../../build-support/setup-hooks/move-docs.sh + ../../build-support/setup-hooks/compress-man-pages.sh + ../../build-support/setup-hooks/strip.sh + ../../build-support/setup-hooks/patch-shebangs.sh + ../../build-support/setup-hooks/prune-libtool-files.sh + ] + # FIXME this on Darwin; see + # https://github.com/NixOS/nixpkgs/commit/94d164dd7#commitcomment-22030369 + ++ lib.optional hostPlatform.isLinux ../../build-support/setup-hooks/audit-tmpdir.sh + ++ [ + ../../build-support/setup-hooks/multiple-outputs.sh + ../../build-support/setup-hooks/move-sbin.sh + ../../build-support/setup-hooks/move-lib64.sh + ../../build-support/setup-hooks/set-source-date-epoch-to-latest.sh + cc + ]; + + defaultBuildInputs = extraBuildInputs; + + # The stdenv that we are producing. + stdenv = + derivation ( + lib.optionalAttrs (allowedRequisites != null) { + allowedRequisites = allowedRequisites + ++ defaultNativeBuildInputs ++ defaultBuildInputs; + } + // { + inherit name; + + # Nix itself uses the `system` field of a derivation to decide where to + # build it. This is a bit confusing for cross compilation. + inherit (buildPlatform) system; + + builder = shell; + + args = ["-e" ./builder.sh]; + + setup = setupScript; + + # We pretty much never need rpaths on Darwin, since all library path references + # are absolute unless we go out of our way to make them relative (like with CF) + # TODO: This really wants to be in stdenv/darwin but we don't have hostPlatform + # there (yet?) so it goes here until then. + preHook = preHook+ lib.optionalString buildPlatform.isDarwin '' + export NIX_BUILD_DONT_SET_RPATH=1 + '' + lib.optionalString (hostPlatform.isDarwin || (hostPlatform.parsed.kernel.execFormat != lib.systems.parse.execFormats.elf && hostPlatform.parsed.kernel.execFormat != lib.systems.parse.execFormats.macho)) '' + export NIX_DONT_SET_RPATH=1 + export NIX_NO_SELF_RPATH=1 + '' + # TODO this should be uncommented, but it causes stupid mass rebuilds. I + # think the best solution would just be to fixup linux RPATHs so we don't + # need to set `-rpath` anywhere. + # + lib.optionalString targetPlatform.isDarwin '' + # export NIX_TARGET_DONT_SET_RPATH=1 + # '' + ; + + inherit initialPath shell + defaultNativeBuildInputs defaultBuildInputs; + } + // lib.optionalAttrs buildPlatform.isDarwin { + __sandboxProfile = stdenvSandboxProfile; + __impureHostDeps = __stdenvImpureHostDeps; + }) + + // { + + meta = { + description = "The default build environment for Unix packages in Nixpkgs"; + platforms = lib.platforms.all; + }; + + inherit buildPlatform hostPlatform targetPlatform; + + inherit extraNativeBuildInputs extraBuildInputs + __extraImpureHostDeps extraSandboxProfile; + + # Utility flags to test the type of platform. + inherit (hostPlatform) + isDarwin isLinux isSunOS isCygwin isFreeBSD isOpenBSD + isi686 isx86_32 isx86_64 + is32bit is64bit + isAarch32 isAarch64 isMips isBigEndian; + isArm = lib.warn + "`stdenv.isArm` is deprecated after 18.03. Please use `stdenv.isAarch32` instead" + hostPlatform.isAarch32; + + # The derivation's `system` is `buildPlatform.system`. + inherit (buildPlatform) system; + + inherit (import ./make-derivation.nix { + inherit lib config stdenv; + }) mkDerivation; + + # For convenience, bring in the library functions in lib/ so + # packages don't have to do that themselves. + inherit lib; + + inherit fetchurlBoot; + + inherit overrides; + + inherit cc; + } + + # Propagate any extra attributes. For instance, we use this to + # "lift" packages like curl from the final stdenv for Linux to + # all-packages.nix for that platform (meaning that it has a line + # like curl = if stdenv ? curl then stdenv.curl else ...). + // extraAttrs; + +in stdenv) diff --git a/nixpkgs/pkgs/stdenv/generic/make-derivation.nix b/nixpkgs/pkgs/stdenv/generic/make-derivation.nix new file mode 100644 index 000000000000..a11b280b047e --- /dev/null +++ b/nixpkgs/pkgs/stdenv/generic/make-derivation.nix @@ -0,0 +1,327 @@ +{ lib, config, stdenv }: + +let + checkMeta = import ./check-meta.nix { + inherit lib config; + # Nix itself uses the `system` field of a derivation to decide where + # to build it. This is a bit confusing for cross compilation. + inherit (stdenv) hostPlatform; + }; +in rec { + # `mkDerivation` wraps the builtin `derivation` function to + # produce derivations that use this stdenv and its shell. + # + # See also: + # + # * https://nixos.org/nixpkgs/manual/#sec-using-stdenv + # Details on how to use this mkDerivation function + # + # * https://nixos.org/nix/manual/#ssec-derivation + # Explanation about derivations in general + mkDerivation = + { + + # These types of dependencies are all exhaustively documented in + # the "Specifying Dependencies" section of the "Standard + # Environment" chapter of the Nixpkgs manual. + + # TODO(@Ericson2314): Stop using legacy dep attribute names + + # host offset -> target offset + depsBuildBuild ? [] # -1 -> -1 + , depsBuildBuildPropagated ? [] # -1 -> -1 + , nativeBuildInputs ? [] # -1 -> 0 N.B. Legacy name + , propagatedNativeBuildInputs ? [] # -1 -> 0 N.B. Legacy name + , depsBuildTarget ? [] # -1 -> 1 + , depsBuildTargetPropagated ? [] # -1 -> 1 + + , depsHostHost ? [] # 0 -> 0 + , depsHostHostPropagated ? [] # 0 -> 0 + , buildInputs ? [] # 0 -> 1 N.B. Legacy name + , propagatedBuildInputs ? [] # 0 -> 1 N.B. Legacy name + + , depsTargetTarget ? [] # 1 -> 1 + , depsTargetTargetPropagated ? [] # 1 -> 1 + + , checkInputs ? [] + , installCheckInputs ? [] + + # Configure Phase + , configureFlags ? [] + , cmakeFlags ? [] + , # Target is not included by default because most programs don't care. + # Including it then would cause needless mass rebuilds. + # + # TODO(@Ericson2314): Make [ "build" "host" ] always the default. + configurePlatforms ? lib.optionals + (stdenv.hostPlatform != stdenv.buildPlatform) + [ "build" "host" ] + + # TODO(@Ericson2314): Make unconditional / resolve #33599 + # Check phase + , doCheck ? config.doCheckByDefault or false + + # TODO(@Ericson2314): Make unconditional / resolve #33599 + # InstallCheck phase + , doInstallCheck ? config.doCheckByDefault or false + + , # TODO(@Ericson2314): Make always true and remove + strictDeps ? stdenv.hostPlatform != stdenv.buildPlatform + , meta ? {} + , passthru ? {} + , pos ? # position used in error messages and for meta.position + (if attrs.meta.description or null != null + then builtins.unsafeGetAttrPos "description" attrs.meta + else if attrs.version or null != null + then builtins.unsafeGetAttrPos "version" attrs + else builtins.unsafeGetAttrPos "name" attrs) + , separateDebugInfo ? false + , outputs ? [ "out" ] + , __darwinAllowLocalNetworking ? false + , __impureHostDeps ? [] + , __propagatedImpureHostDeps ? [] + , sandboxProfile ? "" + , propagatedSandboxProfile ? "" + + , hardeningEnable ? [] + , hardeningDisable ? [] + + , patches ? [] + + , ... } @ attrs: + + let + # TODO(@oxij, @Ericson2314): This is here to keep the old semantics, remove when + # no package has `doCheck = true`. + doCheck' = doCheck && stdenv.hostPlatform == stdenv.buildPlatform; + doInstallCheck' = doInstallCheck && stdenv.hostPlatform == stdenv.buildPlatform; + + separateDebugInfo' = separateDebugInfo && stdenv.hostPlatform.isLinux && !(stdenv.hostPlatform.useLLVM or false); + outputs' = outputs ++ lib.optional separateDebugInfo' "debug"; + + noNonNativeDeps = builtins.length (depsBuildTarget ++ depsBuildTargetPropagated + ++ depsHostHost ++ depsHostHostPropagated + ++ buildInputs ++ propagatedBuildInputs + ++ depsTargetTarget ++ depsTargetTargetPropagated) == 0; + dontAddHostSuffix = attrs ? outputHash && !noNonNativeDeps || (stdenv.noCC or false); + supportedHardeningFlags = [ "fortify" "stackprotector" "pie" "pic" "strictoverflow" "format" "relro" "bindnow" ]; + defaultHardeningFlags = if stdenv.hostPlatform.isMusl + then supportedHardeningFlags + else lib.remove "pie" supportedHardeningFlags; + enabledHardeningOptions = + if builtins.elem "all" hardeningDisable + then [] + else lib.subtractLists hardeningDisable (defaultHardeningFlags ++ hardeningEnable); + # hardeningDisable additionally supports "all". + erroneousHardeningFlags = lib.subtractLists supportedHardeningFlags (hardeningEnable ++ lib.remove "all" hardeningDisable); + in if builtins.length erroneousHardeningFlags != 0 + then abort ("mkDerivation was called with unsupported hardening flags: " + lib.generators.toPretty {} { + inherit erroneousHardeningFlags hardeningDisable hardeningEnable supportedHardeningFlags; + }) + else let + doCheck = doCheck'; + doInstallCheck = doInstallCheck'; + + outputs = outputs'; + + references = nativeBuildInputs ++ buildInputs + ++ propagatedNativeBuildInputs ++ propagatedBuildInputs; + + dependencies = map (map lib.chooseDevOutputs) [ + [ + (map (drv: drv.__spliced.buildBuild or drv) depsBuildBuild) + (map (drv: drv.nativeDrv or drv) nativeBuildInputs + ++ lib.optional separateDebugInfo' ../../build-support/setup-hooks/separate-debug-info.sh + ++ lib.optional stdenv.hostPlatform.isWindows ../../build-support/setup-hooks/win-dll-link.sh + ++ lib.optionals doCheck checkInputs + ++ lib.optionals doInstallCheck' installCheckInputs) + (map (drv: drv.__spliced.buildTarget or drv) depsBuildTarget) + ] + [ + (map (drv: drv.__spliced.hostHost or drv) depsHostHost) + (map (drv: drv.crossDrv or drv) buildInputs) + ] + [ + (map (drv: drv.__spliced.targetTarget or drv) depsTargetTarget) + ] + ]; + propagatedDependencies = map (map lib.chooseDevOutputs) [ + [ + (map (drv: drv.__spliced.buildBuild or drv) depsBuildBuildPropagated) + (map (drv: drv.nativeDrv or drv) propagatedNativeBuildInputs) + (map (drv: drv.__spliced.buildTarget or drv) depsBuildTargetPropagated) + ] + [ + (map (drv: drv.__spliced.hostHost or drv) depsHostHostPropagated) + (map (drv: drv.crossDrv or drv) propagatedBuildInputs) + ] + [ + (map (drv: drv.__spliced.targetTarget or drv) depsTargetTargetPropagated) + ] + ]; + + computedSandboxProfile = + lib.concatMap (input: input.__propagatedSandboxProfile or []) + (stdenv.extraNativeBuildInputs + ++ stdenv.extraBuildInputs + ++ lib.concatLists dependencies); + + computedPropagatedSandboxProfile = + lib.concatMap (input: input.__propagatedSandboxProfile or []) + (lib.concatLists propagatedDependencies); + + computedImpureHostDeps = + lib.unique (lib.concatMap (input: input.__propagatedImpureHostDeps or []) + (stdenv.extraNativeBuildInputs + ++ stdenv.extraBuildInputs + ++ lib.concatLists dependencies)); + + computedPropagatedImpureHostDeps = + lib.unique (lib.concatMap (input: input.__propagatedImpureHostDeps or []) + (lib.concatLists propagatedDependencies)); + + derivationArg = + (removeAttrs attrs + ["meta" "passthru" "pos" + "checkInputs" "installCheckInputs" + "__darwinAllowLocalNetworking" + "__impureHostDeps" "__propagatedImpureHostDeps" + "sandboxProfile" "propagatedSandboxProfile"]) + // (lib.optionalAttrs (!(attrs ? name) && attrs ? pname && attrs ? version)) { + name = "${attrs.pname}-${attrs.version}"; + } // (lib.optionalAttrs (stdenv.hostPlatform != stdenv.buildPlatform && !dontAddHostSuffix && (attrs ? name || (attrs ? pname && attrs ? version)))) { + # Fixed-output derivations like source tarballs shouldn't get a host + # suffix. But we have some weird ones with run-time deps that are + # just used for their side-affects. Those might as well since the + # hash can't be the same. See #32986. + name = "${attrs.name or "${attrs.pname}-${attrs.version}"}-${stdenv.hostPlatform.config}"; + } // { + builder = attrs.realBuilder or stdenv.shell; + args = attrs.args or ["-e" (attrs.builder or ./default-builder.sh)]; + inherit stdenv; + + # The `system` attribute of a derivation has special meaning to Nix. + # Derivations set it to choose what sort of machine could be used to + # execute the build, The build platform entirely determines this, + # indeed more finely than Nix knows or cares about. The `system` + # attribute of `buildPlatfom` matches Nix's degree of specificity. + # exactly. + inherit (stdenv.buildPlatform) system; + + userHook = config.stdenv.userHook or null; + __ignoreNulls = true; + + inherit strictDeps; + + depsBuildBuild = lib.elemAt (lib.elemAt dependencies 0) 0; + nativeBuildInputs = lib.elemAt (lib.elemAt dependencies 0) 1; + depsBuildTarget = lib.elemAt (lib.elemAt dependencies 0) 2; + depsHostHost = lib.elemAt (lib.elemAt dependencies 1) 0; + buildInputs = lib.elemAt (lib.elemAt dependencies 1) 1; + depsTargetTarget = lib.elemAt (lib.elemAt dependencies 2) 0; + + depsBuildBuildPropagated = lib.elemAt (lib.elemAt propagatedDependencies 0) 0; + propagatedNativeBuildInputs = lib.elemAt (lib.elemAt propagatedDependencies 0) 1; + depsBuildTargetPropagated = lib.elemAt (lib.elemAt propagatedDependencies 0) 2; + depsHostHostPropagated = lib.elemAt (lib.elemAt propagatedDependencies 1) 0; + propagatedBuildInputs = lib.elemAt (lib.elemAt propagatedDependencies 1) 1; + depsTargetTargetPropagated = lib.elemAt (lib.elemAt propagatedDependencies 2) 0; + + # This parameter is sometimes a string, sometimes null, and sometimes a list, yuck + configureFlags = let inherit (lib) optional elem; in + (/**/ if lib.isString configureFlags then [configureFlags] + else if configureFlags == null then [] + else configureFlags) + ++ optional (elem "build" configurePlatforms) "--build=${stdenv.buildPlatform.config}" + ++ optional (elem "host" configurePlatforms) "--host=${stdenv.hostPlatform.config}" + ++ optional (elem "target" configurePlatforms) "--target=${stdenv.targetPlatform.config}"; + + inherit patches; + + inherit doCheck doInstallCheck; + + inherit outputs; + } // lib.optionalAttrs (stdenv.hostPlatform != stdenv.buildPlatform) { + cmakeFlags = + (/**/ if lib.isString cmakeFlags then [cmakeFlags] + else if cmakeFlags == null then [] + else cmakeFlags) + ++ [ "-DCMAKE_SYSTEM_NAME=${lib.findFirst lib.isString "Generic" [ stdenv.hostPlatform.uname.system ]}" ] + ++ lib.optional (stdenv.hostPlatform.uname.processor != null) "-DCMAKE_SYSTEM_PROCESSOR=${stdenv.hostPlatform.uname.processor}" + ++ lib.optional (stdenv.hostPlatform.uname.release != null) "-DCMAKE_SYSTEM_VERSION=${stdenv.hostPlatform.release}" + ++ lib.optional (stdenv.buildPlatform.uname.system != null) "-DCMAKE_HOST_SYSTEM_NAME=${stdenv.buildPlatform.uname.system}" + ++ lib.optional (stdenv.buildPlatform.uname.processor != null) "-DCMAKE_HOST_SYSTEM_PROCESSOR=${stdenv.buildPlatform.uname.processor}" + ++ lib.optional (stdenv.buildPlatform.uname.release != null) "-DCMAKE_HOST_SYSTEM_VERSION=${stdenv.buildPlatform.uname.release}"; + } // lib.optionalAttrs (attrs.enableParallelBuilding or false) { + enableParallelChecking = attrs.enableParallelChecking or true; + } // lib.optionalAttrs (hardeningDisable != [] || hardeningEnable != []) { + NIX_HARDENING_ENABLE = enabledHardeningOptions; + } // lib.optionalAttrs (stdenv.hostPlatform.isx86_64 && stdenv.hostPlatform ? platform.gcc.arch) { + requiredSystemFeatures = attrs.requiredSystemFeatures or [] ++ [ "gccarch-${stdenv.hostPlatform.platform.gcc.arch}" ]; + } // lib.optionalAttrs (stdenv.buildPlatform.isDarwin) { + inherit __darwinAllowLocalNetworking; + # TODO: remove lib.unique once nix has a list canonicalization primitive + __sandboxProfile = + let profiles = [ stdenv.extraSandboxProfile ] ++ computedSandboxProfile ++ computedPropagatedSandboxProfile ++ [ propagatedSandboxProfile sandboxProfile ]; + final = lib.concatStringsSep "\n" (lib.filter (x: x != "") (lib.unique profiles)); + in final; + __propagatedSandboxProfile = lib.unique (computedPropagatedSandboxProfile ++ [ propagatedSandboxProfile ]); + __impureHostDeps = computedImpureHostDeps ++ computedPropagatedImpureHostDeps ++ __propagatedImpureHostDeps ++ __impureHostDeps ++ stdenv.__extraImpureHostDeps ++ [ + "/dev/zero" + "/dev/random" + "/dev/urandom" + "/bin/sh" + ]; + __propagatedImpureHostDeps = computedPropagatedImpureHostDeps ++ __propagatedImpureHostDeps; + }; + + validity = checkMeta { inherit meta attrs; }; + + # The meta attribute is passed in the resulting attribute set, + # but it's not part of the actual derivation, i.e., it's not + # passed to the builder and is not a dependency. But since we + # include it in the result, it *is* available to nix-env for queries. + meta = { + # `name` above includes cross-compilation cruft (and is under assert), + # lets have a clean always accessible version here. + name = attrs.name or "${attrs.pname}-${attrs.version}"; + + # If the packager hasn't specified `outputsToInstall`, choose a default, + # which is the name of `p.bin or p.out or p`; + # if he has specified it, it will be overridden below in `// meta`. + # Note: This default probably shouldn't be globally configurable. + # Services and users should specify outputs explicitly, + # unless they are comfortable with this default. + outputsToInstall = + let + hasOutput = out: builtins.elem out outputs; + in [( lib.findFirst hasOutput null (["bin" "out"] ++ outputs) )] + ++ lib.optional (hasOutput "man") "man"; + } + // attrs.meta or {} + # Fill `meta.position` to identify the source location of the package. + // lib.optionalAttrs (pos != null) { + position = pos.file + ":" + toString pos.line; + # Expose the result of the checks for everyone to see. + } // { + available = validity.valid + && (if config.checkMetaRecursively or false + then lib.all (d: d.meta.available or true) references + else true); + }; + + in + + lib.extendDerivation + validity.handled + ({ + overrideAttrs = f: mkDerivation (attrs // (f attrs)); + inherit meta passthru; + } // + # Pass through extra attributes that are not inputs, but + # should be made available to Nix expressions using the + # derivation (e.g., in assertions). + passthru) + (derivation derivationArg); + +} diff --git a/nixpkgs/pkgs/stdenv/generic/setup.sh b/nixpkgs/pkgs/stdenv/generic/setup.sh new file mode 100644 index 000000000000..311292169ecd --- /dev/null +++ b/nixpkgs/pkgs/stdenv/generic/setup.sh @@ -0,0 +1,1341 @@ +set -eu +set -o pipefail + +if (( "${NIX_DEBUG:-0}" >= 6 )); then + set -x +fi + +: ${outputs:=out} + + +###################################################################### +# Hook handling. + + +# Run all hooks with the specified name in the order in which they +# were added, stopping if any fails (returns a non-zero exit +# code). The hooks for <hookName> are the shell function or variable +# <hookName>, and the values of the shell array ‘<hookName>Hooks’. +runHook() { + local oldOpts="$(shopt -po nounset)" + set -u # May be called from elsewhere, so do `set -u`. + + local hookName="$1" + shift + local hooksSlice="${hookName%Hook}Hooks[@]" + + local hook + # Hack around old bash being bad and thinking empty arrays are + # undefined. + for hook in "_callImplicitHook 0 $hookName" ${!hooksSlice+"${!hooksSlice}"}; do + _eval "$hook" "$@" + set -u # To balance `_eval` + done + + eval "${oldOpts}" + return 0 +} + + +# Run all hooks with the specified name, until one succeeds (returns a +# zero exit code). If none succeed, return a non-zero exit code. +runOneHook() { + local oldOpts="$(shopt -po nounset)" + set -u # May be called from elsewhere, so do `set -u`. + + local hookName="$1" + shift + local hooksSlice="${hookName%Hook}Hooks[@]" + + local hook ret=1 + # Hack around old bash like above + for hook in "_callImplicitHook 1 $hookName" ${!hooksSlice+"${!hooksSlice}"}; do + if _eval "$hook" "$@"; then + ret=0 + break + fi + set -u # To balance `_eval` + done + + eval "${oldOpts}" + return "$ret" +} + + +# Run the named hook, either by calling the function with that name or +# by evaluating the variable with that name. This allows convenient +# setting of hooks both from Nix expressions (as attributes / +# environment variables) and from shell scripts (as functions). If you +# want to allow multiple hooks, use runHook instead. +_callImplicitHook() { + set -u + local def="$1" + local hookName="$2" + case "$(type -t "$hookName")" in + (function|alias|builtin) + set +u + "$hookName";; + (file) + set +u + source "$hookName";; + (keyword) :;; + (*) if [ -z "${!hookName:-}" ]; then + return "$def"; + else + set +u + eval "${!hookName}" + fi;; + esac + # `_eval` expects hook to need nounset disable and leave it + # disabled anyways, so Ok to to delegate. The alternative of a + # return trap is no good because it would affect nested returns. +} + + +# A function wrapper around ‘eval’ that ensures that ‘return’ inside +# hooks exits the hook, not the caller. Also will only pass args if +# command can take them +_eval() { + if [ "$(type -t "$1")" = function ]; then + set +u + "$@" # including args + else + set +u + eval "$1" + fi + # `run*Hook` reenables `set -u` +} + + +###################################################################### +# Logging. + +# Obsolete. +stopNest() { true; } +header() { echo "$1"; } +closeNest() { true; } + +# Prints a command such that all word splits are unambiguous. We need +# to split the command in three parts because the middle format string +# will be, and must be, repeated for each argument. The first argument +# goes before the ':' and is just for convenience. +echoCmd() { + printf "%s:" "$1" + shift + printf ' %q' "$@" + echo +} + + +###################################################################### +# Error handling. + +exitHandler() { + exitCode="$?" + set +e + + if [ -n "${showBuildStats:-}" ]; then + times > "$NIX_BUILD_TOP/.times" + local -a times=($(cat "$NIX_BUILD_TOP/.times")) + # Print the following statistics: + # - user time for the shell + # - system time for the shell + # - user time for all child processes + # - system time for all child processes + echo "build time elapsed: " "${times[@]}" + fi + + if (( "$exitCode" != 0 )); then + runHook failureHook + + # If the builder had a non-zero exit code and + # $succeedOnFailure is set, create the file + # ‘$out/nix-support/failed’ to signal failure, and exit + # normally. Otherwise, return the original exit code. + if [ -n "${succeedOnFailure:-}" ]; then + echo "build failed with exit code $exitCode (ignored)" + mkdir -p "$out/nix-support" + printf "%s" "$exitCode" > "$out/nix-support/failed" + exit 0 + fi + + else + runHook exitHook + fi + + exit "$exitCode" +} + +trap "exitHandler" EXIT + + +###################################################################### +# Helper functions. + + +addToSearchPathWithCustomDelimiter() { + local delimiter="$1" + local varName="$2" + local dir="$3" + if [ -d "$dir" ]; then + export "${varName}=${!varName:+${!varName}${delimiter}}${dir}" + fi +} + +addToSearchPath() { + addToSearchPathWithCustomDelimiter ":" "$@" +} + +# Add $1/lib* into rpaths. +# The function is used in multiple-outputs.sh hook, +# so it is defined here but tried after the hook. +_addRpathPrefix() { + if [ "${NIX_NO_SELF_RPATH:-0}" != 1 ]; then + export NIX_LDFLAGS="-rpath $1/lib $NIX_LDFLAGS" + if [ -n "${NIX_LIB64_IN_SELF_RPATH:-}" ]; then + export NIX_LDFLAGS="-rpath $1/lib64 $NIX_LDFLAGS" + fi + if [ -n "${NIX_LIB32_IN_SELF_RPATH:-}" ]; then + export NIX_LDFLAGS="-rpath $1/lib32 $NIX_LDFLAGS" + fi + fi +} + +# Return success if the specified file is an ELF object. +isELF() { + local fn="$1" + local fd + local magic + exec {fd}< "$fn" + read -r -n 4 -u "$fd" magic + exec {fd}<&- + if [ "$magic" = $'\177ELF' ]; then return 0; else return 1; fi +} + +# Return success if the specified file is an ELF object +# and its e_type is ET_EXEC (executable file) +isELFExec() { + grep -ao -P '^\177ELF.{11}\x00\x02' "$1" >/dev/null +} + +# Return success if the specified file is an ELF object +# and its e_type is ET_DYN (shared object file) +isELFDyn() { + grep -ao -P '^\177ELF.{11}\x00\x03' "$1" >/dev/null +} + +# Return success if the specified file is a script (i.e. starts with +# "#!"). +isScript() { + local fn="$1" + local fd + local magic + exec {fd}< "$fn" + read -r -n 2 -u "$fd" magic + exec {fd}<&- + if [[ "$magic" =~ \#! ]]; then return 0; else return 1; fi +} + +# printf unfortunately will print a trailing newline regardless +printLines() { + (( "$#" > 0 )) || return 0 + printf '%s\n' "$@" +} + +printWords() { + (( "$#" > 0 )) || return 0 + printf '%s ' "$@" +} + +###################################################################### +# Initialisation. + + +# Set a fallback default value for SOURCE_DATE_EPOCH, used by some +# build tools to provide a deterministic substitute for the "current" +# time. Note that 1 = 1970-01-01 00:00:01. We don't use 0 because it +# confuses some applications. +export SOURCE_DATE_EPOCH +: ${SOURCE_DATE_EPOCH:=1} + + +# Wildcard expansions that don't match should expand to an empty list. +# This ensures that, for instance, "for i in *; do ...; done" does the +# right thing. +shopt -s nullglob + + +# Set up the initial path. +PATH= +HOST_PATH= +for i in $initialPath; do + if [ "$i" = / ]; then i=; fi + addToSearchPath PATH "$i/bin" + + # For backward compatibility, we add initial path to HOST_PATH so + # it can be used in auto patch-shebangs. Unfortunately this will + # not work with cross compilation. + if [ -z "${strictDeps-}" ]; then + addToSearchPath HOST_PATH "$i/bin" + fi +done + +if (( "${NIX_DEBUG:-0}" >= 1 )); then + echo "initial path: $PATH" +fi + + +# Check that the pre-hook initialised SHELL. +if [ -z "${SHELL:-}" ]; then echo "SHELL not set"; exit 1; fi +BASH="$SHELL" +export CONFIG_SHELL="$SHELL" + + +# Execute the pre-hook. +if [ -z "${shell:-}" ]; then export shell="$SHELL"; fi +runHook preHook + + +# Allow the caller to augment buildInputs (it's not always possible to +# do this before the call to setup.sh, since the PATH is empty at that +# point; here we have a basic Unix environment). +runHook addInputsHook + + +# Package accumulators + +# shellcheck disable=SC2034 +declare -a pkgsBuildBuild pkgsBuildHost pkgsBuildTarget +declare -a pkgsHostHost pkgsHostTarget +declare -a pkgsTargetTarget + +declare -ra pkgBuildAccumVars=(pkgsBuildBuild pkgsBuildHost pkgsBuildTarget) +declare -ra pkgHostAccumVars=(pkgsHostHost pkgsHostTarget) +declare -ra pkgTargetAccumVars=(pkgsTargetTarget) + +declare -ra pkgAccumVarVars=(pkgBuildAccumVars pkgHostAccumVars pkgTargetAccumVars) + + +# Hooks + +declare -a envBuildBuildHooks envBuildHostHooks envBuildTargetHooks +declare -a envHostHostHooks envHostTargetHooks +declare -a envTargetTargetHooks + +declare -ra pkgBuildHookVars=(envBuildBuildHook envBuildHostHook envBuildTargetHook) +declare -ra pkgHostHookVars=(envHostHostHook envHostTargetHook) +declare -ra pkgTargetHookVars=(envTargetTargetHook) + +declare -ra pkgHookVarVars=(pkgBuildHookVars pkgHostHookVars pkgTargetHookVars) + +# Add env hooks for all sorts of deps with the specified host offset. +addEnvHooks() { + local depHostOffset="$1" + shift + local pkgHookVarsSlice="${pkgHookVarVars[$depHostOffset + 1]}[@]" + local pkgHookVar + for pkgHookVar in "${!pkgHookVarsSlice}"; do + eval "${pkgHookVar}s"'+=("$@")' + done +} + + +# Propagated dep files + +declare -ra propagatedBuildDepFiles=( + propagated-build-build-deps + propagated-native-build-inputs # Legacy name for back-compat + propagated-build-target-deps +) +declare -ra propagatedHostDepFiles=( + propagated-host-host-deps + propagated-build-inputs # Legacy name for back-compat +) +declare -ra propagatedTargetDepFiles=( + propagated-target-target-deps +) +declare -ra propagatedDepFilesVars=( + propagatedBuildDepFiles + propagatedHostDepFiles + propagatedTargetDepFiles +) + +# Platform offsets: build = -1, host = 0, target = 1 +declare -ra allPlatOffsets=(-1 0 1) + + +# Mutually-recursively find all build inputs. See the dependency section of the +# stdenv chapter of the Nixpkgs manual for the specification this algorithm +# implements. +findInputs() { + local -r pkg="$1" + local -ri hostOffset="$2" + local -ri targetOffset="$3" + + # Sanity check + (( "$hostOffset" <= "$targetOffset" )) || exit -1 + + local varVar="${pkgAccumVarVars[$hostOffset + 1]}" + local varRef="$varVar[\$targetOffset - \$hostOffset]" + local var="${!varRef}" + unset -v varVar varRef + + # TODO(@Ericson2314): Restore using associative array once Darwin + # nix-shell doesn't use impure bash. This should replace the O(n) + # case with an O(1) hash map lookup, assuming bash is implemented + # well :D. + local varSlice="$var[*]" + # ${..-} to hack around old bash empty array problem + case "${!varSlice-}" in + *" $pkg "*) return 0 ;; + esac + unset -v varSlice + + eval "$var"'+=("$pkg")' + + if ! [ -e "$pkg" ]; then + echo "build input $pkg does not exist" >&2 + exit 1 + fi + + # The current package's host and target offset together + # provide a <=-preserving homomorphism from the relative + # offsets to current offset + function mapOffset() { + local -ri inputOffset="$1" + if (( "$inputOffset" <= 0 )); then + local -ri outputOffset="$inputOffset + $hostOffset" + else + local -ri outputOffset="$inputOffset - 1 + $targetOffset" + fi + echo "$outputOffset" + } + + # Host offset relative to that of the package whose immediate + # dependencies we are currently exploring. + local -i relHostOffset + for relHostOffset in "${allPlatOffsets[@]}"; do + # `+ 1` so we start at 0 for valid index + local files="${propagatedDepFilesVars[$relHostOffset + 1]}" + + # Host offset relative to the package currently being + # built---as absolute an offset as will be used. + local -i hostOffsetNext + hostOffsetNext="$(mapOffset relHostOffset)" + + # Ensure we're in bounds relative to the package currently + # being built. + [[ "${allPlatOffsets[*]}" = *"$hostOffsetNext"* ]] || continue + + # Target offset relative to the *host* offset of the package + # whose immediate dependencies we are currently exploring. + local -i relTargetOffset + for relTargetOffset in "${allPlatOffsets[@]}"; do + (( "$relHostOffset" <= "$relTargetOffset" )) || continue + + local fileRef="${files}[$relTargetOffset - $relHostOffset]" + local file="${!fileRef}" + unset -v fileRef + + # Target offset relative to the package currently being + # built. + local -i targetOffsetNext + targetOffsetNext="$(mapOffset relTargetOffset)" + + # Once again, ensure we're in bounds relative to the + # package currently being built. + [[ "${allPlatOffsets[*]}" = *"$targetOffsetNext"* ]] || continue + + [[ -f "$pkg/nix-support/$file" ]] || continue + + local pkgNext + for pkgNext in $(< "$pkg/nix-support/$file"); do + findInputs "$pkgNext" "$hostOffsetNext" "$targetOffsetNext" + done + done + done +} + +# Make sure all are at least defined as empty +: ${depsBuildBuild=} ${depsBuildBuildPropagated=} +: ${nativeBuildInputs=} ${propagatedNativeBuildInputs=} ${defaultNativeBuildInputs=} +: ${depsBuildTarget=} ${depsBuildTargetPropagated=} +: ${depsHostHost=} ${depsHostHostPropagated=} +: ${buildInputs=} ${propagatedBuildInputs=} ${defaultBuildInputs=} +: ${depsTargetTarget=} ${depsTargetTargetPropagated=} + +for pkg in $depsBuildBuild $depsBuildBuildPropagated; do + findInputs "$pkg" -1 -1 +done +for pkg in $nativeBuildInputs $propagatedNativeBuildInputs; do + findInputs "$pkg" -1 0 +done +for pkg in $depsBuildTarget $depsBuildTargetPropagated; do + findInputs "$pkg" -1 1 +done +for pkg in $depsHostHost $depsHostHostPropagated; do + findInputs "$pkg" 0 0 +done +for pkg in $buildInputs $propagatedBuildInputs ; do + findInputs "$pkg" 0 1 +done +for pkg in $depsTargetTarget $depsTargetTargetPropagated; do + findInputs "$pkg" 1 1 +done +# Default inputs must be processed last +for pkg in $defaultNativeBuildInputs; do + findInputs "$pkg" -1 0 +done +for pkg in $defaultBuildInputs; do + findInputs "$pkg" 0 1 +done + +# Add package to the future PATH and run setup hooks +activatePackage() { + local pkg="$1" + local -ri hostOffset="$2" + local -ri targetOffset="$3" + + # Sanity check + (( "$hostOffset" <= "$targetOffset" )) || exit -1 + + if [ -f "$pkg" ]; then + local oldOpts="$(shopt -po nounset)" + set +u + source "$pkg" + eval "$oldOpts" + fi + + # Only dependencies whose host platform is guaranteed to match the + # build platform are included here. That would be `depsBuild*`, + # and legacy `nativeBuildInputs`, in general. If we aren't cross + # compiling, however, everything can be put on the PATH. To ease + # the transition, we do include everything in thatcase. + # + # TODO(@Ericson2314): Don't special-case native compilation + if [[ ( -z "${strictDeps-}" || "$hostOffset" -le -1 ) && -d "$pkg/bin" ]]; then + addToSearchPath _PATH "$pkg/bin" + fi + + if [[ "$hostOffset" -eq 0 && -d "$pkg/bin" ]]; then + addToSearchPath _HOST_PATH "$pkg/bin" + fi + + if [[ -f "$pkg/nix-support/setup-hook" ]]; then + local oldOpts="$(shopt -po nounset)" + set +u + source "$pkg/nix-support/setup-hook" + eval "$oldOpts" + fi +} + +_activatePkgs() { + local -i hostOffset targetOffset + local pkg + + for hostOffset in "${allPlatOffsets[@]}"; do + local pkgsVar="${pkgAccumVarVars[$hostOffset + 1]}" + for targetOffset in "${allPlatOffsets[@]}"; do + (( "$hostOffset" <= "$targetOffset" )) || continue + local pkgsRef="${pkgsVar}[$targetOffset - $hostOffset]" + local pkgsSlice="${!pkgsRef}[@]" + for pkg in ${!pkgsSlice+"${!pkgsSlice}"}; do + activatePackage "$pkg" "$hostOffset" "$targetOffset" + done + done + done +} + +# Run the package setup hooks and build _PATH +_activatePkgs + +# Set the relevant environment variables to point to the build inputs +# found above. +# +# These `depOffset`s, beyond indexing the arrays, also tell the env +# hook what sort of dependency (ignoring propagatedness) is being +# passed to the env hook. In a real language, we'd append a closure +# with this information to the relevant env hook array, but bash +# doesn't have closures, so it's easier to just pass this in. +_addToEnv() { + local -i depHostOffset depTargetOffset + local pkg + + for depHostOffset in "${allPlatOffsets[@]}"; do + local hookVar="${pkgHookVarVars[$depHostOffset + 1]}" + local pkgsVar="${pkgAccumVarVars[$depHostOffset + 1]}" + for depTargetOffset in "${allPlatOffsets[@]}"; do + (( "$depHostOffset" <= "$depTargetOffset" )) || continue + local hookRef="${hookVar}[$depTargetOffset - $depHostOffset]" + if [[ -z "${strictDeps-}" ]]; then + + # Keep track of which packages we have visited before. + local visitedPkgs="" + + # Apply environment hooks to all packages during native + # compilation to ease the transition. + # + # TODO(@Ericson2314): Don't special-case native compilation + for pkg in \ + ${pkgsBuildBuild+"${pkgsBuildBuild[@]}"} \ + ${pkgsBuildHost+"${pkgsBuildHost[@]}"} \ + ${pkgsBuildTarget+"${pkgsBuildTarget[@]}"} \ + ${pkgsHostHost+"${pkgsHostHost[@]}"} \ + ${pkgsHostTarget+"${pkgsHostTarget[@]}"} \ + ${pkgsTargetTarget+"${pkgsTargetTarget[@]}"} + do + if [[ "$visitedPkgs" = *"$pkg"* ]]; then + continue + fi + runHook "${!hookRef}" "$pkg" + visitedPkgs+=" $pkg" + done + else + local pkgsRef="${pkgsVar}[$depTargetOffset - $depHostOffset]" + local pkgsSlice="${!pkgsRef}[@]" + for pkg in ${!pkgsSlice+"${!pkgsSlice}"}; do + runHook "${!hookRef}" "$pkg" + done + fi + done + done +} + +# Run the package-specific hooks set by the setup-hook scripts. +_addToEnv + + +_addRpathPrefix "$out" + + +# Set the TZ (timezone) environment variable, otherwise commands like +# `date' will complain (e.g., `Tue Mar 9 10:01:47 Local time zone must +# be set--see zic manual page 2004'). +export TZ=UTC + + +# Set the prefix. This is generally $out, but it can be overriden, +# for instance if we just want to perform a test build/install to a +# temporary location and write a build report to $out. +if [ -z "${prefix:-}" ]; then + prefix="$out"; +fi + +if [ "${useTempPrefix:-}" = 1 ]; then + prefix="$NIX_BUILD_TOP/tmp_prefix"; +fi + + +PATH="${_PATH-}${_PATH:+${PATH:+:}}$PATH" +HOST_PATH="${_HOST_PATH-}${_HOST_PATH:+${HOST_PATH:+:}}$HOST_PATH" +if (( "${NIX_DEBUG:-0}" >= 1 )); then + echo "final path: $PATH" + echo "final host path: $HOST_PATH" +fi + +unset _PATH +unset _HOST_PATH + + +# Make GNU Make produce nested output. +export NIX_INDENT_MAKE=1 + + +# Normalize the NIX_BUILD_CORES variable. The value might be 0, which +# means that we're supposed to try and auto-detect the number of +# available CPU cores at run-time. + +if [ -z "${NIX_BUILD_CORES:-}" ]; then + NIX_BUILD_CORES="1" +elif [ "$NIX_BUILD_CORES" -le 0 ]; then + NIX_BUILD_CORES=$(nproc 2>/dev/null || true) + if expr >/dev/null 2>&1 "$NIX_BUILD_CORES" : "^[0-9][0-9]*$"; then + : + else + NIX_BUILD_CORES="1" + fi +fi +export NIX_BUILD_CORES + + +# Prevent SSL libraries from using certificates in /etc/ssl, unless set explicitly. +# Leave it in impure shells for convenience. +if [ -z "${NIX_SSL_CERT_FILE:-}" ] && [ "${IN_NIX_SHELL:-}" != "impure" ]; then + export NIX_SSL_CERT_FILE=/no-cert-file.crt +fi +# Another variant left for compatibility. +if [ -z "${SSL_CERT_FILE:-}" ] && [ "${IN_NIX_SHELL:-}" != "impure" ]; then + export SSL_CERT_FILE=/no-cert-file.crt +fi + + +###################################################################### +# Textual substitution functions. + + +substituteStream() { + local var=$1 + local description=$2 + shift 2 + + while (( "$#" )); do + case "$1" in + --replace) + pattern="$2" + replacement="$3" + shift 3 + local savedvar + savedvar="${!var}" + eval "$var"'=${'"$var"'//"$pattern"/"$replacement"}' + if [ "$pattern" != "$replacement" ]; then + if [ "${!var}" == "$savedvar" ]; then + echo "substituteStream(): WARNING: pattern '$pattern' doesn't match anything in $description" >&2 + fi + fi + ;; + + --subst-var) + local varName="$2" + shift 2 + # check if the used nix attribute name is a valid bash name + if ! [[ "$varName" =~ ^[a-zA-Z_][a-zA-Z0-9_]*$ ]]; then + echo "substituteStream(): ERROR: substitution variables must be valid Bash names, \"$varName\" isn't." >&2 + return 1 + fi + if [ -z ${!varName+x} ]; then + echo "substituteStream(): ERROR: variable \$$varName is unset" >&2 + return 1 + fi + pattern="@$varName@" + replacement="${!varName}" + eval "$var"'=${'"$var"'//"$pattern"/"$replacement"}' + ;; + + --subst-var-by) + pattern="@$2@" + replacement="$3" + eval "$var"'=${'"$var"'//"$pattern"/"$replacement"}' + shift 3 + ;; + + *) + echo "substituteStream(): ERROR: Invalid command line argument: $1" >&2 + return 1 + ;; + esac + done + + printf "%s" "${!var}" +} + +consumeEntire() { + # read returns non-0 on EOF, so we want read to fail + if IFS='' read -r -N 0 $1; then + echo "consumeEntire(): ERROR: Input null bytes, won't process" >&2 + return 1 + fi +} + +substitute() { + local input="$1" + local output="$2" + shift 2 + + if [ ! -f "$input" ]; then + echo "substitute(): ERROR: file '$input' does not exist" >&2 + return 1 + fi + + local content + consumeEntire content < "$input" + + if [ -e "$output" ]; then chmod +w "$output"; fi + substituteStream content "file '$input'" "$@" > "$output" +} + +substituteInPlace() { + local fileName="$1" + shift + substitute "$fileName" "$fileName" "$@" +} + +_allFlags() { + for varName in $(awk 'BEGIN { for (v in ENVIRON) if (v ~ /^[a-z][a-zA-Z0-9_]*$/) print v }'); do + if (( "${NIX_DEBUG:-0}" >= 1 )); then + printf "@%s@ -> %q\n" "${varName}" "${!varName}" + fi + args+=("--subst-var" "$varName") + done +} + +substituteAllStream() { + local -a args=() + _allFlags + + substituteStream "$1" "$2" "${args[@]}" +} + +# Substitute all environment variables that start with a lowercase character and +# are valid Bash names. +substituteAll() { + local input="$1" + local output="$2" + + local -a args=() + _allFlags + + substitute "$input" "$output" "${args[@]}" +} + + +substituteAllInPlace() { + local fileName="$1" + shift + substituteAll "$fileName" "$fileName" "$@" +} + + +###################################################################### +# What follows is the generic builder. + + +# This function is useful for debugging broken Nix builds. It dumps +# all environment variables to a file `env-vars' in the build +# directory. If the build fails and the `-K' option is used, you can +# then go to the build directory and source in `env-vars' to reproduce +# the environment used for building. +dumpVars() { + if [ "${noDumpEnvVars:-0}" != 1 ]; then + export > "$NIX_BUILD_TOP/env-vars" || true + fi +} + + +# Utility function: echo the base name of the given path, with the +# prefix `HASH-' removed, if present. +stripHash() { + local strippedName + # On separate line for `set -e` + strippedName="$(basename "$1")" + if echo "$strippedName" | grep -q '^[a-z0-9]\{32\}-'; then + echo "$strippedName" | cut -c34- + else + echo "$strippedName" + fi +} + + +unpackCmdHooks+=(_defaultUnpack) +_defaultUnpack() { + local fn="$1" + + if [ -d "$fn" ]; then + + # We can't preserve hardlinks because they may have been + # introduced by store optimization, which might break things + # in the build. + cp -pr --reflink=auto -- "$fn" "$(stripHash "$fn")" + + else + + case "$fn" in + *.tar.xz | *.tar.lzma | *.txz) + # Don't rely on tar knowing about .xz. + xz -d < "$fn" | tar xf - + ;; + *.tar | *.tar.* | *.tgz | *.tbz2 | *.tbz) + # GNU tar can automatically select the decompression method + # (info "(tar) gzip"). + tar xf "$fn" + ;; + *) + return 1 + ;; + esac + + fi +} + + +unpackFile() { + curSrc="$1" + header "unpacking source archive $curSrc" 3 + if ! runOneHook unpackCmd "$curSrc"; then + echo "do not know how to unpack source archive $curSrc" + exit 1 + fi +} + + +unpackPhase() { + runHook preUnpack + + if [ -z "${srcs:-}" ]; then + if [ -z "${src:-}" ]; then + # shellcheck disable=SC2016 + echo 'variable $src or $srcs should point to the source' + exit 1 + fi + srcs="$src" + fi + + # To determine the source directory created by unpacking the + # source archives, we record the contents of the current + # directory, then look below which directory got added. Yeah, + # it's rather hacky. + local dirsBefore="" + for i in *; do + if [ -d "$i" ]; then + dirsBefore="$dirsBefore $i " + fi + done + + # Unpack all source archives. + for i in $srcs; do + unpackFile "$i" + done + + # Find the source directory. + + # set to empty if unset + : ${sourceRoot=} + + if [ -n "${setSourceRoot:-}" ]; then + runOneHook setSourceRoot + elif [ -z "$sourceRoot" ]; then + for i in *; do + if [ -d "$i" ]; then + case $dirsBefore in + *\ $i\ *) + ;; + *) + if [ -n "$sourceRoot" ]; then + echo "unpacker produced multiple directories" + exit 1 + fi + sourceRoot="$i" + ;; + esac + fi + done + fi + + if [ -z "$sourceRoot" ]; then + echo "unpacker appears to have produced no directories" + exit 1 + fi + + echo "source root is $sourceRoot" + + # By default, add write permission to the sources. This is often + # necessary when sources have been copied from other store + # locations. + if [ "${dontMakeSourcesWritable:-0}" != 1 ]; then + chmod -R u+w -- "$sourceRoot" + fi + + runHook postUnpack +} + + +patchPhase() { + runHook prePatch + + for i in ${patches:-}; do + header "applying patch $i" 3 + local uncompress=cat + case "$i" in + *.gz) + uncompress="gzip -d" + ;; + *.bz2) + uncompress="bzip2 -d" + ;; + *.xz) + uncompress="xz -d" + ;; + *.lzma) + uncompress="lzma -d" + ;; + esac + # "2>&1" is a hack to make patch fail if the decompressor fails (nonexistent patch, etc.) + # shellcheck disable=SC2086 + $uncompress < "$i" 2>&1 | patch ${patchFlags:--p1} + done + + runHook postPatch +} + + +fixLibtool() { + sed -i -e 's^eval sys_lib_.*search_path=.*^^' "$1" +} + + +configurePhase() { + runHook preConfigure + + # set to empty if unset + : ${configureScript=} + : ${configureFlags=} + + if [[ -z "$configureScript" && -x ./configure ]]; then + configureScript=./configure + fi + + if [ -z "${dontFixLibtool:-}" ]; then + local i + find . -iname "ltmain.sh" -print0 | while IFS='' read -r -d '' i; do + echo "fixing libtool script $i" + fixLibtool "$i" + done + fi + + if [[ -z "${dontAddPrefix:-}" && -n "$prefix" ]]; then + configureFlags="${prefixKey:---prefix=}$prefix $configureFlags" + fi + + # Add --disable-dependency-tracking to speed up some builds. + if [ -z "${dontAddDisableDepTrack:-}" ]; then + if [ -f "$configureScript" ] && grep -q dependency-tracking "$configureScript"; then + configureFlags="--disable-dependency-tracking $configureFlags" + fi + fi + + # By default, disable static builds. + if [ -z "${dontDisableStatic:-}" ]; then + if [ -f "$configureScript" ] && grep -q enable-static "$configureScript"; then + configureFlags="--disable-static $configureFlags" + fi + fi + + if [ -n "$configureScript" ]; then + # Old bash empty array hack + # shellcheck disable=SC2086 + local flagsArray=( + $configureFlags ${configureFlagsArray+"${configureFlagsArray[@]}"} + ) + echoCmd 'configure flags' "${flagsArray[@]}" + # shellcheck disable=SC2086 + $configureScript "${flagsArray[@]}" + unset flagsArray + else + echo "no configure script, doing nothing" + fi + + runHook postConfigure +} + + +buildPhase() { + runHook preBuild + + # set to empty if unset + : ${makeFlags=} + + if [[ -z "$makeFlags" && -z "${makefile:-}" && ! ( -e Makefile || -e makefile || -e GNUmakefile ) ]]; then + echo "no Makefile, doing nothing" + else + foundMakefile=1 + + # Old bash empty array hack + # shellcheck disable=SC2086 + local flagsArray=( + ${enableParallelBuilding:+-j${NIX_BUILD_CORES} -l${NIX_BUILD_CORES}} + SHELL=$SHELL + $makeFlags ${makeFlagsArray+"${makeFlagsArray[@]}"} + $buildFlags ${buildFlagsArray+"${buildFlagsArray[@]}"} + ) + + echoCmd 'build flags' "${flagsArray[@]}" + make ${makefile:+-f $makefile} "${flagsArray[@]}" + unset flagsArray + fi + + runHook postBuild +} + + +checkPhase() { + runHook preCheck + + if [[ -z "${foundMakefile:-}" ]]; then + echo "no Makefile or custom buildPhase, doing nothing" + runHook postCheck + return + fi + + if [[ -z "${checkTarget:-}" ]]; then + #TODO(@oxij): should flagsArray influence make -n? + if make -n ${makefile:+-f $makefile} check >/dev/null 2>&1; then + checkTarget=check + elif make -n ${makefile:+-f $makefile} test >/dev/null 2>&1; then + checkTarget=test + fi + fi + + if [[ -z "${checkTarget:-}" ]]; then + echo "no check/test target in ${makefile:-Makefile}, doing nothing" + else + # Old bash empty array hack + # shellcheck disable=SC2086 + local flagsArray=( + ${enableParallelChecking:+-j${NIX_BUILD_CORES} -l${NIX_BUILD_CORES}} + SHELL=$SHELL + $makeFlags ${makeFlagsArray+"${makeFlagsArray[@]}"} + ${checkFlags:-VERBOSE=y} ${checkFlagsArray+"${checkFlagsArray[@]}"} + ${checkTarget} + ) + + echoCmd 'check flags' "${flagsArray[@]}" + make ${makefile:+-f $makefile} "${flagsArray[@]}" + + unset flagsArray + fi + + runHook postCheck +} + + +installPhase() { + runHook preInstall + + if [ -n "$prefix" ]; then + mkdir -p "$prefix" + fi + + # Old bash empty array hack + # shellcheck disable=SC2086 + local flagsArray=( + SHELL=$SHELL + $makeFlags ${makeFlagsArray+"${makeFlagsArray[@]}"} + $installFlags ${installFlagsArray+"${installFlagsArray[@]}"} + ${installTargets:-install} + ) + + echoCmd 'install flags' "${flagsArray[@]}" + make ${makefile:+-f $makefile} "${flagsArray[@]}" + unset flagsArray + + runHook postInstall +} + + +# The fixup phase performs generic, package-independent stuff, like +# stripping binaries, running patchelf and setting +# propagated-build-inputs. +fixupPhase() { + # Make sure everything is writable so "strip" et al. work. + local output + for output in $outputs; do + if [ -e "${!output}" ]; then chmod -R u+w "${!output}"; fi + done + + runHook preFixup + + # Apply fixup to each output. + local output + for output in $outputs; do + prefix="${!output}" runHook fixupOutput + done + + + # Propagate dependencies & setup hook into the development output. + declare -ra flatVars=( + # Build + depsBuildBuildPropagated + propagatedNativeBuildInputs + depsBuildTargetPropagated + # Host + depsHostHostPropagated + propagatedBuildInputs + # Target + depsTargetTargetPropagated + ) + declare -ra flatFiles=( + "${propagatedBuildDepFiles[@]}" + "${propagatedHostDepFiles[@]}" + "${propagatedTargetDepFiles[@]}" + ) + + local propagatedInputsIndex + for propagatedInputsIndex in "${!flatVars[@]}"; do + local propagatedInputsSlice="${flatVars[$propagatedInputsIndex]}[@]" + local propagatedInputsFile="${flatFiles[$propagatedInputsIndex]}" + + [[ "${!propagatedInputsSlice}" ]] || continue + + mkdir -p "${!outputDev}/nix-support" + # shellcheck disable=SC2086 + printWords ${!propagatedInputsSlice} > "${!outputDev}/nix-support/$propagatedInputsFile" + done + + + if [ -n "${setupHook:-}" ]; then + mkdir -p "${!outputDev}/nix-support" + substituteAll "$setupHook" "${!outputDev}/nix-support/setup-hook" + fi + + # TODO(@Ericson2314): Remove after https://github.com/NixOS/nixpkgs/pull/31414 + if [ -n "${setupHooks:-}" ]; then + mkdir -p "${!outputDev}/nix-support" + local hook + for hook in $setupHooks; do + local content + consumeEntire content < "$hook" + substituteAllStream content "file '$hook'" >> "${!outputDev}/nix-support/setup-hook" + unset -v content + done + unset -v hook + fi + + # Propagate user-env packages into the output with binaries, TODO? + + if [ -n "${propagatedUserEnvPkgs:-}" ]; then + mkdir -p "${!outputBin}/nix-support" + # shellcheck disable=SC2086 + printWords $propagatedUserEnvPkgs > "${!outputBin}/nix-support/propagated-user-env-packages" + fi + + runHook postFixup +} + + +installCheckPhase() { + runHook preInstallCheck + + if [[ -z "${foundMakefile:-}" ]]; then + echo "no Makefile or custom buildPhase, doing nothing" + #TODO(@oxij): should flagsArray influence make -n? + elif [[ -z "${installCheckTarget:-}" ]] \ + && ! make -n ${makefile:+-f $makefile} ${installCheckTarget:-installcheck} >/dev/null 2>&1; then + echo "no installcheck target in ${makefile:-Makefile}, doing nothing" + else + # Old bash empty array hack + # shellcheck disable=SC2086 + local flagsArray=( + ${enableParallelChecking:+-j${NIX_BUILD_CORES} -l${NIX_BUILD_CORES}} + SHELL=$SHELL + $makeFlags ${makeFlagsArray+"${makeFlagsArray[@]}"} + $installCheckFlags ${installCheckFlagsArray+"${installCheckFlagsArray[@]}"} + ${installCheckTarget:-installcheck} + ) + + echoCmd 'installcheck flags' "${flagsArray[@]}" + make ${makefile:+-f $makefile} "${flagsArray[@]}" + unset flagsArray + fi + + runHook postInstallCheck +} + + +distPhase() { + runHook preDist + + # Old bash empty array hack + # shellcheck disable=SC2086 + local flagsArray=( + $distFlags ${distFlagsArray+"${distFlagsArray[@]}"} ${distTarget:-dist} + ) + + echo 'dist flags: %q' "${flagsArray[@]}" + make ${makefile:+-f $makefile} "${flagsArray[@]}" + + if [ "${dontCopyDist:-0}" != 1 ]; then + mkdir -p "$out/tarballs" + + # Note: don't quote $tarballs, since we explicitly permit + # wildcards in there. + # shellcheck disable=SC2086 + cp -pvd ${tarballs:-*.tar.gz} "$out/tarballs" + fi + + runHook postDist +} + + +showPhaseHeader() { + local phase="$1" + case "$phase" in + unpackPhase) header "unpacking sources";; + patchPhase) header "patching sources";; + configurePhase) header "configuring";; + buildPhase) header "building";; + checkPhase) header "running tests";; + installPhase) header "installing";; + fixupPhase) header "post-installation fixup";; + installCheckPhase) header "running install tests";; + *) header "$phase";; + esac +} + + +genericBuild() { + if [ -f "${buildCommandPath:-}" ]; then + local oldOpts="$(shopt -po nounset)" + set +u + source "$buildCommandPath" + eval "$oldOpts" + return + fi + if [ -n "${buildCommand:-}" ]; then + local oldOpts="$(shopt -po nounset)" + set +u + eval "$buildCommand" + eval "$oldOpts" + return + fi + + if [ -z "${phases:-}" ]; then + phases="${prePhases:-} unpackPhase patchPhase ${preConfigurePhases:-} \ + configurePhase ${preBuildPhases:-} buildPhase checkPhase \ + ${preInstallPhases:-} installPhase ${preFixupPhases:-} fixupPhase installCheckPhase \ + ${preDistPhases:-} distPhase ${postPhases:-}"; + fi + + for curPhase in $phases; do + if [[ "$curPhase" = unpackPhase && -n "${dontUnpack:-}" ]]; then continue; fi + if [[ "$curPhase" = configurePhase && -n "${dontConfigure:-}" ]]; then continue; fi + if [[ "$curPhase" = buildPhase && -n "${dontBuild:-}" ]]; then continue; fi + if [[ "$curPhase" = checkPhase && -z "${doCheck:-}" ]]; then continue; fi + if [[ "$curPhase" = installPhase && -n "${dontInstall:-}" ]]; then continue; fi + if [[ "$curPhase" = fixupPhase && -n "${dontFixup:-}" ]]; then continue; fi + if [[ "$curPhase" = installCheckPhase && -z "${doInstallCheck:-}" ]]; then continue; fi + if [[ "$curPhase" = distPhase && -z "${doDist:-}" ]]; then continue; fi + + if [[ -n $NIX_LOG_FD ]]; then + echo "@nix { \"action\": \"setPhase\", \"phase\": \"$curPhase\" }" >&$NIX_LOG_FD + fi + + showPhaseHeader "$curPhase" + dumpVars + + # Evaluate the variable named $curPhase if it exists, otherwise the + # function named $curPhase. + local oldOpts="$(shopt -po nounset)" + set +u + eval "${!curPhase:-$curPhase}" + eval "$oldOpts" + + if [ "$curPhase" = unpackPhase ]; then + cd "${sourceRoot:-.}" + fi + done +} + + +# Execute the post-hooks. +runHook postHook + + +# Execute the global user hook (defined through the Nixpkgs +# configuration option ‘stdenv.userHook’). This can be used to set +# global compiler optimisation flags, for instance. +runHook userHook + + +dumpVars + +# Disable nounset for nix-shell. +set +u diff --git a/nixpkgs/pkgs/stdenv/linux/bootstrap-files/aarch64-musl.nix b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/aarch64-musl.nix new file mode 100644 index 000000000000..ff0eec893f2f --- /dev/null +++ b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/aarch64-musl.nix @@ -0,0 +1,11 @@ +{ + busybox = import <nix/fetchurl.nix> { + url = https://wdtz.org/files/wjzsj9cmdkc70f78yh072483x8656nci-stdenv-bootstrap-tools-aarch64-unknown-linux-musl/on-server/busybox; + sha256 = "01s6bwq84wyrjh3rdsgxni9gkzp7ss8rghg0cmp8zd87l79y8y4g"; + executable = true; + }; + bootstrapTools = import <nix/fetchurl.nix> { + url = https://wdtz.org/files/wjzsj9cmdkc70f78yh072483x8656nci-stdenv-bootstrap-tools-aarch64-unknown-linux-musl/on-server/bootstrap-tools.tar.xz; + sha256 = "0pbqrw9z4ifkijpfpx15l2dzi00rq8c5zg9ghimz5qgr5dx7f7cl"; + }; +} diff --git a/nixpkgs/pkgs/stdenv/linux/bootstrap-files/aarch64.nix b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/aarch64.nix new file mode 100644 index 000000000000..ca7e84502ab3 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/aarch64.nix @@ -0,0 +1,11 @@ +{ + busybox = import <nix/fetchurl.nix> { + url = http://nixos-arm.dezgeg.me/bootstrap-aarch64-2017-03-11-bb3ef8/busybox; + sha256 = "12qcml1l67skpjhfjwy7gr10nc86gqcwjmz9ggp7knss8gq8pv7f"; + executable = true; + }; + bootstrapTools = import <nix/fetchurl.nix> { + url = http://nixos-arm.dezgeg.me/bootstrap-aarch64-2017-03-11-bb3ef8/bootstrap-tools.tar.xz; + sha256 = "1075d5n4yclbhgisi6ba50601mw3fhivlkjs462qlnq8hh0xc7nq"; + }; +} diff --git a/nixpkgs/pkgs/stdenv/linux/bootstrap-files/armv5tel.nix b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/armv5tel.nix new file mode 100644 index 000000000000..37471e9ce426 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/armv5tel.nix @@ -0,0 +1,12 @@ +{ + busybox = import <nix/fetchurl.nix> { + url = http://nixos-arm.dezgeg.me/bootstrap-2017-04-13-1f32d4b4/armv5tel/busybox; + sha256 = "00mxas5xg2j9n1g0q0nklr0dy87qqxk0jja5qz1yi7xl7zzsnpnw"; + executable = true; + }; + + bootstrapTools = import <nix/fetchurl.nix> { + url = http://nixos-arm.dezgeg.me/bootstrap-2017-04-13-1f32d4b4/armv5tel/bootstrap-tools.tar.xz; + sha256 = "0fhiy9l3mbmlhpkby31c2s63bhjiqx25qqr3wdp8cb7fxz8ayx2f"; + }; +} diff --git a/nixpkgs/pkgs/stdenv/linux/bootstrap-files/armv6l-musl.nix b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/armv6l-musl.nix new file mode 100644 index 000000000000..45ac0d5f9acd --- /dev/null +++ b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/armv6l-musl.nix @@ -0,0 +1,11 @@ +{ + busybox = import <nix/fetchurl.nix> { + url = https://wdtz.org/files/xmz441m69qrlfdw47l2k10zf87fsya6r-stdenv-bootstrap-tools-armv6l-unknown-linux-musleabihf/on-server/busybox; + sha256 = "01d0hp1xgrriiy9w0sd9vbqzwxnpwiyah80pi4vrpcmbwji36j1i"; + executable = true; + }; + bootstrapTools = import <nix/fetchurl.nix> { + url = https://wdtz.org/files/xmz441m69qrlfdw47l2k10zf87fsya6r-stdenv-bootstrap-tools-armv6l-unknown-linux-musleabihf/on-server/bootstrap-tools.tar.xz; + sha256 = "1r9mz9w8y5jd7gfwfsrvs20qarzxy7bvrp5dlm41hnx6z617if1h"; + }; +} diff --git a/nixpkgs/pkgs/stdenv/linux/bootstrap-files/armv6l.nix b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/armv6l.nix new file mode 100644 index 000000000000..447189756821 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/armv6l.nix @@ -0,0 +1,12 @@ +{ + busybox = import <nix/fetchurl.nix> { + url = http://nixos-arm.dezgeg.me/bootstrap-2017-04-13-1f32d4b4/armv6l/busybox; + sha256 = "06n8dy8y2v28yx9ws8x64wxrvn9pszgpd299hc90nv9x21m79jzd"; + executable = true; + }; + + bootstrapTools = import <nix/fetchurl.nix> { + url = http://nixos-arm.dezgeg.me/bootstrap-2017-04-13-1f32d4b4/armv6l/bootstrap-tools.tar.xz; + sha256 = "1gg2q3sw81vi65g1gmpvx0nnd6hxb76vlz73wfp292m90z1mym7f"; + }; +} diff --git a/nixpkgs/pkgs/stdenv/linux/bootstrap-files/armv7l.nix b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/armv7l.nix new file mode 100644 index 000000000000..b97fd9967eae --- /dev/null +++ b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/armv7l.nix @@ -0,0 +1,12 @@ +{ + busybox = import <nix/fetchurl.nix> { + url = http://nixos-arm.dezgeg.me/bootstrap-2017-04-13-1f32d4b4/armv7l/busybox; + sha256 = "187xwzsng5lpak1nanrk88y4mlydmrbhx6la00rrd6kjx376s565"; + executable = true; + }; + + bootstrapTools = import <nix/fetchurl.nix> { + url = http://nixos-arm.dezgeg.me/bootstrap-2017-04-13-1f32d4b4/armv7l/bootstrap-tools.tar.xz; + sha256 = "05ayki2kak3i5lw97qidd5h9jv00dmlhx9h7l771bj331yamyqdn"; + }; +} diff --git a/nixpkgs/pkgs/stdenv/linux/bootstrap-files/i686.nix b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/i686.nix new file mode 100644 index 000000000000..cf484fd92533 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/i686.nix @@ -0,0 +1,12 @@ +{ + busybox = import <nix/fetchurl.nix> { + url = http://tarballs.nixos.org/stdenv-linux/i686/4907fc9e8d0d82b28b3c56e3a478a2882f1d700f/busybox; + sha256 = "ef4c1be6c7ae57e4f654efd90ae2d2e204d6769364c46469fa9ff3761195cba1"; + executable = true; + }; + + bootstrapTools = import <nix/fetchurl.nix> { + url = http://tarballs.nixos.org/stdenv-linux/i686/4907fc9e8d0d82b28b3c56e3a478a2882f1d700f/bootstrap-tools.tar.xz; + sha256 = "cf920d26d94335f5cb46e247455d0e5389765d16a2b8fc233b792a655b5b58aa"; + }; +} diff --git a/nixpkgs/pkgs/stdenv/linux/bootstrap-files/loongson2f.nix b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/loongson2f.nix new file mode 100644 index 000000000000..8e22a274974a --- /dev/null +++ b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/loongson2f.nix @@ -0,0 +1,44 @@ +let + + fetch = { file, sha256 }: import <nix/fetchurl.nix> { + url = "http://tarballs.nixos.org/stdenv-linux/loongson2f/r22849/${file}"; + inherit sha256; + executable = true; + }; + +in { + sh = fetch { + file = "sh"; + sha256 = "02jjl49wdq85pgh61aqf78yaknn9mi3rcspbpk7hs9c4mida2rhf"; + }; + + bzip2 = fetch { + file = "bzip2"; + sha256 = "1qn27y3amj9c6mnjk2kyb59y0d2w4yv16z9apaxx91hyq19gf29z"; + }; + + mkdir = fetch { + file = "mkdir"; + sha256 = "1vbp2bv9hkyb2fwl8hjrffpywn1wrl1kc4yrwi2lirawlnc6kymh"; + }; + + cpio = fetch { + file = "cpio"; + sha256 = "0mqxwdx0sl7skxx6049mk35l7d0fnibqsv174284kdp4p7iixwa0"; + }; + + ln = fetch { + file = "ln"; + sha256 = "05lwx8qvga3yv8xhs8bjgsfygsfrcxsfck0lxw6gsdckx25fgi7s"; + }; + + curl = fetch { + file = "curl.bz2"; + sha256 = "0iblnz4my54gryac04i64fn3ksi9g3dx96yjq93fj39z6kx6151c"; + }; + + bootstrapTools = { + url = "http://tarballs.nixos.org/stdenv-linux/loongson2f/r22849/cross-bootstrap-tools.cpio.bz2"; + sha256 = "00aavbk76qjj2gdlmpaaj66r8nzl4d7pyl8cv1gigyzgpbr5vv3j"; + }; +} diff --git a/nixpkgs/pkgs/stdenv/linux/bootstrap-files/x86_64-musl.nix b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/x86_64-musl.nix new file mode 100644 index 000000000000..543c1c838492 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/x86_64-musl.nix @@ -0,0 +1,11 @@ +{ + busybox = import <nix/fetchurl.nix> { + url = https://wdtz.org/files/gywxhjgl70sxippa0pxs0vj5qcgz1wi8-stdenv-bootstrap-tools/on-server/busybox; + sha256 = "0779c2wn00467h76xpqil678gfi1y2p57c7zq2d917jsv2qj5009"; + executable = true; + }; + bootstrapTools = import <nix/fetchurl.nix> { + url = https://wdtz.org/files/gywxhjgl70sxippa0pxs0vj5qcgz1wi8-stdenv-bootstrap-tools/on-server/bootstrap-tools.tar.xz; + sha256 = "1dwiqw4xvnm0b5fdgl89lz2qq45f6s9icwxn6n6ams71xw0dbqyi"; + }; +} diff --git a/nixpkgs/pkgs/stdenv/linux/bootstrap-files/x86_64.nix b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/x86_64.nix new file mode 100644 index 000000000000..69d08c5e981a --- /dev/null +++ b/nixpkgs/pkgs/stdenv/linux/bootstrap-files/x86_64.nix @@ -0,0 +1,9 @@ +# Use busybox for i686-linux since it works on x86_64-linux as well. +(import ./i686.nix) // + +{ + bootstrapTools = import <nix/fetchurl.nix> { + url = http://tarballs.nixos.org/stdenv-linux/x86_64/4907fc9e8d0d82b28b3c56e3a478a2882f1d700f/bootstrap-tools.tar.xz; + sha256 = "abe3f0727dd771a60b7922892d308da1bc7b082afc13440880862f0c8823c09f"; + }; +} diff --git a/nixpkgs/pkgs/stdenv/linux/bootstrap-tools-musl/default.nix b/nixpkgs/pkgs/stdenv/linux/bootstrap-tools-musl/default.nix new file mode 100644 index 000000000000..6118585d545f --- /dev/null +++ b/nixpkgs/pkgs/stdenv/linux/bootstrap-tools-musl/default.nix @@ -0,0 +1,18 @@ +{ system, bootstrapFiles }: + +derivation { + name = "bootstrap-tools"; + + builder = bootstrapFiles.busybox; + + args = [ "ash" "-e" ./scripts/unpack-bootstrap-tools.sh ]; + + tarball = bootstrapFiles.bootstrapTools; + + inherit system; + + # Needed by the GCC wrapper. + langC = true; + langCC = true; + isGNU = true; +} diff --git a/nixpkgs/pkgs/stdenv/linux/bootstrap-tools-musl/scripts/unpack-bootstrap-tools.sh b/nixpkgs/pkgs/stdenv/linux/bootstrap-tools-musl/scripts/unpack-bootstrap-tools.sh new file mode 100644 index 000000000000..b160a748d8dc --- /dev/null +++ b/nixpkgs/pkgs/stdenv/linux/bootstrap-tools-musl/scripts/unpack-bootstrap-tools.sh @@ -0,0 +1,64 @@ +# Unpack the bootstrap tools tarball. +echo Unpacking the bootstrap tools... +$builder mkdir $out +< $tarball $builder unxz | $builder tar x -C $out + +# Set the ELF interpreter / RPATH in the bootstrap binaries. +echo Patching the bootstrap tools... + +if test -f $out/lib/ld.so.?; then + # MIPS case + LD_BINARY=$out/lib/ld.so.? +else + # i686, x86_64 and armv5tel + LD_BINARY=$out/lib/ld-*so.? +fi + +# On x86_64, ld-linux-x86-64.so.2 barfs on patchelf'ed programs. So +# use a copy of patchelf. +LD_LIBRARY_PATH=$out/lib $LD_BINARY $out/bin/cp $out/bin/patchelf . + +for i in $out/bin/* $out/libexec/gcc/*/*/*; do + if [ -L "$i" ]; then continue; fi + if [ -z "${i##*/liblto*}" ]; then continue; fi + echo patching "$i" + LD_LIBRARY_PATH=$out/lib $LD_BINARY \ + ./patchelf --set-interpreter $LD_BINARY --set-rpath $out/lib --force-rpath "$i" +done + +for i in $out/lib/libpcre* $out/lib/libc.so; do + if [ -L "$i" ]; then continue; fi + echo patching "$i" + $out/bin/patchelf --set-rpath $out/lib --force-rpath "$i" +done + +export PATH=$out/bin + +# Fix the libc linker script. +#cat $out/lib/libc.so | sed "s|/nix/store/e*-[^/]*/|$out/|g" > $out/lib/libc.so.tmp +#mv $out/lib/libc.so.tmp $out/lib/libc.so +#cat $out/lib/libpthread.so | sed "s|/nix/store/e*-[^/]*/|$out/|g" > $out/lib/libpthread.so.tmp +#mv $out/lib/libpthread.so.tmp $out/lib/libpthread.so + +# Provide some additional symlinks. +ln -s bash $out/bin/sh +ln -s bzip2 $out/bin/bunzip2 + +# Provide a gunzip script. +cat > $out/bin/gunzip <<EOF +#!$out/bin/sh +exec $out/bin/gzip -d "\$@" +EOF +chmod +x $out/bin/gunzip + +# Provide fgrep/egrep. +echo "#! $out/bin/sh" > $out/bin/egrep +echo "exec $out/bin/grep -E \"\$@\"" >> $out/bin/egrep +echo "#! $out/bin/sh" > $out/bin/fgrep +echo "exec $out/bin/grep -F \"\$@\"" >> $out/bin/fgrep + +# Provide xz (actually only xz -d will work). +echo "#! $out/bin/sh" > $out/bin/xz +echo "exec $builder unxz \"\$@\"" >> $out/bin/xz + +chmod +x $out/bin/egrep $out/bin/fgrep $out/bin/xz diff --git a/nixpkgs/pkgs/stdenv/linux/bootstrap-tools/default.nix b/nixpkgs/pkgs/stdenv/linux/bootstrap-tools/default.nix new file mode 100644 index 000000000000..6118585d545f --- /dev/null +++ b/nixpkgs/pkgs/stdenv/linux/bootstrap-tools/default.nix @@ -0,0 +1,18 @@ +{ system, bootstrapFiles }: + +derivation { + name = "bootstrap-tools"; + + builder = bootstrapFiles.busybox; + + args = [ "ash" "-e" ./scripts/unpack-bootstrap-tools.sh ]; + + tarball = bootstrapFiles.bootstrapTools; + + inherit system; + + # Needed by the GCC wrapper. + langC = true; + langCC = true; + isGNU = true; +} diff --git a/nixpkgs/pkgs/stdenv/linux/bootstrap-tools/scripts/unpack-bootstrap-tools.sh b/nixpkgs/pkgs/stdenv/linux/bootstrap-tools/scripts/unpack-bootstrap-tools.sh new file mode 100644 index 000000000000..64583f80fa8f --- /dev/null +++ b/nixpkgs/pkgs/stdenv/linux/bootstrap-tools/scripts/unpack-bootstrap-tools.sh @@ -0,0 +1,66 @@ +# Unpack the bootstrap tools tarball. +echo Unpacking the bootstrap tools... +$builder mkdir $out +< $tarball $builder unxz | $builder tar x -C $out + +# Set the ELF interpreter / RPATH in the bootstrap binaries. +echo Patching the bootstrap tools... + +if test -f $out/lib/ld.so.?; then + # MIPS case + LD_BINARY=$out/lib/ld.so.? +elif test -f $out/lib/ld64.so.?; then + # ppc64(le) + LD_BINARY=$out/lib/ld64.so.? +else + # i686, x86_64 and armv5tel + LD_BINARY=$out/lib/ld-*so.? +fi + +# On x86_64, ld-linux-x86-64.so.2 barfs on patchelf'ed programs. So +# use a copy of patchelf. +LD_LIBRARY_PATH=$out/lib $LD_BINARY $out/bin/cp $out/bin/patchelf . + +for i in $out/bin/* $out/libexec/gcc/*/*/*; do + if [ -L "$i" ]; then continue; fi + if [ -z "${i##*/liblto*}" ]; then continue; fi + echo patching "$i" + LD_LIBRARY_PATH=$out/lib $LD_BINARY \ + ./patchelf --set-interpreter $LD_BINARY --set-rpath $out/lib --force-rpath "$i" +done + +for i in $out/lib/librt-*.so $out/lib/libpcre*; do + if [ -L "$i" ]; then continue; fi + echo patching "$i" + $out/bin/patchelf --set-rpath $out/lib --force-rpath "$i" +done + +# Fix the libc linker script. +export PATH=$out/bin +cat $out/lib/libc.so | sed "s|/nix/store/e*-[^/]*/|$out/|g" > $out/lib/libc.so.tmp +mv $out/lib/libc.so.tmp $out/lib/libc.so +cat $out/lib/libpthread.so | sed "s|/nix/store/e*-[^/]*/|$out/|g" > $out/lib/libpthread.so.tmp +mv $out/lib/libpthread.so.tmp $out/lib/libpthread.so + +# Provide some additional symlinks. +ln -s bash $out/bin/sh +ln -s bzip2 $out/bin/bunzip2 + +# Provide a gunzip script. +cat > $out/bin/gunzip <<EOF +#!$out/bin/sh +exec $out/bin/gzip -d "\$@" +EOF +chmod +x $out/bin/gunzip + +# Provide fgrep/egrep. +echo "#! $out/bin/sh" > $out/bin/egrep +echo "exec $out/bin/grep -E \"\$@\"" >> $out/bin/egrep +echo "#! $out/bin/sh" > $out/bin/fgrep +echo "exec $out/bin/grep -F \"\$@\"" >> $out/bin/fgrep + +# Provide xz (actually only xz -d will work). +echo "#! $out/bin/sh" > $out/bin/xz +echo "exec $builder unxz \"\$@\"" >> $out/bin/xz + +chmod +x $out/bin/egrep $out/bin/fgrep $out/bin/xz diff --git a/nixpkgs/pkgs/stdenv/linux/default.nix b/nixpkgs/pkgs/stdenv/linux/default.nix new file mode 100644 index 000000000000..8344c9dfb2b8 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/linux/default.nix @@ -0,0 +1,390 @@ +# This file constructs the standard build environment for the +# Linux/i686 platform. It's completely pure; that is, it relies on no +# external (non-Nix) tools, such as /usr/bin/gcc, and it contains a C +# compiler and linker that do not search in default locations, +# ensuring purity of components produced by it. +{ lib +, localSystem, crossSystem, config, overlays, crossOverlays ? [] + +, bootstrapFiles ? + let table = { + glibc = { + i686-linux = import ./bootstrap-files/i686.nix; + x86_64-linux = import ./bootstrap-files/x86_64.nix; + armv5tel-linux = import ./bootstrap-files/armv5tel.nix; + armv6l-linux = import ./bootstrap-files/armv6l.nix; + armv7l-linux = import ./bootstrap-files/armv7l.nix; + aarch64-linux = import ./bootstrap-files/aarch64.nix; + mipsel-linux = import ./bootstrap-files/loongson2f.nix; + powerpc64le-linux = import ./bootstrap-files/ppc64le.nix; + }; + musl = { + aarch64-linux = import ./bootstrap-files/aarch64-musl.nix; + armv6l-linux = import ./bootstrap-files/armv6l-musl.nix; + x86_64-linux = import ./bootstrap-files/x86_64-musl.nix; + powerpc64le-linux = import ./bootstrap-files/ppc64le-musl.nix; + }; + }; + + # Try to find an architecture compatible with our current system. We + # just try every bootstrap we’ve got and test to see if it is + # compatible with or current architecture. + getCompatibleTools = lib.foldl (v: system: + if v != null then v + else if localSystem.isCompatible (lib.systems.elaborate { inherit system; }) then archLookupTable.${system} + else null) null (lib.attrNames archLookupTable); + + archLookupTable = table.${localSystem.libc} + or (abort "unsupported libc for the pure Linux stdenv"); + files = archLookupTable.${localSystem.system} or (if getCompatibleTools != null then getCompatibleTools + else (abort "unsupported platform for the pure Linux stdenv")); + in files +}: + +assert crossSystem == localSystem; + +let + inherit (localSystem) system platform; + + commonPreHook = + '' + export NIX_ENFORCE_PURITY="''${NIX_ENFORCE_PURITY-1}" + export NIX_ENFORCE_NO_NATIVE="''${NIX_ENFORCE_NO_NATIVE-1}" + ${if system == "x86_64-linux" then "NIX_LIB64_IN_SELF_RPATH=1" else ""} + ${if system == "mipsel-linux" then "NIX_LIB32_IN_SELF_RPATH=1" else ""} + ''; + + + # The bootstrap process proceeds in several steps. + + + # Create a standard environment by downloading pre-built binaries of + # coreutils, GCC, etc. + + + # Download and unpack the bootstrap tools (coreutils, GCC, Glibc, ...). + bootstrapTools = import (if localSystem.libc == "musl" then ./bootstrap-tools-musl else ./bootstrap-tools) { inherit system bootstrapFiles; }; + + getLibc = stage: stage.${localSystem.libc}; + + + # This function builds the various standard environments used during + # the bootstrap. In all stages, we build an stdenv and the package + # set that can be built with that stdenv. + stageFun = prevStage: + { name, overrides ? (self: super: {}), extraNativeBuildInputs ? [] }: + + let + + thisStdenv = import ../generic { + name = "${name}-stdenv-linux"; + buildPlatform = localSystem; + hostPlatform = localSystem; + targetPlatform = localSystem; + inherit config extraNativeBuildInputs; + preHook = + '' + # Don't patch #!/interpreter because it leads to retained + # dependencies on the bootstrapTools in the final stdenv. + dontPatchShebangs=1 + ${commonPreHook} + ''; + shell = "${bootstrapTools}/bin/bash"; + initialPath = [bootstrapTools]; + + fetchurlBoot = import ../../build-support/fetchurl/boot.nix { + inherit system; + }; + + cc = if prevStage.gcc-unwrapped == null + then null + else lib.makeOverridable (import ../../build-support/cc-wrapper) { + name = "${name}-gcc-wrapper"; + nativeTools = false; + nativeLibc = false; + buildPackages = lib.optionalAttrs (prevStage ? stdenv) { + inherit (prevStage) stdenv; + }; + cc = prevStage.gcc-unwrapped; + bintools = prevStage.binutils; + isGNU = true; + libc = getLibc prevStage; + inherit (prevStage) coreutils gnugrep; + stdenvNoCC = prevStage.ccWrapperStdenv; + }; + + extraAttrs = { + # Having the proper 'platform' in all the stdenvs allows getting proper + # linuxHeaders for example. + inherit platform; + }; + overrides = self: super: (overrides self super) // { fetchurl = thisStdenv.fetchurlBoot; }; + }; + + in { + inherit config overlays; + stdenv = thisStdenv; + }; + +in + +[ + + ({}: { + __raw = true; + + gcc-unwrapped = null; + binutils = null; + coreutils = null; + gnugrep = null; + }) + + # Build a dummy stdenv with no GCC or working fetchurl. This is + # because we need a stdenv to build the GCC wrapper and fetchurl. + (prevStage: stageFun prevStage { + name = "bootstrap-stage0"; + + overrides = self: super: { + # We thread stage0's stdenv through under this name so downstream stages + # can use it for wrapping gcc too. This way, downstream stages don't need + # to refer to this stage directly, which violates the principle that each + # stage should only access the stage that came before it. + ccWrapperStdenv = self.stdenv; + # The Glibc include directory cannot have the same prefix as the + # GCC include directory, since GCC gets confused otherwise (it + # will search the Glibc headers before the GCC headers). So + # create a dummy Glibc here, which will be used in the stdenv of + # stage1. + ${localSystem.libc} = self.stdenv.mkDerivation { + name = "bootstrap-stage0-${localSystem.libc}"; + buildCommand = '' + mkdir -p $out + ln -s ${bootstrapTools}/lib $out/lib + '' + lib.optionalString (localSystem.libc == "glibc") '' + ln -s ${bootstrapTools}/include-glibc $out/include + '' + lib.optionalString (localSystem.libc == "musl") '' + ln -s ${bootstrapTools}/include-libc $out/include + ''; + }; + gcc-unwrapped = bootstrapTools; + binutils = import ../../build-support/bintools-wrapper { + name = "bootstrap-stage0-binutils-wrapper"; + nativeTools = false; + nativeLibc = false; + buildPackages = { }; + libc = getLibc self; + inherit (self) stdenvNoCC coreutils gnugrep; + bintools = bootstrapTools; + }; + coreutils = bootstrapTools; + gnugrep = bootstrapTools; + }; + }) + + + # Create the first "real" standard environment. This one consists + # of bootstrap tools only, and a minimal Glibc to keep the GCC + # configure script happy. + # + # For clarity, we only use the previous stage when specifying these + # stages. So stageN should only ever have references for stage{N-1}. + # + # If we ever need to use a package from more than one stage back, we + # simply re-export those packages in the middle stage(s) using the + # overrides attribute and the inherit syntax. + (prevStage: stageFun prevStage { + name = "bootstrap-stage1"; + + # Rebuild binutils to use from stage2 onwards. + overrides = self: super: { + binutils-unwrapped = super.binutils-unwrapped.override { + gold = false; + }; + inherit (prevStage) + ccWrapperStdenv + gcc-unwrapped coreutils gnugrep; + + ${localSystem.libc} = getLibc prevStage; + + # A threaded perl build needs glibc/libpthread_nonshared.a, + # which is not included in bootstrapTools, so disable threading. + # This is not an issue for the final stdenv, because this perl + # won't be included in the final stdenv and won't be exported to + # top-level pkgs as an override either. + perl = super.perl.override { enableThreading = false; }; + }; + }) + + + # 2nd stdenv that contains our own rebuilt binutils and is used for + # compiling our own Glibc. + (prevStage: stageFun prevStage { + name = "bootstrap-stage2"; + + overrides = self: super: { + inherit (prevStage) + ccWrapperStdenv + gcc-unwrapped coreutils gnugrep + perl gnum4 bison; + # This also contains the full, dynamically linked, final Glibc. + binutils = prevStage.binutils.override { + # Rewrap the binutils with the new glibc, so both the next + # stage's wrappers use it. + libc = getLibc self; + }; + }; + }) + + + # Construct a third stdenv identical to the 2nd, except that this + # one uses the rebuilt Glibc from stage2. It still uses the recent + # binutils and rest of the bootstrap tools, including GCC. + (prevStage: stageFun prevStage { + name = "bootstrap-stage3"; + + overrides = self: super: rec { + inherit (prevStage) + ccWrapperStdenv + binutils coreutils gnugrep + perl patchelf linuxHeaders gnum4 bison; + ${localSystem.libc} = getLibc prevStage; + # Link GCC statically against GMP etc. This makes sense because + # these builds of the libraries are only used by GCC, so it + # reduces the size of the stdenv closure. + gmp = super.gmp.override { stdenv = self.makeStaticLibraries self.stdenv; }; + mpfr = super.mpfr.override { stdenv = self.makeStaticLibraries self.stdenv; }; + libmpc = super.libmpc.override { stdenv = self.makeStaticLibraries self.stdenv; }; + isl_0_17 = super.isl_0_17.override { stdenv = self.makeStaticLibraries self.stdenv; }; + gcc-unwrapped = super.gcc-unwrapped.override { + isl = isl_0_17; + }; + }; + extraNativeBuildInputs = [ prevStage.patchelf ] ++ + # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64. + lib.optional (!localSystem.isx86 || localSystem.libc == "musl") + prevStage.updateAutotoolsGnuConfigScriptsHook; + }) + + + # Construct a fourth stdenv that uses the new GCC. But coreutils is + # still from the bootstrap tools. + (prevStage: stageFun prevStage { + name = "bootstrap-stage4"; + + overrides = self: super: { + # Zlib has to be inherited and not rebuilt in this stage, + # because gcc (since JAR support) already depends on zlib, and + # then if we already have a zlib we want to use that for the + # other purposes (binutils and top-level pkgs) too. + inherit (prevStage) gettext gnum4 bison gmp perl texinfo zlib linuxHeaders; + ${localSystem.libc} = getLibc prevStage; + binutils = super.binutils.override { + # Don't use stdenv's shell but our own + shell = self.bash + "/bin/bash"; + # Build expand-response-params with last stage like below + buildPackages = { + inherit (prevStage) stdenv; + }; + }; + + gcc = lib.makeOverridable (import ../../build-support/cc-wrapper) { + nativeTools = false; + nativeLibc = false; + isGNU = true; + buildPackages = { + inherit (prevStage) stdenv; + }; + cc = prevStage.gcc-unwrapped; + bintools = self.binutils; + libc = getLibc self; + inherit (self) stdenvNoCC coreutils gnugrep; + shell = self.bash + "/bin/bash"; + }; + }; + extraNativeBuildInputs = [ prevStage.patchelf prevStage.xz ] ++ + # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64. + lib.optional (!localSystem.isx86 || localSystem.libc == "musl") + prevStage.updateAutotoolsGnuConfigScriptsHook; + }) + + # Construct the final stdenv. It uses the Glibc and GCC, and adds + # in a new binutils that doesn't depend on bootstrap-tools, as well + # as dynamically linked versions of all other tools. + # + # When updating stdenvLinux, make sure that the result has no + # dependency (`nix-store -qR') on bootstrapTools or the first + # binutils built. + (prevStage: { + inherit config overlays; + stdenv = import ../generic rec { + name = "stdenv-linux"; + + buildPlatform = localSystem; + hostPlatform = localSystem; + targetPlatform = localSystem; + inherit config; + + preHook = '' + # Make "strip" produce deterministic output, by setting + # timestamps etc. to a fixed value. + commonStripFlags="--enable-deterministic-archives" + ${commonPreHook} + ''; + + initialPath = + ((import ../common-path.nix) {pkgs = prevStage;}); + + extraNativeBuildInputs = [ prevStage.patchelf ] ++ + # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64. + lib.optional (!localSystem.isx86 || localSystem.libc == "musl") + prevStage.updateAutotoolsGnuConfigScriptsHook; + + cc = prevStage.gcc; + + shell = cc.shell; + + inherit (prevStage.stdenv) fetchurlBoot; + + extraAttrs = { + # TODO: remove this! + inherit (prevStage) glibc; + + inherit platform bootstrapTools; + shellPackage = prevStage.bash; + }; + + # Mainly avoid reference to bootstrap tools + allowedRequisites = with prevStage; with lib; + # Simple executable tools + concatMap (p: [ (getBin p) (getLib p) ]) [ + gzip bzip2 xz bash binutils.bintools coreutils diffutils findutils + gawk gnumake gnused gnutar gnugrep gnupatch patchelf ed + ] + # Library dependencies + ++ map getLib ( + [ attr acl zlib pcre ] + ++ lib.optional (gawk.libsigsegv != null) gawk.libsigsegv + ) + # More complicated cases + ++ (map (x: getOutput x (getLibc prevStage)) [ "out" "dev" "bin" ] ) + ++ [ /*propagated from .dev*/ linuxHeaders + binutils gcc gcc.cc gcc.cc.lib gcc.expand-response-params + ] + ++ lib.optionals (!localSystem.isx86 || localSystem.libc == "musl") + [ prevStage.updateAutotoolsGnuConfigScriptsHook prevStage.gnu-config ]; + + overrides = self: super: { + inherit (prevStage) + gzip bzip2 xz bash coreutils diffutils findutils gawk + gnumake gnused gnutar gnugrep gnupatch patchelf + attr acl zlib pcre; + ${localSystem.libc} = getLibc prevStage; + } // lib.optionalAttrs (super.stdenv.targetPlatform == localSystem) { + # Need to get rid of these when cross-compiling. + inherit (prevStage) binutils binutils-unwrapped; + gcc = cc; + }; + }; + }) + +] diff --git a/nixpkgs/pkgs/stdenv/linux/make-bootstrap-tools-cross.nix b/nixpkgs/pkgs/stdenv/linux/make-bootstrap-tools-cross.nix new file mode 100644 index 000000000000..d1ee317a2bcf --- /dev/null +++ b/nixpkgs/pkgs/stdenv/linux/make-bootstrap-tools-cross.nix @@ -0,0 +1,22 @@ +{system ? builtins.currentSystem}: + +let + make = crossSystem: import ./make-bootstrap-tools.nix { + localSystem = { inherit system; }; + inherit crossSystem; + }; + lib = import ../../../lib; +in lib.mapAttrs (n: make) (with lib.systems.examples; { + armv5tel = sheevaplug; + scaleway = scaleway-c1; + pogoplug4 = pogoplug4; + armv6l = raspberryPi; + armv7l = armv7l-hf-multiplatform; + aarch64 = aarch64-multiplatform; + x86_64-musl = musl64; + armv6l-musl = muslpi; + aarch64-musl = aarch64-multiplatform-musl; + riscv64 = riscv64; + powerpc64le = powernv; + powerpc64le-musl = musl-power; +}) diff --git a/nixpkgs/pkgs/stdenv/linux/make-bootstrap-tools.nix b/nixpkgs/pkgs/stdenv/linux/make-bootstrap-tools.nix new file mode 100644 index 000000000000..8d513625df21 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/linux/make-bootstrap-tools.nix @@ -0,0 +1,266 @@ +{ localSystem ? { system = builtins.currentSystem; } +, crossSystem ? null +}: + +let + pkgs = import ../../.. { inherit localSystem crossSystem; }; + libc = pkgs.stdenv.cc.libc; +in with pkgs; rec { + + + coreutilsMinimal = coreutils.override (args: { + # We want coreutils without ACL/attr support. + aclSupport = false; + attrSupport = false; + # Our tooling currently can't handle scripts in bin/, only ELFs and symlinks. + singleBinary = "symlinks"; + }); + + tarMinimal = gnutar.override { acl = null; }; + + busyboxMinimal = busybox.override { + useMusl = !stdenv.targetPlatform.isRiscV; + enableStatic = true; + enableMinimal = true; + extraConfig = '' + CONFIG_ASH y + CONFIG_ASH_ECHO y + CONFIG_ASH_TEST y + CONFIG_ASH_OPTIMIZE_FOR_SIZE y + CONFIG_MKDIR y + CONFIG_TAR y + CONFIG_UNXZ y + ''; + }; + + build = + + stdenv.mkDerivation { + name = "stdenv-bootstrap-tools"; + + nativeBuildInputs = [ buildPackages.nukeReferences buildPackages.cpio ]; + + buildCommand = '' + set -x + mkdir -p $out/bin $out/lib $out/libexec + + '' + (if (stdenv.hostPlatform.libc == "glibc") then '' + # Copy what we need of Glibc. + cp -d ${libc.out}/lib/ld*.so* $out/lib + cp -d ${libc.out}/lib/libc*.so* $out/lib + cp -d ${libc.out}/lib/libc_nonshared.a $out/lib + cp -d ${libc.out}/lib/libm*.so* $out/lib + cp -d ${libc.out}/lib/libdl*.so* $out/lib + cp -d ${libc.out}/lib/librt*.so* $out/lib + cp -d ${libc.out}/lib/libpthread*.so* $out/lib + cp -d ${libc.out}/lib/libnsl*.so* $out/lib + cp -d ${libc.out}/lib/libutil*.so* $out/lib + cp -d ${libc.out}/lib/libnss*.so* $out/lib + cp -d ${libc.out}/lib/libresolv*.so* $out/lib + cp -d ${libc.out}/lib/crt?.o $out/lib + + cp -rL ${libc.dev}/include $out + chmod -R u+w "$out" + + # libc can contain linker scripts: find them, copy their deps, + # and get rid of absolute paths (nuke-refs would make them useless) + local lScripts=$(grep --files-with-matches --max-count=1 'GNU ld script' -R "$out/lib") + cp -d -t "$out/lib/" $(cat $lScripts | tr " " "\n" | grep -F '${libc.out}' | sort -u) + for f in $lScripts; do + substituteInPlace "$f" --replace '${libc.out}/lib/' "" + done + + # Hopefully we won't need these. + rm -rf $out/include/mtd $out/include/rdma $out/include/sound $out/include/video + find $out/include -name .install -exec rm {} \; + find $out/include -name ..install.cmd -exec rm {} \; + mv $out/include $out/include-glibc + '' else if (stdenv.hostPlatform.libc == "musl") then '' + # Copy what we need from musl + cp ${libc.out}/lib/* $out/lib + cp -rL ${libc.dev}/include $out + chmod -R u+w "$out" + + rm -rf $out/include/mtd $out/include/rdma $out/include/sound $out/include/video + find $out/include -name .install -exec rm {} \; + find $out/include -name ..install.cmd -exec rm {} \; + mv $out/include $out/include-libc + '' else throw "unsupported libc for bootstrap tools") + + '' + # Copy coreutils, bash, etc. + cp -d ${coreutilsMinimal.out}/bin/* $out/bin + (cd $out/bin && rm vdir dir sha*sum pinky factor pathchk runcon shuf who whoami shred users) + + cp ${bash.out}/bin/bash $out/bin + cp ${findutils.out}/bin/find $out/bin + cp ${findutils.out}/bin/xargs $out/bin + cp -d ${diffutils.out}/bin/* $out/bin + cp -d ${gnused.out}/bin/* $out/bin + cp -d ${gnugrep.out}/bin/grep $out/bin + cp ${gawk.out}/bin/gawk $out/bin + cp -d ${gawk.out}/bin/awk $out/bin + cp ${tarMinimal.out}/bin/tar $out/bin + cp ${gzip.out}/bin/gzip $out/bin + cp ${bzip2.bin}/bin/bzip2 $out/bin + cp -d ${gnumake.out}/bin/* $out/bin + cp -d ${patch}/bin/* $out/bin + cp ${patchelf}/bin/* $out/bin + + cp -d ${gnugrep.pcre.out}/lib/libpcre*.so* $out/lib # needed by grep + + # Copy what we need of GCC. + cp -d ${gcc.cc.out}/bin/gcc $out/bin + cp -d ${gcc.cc.out}/bin/cpp $out/bin + cp -d ${gcc.cc.out}/bin/g++ $out/bin + cp -d ${gcc.cc.lib}/lib/libgcc_s.so* $out/lib + cp -d ${gcc.cc.lib}/lib/libstdc++.so* $out/lib + cp -rd ${gcc.cc.out}/lib/gcc $out/lib + chmod -R u+w $out/lib + rm -f $out/lib/gcc/*/*/include*/linux + rm -f $out/lib/gcc/*/*/include*/sound + rm -rf $out/lib/gcc/*/*/include*/root + rm -f $out/lib/gcc/*/*/include-fixed/asm + rm -rf $out/lib/gcc/*/*/plugin + #rm -f $out/lib/gcc/*/*/*.a + cp -rd ${gcc.cc.out}/libexec/* $out/libexec + chmod -R u+w $out/libexec + rm -rf $out/libexec/gcc/*/*/plugin + mkdir -p $out/include + cp -rd ${gcc.cc.out}/include/c++ $out/include + chmod -R u+w $out/include + rm -rf $out/include/c++/*/ext/pb_ds + rm -rf $out/include/c++/*/ext/parallel + + cp -d ${gmpxx.out}/lib/libgmp*.so* $out/lib + cp -d ${mpfr.out}/lib/libmpfr*.so* $out/lib + cp -d ${libmpc.out}/lib/libmpc*.so* $out/lib + cp -d ${zlib.out}/lib/libz.so* $out/lib + cp -d ${libelf}/lib/libelf.so* $out/lib + + '' + lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) '' + # These needed for cross but not native tools because the stdenv + # GCC has certain things built in statically. See + # pkgs/stdenv/linux/default.nix for the details. + cp -d ${isl_0_17.out}/lib/libisl*.so* $out/lib + + '' + '' + cp -d ${bzip2.out}/lib/libbz2.so* $out/lib + + # Copy binutils. + for i in as ld ar ranlib nm strip readelf objdump; do + cp ${binutils.bintools.out}/bin/$i $out/bin + done + cp '${lib.getLib binutils.bintools}'/lib/* "$out/lib/" + + chmod -R u+w $out + + # Strip executables even further. + for i in $out/bin/* $out/libexec/gcc/*/*/*; do + if test -x $i -a ! -L $i; then + chmod +w $i + $STRIP -s $i || true + fi + done + + nuke-refs $out/bin/* + nuke-refs $out/lib/* + nuke-refs $out/libexec/gcc/*/*/* + nuke-refs $out/lib/gcc/*/*/* + + mkdir $out/.pack + mv $out/* $out/.pack + mv $out/.pack $out/pack + + mkdir $out/on-server + XZ_OPT=-9 tar cvJf $out/on-server/bootstrap-tools.tar.xz --hard-dereference --sort=name --numeric-owner --owner=0 --group=0 --mtime=@1 -C $out/pack . + cp ${busyboxMinimal}/bin/busybox $out/on-server + chmod u+w $out/on-server/busybox + nuke-refs $out/on-server/busybox + ''; # */ + + # The result should not contain any references (store paths) so + # that we can safely copy them out of the store and to other + # locations in the store. + allowedReferences = []; + }; + + dist = stdenv.mkDerivation { + name = "stdenv-bootstrap-tools"; + + buildCommand = '' + mkdir -p $out/nix-support + echo "file tarball ${build}/on-server/bootstrap-tools.tar.xz" >> $out/nix-support/hydra-build-products + echo "file busybox ${build}/on-server/busybox" >> $out/nix-support/hydra-build-products + ''; + }; + + bootstrapFiles = { + # Make them their own store paths to test that busybox still works when the binary is named /nix/store/HASH-busybox + busybox = runCommand "busybox" {} "cp ${build}/on-server/busybox $out"; + bootstrapTools = runCommand "bootstrap-tools.tar.xz" {} "cp ${build}/on-server/bootstrap-tools.tar.xz $out"; + }; + + bootstrapTools = if (stdenv.hostPlatform.libc == "glibc") then + import ./bootstrap-tools { + inherit (stdenv.buildPlatform) system; # Used to determine where to build + inherit bootstrapFiles; + } + else if (stdenv.hostPlatform.libc == "musl") then + import ./bootstrap-tools-musl { + inherit (stdenv.buildPlatform) system; # Used to determine where to build + inherit bootstrapFiles; + } + else throw "unsupported libc"; + + test = derivation { + name = "test-bootstrap-tools"; + inherit (stdenv.hostPlatform) system; # We cannot "cross test" + builder = bootstrapFiles.busybox; + args = [ "ash" "-e" "-c" "eval \"$buildCommand\"" ]; + + buildCommand = '' + export PATH=${bootstrapTools}/bin + + ls -l + mkdir $out + mkdir $out/bin + sed --version + find --version + diff --version + patch --version + make --version + awk --version + grep --version + gcc --version + + '' + lib.optionalString (stdenv.hostPlatform.libc == "glibc") '' + ldlinux=$(echo ${bootstrapTools}/lib/ld-linux*.so.?) + export CPP="cpp -idirafter ${bootstrapTools}/include-glibc -B${bootstrapTools}" + export CC="gcc -idirafter ${bootstrapTools}/include-glibc -B${bootstrapTools} -Wl,-dynamic-linker,$ldlinux -Wl,-rpath,${bootstrapTools}/lib" + export CXX="g++ -idirafter ${bootstrapTools}/include-glibc -B${bootstrapTools} -Wl,-dynamic-linker,$ldlinux -Wl,-rpath,${bootstrapTools}/lib" + '' + lib.optionalString (stdenv.hostPlatform.libc == "musl") '' + ldmusl=$(echo ${bootstrapTools}/lib/ld-musl*.so.?) + export CPP="cpp -idirafter ${bootstrapTools}/include-libc -B${bootstrapTools}" + export CC="gcc -idirafter ${bootstrapTools}/include-libc -B${bootstrapTools} -Wl,-dynamic-linker,$ldmusl -Wl,-rpath,${bootstrapTools}/lib" + export CXX="g++ -idirafter ${bootstrapTools}/include-libc -B${bootstrapTools} -Wl,-dynamic-linker,$ldmusl -Wl,-rpath,${bootstrapTools}/lib" + '' + '' + + echo '#include <stdio.h>' >> foo.c + echo '#include <limits.h>' >> foo.c + echo 'int main() { printf("Hello World\\n"); return 0; }' >> foo.c + $CC -o $out/bin/foo foo.c + $out/bin/foo + + echo '#include <iostream>' >> bar.cc + echo 'int main() { std::cout << "Hello World\\n"; }' >> bar.cc + $CXX -v -o $out/bin/bar bar.cc + $out/bin/bar + + tar xvf ${hello.src} + cd hello-* + ./configure --prefix=$out + make + make install + ''; + }; +} diff --git a/nixpkgs/pkgs/stdenv/native/default.nix b/nixpkgs/pkgs/stdenv/native/default.nix new file mode 100644 index 000000000000..f6e0df161ad0 --- /dev/null +++ b/nixpkgs/pkgs/stdenv/native/default.nix @@ -0,0 +1,169 @@ +{ lib +, localSystem, crossSystem, config, overlays, crossOverlays ? [] +}: + +assert crossSystem == localSystem; + +let + inherit (localSystem) system; + + shell = + if system == "i686-freebsd" || system == "x86_64-freebsd" then "/usr/local/bin/bash" + else "/bin/bash"; + + path = + (if system == "i686-solaris" then [ "/usr/gnu" ] else []) ++ + (if system == "i686-netbsd" then [ "/usr/pkg" ] else []) ++ + (if system == "x86_64-solaris" then [ "/opt/local/gnu" ] else []) ++ + ["/" "/usr" "/usr/local"]; + + prehookBase = '' + # Disable purity tests; it's allowed (even needed) to link to + # libraries outside the Nix store (like the C library). + export NIX_ENFORCE_PURITY= + export NIX_ENFORCE_NO_NATIVE="''${NIX_ENFORCE_NO_NATIVE-1}" + ''; + + prehookFreeBSD = '' + ${prehookBase} + + alias make=gmake + alias tar=gtar + alias sed=gsed + export MAKE=gmake + shopt -s expand_aliases + ''; + + prehookOpenBSD = '' + ${prehookBase} + + alias make=gmake + alias grep=ggrep + alias mv=gmv + alias ln=gln + alias sed=gsed + alias tar=gtar + + export MAKE=gmake + shopt -s expand_aliases + ''; + + prehookNetBSD = '' + ${prehookBase} + + alias make=gmake + alias sed=gsed + alias tar=gtar + export MAKE=gmake + shopt -s expand_aliases + ''; + + # prevent libtool from failing to find dynamic libraries + prehookCygwin = '' + ${prehookBase} + + shopt -s expand_aliases + export lt_cv_deplibs_check_method=pass_all + ''; + + extraNativeBuildInputsCygwin = [ + ../cygwin/all-buildinputs-as-runtimedep.sh + ../cygwin/wrap-exes-to-find-dlls.sh + ] ++ (if system == "i686-cygwin" then [ + ../cygwin/rebase-i686.sh + ] else if system == "x86_64-cygwin" then [ + ../cygwin/rebase-x86_64.sh + ] else []); + + # A function that builds a "native" stdenv (one that uses tools in + # /usr etc.). + makeStdenv = + { cc, fetchurl, extraPath ? [], overrides ? (self: super: { }) }: + + import ../generic { + buildPlatform = localSystem; + hostPlatform = localSystem; + targetPlatform = localSystem; + + preHook = + if system == "i686-freebsd" then prehookFreeBSD else + if system == "x86_64-freebsd" then prehookFreeBSD else + if system == "i686-openbsd" then prehookOpenBSD else + if system == "i686-netbsd" then prehookNetBSD else + if system == "i686-cygwin" then prehookCygwin else + if system == "x86_64-cygwin" then prehookCygwin else + prehookBase; + + extraNativeBuildInputs = + if system == "i686-cygwin" then extraNativeBuildInputsCygwin else + if system == "x86_64-cygwin" then extraNativeBuildInputsCygwin else + []; + + initialPath = extraPath ++ path; + + fetchurlBoot = fetchurl; + + inherit shell cc overrides config; + }; + +in + +[ + + ({}: rec { + __raw = true; + + stdenv = makeStdenv { + cc = null; + fetchurl = null; + }; + stdenvNoCC = stdenv; + + cc = let + nativePrefix = { # switch + i686-solaris = "/usr/gnu"; + x86_64-solaris = "/opt/local/gcc47"; + }.${system} or "/usr"; + in + import ../../build-support/cc-wrapper { + name = "cc-native"; + nativeTools = true; + nativeLibc = true; + inherit nativePrefix; + bintools = import ../../build-support/bintools-wrapper { + name = "bintools"; + inherit stdenvNoCC nativePrefix; + nativeTools = true; + nativeLibc = true; + }; + inherit stdenvNoCC; + }; + + fetchurl = import ../../build-support/fetchurl { + inherit lib stdenvNoCC; + # Curl should be in /usr/bin or so. + curl = null; + }; + + }) + + # First build a stdenv based only on tools outside the store. + (prevStage: { + inherit config overlays; + stdenv = makeStdenv { + inherit (prevStage) cc fetchurl; + } // { inherit (prevStage) fetchurl; }; + }) + + # Using that, build a stdenv that adds the ‘xz’ command (which most systems + # don't have, so we mustn't rely on the native environment providing it). + (prevStage: { + inherit config overlays; + stdenv = makeStdenv { + inherit (prevStage.stdenv) cc fetchurl; + extraPath = [ prevStage.xz ]; + overrides = self: super: { inherit (prevStage) xz; }; + }; + }) + +] diff --git a/nixpkgs/pkgs/stdenv/nix/default.nix b/nixpkgs/pkgs/stdenv/nix/default.nix new file mode 100644 index 000000000000..a8311f49609a --- /dev/null +++ b/nixpkgs/pkgs/stdenv/nix/default.nix @@ -0,0 +1,49 @@ +{ lib +, crossSystem, localSystem, config, overlays +, bootStages +, ... +}: + +assert crossSystem == localSystem; + +bootStages ++ [ + (prevStage: { + inherit config overlays; + + stdenv = import ../generic rec { + inherit config; + + inherit (prevStage.stdenv) buildPlatform hostPlatform targetPlatform; + + preHook = '' + export NIX_ENFORCE_PURITY="''${NIX_ENFORCE_PURITY-1}" + export NIX_ENFORCE_NO_NATIVE="''${NIX_ENFORCE_NO_NATIVE-1}" + export NIX_IGNORE_LD_THROUGH_GCC=1 + ''; + + initialPath = (import ../common-path.nix) { pkgs = prevStage; }; + + cc = import ../../build-support/cc-wrapper { + nativeTools = false; + nativePrefix = lib.optionalString hostPlatform.isSunOS "/usr"; + nativeLibc = true; + inherit (prevStage) stdenvNoCC binutils coreutils gnugrep; + cc = prevStage.gcc.cc; + isGNU = true; + shell = prevStage.bash + "/bin/sh"; + }; + + shell = prevStage.bash + "/bin/sh"; + + fetchurlBoot = prevStage.stdenv.fetchurlBoot; + + overrides = self: super: { + inherit cc; + inherit (cc) binutils; + inherit (prevStage) + gzip bzip2 xz bash coreutils diffutils findutils gawk + gnumake gnused gnutar gnugrep gnupatch perl; + }; + }; + }) +] |