aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/build.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore/build.cc')
-rw-r--r--src/libstore/build.cc107
1 files changed, 107 insertions, 0 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 1fc5d4181..de33e1154 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -89,6 +89,7 @@ static string pathNullDevice = "/dev/null";
/* Forward definition. */
class Worker;
struct HookInstance;
+struct PreBuildHookInstance;
/* A pointer to a goal. */
@@ -269,6 +270,8 @@ public:
std::shared_ptr<HookInstance> hook;
+ std::shared_ptr<PreBuildHookInstance> preBuildHook;
+
Worker(LocalStore & store);
~Worker();
@@ -649,6 +652,72 @@ HookInstance::~HookInstance()
//////////////////////////////////////////////////////////////////////
+struct PreBuildHookInstance
+{
+ /* Pipes for talking to the build hook. */
+ Pipe toHook;
+
+ /* Pipe for the hook's standard output/error. */
+ Pipe fromHook;
+
+ /* The process ID of the hook. */
+ Pid pid;
+
+ PreBuildHookInstance();
+
+ ~PreBuildHookInstance();
+};
+
+
+PreBuildHookInstance::PreBuildHookInstance()
+{
+ debug("starting pre-build hook");
+
+ /* Create a pipe to get the output of the child. */
+ fromHook.create();
+
+ /* Create the communication pipes. */
+ toHook.create();
+
+ /* Fork the hook. */
+ pid = startProcess([&]() {
+
+ commonChildInit(fromHook);
+
+ if (chdir("/") == -1) throw SysError("changing into /");
+
+ /* Dup the communication pipes. */
+ if (dup2(toHook.readSide, STDIN_FILENO) == -1)
+ throw SysError("dupping to-hook read side");
+
+ setenv("_NIX_OPTIONS", settings.pack().c_str(), 1);
+
+ execl(settings.preBuildHook.c_str(), settings.preBuildHook.c_str(),
+ NULL);
+
+ throw SysError(format("executing ‘%1%’") % settings.preBuildHook);
+ });
+
+ pid.setSeparatePG(true);
+ fromHook.writeSide.close();
+ toHook.readSide.close();
+}
+
+
+PreBuildHookInstance::~PreBuildHookInstance()
+{
+ try {
+ toHook.writeSide.close();
+ pid.kill(true);
+ } catch (...) {
+ ignoreException();
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////
+
+
typedef map<string, string> HashRewrites;
@@ -813,6 +882,13 @@ private:
/* Is the build hook willing to perform the build? */
HookReply tryBuildHook();
+ /* Run the pre-build hook, which can set system-specific
+ per-derivation settings too complex/volatile to hard-code
+ in nix itself */
+ void runPreBuildHook();
+
+ PathSet extraChrootDirs;
+
/* Start building a derivation. */
void startBuilder();
@@ -1178,6 +1254,9 @@ void DerivationGoal::inputsRealised()
foreach (DerivationOutputs::iterator, i, drv.outputs)
if (i->second.hash == "") fixedOutput = false;
+ /* Ask the pre-build hook for any required settings */
+ runPreBuildHook();
+
/* Okay, try to build. Note that here we don't wait for a build
slot to become available, since we don't need one if there is a
build hook. */
@@ -1794,6 +1873,7 @@ void DerivationGoal::startBuilder()
PathSet dirs = tokenizeString<StringSet>(settings.get("build-chroot-dirs", defaultChrootDirs));
PathSet dirs2 = tokenizeString<StringSet>(settings.get("build-extra-chroot-dirs", string("")));
dirs.insert(dirs2.begin(), dirs2.end());
+ dirs.insert(extraChrootDirs.begin(), extraChrootDirs.end());
for (auto & i : dirs) {
size_t p = i.find('=');
@@ -2794,6 +2874,33 @@ Path DerivationGoal::addHashRewrite(const Path & path)
}
+void DerivationGoal::runPreBuildHook()
+{
+ if (settings.preBuildHook == "")
+ return;
+
+ if (!worker.preBuildHook)
+ worker.preBuildHook = std::make_shared<PreBuildHookInstance>();
+
+ writeLine(worker.preBuildHook->toHook.writeSide, drvPath);
+ while (true) {
+ string s = readLine(worker.preBuildHook->fromHook.readSide);
+ if (s == "extra-chroot-dirs") {
+ while (true) {
+ string s = readLine(worker.preBuildHook->fromHook.readSide);
+ if (s == "")
+ break;
+ extraChrootDirs.emplace(std::move(s));
+ }
+ } else if (s == "") {
+ break;
+ } else {
+ throw Error(format("unknown pre-build hook command ‘%1%’") % s);
+ }
+ }
+}
+
+
//////////////////////////////////////////////////////////////////////