aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2017-09-06 16:03:22 +0200
committerEelco Dolstra <edolstra@gmail.com>2017-09-06 16:03:22 +0200
commitdf4342bc175a153986ebcf5bce2a758d5353adeb (patch)
treed491cac5bd1c4d45c689fd1a19c98958c32e9674
parent1277aab219c83beae856024eea6e868677f7523b (diff)
nix build: Create result symlinks
-rw-r--r--src/nix/build.cc15
-rw-r--r--src/nix/command.hh19
-rw-r--r--src/nix/installables.cc87
-rw-r--r--src/nix/log.cc26
4 files changed, 105 insertions, 42 deletions
diff --git a/src/nix/build.cc b/src/nix/build.cc
index 4239dd3ff..64bcafd2d 100644
--- a/src/nix/build.cc
+++ b/src/nix/build.cc
@@ -23,9 +23,20 @@ struct CmdBuild : MixDryRun, InstallablesCommand
void run(ref<Store> store) override
{
- auto paths = toStorePaths(store, dryRun ? DryRun : Build);
+ auto buildables = toBuildables(store, dryRun ? DryRun : Build);
- printError("build result: %s", showPaths(paths));
+ for (size_t i = 0; i < buildables.size(); ++i) {
+ auto & b(buildables[i]);
+
+ for (auto & output : b.outputs) {
+ if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>()) {
+ std::string symlink = "result";
+ if (i) symlink += fmt("-%d", i);
+ if (output.first != "out") symlink += fmt("-%s", output.first);
+ store2->addPermRoot(output.second, absPath(symlink), true);
+ }
+ }
+ }
}
};
diff --git a/src/nix/command.hh b/src/nix/command.hh
index 479e6fd37..b052c42b1 100644
--- a/src/nix/command.hh
+++ b/src/nix/command.hh
@@ -44,18 +44,25 @@ private:
std::shared_ptr<Store> _store;
};
-struct Whence { std::string outputName; Path drvPath; };
-typedef std::map<Path, Whence> Buildables;
+struct Buildable
+{
+ Path drvPath; // may be empty
+ std::map<std::string, Path> outputs;
+};
+
+typedef std::vector<Buildable> Buildables;
struct Installable
{
virtual std::string what() = 0;
- virtual Buildables toBuildable(bool singular = false)
+ virtual Buildables toBuildables()
{
throw Error("argument '%s' cannot be built", what());
}
+ Buildable toBuildable();
+
virtual Value * toValue(EvalState & state)
{
throw Error("argument '%s' cannot be evaluated", what());
@@ -97,9 +104,11 @@ struct InstallablesCommand : virtual Args, SourceExprCommand
expectArgs("installables", &_installables);
}
- enum ToStorePathsMode { Build, NoBuild, DryRun };
+ enum RealiseMode { Build, NoBuild, DryRun };
+
+ Buildables toBuildables(ref<Store> store, RealiseMode mode);
- PathSet toStorePaths(ref<Store> store, ToStorePathsMode mode);
+ PathSet toStorePaths(ref<Store> store, RealiseMode mode);
void prepare() override;
diff --git a/src/nix/installables.cc b/src/nix/installables.cc
index fdb6004fb..f3c7d3075 100644
--- a/src/nix/installables.cc
+++ b/src/nix/installables.cc
@@ -70,17 +70,27 @@ ref<EvalState> SourceExprCommand::getEvalState()
return ref<EvalState>(evalState);
}
+Buildable Installable::toBuildable()
+{
+ auto buildables = toBuildables();
+ if (buildables.size() != 1)
+ throw Error("installable '%s' evaluates to %d derivations, where only one is expected", what(), buildables.size());
+ return std::move(buildables[0]);
+}
+
struct InstallableStoreDrv : Installable
{
- Path storePath;
+ Path drvPath;
- InstallableStoreDrv(const Path & storePath) : storePath(storePath) { }
+ InstallableStoreDrv(const Path & drvPath) : drvPath(drvPath) { }
- std::string what() override { return storePath; }
+ std::string what() override { return drvPath; }
- Buildables toBuildable(bool singular) override
+ Buildables toBuildables() override
{
- return {{storePath, {}}};
+ Buildable b = {drvPath};
+ // FIXME: add outputs?
+ return {b};
}
};
@@ -92,9 +102,9 @@ struct InstallableStorePath : Installable
std::string what() override { return storePath; }
- Buildables toBuildable(bool singular) override
+ Buildables toBuildables() override
{
- return {{storePath, {}}};
+ return {{"", {{"out", storePath}}}};
}
};
@@ -104,7 +114,7 @@ struct InstallableValue : Installable
InstallableValue(SourceExprCommand & cmd) : cmd(cmd) { }
- Buildables toBuildable(bool singular) override
+ Buildables toBuildables() override
{
auto state = cmd.getEvalState();
@@ -117,16 +127,32 @@ struct InstallableValue : Installable
DrvInfos drvs;
getDerivations(*state, *v, "", autoArgs, drvs, false);
- if (singular && drvs.size() != 1)
- throw Error("installable '%s' evaluates to %d derivations, where only one is expected", what(), drvs.size());
-
Buildables res;
- for (auto & drv : drvs)
- for (auto & output : drv.queryOutputs())
- res.emplace(output.second, Whence{output.first, drv.queryDrvPath()});
+ PathSet drvPaths;
+
+ for (auto & drv : drvs) {
+ Buildable b{drv.queryDrvPath()};
+ drvPaths.insert(b.drvPath);
+
+ auto outputName = drv.queryOutputName();
+ if (outputName == "")
+ throw Error("derivation '%s' lacks an 'outputName' attribute", b.drvPath);
+
+ b.outputs.emplace(outputName, drv.queryOutPath());
- return res;
+ res.push_back(std::move(b));
+ }
+
+ // Hack to recognize .all: if all drvs have the same drvPath,
+ // merge the buildables.
+ if (drvPaths.size() == 1) {
+ Buildable b{*drvPaths.begin()};
+ for (auto & b2 : res)
+ b.outputs.insert(b2.outputs.begin(), b2.outputs.end());
+ return {b};
+ } else
+ return res;
}
};
@@ -214,23 +240,38 @@ static std::vector<std::shared_ptr<Installable>> parseInstallables(
return result;
}
-PathSet InstallablesCommand::toStorePaths(ref<Store> store, ToStorePathsMode mode)
+Buildables InstallablesCommand::toBuildables(ref<Store> store, RealiseMode mode)
{
if (mode != Build)
settings.readOnlyMode = true;
- PathSet outPaths, buildables;
+ Buildables buildables;
+
+ PathSet pathsToBuild;
- for (auto & i : installables)
- for (auto & b : i->toBuildable()) {
- outPaths.insert(b.first);
- buildables.insert(b.second.drvPath != "" ? b.second.drvPath : b.first);
+ for (auto & i : installables) {
+ for (auto & b : i->toBuildables()) {
+ if (b.drvPath != "")
+ pathsToBuild.insert(b.drvPath);
+ buildables.push_back(std::move(b));
}
+ }
if (mode == DryRun)
- printMissing(store, buildables, lvlError);
+ printMissing(store, pathsToBuild, lvlError);
else if (mode == Build)
- store->buildPaths(buildables);
+ store->buildPaths(pathsToBuild);
+
+ return buildables;
+}
+
+PathSet InstallablesCommand::toStorePaths(ref<Store> store, RealiseMode mode)
+{
+ PathSet outPaths;
+
+ for (auto & b : toBuildables(store, mode))
+ for (auto & output : b.outputs)
+ outPaths.insert(output.second);
return outPaths;
}
diff --git a/src/nix/log.cc b/src/nix/log.cc
index ba5e71c10..15ae61d08 100644
--- a/src/nix/log.cc
+++ b/src/nix/log.cc
@@ -24,23 +24,25 @@ struct CmdLog : InstallableCommand
void run(ref<Store> store) override
{
+ settings.readOnlyMode = true;
+
auto subs = getDefaultSubstituters();
subs.push_front(store);
- for (auto & b : installable->toBuildable(true)) {
-
- for (auto & sub : subs) {
- auto log = b.second.drvPath != "" ? sub->getBuildLog(b.second.drvPath) : nullptr;
- if (!log) {
- log = sub->getBuildLog(b.first);
- if (!log) continue;
- }
- stopProgressBar();
- printInfo("got build log for '%s' from '%s'", b.first, sub->getUri());
- std::cout << *log;
- return;
+ auto b = installable->toBuildable();
+
+ for (auto & sub : subs) {
+ auto log = b.drvPath != "" ? sub->getBuildLog(b.drvPath) : nullptr;
+ for (auto & output : b.outputs) {
+ if (log) break;
+ log = sub->getBuildLog(output.second);
}
+ if (!log) continue;
+ stopProgressBar();
+ printInfo("got build log for '%s' from '%s'", installable->what(), sub->getUri());
+ std::cout << *log;
+ return;
}
throw Error("build log of '%s' is not available", installable->what());