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:
parent
14465e61ae
commit
46bbce1922
2 changed files with 123 additions and 35 deletions
111
lib/spack/env/cc
vendored
111
lib/spack/env/cc
vendored
|
@ -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.
|
||||||
|
append other_args_list -Xlinker
|
||||||
|
xlinker_expect_rpath=no
|
||||||
|
break
|
||||||
|
elif [ "$xlinker_expect_rpath" = yes ]; then
|
||||||
|
# Register the path of -Xlinker -rpath <other args> -Xlinker <path>
|
||||||
|
if system_dir "$1"; then
|
||||||
|
append system_rpath_dirs_list "$1"
|
||||||
|
else
|
||||||
|
append rpath_dirs_list "$1"
|
||||||
fi
|
fi
|
||||||
shift 3;
|
xlinker_expect_rpath=no
|
||||||
rp="$1"
|
|
||||||
elif [ "$2" = "$dtags_to_strip" ]; then
|
|
||||||
shift # We want to remove explicitly this flag
|
|
||||||
else
|
else
|
||||||
append other_args_list "$1"
|
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")
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
append other_args_list -Xlinker
|
||||||
|
append other_args_list "$1"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
"$dtags_to_strip")
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
if [ "$1" = "$dtags_to_strip" ]; then
|
append other_args_list "$1"
|
||||||
: # We want to remove explicitly this flag
|
|
||||||
else
|
|
||||||
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
|
|
||||||
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.
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue