From e91b5670e3fc0a7e39b9f3e469bedfe742d42eda Mon Sep 17 00:00:00 2001 From: Manuel Mendez Date: Tue, 7 Jun 2022 13:14:38 -0400 Subject: [PATCH 1/3] cc-wrapper: Use case statements instead of bunch of if/elif checks Makes for easier to read code imo, case-in-point there was a duplicate test for `$p = -E` before. While doing this little bit of refactor I changed rest -> kept because that makes more sense, rest sounds like its the rest of params while kept says these are the params that we've kept. I tested for no change in behavior using the following bash script: ``` reset() { cInclude=1 cxxInclude=1 cxxLibrary=1 dontLink=0 isCxx=0 nonFlagArgs=0 params=() } parseParams() { declare -i n=0 nParams=${#params[@]} while (("$n" < "$nParams")); do p=${params[n]} p2=${params[n + 1]:-} # handle `p` being last one case "$p" in -[cSEM] | -MM) dontLink=1 ;; -cc1) cc1=1 ;; -nostdinc) cInclude=0 cxxInclude=0 ;; -nostdinc++) cxxInclude=0 ;; -nostdlib) cxxLibrary=0 ;; -x) case "$p2" in *-header) dontLink=1 ;; c++*) isCxx=1 ;; esac ;; -?*) ;; *) nonFlagArgs=1 ;; # Includes a solitary dash (`-`) which signifies standard input; it is not a flag esac n+=1 done } for p in c S E M MM; do reset params=-$p parseParams [[ $dontLink != 1 ]] && echo "expected dontLink=1 for params:${params[@]}" >&2 && exit 1 done reset params=(-x foo-header) parseParams [[ $dontLink != 1 ]] && echo "expected dontLink=1 for params:${params[@]}" >&2 && exit 1 reset params=(-x c++-foo) parseParams [[ $isCxx != 1 ]] && echo "expected isCxx=1 for params:${params[@]}" >&2 && exit 1 reset params=-nostdlib parseParams [[ $cxxLibrary != 0 ]] && echo "expected cxxLibrary=0 for params:${params[@]}" >&2 && exit 1 reset params=-nostdinc parseParams [[ $cInclude != 0 ]] && echo "expected cInclude=0 for params:${params[@]}" >&2 && exit 1 [[ $cxxInclude != 0 ]] && echo "expected cxxInclude=0 for params:${params[@]}" >&2 && exit 1 reset params=-nostdinc++ parseParams [[ $cxxInclude != 0 ]] && echo "expected cxxInclude=0 for params:${params[@]}" >&2 && exit 1 reset params=-cc1 parseParams [[ $cc1 != 1 ]] && echo "expected cc1=1 for params:${params[@]}" >&2 && exit 1 reset params=- parseParams [[ $nonFlagArgs != 1 ]] && echo "expected nonFlagArgs=1 for params:${params[@]}" >&2 && exit 1 reset params=bleh parseParams [[ $nonFlagArgs != 1 ]] && echo "expected nonFlagArgs=1 for params:${params[@]}" >&2 && exit 1 reset params=-? parseParams [[ $nonFlagArgs != 0 ]] && echo "expected nonFlagArgs=0 for params:${params[@]}" >&2 && exit 1 exit 0 ``` --- pkgs/build-support/cc-wrapper/cc-wrapper.sh | 83 +++++++++------------ 1 file changed, 36 insertions(+), 47 deletions(-) diff --git a/pkgs/build-support/cc-wrapper/cc-wrapper.sh b/pkgs/build-support/cc-wrapper/cc-wrapper.sh index 1220841162c..334bd72e4d4 100644 --- a/pkgs/build-support/cc-wrapper/cc-wrapper.sh +++ b/pkgs/build-support/cc-wrapper/cc-wrapper.sh @@ -38,36 +38,23 @@ nParams=${#params[@]} while (( "$n" < "$nParams" )); do p=${params[n]} p2=${params[n+1]:-} # handle `p` being last one - if [ "$p" = -c ]; then - dontLink=1 - elif [ "$p" = -S ]; then - dontLink=1 - elif [ "$p" = -E ]; then - dontLink=1 - elif [ "$p" = -E ]; then - dontLink=1 - elif [ "$p" = -M ]; then - dontLink=1 - elif [ "$p" = -MM ]; then - dontLink=1 - elif [[ "$p" = -x && "$p2" = *-header ]]; then - dontLink=1 - elif [[ "$p" = -x && "$p2" = c++* && "$isCxx" = 0 ]]; then - isCxx=1 - elif [ "$p" = -nostdlib ]; then - cxxLibrary=0 - elif [ "$p" = -nostdinc ]; then - cInclude=0 - cxxInclude=0 - elif [ "$p" = -nostdinc++ ]; then - cxxInclude=0 - elif [[ "$p" != -?* ]]; then - # A dash alone signifies standard input; it is not a flag - nonFlagArgs=1 - elif [ "$p" = -cc1 ]; then - cc1=1 - fi n+=1 + + case "$p" in + -[cSEM] | -MM) dontLink=1 ;; + -cc1) cc1=1 ;; + -nostdinc) cInclude=0 cxxInclude=0 ;; + -nostdinc++) cxxInclude=0 ;; + -nostdlib) cxxLibrary=0 ;; + -x) + case "$p2" in + *-header) dontLink=1 ;; + c++*) isCxx=1 ;; + esac + ;; + -?*) ;; + *) nonFlagArgs=1 ;; # Includes a solitary dash (`-`) which signifies standard input; it is not a flag + esac done # If we pass a flag like -Wl, then gcc will call the linker unless it @@ -81,29 +68,31 @@ fi # Optionally filter out paths not refering to the store. if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "$NIX_STORE" ]]; then - rest=() + kept=() nParams=${#params[@]} declare -i n=0 while (( "$n" < "$nParams" )); do p=${params[n]} p2=${params[n+1]:-} # handle `p` being last one - if [ "${p:0:3}" = -L/ ] && badPath "${p:2}"; then - skip "${p:2}" - elif [ "$p" = -L ] && badPath "$p2"; then - n+=1; skip "$p2" - elif [ "${p:0:3}" = -I/ ] && badPath "${p:2}"; then - skip "${p:2}" - elif [ "$p" = -I ] && badPath "$p2"; then - n+=1; skip "$p2" - elif [ "$p" = -isystem ] && badPath "$p2"; then - n+=1; skip "$p2" - else - rest+=("$p") - fi n+=1 + + skipNext=false + path="" + case "$p" in + -[IL]/*) path=${p:2} ;; + -[IL] | -isystem) path=$p2 skipNext=true ;; + esac + + if [[ -n $path ]] && badPath "$path"; then + skip "$path" + $skipNext && n+=1 + continue + fi + + kept+=("$p") done # Old bash empty array hack - params=(${rest+"${rest[@]}"}) + params=(${kept+"${kept[@]}"}) fi # Flirting with a layer violation here. @@ -118,17 +107,17 @@ fi # Clear march/mtune=native -- they bring impurity. if [ "$NIX_ENFORCE_NO_NATIVE_@suffixSalt@" = 1 ]; then - rest=() + kept=() # Old bash empty array hack for p in ${params+"${params[@]}"}; do if [[ "$p" = -m*=native ]]; then skip "$p" else - rest+=("$p") + kept+=("$p") fi done # Old bash empty array hack - params=(${rest+"${rest[@]}"}) + params=(${kept+"${kept[@]}"}) fi if [[ "$isCxx" = 1 ]]; then From 19b6ccd9acb89585cb9df7fae22e68baacda3534 Mon Sep 17 00:00:00 2001 From: Manuel Mendez Date: Fri, 3 Jun 2022 17:00:10 -0400 Subject: [PATCH 2/3] cc-wrapper: Allow for override of -target for clang/clang++ This enables users to make use of clang's multi-platform/target support without having to go through full cross system setup. This is especially useful for generating bpf object files, I'm not even usre what would a no-userland cross compile system tuple even look like to even try going that route. Fixes #176128 --- pkgs/build-support/cc-wrapper/cc-wrapper.sh | 6 ++++++ pkgs/build-support/cc-wrapper/default.nix | 13 +++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/pkgs/build-support/cc-wrapper/cc-wrapper.sh b/pkgs/build-support/cc-wrapper/cc-wrapper.sh index 334bd72e4d4..b8049dafb98 100644 --- a/pkgs/build-support/cc-wrapper/cc-wrapper.sh +++ b/pkgs/build-support/cc-wrapper/cc-wrapper.sh @@ -29,6 +29,7 @@ cc1=0 cxxInclude=1 cxxLibrary=1 cInclude=1 +needsTarget=@needsTarget@ expandResponseParams "$@" linkType=$(checkLinkType "${params[@]}") @@ -46,6 +47,7 @@ while (( "$n" < "$nParams" )); do -nostdinc) cInclude=0 cxxInclude=0 ;; -nostdinc++) cxxInclude=0 ;; -nostdlib) cxxLibrary=0 ;; + -target|--target=*) needsTarget=0;; -x) case "$p2" in *-header) dontLink=1 ;; @@ -159,6 +161,10 @@ if [ "$dontLink" != 1 ]; then export NIX_LINK_TYPE_@suffixSalt@=$linkType fi +if [ $needsTarget == 1 ]; then + extraAfter+=(-target @defaultTarget@) +fi + # As a very special hack, if the arguments are just `-v', then don't # add anything. This is to prevent `gcc -v' (which normally prints # out the version number and returns exit code 0) from printing out diff --git a/pkgs/build-support/cc-wrapper/default.nix b/pkgs/build-support/cc-wrapper/default.nix index 35d714f9b41..1fc0491cbec 100644 --- a/pkgs/build-support/cc-wrapper/default.nix +++ b/pkgs/build-support/cc-wrapper/default.nix @@ -208,6 +208,7 @@ stdenv.mkDerivation { + '' export named_cc=${targetPrefix}cc export named_cxx=${targetPrefix}c++ + export needsTarget=0 if [ -e $ccPath/${targetPrefix}gcc ]; then wrap ${targetPrefix}gcc $wrapper $ccPath/${targetPrefix}gcc @@ -215,6 +216,8 @@ stdenv.mkDerivation { export named_cc=${targetPrefix}gcc export named_cxx=${targetPrefix}g++ elif [ -e $ccPath/clang ]; then + needsTarget=1 + export defaultTarget=${targetPlatform.config} wrap ${targetPrefix}clang $wrapper $ccPath/clang ln -s ${targetPrefix}clang $out/bin/${targetPrefix}cc export named_cc=${targetPrefix}clang @@ -225,6 +228,8 @@ stdenv.mkDerivation { wrap ${targetPrefix}g++ $wrapper $ccPath/${targetPrefix}g++ ln -s ${targetPrefix}g++ $out/bin/${targetPrefix}c++ elif [ -e $ccPath/clang++ ]; then + needsTarget=1 + export defaultTarget=${targetPlatform.config} wrap ${targetPrefix}clang++ $wrapper $ccPath/clang++ ln -s ${targetPrefix}clang++ $out/bin/${targetPrefix}c++ fi @@ -297,14 +302,6 @@ stdenv.mkDerivation { fi '' - ## - ## General Clang support - ## - + optionalString isClang '' - - echo "-target ${targetPlatform.config}" >> $out/nix-support/cc-cflags - '' - ## ## GCC libs for non-GCC support ## From 0fdc72b7e94f121943b4c03bc97c6b7bdabc28d9 Mon Sep 17 00:00:00 2001 From: Manuel Mendez Date: Mon, 13 Jun 2022 14:24:52 -0400 Subject: [PATCH 3/3] cc-wrapper: Add clang specific options to clang specific file This way gcc doesn't need to be rebuilt because of clang. This also avoids rebuilding clang when only the wrapper needs to be tweaked. --- .../cc-wrapper/add-clang-cc-cflags-before.sh | 11 +++++++++++ pkgs/build-support/cc-wrapper/cc-wrapper.sh | 6 ++---- pkgs/build-support/cc-wrapper/default.nix | 14 +++++++++----- 3 files changed, 22 insertions(+), 9 deletions(-) create mode 100644 pkgs/build-support/cc-wrapper/add-clang-cc-cflags-before.sh diff --git a/pkgs/build-support/cc-wrapper/add-clang-cc-cflags-before.sh b/pkgs/build-support/cc-wrapper/add-clang-cc-cflags-before.sh new file mode 100644 index 00000000000..f943b850468 --- /dev/null +++ b/pkgs/build-support/cc-wrapper/add-clang-cc-cflags-before.sh @@ -0,0 +1,11 @@ +needsTarget=true + +for p in "${params[@]}"; do + case "$p" in + -target | --target=*) needsTarget=false ;; + esac +done + +if $needsTarget; then + extraBefore+=(-target @defaultTarget@) +fi diff --git a/pkgs/build-support/cc-wrapper/cc-wrapper.sh b/pkgs/build-support/cc-wrapper/cc-wrapper.sh index b8049dafb98..651519490aa 100644 --- a/pkgs/build-support/cc-wrapper/cc-wrapper.sh +++ b/pkgs/build-support/cc-wrapper/cc-wrapper.sh @@ -29,7 +29,6 @@ cc1=0 cxxInclude=1 cxxLibrary=1 cInclude=1 -needsTarget=@needsTarget@ expandResponseParams "$@" linkType=$(checkLinkType "${params[@]}") @@ -47,7 +46,6 @@ while (( "$n" < "$nParams" )); do -nostdinc) cInclude=0 cxxInclude=0 ;; -nostdinc++) cxxInclude=0 ;; -nostdlib) cxxLibrary=0 ;; - -target|--target=*) needsTarget=0;; -x) case "$p2" in *-header) dontLink=1 ;; @@ -161,8 +159,8 @@ if [ "$dontLink" != 1 ]; then export NIX_LINK_TYPE_@suffixSalt@=$linkType fi -if [ $needsTarget == 1 ]; then - extraAfter+=(-target @defaultTarget@) +if [[ -e @out@/nix-support/add-local-cc-cflags-before.sh ]]; then + source @out@/nix-support/add-local-cflags-before.sh fi # As a very special hack, if the arguments are just `-v', then don't diff --git a/pkgs/build-support/cc-wrapper/default.nix b/pkgs/build-support/cc-wrapper/default.nix index 1fc0491cbec..5be2589088b 100644 --- a/pkgs/build-support/cc-wrapper/default.nix +++ b/pkgs/build-support/cc-wrapper/default.nix @@ -208,7 +208,6 @@ stdenv.mkDerivation { + '' export named_cc=${targetPrefix}cc export named_cxx=${targetPrefix}c++ - export needsTarget=0 if [ -e $ccPath/${targetPrefix}gcc ]; then wrap ${targetPrefix}gcc $wrapper $ccPath/${targetPrefix}gcc @@ -216,8 +215,6 @@ stdenv.mkDerivation { export named_cc=${targetPrefix}gcc export named_cxx=${targetPrefix}g++ elif [ -e $ccPath/clang ]; then - needsTarget=1 - export defaultTarget=${targetPlatform.config} wrap ${targetPrefix}clang $wrapper $ccPath/clang ln -s ${targetPrefix}clang $out/bin/${targetPrefix}cc export named_cc=${targetPrefix}clang @@ -228,8 +225,6 @@ stdenv.mkDerivation { wrap ${targetPrefix}g++ $wrapper $ccPath/${targetPrefix}g++ ln -s ${targetPrefix}g++ $out/bin/${targetPrefix}c++ elif [ -e $ccPath/clang++ ]; then - needsTarget=1 - export defaultTarget=${targetPlatform.config} wrap ${targetPrefix}clang++ $wrapper $ccPath/clang++ ln -s ${targetPrefix}clang++ $out/bin/${targetPrefix}c++ fi @@ -519,6 +514,15 @@ stdenv.mkDerivation { substituteAll ${../wrapper-common/utils.bash} $out/nix-support/utils.bash '' + ## + ## General Clang support + ## Needs to go after ^ because the for loop eats \n and makes this file an invalid script + ## + + optionalString isClang '' + export defaultTarget=${targetPlatform.config} + substituteAll ${./add-clang-cc-cflags-before.sh} $out/nix-support/add-local-cc-cflags-before.sh + '' + ## ## Extra custom steps ##