-
-
Notifications
You must be signed in to change notification settings - Fork 14.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
stdenv: log build hooks as they run #290081
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,6 +50,42 @@ getAllOutputNames() { | |
###################################################################### | ||
# Hook handling. | ||
|
||
# Log a hook, to be run before the hook is actually called. | ||
# This only logs explicit hooks; "implicit" hooks, those specified directly | ||
# in a derivation's arguments, are logged in `_callImplicitHook` instead. | ||
_logHook() { | ||
local hookKind="$1" | ||
local hookExpr="$2" | ||
shift 2 | ||
|
||
if declare -F "$hookExpr" > /dev/null 2>&1; then | ||
echo "calling '$hookKind' function hook '$hookExpr'" "$@" | ||
elif type -p "$hookExpr" > /dev/null; then | ||
echo "sourcing '$hookKind' script hook '$hookExpr'" | ||
elif [[ "$hookExpr" != "_callImplicitHook"* ]]; then | ||
# Here we have a string hook to eval. | ||
# Join lines onto one with literal \n characters unless NIX_DEBUG >= 2. | ||
local exprToOutput | ||
if (( "${NIX_DEBUG:-0}" >= 2 )); then | ||
exprToOutput="$hookExpr" | ||
else | ||
while IFS= read -r hookExprLine; do | ||
# These lines often have indentation, | ||
# so let's remove leading whitespace. | ||
hookExprLine="${hookExprLine#"${hookExprLine%%[![:space:]]*}"}" | ||
# If this line wasn't entirely whitespace, | ||
# then add it to our output. | ||
if [[ -n "$hookExprLine" ]]; then | ||
exprToOutput+="$hookExprLine\\n " | ||
fi | ||
done <<< "$hookExpr" | ||
|
||
# And then remove the final, unnecessary, \n | ||
exprToOutput="${exprToOutput%%\\n }" | ||
fi | ||
echo "evaling '$hookKind' string hook '$exprToOutput'" | ||
fi | ||
} | ||
|
||
# Run all hooks with the specified name in the order in which they | ||
# were added, stopping if any fails (returns a non-zero exit | ||
|
@@ -64,6 +100,7 @@ runHook() { | |
# Hack around old bash being bad and thinking empty arrays are | ||
# undefined. | ||
for hook in "_callImplicitHook 0 $hookName" ${!hooksSlice+"${!hooksSlice}"}; do | ||
_logHook "$hookName" "$hook" "$@" | ||
_eval "$hook" "$@" | ||
done | ||
|
||
|
@@ -81,6 +118,7 @@ runOneHook() { | |
local hook ret=1 | ||
# Hack around old bash like above | ||
for hook in "_callImplicitHook 1 $hookName" ${!hooksSlice+"${!hooksSlice}"}; do | ||
_logHook "$hookName" "$hook" "$@" | ||
if _eval "$hook" "$@"; then | ||
ret=0 | ||
break | ||
|
@@ -100,10 +138,13 @@ _callImplicitHook() { | |
local def="$1" | ||
local hookName="$2" | ||
if declare -F "$hookName" > /dev/null; then | ||
echo "calling implicit '$hookName' function hook" | ||
"$hookName" | ||
elif type -p "$hookName" > /dev/null; then | ||
echo "sourcing implicit '$hookName' script hook" | ||
source "$hookName" | ||
elif [ -n "${!hookName:-}" ]; then | ||
echo "evaling implicit '$hookName' string hook" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For instance, here you don't do the trick with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually this part doesn't splat out the hook string — since implicit hooks are for specifying "one-off" hooks right in a derivation, they're going to be specified by the derivation being built itself. Those often are multiline, but since they're also by far the most obvious hooks, I went with just logging the name. So something like preConfigure = ''
some foo commands
''; Gets logged as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's definitely good enough. Thanks for the example. I wonder (and this isn't for this review) whether "implicit" is the right name for this concept, and whether "immediate" or "derivation-supplied" might be a better name. In fact, from the perspective of the derivation or package author, they might be thought of as "explicit" hooks as opposed to the "implicit" ones that come from elsewhere. An irony if so. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A lot of my time spent debugging this ended up actually amounting to figuring out what implicit hooks are and where they come from and why there's a separate, special mechanism for them in stdenv 😅 So I completely agree; a rename of the concept would be very helpful. "Immediate" is decent, but further bikeshedding can be at a later date |
||
eval "${!hookName}" | ||
else | ||
return "$def" | ||
|
@@ -644,6 +685,7 @@ activatePackage() { | |
(( hostOffset <= targetOffset )) || exit 1 | ||
|
||
if [ -f "$pkg" ]; then | ||
echo "sourcing setup hook '$pkg'" | ||
source "$pkg" | ||
fi | ||
|
||
|
@@ -667,6 +709,7 @@ activatePackage() { | |
fi | ||
|
||
if [[ -f "$pkg/nix-support/setup-hook" ]]; then | ||
echo "sourcing setup hook '$pkg/nix-support/setuphook'" | ||
source "$pkg/nix-support/setup-hook" | ||
fi | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is cute, but what's the damage just showing the log-viewing user what the hook value is directly? How many of these are there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not many. I only know of one, which is autoPatchelfHook. I ran
rg -U -t sh 'hook.?\+?=\(.\n'
to try to find other examples but I couldn't find any, though I'm not confidant that regex is all-inclusive. By far most hooks are either functions, or single-lineif [[ -z "${dontDoHookThing-}" ]]; then doHookThing; fi
. I am fine with splatting out potential multiline hooks, and autoPatchelfHook could easily be changed to do its multiline logic in its hook function instead of inline.