Moving more code out of DerivationGoal::startBuilder()
This commit is contained in:
parent
e8c43abd9a
commit
a529c740d2
1 changed files with 111 additions and 100 deletions
|
@ -780,6 +780,7 @@ private:
|
||||||
};
|
};
|
||||||
typedef map<Path, ChrootPath> DirsInChroot; // maps target path to source path
|
typedef map<Path, ChrootPath> DirsInChroot; // maps target path to source path
|
||||||
DirsInChroot dirsInChroot;
|
DirsInChroot dirsInChroot;
|
||||||
|
|
||||||
typedef map<string, string> Environment;
|
typedef map<string, string> Environment;
|
||||||
Environment env;
|
Environment env;
|
||||||
|
|
||||||
|
@ -817,6 +818,8 @@ private:
|
||||||
const uid_t sandboxUid = 1000;
|
const uid_t sandboxUid = 1000;
|
||||||
const gid_t sandboxGid = 100;
|
const gid_t sandboxGid = 100;
|
||||||
|
|
||||||
|
const static Path homeDir;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs,
|
DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs,
|
||||||
Worker & worker, BuildMode buildMode = bmNormal);
|
Worker & worker, BuildMode buildMode = bmNormal);
|
||||||
|
@ -864,6 +867,12 @@ private:
|
||||||
/* Start building a derivation. */
|
/* Start building a derivation. */
|
||||||
void startBuilder();
|
void startBuilder();
|
||||||
|
|
||||||
|
/* Fill in the environment for the builder. */
|
||||||
|
void initEnv();
|
||||||
|
|
||||||
|
/* Make a file owned by the builder. */
|
||||||
|
void chownToBuilder(const Path & path);
|
||||||
|
|
||||||
/* Handle the exportReferencesGraph attribute. */
|
/* Handle the exportReferencesGraph attribute. */
|
||||||
void doExportReferencesGraph();
|
void doExportReferencesGraph();
|
||||||
|
|
||||||
|
@ -907,6 +916,9 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const Path DerivationGoal::homeDir = "/homeless-shelter";
|
||||||
|
|
||||||
|
|
||||||
DerivationGoal::DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs,
|
DerivationGoal::DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs,
|
||||||
Worker & worker, BuildMode buildMode)
|
Worker & worker, BuildMode buildMode)
|
||||||
: Goal(worker)
|
: Goal(worker)
|
||||||
|
@ -1672,11 +1684,7 @@ void DerivationGoal::startBuilder()
|
||||||
additionalSandboxProfile = get(drv->env, "__sandboxProfile");
|
additionalSandboxProfile = get(drv->env, "__sandboxProfile");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Are we doing a chroot build? Note that fixed-output
|
/* Are we doing a chroot build? */
|
||||||
derivations are never done in a chroot, mainly so that
|
|
||||||
functions like fetchurl (which needs a proper /etc/resolv.conf)
|
|
||||||
work properly. Purity checking for fixed-output derivations
|
|
||||||
is somewhat pointless anyway. */
|
|
||||||
{
|
{
|
||||||
string x = settings.get("build-use-sandbox",
|
string x = settings.get("build-use-sandbox",
|
||||||
/* deprecated alias */
|
/* deprecated alias */
|
||||||
|
@ -1703,31 +1711,15 @@ void DerivationGoal::startBuilder()
|
||||||
if (worker.store.storeDir != worker.store.realStoreDir)
|
if (worker.store.storeDir != worker.store.realStoreDir)
|
||||||
useChroot = true;
|
useChroot = true;
|
||||||
|
|
||||||
/* Construct the environment passed to the builder. */
|
/* If `build-users-group' is not empty, then we have to build as
|
||||||
env.clear();
|
one of the members of that group. */
|
||||||
|
if (settings.buildUsersGroup != "" && getuid() == 0) {
|
||||||
|
buildUser.acquire();
|
||||||
|
|
||||||
/* Most shells initialise PATH to some default (/bin:/usr/bin:...) when
|
/* Make sure that no other processes are executing under this
|
||||||
PATH is not set. We don't want this, so we fill it in with some dummy
|
uid. */
|
||||||
value. */
|
buildUser.kill();
|
||||||
env["PATH"] = "/path-not-set";
|
}
|
||||||
|
|
||||||
/* Set HOME to a non-existing path to prevent certain programs from using
|
|
||||||
/etc/passwd (or NIS, or whatever) to locate the home directory (for
|
|
||||||
example, wget looks for ~/.wgetrc). I.e., these tools use /etc/passwd
|
|
||||||
if HOME is not set, but they will just assume that the settings file
|
|
||||||
they are looking for does not exist if HOME is set but points to some
|
|
||||||
non-existing path. */
|
|
||||||
Path homeDir = "/homeless-shelter";
|
|
||||||
env["HOME"] = homeDir;
|
|
||||||
|
|
||||||
/* Tell the builder where the Nix store is. Usually they
|
|
||||||
shouldn't care, but this is useful for purity checking (e.g.,
|
|
||||||
the compiler or linker might only want to accept paths to files
|
|
||||||
in the store or in the build directory). */
|
|
||||||
env["NIX_STORE"] = worker.store.storeDir;
|
|
||||||
|
|
||||||
/* The maximum number of cores to utilize for parallel building. */
|
|
||||||
env["NIX_BUILD_CORES"] = (format("%d") % settings.buildCores).str();
|
|
||||||
|
|
||||||
/* Create a temporary directory where the build will take
|
/* Create a temporary directory where the build will take
|
||||||
place. */
|
place. */
|
||||||
|
@ -1737,86 +1729,18 @@ void DerivationGoal::startBuilder()
|
||||||
/* In a sandbox, for determinism, always use the same temporary
|
/* In a sandbox, for determinism, always use the same temporary
|
||||||
directory. */
|
directory. */
|
||||||
tmpDirInSandbox = useChroot ? canonPath("/tmp", true) + "/nix-build-" + drvName + "-0" : tmpDir;
|
tmpDirInSandbox = useChroot ? canonPath("/tmp", true) + "/nix-build-" + drvName + "-0" : tmpDir;
|
||||||
|
chownToBuilder(tmpDir);
|
||||||
|
|
||||||
/* Add all bindings specified in the derivation via the
|
/* Construct the environment passed to the builder. */
|
||||||
environments, except those listed in the passAsFile
|
initEnv();
|
||||||
attribute. Those are passed as file names pointing to
|
|
||||||
temporary files containing the contents. */
|
|
||||||
PathSet filesToChown;
|
|
||||||
StringSet passAsFile = tokenizeString<StringSet>(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 {
|
|
||||||
string fn = ".attr-" + std::to_string(fileNr++);
|
|
||||||
Path p = tmpDir + "/" + fn;
|
|
||||||
writeFile(p, i.second);
|
|
||||||
filesToChown.insert(p);
|
|
||||||
env[i.first + "Path"] = tmpDirInSandbox + "/" + fn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For convenience, set an environment pointing to the top build
|
|
||||||
directory. */
|
|
||||||
env["NIX_BUILD_TOP"] = tmpDirInSandbox;
|
|
||||||
|
|
||||||
/* Also set TMPDIR and variants to point to this directory. */
|
|
||||||
env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = tmpDirInSandbox;
|
|
||||||
|
|
||||||
/* Explicitly set PWD to prevent problems with chroot builds. In
|
|
||||||
particular, dietlibc cannot figure out the cwd because the
|
|
||||||
inode of the current directory doesn't appear in .. (because
|
|
||||||
getdents returns the inode of the mount point). */
|
|
||||||
env["PWD"] = tmpDirInSandbox;
|
|
||||||
|
|
||||||
/* Compatibility hack with Nix <= 0.7: if this is a fixed-output
|
|
||||||
derivation, tell the builder, so that for instance `fetchurl'
|
|
||||||
can skip checking the output. On older Nixes, this environment
|
|
||||||
variable won't be set, so `fetchurl' will do the check. */
|
|
||||||
if (fixedOutput) env["NIX_OUTPUT_CHECKED"] = "1";
|
|
||||||
|
|
||||||
/* *Only* if this is a fixed-output derivation, propagate the
|
|
||||||
values of the environment variables specified in the
|
|
||||||
`impureEnvVars' attribute to the builder. This allows for
|
|
||||||
instance environment variables for proxy configuration such as
|
|
||||||
`http_proxy' to be easily passed to downloaders like
|
|
||||||
`fetchurl'. Passing such environment variables from the caller
|
|
||||||
to the builder is generally impure, but the output of
|
|
||||||
fixed-output derivations is by definition pure (since we
|
|
||||||
already know the cryptographic hash of the output). */
|
|
||||||
if (fixedOutput) {
|
|
||||||
Strings varNames = tokenizeString<Strings>(get(drv->env, "impureEnvVars"));
|
|
||||||
for (auto & i : varNames) env[i] = getEnv(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Substitute output placeholders with the actual output paths. */
|
/* Substitute output placeholders with the actual output paths. */
|
||||||
for (auto & output : drv->outputs)
|
for (auto & output : drv->outputs)
|
||||||
inputRewrites[hashPlaceholder(output.first)] = output.second.path;
|
inputRewrites[hashPlaceholder(output.first)] = output.second.path;
|
||||||
|
|
||||||
|
|
||||||
/* Handle exportReferencesGraph(), if set. */
|
/* Handle exportReferencesGraph(), if set. */
|
||||||
doExportReferencesGraph();
|
doExportReferencesGraph();
|
||||||
|
|
||||||
|
|
||||||
/* If `build-users-group' is not empty, then we have to build as
|
|
||||||
one of the members of that group. */
|
|
||||||
if (settings.buildUsersGroup != "" && getuid() == 0) {
|
|
||||||
buildUser.acquire();
|
|
||||||
|
|
||||||
/* Make sure that no other processes are executing under this
|
|
||||||
uid. */
|
|
||||||
buildUser.kill();
|
|
||||||
|
|
||||||
/* Change ownership of the temporary build directory. */
|
|
||||||
filesToChown.insert(tmpDir);
|
|
||||||
|
|
||||||
for (auto & p : filesToChown)
|
|
||||||
if (chown(p.c_str(), buildUser.getUID(), buildUser.getGID()) == -1)
|
|
||||||
throw SysError(format("cannot change ownership of ‘%1%’") % p);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (useChroot) {
|
if (useChroot) {
|
||||||
|
|
||||||
string defaultChrootDirs;
|
string defaultChrootDirs;
|
||||||
|
@ -2203,6 +2127,93 @@ void DerivationGoal::startBuilder()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DerivationGoal::initEnv()
|
||||||
|
{
|
||||||
|
env.clear();
|
||||||
|
|
||||||
|
/* Most shells initialise PATH to some default (/bin:/usr/bin:...) when
|
||||||
|
PATH is not set. We don't want this, so we fill it in with some dummy
|
||||||
|
value. */
|
||||||
|
env["PATH"] = "/path-not-set";
|
||||||
|
|
||||||
|
/* Set HOME to a non-existing path to prevent certain programs from using
|
||||||
|
/etc/passwd (or NIS, or whatever) to locate the home directory (for
|
||||||
|
example, wget looks for ~/.wgetrc). I.e., these tools use /etc/passwd
|
||||||
|
if HOME is not set, but they will just assume that the settings file
|
||||||
|
they are looking for does not exist if HOME is set but points to some
|
||||||
|
non-existing path. */
|
||||||
|
env["HOME"] = homeDir;
|
||||||
|
|
||||||
|
/* Tell the builder where the Nix store is. Usually they
|
||||||
|
shouldn't care, but this is useful for purity checking (e.g.,
|
||||||
|
the compiler or linker might only want to accept paths to files
|
||||||
|
in the store or in the build directory). */
|
||||||
|
env["NIX_STORE"] = worker.store.storeDir;
|
||||||
|
|
||||||
|
/* 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 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<StringSet>(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 {
|
||||||
|
string fn = ".attr-" + std::to_string(fileNr++);
|
||||||
|
Path p = tmpDir + "/" + fn;
|
||||||
|
writeFile(p, i.second);
|
||||||
|
chownToBuilder(p);
|
||||||
|
env[i.first + "Path"] = tmpDirInSandbox + "/" + fn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For convenience, set an environment pointing to the top build
|
||||||
|
directory. */
|
||||||
|
env["NIX_BUILD_TOP"] = tmpDirInSandbox;
|
||||||
|
|
||||||
|
/* Also set TMPDIR and variants to point to this directory. */
|
||||||
|
env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = tmpDirInSandbox;
|
||||||
|
|
||||||
|
/* Explicitly set PWD to prevent problems with chroot builds. In
|
||||||
|
particular, dietlibc cannot figure out the cwd because the
|
||||||
|
inode of the current directory doesn't appear in .. (because
|
||||||
|
getdents returns the inode of the mount point). */
|
||||||
|
env["PWD"] = tmpDirInSandbox;
|
||||||
|
|
||||||
|
/* Compatibility hack with Nix <= 0.7: if this is a fixed-output
|
||||||
|
derivation, tell the builder, so that for instance `fetchurl'
|
||||||
|
can skip checking the output. On older Nixes, this environment
|
||||||
|
variable won't be set, so `fetchurl' will do the check. */
|
||||||
|
if (fixedOutput) env["NIX_OUTPUT_CHECKED"] = "1";
|
||||||
|
|
||||||
|
/* *Only* if this is a fixed-output derivation, propagate the
|
||||||
|
values of the environment variables specified in the
|
||||||
|
`impureEnvVars' attribute to the builder. This allows for
|
||||||
|
instance environment variables for proxy configuration such as
|
||||||
|
`http_proxy' to be easily passed to downloaders like
|
||||||
|
`fetchurl'. Passing such environment variables from the caller
|
||||||
|
to the builder is generally impure, but the output of
|
||||||
|
fixed-output derivations is by definition pure (since we
|
||||||
|
already know the cryptographic hash of the output). */
|
||||||
|
if (fixedOutput) {
|
||||||
|
Strings varNames = tokenizeString<Strings>(get(drv->env, "impureEnvVars"));
|
||||||
|
for (auto & i : varNames) env[i] = getEnv(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DerivationGoal::chownToBuilder(const Path & path)
|
||||||
|
{
|
||||||
|
if (!buildUser.enabled()) return;
|
||||||
|
if (chown(path.c_str(), buildUser.getUID(), buildUser.getGID()) == -1)
|
||||||
|
throw SysError(format("cannot change ownership of ‘%1%’") % path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DerivationGoal::doExportReferencesGraph()
|
void DerivationGoal::doExportReferencesGraph()
|
||||||
{
|
{
|
||||||
/* The `exportReferencesGraph' feature allows the references graph
|
/* The `exportReferencesGraph' feature allows the references graph
|
||||||
|
|
Loading…
Reference in a new issue