Skip to content
Snippets Groups Projects
Commit e1fdd434 authored by Todd Gamblin's avatar Todd Gamblin
Browse files

Merge branch 'eschnett-correct-cc' into develop

parents 7e7461e8 f80e839f
No related branches found
Tags v0.12.1
No related merge requests found
...@@ -65,7 +65,7 @@ function die { ...@@ -65,7 +65,7 @@ function die {
} }
for param in $parameters; do for param in $parameters; do
if [ -z "${!param}" ]; then if [[ -z ${!param} ]]; then
die "Spack compiler must be run from spack! Input $param was missing!" die "Spack compiler must be run from spack! Input $param was missing!"
fi fi
done done
...@@ -78,12 +78,17 @@ done ...@@ -78,12 +78,17 @@ done
# 'command' is set based on the input command to $SPACK_[CC|CXX|F77|F90] # 'command' is set based on the input command to $SPACK_[CC|CXX|F77|F90]
# #
# 'mode' is set to one of: # 'mode' is set to one of:
# cpp preprocess
# cc compile # cc compile
# as assemble
# ld link # ld link
# ccld compile & link # ccld compile & link
# cpp preprocessor
# vcheck version check # vcheck version check
# #
# Depending on the mode, we may or may not add extra rpaths.
# This variable controls whether they are added.
add_rpaths=true
command=$(basename "$0") command=$(basename "$0")
case "$command" in case "$command" in
cc|c89|c99|gcc|clang|icc|pgcc|xlc) cc|c89|c99|gcc|clang|icc|pgcc|xlc)
...@@ -107,13 +112,26 @@ case "$command" in ...@@ -107,13 +112,26 @@ case "$command" in
;; ;;
ld) ld)
mode=ld mode=ld
# Darwin's linker has a -r argument that merges object files
# together. It doesn't work with -rpath.
if [[ $OSTYPE = darwin* ]]; then
for arg in "$@"; do
if [ "$arg" = -r ]; then
add_rpaths=false
break
fi
done
fi
;; ;;
*) *)
die "Unkown compiler: $command" die "Unkown compiler: $command"
;; ;;
esac 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 if [ -z "$mode" ]; then
for arg in "$@"; do for arg in "$@"; do
if [ "$arg" = -v -o "$arg" = -V -o "$arg" = --version -o "$arg" = -dumpversion ]; then if [ "$arg" = -v -o "$arg" = -V -o "$arg" = --version -o "$arg" = -dumpversion ]; then
...@@ -124,13 +142,15 @@ if [ -z "$mode" ]; then ...@@ -124,13 +142,15 @@ if [ -z "$mode" ]; then
fi fi
# Finish setting up the mode. # Finish setting up the mode.
if [ -z "$mode" ]; then if [ -z "$mode" ]; then
mode=ccld mode=ccld
for arg in "$@"; do for arg in "$@"; do
if [ "$arg" = -E ]; then if [ "$arg" = -E ]; then
mode=cpp mode=cpp
break break
elif [ "$arg" = -S ]; then
mode=as
break
elif [ "$arg" = -c ]; then elif [ "$arg" = -c ]; then
mode=cc mode=cc
break break
...@@ -146,168 +166,56 @@ fi ...@@ -146,168 +166,56 @@ fi
# Check that at least one of the real commands was actually selected, # Check that at least one of the real commands was actually selected,
# otherwise we don't know what to execute. # 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." die "ERROR: Compiler '$SPACK_COMPILER_SPEC' does not support compiling $language programs."
fi fi
# Save original command for debug logging
input_command="$@"
if [ "$mode" == vcheck ] ; then if [ "$mode" == vcheck ] ; then
exec ${command} "$@" exec ${command} "$@"
fi fi
# # Save original command for debug logging
# Now do real parsing of the command line args, trying hard to keep input_command="$@"
# non-rpath linker arguments in the proper order w.r.t. other command args=("$@")
# 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
# Dump parsed values for unit testing if asked for
if [ -n "$SPACK_TEST_COMMAND" ]; then
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[*]}"
;;
*)
echo "ERROR: Unknown test command"
exit 1 ;;
esac
exit
fi
# Read spack dependencies from the path environment variable # Read spack dependencies from the path environment variable
IFS=':' read -ra deps <<< "$SPACK_DEPENDENCIES" IFS=':' read -ra deps <<< "$SPACK_DEPENDENCIES"
for dep in "${deps[@]}"; do for dep in "${deps[@]}"; do
if [ -d "$dep/include" ]; then # Prepend include directories
includes+=("$dep/include") if [[ -d $dep/include ]]; then
if [[ $mode = cpp || $mode = cc || $mode = as || $mode = ccld ]]; then
args=("-I$dep/include" "${args[@]}")
fi
fi fi
if [ -d "$dep/lib" ]; then # Prepend lib and RPATH directories
libraries+=("$dep/lib") if [[ -d $dep/lib ]]; then
rpaths+=("$dep/lib") if [[ $mode = ccld ]]; then
$add_rpaths && args=("-Wl,-rpath,$dep/lib" "${args[@]}")
args=("-L$dep/lib" "${args[@]}")
elif [[ $mode = ld ]]; then
$add_rpaths && args=("-rpath" "$dep/lib" "${args[@]}")
args=("-L$dep/lib" "${args[@]}")
fi
fi fi
if [ -d "$dep/lib64" ]; then # Prepend lib64 and RPATH directories
libraries+=("$dep/lib64") if [[ -d $dep/lib64 ]]; then
rpaths+=("$dep/lib64") if [[ $mode = ccld ]]; then
$add_rpaths && args=("-Wl,-rpath,$dep/lib64" "${args[@]}")
args=("-L$dep/lib64" "${args[@]}")
elif [[ $mode = ld ]]; then
$add_rpaths && args=("-rpath" "$dep/lib64" "${args[@]}")
args=("-L$dep/lib64" "${args[@]}")
fi
fi fi
done done
# Include all -L's and prefix/whatever dirs in rpath # Include all -L's and prefix/whatever dirs in rpath
for dir in "${libraries[@]}"; do if [[ $mode = ccld ]]; then
[[ dir = $SPACK_INSTALL* ]] && rpaths+=("$dir") $add_rpaths && args=("-Wl,-rpath,$SPACK_PREFIX/lib" "-Wl,-rpath,$SPACK_PREFIX/lib64" "${args[@]}")
done elif [[ $mode = ld ]]; then
rpaths+=("$SPACK_PREFIX/lib") $add_rpaths && args=("-rpath" "$SPACK_PREFIX/lib" "-rpath" "$SPACK_PREFIX/lib64" "${args[@]}")
rpaths+=("$SPACK_PREFIX/lib64")
# Put the arguments together
args=()
for dir in "${includes[@]}"; do args+=("-I$dir"); done
args+=("${other_args[@]}")
for dir in "${libraries[@]}"; do args+=("-L$dir"); done
for lib in "${libs[@]}"; do args+=("-l$lib"); done
if [ "$mode" = ccld ]; then
for dir in "${rpaths[@]}"; do
args+=("-Wl,-rpath")
args+=("-Wl,$dir");
done
elif [ "$mode" = ld ]; then
for dir in "${rpaths[@]}"; do
args+=("-rpath")
args+=("$dir");
done
fi fi
# #
...@@ -323,34 +231,37 @@ unset DYLD_LIBRARY_PATH ...@@ -323,34 +231,37 @@ unset DYLD_LIBRARY_PATH
# #
IFS=':' read -ra env_path <<< "$PATH" IFS=':' read -ra env_path <<< "$PATH"
IFS=':' read -ra spack_env_dirs <<< "$SPACK_ENV_PATH" IFS=':' read -ra spack_env_dirs <<< "$SPACK_ENV_PATH"
spack_env_dirs+=(".") spack_env_dirs+=("" ".")
PATH="" PATH=""
for dir in "${env_path[@]}"; do for dir in "${env_path[@]}"; do
remove="" remove=""
for rm_dir in "${spack_env_dirs[@]}"; do for rm_dir in "${spack_env_dirs[@]}"; do
if [ "$dir" = "$rm_dir" ]; then remove=True; fi if [[ $dir = $rm_dir ]]; then remove=True; fi
done done
if [ -z "$remove" ]; then if [[ -z $remove ]]; then
if [ -z "$PATH" ]; then PATH="${PATH:+$PATH:}$dir"
PATH="$dir"
else
PATH="$PATH:$dir"
fi
fi fi
done done
export PATH export PATH
full_command=("$command") full_command=("$command" "${args[@]}")
full_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. # 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_SHORT_SPEC.in.log" input_log="$SPACK_DEBUG_LOG_DIR/spack-cc-$SPACK_SHORT_SPEC.in.log"
output_log="$SPACK_DEBUG_LOG_DIR/spack-cc-$SPACK_SHORT_SPEC.out.log" output_log="$SPACK_DEBUG_LOG_DIR/spack-cc-$SPACK_SHORT_SPEC.out.log"
echo "$input_command" >> $input_log echo "[$mode] $command $input_command" >> $input_log
echo "$mode ${full_command[@]}" >> $output_log echo "[$mode] ${full_command[@]}" >> $output_log
fi fi
exec "${full_command[@]}" exec "${full_command[@]}"
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
""" """
import os import os
import unittest import unittest
import tempfile
import shutil
from llnl.util.filesystem import * from llnl.util.filesystem import *
import spack import spack
...@@ -55,13 +57,40 @@ def setUp(self): ...@@ -55,13 +57,40 @@ def setUp(self):
self.ld = Executable(join_path(spack.build_env_path, "ld")) self.ld = Executable(join_path(spack.build_env_path, "ld"))
self.cpp = Executable(join_path(spack.build_env_path, "cpp")) self.cpp = Executable(join_path(spack.build_env_path, "cpp"))
os.environ['SPACK_CC'] = "/bin/mycc" self.realcc = "/bin/mycc"
os.environ['SPACK_PREFIX'] = "/usr" 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_ENV_PATH']="test"
os.environ['SPACK_DEBUG_LOG_DIR'] = "." os.environ['SPACK_DEBUG_LOG_DIR'] = "."
os.environ['SPACK_COMPILER_SPEC'] = "gcc@4.4.7" os.environ['SPACK_COMPILER_SPEC'] = "gcc@4.4.7"
os.environ['SPACK_SHORT_SPEC'] = "foo@1.2" 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): def check_cc(self, command, args, expected):
os.environ['SPACK_TEST_COMMAND'] = command os.environ['SPACK_TEST_COMMAND'] = command
...@@ -92,6 +121,10 @@ def test_cpp_mode(self): ...@@ -92,6 +121,10 @@ def test_cpp_mode(self):
self.check_cpp('dump-mode', [], "cpp") self.check_cpp('dump-mode', [], "cpp")
def test_as_mode(self):
self.check_cc('dump-mode', ['-S'], "as")
def test_ccld_mode(self): def test_ccld_mode(self):
self.check_cc('dump-mode', [], "ccld") self.check_cc('dump-mode', [], "ccld")
self.check_cc('dump-mode', ['foo.c', '-o', 'foo'], "ccld") self.check_cc('dump-mode', ['foo.c', '-o', 'foo'], "ccld")
...@@ -104,27 +137,85 @@ def test_ld_mode(self): ...@@ -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") self.check_ld('dump-mode', ['foo.o', 'bar.o', 'baz.o', '-o', 'foo', '-Wl,-rpath,foo'], "ld")
def test_includes(self): def test_dep_rpath(self):
self.check_cc('dump-includes', test_command, """Ensure RPATHs for root package are added."""
"\n".join(["/test/include", "/other/include"])) self.check_cc('dump-args', test_command,
self.realcc + ' ' +
'-Wl,-rpath,' + self.prefix + '/lib ' +
'-Wl,-rpath,' + self.prefix + '/lib64 ' +
' '.join(test_command))
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_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_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_libraries(self): def test_ld_deps(self):
self.check_cc('dump-libraries', test_command, """Ensure no (extra) -I args or -Wl, are passed in ld mode."""
"\n".join(["/test/lib", "/other/lib"])) 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 ' +
def test_libs(self): '-L' + self.dep3 + '/lib64 ' +
self.check_cc('dump-libs', test_command, '-rpath ' + self.dep3 + '/lib64 ' +
"\n".join(["lib1", "lib2", "lib3", "lib4"]))
'-L' + self.dep2 + '/lib64 ' +
'-rpath ' + self.dep2 + '/lib64 ' +
def test_rpaths(self): '-L' + self.dep1 + '/lib ' +
self.check_cc('dump-rpaths', test_command, '-rpath ' + self.dep1 + '/lib ' +
"\n".join(["/first/rpath", "/second/rpath", "/third/rpath", "/fourth/rpath"]))
' '.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"]))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment