forked from lix-project/lix
Merge pull request #7328 from edolstra/nix-build-stats
nix build --json: Include build statistics
This commit is contained in:
commit
05d0892443
|
@ -844,20 +844,20 @@ std::shared_ptr<Installable> SourceExprCommand::parseInstallable(
|
||||||
return installables.front();
|
return installables.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
BuiltPaths Installable::build(
|
std::vector<BuiltPathWithResult> Installable::build(
|
||||||
ref<Store> evalStore,
|
ref<Store> evalStore,
|
||||||
ref<Store> store,
|
ref<Store> store,
|
||||||
Realise mode,
|
Realise mode,
|
||||||
const std::vector<std::shared_ptr<Installable>> & installables,
|
const std::vector<std::shared_ptr<Installable>> & installables,
|
||||||
BuildMode bMode)
|
BuildMode bMode)
|
||||||
{
|
{
|
||||||
BuiltPaths res;
|
std::vector<BuiltPathWithResult> res;
|
||||||
for (auto & [_, builtPath] : build2(evalStore, store, mode, installables, bMode))
|
for (auto & [_, builtPathWithResult] : build2(evalStore, store, mode, installables, bMode))
|
||||||
res.push_back(builtPath);
|
res.push_back(builtPathWithResult);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> Installable::build2(
|
std::vector<std::pair<std::shared_ptr<Installable>, BuiltPathWithResult>> Installable::build2(
|
||||||
ref<Store> evalStore,
|
ref<Store> evalStore,
|
||||||
ref<Store> store,
|
ref<Store> store,
|
||||||
Realise mode,
|
Realise mode,
|
||||||
|
@ -877,7 +877,7 @@ std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> Installable::bui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> res;
|
std::vector<std::pair<std::shared_ptr<Installable>, BuiltPathWithResult>> res;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
|
|
||||||
|
@ -918,10 +918,10 @@ std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> Installable::bui
|
||||||
output, *drvOutput->second);
|
output, *drvOutput->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res.push_back({installable, BuiltPath::Built { bfd.drvPath, outputs }});
|
res.push_back({installable, {.path = BuiltPath::Built { bfd.drvPath, outputs }}});
|
||||||
},
|
},
|
||||||
[&](const DerivedPath::Opaque & bo) {
|
[&](const DerivedPath::Opaque & bo) {
|
||||||
res.push_back({installable, BuiltPath::Opaque { bo.path }});
|
res.push_back({installable, {.path = BuiltPath::Opaque { bo.path }}});
|
||||||
},
|
},
|
||||||
}, path.raw());
|
}, path.raw());
|
||||||
}
|
}
|
||||||
|
@ -943,10 +943,10 @@ std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> Installable::bui
|
||||||
std::map<std::string, StorePath> outputs;
|
std::map<std::string, StorePath> outputs;
|
||||||
for (auto & path : buildResult.builtOutputs)
|
for (auto & path : buildResult.builtOutputs)
|
||||||
outputs.emplace(path.first.outputName, path.second.outPath);
|
outputs.emplace(path.first.outputName, path.second.outPath);
|
||||||
res.push_back({installable, BuiltPath::Built { bfd.drvPath, outputs }});
|
res.push_back({installable, {.path = BuiltPath::Built { bfd.drvPath, outputs }, .result = buildResult}});
|
||||||
},
|
},
|
||||||
[&](const DerivedPath::Opaque & bo) {
|
[&](const DerivedPath::Opaque & bo) {
|
||||||
res.push_back({installable, BuiltPath::Opaque { bo.path }});
|
res.push_back({installable, {.path = BuiltPath::Opaque { bo.path }, .result = buildResult}});
|
||||||
},
|
},
|
||||||
}, buildResult.path.raw());
|
}, buildResult.path.raw());
|
||||||
}
|
}
|
||||||
|
@ -969,9 +969,12 @@ BuiltPaths Installable::toBuiltPaths(
|
||||||
OperateOn operateOn,
|
OperateOn operateOn,
|
||||||
const std::vector<std::shared_ptr<Installable>> & installables)
|
const std::vector<std::shared_ptr<Installable>> & installables)
|
||||||
{
|
{
|
||||||
if (operateOn == OperateOn::Output)
|
if (operateOn == OperateOn::Output) {
|
||||||
return Installable::build(evalStore, store, mode, installables);
|
BuiltPaths res;
|
||||||
else {
|
for (auto & p : Installable::build(evalStore, store, mode, installables))
|
||||||
|
res.push_back(p.path);
|
||||||
|
return res;
|
||||||
|
} else {
|
||||||
if (mode == Realise::Nothing)
|
if (mode == Realise::Nothing)
|
||||||
settings.readOnlyMode = true;
|
settings.readOnlyMode = true;
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
#include "flake/flake.hh"
|
#include "flake/flake.hh"
|
||||||
|
#include "build-result.hh"
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
|
@ -51,6 +52,12 @@ enum class OperateOn {
|
||||||
Derivation
|
Derivation
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BuiltPathWithResult
|
||||||
|
{
|
||||||
|
BuiltPath path;
|
||||||
|
std::optional<BuildResult> result;
|
||||||
|
};
|
||||||
|
|
||||||
struct Installable
|
struct Installable
|
||||||
{
|
{
|
||||||
virtual ~Installable() { }
|
virtual ~Installable() { }
|
||||||
|
@ -91,14 +98,14 @@ struct Installable
|
||||||
return FlakeRef::fromAttrs({{"type","indirect"}, {"id", "nixpkgs"}});
|
return FlakeRef::fromAttrs({{"type","indirect"}, {"id", "nixpkgs"}});
|
||||||
}
|
}
|
||||||
|
|
||||||
static BuiltPaths build(
|
static std::vector<BuiltPathWithResult> build(
|
||||||
ref<Store> evalStore,
|
ref<Store> evalStore,
|
||||||
ref<Store> store,
|
ref<Store> store,
|
||||||
Realise mode,
|
Realise mode,
|
||||||
const std::vector<std::shared_ptr<Installable>> & installables,
|
const std::vector<std::shared_ptr<Installable>> & installables,
|
||||||
BuildMode bMode = bmNormal);
|
BuildMode bMode = bmNormal);
|
||||||
|
|
||||||
static std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> build2(
|
static std::vector<std::pair<std::shared_ptr<Installable>, BuiltPathWithResult>> build2(
|
||||||
ref<Store> evalStore,
|
ref<Store> evalStore,
|
||||||
ref<Store> store,
|
ref<Store> store,
|
||||||
Realise mode,
|
Realise mode,
|
||||||
|
|
|
@ -53,28 +53,13 @@ StorePathSet BuiltPath::outPaths() const
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
std::string DerivedPath::Opaque::to_string(const Store & store) const
|
||||||
nlohmann::json stuffToJSON(const std::vector<T> & ts, ref<Store> store) {
|
{
|
||||||
auto res = nlohmann::json::array();
|
|
||||||
for (const T & t : ts) {
|
|
||||||
std::visit([&res, store](const auto & t) {
|
|
||||||
res.push_back(t.toJSON(store));
|
|
||||||
}, t.raw());
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
nlohmann::json derivedPathsWithHintsToJSON(const BuiltPaths & buildables, ref<Store> store)
|
|
||||||
{ return stuffToJSON<BuiltPath>(buildables, store); }
|
|
||||||
nlohmann::json derivedPathsToJSON(const DerivedPaths & paths, ref<Store> store)
|
|
||||||
{ return stuffToJSON<DerivedPath>(paths, store); }
|
|
||||||
|
|
||||||
|
|
||||||
std::string DerivedPath::Opaque::to_string(const Store & store) const {
|
|
||||||
return store.printStorePath(path);
|
return store.printStorePath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string DerivedPath::Built::to_string(const Store & store) const {
|
std::string DerivedPath::Built::to_string(const Store & store) const
|
||||||
|
{
|
||||||
return store.printStorePath(drvPath)
|
return store.printStorePath(drvPath)
|
||||||
+ "!"
|
+ "!"
|
||||||
+ (outputs.empty() ? std::string { "*" } : concatStringsSep(",", outputs));
|
+ (outputs.empty() ? std::string { "*" } : concatStringsSep(",", outputs));
|
||||||
|
|
|
@ -125,7 +125,4 @@ struct BuiltPath : _BuiltPathRaw {
|
||||||
typedef std::vector<DerivedPath> DerivedPaths;
|
typedef std::vector<DerivedPath> DerivedPaths;
|
||||||
typedef std::vector<BuiltPath> BuiltPaths;
|
typedef std::vector<BuiltPath> BuiltPaths;
|
||||||
|
|
||||||
nlohmann::json derivedPathsWithHintsToJSON(const BuiltPaths & buildables, ref<Store> store);
|
|
||||||
nlohmann::json derivedPathsToJSON(const DerivedPaths & , ref<Store> store);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,11 +37,13 @@ struct InstallableDerivedPath : Installable
|
||||||
* Return the rewrites that are needed to resolve a string whose context is
|
* Return the rewrites that are needed to resolve a string whose context is
|
||||||
* included in `dependencies`.
|
* included in `dependencies`.
|
||||||
*/
|
*/
|
||||||
StringPairs resolveRewrites(Store & store, const BuiltPaths dependencies)
|
StringPairs resolveRewrites(
|
||||||
|
Store & store,
|
||||||
|
const std::vector<BuiltPathWithResult> & dependencies)
|
||||||
{
|
{
|
||||||
StringPairs res;
|
StringPairs res;
|
||||||
for (auto & dep : dependencies)
|
for (auto & dep : dependencies)
|
||||||
if (auto drvDep = std::get_if<BuiltPathBuilt>(&dep))
|
if (auto drvDep = std::get_if<BuiltPathBuilt>(&dep.path))
|
||||||
for (auto & [ outputName, outputPath ] : drvDep->outputs)
|
for (auto & [ outputName, outputPath ] : drvDep->outputs)
|
||||||
res.emplace(
|
res.emplace(
|
||||||
downstreamPlaceholder(store, drvDep->drvPath, outputName),
|
downstreamPlaceholder(store, drvDep->drvPath, outputName),
|
||||||
|
@ -53,7 +55,10 @@ StringPairs resolveRewrites(Store & store, const BuiltPaths dependencies)
|
||||||
/**
|
/**
|
||||||
* Resolve the given string assuming the given context.
|
* Resolve the given string assuming the given context.
|
||||||
*/
|
*/
|
||||||
std::string resolveString(Store & store, const std::string & toResolve, const BuiltPaths dependencies)
|
std::string resolveString(
|
||||||
|
Store & store,
|
||||||
|
const std::string & toResolve,
|
||||||
|
const std::vector<BuiltPathWithResult> & dependencies)
|
||||||
{
|
{
|
||||||
auto rewrites = resolveRewrites(store, dependencies);
|
auto rewrites = resolveRewrites(store, dependencies);
|
||||||
return rewriteStrings(toResolve, rewrites);
|
return rewriteStrings(toResolve, rewrites);
|
||||||
|
|
|
@ -10,6 +10,33 @@
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
|
nlohmann::json derivedPathsToJSON(const DerivedPaths & paths, ref<Store> store)
|
||||||
|
{
|
||||||
|
auto res = nlohmann::json::array();
|
||||||
|
for (auto & t : paths) {
|
||||||
|
std::visit([&res, store](const auto & t) {
|
||||||
|
res.push_back(t.toJSON(store));
|
||||||
|
}, t.raw());
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json builtPathsWithResultToJSON(const std::vector<BuiltPathWithResult> & buildables, ref<Store> store)
|
||||||
|
{
|
||||||
|
auto res = nlohmann::json::array();
|
||||||
|
for (auto & b : buildables) {
|
||||||
|
std::visit([&](const auto & t) {
|
||||||
|
auto j = t.toJSON(store);
|
||||||
|
if (b.result) {
|
||||||
|
j["startTime"] = b.result->startTime;
|
||||||
|
j["stopTime"] = b.result->stopTime;
|
||||||
|
}
|
||||||
|
res.push_back(j);
|
||||||
|
}, b.path.raw());
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile
|
struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile
|
||||||
{
|
{
|
||||||
Path outLink = "result";
|
Path outLink = "result";
|
||||||
|
@ -78,7 +105,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile
|
||||||
Realise::Outputs,
|
Realise::Outputs,
|
||||||
installables, buildMode);
|
installables, buildMode);
|
||||||
|
|
||||||
if (json) logger->cout("%s", derivedPathsWithHintsToJSON(buildables, store).dump());
|
if (json) logger->cout("%s", builtPathsWithResultToJSON(buildables, store).dump());
|
||||||
|
|
||||||
if (outLink != "")
|
if (outLink != "")
|
||||||
if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>())
|
if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>())
|
||||||
|
@ -98,7 +125,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile
|
||||||
store2->addPermRoot(output.second, absPath(symlink));
|
store2->addPermRoot(output.second, absPath(symlink));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}, buildable.raw());
|
}, buildable.path.raw());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (printOutputPaths) {
|
if (printOutputPaths) {
|
||||||
|
@ -113,11 +140,14 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile
|
||||||
std::cout << store->printStorePath(output.second) << std::endl;
|
std::cout << store->printStorePath(output.second) << std::endl;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}, buildable.raw());
|
}, buildable.path.raw());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateProfile(buildables);
|
BuiltPaths buildables2;
|
||||||
|
for (auto & b : buildables)
|
||||||
|
buildables2.push_back(b.path);
|
||||||
|
updateProfile(buildables2);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -253,11 +253,11 @@ struct ProfileManifest
|
||||||
|
|
||||||
static std::map<Installable *, BuiltPaths>
|
static std::map<Installable *, BuiltPaths>
|
||||||
builtPathsPerInstallable(
|
builtPathsPerInstallable(
|
||||||
const std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> & builtPaths)
|
const std::vector<std::pair<std::shared_ptr<Installable>, BuiltPathWithResult>> & builtPaths)
|
||||||
{
|
{
|
||||||
std::map<Installable *, BuiltPaths> res;
|
std::map<Installable *, BuiltPaths> res;
|
||||||
for (auto & [installable, builtPath] : builtPaths)
|
for (auto & [installable, builtPath] : builtPaths)
|
||||||
res[installable.get()].push_back(builtPath);
|
res[installable.get()].push_back(builtPath.path);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue