aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/manual/rl-next/build-dir.md12
-rw-r--r--src/libstore/build/local-derivation-goal.cc6
-rw-r--r--src/libstore/globals.cc2
-rw-r--r--src/libstore/globals.hh30
-rw-r--r--src/libutil/file-system.cc8
-rw-r--r--src/libutil/file-system.hh5
-rw-r--r--src/nix-build/nix-build.cc5
-rw-r--r--tests/functional/check.sh15
-rw-r--r--tests/functional/common/vars-and-functions.sh.in5
9 files changed, 74 insertions, 14 deletions
diff --git a/doc/manual/rl-next/build-dir.md b/doc/manual/rl-next/build-dir.md
new file mode 100644
index 000000000..88bcd8da4
--- /dev/null
+++ b/doc/manual/rl-next/build-dir.md
@@ -0,0 +1,12 @@
+---
+synopsis: "Add a `build-dir` setting to set the backing directory for builds"
+cls: 1514
+credits: [roberth, tomberek]
+category: Improvements
+---
+
+`build-dir` can now be set in the Nix configuration to choose the backing directory for the build sandbox.
+This can be useful on systems with `/tmp` on tmpfs, or simply to relocate large builds to another disk.
+
+Also, `XDG_RUNTIME_DIR` is no longer considered when selecting the default temporary directory,
+as it's not intended to be used for large amounts of data.
diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc
index efba648a4..968f669ec 100644
--- a/src/libstore/build/local-derivation-goal.cc
+++ b/src/libstore/build/local-derivation-goal.cc
@@ -495,7 +495,7 @@ void LocalDerivationGoal::startBuilder()
/* Create a temporary directory where the build will take
place. */
- tmpDir = createTempDir("", "nix-build-" + std::string(drvPath.name()), false, false, 0700);
+ tmpDir = createTempDir(settings.buildDir.get().value_or(""), "nix-build-" + std::string(drvPath.name()), false, false, 0700);
chownToBuilder(tmpDir);
@@ -2107,8 +2107,8 @@ void LocalDerivationGoal::runChild()
bool allowLocalNetworking = parsedDrv->getBoolAttr("__darwinAllowLocalNetworking");
/* The tmpDir in scope points at the temporary build directory for our derivation. Some packages try different mechanisms
- to find temporary directories, so we want to open up a broader place for them to dump their files, if needed. */
- Path globalTmpDir = canonPath(getEnvNonEmpty("TMPDIR").value_or("/tmp"), true);
+ to find temporary directories, so we want to open up a broader place for them to put their files, if needed. */
+ Path globalTmpDir = canonPath(defaultTempDir(), true);
/* They don't like trailing slashes on subpath directives */
if (globalTmpDir.back() == '/') globalTmpDir.pop_back();
diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc
index 763dc9158..02d26e034 100644
--- a/src/libstore/globals.cc
+++ b/src/libstore/globals.cc
@@ -429,7 +429,7 @@ void initLibStore() {
/* On macOS, don't use the per-session TMPDIR (as set e.g. by
sshd). This breaks build users because they don't have access
to the TMPDIR, in particular in ‘nix-store --serve’. */
- if (getEnv("TMPDIR").value_or("/tmp").starts_with("/var/folders/"))
+ if (defaultTempDir().starts_with("/var/folders/"))
unsetenv("TMPDIR");
#endif
diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh
index 947a2fbf0..d360e5c5e 100644
--- a/src/libstore/globals.hh
+++ b/src/libstore/globals.hh
@@ -582,16 +582,36 @@ public:
Setting<std::string> sandboxShmSize{
this, "50%", "sandbox-dev-shm-size",
R"(
- This option determines the maximum size of the `tmpfs` filesystem
- mounted on `/dev/shm` in Linux sandboxes. For the format, see the
- description of the `size` option of `tmpfs` in mount(8). The default
- is `50%`.
+ *Linux only*
+
+ This option determines the maximum size of the `tmpfs` filesystem
+ mounted on `/dev/shm` in Linux sandboxes. For the format, see the
+ description of the `size` option of `tmpfs` in mount(8). The default
+ is `50%`.
)"};
Setting<Path> sandboxBuildDir{this, "/build", "sandbox-build-dir",
- "The build directory inside the sandbox."};
+ R"(
+ *Linux only*
+
+ The build directory inside the sandbox.
+
+ This directory is backed by [`build-dir`](#conf-build-dir) on the host.
+ )"};
#endif
+ Setting<std::optional<Path>> buildDir{this, std::nullopt, "build-dir",
+ R"(
+ The directory on the host, in which derivations' temporary build directories are created.
+
+ If not set, Nix will use the system temporary directory indicated by the `TMPDIR` environment variable.
+ Note that builds are often performed by the Nix daemon, so its `TMPDIR` is used, and not that of the Nix command line interface.
+
+ This is also the location where [`--keep-failed`](@docroot@/command-ref/opt-common.md#opt-keep-failed) leaves its files.
+
+ If Nix runs without sandbox, or if the platform does not support sandboxing with bind mounts (e.g. macOS), then the [`builder`](@docroot@/language/derivations.md#attr-builder)'s environment will contain this directory, instead of the virtual location [`sandbox-build-dir`](#conf-sandbox-build-dir).
+ )"};
+
Setting<PathSet> allowedImpureHostPrefixes{this, {}, "allowed-impure-host-deps",
"Which prefixes to allow derivations to ask for access to (primarily for Darwin)."};
diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc
index f51f3c092..871707468 100644
--- a/src/libutil/file-system.cc
+++ b/src/libutil/file-system.cc
@@ -511,10 +511,14 @@ void AutoDelete::reset(const Path & p, bool recursive) {
//////////////////////////////////////////////////////////////////////
+std::string defaultTempDir() {
+ return getEnvNonEmpty("TMPDIR").value_or("/tmp");
+}
+
static Path tempName(Path tmpRoot, const Path & prefix, bool includePid,
std::atomic<unsigned int> & counter)
{
- tmpRoot = canonPath(tmpRoot.empty() ? getEnv("TMPDIR").value_or("/tmp") : tmpRoot, true);
+ tmpRoot = canonPath(tmpRoot.empty() ? defaultTempDir() : tmpRoot, true);
if (includePid)
return fmt("%1%/%2%-%3%-%4%", tmpRoot, prefix, getpid(), counter++);
else
@@ -554,7 +558,7 @@ Path createTempDir(const Path & tmpRoot, const Path & prefix,
std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix)
{
- Path tmpl(getEnv("TMPDIR").value_or("/tmp") + "/" + prefix + ".XXXXXX");
+ Path tmpl(defaultTempDir() + "/" + prefix + ".XXXXXX");
// Strictly speaking, this is UB, but who cares...
// FIXME: use O_TMPFILE.
AutoCloseFD fd(mkstemp((char *) tmpl.c_str()));
diff --git a/src/libutil/file-system.hh b/src/libutil/file-system.hh
index 64d884227..17f5da062 100644
--- a/src/libutil/file-system.hh
+++ b/src/libutil/file-system.hh
@@ -259,6 +259,11 @@ Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix",
std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix = "nix");
/**
+ * Return `TMPDIR`, or the default temporary directory if unset or empty.
+ */
+Path defaultTempDir();
+
+/**
* Used in various places.
*/
typedef std::function<bool(const Path & path)> PathFilter;
diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc
index 4cce33eb1..37b553dbb 100644
--- a/src/nix-build/nix-build.cc
+++ b/src/nix-build/nix-build.cc
@@ -414,8 +414,7 @@ static void main_nix_build(int argc, char * * argv)
// Set the environment.
auto env = getEnv();
- auto tmp = getEnv("TMPDIR");
- if (!tmp) tmp = getEnv("XDG_RUNTIME_DIR").value_or("/tmp");
+ auto tmp = defaultTempDir();
if (pure) {
decltype(env) newEnv;
@@ -427,7 +426,7 @@ static void main_nix_build(int argc, char * * argv)
env["__ETC_PROFILE_SOURCED"] = "1";
}
- env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = *tmp;
+ env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = tmp;
env["NIX_STORE"] = store->storeDir;
env["NIX_BUILD_CORES"] = std::to_string(settings.buildCores);
diff --git a/tests/functional/check.sh b/tests/functional/check.sh
index e13abf747..38883c5d7 100644
--- a/tests/functional/check.sh
+++ b/tests/functional/check.sh
@@ -34,6 +34,21 @@ nix-build check.nix -A failed --argstr checkBuildId $checkBuildId \
[ "$status" = "100" ]
if checkBuildTempDirRemoved $TEST_ROOT/log; then false; fi
+test_custom_build_dir() {
+ local customBuildDir="$TEST_ROOT/custom-build-dir"
+
+ # Nix does not create the parent directories, and perhaps it shouldn't try to
+ # decide the permissions of build-dir.
+ mkdir "$customBuildDir"
+ nix-build check.nix -A failed --argstr checkBuildId $checkBuildId \
+ --no-out-link --keep-failed --option build-dir "$TEST_ROOT/custom-build-dir" 2> $TEST_ROOT/log || status=$?
+ [ "$status" = "100" ]
+ [[ 1 == "$(count "$customBuildDir/nix-build-"*)" ]]
+ local buildDir="$customBuildDir/nix-build-"*
+ grep $checkBuildId $buildDir/checkBuildId
+}
+test_custom_build_dir
+
nix-build check.nix -A deterministic --argstr checkBuildId $checkBuildId \
--no-out-link 2> $TEST_ROOT/log
checkBuildTempDirRemoved $TEST_ROOT/log
diff --git a/tests/functional/common/vars-and-functions.sh.in b/tests/functional/common/vars-and-functions.sh.in
index bfc4fbc44..eda15308d 100644
--- a/tests/functional/common/vars-and-functions.sh.in
+++ b/tests/functional/common/vars-and-functions.sh.in
@@ -274,6 +274,11 @@ grepQuietInverse() {
! grep "$@" > /dev/null
}
+# Return the number of arguments
+count() {
+ echo $#
+}
+
trap onError ERR
fi # COMMON_VARS_AND_FUNCTIONS_SH_SOURCED