Simplify cc: Remove old logic and add better tests.
- removed a lot of old logic that was only still needed for tests. - Added better unit tests for dependency RPATH, -L, and -I args - tests now check whether the compiler omits -I args in link mode.
This commit is contained in:
parent
f3dd889d44
commit
d8579a5b80
2 changed files with 123 additions and 142 deletions
138
lib/spack/env/cc
vendored
138
lib/spack/env/cc
vendored
|
@ -114,7 +114,9 @@ case "$command" in
|
|||
;;
|
||||
esac
|
||||
|
||||
# If any of the arguments below is present then the mode is vcheck. In vcheck mode nothing is added in terms of extra search paths or libraries
|
||||
# If any of the arguments below is present then the mode is vcheck. In
|
||||
# vcheck mode nothing is added in terms of extra search paths or
|
||||
# libraries
|
||||
if [ -z "$mode" ]; then
|
||||
for arg in "$@"; do
|
||||
if [ "$arg" = -v -o "$arg" = -V -o "$arg" = --version -o "$arg" = -dumpversion ]; then
|
||||
|
@ -125,7 +127,6 @@ if [ -z "$mode" ]; then
|
|||
fi
|
||||
|
||||
# Finish setting up the mode.
|
||||
|
||||
if [ -z "$mode" ]; then
|
||||
mode=ccld
|
||||
for arg in "$@"; do
|
||||
|
@ -162,127 +163,18 @@ fi
|
|||
input_command="$@"
|
||||
args=("$@")
|
||||
|
||||
# Dump parsed values for unit testing if asked for
|
||||
if [[ -n $SPACK_TEST_COMMAND ]]; then
|
||||
|
||||
#
|
||||
# Now do real parsing of the command line args, trying hard to keep
|
||||
# non-rpath linker arguments in the proper order w.r.t. other command line
|
||||
# arguments. This is important for things like groups.
|
||||
#
|
||||
includes=()
|
||||
libraries=()
|
||||
libs=()
|
||||
rpaths=()
|
||||
other_args=()
|
||||
|
||||
while [ -n "$1" ]; do
|
||||
case "$1" in
|
||||
-I*)
|
||||
arg="${1#-I}"
|
||||
if [ -z "$arg" ]; then shift; arg="$1"; fi
|
||||
includes+=("$arg")
|
||||
;;
|
||||
-L*)
|
||||
arg="${1#-L}"
|
||||
if [ -z "$arg" ]; then shift; arg="$1"; fi
|
||||
libraries+=("$arg")
|
||||
;;
|
||||
-l*)
|
||||
arg="${1#-l}"
|
||||
if [ -z "$arg" ]; then shift; arg="$1"; fi
|
||||
libs+=("$arg")
|
||||
;;
|
||||
-Wl,*)
|
||||
arg="${1#-Wl,}"
|
||||
# TODO: Handle multiple -Wl, continuations of -Wl,-rpath
|
||||
if [[ $arg == -rpath=* ]]; then
|
||||
arg="${arg#-rpath=}"
|
||||
for rpath in ${arg//,/ }; do
|
||||
rpaths+=("$rpath")
|
||||
done
|
||||
elif [[ $arg == -rpath,* ]]; then
|
||||
arg="${arg#-rpath,}"
|
||||
for rpath in ${arg//,/ }; do
|
||||
rpaths+=("$rpath")
|
||||
done
|
||||
elif [[ $arg == -rpath ]]; then
|
||||
shift; arg="$1"
|
||||
if [[ $arg != '-Wl,'* ]]; then
|
||||
die "-Wl,-rpath was not followed by -Wl,*"
|
||||
fi
|
||||
arg="${arg#-Wl,}"
|
||||
for rpath in ${arg//,/ }; do
|
||||
rpaths+=("$rpath")
|
||||
done
|
||||
else
|
||||
other_args+=("-Wl,$arg")
|
||||
fi
|
||||
;;
|
||||
-Xlinker)
|
||||
shift; arg="$1";
|
||||
if [[ $arg = -rpath=* ]]; then
|
||||
rpaths+=("${arg#-rpath=}")
|
||||
elif [[ $arg = -rpath ]]; then
|
||||
shift; arg="$1"
|
||||
if [[ $arg != -Xlinker ]]; then
|
||||
die "-Xlinker -rpath was not followed by -Xlinker <arg>"
|
||||
fi
|
||||
shift; arg="$1"
|
||||
rpaths+=("$arg")
|
||||
else
|
||||
other_args+=("-Xlinker")
|
||||
other_args+=("$arg")
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
other_args+=("$1")
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
IFS=$'\n'
|
||||
case "$SPACK_TEST_COMMAND" in
|
||||
dump-includes) echo "${includes[*]}";;
|
||||
dump-libraries) echo "${libraries[*]}";;
|
||||
dump-libs) echo "${libs[*]}";;
|
||||
dump-rpaths) echo "${rpaths[*]}";;
|
||||
dump-other-args) echo "${other_args[*]}";;
|
||||
dump-all)
|
||||
echo "INCLUDES:"
|
||||
echo "${includes[*]}"
|
||||
echo
|
||||
echo "LIBRARIES:"
|
||||
echo "${libraries[*]}"
|
||||
echo
|
||||
echo "LIBS:"
|
||||
echo "${libs[*]}"
|
||||
echo
|
||||
echo "RPATHS:"
|
||||
echo "${rpaths[*]}"
|
||||
echo
|
||||
echo "ARGS:"
|
||||
echo "${other_args[*]}"
|
||||
;;
|
||||
*)
|
||||
die "ERROR: Unknown test command"
|
||||
;;
|
||||
esac
|
||||
exit
|
||||
fi
|
||||
|
||||
# Read spack dependencies from the path environment variable
|
||||
IFS=':' read -ra deps <<< "$SPACK_DEPENDENCIES"
|
||||
for dep in "${deps[@]}"; do
|
||||
# Prepend include directories
|
||||
if [[ -d $dep/include ]]; then
|
||||
if [[ $mode = cpp || $mode = cc || $mode = as || $mode = ccld ]]; then
|
||||
args=("-I$dep/include" "${args[@]}")
|
||||
fi
|
||||
fi
|
||||
|
||||
# Prepend lib and RPATH directories
|
||||
if [[ -d $dep/lib ]]; then
|
||||
# libraries+=("$dep/lib")
|
||||
if [[ $mode = ccld ]]; then
|
||||
args=("-L$dep/lib" "-Wl,-rpath,$dep/lib" "${args[@]}")
|
||||
elif [[ $mode = ld ]]; then
|
||||
|
@ -290,8 +182,8 @@ for dep in "${deps[@]}"; do
|
|||
fi
|
||||
fi
|
||||
|
||||
# Prepend lib64 and RPATH directories
|
||||
if [[ -d $dep/lib64 ]]; then
|
||||
# libraries+=("$dep/lib64")
|
||||
if [[ $mode = ccld ]]; then
|
||||
args=("-L$dep/lib64" "-Wl,-rpath,$dep/lib64" "${args[@]}")
|
||||
elif [[ $mode = ld ]]; then
|
||||
|
@ -302,18 +194,8 @@ done
|
|||
|
||||
# Include all -L's and prefix/whatever dirs in rpath
|
||||
if [[ $mode = ccld ]]; then
|
||||
# for dir in "${libraries[@]}"; do
|
||||
# if [[ dir = $SPACK_INSTALL* ]]; then
|
||||
# args=("-Wl,-rpath,$dir" "${args[@]}")
|
||||
# fi
|
||||
# done
|
||||
args=("-Wl,-rpath,$SPACK_PREFIX/lib" "-Wl,-rpath,$SPACK_PREFIX/lib64" "${args[@]}")
|
||||
elif [[ $mode = ld ]]; then
|
||||
# for dir in "${libraries[@]}"; do
|
||||
# if [[ dir = $SPACK_INSTALL* ]]; then
|
||||
# args=("-rpath" "$dir" "${args[@]}")
|
||||
# fi
|
||||
# done
|
||||
args=("-rpath" "$SPACK_PREFIX/lib" "-rpath" "$SPACK_PREFIX/lib64" "${args[@]}")
|
||||
fi
|
||||
|
||||
|
@ -345,6 +227,14 @@ export PATH
|
|||
|
||||
full_command=("$command" "${args[@]}")
|
||||
|
||||
# In test command mode, write out full command for Spack tests.
|
||||
if [[ $SPACK_TEST_COMMAND = dump-args ]]; then
|
||||
echo "${full_command[@]}"
|
||||
exit
|
||||
elif [[ -n $SPACK_TEST_COMMAND ]]; then
|
||||
die "ERROR: Unknown test command"
|
||||
fi
|
||||
|
||||
#
|
||||
# Write the input and output commands to debug logs if it's asked for.
|
||||
#
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
"""
|
||||
import os
|
||||
import unittest
|
||||
import tempfile
|
||||
import shutil
|
||||
|
||||
from llnl.util.filesystem import *
|
||||
import spack
|
||||
|
@ -55,13 +57,40 @@ def setUp(self):
|
|||
self.ld = Executable(join_path(spack.build_env_path, "ld"))
|
||||
self.cpp = Executable(join_path(spack.build_env_path, "cpp"))
|
||||
|
||||
os.environ['SPACK_CC'] = "/bin/mycc"
|
||||
os.environ['SPACK_PREFIX'] = "/usr"
|
||||
self.realcc = "/bin/mycc"
|
||||
self.prefix = "/spack-test-prefix"
|
||||
|
||||
os.environ['SPACK_CC'] = self.realcc
|
||||
os.environ['SPACK_PREFIX'] = self.prefix
|
||||
os.environ['SPACK_ENV_PATH']="test"
|
||||
os.environ['SPACK_DEBUG_LOG_DIR'] = "."
|
||||
os.environ['SPACK_COMPILER_SPEC'] = "gcc@4.4.7"
|
||||
os.environ['SPACK_SHORT_SPEC'] = "foo@1.2"
|
||||
|
||||
# Make some fake dependencies
|
||||
self.tmp_deps = tempfile.mkdtemp()
|
||||
self.dep1 = join_path(self.tmp_deps, 'dep1')
|
||||
self.dep2 = join_path(self.tmp_deps, 'dep2')
|
||||
self.dep3 = join_path(self.tmp_deps, 'dep3')
|
||||
self.dep4 = join_path(self.tmp_deps, 'dep4')
|
||||
|
||||
mkdirp(join_path(self.dep1, 'include'))
|
||||
mkdirp(join_path(self.dep1, 'lib'))
|
||||
|
||||
mkdirp(join_path(self.dep2, 'lib64'))
|
||||
|
||||
mkdirp(join_path(self.dep3, 'include'))
|
||||
mkdirp(join_path(self.dep3, 'lib64'))
|
||||
|
||||
mkdirp(join_path(self.dep4, 'include'))
|
||||
|
||||
if 'SPACK_DEPENDENCIES' in os.environ:
|
||||
del os.environ['SPACK_DEPENDENCIES']
|
||||
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.tmp_deps, True)
|
||||
|
||||
|
||||
def check_cc(self, command, args, expected):
|
||||
os.environ['SPACK_TEST_COMMAND'] = command
|
||||
|
@ -92,6 +121,10 @@ def test_cpp_mode(self):
|
|||
self.check_cpp('dump-mode', [], "cpp")
|
||||
|
||||
|
||||
def test_as_mode(self):
|
||||
self.check_cc('dump-mode', ['-S'], "as")
|
||||
|
||||
|
||||
def test_ccld_mode(self):
|
||||
self.check_cc('dump-mode', [], "ccld")
|
||||
self.check_cc('dump-mode', ['foo.c', '-o', 'foo'], "ccld")
|
||||
|
@ -104,27 +137,85 @@ def test_ld_mode(self):
|
|||
self.check_ld('dump-mode', ['foo.o', 'bar.o', 'baz.o', '-o', 'foo', '-Wl,-rpath,foo'], "ld")
|
||||
|
||||
|
||||
def test_includes(self):
|
||||
self.check_cc('dump-includes', test_command,
|
||||
"\n".join(["/test/include", "/other/include"]))
|
||||
def test_dep_rpath(self):
|
||||
"""Ensure RPATHs for root package are added."""
|
||||
self.check_cc('dump-args', test_command,
|
||||
self.realcc + ' ' +
|
||||
'-Wl,-rpath,' + self.prefix + '/lib ' +
|
||||
'-Wl,-rpath,' + self.prefix + '/lib64 ' +
|
||||
' '.join(test_command))
|
||||
|
||||
|
||||
def test_libraries(self):
|
||||
self.check_cc('dump-libraries', test_command,
|
||||
"\n".join(["/test/lib", "/other/lib"]))
|
||||
def test_dep_include(self):
|
||||
"""Ensure a single dependency include directory is added."""
|
||||
os.environ['SPACK_DEPENDENCIES'] = self.dep4
|
||||
self.check_cc('dump-args', test_command,
|
||||
self.realcc + ' ' +
|
||||
'-Wl,-rpath,' + self.prefix + '/lib ' +
|
||||
'-Wl,-rpath,' + self.prefix + '/lib64 ' +
|
||||
'-I' + self.dep4 + '/include ' +
|
||||
' '.join(test_command))
|
||||
|
||||
|
||||
def test_libs(self):
|
||||
self.check_cc('dump-libs', test_command,
|
||||
"\n".join(["lib1", "lib2", "lib3", "lib4"]))
|
||||
def test_dep_lib(self):
|
||||
"""Ensure a single dependency RPATH is added."""
|
||||
os.environ['SPACK_DEPENDENCIES'] = self.dep2
|
||||
self.check_cc('dump-args', test_command,
|
||||
self.realcc + ' ' +
|
||||
'-Wl,-rpath,' + self.prefix + '/lib ' +
|
||||
'-Wl,-rpath,' + self.prefix + '/lib64 ' +
|
||||
'-L' + self.dep2 + '/lib64 ' +
|
||||
'-Wl,-rpath,' + self.dep2 + '/lib64 ' +
|
||||
' '.join(test_command))
|
||||
|
||||
|
||||
def test_rpaths(self):
|
||||
self.check_cc('dump-rpaths', test_command,
|
||||
"\n".join(["/first/rpath", "/second/rpath", "/third/rpath", "/fourth/rpath"]))
|
||||
def test_all_deps(self):
|
||||
"""Ensure includes and RPATHs for all deps are added. """
|
||||
os.environ['SPACK_DEPENDENCIES'] = ':'.join([
|
||||
self.dep1, self.dep2, self.dep3, self.dep4])
|
||||
|
||||
# This is probably more constrained than it needs to be; it
|
||||
# checks order within prepended args and doesn't strictly have
|
||||
# to. We could loosen that if it becomes necessary
|
||||
self.check_cc('dump-args', test_command,
|
||||
self.realcc + ' ' +
|
||||
'-Wl,-rpath,' + self.prefix + '/lib ' +
|
||||
'-Wl,-rpath,' + self.prefix + '/lib64 ' +
|
||||
|
||||
'-I' + self.dep4 + '/include ' +
|
||||
|
||||
'-L' + self.dep3 + '/lib64 ' +
|
||||
'-Wl,-rpath,' + self.dep3 + '/lib64 ' +
|
||||
'-I' + self.dep3 + '/include ' +
|
||||
|
||||
'-L' + self.dep2 + '/lib64 ' +
|
||||
'-Wl,-rpath,' + self.dep2 + '/lib64 ' +
|
||||
|
||||
'-L' + self.dep1 + '/lib ' +
|
||||
'-Wl,-rpath,' + self.dep1 + '/lib ' +
|
||||
'-I' + self.dep1 + '/include ' +
|
||||
|
||||
' '.join(test_command))
|
||||
|
||||
|
||||
def test_other_args(self):
|
||||
self.check_cc('dump-other-args', test_command,
|
||||
"\n".join(["arg1", "-Wl,--start-group", "arg2", "arg3", "arg4",
|
||||
"-Wl,--end-group", "arg5", "arg6"]))
|
||||
def test_ld_deps(self):
|
||||
"""Ensure no (extra) -I args or -Wl, are passed in ld mode."""
|
||||
os.environ['SPACK_DEPENDENCIES'] = ':'.join([
|
||||
self.dep1, self.dep2, self.dep3, self.dep4])
|
||||
|
||||
self.check_ld('dump-args', test_command,
|
||||
'ld ' +
|
||||
'-rpath ' + self.prefix + '/lib ' +
|
||||
'-rpath ' + self.prefix + '/lib64 ' +
|
||||
|
||||
'-L' + self.dep3 + '/lib64 ' +
|
||||
'-rpath ' + self.dep3 + '/lib64 ' +
|
||||
|
||||
'-L' + self.dep2 + '/lib64 ' +
|
||||
'-rpath ' + self.dep2 + '/lib64 ' +
|
||||
|
||||
'-L' + self.dep1 + '/lib ' +
|
||||
'-rpath ' + self.dep1 + '/lib ' +
|
||||
|
||||
' '.join(test_command))
|
||||
|
||||
|
|
Loading…
Reference in a new issue