Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/libcmd/installables.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "nix/expr/eval.hh"
#include "nix/expr/eval-settings.hh"
#include "nix/store/store-api.hh"
#include "nix/store/build.hh"
#include "nix/main/shared.hh"
#include "nix/flake/flake.hh"
#include "nix/expr/eval-cache.hh"
Expand Down Expand Up @@ -593,7 +594,7 @@ std::vector<InstallableWithBuildResult> Installable::build2(
if (settings.printMissing)
printMissing(store, pathsToBuild, lvlInfo);

auto buildResults = store->buildPathsWithResults(pathsToBuild, bMode, evalStore);
auto buildResults = store->getBuilder(evalStore)->buildPathsWithResults(pathsToBuild, bMode);
for (auto & buildResult : buildResults) {
if (buildResult.tryGetFailure()) {
for (auto & aux : backmap[buildResult.path]) {
Expand Down
3 changes: 2 additions & 1 deletion src/libcmd/repl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "nix/util/finally.hh"
#include "nix/cmd/markdown.hh"
#include "nix/store/local-fs-store.hh"
#include "nix/store/build.hh"
#include "nix/expr/print.hh"
#include "nix/util/ref.hh"
#include "nix/expr/value.hh"
Expand Down Expand Up @@ -549,7 +550,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
std::string drvPathRaw = state->store->printStorePath(drvPath);

if (command == ":b" || command == ":bl") {
state->store->buildPaths({
state->store->getBuilder()->buildPaths({
DerivedPath::Built{
.drvPath = makeConstantStorePathRef(drvPath),
.outputs = OutputsSpec::All{},
Expand Down
5 changes: 3 additions & 2 deletions src/libexpr/primops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "nix/store/names.hh"
#include "nix/store/path-references.hh"
#include "nix/store/store-api.hh"
#include "nix/store/build.hh"
#include "nix/util/util.hh"
#include "nix/util/os-string.hh"
#include "nix/util/processes.hh"
Expand Down Expand Up @@ -131,7 +132,7 @@ StringMap EvalState::realiseContext(const NixStringContext & context, StorePathS
buildReqs.reserve(drvs.size());
for (auto & d : drvs)
buildReqs.emplace_back(DerivedPath{d});
buildStore->buildPaths(buildReqs, bmNormal, store);
buildStore->getBuilder(store)->buildPaths(buildReqs, bmNormal);

StorePathSet outputsToCopyAndAllow;

Expand Down Expand Up @@ -2035,7 +2036,7 @@ static void prim_storePath(EvalState & state, const PosIdx pos, Value ** args, V
state.error<EvalError>("path '%1%' is not in the Nix store", sourcePath).atPos(pos).debugThrow();
auto storePath = state.store->toStorePath(sourcePath.path.abs()).first;
if (!state.storeFS->getMount(CanonPath(state.store->printStorePath(storePath))) && !settings.readOnlyMode)
state.store->ensurePath(storePath);
state.store->getBuilder()->ensurePath(storePath);
context.insert(NixStringContextElem::Opaque{.path = storePath});
v.mkString(sourcePath.path.abs(), context, state.mem);
}
Expand Down
3 changes: 2 additions & 1 deletion src/libexpr/primops/context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "nix/expr/eval-inline.hh"
#include "nix/store/derivations.hh"
#include "nix/store/store-api.hh"
#include "nix/store/build.hh"
#include "nix/store/globals.hh"

namespace nix {
Expand Down Expand Up @@ -293,7 +294,7 @@ static void prim_appendContext(EvalState & state, const PosIdx pos, Value ** arg
state.error<EvalError>("context key '%s' is not a store path", name).atPos(i.pos).debugThrow();
auto namePath = state.store->parseStorePath(name);
if (!settings.readOnlyMode)
state.store->ensurePath(namePath);
state.store->getBuilder()->ensurePath(namePath);
state.forceAttrs(*i.value, i.pos, "while evaluating the value of a string context");

if (auto attr = i.value->attrs()->get(sPath)) {
Expand Down
3 changes: 2 additions & 1 deletion src/libexpr/primops/fetchTree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "nix/expr/eval-settings.hh"
#include "nix/expr/fetch-tree.hh"
#include "nix/store/store-api.hh"
#include "nix/store/build.hh"
#include "nix/fetchers/fetchers.hh"
#include "nix/store/filetransfer.hh"
#include "nix/fetchers/registry.hh"
Expand Down Expand Up @@ -536,7 +537,7 @@ static void fetch(

// Try to get the path from the local store or substituters
try {
state.store->ensurePath(expectedPath);
state.store->getBuilder()->ensurePath(expectedPath);
debug("using substituted/cached path '%s' for '%s'", state.store->printStorePath(expectedPath), *url);
state.allowAndSetStorePathString(expectedPath, v);
return;
Expand Down
3 changes: 2 additions & 1 deletion src/libfetchers/fetchers.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "nix/fetchers/fetchers.hh"
#include "nix/store/store-api.hh"
#include "nix/util/fs-sink.hh"
#include "nix/store/build.hh"
#include "nix/util/source-path.hh"
#include "nix/fetchers/fetch-to-store.hh"
#include "nix/util/json-utils.hh"
Expand Down Expand Up @@ -382,7 +383,7 @@ std::pair<ref<SourceAccessor>, Input> Input::getAccessorUnchecked(const Settings
/* If not, try to substitute the input. */
if (storePath) {
try {
store.ensurePath(*storePath);
store.getBuilder()->ensurePath(*storePath);
return makeStoreAccessor();
}
// Ignore any substitution error.
Expand Down
5 changes: 3 additions & 2 deletions src/libstore-c/nix_api_store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "nix/store/path.hh"
#include "nix/store/store-api.hh"
#include "nix/store/build.hh"
#include "nix/store/store-open.hh"
#include "nix/store/store-reference.hh"
#include "nix/store/build-result.hh"
Expand Down Expand Up @@ -178,7 +179,7 @@ nix_err nix_store_realise(
.drvPath = nix::makeConstantStorePathRef(path->path), .outputs = nix::OutputsSpec::All{}}};

const auto nixStore = store->ptr;
auto results = nixStore->buildPathsWithResults(paths, nix::bmNormal, nixStore);
auto results = nixStore->getBuilder(nixStore)->buildPathsWithResults(paths, nix::bmNormal);

assert(results.size() == 1);

Expand Down Expand Up @@ -420,7 +421,7 @@ nix_err nix_store_build_paths(
derived_paths.push_back(nix::SingleDerivedPath::Opaque{store_path->path});
}

auto results = store->ptr->buildPathsWithResults(derived_paths);
auto results = store->ptr->getBuilder()->buildPathsWithResults(derived_paths);
for (auto & result : results) {
if (callback)
callback(
Expand Down
18 changes: 18 additions & 0 deletions src/libstore/build/derivation-building-goal.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "nix/store/build/derivation-building-goal.hh"
#include "nix/store/build/derivation-env-desugar.hh"
#include "nix/store/restricted-store.hh"
#include "nix/store/daemon.hh"
#ifndef _WIN32 // TODO enable build hook on Windows
# include "nix/store/build/hook-instance.hh"
# include "nix/store/build/derivation-builder.hh"
Expand Down Expand Up @@ -946,6 +948,22 @@ Goal::Co DerivationBuildingGoal::buildLocally(
{
closeLogFileFn();
}

void processDaemonConnection(
ref<Store> store, FdSource && from, FdSink && to, RestrictionContext & context) override
{
/**
* TODO: We create a fresh Worker here because the
* parent Worker is blocked waiting for the current
* build to finish, so we can't reuse it from a
* daemon thread. Ideally we should reuse the same
* Worker to share scheduling state.
*/
Worker freshWorker{goal.worker.store, goal.worker.evalStore};
auto builder = makeRestrictedBuilder(freshWorker, context);
daemon::processConnection(
store, std::move(from), std::move(to), NotTrusted, daemon::Recursive, builder.get_ptr());
}
};

decltype(DerivationBuilderParams::defaultPathsInChroot) defaultPathsInChroot =
Expand Down
91 changes: 57 additions & 34 deletions src/libstore/build/entry-points.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,47 @@
#include "nix/store/build/substitution-goal.hh"
#include "nix/store/build/derivation-trampoline-goal.hh"
#include "nix/util/strings.hh"
#include <memory>

namespace nix {

void Store::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMode, std::shared_ptr<Store> evalStore)
void LocalBuilder::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMode)
{
Worker worker(*this, evalStore ? *evalStore : *this);
getWorker()->buildPaths(reqs, buildMode);
}

std::vector<KeyedBuildResult>
LocalBuilder::buildPathsWithResults(const std::vector<DerivedPath> & reqs, BuildMode buildMode)
{
return getWorker()->buildPathsWithResults(reqs, buildMode);
}

BuildResult LocalBuilder::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildMode buildMode)
{
return getWorker()->buildDerivation(drvPath, drv, buildMode);
}

void LocalBuilder::ensurePath(const StorePath & path)
{
/* If the path is already valid, we're done. */
if (store->isValidPath(path))
return;

getWorker()->ensurePath(path);
}

void LocalBuilder::repairPath(const StorePath & path)
{
getWorker()->repairPath(path);
}

void Worker::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMode)
{
Goals goals;
for (auto & br : reqs)
goals.insert(worker.makeGoal(br, buildMode));
goals.insert(makeGoal(br, buildMode));

worker.run(goals);
run(goals);

StringSet failed;
BuildResult::Failure * failure = nullptr;
Expand All @@ -27,38 +56,35 @@ void Store::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMod
}
if (i->exitCode != Goal::ecSuccess) {
if (auto i2 = dynamic_cast<DerivationTrampolineGoal *>(i.get()))
failed.insert(i2->drvReq->to_string(*this));
failed.insert(i2->drvReq->to_string(store));
else if (auto i2 = dynamic_cast<PathSubstitutionGoal *>(i.get()))
failed.insert(printStorePath(i2->storePath));
failed.insert(store.printStorePath(i2->storePath));
}
}

if (failed.size() == 1 && failure) {
failure->withExitStatus(worker.exitStatusFlags.failingExitStatus());
failure->withExitStatus(exitStatusFlags.failingExitStatus());
throw *failure;
} else if (!failed.empty()) {
auto exitStatus = worker.exitStatusFlags.failingExitStatus();
auto exitStatus = exitStatusFlags.failingExitStatus();
if (failure)
logError(failure->info());
throw Error(exitStatus, "build of %s failed", concatStringsSep(", ", quoteStrings(failed)));
}
}

std::vector<KeyedBuildResult> Store::buildPathsWithResults(
const std::vector<DerivedPath> & reqs, BuildMode buildMode, std::shared_ptr<Store> evalStore)
std::vector<KeyedBuildResult> Worker::buildPathsWithResults(const std::vector<DerivedPath> & reqs, BuildMode buildMode)
{
Worker worker(*this, evalStore ? *evalStore : *this);

Goals goals;
std::vector<std::pair<const DerivedPath &, GoalPtr>> state;

for (const auto & req : reqs) {
auto goal = worker.makeGoal(req, buildMode);
auto goal = makeGoal(req, buildMode);
goals.insert(goal);
state.push_back({req, goal});
}

worker.run(goals);
run(goals);

std::vector<KeyedBuildResult> results;
results.reserve(state.size());
Expand All @@ -74,13 +100,12 @@ std::vector<KeyedBuildResult> Store::buildPathsWithResults(
return results;
}

BuildResult Store::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildMode buildMode)
BuildResult Worker::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildMode buildMode)
{
Worker worker(*this, *this);
auto goal = worker.makeDerivationTrampolineGoal(drvPath, OutputsSpec::All{}, drv, buildMode);
auto goal = makeDerivationTrampolineGoal(drvPath, OutputsSpec::All{}, drv, buildMode);

try {
worker.run(Goals{goal});
run(Goals{goal});
return goal->buildResult;
} catch (Error & e) {
return BuildResult{
Expand All @@ -91,49 +116,47 @@ BuildResult Store::buildDerivation(const StorePath & drvPath, const BasicDerivat
};
}

void Store::ensurePath(const StorePath & path)
void Worker::ensurePath(const StorePath & path)
{
/* If the path is already valid, we're done. */
if (isValidPath(path))
if (store.isValidPath(path))
return;

Worker worker(*this, *this);
GoalPtr goal = worker.makePathSubstitutionGoal(path, true);
GoalPtr goal = makePathSubstitutionGoal(path, true);
Goals goals = {goal};

worker.run(goals);
run(goals);

if (goal->exitCode != Goal::ecSuccess) {
auto exitStatus = worker.exitStatusFlags.failingExitStatus();
auto exitStatus = exitStatusFlags.failingExitStatus();
goal->buildResult.tryThrowBuildError(exitStatus);
throw Error(exitStatus, "path '%s' does not exist and cannot be created", printStorePath(path));
throw Error(exitStatus, "path '%s' does not exist and cannot be created", store.printStorePath(path));
}
}

void Store::repairPath(const StorePath & path)
void Worker::repairPath(const StorePath & path)
{
Worker worker(*this, *this);
GoalPtr goal = worker.makePathSubstitutionGoal(path, true, Repair);
GoalPtr goal = makePathSubstitutionGoal(path, true, Repair);
Goals goals = {goal};

worker.run(goals);
run(goals);

if (goal->exitCode != Goal::ecSuccess) {
/* Since substituting the path didn't work, if we have a valid
deriver, then rebuild the deriver. */
auto info = queryPathInfo(path);
if (info->deriver && isValidPath(*info->deriver)) {
auto info = store.queryPathInfo(path);
if (info->deriver && store.isValidPath(*info->deriver)) {
goals.clear();
goals.insert(worker.makeGoal(
goals.insert(makeGoal(
DerivedPath::Built{
.drvPath = makeConstantStorePathRef(*info->deriver),
// FIXME: Should just build the specific output we need.
.outputs = OutputsSpec::All{},
},
bmRepair));
worker.run(goals);
run(goals);
} else
throw Error(worker.exitStatusFlags.failingExitStatus(), "cannot repair path '%s'", printStorePath(path));
throw Error(exitStatusFlags.failingExitStatus(), "cannot repair path '%s'", store.printStorePath(path));
}
}

Expand Down
Loading
Loading