compiler wrappers: don't override -isystem with -I (#16077)

If the Spack compiler wrapper encounters any "-isystem" option, then
when adding include directories for Spack dependencies, Spack will
use "-isystem" instead of "-I". This prevents Spack-generated "-I"
options from overriding the "-isystem" options generated by the build
system. To ensure that build-system "-isystem" directories are
searched first, Spack places all of its inserted "-isystem"
directories after.

The new ordering of -isystem includes is:

* -isystem from build system (not system directories)
* -isystem from Spack
* -isystem from build system (for directories like /usr/include)

The prior order of "-I" arguments is preserved (although as of this
commit Spack no longer generates -I if -isystem is detected):

* -I from build system (not system directories)
* -I from Spack (only if there are no "-isystem" options)
* -I from build system (for directories like /usr/include)
This commit is contained in:
Andrew W Elble 2020-04-21 16:56:50 -04:00 committed by GitHub
parent 74c159b883
commit f1050c4be2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 102 additions and 14 deletions

44
lib/spack/env/cc vendored
View file

@ -15,7 +15,7 @@
# 1. It allows Spack to swap compilers into and out of builds easily. # 1. It allows Spack to swap compilers into and out of builds easily.
# 2. It adds several options to the compile line so that spack # 2. It adds several options to the compile line so that spack
# packages can find their dependencies at build time and run time: # packages can find their dependencies at build time and run time:
# -I arguments for dependency /include directories. # -I and/or -isystem arguments for dependency /include directories.
# -L arguments for dependency /lib directories. # -L arguments for dependency /lib directories.
# -Wl,-rpath arguments for dependency /lib directories. # -Wl,-rpath arguments for dependency /lib directories.
# #
@ -251,10 +251,11 @@ input_command="$*"
# #
# Parse the command line arguments. # Parse the command line arguments.
# #
# We extract -L, -I, and -Wl,-rpath arguments from the command line and # We extract -L, -I, -isystem and -Wl,-rpath arguments from the
# recombine them with Spack arguments later. We parse these out so that # command line and recombine them with Spack arguments later. We
# we can make sure that system paths come last, that package arguments # parse these out so that we can make sure that system paths come
# come first, and that Spack arguments are injected properly. # last, that package arguments come first, and that Spack arguments
# are injected properly.
# #
# All other arguments, including -l arguments, are treated as # All other arguments, including -l arguments, are treated as
# 'other_args' and left in their original order. This ensures that # 'other_args' and left in their original order. This ensures that
@ -273,12 +274,24 @@ system_libdirs=()
system_rpaths=() system_rpaths=()
libs=() libs=()
other_args=() other_args=()
isystem_system_includes=()
isystem_includes=()
while [ -n "$1" ]; do while [ -n "$1" ]; do
# an RPATH to be added after the case statement. # an RPATH to be added after the case statement.
rp="" rp=""
case "$1" in case "$1" in
-isystem*)
arg="${1#-isystem}"
isystem_was_used=true
if [ -z "$arg" ]; then shift; arg="$1"; fi
if system_dir "$arg"; then
isystem_system_includes+=("$arg")
else
isystem_includes+=("$arg")
fi
;;
-I*) -I*)
arg="${1#-I}" arg="${1#-I}"
if [ -z "$arg" ]; then shift; arg="$1"; fi if [ -z "$arg" ]; then shift; arg="$1"; fi
@ -425,12 +438,6 @@ then
esac esac
fi fi
# Prepend include directories
IFS=':' read -ra include_dirs <<< "$SPACK_INCLUDE_DIRS"
if [[ $mode == cpp || $mode == cc || $mode == as || $mode == ccld ]]; then
includes=("${includes[@]}" "${include_dirs[@]}")
fi
IFS=':' read -ra rpath_dirs <<< "$SPACK_RPATH_DIRS" IFS=':' read -ra rpath_dirs <<< "$SPACK_RPATH_DIRS"
if [[ $mode == ccld || $mode == ld ]]; then if [[ $mode == ccld || $mode == ld ]]; then
@ -481,9 +488,22 @@ args=()
# flags assembled earlier # flags assembled earlier
args+=("${flags[@]}") args+=("${flags[@]}")
# include directory search paths # Insert include directories just prior to any system include directories
for dir in "${includes[@]}"; do args+=("-I$dir"); done 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
for dir in "${system_includes[@]}"; do args+=("-I$dir"); done for dir in "${system_includes[@]}"; do args+=("-I$dir"); done
for dir in "${isystem_system_includes[@]}"; do args+=("-isystem$dir"); done
# Library search paths # Library search paths
for dir in "${libdirs[@]}"; do args+=("-L$dir"); done for dir in "${libdirs[@]}"; do args+=("-L$dir"); done

View file

@ -338,6 +338,36 @@ def test_ccld_deps():
test_args_without_paths) test_args_without_paths)
def test_ccld_deps_isystem():
"""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
after any provided -isystem includes, but before any
system directories included using -isystem"""
with set_env(SPACK_INCLUDE_DIRS='xinc:yinc:zinc',
SPACK_RPATH_DIRS='xlib:ylib:zlib',
SPACK_LINK_DIRS='xlib:ylib:zlib'):
mytest_args = test_args + ['-isystemfooinc']
check_args(
cc, mytest_args,
[real_cc] +
test_include_paths +
['-isystemfooinc',
'-isystemxinc',
'-isystemyinc',
'-isystemzinc'] +
test_library_paths +
['-Lxlib',
'-Lylib',
'-Lzlib'] +
['-Wl,--disable-new-dtags'] +
test_wl_rpaths +
['-Wl,-rpath,xlib',
'-Wl,-rpath,ylib',
'-Wl,-rpath,zlib'] +
test_args_without_paths)
def test_cc_deps(): def test_cc_deps():
"""Ensure -L and RPATHs are not added in cc mode.""" """Ensure -L and RPATHs are not added in cc mode."""
with set_env(SPACK_INCLUDE_DIRS='xinc:yinc:zinc', with set_env(SPACK_INCLUDE_DIRS='xinc:yinc:zinc',
@ -390,6 +420,44 @@ def test_ccld_with_system_dirs():
test_args_without_paths) test_args_without_paths)
def test_ccld_with_system_dirs_isystem():
"""Ensure all flags are added in ccld mode.
Ensure that includes are in the proper
place when a build uses -isystem, and uses
system directories in the include paths"""
with set_env(SPACK_INCLUDE_DIRS='xinc:yinc:zinc',
SPACK_RPATH_DIRS='xlib:ylib:zlib',
SPACK_LINK_DIRS='xlib:ylib:zlib'):
sys_path_args = ['-isystem/usr/include',
'-L/usr/local/lib',
'-Wl,-rpath,/usr/lib64',
'-isystem/usr/local/include',
'-L/lib64/']
check_args(
cc, sys_path_args + test_args,
[real_cc] +
test_include_paths +
['-isystemxinc',
'-isystemyinc',
'-isystemzinc'] +
['-isystem/usr/include',
'-isystem/usr/local/include'] +
test_library_paths +
['-Lxlib',
'-Lylib',
'-Lzlib'] +
['-L/usr/local/lib',
'-L/lib64/'] +
['-Wl,--disable-new-dtags'] +
test_wl_rpaths +
['-Wl,-rpath,xlib',
'-Wl,-rpath,ylib',
'-Wl,-rpath,zlib'] +
['-Wl,-rpath,/usr/lib64'] +
test_args_without_paths)
def test_ld_deps(): def test_ld_deps():
"""Ensure no (extra) -I args or -Wl, are passed in ld mode.""" """Ensure no (extra) -I args or -Wl, are passed in ld mode."""
with set_env(SPACK_INCLUDE_DIRS='xinc:yinc:zinc', with set_env(SPACK_INCLUDE_DIRS='xinc:yinc:zinc',