mirror of
https://github.com/NixOS/nix
synced 2025-07-03 06:11:46 +02:00
This is because with the split packages of the Meson build, we simply have no idea what directory the binaries will be installed in when we build the library. In the process of doing so, consolidate and make more sophisticated the logic to cope with a few corner cases (e.g. `NIX_BIN_DIR` exists, but no binaries are inside it). Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
98 lines
2.6 KiB
C++
98 lines
2.6 KiB
C++
#include "globals.hh"
|
|
#include "config-global.hh"
|
|
#include "hook-instance.hh"
|
|
#include "file-system.hh"
|
|
#include "child.hh"
|
|
#include "strings.hh"
|
|
#include "executable-path.hh"
|
|
|
|
namespace nix {
|
|
|
|
HookInstance::HookInstance()
|
|
{
|
|
debug("starting build hook '%s'", concatStringsSep(" ", settings.buildHook.get()));
|
|
|
|
auto buildHookArgs = settings.buildHook.get();
|
|
|
|
if (buildHookArgs.empty())
|
|
throw Error("'build-hook' setting is empty");
|
|
|
|
std::filesystem::path buildHook = buildHookArgs.front();
|
|
buildHookArgs.pop_front();
|
|
|
|
try {
|
|
buildHook = ExecutablePath::load().findPath(buildHook);
|
|
} catch (ExecutableLookupError & e) {
|
|
e.addTrace(nullptr, "while resolving the 'build-hook' setting'");
|
|
throw;
|
|
}
|
|
|
|
Strings args;
|
|
args.push_back(buildHook.filename().string());
|
|
|
|
for (auto & arg : buildHookArgs)
|
|
args.push_back(arg);
|
|
|
|
args.push_back(std::to_string(verbosity));
|
|
|
|
/* Create a pipe to get the output of the child. */
|
|
fromHook.create();
|
|
|
|
/* Create the communication pipes. */
|
|
toHook.create();
|
|
|
|
/* Create a pipe to get the output of the builder. */
|
|
builderOut.create();
|
|
|
|
/* Fork the hook. */
|
|
pid = startProcess([&]() {
|
|
|
|
if (dup2(fromHook.writeSide.get(), STDERR_FILENO) == -1)
|
|
throw SysError("cannot pipe standard error into log file");
|
|
|
|
commonChildInit();
|
|
|
|
if (chdir("/") == -1) throw SysError("changing into /");
|
|
|
|
/* Dup the communication pipes. */
|
|
if (dup2(toHook.readSide.get(), STDIN_FILENO) == -1)
|
|
throw SysError("dupping to-hook read side");
|
|
|
|
/* Use fd 4 for the builder's stdout/stderr. */
|
|
if (dup2(builderOut.writeSide.get(), 4) == -1)
|
|
throw SysError("dupping builder's stdout/stderr");
|
|
|
|
/* Hack: pass the read side of that fd to allow build-remote
|
|
to read SSH error messages. */
|
|
if (dup2(builderOut.readSide.get(), 5) == -1)
|
|
throw SysError("dupping builder's stdout/stderr");
|
|
|
|
execv(buildHook.native().c_str(), stringsToCharPtrs(args).data());
|
|
|
|
throw SysError("executing '%s'", buildHook);
|
|
});
|
|
|
|
pid.setSeparatePG(true);
|
|
fromHook.writeSide = -1;
|
|
toHook.readSide = -1;
|
|
|
|
sink = FdSink(toHook.writeSide.get());
|
|
std::map<std::string, Config::SettingInfo> settings;
|
|
globalConfig.getSettings(settings);
|
|
for (auto & setting : settings)
|
|
sink << 1 << setting.first << setting.second.value;
|
|
sink << 0;
|
|
}
|
|
|
|
|
|
HookInstance::~HookInstance()
|
|
{
|
|
try {
|
|
toHook.writeSide = -1;
|
|
if (pid != -1) pid.kill();
|
|
} catch (...) {
|
|
ignoreException();
|
|
}
|
|
}
|
|
|
|
}
|