-
-
Notifications
You must be signed in to change notification settings - Fork 14.1k
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 setup misc cleanups #27336
Stdenv setup misc cleanups #27336
Conversation
@@ -211,7 +211,7 @@ stdenv.mkDerivation ({ | |||
configureFlags="${concatStringsSep " " defaultConfigureFlags} $configureFlags" | |||
|
|||
# nativePkgs defined in stdenv/setup.hs | |||
for p in $nativePkgs; do | |||
for p in "${!nativePkgs[@]}"; do |
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.
Does this work? Isn't the ${} escaping into nix?
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.
Weird you would think, but I did build it. ah building nevermind building stdenv wouldn't catch that. Thanks!
…d of strings This is generally cleaner: less eval, less worrying about separators, and probably also faster. I got the idea from that python wrapper script.
I took some liberties with the flags-echoing code to make it more concise and correct. Also, a few warnings in findInputs and friends I skipped because I am going to rewrite those anyways. Thanks @grahamc for telling me about this great linter!
02ff8c1
to
2087c3e
Compare
pkgs/stdenv/generic/setup.sh
Outdated
local input="$1" | ||
local output="$2" | ||
local input=$1; shift | ||
local output=$1; shift |
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.
shift
also takes a numeric argument, so you can do e.g., local foo=$1 bar=$2; shift 2
to achieve the same effect.
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.
I short of like the "one variable, one shift" correspondence, but I'd be happy to change it.
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.
Looks a bit odd to me, but it's entirely superficial :)
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.
Ah I can avoid binding p
doing this. Swayed :).
2087c3e
to
959801d
Compare
It now blows up on null byte in file (rather than silently truncating), and invalid arguments (rather than silently skipping).
959801d
to
5d693c8
Compare
local input="$1" | ||
local output="$2" | ||
local input=$1 | ||
local output=$2 |
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.
Why no quotes here?
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.
Bash parses it the same either way! I learned this and was quite surprised.
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.
I could leave as is, but I figured given it didn't matter I should pick one and be consistent. I could normalize the other way if you like.
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.
Copying from the bash because it's really quite unbelievable for me still:
$ set -x; x='asdf asdf'; y=$x; z="$x"
+ set -x
+ x='asdf asdf'
+ y='asdf asdf'
+ z='asdf asdf'
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 covered under PARAMETERS in the bash manual. Word splitting & pathname expansion is not performed on assignment.
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.
I don't find this an improvement, it's just forces people to learn another special case in bash syntax instead of using the obviously safe variant.
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.
Agree with @dezgeg here. Shell quoting is such a pain and source of subtle bugs already; although it may be technically correct, why not be explicit when we can do so trivially? This particular gun might have a fancy high tech anti-foot-shot protection device in it, but I'd rather just point it away from my feet.
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.
Uh, I hate how the bash language is so complex.
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.
I basically got bash Stockholm syndrome writing this stuff. Happy to quote everything for consistency.
pkgs/stdenv/generic/setup.sh
Outdated
@@ -727,17 +742,23 @@ configurePhase() { | |||
buildPhase() { | |||
runHook preBuild | |||
|
|||
if [ -z "$makeFlags" ] && ! [ -n "$makefile" -o -e "Makefile" -o -e "makefile" -o -e "GNUmakefile" ]; then | |||
if [ -z "$makeFlags" ] && ! [[ -n "$makefile" || -e "Makefile" || -e "makefile" || -e "GNUmakefile" ]]; then |
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.
Can't this be written as a single [[...]]
test? Something like
if [[ -z $makeFlags && ! ( -n $makefile || ... ) ]]; then
Note that quotes are not necessary inside [[...]]
.
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.
Yes it can. Will do.
Looks good to me! |
pkgs/stdenv/generic/setup.sh
Outdated
eval $var="'${!var} $pkg '" | ||
# Stop if we've already added this one | ||
[[ -z "${varDeref["$pkg"]}" ]] || return 0 | ||
varDeref["$pkg"]=1 |
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 great because it fixes the O(n^2) performance setting up the environment!
Also remove useless quotes on same line
foo=$1 surprisingly doesn't need quotes in Bash. Word splits are only syntactic in string variable (not array var!) assignments.
Doing another build with those changes, and then will merge. |
pkgs/stdenv/generic/setup.sh
Outdated
$installFlags "${installFlagsArray[@]}" | ||
$installFlags "${installFlagsArray[@]}") | ||
|
||
printf 'install flags:' |
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.
Why is this multiple commands?
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.
@dezgeg it hash to be:
- print the name of the flags
- repeat the format string (unquoted space + quoted arg) for each argument
- close the line
printf repeats the format string until all the args are gone, so it is essential the repeated format string contain one a single substitution.
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.
I could add a helper function and comments for this :).
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.
Ah.
local content | ||
# read returns non-0 on EOF, so we want read to fail | ||
if IFS='' read -r -N 0 content < "$input"; then | ||
echo "${FUNCNAME[0]}(): ERROR: File \"$input\" has null bytes, won't process" >&2 |
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.
substitute
is documented to work on binaries in the manual:
It supports performing substitutions on binary files (such as executables), though there you’ll probably want to make sure that the replacement string is as long as the replaced string.
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.
@dezgeg Woah. Well the manual is definitely wrong about that. We can use mapfile
and carefully printf
the missing null bytes, but I think that should be a followup PR.
@dezgeg made the good point that the reasons for doing this were not at all intuitive.
Motivation for this change
@grahamc showed me shellcheck, which I am now quite fond of. In order to tightening things up so #26805 is easier to debug, I did these clean ups.
I left the
# shellcheck disable=...
in there in hopes we can eventually make it a test. A lot of this quoting doesn't by us much since other things block store paths with whitespace, but shellcheck can also make switching toset -u
feasible, which is definitely worthy of static analysis.This is easiest to review commit-by-commit:
substitue
Things done
Rebuilt Linux and Darwin stdenvs.