* An quick and dirty hack to support distributed builds.
This commit is contained in:
parent
c8d3882cdc
commit
8c0b42f857
9 changed files with 92 additions and 13 deletions
|
@ -52,13 +52,6 @@ void checkStoreNotSymlink(Path path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static string getEnv(const string & key, const string & def = "")
|
|
||||||
{
|
|
||||||
char * value = getenv(key.c_str());
|
|
||||||
return value ? string(value) : def;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Initialize and reorder arguments, then call the actual argument
|
/* Initialize and reorder arguments, then call the actual argument
|
||||||
processor. */
|
processor. */
|
||||||
static void initAndRun(int argc, char * * argv)
|
static void initAndRun(int argc, char * * argv)
|
||||||
|
|
|
@ -302,6 +302,7 @@ bool Normaliser::startBuild(Path nePath)
|
||||||
|
|
||||||
/* Obtain locks on all output paths. The locks are automatically
|
/* Obtain locks on all output paths. The locks are automatically
|
||||||
released when we exit this function or Nix crashes. */
|
released when we exit this function or Nix crashes. */
|
||||||
|
/* !!! BUG: this could block, which is not allowed. */
|
||||||
goal.outputLocks.lockPaths(goal.expr.derivation.outputs);
|
goal.outputLocks.lockPaths(goal.expr.derivation.outputs);
|
||||||
|
|
||||||
/* Now check again whether there is a successor. This is because
|
/* Now check again whether there is a successor. This is because
|
||||||
|
@ -364,6 +365,25 @@ bool Normaliser::startBuild(Path nePath)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* !!! Hack */
|
||||||
|
Path buildHook = getEnv("NIX_BUILD_HOOK");
|
||||||
|
if (buildHook != "") {
|
||||||
|
printMsg(lvlChatty, format("using build hook `%1%'") % buildHook);
|
||||||
|
int status = system((buildHook + " " + goal.nePath + " 1>&2").c_str());
|
||||||
|
if (WIFEXITED(status)) {
|
||||||
|
int code = WEXITSTATUS(status);
|
||||||
|
if (code == 100) { /* == accepted */
|
||||||
|
printMsg(lvlChatty,
|
||||||
|
format("build hook succesfully realised output paths"));
|
||||||
|
finishGoal(goal);
|
||||||
|
return true;
|
||||||
|
} else if (code != 101) /* != declined */
|
||||||
|
throw Error(
|
||||||
|
format("build hook returned exit code %1%") % code);
|
||||||
|
} else throw Error(
|
||||||
|
format("build hook died with status %1%") % status);
|
||||||
|
}
|
||||||
|
|
||||||
/* Otherwise, start the build in a child process. */
|
/* Otherwise, start the build in a child process. */
|
||||||
startBuildChild(goal);
|
startBuildChild(goal);
|
||||||
|
|
||||||
|
@ -660,7 +680,7 @@ void Normaliser::finishGoal(Goal & goal)
|
||||||
{
|
{
|
||||||
Path path = *i;
|
Path path = *i;
|
||||||
if (!pathExists(path))
|
if (!pathExists(path))
|
||||||
throw Error(format("path `%1%' does not exist") % path);
|
throw Error(format("output path `%1%' does not exist") % path);
|
||||||
nf.closure.roots.insert(path);
|
nf.closure.roots.insert(path);
|
||||||
|
|
||||||
makePathReadOnly(path);
|
makePathReadOnly(path);
|
||||||
|
|
|
@ -29,6 +29,13 @@ SysError::SysError(const format & f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string getEnv(const string & key, const string & def)
|
||||||
|
{
|
||||||
|
char * value = getenv(key.c_str());
|
||||||
|
return value ? string(value) : def;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Path absPath(Path path, Path dir)
|
Path absPath(Path path, Path dir)
|
||||||
{
|
{
|
||||||
if (path[0] != '/') {
|
if (path[0] != '/') {
|
||||||
|
@ -206,8 +213,7 @@ void makePathReadOnly(const Path & path)
|
||||||
static Path tempName()
|
static Path tempName()
|
||||||
{
|
{
|
||||||
static int counter = 0;
|
static int counter = 0;
|
||||||
char * s = getenv("TMPDIR");
|
Path tmpRoot = canonPath(getEnv("TMPDIR", "/tmp"));
|
||||||
Path tmpRoot = s ? canonPath(Path(s)) : "/tmp";
|
|
||||||
return (format("%1%/nix-%2%-%3%") % tmpRoot % getpid() % counter++).str();
|
return (format("%1%/nix-%2%-%3%") % tmpRoot % getpid() % counter++).str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,9 @@ typedef set<Path> PathSet;
|
||||||
extern string thisSystem;
|
extern string thisSystem;
|
||||||
|
|
||||||
|
|
||||||
|
/* Return an environment variable. */
|
||||||
|
string getEnv(const string & key, const string & def = "");
|
||||||
|
|
||||||
/* Return an absolutized path, resolving paths relative to the
|
/* Return an absolutized path, resolving paths relative to the
|
||||||
specified directory, or the current directory otherwise. The path
|
specified directory, or the current directory otherwise. The path
|
||||||
is also canonicalised. */
|
is also canonicalised. */
|
||||||
|
|
|
@ -118,7 +118,7 @@ void loadDerivations(EvalState & state, Path nePath, DrvInfos & drvs)
|
||||||
|
|
||||||
static Path getHomeDir()
|
static Path getHomeDir()
|
||||||
{
|
{
|
||||||
Path homeDir(getenv("HOME"));
|
Path homeDir(getEnv("HOME", ""));
|
||||||
if (homeDir == "") throw Error("HOME environment variable not set");
|
if (homeDir == "") throw Error("HOME environment variable not set");
|
||||||
return homeDir;
|
return homeDir;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,10 @@ simple.sh: simple.nix
|
||||||
dependencies.sh: dependencies.nix
|
dependencies.sh: dependencies.nix
|
||||||
locking.sh: locking.nix
|
locking.sh: locking.nix
|
||||||
parallel.sh: parallel.nix
|
parallel.sh: parallel.nix
|
||||||
|
build-hook.sh: build-hook.nix
|
||||||
|
|
||||||
TESTS = init.sh simple.sh dependencies.sh locking.sh parallel.sh
|
TESTS = init.sh simple.sh dependencies.sh locking.sh parallel.sh \
|
||||||
|
build-hook.sh
|
||||||
|
|
||||||
XFAIL_TESTS =
|
XFAIL_TESTS =
|
||||||
|
|
||||||
|
@ -27,4 +29,5 @@ EXTRA_DIST = $(TESTS) \
|
||||||
simple.nix.in simple.builder.sh \
|
simple.nix.in simple.builder.sh \
|
||||||
dependencies.nix.in dependencies.builder*.sh \
|
dependencies.nix.in dependencies.builder*.sh \
|
||||||
locking.nix.in locking.builder.sh \
|
locking.nix.in locking.builder.sh \
|
||||||
parallel.nix.in parallel.builder.sh
|
parallel.nix.in parallel.builder.sh \
|
||||||
|
build-hook.nix.in
|
||||||
|
|
17
tests/build-hook.hook.sh
Normal file
17
tests/build-hook.hook.sh
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
set -x
|
||||||
|
|
||||||
|
drv=$1
|
||||||
|
|
||||||
|
echo "HOOK for $drv"
|
||||||
|
|
||||||
|
outPath=$(sed 's/Derive(\[\"\([^\"]*\)\".*/\1/' $drv)
|
||||||
|
|
||||||
|
echo "output path is $outPath"
|
||||||
|
|
||||||
|
if $(echo $outPath | grep -q input-1); then
|
||||||
|
mkdir $outPath
|
||||||
|
echo "BAR" > $outPath/foo
|
||||||
|
exit 100
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 101
|
25
tests/build-hook.nix.in
Normal file
25
tests/build-hook.nix.in
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
let {
|
||||||
|
|
||||||
|
input1 = derivation {
|
||||||
|
name = "dependencies-input-1";
|
||||||
|
system = "@system@";
|
||||||
|
builder = "@shell@";
|
||||||
|
args = ["-e" "-x" ./dependencies.builder1.sh];
|
||||||
|
};
|
||||||
|
|
||||||
|
input2 = derivation {
|
||||||
|
name = "dependencies-input-2";
|
||||||
|
system = "@system@";
|
||||||
|
builder = "@shell@";
|
||||||
|
args = ["-e" "-x" ./dependencies.builder2.sh];
|
||||||
|
};
|
||||||
|
|
||||||
|
body = derivation {
|
||||||
|
name = "dependencies";
|
||||||
|
system = "@system@";
|
||||||
|
builder = "@shell@";
|
||||||
|
args = ["-e" "-x" ./dependencies.builder0.sh];
|
||||||
|
inherit input1 input2;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
12
tests/build-hook.sh
Normal file
12
tests/build-hook.sh
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
export NIX_BUILD_HOOK="sh build-hook.hook.sh"
|
||||||
|
|
||||||
|
storeExpr=$($TOP/src/nix-instantiate/nix-instantiate build-hook.nix)
|
||||||
|
|
||||||
|
echo "store expr is $storeExpr"
|
||||||
|
|
||||||
|
outPath=$($TOP/src/nix-store/nix-store -qnfvvvvv "$storeExpr")
|
||||||
|
|
||||||
|
echo "output path is $outPath"
|
||||||
|
|
||||||
|
text=$(cat "$outPath"/foobar)
|
||||||
|
if test "$text" != "BARBAR"; then exit 1; fi
|
Loading…
Reference in a new issue