with (import ../../lib/strings-with-deps.nix (import ../../lib/default-unstable.nix)); rec { setStrictMode = noDepEntry "set -e;"; setNixGcc = noDepEntry "test -z \$NIX_GCC && NIX_GCC=@gcc@;"; setPathDelimiter = noDepEntry " if [ -z ${system##*cygwin*} ]; then PATH_DELIMITER=; else PATH_DELIMITER=; fi " ; initPath = noDepEntry "# Set up the initial path. PATH= for i in \$NIX_GCC @initialPath@; do PATH=\$PATH\${PATH:+:}\$i/bin done if test \"\$NIX_DEBUG\" = \"1\"; then echo \"Initial path: \$PATH\" fi "; execPreHook = FullDepEntry "# Execute the pre-hook. export SHELL=@shell@ if test -z \"\$shell\"; then export shell=@shell@ fi param1=@param1@ param2=@param2@ param3=@param3@ param4=@param4@ param5=@param5@ if test -n \"@preHook@\"; then source @preHook@ fi " []; checkShellEnv = FullDepEntry "# Check that the pre-hook initialised SHELL. if test -z \"\$SHELL\"; then echo \"SHELL not set\"; exit 1; fi " []; gccSetupHook = FullDepEntry "# Hack: run gcc's setup hook. envHooks=() if test -f \$NIX_GCC/nix-support/setup-hook; then source \$NIX_GCC/nix-support/setup-hook fi " [setNixGcc]; defEnsureDir = FullDepEntry "# Ensure that the given directories exists. ensureDir() { local dir for dir in \"\$@\"; do if ! test -x \"\$dir\"; then mkdir -p \"\$dir\"; fi done } " []; defInstallBin = FullDepEntry " installBin() { ensureDir $out/bin cp "$@" $out/bin } " []; defAssertEnvExists = FullDepEntry " assertEnvExists(){ if test -z "${!1}"; then msg=${2:-error: assertion failed: env var $1 is required} echo $msg >&2; exit 1 fi } " []; defFail = FullDepEntry "# Called when some build action fails. If \$succeedOnFailure is set, # create the file `\$out/nix-support/failed' to signal failure, and # exit normally. Otherwise, exit with failure. fail() { exitCode=\$? if test \"\$succeedOnFailure\" = 1; then ensureDir \"\$out/nix-support\" touch \"\$out/nix-support/failed\" exit 0 else exit \$? fi } " []; runAddInputsHook = FullDepEntry "# 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). eval \"\$addInputsHook\" " [defFail]; defFindInputs = FullDepEntry "# Recursively find all build inputs. findInputs() { local pkg=\$1 case \$pkgs in *\ \$pkg\ *) return 0 ;; esac pkgs=\"\$pkgs \$pkg \" if test -f \$pkg/nix-support/setup-hook; then source \$pkg/nix-support/setup-hook fi if test -f \$pkg/nix-support/propagated-build-inputs; then for i in \$(cat \$pkg/nix-support/propagated-build-inputs); do findInputs \$i done fi } " []; getInputs = FullDepEntry "pkgs=\"\" if test -n \"\$buildinputs\"; then buildInputs=\"\$buildinputs\" # compatibility fi for i in \$buildInputs \$propagatedBuildInputs; do findInputs \$i done " [defFindInputs]; defAddToEnv = FullDepEntry "# Set the relevant environment variables to point to the build inputs # found above. addToEnv() { local pkg=\$1 if test \"\$ignoreFailedInputs\" != \"1\" -a -e \$1/nix-support/failed; then echo \"failed input \$1\" >&2 fail fi if test -d \$1/bin; then export _PATH=\$_PATH\${_PATH:+:}\$1/bin fi for i in \"\${envHooks[@]}\"; do \$i \$pkg done } " [defFail]; preparePackageEnv = FullDepEntry "for i in \$pkgs; do addToEnv \$i done " [getInputs defAddToEnv]; putOutInRpath = FullDepEntry "# Add the output as an rpath. if test \"\$NIX_NO_SELF_RPATH\" != \"1\"; then export NIX_LDFLAGS=\"-rpath \$out/lib \$NIX_LDFLAGS\" fi " [initPath]; setupStripping = FullDepEntry "# Strip debug information by default. if test -z \"\$NIX_STRIP_DEBUG\"; then export NIX_STRIP_DEBUG=1 export NIX_CFLAGS_STRIP=\"-g0 -Wl,--strip-debug\" fi " [initPath]; checkNixEnv = FullDepEntry "# Do we know where the store is? This is required for purity checking. if test -z \"\$NIX_STORE\"; then echo \"Error: you have an old version of Nix that does not set the\" \ \"NIX_STORE variable. Please upgrade.\" >&2 exit 1 fi # We also need to know the root of the build directory for purity checking. if test -z \"\$NIX_BUILD_TOP\"; then echo \"Error: you have an old version of Nix that does not set the\" \ \"NIX_BUILD_TOP variable. Please upgrade.\" >&2 exit 1 fi " [initPath]; setTZ = noDepEntry "# 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 " ; setPrefix = FullDepEntry "# 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 test -z \"\$prefix\"; then prefix=\"\$out\"; fi if test \"\$useTempPrefix\" = \"1\"; then prefix=\"\$NIX_BUILD_TOP/tmp_prefix\"; fi " [checkNixEnv]; runPostHook = FullDepEntry "# Execute the post-hook. if test -n \"@postHook@\"; then source @postHook@ fi " [setTZ setPrefix execPreHook gccSetupHook preparePackageEnv]; finalSetPath = FullDepEntry "PATH=\$_PATH\${_PATH:+:}\$PATH if test \"\$NIX_DEBUG\" = \"1\"; then echo \"Final path: \$PATH\" fi " [runPostHook]; defSubstitute = FullDepEntry "###################################################################### # Textual substitution functions. # Some disgusting hackery to escape replacements in Sed substitutions. # We should really have a tool that replaces literal values by other # literal values, without any need for escaping. escapeSed() { local s=\"\$1\" # The `tr' hack is to escape newlines. Sed handles newlines very # badly, so we just replace newlines with the magic character 0xff # (377 octal). So don't use that character in replacements :-P echo -n \"\$1\" | tr '\012' '\377' | sed -e 's^\\^\\\\^g' -e 's^\xff^\\n^g' -e 's/\^/\\^/g' -e 's/&/\\&/g' } substitute() { local input=\"\$1\" local output=\"\$2\" local -a params=(\"\$@\") local sedScript=\$NIX_BUILD_TOP/.sedargs rm -f \$sedScript touch \$sedScript local n p pattern replacement varName for ((n = 2; n < \${#params[*]}; n += 1)); do p=\${params[\$n]} if test \"\$p\" = \"--replace\"; then pattern=\"\${params[\$((n + 1))]}\" replacement=\"\${params[\$((n + 2))]}\" n=\$((n + 2)) fi if test \"\$p\" = \"--subst-var\"; then varName=\"\${params[\$((n + 1))]}\" pattern=\"@\$varName@\" replacement=\"\${!varName}\" n=\$((n + 1)) fi if test \"\$p\" = \"--subst-var-by\"; then pattern=\"@\${params[\$((n + 1))]}@\" replacement=\"\${params[\$((n + 2))]}\" n=\$((n + 2)) fi replacement=\"\$(escapeSed \"\$replacement\")\" echo \"s^\$pattern^\$replacement^g\" >> \$sedScript done sed -f \$sedScript < \"\$input\" > \"\$output\".tmp if test -x \"\$output\"; then chmod +x \"\$output\".tmp fi mv -f \"\$output\".tmp \"\$output\" } substituteInPlace() { local fileName=\"\$1\" shift substitute \"\$fileName\" \"\$fileName\" \"\$@\" } substituteAll() { local input=\"\$1\" local output=\"\$2\" # Select all environment variables that start with a lowercase character. for envVar in \$(env | sed \"s/^[^a-z].*//\" | sed \"s/^\([^=]*\)=.*/\1/\"); do if test \"\$NIX_DEBUG\" = \"1\"; then echo \"\$envVar -> \${!envVar}\" fi args=\"\$args --subst-var \$envVar\" done substitute \"\$input\" \"\$output\" \$args } " [initPath]; defNest = NoDepEntry "###################################################################### # What follows is the generic builder. nestingLevel=0 startNest() { nestingLevel=\$((\$nestingLevel + 1)) echo -en \"\e[\$1p\" } stopNest() { nestingLevel=\$((\$nestingLevel - 1)) echo -en \"\e[q\" } header() { startNest \"\$2\" echo \"\$1\" } # Make sure that even when we exit abnormally, the original nesting # level is properly restored. closeNest() { while test \$nestingLevel -gt 0; do stopNest done } trap \"closeNest\" EXIT " ; defDumpVars = FullDepEntry "# 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 test \"\$noDumpEnvVars\" != \"1\"; then export > \$NIX_BUILD_TOP/env-vars fi } " [checkNixEnv]; defStartStopLog = FullDepEntry "# Redirect stdout/stderr to a named pipe connected to a `tee' process # that writes the specified file (and also to our original stdout). # The original stdout is saved in descriptor 3. startLog() { local logFile=\${logNr}_\$1 logNr=\$((logNr + 1)) if test \"\$logPhases\" = 1; then ensureDir \$logDir exec 3>&1 if test \"\$dontLogThroughTee\" != 1; then # This required named pipes (fifos). logFifo=\$NIX_BUILD_TOP/log_fifo test -p \$logFifo || mkfifo \$logFifo startLogWrite \"\$logDir/\$logFile\" \"\$logFifo\" exec > \$logFifo 2>&1 else exec > \$logDir/\$logFile 2>&1 fi fi } # Factored into a separate function so that it can be overriden. startLogWrite() { tee \"\$1\" < \"\$2\" & logWriterPid=\$! } # Restore the original stdout/stderr. stopLog() { if test \"\$logPhases\" = 1; then exec >&3 2>&1 # Wait until the tee process has died. Otherwise output from # different phases may be mixed up. if test -n \"\$logWriterPid\"; then wait \$logWriterPid logWriterPid= rm \$logFifo fi fi } " [setLogVars checkNixEnv ]; setLogVars = FullDepEntry "if test -z \"\$logDir\"; then logDir=\$out/log fi logNr=0 " [initPath]; defStripHash = FullDepEntry "# Utility function: return the base name of the given path, with the # prefix `HASH-' removed, if present. stripHash() { strippedName=\$(basename \$1); if echo \"\$strippedName\" | grep -q '^[a-z0-9]\{32\}-'; then strippedName=\$(echo \"\$strippedName\" | cut -c34-) fi } " [initPath]; defUnpack = FullDepEntry " unpackFile() { local file=\$1 local cmd header \"unpacking source archive \$file\" 3 case \$file in *.tar) tar xvf \$file || fail ;; *.tar.gz | *.tgz | *.tar.Z) gunzip < \$file | tar xvf - || fail ;; *.tar.bz2 | *.tbz2) bunzip2 < \$file | tar xvf - || fail ;; *.zip) unzip \$file || fail ;; *) if test -d \"\$file\"; then stripHash \$file cp -prvd \$file \$strippedName || fail else if test -n \"\$findUnpacker\"; then \$findUnpacker \$1; fi if test -z \"\$unpackCmd\"; then echo \"source archive \$file has unknown type\" exit 1 fi eval \"\$unpackCmd\" || fail fi ;; esac stopNest } " [preparePackageEnv]; defUnpackW = FullDepEntry " unpackW() { if test -n \"\$unpackPhase\"; then eval \"\$unpackPhase\" return fi if test -z \"\$srcs\"; then if test -z \"\$src\"; then 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 test -d \"\$i\"; then dirsBefore=\"\$dirsBefore \$i \" fi done # Unpack all source archives. for i in \$srcs; do unpackFile \$i done # Find the source directory. if test -n \"\$setSourceRoot\"; then eval \"\$setSourceRoot\" else sourceRoot= for i in *; do if test -d \"\$i\"; then case \$dirsBefore in *\ \$i\ *) ;; *) if test -n \"\$sourceRoot\"; then echo \"unpacker produced multiple directories\" exit 1 fi sourceRoot=\$i ;; esac fi done fi if test -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 test \"dontMakeSourcesWritable\" != 1; then chmod -R +w \$sourceRoot fi eval \"\$postUnpack\" } " [defUnpack]; defUnpackPhase = FullDepEntry " unpackPhase() { sourceRoot=. # don't change to user dir homeless shelter if custom unpackSource does'nt set sourceRoot header \"unpacking sources\" startLog \"unpack\" unpackW stopLog stopNest cd \$sourceRoot } " [unpackW]; defPatchW = FullDepEntry " patchW() { if test -n \"\$patchPhase\"; then eval \"\$patchPhase\" return fi if test -z \"\$patchFlags\"; then patchFlags=\"-p1\" fi for i in \$patches; do header \"applying patch \$i\" 3 local uncompress=cat case \$i in *.gz) uncompress=gunzip ;; *.bz2) uncompress=bunzip2 ;; esac \$uncompress < \$i | patch \$patchFlags || fail stopNest done } " [getInputs] defPatchPhase = FullDepEntry " patchPhase() { if test -z \"\$patchPhase\" -a -z \"\$patches\"; then return; fi header \"patching sources\" startLog \"patch\" patchW stopLog stopNest } " [defPatchW]; defFixLibTool = FullDepEntry "fixLibtool() { sed 's^eval sys_lib_.*search_path=.*^^' < \$1 > \$1.tmp mv \$1.tmp \$1 } " [initPath]; defConfigureW = FullDepEntry " configureW() { if test -n \"\$configurePhase\"; then eval \"\$configurePhase\" return fi eval \"\$preConfigure\" if test -z \"\$configureScript\"; then configureScript=./configure if ! test -x \$configureScript; then echo \"no configure script, doing nothing\" return fi fi if test -z \"\$dontFixLibtool\"; then for i in \$(find . -name \"ltmain.sh\"); do echo \"fixing libtool script \$i\" fixLibtool \$i done fi if test -z \"\$dontAddPrefix\"; then configureFlags=\"--prefix=\$prefix \$configureFlags\" fi echo \"configure flags: \$configureFlags \${configureFlagsArray[@]}\" \$configureScript \$configureFlags\"\${configureFlagsArray[@]}\" || fail eval \"\$postConfigure\" } " [initPath]; defConfigurePhase = FullDepEntry " configurePhase() { header \"configuring\" startLog \"configure\" configureW stopLog stopNest } " [defConfigureW]; defBuildW = FullDepEntry " buildW() { if test -n \"\$buildPhase\"; then eval \"\$buildPhase\" return fi eval \"\$preBuild\" echo \"make flags: \$makeFlags \${makeFlagsArray[@]} \$buildFlags \${buildFlagsArray[@]}\" make \ \$makeFlags \"\${makeFlagsArray[@]}\" \ \$buildFlags \"\${buildFlagsArray[@]}\" || fail eval \"\$postBuild\" } " [initPath]; defBuildPhase = FullDepEntry " buildPhase() { if test \"\$dontBuild\" = 1; then return fi header \"building\" startLog \"build\" buildW stopLog stopNest } " [defBuildW]; defCheckW = FullDepEntry " checkW() { if test -n \"\$checkPhase\"; then eval \"\$checkPhase\" return fi if test -z \"\$checkTarget\"; then checkTarget=\"check\" fi echo \"check flags: \$makeFlags \${makeFlagsArray[@]} \$checkFlags \${checkFlagsArray[@]}\" make \ \$makeFlags \"\${makeFlagsArray[@]}\" \ \$checkFlags \"\${checkFlagsArray[@]}\" \$checkTarget || fail } " [initPath]; defCheckPhase = FullDepEntry " checkPhase() { if test \"\$doCheck\" != 1; then return fi header \"checking\" startLog \"check\" checkW stopLog stopNest } " [checkPhase]; defPatchElf = FullDepEntry " patchELF() { # Patch all ELF executables and shared libraries. header \"patching ELF executables and libraries\" find \"\$prefix\" \( \ \( -type f -a -name \"*.so*\" \) -o \ \( -type f -a -perm +0100 \) \ \) -print -exec patchelf --shrink-rpath {} \; stopNest } " [initPath defNest]; defInstallW = FullDepEntry " installW() { if test -n \"\$installPhase\"; then eval \"\$installPhase\" return fi eval \"\$preInstall\" ensureDir \"\$prefix\" if test -z \"\$installCommand\"; then if test -z \"\$installTargets\"; then installTargets=install fi echo \"install flags: \$installTargets \$makeFlags \${makeFlagsArray[@]} \$installFlags \${installFlagsArray[@]}\" make \$installTargets \ \$makeFlags \"\${makeFlagsArray[@]}\" \ \$installFlags \"\${installFlagsArray[@]}\" || fail else eval \"\$installCommand\" fi eval \"\$postInstall\" } " [initPath]; defInstallPhase = FullDepEntry " installPhase() { if test \"\$dontInstall\" = 1; then return fi header \"installing\" startLog \"install\" installW stopLog stopNest } " [defInstallW defNest defStartStopLog]; defFixupW = FullDepEntry " # The fixup phase performs generic, package-independent, Nix-related # stuff, like running patchelf and setting the # propagated-build-inputs. It should rarely be overriden. fixupW() { if test -n "$fixupPhase"; then eval "$fixupPhase" return fi eval "$preFixup" forceShare=${forceShare:=man doc info} if test -n "$forceShare"; then for d in $forceShare; do if test -d "$prefix/$d"; then if test -d "$prefix/share/$d"; then echo "Both $d/ and share/$d/ exists!" else echo Fixing location of $dir/ subdirectory ensureDir $prefix/share if test -w $prefix/share; then mv -v $prefix/$d $prefix/share ln -sv share/$d $prefix fi fi else echo "No $d/ subdirectory, skipping." fi done; fi # TODO : strip _only_ ELF executables, and return || fail here... if test -z "$dontStrip"; then echo "Stripping debuging symbols from files in" stripDirs "${stripDebugList:-lib}" -S echo "Stripping all symbols from files in" stripDirs "${stripAllList:-bin sbin}" -s fi if test "$havePatchELF" = 1 -a -z "$dontPatchELF"; then patchELF "$prefix" fi if test -n "$propagatedBuildInputs"; then ensureDir "$out/nix-support" echo "$propagatedBuildInputs" > "$out/nix-support/propagated-build-inputs" fi if test -n "$setupHook"; then ensureDir "$out/nix-support" substituteAll "$setupHook" "$out/nix-support/setup-hook" fi eval "$postFixup" } " [defPatchElf initPath]; defFixupPhase = FullDepEntry " fixupPhase() { if test \"\$dontFixup\" = 1; then return fi header \"post-installation fixup\" startLog \"fixup\" fixupW stopLog stopNest } " [defFixupW defNest defStartStopLog]; defDistW = FullDepEntry " distW() { if test -n \"\$distPhase\"; then eval \"\$distPhase\" return fi eval \"\$preDist\" if test -z \"\$distTarget\"; then distTarget=\"dist\" fi echo \"dist flags: \$distFlags \${distFlagsArray[@]}\" make \$distFlags \"\${distFlagsArray[@]}\" \$distTarget || fail if test \"\$dontCopyDist\" != 1; then ensureDir \"\$out/tarballs\" if test -z \"\$tarballs\"; then tarballs=\"*.tar.gz\" fi # Note: don't quote \$tarballs, since we explicitly permit # wildcards in there. cp -pvd \$tarballs \$out/tarballs fi eval \"\$postDist\" } " [initPath ]; defDistPhase = FullDepEntry " distPhase() { if test \"\$doDist\" != 1; then return fi header \"creating distribution\" startLog \"dist\" distW stopLog stopNest } " [defDistW defNest defStartStopLog]; defGenericBuild = FullDepEntry " genericBuild() { header \"building \$out\" if test -n \"\$buildCommand\"; then eval \"\$buildCommand\" return fi if test -z \"\$phases\"; then phases=\"unpackPhase patchPhase configurePhase buildPhase checkPhase \ installPhase fixupPhase distPhase\"; fi for i in \$phases; do dumpVars eval \"\$i\" done stopNest } " [defUnpackPhase defBuildPhase defInstallPhase]; doDumpVars = FullDepEntry " dumpVars " [defDumpVars];