mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-26 15:56:18 +02:00
* Another change to low-level derivations. The last one this year, I
promise :-) This allows derivations to specify on *what* output paths of input derivations they are dependent. This helps to prevent unnecessary downloads. For instance, a build might be dependent on the `devel' and `lib' outputs of some library component, but not the `docs' output.
This commit is contained in:
parent
6ff48e77f6
commit
05f0430de1
7 changed files with 70 additions and 32 deletions
|
@ -68,17 +68,17 @@ static Hash hashDerivationModulo(EvalState & state, Derivation drv)
|
|||
|
||||
/* For other derivations, replace the inputs paths with recursive
|
||||
calls to this function.*/
|
||||
PathSet inputs2;
|
||||
for (PathSet::iterator i = drv.inputDrvs.begin();
|
||||
DerivationInputs inputs2;
|
||||
for (DerivationInputs::iterator i = drv.inputDrvs.begin();
|
||||
i != drv.inputDrvs.end(); ++i)
|
||||
{
|
||||
Hash h = state.drvHashes[*i];
|
||||
Hash h = state.drvHashes[i->first];
|
||||
if (h.type == htUnknown) {
|
||||
Derivation drv2 = derivationFromPath(*i);
|
||||
Derivation drv2 = derivationFromPath(i->first);
|
||||
h = hashDerivationModulo(state, drv2);
|
||||
state.drvHashes[*i] = h;
|
||||
state.drvHashes[i->first] = h;
|
||||
}
|
||||
inputs2.insert(printHash(h));
|
||||
inputs2[printHash(h)] = i->second;
|
||||
}
|
||||
drv.inputDrvs = inputs2;
|
||||
|
||||
|
@ -119,7 +119,9 @@ static void processBinding(EvalState & state, Expr e, Derivation & drv,
|
|||
/* !!! supports only single output path */
|
||||
Path outPath = evalPath(state, a);
|
||||
|
||||
drv.inputDrvs.insert(drvPath);
|
||||
StringSet ids;
|
||||
ids.insert("out");
|
||||
drv.inputDrvs[drvPath] = ids;
|
||||
ss.push_back(outPath);
|
||||
} else
|
||||
throw Error("invalid derivation attribute");
|
||||
|
|
|
@ -448,9 +448,10 @@ void DerivationGoal::haveStoreExpr()
|
|||
}
|
||||
|
||||
/* Inputs must be built before we can build this goal. */
|
||||
for (PathSet::iterator i = drv.inputDrvs.begin();
|
||||
/* !!! but if possible, only install the paths that we need */
|
||||
for (DerivationInputs::iterator i = drv.inputDrvs.begin();
|
||||
i != drv.inputDrvs.end(); ++i)
|
||||
addWaitee(worker.makeDerivationGoal(*i));
|
||||
addWaitee(worker.makeDerivationGoal(i->first));
|
||||
|
||||
for (PathSet::iterator i = drv.inputSrcs.begin();
|
||||
i != drv.inputSrcs.end(); ++i)
|
||||
|
@ -812,18 +813,23 @@ bool DerivationGoal::prepareBuild()
|
|||
/* Determine the full set of input paths. */
|
||||
|
||||
/* First, the input derivations. */
|
||||
for (PathSet::iterator i = drv.inputDrvs.begin();
|
||||
for (DerivationInputs::iterator i = drv.inputDrvs.begin();
|
||||
i != drv.inputDrvs.end(); ++i)
|
||||
{
|
||||
/* Add all the output closures of the input derivation `*i' as
|
||||
input paths. !!! there should be a way to indicate
|
||||
specific outputs. */
|
||||
/* Add the relevant output closures of the input derivation
|
||||
`*i' as input paths. Only add the closures of output paths
|
||||
that are specified as inputs. */
|
||||
/* !!! is `*i' present? */
|
||||
assert(isValidPath(*i));
|
||||
Derivation inDrv = derivationFromPath(*i);
|
||||
for (DerivationOutputs::iterator j = inDrv.outputs.begin();
|
||||
j != inDrv.outputs.end(); ++j)
|
||||
computeFSClosure(j->second.path, inputPaths);
|
||||
assert(isValidPath(i->first));
|
||||
Derivation inDrv = derivationFromPath(i->first);
|
||||
for (StringSet::iterator j = i->second.begin();
|
||||
j != i->second.begin(); ++j)
|
||||
if (inDrv.outputs.find(*j) != inDrv.outputs.end())
|
||||
computeFSClosure(inDrv.outputs[*j].path, inputPaths);
|
||||
else
|
||||
throw Error(
|
||||
format("derivation `%1%' requires non-existent output `%2%' from input derivation `%3%'")
|
||||
% drvPath % *j % i->first);
|
||||
}
|
||||
|
||||
for (PathSet::iterator i = inputPaths.begin(); i != inputPaths.end(); ++i)
|
||||
|
|
|
@ -3,4 +3,5 @@ init initDerivationsHelpers
|
|||
Derive | ATermList ATermList ATermList string string ATermList ATermList | ATerm |
|
||||
|
||||
| string string | ATerm | EnvBinding |
|
||||
| string ATermList | ATerm | DerivationInput |
|
||||
| string string string string | ATerm | DerivationOutput |
|
||||
|
|
|
@ -26,13 +26,13 @@ static void checkPath(const string & s)
|
|||
}
|
||||
|
||||
|
||||
static void parsePaths(ATermList paths, PathSet & out)
|
||||
static void parseStrings(ATermList paths, StringSet & out, bool arePaths)
|
||||
{
|
||||
for (ATermIterator i(paths); i; ++i) {
|
||||
if (ATgetType(*i) != AT_APPL)
|
||||
throw badTerm("not a path", *i);
|
||||
string s = aterm2String(*i);
|
||||
checkPath(s);
|
||||
if (arePaths) checkPath(s);
|
||||
out.insert(s);
|
||||
}
|
||||
}
|
||||
|
@ -65,8 +65,19 @@ Derivation parseDerivation(ATerm t)
|
|||
drv.outputs[aterm2String(id)] = out;
|
||||
}
|
||||
|
||||
parsePaths(inDrvs, drv.inputDrvs);
|
||||
parsePaths(inSrcs, drv.inputSrcs);
|
||||
for (ATermIterator i(inDrvs); i; ++i) {
|
||||
ATerm drvPath;
|
||||
ATermList ids;
|
||||
if (!matchDerivationInput(*i, drvPath, ids))
|
||||
throwBadDrv(t);
|
||||
Path drvPath2 = aterm2String(drvPath);
|
||||
checkPath(drvPath2);
|
||||
StringSet ids2;
|
||||
parseStrings(ids, ids2, false);
|
||||
drv.inputDrvs[drvPath2] = ids2;
|
||||
}
|
||||
|
||||
parseStrings(inSrcs, drv.inputSrcs, true);
|
||||
|
||||
drv.builder = aterm2String(builder);
|
||||
drv.platform = aterm2String(platform);
|
||||
|
@ -88,11 +99,11 @@ Derivation parseDerivation(ATerm t)
|
|||
}
|
||||
|
||||
|
||||
static ATermList unparsePaths(const PathSet & paths)
|
||||
static ATermList unparseStrings(const StringSet & paths)
|
||||
{
|
||||
ATermList l = ATempty;
|
||||
for (PathSet::const_iterator i = paths.begin();
|
||||
i != paths.end(); i++)
|
||||
i != paths.end(); ++i)
|
||||
l = ATinsert(l, toATerm(*i));
|
||||
return ATreverse(l);
|
||||
}
|
||||
|
@ -102,7 +113,7 @@ ATerm unparseDerivation(const Derivation & drv)
|
|||
{
|
||||
ATermList outputs = ATempty;
|
||||
for (DerivationOutputs::const_iterator i = drv.outputs.begin();
|
||||
i != drv.outputs.end(); i++)
|
||||
i != drv.outputs.end(); ++i)
|
||||
outputs = ATinsert(outputs,
|
||||
makeDerivationOutput(
|
||||
toATerm(i->first),
|
||||
|
@ -110,14 +121,22 @@ ATerm unparseDerivation(const Derivation & drv)
|
|||
toATerm(i->second.hashAlgo),
|
||||
toATerm(i->second.hash)));
|
||||
|
||||
ATermList inDrvs = ATempty;
|
||||
for (DerivationInputs::const_iterator i = drv.inputDrvs.begin();
|
||||
i != drv.inputDrvs.end(); ++i)
|
||||
inDrvs = ATinsert(inDrvs,
|
||||
makeDerivationInput(
|
||||
toATerm(i->first),
|
||||
unparseStrings(i->second)));
|
||||
|
||||
ATermList args = ATempty;
|
||||
for (Strings::const_iterator i = drv.args.begin();
|
||||
i != drv.args.end(); i++)
|
||||
i != drv.args.end(); ++i)
|
||||
args = ATinsert(args, toATerm(*i));
|
||||
|
||||
ATermList env = ATempty;
|
||||
for (StringPairs::const_iterator i = drv.env.begin();
|
||||
i != drv.env.end(); i++)
|
||||
i != drv.env.end(); ++i)
|
||||
env = ATinsert(env,
|
||||
makeEnvBinding(
|
||||
toATerm(i->first),
|
||||
|
@ -125,8 +144,8 @@ ATerm unparseDerivation(const Derivation & drv)
|
|||
|
||||
return makeDerive(
|
||||
ATreverse(outputs),
|
||||
unparsePaths(drv.inputDrvs),
|
||||
unparsePaths(drv.inputSrcs),
|
||||
ATreverse(inDrvs),
|
||||
unparseStrings(drv.inputSrcs),
|
||||
toATerm(drv.platform),
|
||||
toATerm(drv.builder),
|
||||
ATreverse(args),
|
||||
|
|
|
@ -28,12 +28,17 @@ struct DerivationOutput
|
|||
};
|
||||
|
||||
typedef map<string, DerivationOutput> DerivationOutputs;
|
||||
|
||||
/* For inputs that are sub-derivations, we specify exactly which
|
||||
output IDs we are interested in. */
|
||||
typedef map<Path, StringSet> DerivationInputs;
|
||||
|
||||
typedef map<string, string> StringPairs;
|
||||
|
||||
struct Derivation
|
||||
{
|
||||
DerivationOutputs outputs; /* keyed on symbolic IDs */
|
||||
PathSet inputDrvs; /* inputs that are sub-derivations */
|
||||
DerivationInputs inputDrvs; /* inputs that are sub-derivations */
|
||||
PathSet inputSrcs; /* inputs that are sources */
|
||||
string platform;
|
||||
Path builder;
|
||||
|
|
|
@ -39,9 +39,12 @@ void storePathRequisites(const Path & storePath,
|
|||
|
||||
Derivation drv = derivationFromPath(storePath);
|
||||
|
||||
for (PathSet::iterator i = drv.inputDrvs.begin();
|
||||
for (DerivationInputs::iterator i = drv.inputDrvs.begin();
|
||||
i != drv.inputDrvs.end(); ++i)
|
||||
storePathRequisites(*i, includeOutputs, paths);
|
||||
/* !!! Maybe this is too strict, since it will include
|
||||
*all* output paths of the input derivation, not just
|
||||
the ones needed by this derivation. */
|
||||
storePathRequisites(i->first, includeOutputs, paths);
|
||||
|
||||
for (PathSet::iterator i = drv.inputSrcs.begin();
|
||||
i != drv.inputSrcs.end(); ++i)
|
||||
|
|
|
@ -588,6 +588,8 @@ Strings unpackStrings(const string & s)
|
|||
len |= ((unsigned char) *i++) << 16;
|
||||
len |= ((unsigned char) *i++) << 24;
|
||||
|
||||
if (len == 0xffffffff) return strings; /* explicit end-of-list */
|
||||
|
||||
if (i + len > s.end())
|
||||
throw Error(format("short db entry: `%1%'") % s);
|
||||
|
||||
|
|
Loading…
Reference in a new issue