2020-10-11 19:17:24 +03:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "parsed-derivations.hh"
|
|
|
|
#include "lock.hh"
|
2021-02-26 17:20:33 +02:00
|
|
|
#include "store-api.hh"
|
|
|
|
#include "pathlocks.hh"
|
2020-10-12 20:15:32 +03:00
|
|
|
#include "goal.hh"
|
2009-01-12 18:30:32 +02:00
|
|
|
|
2006-09-05 00:06:23 +03:00
|
|
|
namespace nix {
|
|
|
|
|
|
|
|
using std::map;
|
2012-07-27 16:59:18 +03:00
|
|
|
|
2014-01-21 19:29:55 +02:00
|
|
|
struct HookInstance;
|
2004-06-18 21:09:32 +03:00
|
|
|
|
2010-08-25 23:44:28 +03:00
|
|
|
typedef enum {rpAccept, rpDecline, rpPostpone} HookReply;
|
|
|
|
|
2020-09-15 18:19:45 +03:00
|
|
|
/* Unless we are repairing, we don't both to test validity and just assume it,
|
|
|
|
so the choices are `Absent` or `Valid`. */
|
|
|
|
enum struct PathStatus {
|
|
|
|
Corrupt,
|
|
|
|
Absent,
|
|
|
|
Valid,
|
|
|
|
};
|
|
|
|
|
2020-09-04 18:15:51 +03:00
|
|
|
struct InitialOutputStatus {
|
2020-08-07 22:09:26 +03:00
|
|
|
StorePath path;
|
2020-09-15 18:19:45 +03:00
|
|
|
PathStatus status;
|
2020-08-07 22:09:26 +03:00
|
|
|
/* Valid in the store, and additionally non-corrupt if we are repairing */
|
|
|
|
bool isValid() const {
|
2020-09-15 18:19:45 +03:00
|
|
|
return status == PathStatus::Valid;
|
|
|
|
}
|
|
|
|
/* Merely present, allowed to be corrupt */
|
|
|
|
bool isPresent() const {
|
|
|
|
return status == PathStatus::Corrupt
|
|
|
|
|| status == PathStatus::Valid;
|
2020-08-07 22:09:26 +03:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-09-04 18:15:51 +03:00
|
|
|
struct InitialOutput {
|
2020-08-07 22:09:26 +03:00
|
|
|
bool wanted;
|
2021-02-04 15:41:49 +02:00
|
|
|
Hash outputHash;
|
2020-09-04 18:15:51 +03:00
|
|
|
std::optional<InitialOutputStatus> known;
|
2020-08-07 22:09:26 +03:00
|
|
|
};
|
|
|
|
|
2020-11-18 15:36:15 +02:00
|
|
|
struct DerivationGoal : public Goal
|
2004-05-11 21:05:44 +03:00
|
|
|
{
|
Allow remote builds without sending the derivation closure
Previously, to build a derivation remotely, we had to copy the entire
closure of the .drv file to the remote machine, even though we only
need the top-level derivation. This is very wasteful: the closure can
contain thousands of store paths, and in some Hydra use cases, include
source paths that are very large (e.g. Git/Mercurial checkouts).
So now there is a new operation, StoreAPI::buildDerivation(), that
performs a build from an in-memory representation of a derivation
(BasicDerivation) rather than from a on-disk .drv file. The only files
that need to be in the Nix store are the sources of the derivation
(drv.inputSrcs), and the needed output paths of the dependencies (as
described by drv.inputDrvs). "nix-store --serve" exposes this
interface.
Note that this is a privileged operation, because you can construct a
derivation that builds any store path whatsoever. Fixing this will
require changing the hashing scheme (i.e., the output paths should be
computed from the other fields in BasicDerivation, allowing them to be
verified without access to other derivations). However, this would be
quite nice because it would allow .drv-free building (e.g. "nix-env
-i" wouldn't have to write any .drv files to disk).
Fixes #173.
2015-07-17 18:57:40 +03:00
|
|
|
/* Whether to use an on-disk .drv file. */
|
|
|
|
bool useDerivation;
|
|
|
|
|
2005-01-20 18:01:07 +02:00
|
|
|
/* The path of the derivation. */
|
2019-12-05 20:11:09 +02:00
|
|
|
StorePath drvPath;
|
2004-05-11 21:05:44 +03:00
|
|
|
|
2021-01-27 11:03:05 +02:00
|
|
|
/* The path of the corresponding resolved derivation */
|
|
|
|
std::optional<BasicDerivation> resolvedDrv;
|
|
|
|
|
2012-11-26 18:15:09 +02:00
|
|
|
/* The specific outputs that we need to build. Empty means all of
|
|
|
|
them. */
|
|
|
|
StringSet wantedOutputs;
|
|
|
|
|
|
|
|
/* Whether additional wanted outputs have been added. */
|
Allow remote builds without sending the derivation closure
Previously, to build a derivation remotely, we had to copy the entire
closure of the .drv file to the remote machine, even though we only
need the top-level derivation. This is very wasteful: the closure can
contain thousands of store paths, and in some Hydra use cases, include
source paths that are very large (e.g. Git/Mercurial checkouts).
So now there is a new operation, StoreAPI::buildDerivation(), that
performs a build from an in-memory representation of a derivation
(BasicDerivation) rather than from a on-disk .drv file. The only files
that need to be in the Nix store are the sources of the derivation
(drv.inputSrcs), and the needed output paths of the dependencies (as
described by drv.inputDrvs). "nix-store --serve" exposes this
interface.
Note that this is a privileged operation, because you can construct a
derivation that builds any store path whatsoever. Fixing this will
require changing the hashing scheme (i.e., the output paths should be
computed from the other fields in BasicDerivation, allowing them to be
verified without access to other derivations). However, this would be
quite nice because it would allow .drv-free building (e.g. "nix-env
-i" wouldn't have to write any .drv files to disk).
Fixes #173.
2015-07-17 18:57:40 +03:00
|
|
|
bool needRestart = false;
|
2012-11-26 18:15:09 +02:00
|
|
|
|
2013-01-02 13:38:28 +02:00
|
|
|
/* Whether to retry substituting the outputs after building the
|
|
|
|
inputs. */
|
2018-06-05 17:04:41 +03:00
|
|
|
bool retrySubstitution;
|
2013-01-02 13:38:28 +02:00
|
|
|
|
2005-01-20 18:01:07 +02:00
|
|
|
/* The derivation stored at drvPath. */
|
2021-02-23 15:12:11 +02:00
|
|
|
std::unique_ptr<Derivation> drv;
|
2012-07-27 16:59:18 +03:00
|
|
|
|
2018-09-28 15:31:16 +03:00
|
|
|
std::unique_ptr<ParsedDerivation> parsedDrv;
|
2018-09-28 13:43:01 +03:00
|
|
|
|
2004-05-11 21:05:44 +03:00
|
|
|
/* The remainder is state held during the build. */
|
|
|
|
|
2020-08-07 22:09:26 +03:00
|
|
|
/* Locks on (fixed) output paths. */
|
2004-05-11 21:05:44 +03:00
|
|
|
PathLocks outputLocks;
|
|
|
|
|
2005-01-19 13:16:11 +02:00
|
|
|
/* All input paths (that is, the union of FS closures of the
|
|
|
|
immediate input paths). */
|
2019-12-05 20:11:09 +02:00
|
|
|
StorePathSet inputPaths;
|
2004-05-11 21:05:44 +03:00
|
|
|
|
2020-09-04 18:15:51 +03:00
|
|
|
std::map<std::string, InitialOutput> initialOutputs;
|
2013-06-13 17:43:20 +03:00
|
|
|
|
2004-05-11 21:05:44 +03:00
|
|
|
/* File descriptor for the log file. */
|
2012-07-17 16:40:12 +03:00
|
|
|
AutoCloseFD fdLogFile;
|
2016-05-04 16:46:25 +03:00
|
|
|
std::shared_ptr<BufferedSink> logFileSink, logSink;
|
2004-05-11 21:05:44 +03:00
|
|
|
|
2013-09-02 12:58:18 +03:00
|
|
|
/* Number of bytes received from the builder's stdout/stderr. */
|
|
|
|
unsigned long logSize;
|
|
|
|
|
2016-04-25 17:47:46 +03:00
|
|
|
/* The most recent log lines. */
|
|
|
|
std::list<std::string> logTail;
|
|
|
|
|
|
|
|
std::string currentLogLine;
|
2016-04-28 15:27:00 +03:00
|
|
|
size_t currentLogLinePos = 0; // to handle carriage return
|
2016-04-25 17:47:46 +03:00
|
|
|
|
2017-10-24 14:41:52 +03:00
|
|
|
std::string currentHookLine;
|
|
|
|
|
2010-08-25 23:44:28 +03:00
|
|
|
/* The build hook. */
|
2017-01-19 16:15:09 +02:00
|
|
|
std::unique_ptr<HookInstance> hook;
|
2012-07-27 16:59:18 +03:00
|
|
|
|
2020-03-15 08:23:17 +02:00
|
|
|
/* The sort of derivation we are building. */
|
|
|
|
DerivationType derivationType;
|
2012-07-27 16:59:18 +03:00
|
|
|
|
2005-01-19 13:16:11 +02:00
|
|
|
typedef void (DerivationGoal::*GoalState)();
|
2004-06-18 21:09:32 +03:00
|
|
|
GoalState state;
|
2012-07-27 16:59:18 +03:00
|
|
|
|
2020-08-07 22:09:26 +03:00
|
|
|
/* The final output paths of the build.
|
|
|
|
|
|
|
|
- For input-addressed derivations, always the precomputed paths
|
|
|
|
|
|
|
|
- For content-addressed derivations, calcuated from whatever the hash
|
|
|
|
ends up being. (Note that fixed outputs derivations that produce the
|
|
|
|
"wrong" output still install that data under its true content-address.)
|
|
|
|
*/
|
2020-08-11 23:49:10 +03:00
|
|
|
OutputPathMap finalOutputs;
|
2020-08-07 22:09:26 +03:00
|
|
|
|
2014-02-18 00:04:52 +02:00
|
|
|
BuildMode buildMode;
|
|
|
|
|
2015-07-20 04:15:45 +03:00
|
|
|
BuildResult result;
|
|
|
|
|
2015-11-10 00:16:24 +02:00
|
|
|
/* The current round, if we're building multiple times. */
|
2018-05-02 14:56:34 +03:00
|
|
|
size_t curRound = 1;
|
2015-11-10 00:16:24 +02:00
|
|
|
|
2018-05-02 14:56:34 +03:00
|
|
|
size_t nrRounds;
|
2015-11-10 00:16:24 +02:00
|
|
|
|
2017-08-15 16:31:59 +03:00
|
|
|
std::unique_ptr<MaintainCount<uint64_t>> mcExpectedBuilds, mcRunningBuilds;
|
|
|
|
|
|
|
|
std::unique_ptr<Activity> act;
|
|
|
|
|
2020-06-15 17:03:29 +03:00
|
|
|
/* Activity that denotes waiting for a lock. */
|
|
|
|
std::unique_ptr<Activity> actLock;
|
|
|
|
|
2017-08-21 13:01:21 +03:00
|
|
|
std::map<ActivityId, Activity> builderActivities;
|
|
|
|
|
2017-10-24 15:24:57 +03:00
|
|
|
/* The remote machine on which we're building. */
|
|
|
|
std::string machineName;
|
|
|
|
|
2020-08-22 23:44:47 +03:00
|
|
|
DerivationGoal(const StorePath & drvPath,
|
|
|
|
const StringSet & wantedOutputs, Worker & worker,
|
|
|
|
BuildMode buildMode = bmNormal);
|
2020-06-16 23:20:18 +03:00
|
|
|
DerivationGoal(const StorePath & drvPath, const BasicDerivation & drv,
|
2020-08-22 23:44:47 +03:00
|
|
|
const StringSet & wantedOutputs, Worker & worker,
|
|
|
|
BuildMode buildMode = bmNormal);
|
2021-02-26 17:20:33 +02:00
|
|
|
virtual ~DerivationGoal();
|
2019-05-12 23:47:41 +03:00
|
|
|
|
2020-06-15 20:25:35 +03:00
|
|
|
void timedOut(Error && ex) override;
|
2012-07-27 16:59:18 +03:00
|
|
|
|
2020-10-12 20:15:32 +03:00
|
|
|
string key() override;
|
2014-11-24 17:48:04 +02:00
|
|
|
|
2015-09-18 02:22:06 +03:00
|
|
|
void work() override;
|
2004-06-20 00:45:04 +03:00
|
|
|
|
2012-11-26 18:15:09 +02:00
|
|
|
/* Add wanted outputs to an already existing derivation goal. */
|
|
|
|
void addWantedOutputs(const StringSet & outputs);
|
|
|
|
|
2015-07-20 04:15:45 +03:00
|
|
|
BuildResult getResult() { return result; }
|
|
|
|
|
2004-06-18 21:09:32 +03:00
|
|
|
/* The states. */
|
Allow remote builds without sending the derivation closure
Previously, to build a derivation remotely, we had to copy the entire
closure of the .drv file to the remote machine, even though we only
need the top-level derivation. This is very wasteful: the closure can
contain thousands of store paths, and in some Hydra use cases, include
source paths that are very large (e.g. Git/Mercurial checkouts).
So now there is a new operation, StoreAPI::buildDerivation(), that
performs a build from an in-memory representation of a derivation
(BasicDerivation) rather than from a on-disk .drv file. The only files
that need to be in the Nix store are the sources of the derivation
(drv.inputSrcs), and the needed output paths of the dependencies (as
described by drv.inputDrvs). "nix-store --serve" exposes this
interface.
Note that this is a privileged operation, because you can construct a
derivation that builds any store path whatsoever. Fixing this will
require changing the hashing scheme (i.e., the output paths should be
computed from the other fields in BasicDerivation, allowing them to be
verified without access to other derivations). However, this would be
quite nice because it would allow .drv-free building (e.g. "nix-env
-i" wouldn't have to write any .drv files to disk).
Fixes #173.
2015-07-17 18:57:40 +03:00
|
|
|
void getDerivation();
|
|
|
|
void loadDerivation();
|
2006-12-08 01:58:36 +02:00
|
|
|
void haveDerivation();
|
2020-08-07 22:09:26 +03:00
|
|
|
void outputsSubstitutionTried();
|
|
|
|
void gaveUpOnSubstitution();
|
2012-10-03 17:38:09 +03:00
|
|
|
void closureRepaired();
|
2005-01-19 13:16:11 +02:00
|
|
|
void inputsRealised();
|
2004-06-18 21:09:32 +03:00
|
|
|
void tryToBuild();
|
2021-02-26 17:20:33 +02:00
|
|
|
virtual void tryLocalBuild();
|
2004-06-18 21:09:32 +03:00
|
|
|
void buildDone();
|
|
|
|
|
2020-08-22 23:44:47 +03:00
|
|
|
void resolvedFinished();
|
|
|
|
|
2004-06-20 00:45:04 +03:00
|
|
|
/* Is the build hook willing to perform the build? */
|
|
|
|
HookReply tryBuildHook();
|
|
|
|
|
2021-02-26 17:20:33 +02:00
|
|
|
virtual int getChildStatus();
|
2012-06-25 22:45:16 +03:00
|
|
|
|
2014-02-17 23:25:15 +02:00
|
|
|
/* Check that the derivation outputs all exist and register them
|
|
|
|
as valid. */
|
2021-02-26 17:20:33 +02:00
|
|
|
virtual void registerOutputs();
|
2018-10-22 22:49:56 +03:00
|
|
|
|
2004-06-18 21:09:32 +03:00
|
|
|
/* Open a log file and a pipe to it. */
|
2008-11-12 13:08:27 +02:00
|
|
|
Path openLogFile();
|
2004-06-18 21:09:32 +03:00
|
|
|
|
2012-05-30 17:12:29 +03:00
|
|
|
/* Close the log file. */
|
|
|
|
void closeLogFile();
|
|
|
|
|
2021-02-26 17:20:33 +02:00
|
|
|
/* Close the read side of the logger pipe. */
|
|
|
|
virtual void closeReadPipes();
|
|
|
|
|
|
|
|
/* Cleanup hooks for buildDone() */
|
|
|
|
virtual void cleanupHookFinally();
|
|
|
|
virtual void cleanupPreChildKill();
|
|
|
|
virtual void cleanupPostChildKill();
|
|
|
|
virtual bool cleanupDecideWhetherDiskFull();
|
|
|
|
virtual void cleanupPostOutputsRegisteredModeCheck();
|
|
|
|
virtual void cleanupPostOutputsRegisteredModeNonCheck();
|
|
|
|
|
|
|
|
virtual bool isReadDesc(int fd);
|
2004-06-18 21:09:32 +03:00
|
|
|
|
2004-06-29 12:41:50 +03:00
|
|
|
/* Callback used by the worker to write to the log. */
|
2015-09-18 02:22:06 +03:00
|
|
|
void handleChildOutput(int fd, const string & data) override;
|
|
|
|
void handleEOF(int fd) override;
|
2016-04-25 17:47:46 +03:00
|
|
|
void flushLine();
|
2004-06-29 12:41:50 +03:00
|
|
|
|
2020-08-07 22:09:26 +03:00
|
|
|
/* Wrappers around the corresponding Store methods that first consult the
|
|
|
|
derivation. This is currently needed because when there is no drv file
|
|
|
|
there also is no DB entry. */
|
2020-08-20 21:14:12 +03:00
|
|
|
std::map<std::string, std::optional<StorePath>> queryPartialDerivationOutputMap();
|
|
|
|
OutputPathMap queryDerivationOutputMap();
|
2020-08-07 22:09:26 +03:00
|
|
|
|
2005-01-25 12:55:33 +02:00
|
|
|
/* Return the set of (in)valid paths. */
|
2020-08-07 22:09:26 +03:00
|
|
|
void checkPathValidity();
|
2009-03-25 23:05:42 +02:00
|
|
|
|
2006-12-08 20:41:48 +02:00
|
|
|
/* Forcibly kill the child process, if any. */
|
2021-02-26 17:20:33 +02:00
|
|
|
virtual void killChild();
|
2012-10-03 17:38:09 +03:00
|
|
|
|
|
|
|
void repairClosure();
|
2015-07-20 04:15:45 +03:00
|
|
|
|
2020-05-14 17:00:54 +03:00
|
|
|
void started();
|
|
|
|
|
2020-06-15 20:25:35 +03:00
|
|
|
void done(
|
|
|
|
BuildResult::Status status,
|
|
|
|
std::optional<Error> ex = {});
|
2018-04-17 13:03:27 +03:00
|
|
|
|
2019-12-05 20:11:09 +02:00
|
|
|
StorePathSet exportReferences(const StorePathSet & storePaths);
|
2004-05-11 21:05:44 +03:00
|
|
|
};
|
|
|
|
|
2021-02-26 17:20:33 +02:00
|
|
|
MakeError(NotDeterministic, BuildError);
|
|
|
|
|
2006-09-05 00:06:23 +03:00
|
|
|
}
|