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
+ '';
+}
+")