diff options
author | Todd Gamblin <tgamblin@llnl.gov> | 2021-09-26 16:20:26 -0700 |
---|---|---|
committer | Todd Gamblin <tgamblin@llnl.gov> | 2021-10-04 18:30:19 -0700 |
commit | 052b2e1b08d54374694abca2321c789a98101243 (patch) | |
tree | b804401f2fdb4042452744b0cf93b967a0d61541 /lib | |
parent | 472638f025abfd08c9ed94be4af2d475c09c32dd (diff) | |
download | spack-052b2e1b08d54374694abca2321c789a98101243.tar.gz spack-052b2e1b08d54374694abca2321c789a98101243.tar.bz2 spack-052b2e1b08d54374694abca2321c789a98101243.tar.xz spack-052b2e1b08d54374694abca2321c789a98101243.zip |
cc: convert compiler wrapper to posix shell
This converts everything in cc to POSIX sh, except for the parts currently
handled with bash arrays. Tests are still passing.
This version tries to be as straightforward as possible. Specifically, most conversions
are kept simple -- convert ifs to ifs, handle indirect expansion the way we do in
`setup-env.sh`, only mess with the logic in `cc`, and don't mess with the python code at
all.
The big refactor is for arrays. We can't rely on bash's nice arrays and be ignorant of
separators anymore. So:
1. To avoid complicated separator logic, there are three types of lists. They are:
* `$lsep`-separated lists, which end with `_list`. `lsep` is customizable, but we
picked `^G` (alarm bell) for `$lsep` because it's ASCII and it's unlikely that it
would actually appear in any arguments. If we need to get fancier (and I will lose
faith in the world if we do) then we could consider XON or XOFF.
* `:`-separated directory lists, which end with `_dirs`, `_DIRS`, `PATH`, or `PATHS`
* Whitespace-separated lists (like flags), which can have any other name.
Whitespace and colon-separated lists come with the territory with PATHs from env
vars and lists of flags. `^G` separated lists are what we use for most internal
variables, b/c it's more likely to work.
2. To avoid subshells, use a bunch of functions that do dirty `eval` stuff instead. This
adds 3 functions to deal with lists:
* `append LISTNAME ELEMENT [SEP]` will put `ELEMENT` at the end of the list called
`LISTNAME`. You can optionally say what separator you expect to use. Note that we
are taking advantage of everything being global and passing lists by name.
* `prepend LISTNAME ELEMENT [SEP]` like append, but puts `ELEMENT` at the start of
`LISTNAME`
* `extend LISTNAME1 LISTNAME2 [PREFIX]` appends everything in LISTNAME2 to
LISTNAME1, and optionally prepends `PREFIX` to every element (this is useful for
things like `-I`, `-isystem `, etc.
* `preextend LISTNAME1 LISTNAME2 [PREFIX]` prepends everything in LISTNAME2 to
LISTNAME1 in order, and optionally prepends `PREFIX` to every element.
The routines determine the separator for each argument by its name, so we don't have to
pass around separators everywhere. Amazingly, as long as you do not expand variables'
values within an `eval` environment, you can do all this and still preserve quoting.
When iterating over lists, the user of this API still has to set and unset `IFS`
properly.
We ended up having to ignore shellcheck SC2034 (unused variable), because using evals
all over the place means that shellcheck doesn't notice that our list variables are
actually used.
So far this is looking pretty good. I took the most complex unit test I could find
(which runs a sample link line) and ran the same command line 200 times in a shell
script. Times are roughly as follows:
For this invocation:
```console
$ bash -c 'time (for i in `seq 1 200`; do ~/test_cc.sh > /dev/null; done)'
```
I get the following performance numbers (the listed shells are what I put in `cc`'s
shebang):
**Original**
* Old version of `cc` with arrays and `bash v3.2.57` (macOS builtin): `4.462s` (`.022s` / call)
* Old version of `cc` with arrays and `bash v5.1.8` (Homebrew): `3.267s` (`.016s` / call)
**Using many subshells (#26408)**
* with `bash v3.2.57`: `25.302s` (`.127s` / call)
* with `bash v5.1.8`: `27.801s` (`.139s` / call)
* with `dash`: `15.302s` (`.077s` / call)
This version didn't seem to work with zsh.
**This PR (no subshells)**
* with `bash v3.2.57`: `4.973s` (`.025s` / call)
* with `bash v5.1.8`: `4.984s` (`.025s` / call)
* with `zsh`: `2.995s` (`.015s` / call)
* with `dash`: `1.890s` (`.0095s` / call)
Dash, with the new posix design, is easily the winner.
So there are several interesting things to note here:
1. Running the posix version in `bash` is slower than using `bash` arrays. That is to be
expected because it's doing a bunch of string processing where it likely did not have
to before, at least in `bash`.
2. `zsh`, at least on macOS, is significantly faster than the ancient `bash` they ship
with the system. Using `zsh` with the new version also makes the posix wrappers
faster than `develop`. So it's worth preferring `zsh` if we have it. I suppose we
should also try this with newer `bash` on Linux.
3. `bash v5.1.8` seems to be significantly faster than the old system `bash v3.2.57` for
arrays. For straight POSIX stuff, it's a little slower. It did not seem to matter
whether `--posix` was used.
4. `dash` is way faster than `bash` or `zsh`, so the real payoff just comes from being
able to use it. I am not sure if that is mostly startup time, but it's significant.
`dash` is ~2.4x faster than the original `bash` with arrays.
So, doing a lot of string stuff is slower than arrays, but converting to posix seems
worth it to be able to exploit `dash`.
- [x] Convert all but array-related portions to sh
- [x] Fix basic shellcheck issues.
- [x] Convert arrays to use a few convenience functions: `append` and `extend`
- [x] Get `cc` tests passing.
- [x] Add `cc` tests where needed passing.
- [x] Benchmarking.
Co-authored-by: Tom Scogland <scogland1@llnl.gov>
Co-authored-by: Danny McClanahan <1305167+cosmicexplorer@users.noreply.github.com>
Diffstat (limited to 'lib')
-rwxr-xr-x | lib/spack/env/cc | 563 | ||||
-rw-r--r-- | lib/spack/spack/test/cc.py | 163 |
2 files changed, 434 insertions, 292 deletions
diff --git a/lib/spack/env/cc b/lib/spack/env/cc index b603c3bc32..4bef0ddf9e 100755 --- a/lib/spack/env/cc +++ b/lib/spack/env/cc @@ -1,4 +1,5 @@ -#!/bin/bash +#!/bin/sh +# shellcheck disable=SC2034 # evals in this script fool shellcheck # # Copyright 2013-2021 Lawrence Livermore National Security, LLC and other # Spack Project Developers. See the top-level COPYRIGHT file for details. @@ -20,25 +21,33 @@ # -Wl,-rpath arguments for dependency /lib directories. # +# Reset IFS to the default: whitespace-separated lists. When we use +# other separators, we set and reset it. +unset IFS + +# Separator for lists whose names end with `_list`. +# We pick the alarm bell character, which is highly unlikely to +# conflict with anything. This is a literal bell character (which +# we have to use since POSIX sh does not convert escape sequences +# like '\a' outside of the format argument of `printf`). +# NOTE: Depending on your editor this may look empty, but it is not. +readonly lsep='' + # This is an array of environment variables that need to be set before # the script runs. They are set by routines in spack.build_environment # as part of the package installation process. -parameters=( - SPACK_ENV_PATH - SPACK_DEBUG_LOG_DIR - SPACK_DEBUG_LOG_ID - SPACK_COMPILER_SPEC - SPACK_CC_RPATH_ARG - SPACK_CXX_RPATH_ARG - SPACK_F77_RPATH_ARG - SPACK_FC_RPATH_ARG - SPACK_TARGET_ARGS - SPACK_DTAGS_TO_ADD - SPACK_DTAGS_TO_STRIP - SPACK_LINKER_ARG - SPACK_SHORT_SPEC - SPACK_SYSTEM_DIRS -) +readonly params="\ +SPACK_ENV_PATH +SPACK_DEBUG_LOG_DIR +SPACK_DEBUG_LOG_ID +SPACK_COMPILER_SPEC +SPACK_CC_RPATH_ARG +SPACK_CXX_RPATH_ARG +SPACK_F77_RPATH_ARG +SPACK_FC_RPATH_ARG +SPACK_LINKER_ARG +SPACK_SHORT_SPEC +SPACK_SYSTEM_DIRS" # Optional parameters that aren't required to be set @@ -58,60 +67,157 @@ parameters=( # Test command is used to unit test the compiler script. # SPACK_TEST_COMMAND -# die() -# Prints a message and exits with error 1. -function die { +# die MESSAGE +# Print a message and exit with error code 1. +die() { echo "$@" exit 1 } -# read input parameters into proper bash arrays. -# SYSTEM_DIRS is delimited by : -IFS=':' read -ra SPACK_SYSTEM_DIRS <<< "${SPACK_SYSTEM_DIRS}" +# empty VARNAME +# Return whether the variable VARNAME is unset or set to the empty string. +empty() { + eval "test -z \"\${$1}\"" +} -# SPACK_<LANG>FLAGS and SPACK_LDLIBS are split by ' ' -IFS=' ' read -ra SPACK_FFLAGS <<< "$SPACK_FFLAGS" -IFS=' ' read -ra SPACK_CPPFLAGS <<< "$SPACK_CPPFLAGS" -IFS=' ' read -ra SPACK_CFLAGS <<< "$SPACK_CFLAGS" -IFS=' ' read -ra SPACK_CXXFLAGS <<< "$SPACK_CXXFLAGS" -IFS=' ' read -ra SPACK_LDFLAGS <<< "$SPACK_LDFLAGS" -IFS=' ' read -ra SPACK_LDLIBS <<< "$SPACK_LDLIBS" +# setsep LISTNAME +# Set the global variable 'sep' to the separator for a list with name LISTNAME. +# There are three types of lists: +# 1. regular lists end with _list and are separated by $lsep +# 2. directory lists end with _dirs/_DIRS/PATH(S) and are separated by ':' +# 3. any other list is assumed to be separated by spaces: " " +setsep() { + case "$1" in + *_dirs|*_DIRS|*PATH|*PATHS) + sep=':' + ;; + *_list) + sep="$lsep" + ;; + *) + sep=" " + ;; + esac +} +# prepend LISTNAME ELEMENT [SEP] +# +# Prepend ELEMENT to the list stored in the variable LISTNAME, +# assuming the list is separated by SEP. +# Handles empty lists and single-element lists. +prepend() { + varname="$1" + elt="$2" + + if empty "$varname"; then + eval "$varname=\"\${elt}\"" + else + # Get the appropriate separator for the list we're appending to. + setsep "$varname" + eval "$varname=\"\${elt}${sep}\${$varname}\"" + fi +} + +# append LISTNAME ELEMENT [SEP] +# +# Append ELEMENT to the list stored in the variable LISTNAME, +# assuming the list is separated by SEP. +# Handles empty lists and single-element lists. +append() { + varname="$1" + elt="$2" + + if empty "$varname"; then + eval "$varname=\"\${elt}\"" + else + # Get the appropriate separator for the list we're appending to. + setsep "$varname" + eval "$varname=\"\${$varname}${sep}\${elt}\"" + fi +} + +# extend LISTNAME1 LISTNAME2 [PREFIX] +# +# Append the elements stored in the variable LISTNAME2 +# to the list stored in LISTNAME1. +# If PREFIX is provided, prepend it to each element. +extend() { + # Figure out the appropriate IFS for the list we're reading. + setsep "$2" + if [ "$sep" != " " ]; then + IFS="$sep" + fi + eval "for elt in \${$2}; do append $1 \"$3\${elt}\"; done" + unset IFS +} + +# preextend LISTNAME1 LISTNAME2 [PREFIX] +# +# Prepend the elements stored in the list at LISTNAME2 +# to the list at LISTNAME1, preserving order. +# If PREFIX is provided, prepend it to each element. +preextend() { + # Figure out the appropriate IFS for the list we're reading. + setsep "$2" + if [ "$sep" != " " ]; then + IFS="$sep" + fi + + # first, reverse the list to prepend + _reversed_list="" + eval "for elt in \${$2}; do prepend _reversed_list \"$3\${elt}\"; done" + + # prepend reversed list to preextend in order + IFS="${lsep}" + for elt in $_reversed_list; do prepend "$1" "$3${elt}"; done + unset IFS +} + +# system_dir PATH # test whether a path is a system directory -function system_dir { +system_dir() { + IFS=':' # SPACK_SYSTEM_DIRS is colon-separated path="$1" - for sd in "${SPACK_SYSTEM_DIRS[@]}"; do - if [ "${path}" == "${sd}" ] || [ "${path}" == "${sd}/" ]; then + for sd in $SPACK_SYSTEM_DIRS; do + if [ "${path}" = "${sd}" ] || [ "${path}" = "${sd}/" ]; then # success if path starts with a system prefix + unset IFS return 0 fi done + unset IFS return 1 # fail if path starts no system prefix } -for param in "${parameters[@]}"; do - if [[ -z ${!param+x} ]]; then +# Fail with a clear message if the input contains any bell characters. +if eval "[ \"\${*#*${lsep}}\" != \"\$*\" ]"; then + die "ERROR: Compiler command line contains our separator ('${lsep}'). Cannot parse." +fi + +# ensure required variables are set +for param in $params; do + if eval "test -z \"\${${param}:-}\""; then die "Spack compiler must be run from Spack! Input '$param' is missing." fi done # Check if optional parameters are defined # If we aren't asking for debug flags, don't add them -if [[ -z ${SPACK_ADD_DEBUG_FLAGS+x} ]]; then +if [ -z "${SPACK_ADD_DEBUG_FLAGS:-}" ]; then SPACK_ADD_DEBUG_FLAGS="false" fi # SPACK_ADD_DEBUG_FLAGS must be true/false/custom is_valid="false" for param in "true" "false" "custom"; do - if [ "$param" == "$SPACK_ADD_DEBUG_FLAGS" ]; then + if [ "$param" = "$SPACK_ADD_DEBUG_FLAGS" ]; then is_valid="true" fi done # Exit with error if we are given an incorrect value -if [ "$is_valid" == "false" ]; then - die "SPACK_ADD_DEBUG_FLAGS, if defined, must be one of 'true' 'false' or 'custom'" +if [ "$is_valid" = "false" ]; then + die "SPACK_ADD_DEBUG_FLAGS, if defined, must be one of 'true', 'false', or 'custom'." fi # Figure out the type of compiler, the language, and the mode so that @@ -174,7 +280,7 @@ esac # If any of the arguments below are present, then the mode is vcheck. # In vcheck mode, nothing is added in terms of extra search paths or # libraries. -if [[ -z $mode ]] || [[ $mode == ld ]]; then +if [ -z "$mode" ] || [ "$mode" = ld ]; then for arg in "$@"; do case $arg in -v|-V|--version|-dumpversion) @@ -186,16 +292,16 @@ if [[ -z $mode ]] || [[ $mode == ld ]]; then fi # Finish setting up the mode. -if [[ -z $mode ]]; then +if [ -z "$mode" ]; then mode=ccld for arg in "$@"; do - if [[ $arg == -E ]]; then + if [ "$arg" = "-E" ]; then mode=cpp break - elif [[ $arg == -S ]]; then + elif [ "$arg" = "-S" ]; then mode=as break - elif [[ $arg == -c ]]; then + elif [ "$arg" = "-c" ]; then mode=cc break fi @@ -222,17 +328,18 @@ dtags_to_strip="${SPACK_DTAGS_TO_STRIP}" linker_arg="${SPACK_LINKER_ARG}" # Set up rpath variable according to language. -eval rpath=\$SPACK_${comp}_RPATH_ARG +rpath="ERROR: RPATH ARG WAS NOT SET" +eval "rpath=\${SPACK_${comp}_RPATH_ARG:?${rpath}}" # Dump the mode and exit if the command is dump-mode. -if [[ $SPACK_TEST_COMMAND == dump-mode ]]; then +if [ "$SPACK_TEST_COMMAND" = "dump-mode" ]; then echo "$mode" exit fi # Check that at least one of the real commands was actually selected, # otherwise we don't know what to execute. -if [[ -z $command ]]; then +if [ -z "$command" ]; then die "ERROR: Compiler '$SPACK_COMPILER_SPEC' does not support compiling $language programs." fi @@ -240,24 +347,26 @@ fi # Filter '.' and Spack environment directories out of PATH so that # this script doesn't just call itself # -IFS=':' read -ra env_path <<< "$PATH" -IFS=':' read -ra spack_env_dirs <<< "$SPACK_ENV_PATH" -spack_env_dirs+=("" ".") -export PATH="" -for dir in "${env_path[@]}"; do +new_dirs="" +IFS=':' +for dir in $PATH; do addpath=true - for env_dir in "${spack_env_dirs[@]}"; do - if [[ "${dir%%/}" == "$env_dir" ]]; then - addpath=false - break - fi + for spack_env_dir in $SPACK_ENV_PATH; do + case "${dir%%/}" in + "$spack_env_dir"|'.'|'') + addpath=false + break + ;; + esac done - if $addpath; then - export PATH="${PATH:+$PATH:}$dir" + if [ $addpath = true ]; then + append new_dirs "$dir" fi done +unset IFS +export PATH="$new_dirs" -if [[ $mode == vcheck ]]; then +if [ "$mode" = vcheck ]; then exec "${command}" "$@" fi @@ -265,16 +374,20 @@ fi # It doesn't work with -rpath. # This variable controls whether they are added. add_rpaths=true -if [[ ($mode == ld || $mode == ccld) && "$SPACK_SHORT_SPEC" =~ "darwin" ]]; -then - for arg in "$@"; do - if [[ ($arg == -r && $mode == ld) || - ($arg == -r && $mode == ccld) || - ($arg == -Wl,-r && $mode == ccld) ]]; then - add_rpaths=false - break - fi - done +if [ "$mode" = ld ] || [ "$mode" = ccld ]; then + if [ "${SPACK_SHORT_SPEC#*darwin}" != "${SPACK_SHORT_SPEC}" ]; then + for arg in "$@"; do + if [ "$arg" = "-r" ]; then + if [ "$mode" = ld ] || [ "$mode" = ccld ]; then + add_rpaths=false + break + fi + elif [ "$arg" = "-Wl,-r" ] && [ "$mode" = ccld ]; then + add_rpaths=false + break + fi + done + fi fi # Save original command for debug logging @@ -297,17 +410,22 @@ input_command="$*" # The libs variable is initialized here for completeness, and it is also # used later to inject flags supplied via `ldlibs` on the command # line. These come into the wrappers via SPACK_LDLIBS. -# -includes=() -libdirs=() -rpaths=() -system_includes=() -system_libdirs=() -system_rpaths=() -libs=() -other_args=() -isystem_system_includes=() -isystem_includes=() + +# The loop below breaks up the command line into these lists of components. +# The lists are all bell-separated to be as flexible as possible, as their +# contents may come from the command line, from ' '-separated lists, +# ':'-separated lists, etc. +include_dirs_list="" +lib_dirs_list="" +rpath_dirs_list="" +system_include_dirs_list="" +system_lib_dirs_list="" +system_rpath_dirs_list="" +isystem_system_include_dirs_list="" +isystem_include_dirs_list="" +libs_list="" +other_args_list="" + while [ $# -ne 0 ]; do @@ -327,32 +445,32 @@ while [ $# -ne 0 ]; do isystem_was_used=true if [ -z "$arg" ]; then shift; arg="$1"; fi if system_dir "$arg"; then - isystem_system_includes+=("$arg") + append isystem_system_include_dirs_list "$arg" else - isystem_includes+=("$arg") + append isystem_include_dirs_list "$arg" fi ;; -I*) arg="${1#-I}" if [ -z "$arg" ]; then shift; arg="$1"; fi if system_dir "$arg"; then - system_includes+=("$arg") + append system_include_dirs_list "$arg" else - includes+=("$arg") + append include_dirs_list "$arg" fi ;; -L*) arg="${1#-L}" if [ -z "$arg" ]; then shift; arg="$1"; fi if system_dir "$arg"; then - system_libdirs+=("$arg") + append system_lib_dirs_list "$arg" else - libdirs+=("$arg") + append lib_dirs_list "$arg" fi ;; -l*) # -loopopt=0 is generated erroneously in autoconf <= 2.69, - # and passed by ifx to the linker, which confuses it with a + # and passed by ifx to the linker, which confuses it with a # library. Filter it out. # TODO: generalize filtering of args with an env var, so that # TODO: we do not have to special case this here. @@ -363,66 +481,76 @@ while [ $# -ne 0 ]; do fi arg="${1#-l}" if [ -z "$arg" ]; then shift; arg="$1"; fi - other_args+=("-l$arg") + append other_args_list "-l$arg" ;; -Wl,*) arg="${1#-Wl,}" if [ -z "$arg" ]; then shift; arg="$1"; fi - if [[ "$arg" = -rpath=* ]]; then - rp="${arg#-rpath=}" - elif [[ "$arg" = --rpath=* ]]; then - rp="${arg#--rpath=}" - elif [[ "$arg" = -rpath,* ]]; then - rp="${arg#-rpath,}" - elif [[ "$arg" = --rpath,* ]]; then - rp="${arg#--rpath,}" - elif [[ "$arg" =~ ^-?-rpath$ ]]; then - shift; arg="$1" - if [[ "$arg" != -Wl,* ]]; then - die "-Wl,-rpath was not followed by -Wl,*" - fi - rp="${arg#-Wl,}" - elif [[ "$arg" = "$dtags_to_strip" ]] ; then - : # We want to remove explicitly this flag - else - other_args+=("-Wl,$arg") - fi + case "$arg" in + -rpath=*) rp="${arg#-rpath=}" ;; + --rpath=*) rp="${arg#--rpath=}" ;; + -rpath,*) rp="${arg#-rpath,}" ;; + --rpath,*) rp="${arg#--rpath,}" ;; + -rpath|--rpath) + shift; arg="$1" + case "$arg" in + -Wl,*) + rp="${arg#-Wl,}" + ;; + *) + die "-Wl,-rpath was not followed by -Wl,*" + ;; + esac + ;; + "$dtags_to_strip") + : # We want to remove explicitly this flag + ;; + *) + append other_args_list "-Wl,$arg" + ;; + esac ;; -Xlinker,*) arg="${1#-Xlinker,}" if [ -z "$arg" ]; then shift; arg="$1"; fi - if [[ "$arg" = -rpath=* ]]; then - rp="${arg#-rpath=}" - elif [[ "$arg" = --rpath=* ]]; then - rp="${arg#--rpath=}" - elif [[ "$arg" = -rpath ]] || [[ "$arg" = --rpath ]]; then - shift; arg="$1" - if [[ "$arg" != -Xlinker,* ]]; then - die "-Xlinker,-rpath was not followed by -Xlinker,*" - fi - rp="${arg#-Xlinker,}" - else - other_args+=("-Xlinker,$arg") - fi + + case "$arg" in + -rpath=*) rp="${arg#-rpath=}" ;; + --rpath=*) rp="${arg#--rpath=}" ;; + -rpath|--rpath) + shift; arg="$1" + case "$arg" in + -Xlinker,*) + rp="${arg#-Xlinker,}" + ;; + *) + die "-Xlinker,-rpath was not followed by -Xlinker,*" + ;; + esac + ;; + *) + append other_args_list "-Xlinker,$arg" + ;; + esac ;; -Xlinker) - if [[ "$2" == "-rpath" ]]; then - if [[ "$3" != "-Xlinker" ]]; then + if [ "$2" = "-rpath" ]; then + if [ "$3" != "-Xlinker" ]; then die "-Xlinker,-rpath was not followed by -Xlinker,*" fi shift 3; rp="$1" - elif [[ "$2" = "$dtags_to_strip" ]] ; then + elif [ "$2" = "$dtags_to_strip" ]; then shift # We want to remove explicitly this flag else - other_args+=("$1") + append other_args_list "$1" fi ;; *) - if [[ "$1" = "$dtags_to_strip" ]] ; then + if [ "$1" = "$dtags_to_strip" ]; then : # We want to remove explicitly this flag else - other_args+=("$1") + append other_args_list "$1" fi ;; esac @@ -430,9 +558,9 @@ while [ $# -ne 0 ]; do # test rpaths against system directories in one place. if [ -n "$rp" ]; then if system_dir "$rp"; then - system_rpaths+=("$rp") + append system_rpath_dirs_list "$rp" else - rpaths+=("$rp") + append rpath_dirs_list "$rp" fi fi shift @@ -445,16 +573,15 @@ done # See the gmake manual on implicit rules for details: # https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html # -flags=() +flags_list="" # Add debug flags -if [ "${SPACK_ADD_DEBUG_FLAGS}" == "true" ]; then - flags=("${flags[@]}" "${debug_flags}") +if [ "${SPACK_ADD_DEBUG_FLAGS}" = "true" ]; then + extend flags_list debug_flags # If a custom flag is requested, derive from environment -elif [ "$SPACK_ADD_DEBUG_FLAGS" == "custom" ]; then - IFS=' ' read -ra SPACK_DEBUG_FLAGS <<< "$SPACK_DEBUG_FLAGS" - flags=("${flags[@]}" "${SPACK_DEBUG_FLAGS[@]}") +elif [ "$SPACK_ADD_DEBUG_FLAGS" = "custom" ]; then + extend flags_list SPACK_DEBUG_FLAGS fi # Fortran flags come before CPPFLAGS @@ -462,7 +589,8 @@ case "$mode" in cc|ccld) case $lang_flags in F) - flags=("${flags[@]}" "${SPACK_FFLAGS[@]}") ;; + extend flags_list SPACK_FFLAGS + ;; esac ;; esac @@ -470,7 +598,8 @@ esac # C preprocessor flags come before any C/CXX flags case "$mode" in cpp|as|cc|ccld) - flags=("${flags[@]}" "${SPACK_CPPFLAGS[@]}") ;; + extend flags_list SPACK_CPPFLAGS + ;; esac @@ -479,67 +608,67 @@ case "$mode" in cc|ccld) case $lang_flags in C) - flags=("${flags[@]}" "${SPACK_CFLAGS[@]}") ;; + extend flags_list SPACK_CFLAGS + ;; CXX) - flags=("${flags[@]}" "${SPACK_CXXFLAGS[@]}") ;; + extend flags_list SPACK_CXXFLAGS + ;; esac - flags=(${SPACK_TARGET_ARGS[@]} "${flags[@]}") + + # prepend target args + preextend flags_list SPACK_TARGET_ARGS ;; esac # Linker flags case "$mode" in ld|ccld) - flags=("${flags[@]}" "${SPACK_LDFLAGS[@]}") ;; + extend flags_list SPACK_LDFLAGS + ;; esac # On macOS insert headerpad_max_install_names linker flag -if [[ ($mode == ld || $mode == ccld) && "$SPACK_SHORT_SPEC" =~ "darwin" ]]; -then - case "$mode" in - ld) - flags=("${flags[@]}" -headerpad_max_install_names) ;; - ccld) - flags=("${flags[@]}" "-Wl,-headerpad_max_install_names") ;; - esac +if [ "$mode" = ld ] || [ "$mode" = ccld ]; then + if [ "${SPACK_SHORT_SPEC#*darwin}" != "${SPACK_SHORT_SPEC}" ]; then + case "$mode" in + ld) + append flags_list "-headerpad_max_install_names" ;; + ccld) + append flags_list "-Wl,-headerpad_max_install_names" ;; + esac + fi fi -IFS=':' read -ra rpath_dirs <<< "$SPACK_RPATH_DIRS" -if [[ $mode == ccld || $mode == ld ]]; then - - if [[ "$add_rpaths" != "false" ]] ; then +if [ "$mode" = ccld ] || [ "$mode" = ld ]; then + if [ "$add_rpaths" != "false" ]; then # Append RPATH directories. Note that in the case of the # top-level package these directories may not exist yet. For dependencies # it is assumed that paths have already been confirmed. - rpaths=("${rpaths[@]}" "${rpath_dirs[@]}") + extend rpath_dirs_list SPACK_RPATH_DIRS fi - fi -IFS=':' read -ra link_dirs <<< "$SPACK_LINK_DIRS" -if [[ $mode == ccld || $mode == ld ]]; then - libdirs=("${libdirs[@]}" "${link_dirs[@]}") +if [ "$mode" = ccld ] || [ "$mode" = ld ]; then + extend lib_dirs_list SPACK_LINK_DIRS fi # add RPATHs if we're in in any linking mode case "$mode" in ld|ccld) # Set extra RPATHs - IFS=':' read -ra extra_rpaths <<< "$SPACK_COMPILER_EXTRA_RPATHS" - libdirs+=("${extra_rpaths[@]}") - if [[ "$add_rpaths" != "false" ]] ; then - rpaths+=("${extra_rpaths[@]}") + extend lib_dirs_list SPACK_COMPILER_EXTRA_RPATHS + if [ "$add_rpaths" != "false" ]; then + extend rpath_dirs_list SPACK_COMPILER_EXTRA_RPATHS fi # Set implicit RPATHs - IFS=':' read -ra implicit_rpaths <<< "$SPACK_COMPILER_IMPLICIT_RPATHS" - if [[ "$add_rpaths" != "false" ]] ; then - rpaths+=("${implicit_rpaths[@]}") + if [ "$add_rpaths" != "false" ]; then + extend rpath_dirs_list SPACK_COMPILER_IMPLICIT_RPATHS fi # Add SPACK_LDLIBS to args - for lib in "${SPACK_LDLIBS[@]}"; do - libs+=("${lib#-l}") + for lib in $SPACK_LDLIBS; do + append libs_list "${lib#-l}" done ;; esac @@ -547,63 +676,62 @@ esac # # Finally, reassemble the command line. # - -# Includes and system includes first -args=() - -# flags assembled earlier -args+=("${flags[@]}") +args_list="$flags_list" # Insert include directories just prior to any system include directories +# NOTE: adding ${lsep} to the prefix here turns every added element into two +extend args_list include_dirs_list "-I" +extend args_list isystem_include_dirs_list "-isystem${lsep}" -for dir in "${includes[@]}"; do args+=("-I$dir"); done -for dir in "${isystem_includes[@]}"; do args+=("-isystem" "$dir"); done - -IFS=':' read -ra spack_include_dirs <<< "$SPACK_INCLUDE_DIRS" -if [[ $mode == cpp || $mode == cc || $mode == as || $mode == ccld ]]; then - if [[ "$isystem_was_used" == "true" ]] ; then - for dir in "${spack_include_dirs[@]}"; do args+=("-isystem" "$dir"); done - else - for dir in "${spack_include_dirs[@]}"; do args+=("-I$dir"); done - fi -fi +case "$mode" in + cpp|cc|as|ccld) + if [ "$isystem_was_used" = "true" ]; then + extend args_list SPACK_INCLUDE_DIRS "-isystem${lsep}" + else + extend args_list SPACK_INCLUDE_DIRS "-I" + fi + ;; +esac -for dir in "${system_includes[@]}"; do args+=("-I$dir"); done -for dir in "${isystem_system_includes[@]}"; do args+=("-isystem" "$dir"); done +extend args_list system_include_dirs_list -I +extend args_list isystem_system_include_dirs_list "-isystem${lsep}" # Library search paths -for dir in "${libdirs[@]}"; do args+=("-L$dir"); done -for dir in "${system_libdirs[@]}"; do args+=("-L$dir"); done +extend args_list lib_dirs_list "-L" +extend args_list system_lib_dirs_list "-L" # RPATHs arguments case "$mode" in ccld) - if [ -n "$dtags_to_add" ] ; then args+=("$linker_arg$dtags_to_add") ; fi - for dir in "${rpaths[@]}"; do args+=("$rpath$dir"); done - for dir in "${system_rpaths[@]}"; do args+=("$rpath$dir"); done + if [ -n "$dtags_to_add" ] ; then + append args_list "$linker_arg$dtags_to_add" + fi + extend args_list rpath_dirs_list "$rpath" + extend args_list system_rpath_dirs_list "$rpath" ;; ld) - if [ -n "$dtags_to_add" ] ; then args+=("$dtags_to_add") ; fi - for dir in "${rpaths[@]}"; do args+=("-rpath" "$dir"); done - for dir in "${system_rpaths[@]}"; do args+=("-rpath" "$dir"); done + if [ -n "$dtags_to_add" ] ; then + append args_list "$dtags_to_add" + fi + extend args_list rpath_dirs_list "-rpath${lsep}" + extend args_list system_rpath_dirs_list "-rpath${lsep}" ;; esac # Other arguments from the input command -args+=("${other_args[@]}") +extend args_list other_args_list # Inject SPACK_LDLIBS, if supplied -for lib in "${libs[@]}"; do - args+=("-l$lib"); -done +extend args_list libs_list "-l" -full_command=("$command" "${args[@]}") +full_command_list="$command" +extend full_command_list args_list # prepend the ccache binary if we're using ccache if [ -n "$SPACK_CCACHE_BINARY" ]; then case "$lang_flags" in C|CXX) # ccache only supports C languages - full_command=("${SPACK_CCACHE_BINARY}" "${full_command[@]}") + prepend full_command_list "${SPACK_CCACHE_BINARY}" # workaround for stage being a temp folder # see #3761#issuecomment-294352232 export CCACHE_NOHASHDIR=yes @@ -612,25 +740,36 @@ if [ -n "$SPACK_CCACHE_BINARY" ]; then fi # dump the full command if the caller supplies SPACK_TEST_COMMAND=dump-args -if [[ $SPACK_TEST_COMMAND == dump-args ]]; then - IFS=" -" && echo "${full_command[*]}" - exit -elif [[ $SPACK_TEST_COMMAND =~ dump-env-* ]]; then - var=${SPACK_TEST_COMMAND#dump-env-} - echo "$0: $var: ${!var}" -elif [[ -n $SPACK_TEST_COMMAND ]]; then - die "ERROR: Unknown test command" +if [ -n "${SPACK_TEST_COMMAND=}" ]; then + case "$SPACK_TEST_COMMAND" in + dump-args) + IFS="$lsep" + for arg in $full_command_list; do + echo "$arg" + done + unset IFS + exit + ;; + dump-env-*) + var=${SPACK_TEST_COMMAND#dump-env-} + eval "printf '%s\n' \"\$0: \$var: \$$var\"" + ;; + *) + die "ERROR: Unknown test command: '$SPACK_TEST_COMMAND'" + ;; + esac fi # # Write the input and output commands to debug logs if it's asked for. # -if [[ $SPACK_DEBUG == TRUE ]]; then +if [ "$SPACK_DEBUG" = TRUE ]; then input_log="$SPACK_DEBUG_LOG_DIR/spack-cc-$SPACK_DEBUG_LOG_ID.in.log" output_log="$SPACK_DEBUG_LOG_DIR/spack-cc-$SPACK_DEBUG_LOG_ID.out.log" echo "[$mode] $command $input_command" >> "$input_log" - echo "[$mode] ${full_command[*]}" >> "$output_log" + echo "[$mode] ${full_command_list}" >> "$output_log" fi -exec "${full_command[@]}" +# Execute the full command, preserving spaces with IFS set +# to the alarm bell separator. +IFS="$lsep"; exec $full_command_list diff --git a/lib/spack/spack/test/cc.py b/lib/spack/spack/test/cc.py index f202dcd62d..5381782480 100644 --- a/lib/spack/spack/test/cc.py +++ b/lib/spack/spack/test/cc.py @@ -13,13 +13,13 @@ import pytest from spack.paths import build_env_path from spack.util.environment import set_env, system_dirs -from spack.util.executable import Executable +from spack.util.executable import Executable, ProcessError # # Complicated compiler test command # test_args = [ - '-I/test/include', '-L/test/lib', '-L/other/lib', '-I/other/include', + '-I/test/include', '-L/test/lib', '-L/with space/lib', '-I/other/include', 'arg1', '-Wl,--start-group', 'arg2', @@ -31,7 +31,9 @@ test_args = [ '-Xlinker', '-rpath', '-Xlinker', '/fourth/rpath', '-Wl,--rpath,/fifth/rpath', '-Wl,--rpath', '-Wl,/sixth/rpath', '-llib3', '-llib4', - 'arg5', 'arg6'] + 'arg5', 'arg6', + '"-DDOUBLE_QUOTED_ARG"', "'-DSINGLE_QUOTED_ARG'", +] # # Pieces of the test command above, as they should be parsed out. @@ -43,7 +45,7 @@ test_include_paths = [ '-I/test/include', '-I/other/include'] test_library_paths = [ - '-L/test/lib', '-L/other/lib'] + '-L/test/lib', '-L/with space/lib'] test_wl_rpaths = [ '-Wl,-rpath,/first/rpath', '-Wl,-rpath,/second/rpath', @@ -60,7 +62,9 @@ test_args_without_paths = [ '-Wl,--start-group', 'arg2', 'arg3', '-llib1', '-llib2', 'arg4', '-Wl,--end-group', - '-llib3', '-llib4', 'arg5', 'arg6'] + '-llib3', '-llib4', 'arg5', 'arg6', + '"-DDOUBLE_QUOTED_ARG"', "'-DSINGLE_QUOTED_ARG'", +] #: The prefix of the package being mock installed pkg_prefix = '/spack-test-prefix' @@ -86,6 +90,17 @@ spack_ldlibs = ['-lfoo'] lheaderpad = ['-Wl,-headerpad_max_install_names'] headerpad = ['-headerpad_max_install_names'] +target_args = ["-march=znver2", "-mtune=znver2"] + +# common compile arguments: includes, libs, -Wl linker args, other args +common_compile_args = ( + test_include_paths + + test_library_paths + + ['-Wl,--disable-new-dtags'] + + test_wl_rpaths + + test_args_without_paths +) + @pytest.fixture(scope='session') def wrapper_environment(): @@ -107,7 +122,7 @@ def wrapper_environment(): SPACK_LINK_DIRS=None, SPACK_INCLUDE_DIRS=None, SPACK_RPATH_DIRS=None, - SPACK_TARGET_ARGS='', + SPACK_TARGET_ARGS="-march=znver2 -mtune=znver2", SPACK_LINKER_ARG='-Wl,', SPACK_DTAGS_TO_ADD='--disable-new-dtags', SPACK_DTAGS_TO_STRIP='--enable-new-dtags'): @@ -126,9 +141,6 @@ def wrapper_flags(): yield -pytestmark = pytest.mark.usefixtures('wrapper_environment') - - def check_args(cc, args, expected): """Check output arguments that cc produces when called with args. @@ -149,7 +161,7 @@ def check_env_var(executable, var, expected): """ with set_env(SPACK_TEST_COMMAND='dump-env-' + var): output = executable(*test_args, output=str).strip() - assert output == executable.path + ': ' + var + ': ' + expected + assert executable.path + ': ' + var + ': ' + expected == output def dump_mode(cc, args): @@ -158,7 +170,13 @@ def dump_mode(cc, args): return cc(*args, output=str).strip() -def test_vcheck_mode(): +def test_no_wrapper_environment(): + with pytest.raises(ProcessError): + output = cc(output=str) + assert "Spack compiler must be run from Spack" in output + + +def test_vcheck_mode(wrapper_environment): assert dump_mode(cc, ['-I/include', '--version']) == 'vcheck' assert dump_mode(cc, ['-I/include', '-V']) == 'vcheck' assert dump_mode(cc, ['-I/include', '-v']) == 'vcheck' @@ -167,17 +185,17 @@ def test_vcheck_mode(): assert dump_mode(cc, ['-I/include', '-V', '-o', 'output']) == 'vcheck' -def test_cpp_mode(): +def test_cpp_mode(wrapper_environment): assert dump_mode(cc, ['-E']) == 'cpp' assert dump_mode(cxx, ['-E']) == 'cpp' assert dump_mode(cpp, []) == 'cpp' -def test_as_mode(): +def test_as_mode(wrapper_environment): assert dump_mode(cc, ['-S']) == 'as' -def test_ccld_mode(): +def test_ccld_mode(wrapper_environment): assert dump_mode(cc, []) == 'ccld' assert dump_mode(cc, ['foo.c', '-o', 'foo']) == 'ccld' assert dump_mode(cc, ['foo.c', '-o', 'foo', '-Wl,-rpath,foo']) == 'ccld' @@ -185,13 +203,13 @@ def test_ccld_mode(): 'foo.o', 'bar.o', 'baz.o', '-o', 'foo', '-Wl,-rpath,foo']) == 'ccld' -def test_ld_mode(): +def test_ld_mode(wrapper_environment): assert dump_mode(ld, []) == 'ld' assert dump_mode(ld, [ 'foo.o', 'bar.o', 'baz.o', '-o', 'foo', '-Wl,-rpath,foo']) == 'ld' -def test_ld_flags(wrapper_flags): +def test_ld_flags(wrapper_environment, wrapper_flags): check_args( ld, test_args, ['ld'] + @@ -204,7 +222,7 @@ def test_ld_flags(wrapper_flags): spack_ldlibs) -def test_cpp_flags(wrapper_flags): +def test_cpp_flags(wrapper_environment, wrapper_flags): check_args( cpp, test_args, ['cpp'] + @@ -214,69 +232,58 @@ def test_cpp_flags(wrapper_flags): test_args_without_paths) -def test_cc_flags(wrapper_flags): +def test_cc_flags(wrapper_environment, wrapper_flags): check_args( cc, test_args, [real_cc] + + target_args + spack_cppflags + spack_cflags + spack_ldflags + - test_include_paths + - test_library_paths + - ['-Wl,--disable-new-dtags'] + - test_wl_rpaths + - test_args_without_paths + + common_compile_args + spack_ldlibs) -def test_cxx_flags(wrapper_flags): +def test_cxx_flags(wrapper_environment, wrapper_flags): check_args( cxx, test_args, [real_cc] + + target_args + spack_cppflags + spack_cxxflags + spack_ldflags + - test_include_paths + - test_library_paths + - ['-Wl,--disable-new-dtags'] + - test_wl_rpaths + - test_args_without_paths + + common_compile_args + spack_ldlibs) -def test_fc_flags(wrapper_flags): +def test_fc_flags(wrapper_environment, wrapper_flags): check_args( fc, test_args, [real_cc] + + target_args + spack_fflags + spack_cppflags + spack_ldflags + - test_include_paths + - test_library_paths + - ['-Wl,--disable-new-dtags'] + - test_wl_rpaths + - test_args_without_paths + + common_compile_args + spack_ldlibs) -def test_dep_rpath(): +def test_dep_rpath(wrapper_environment): """Ensure RPATHs for root package are added.""" check_args( cc, test_args, [real_cc] + - test_include_paths + - test_library_paths + - ['-Wl,--disable-new-dtags'] + - test_wl_rpaths + - test_args_without_paths) + target_args + + common_compile_args) -def test_dep_include(): +def test_dep_include(wrapper_environment): """Ensure a single dependency include directory is added.""" with set_env(SPACK_INCLUDE_DIRS='x'): check_args( cc, test_args, [real_cc] + + target_args + test_include_paths + ['-Ix'] + test_library_paths + @@ -285,7 +292,7 @@ def test_dep_include(): test_args_without_paths) -def test_system_path_cleanup(): +def test_system_path_cleanup(wrapper_environment): """Ensure SPACK_ENV_PATH is removed from PATH, even with trailing / The compiler wrapper has to ensure that it is not called nested @@ -305,13 +312,14 @@ def test_system_path_cleanup(): check_env_var(cc, 'PATH', system_path) -def test_dep_lib(): +def test_dep_lib(wrapper_environment): """Ensure a single dependency RPATH is added.""" with set_env(SPACK_LINK_DIRS='x', SPACK_RPATH_DIRS='x'): check_args( cc, test_args, [real_cc] + + target_args + test_include_paths + test_library_paths + ['-Lx'] + @@ -321,12 +329,13 @@ def test_dep_lib(): test_args_without_paths) -def test_dep_lib_no_rpath(): +def test_dep_lib_no_rpath(wrapper_environment): """Ensure a single dependency link flag is added with no dep RPATH.""" with set_env(SPACK_LINK_DIRS='x'): check_args( cc, test_args, [real_cc] + + target_args + test_include_paths + test_library_paths + ['-Lx'] + @@ -335,12 +344,13 @@ def test_dep_lib_no_rpath(): test_args_without_paths) -def test_dep_lib_no_lib(): +def test_dep_lib_no_lib(wrapper_environment): """Ensure a single dependency RPATH is added with no -L.""" with set_env(SPACK_RPATH_DIRS='x'): check_args( cc, test_args, [real_cc] + + target_args + test_include_paths + test_library_paths + ['-Wl,--disable-new-dtags'] + @@ -349,7 +359,7 @@ def test_dep_lib_no_lib(): test_args_without_paths) -def test_ccld_deps(): +def test_ccld_deps(wrapper_environment): """Ensure all flags are added in ccld mode.""" with set_env(SPACK_INCLUDE_DIRS='xinc:yinc:zinc', SPACK_RPATH_DIRS='xlib:ylib:zlib', @@ -357,6 +367,7 @@ def test_ccld_deps(): check_args( cc, test_args, [real_cc] + + target_args + test_include_paths + ['-Ixinc', '-Iyinc', @@ -373,7 +384,7 @@ def test_ccld_deps(): test_args_without_paths) -def test_ccld_deps_isystem(): +def test_ccld_deps_isystem(wrapper_environment): """Ensure all flags are added in ccld mode. When a build uses -isystem, Spack should inject it's include paths using -isystem. Spack will insert these @@ -386,6 +397,7 @@ def test_ccld_deps_isystem(): check_args( cc, mytest_args, [real_cc] + + target_args + test_include_paths + ['-isystem', 'fooinc', '-isystem', 'xinc', @@ -403,7 +415,7 @@ def test_ccld_deps_isystem(): test_args_without_paths) -def test_cc_deps(): +def test_cc_deps(wrapper_environment): """Ensure -L and RPATHs are not added in cc mode.""" with set_env(SPACK_INCLUDE_DIRS='xinc:yinc:zinc', SPACK_RPATH_DIRS='xlib:ylib:zlib', @@ -411,6 +423,7 @@ def test_cc_deps(): check_args( cc, ['-c'] + test_args, [real_cc] + + target_args + test_include_paths + ['-Ixinc', '-Iyinc', @@ -420,7 +433,7 @@ def test_cc_deps(): test_args_without_paths) -def test_ccld_with_system_dirs(): +def test_ccld_with_system_dirs(wrapper_environment): """Ensure all flags are added in ccld mode.""" with set_env(SPACK_INCLUDE_DIRS='xinc:yinc:zinc', SPACK_RPATH_DIRS='xlib:ylib:zlib', @@ -434,6 +447,7 @@ def test_ccld_with_system_dirs(): check_args( cc, sys_path_args + test_args, [real_cc] + + target_args + test_include_paths + ['-Ixinc', '-Iyinc', @@ -455,7 +469,7 @@ def test_ccld_with_system_dirs(): test_args_without_paths) -def test_ccld_with_system_dirs_isystem(): +def test_ccld_with_system_dirs_isystem(wrapper_environment): """Ensure all flags are added in ccld mode. Ensure that includes are in the proper place when a build uses -isystem, and uses @@ -472,6 +486,7 @@ def test_ccld_with_system_dirs_isystem(): check_args( cc, sys_path_args + test_args, [real_cc] + + target_args + test_include_paths + ['-isystem', 'xinc', '-isystem', 'yinc', @@ -493,7 +508,7 @@ def test_ccld_with_system_dirs_isystem(): test_args_without_paths) -def test_ld_deps(): +def test_ld_deps(wrapper_environment): """Ensure no (extra) -I args or -Wl, are passed in ld mode.""" with set_env(SPACK_INCLUDE_DIRS='xinc:yinc:zinc', SPACK_RPATH_DIRS='xlib:ylib:zlib', @@ -514,7 +529,7 @@ def test_ld_deps(): test_args_without_paths) -def test_ld_deps_no_rpath(): +def test_ld_deps_no_rpath(wrapper_environment): """Ensure SPACK_LINK_DEPS controls -L for ld.""" with set_env(SPACK_INCLUDE_DIRS='xinc:yinc:zinc', SPACK_LINK_DIRS='xlib:ylib:zlib'): @@ -531,7 +546,7 @@ def test_ld_deps_no_rpath(): test_args_without_paths) -def test_ld_deps_no_link(): +def test_ld_deps_no_link(wrapper_environment): """Ensure SPACK_RPATH_DEPS controls -rpath for ld.""" with set_env(SPACK_INCLUDE_DIRS='xinc:yinc:zinc', SPACK_RPATH_DIRS='xlib:ylib:zlib'): @@ -548,7 +563,7 @@ def test_ld_deps_no_link(): test_args_without_paths) -def test_ld_deps_partial(): +def test_ld_deps_partial(wrapper_environment): """Make sure ld -r (partial link) is handled correctly on OS's where it doesn't accept rpaths. """ @@ -586,57 +601,45 @@ def test_ld_deps_partial(): test_args_without_paths) -def test_ccache_prepend_for_cc(): +def test_ccache_prepend_for_cc(wrapper_environment): with set_env(SPACK_CCACHE_BINARY='ccache'): os.environ['SPACK_SHORT_SPEC'] = "foo@1.2=linux-x86_64" check_args( cc, test_args, ['ccache'] + # ccache prepended in cc mode [real_cc] + - test_include_paths + - test_library_paths + - ['-Wl,--disable-new-dtags'] + - test_wl_rpaths + - test_args_without_paths) + target_args + + common_compile_args) os.environ['SPACK_SHORT_SPEC'] = "foo@1.2=darwin-x86_64" check_args( cc, test_args, ['ccache'] + # ccache prepended in cc mode [real_cc] + + target_args + lheaderpad + - test_include_paths + - test_library_paths + - ['-Wl,--disable-new-dtags'] + - test_wl_rpaths + - test_args_without_paths) + common_compile_args) -def test_no_ccache_prepend_for_fc(): +def test_no_ccache_prepend_for_fc(wrapper_environment): os.environ['SPACK_SHORT_SPEC'] = "foo@1.2=linux-x86_64" check_args( fc, test_args, # no ccache for Fortran [real_cc] + - test_include_paths + - test_library_paths + - ['-Wl,--disable-new-dtags'] + - test_wl_rpaths + - test_args_without_paths) + target_args + + common_compile_args) os.environ['SPACK_SHORT_SPEC'] = "foo@1.2=darwin-x86_64" check_args( fc, test_args, # no ccache for Fortran [real_cc] + + target_args + lheaderpad + - test_include_paths + - test_library_paths + - ['-Wl,--disable-new-dtags'] + - test_wl_rpaths + - test_args_without_paths) + common_compile_args) @pytest.mark.regression('9160') -def test_disable_new_dtags(wrapper_flags): +def test_disable_new_dtags(wrapper_environment, wrapper_flags): with set_env(SPACK_TEST_COMMAND='dump-args'): result = ld(*test_args, output=str).strip().split('\n') assert '--disable-new-dtags' in result @@ -645,7 +648,7 @@ def test_disable_new_dtags(wrapper_flags): @pytest.mark.regression('9160') -def test_filter_enable_new_dtags(wrapper_flags): +def test_filter_enable_new_dtags(wrapper_environment, wrapper_flags): with set_env(SPACK_TEST_COMMAND='dump-args'): result = ld(*(test_args + ['--enable-new-dtags']), output=str) result = result.strip().split('\n') @@ -657,7 +660,7 @@ def test_filter_enable_new_dtags(wrapper_flags): @pytest.mark.regression('22643') -def test_linker_strips_loopopt(wrapper_flags): +def test_linker_strips_loopopt(wrapper_environment, wrapper_flags): with set_env(SPACK_TEST_COMMAND='dump-args'): # ensure that -loopopt=0 is not present in ld mode result = ld(*(test_args + ["-loopopt=0"]), output=str) |