Skip to content

Commit

Permalink
Add the pre-build hook.
Browse files Browse the repository at this point in the history
This hook can be used to set system-specific per-derivation build
settings that don't fit into the derivation model and are too complex or
volatile to be hard-coded into nix. Currently, the pre-build hook can
only add chroot dirs/files through the interface, but it also has full
access to the chroot root.

The specific use case for this is systems where the operating system ABI
is more complex than just the kernel-support system calls. For example,
on OS X there is a set of system-provided frameworks that can reliably
be accessed by any program linked to them, no matter the version the
program is running on. Unfortunately, those frameworks do not
necessarily live in the same locations on each version of OS X, nor do
their dependencies, and thus nix needs to know the specific version of
OS X currently running in order to make those frameworks available. The
pre-build hook is a perfect mechanism for doing just that.
  • Loading branch information
shlevy committed Apr 18, 2015
1 parent fd6774e commit 4d65287
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 0 deletions.
34 changes: 34 additions & 0 deletions doc/manual/command-ref/conf-file.xml
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,40 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para>
</varlistentry>


<varlistentry xml:id="conf-pre-build-hook"><term><literal>pre-build-hook</literal></term>

<listitem>


<para>If set, the path to a program that can set extra
derivation-specific settings for this system. This is used for settings
that can't be captured by the derivation model itself and are too variable
between different versions of the same system to be hard-coded into nix.
</para>

<para>The hook is passed the derivation path and, if chroots are enabled,
the chroot directory. It can then modify the chroot and send a series of
commands to modify various settings to stdout. The currently recognized
commands are:</para>

<variablelist>
<varlistentry xml:id="extra-chroot-dirs"><term><literal>extra-chroot-dirs</literal></term>

<listitem>

<para>Pass a list of files and directories to be included in the
chroot for this build. One entry per line, terminated by an empty
line. Entries have the same format as build-chroot-dirs.</para>

</listitem>

</varlistentry>
</variablelist>
</listitem>

</varlistentry>


</variablelist>

</para>
Expand Down
36 changes: 36 additions & 0 deletions src/libstore/build.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1969,6 +1969,42 @@ void DerivationGoal::startBuilder()
}
}

if (settings.preBuildHook != "") {
printMsg(lvlChatty, format("executing pre-build hook ‘%1%’")
% settings.preBuildHook);
auto args = useChroot ? Strings({drvPath, chrootRootDir}) :
Strings({ drvPath });
enum BuildHookState {
stBegin,
stExtraChrootDirs
};
auto state = stBegin;
auto lines = runProgram(settings.preBuildHook, false, args);
auto lastPos = std::string::size_type{0};
for (auto nlPos = lines.find('\n'); nlPos != string::npos;
nlPos = lines.find('\n', lastPos)) {
auto line = std::string{lines, lastPos, nlPos};
lastPos = nlPos + 1;
if (state == stBegin) {
if (line == "extra-chroot-dirs") {
state = stExtraChrootDirs;
} else {
throw Error(format("unknown pre-build hook command ‘%1%’")
% line);
}
} else if (state == stExtraChrootDirs) {
if (line == "") {
state = stBegin;
} else {
auto p = line.find('=');
if (p == string::npos)
dirsInChroot[line] = line;
else
dirsInChroot[string(line, 0, p)] = string(line, p + 1);
}
}
}
}

/* Run the builder. */
printMsg(lvlChatty, format("executing builder ‘%1%’") % drv.builder);
Expand Down
1 change: 1 addition & 0 deletions src/libstore/globals.cc
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ void Settings::update()
_get(logServers, "log-servers");
_get(enableImportNative, "allow-unsafe-native-code-during-evaluation");
_get(useCaseHack, "use-case-hack");
_get(preBuildHook, "pre-build-hook");

string subs = getEnv("NIX_SUBSTITUTERS", "default");
if (subs == "default") {
Expand Down
4 changes: 4 additions & 0 deletions src/libstore/globals.hh
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ struct Settings {
/* Whether the importNative primop should be enabled */
bool enableImportNative;

/* The hook to run just before a build to set derivation-specific
build settings */
Path preBuildHook;

private:
SettingsMap settings, overrides;

Expand Down

1 comment on commit 4d65287

@edolstra
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🍺

Please sign in to comment.