compiler wrapper: fix -Xlinker parsing (#35929)

* compiler wrapper: fix -Xlinker parsing
* handle the case of -rpath without value; avoid that we drop the flag
* also handle the -Xlinker -rpath -Xlinker without further args case...
* fix test
* get rid of global $rp var, reduce branching
This commit is contained in:
Harmen Stoppels 2023-03-31 18:47:24 +02:00 committed by GitHub
parent 14465e61ae
commit 46bbce1922
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 123 additions and 35 deletions

109
lib/spack/env/cc vendored
View file

@ -430,21 +430,37 @@ other_args_list=""
# Global state for keeping track of -Wl,-rpath -Wl,/path # Global state for keeping track of -Wl,-rpath -Wl,/path
wl_expect_rpath=no wl_expect_rpath=no
# Same, but for -Xlinker -rpath -Xlinker /path
xlinker_expect_rpath=no
parse_Wl() { parse_Wl() {
# drop -Wl # drop -Wl
shift shift
while [ $# -ne 0 ]; do while [ $# -ne 0 ]; do
if [ "$wl_expect_rpath" = yes ]; then if [ "$wl_expect_rpath" = yes ]; then
rp="$1" if system_dir "$1"; then
append system_rpath_dirs_list "$1"
else
append rpath_dirs_list "$1"
fi
wl_expect_rpath=no wl_expect_rpath=no
else else
rp=""
case "$1" in case "$1" in
-rpath=*) -rpath=*)
rp="${1#-rpath=}" arg="${1#-rpath=}"
if system_dir "$arg"; then
append system_rpath_dirs_list "$arg"
else
append rpath_dirs_list "$arg"
fi
;; ;;
--rpath=*) --rpath=*)
rp="${1#--rpath=}" arg="${1#--rpath=}"
if system_dir "$arg"; then
append system_rpath_dirs_list "$arg"
else
append rpath_dirs_list "$arg"
fi
;; ;;
-rpath|--rpath) -rpath|--rpath)
wl_expect_rpath=yes wl_expect_rpath=yes
@ -456,17 +472,8 @@ parse_Wl() {
;; ;;
esac esac
fi fi
if [ -n "$rp" ]; then
if system_dir "$rp"; then
append system_rpath_dirs_list "$rp"
else
append rpath_dirs_list "$rp"
fi
fi
shift shift
done done
# By lack of local variables, always set this to empty string.
rp=""
} }
@ -573,38 +580,72 @@ while [ $# -ne 0 ]; do
unset IFS unset IFS
;; ;;
-Xlinker) -Xlinker)
if [ "$2" = "-rpath" ]; then shift
if [ "$3" != "-Xlinker" ]; then if [ $# -eq 0 ]; then
die "-Xlinker,-rpath was not followed by -Xlinker,*" # -Xlinker without value: let the compiler error about it.
fi append other_args_list -Xlinker
shift 3; xlinker_expect_rpath=no
rp="$1" break
elif [ "$2" = "$dtags_to_strip" ]; then elif [ "$xlinker_expect_rpath" = yes ]; then
shift # We want to remove explicitly this flag # Register the path of -Xlinker -rpath <other args> -Xlinker <path>
if system_dir "$1"; then
append system_rpath_dirs_list "$1"
else else
append other_args_list "$1" append rpath_dirs_list "$1"
fi fi
xlinker_expect_rpath=no
else
case "$1" in
-rpath=*)
arg="${1#-rpath=}"
if system_dir "$arg"; then
append system_rpath_dirs_list "$arg"
else
append rpath_dirs_list "$arg"
fi
;;
--rpath=*)
arg="${1#--rpath=}"
if system_dir "$arg"; then
append system_rpath_dirs_list "$arg"
else
append rpath_dirs_list "$arg"
fi
;;
-rpath|--rpath)
xlinker_expect_rpath=yes
;;
"$dtags_to_strip")
;; ;;
*) *)
if [ "$1" = "$dtags_to_strip" ]; then append other_args_list -Xlinker
: # We want to remove explicitly this flag
else
append other_args_list "$1" append other_args_list "$1"
fi
;; ;;
esac esac
# test rpaths against system directories in one place.
if [ -n "$rp" ]; then
if system_dir "$rp"; then
append system_rpath_dirs_list "$rp"
else
append rpath_dirs_list "$rp"
fi
fi fi
;;
"$dtags_to_strip")
;;
*)
append other_args_list "$1"
;;
esac
shift shift
done done
# We found `-Xlinker -rpath` but no matching value `-Xlinker /path`. Just append
# `-Xlinker -rpath` again and let the compiler or linker handle the error during arg
# parsing.
if [ "$xlinker_expect_rpath" = yes ]; then
append other_args_list -Xlinker
append other_args_list -rpath
fi
# Same, but for -Wl flags.
if [ "$wl_expect_rpath" = yes ]; then
append other_args_list -Wl,-rpath
fi
# #
# Add flags from Spack's cppflags, cflags, cxxflags, fcflags, fflags, and # Add flags from Spack's cppflags, cflags, cxxflags, fcflags, fflags, and
# ldflags. We stick to the order that gmake puts the flags in by default. # ldflags. We stick to the order that gmake puts the flags in by default.

View file

@ -352,6 +352,53 @@ def test_Wl_parsing(wrapper_environment):
) )
def test_Xlinker_parsing(wrapper_environment):
# -Xlinker <x> ... -Xlinker <y> may have compiler flags inbetween, like -O3 in this
# example. Also check that a trailing -Xlinker (which is a compiler error) is not
# dropped or given an empty argument.
check_args(
cc,
[
"-Xlinker",
"-rpath",
"-O3",
"-Xlinker",
"/a",
"-Xlinker",
"--flag",
"-Xlinker",
"-rpath=/b",
"-Xlinker",
],
[real_cc]
+ target_args
+ [
"-Wl,--disable-new-dtags",
"-Wl,-rpath,/a",
"-Wl,-rpath,/b",
"-O3",
"-Xlinker",
"--flag",
"-Xlinker",
],
)
def test_rpath_without_value(wrapper_environment):
# cc -Wl,-rpath without a value shouldn't drop -Wl,-rpath;
# same for -Xlinker
check_args(
cc,
["-Wl,-rpath", "-O3", "-g"],
[real_cc] + target_args + ["-Wl,--disable-new-dtags", "-O3", "-g", "-Wl,-rpath"],
)
check_args(
cc,
["-Xlinker", "-rpath", "-O3", "-g"],
[real_cc] + target_args + ["-Wl,--disable-new-dtags", "-O3", "-g", "-Xlinker", "-rpath"],
)
def test_dep_rpath(wrapper_environment): def test_dep_rpath(wrapper_environment):
"""Ensure RPATHs for root package are added.""" """Ensure RPATHs for root package are added."""
check_args(cc, test_args, [real_cc] + target_args + common_compile_args) check_args(cc, test_args, [real_cc] + target_args + common_compile_args)