From a70d275f3d25f6e1eb1b6d528ee07ecd7265ada5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 17 Feb 2015 14:42:15 +0100 Subject: [PATCH] Allow passing attributes via files instead of environment variables Closes #473. --- .../expressions/advanced-attributes.xml | 21 +++++++++++++++++++ src/libstore/build.cc | 20 ++++++++++++++---- tests/local.mk | 2 +- tests/pass-as-file.sh | 17 +++++++++++++++ 4 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 tests/pass-as-file.sh diff --git a/doc/manual/expressions/advanced-attributes.xml b/doc/manual/expressions/advanced-attributes.xml index 274e36f5c..fee35f0be 100644 --- a/doc/manual/expressions/advanced-attributes.xml +++ b/doc/manual/expressions/advanced-attributes.xml @@ -242,6 +242,27 @@ stdenv.mkDerivation { + passAsFile + + A list of names of attributes that should be + passed via files rather than environment variables. For example, + if you have + + +passAsFile = ["big"]; +big = "a very long string"; + + + then when the builder runs, the environment variable + big will contain the absolute path to a temporary + file containing a very long string. This is + useful when you need to pass large strings to a builder, since + most operating systems impose a limit on the size of the + environment (typically, a few hundred kilobyte). + + + + preferLocalBuild If this attribute is set to diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 4841c9373..0b1985828 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -1646,14 +1646,26 @@ void DerivationGoal::startBuilder() /* The maximum number of cores to utilize for parallel building. */ env["NIX_BUILD_CORES"] = (format("%d") % settings.buildCores).str(); - /* Add all bindings specified in the derivation. */ - foreach (StringPairs::iterator, i, drv.env) - env[i->first] = i->second; - /* Create a temporary directory where the build will take place. */ tmpDir = createTempDir("", "nix-build-" + storePathToName(drvPath), false, false, 0700); + /* Add all bindings specified in the derivation via the + environments, except those listed in the passAsFile + attribute. Those are passed as file names pointing to + temporary files containing the contents. */ + StringSet passAsFile = tokenizeString(get(drv.env, "passAsFile")); + int fileNr = 0; + for (auto & i : drv.env) { + if (passAsFile.find(i.first) == passAsFile.end()) { + env[i.first] = i.second; + } else { + Path p = tmpDir + "/.attr-" + int2String(fileNr++); + writeFile(p, i.second); + env[i.first] = p; + } + } + /* For convenience, set an environment pointing to the top build directory. */ env["NIX_BUILD_TOP"] = tmpDir; diff --git a/tests/local.mk b/tests/local.mk index 69a227495..7a24fadcb 100644 --- a/tests/local.mk +++ b/tests/local.mk @@ -11,7 +11,7 @@ nix_tests = \ binary-patching.sh timeout.sh secure-drv-outputs.sh nix-channel.sh \ multiple-outputs.sh import-derivation.sh fetchurl.sh optimise-store.sh \ binary-cache.sh nix-profile.sh repair.sh dump-db.sh case-hack.sh \ - check-reqs.sh + check-reqs.sh pass-as-file.sh # parallel.sh install-tests += $(foreach x, $(nix_tests), tests/$(x)) diff --git a/tests/pass-as-file.sh b/tests/pass-as-file.sh new file mode 100644 index 000000000..b61576e05 --- /dev/null +++ b/tests/pass-as-file.sh @@ -0,0 +1,17 @@ +source common.sh + +clearStore + +outPath=$(nix-build --no-out-link -E " +with import ./config.nix; + +mkDerivation { + name = \"pass-as-file\"; + passAsFile = [ \"foo\" ]; + foo = [ \"xyzzy\" ]; + builder = builtins.toFile \"builder.sh\" '' + [ \"\$(cat \$foo)\" = xyzzy ] + touch \$out + ''; +} +")