bugfix: cc handles spaces in flag variables properly
- cc cleanup caused a parsing regression in flag handling - We added proper quoting to array expansions, but flag variables were never actually converted to arrays. Old code relied on this. This commit: - Adds reads to convert flags to arrays. - Makes the cc test check for improper space handling to prevent future regressions.
This commit is contained in:
parent
393d3c64fc
commit
ed79d6a11b
14
lib/spack/env/cc
vendored
14
lib/spack/env/cc
vendored
@ -74,9 +74,18 @@ function die {
|
||||
exit 1
|
||||
}
|
||||
|
||||
# read system directories into an array (delimited by :)
|
||||
# read input parameters into proper bash arrays.
|
||||
# SYSTEM_DIRS is delimited by :
|
||||
IFS=':' read -ra SPACK_SYSTEM_DIRS <<< "${SPACK_SYSTEM_DIRS}"
|
||||
|
||||
# SPACK_<LANG>FLAGS and SPACK_LDLIBS are split by ' '
|
||||
IFS=' ' read -ra SPACK_FFLAGS <<< "$SPACK_FFLAGS"
|
||||
IFS=' ' read -ra SPACK_CPPFLAGS <<< "$SPACK_CPPFLAGS"
|
||||
IFS=' ' read -ra SPACK_CFLAGS <<< "$SPACK_CFLAGS"
|
||||
IFS=' ' read -ra SPACK_CXXFLAGS <<< "$SPACK_CXXFLAGS"
|
||||
IFS=' ' read -ra SPACK_LDFLAGS <<< "$SPACK_LDFLAGS"
|
||||
IFS=' ' read -ra SPACK_LDLIBS <<< "$SPACK_LDLIBS"
|
||||
|
||||
# test whether a path is a system directory
|
||||
function system_dir {
|
||||
path="$1"
|
||||
@ -524,7 +533,8 @@ fi
|
||||
|
||||
# dump the full command if the caller supplies SPACK_TEST_COMMAND=dump-args
|
||||
if [[ $SPACK_TEST_COMMAND == dump-args ]]; then
|
||||
echo "${full_command[@]}"
|
||||
IFS="
|
||||
" && echo "${full_command[*]}"
|
||||
exit
|
||||
elif [[ -n $SPACK_TEST_COMMAND ]]; then
|
||||
die "ERROR: Unknown test command"
|
||||
|
@ -178,77 +178,59 @@ def dep4(tmpdir_factory):
|
||||
pytestmark = pytest.mark.usefixtures('wrapper_environment')
|
||||
|
||||
|
||||
def check_cc(command, args, expected):
|
||||
with set_env(SPACK_TEST_COMMAND=command):
|
||||
assert expected == cc(*args, output=str).strip().split()
|
||||
def check_args(cc, args, expected):
|
||||
"""Check output arguments that cc produces when called with args.
|
||||
|
||||
This assumes that cc will print debug command output with one element
|
||||
per line, so that we see whether arguments that should (or shouldn't)
|
||||
contain spaces are parsed correctly.
|
||||
"""
|
||||
with set_env(SPACK_TEST_COMMAND='dump-args'):
|
||||
assert expected == cc(*args, output=str).strip().split('\n')
|
||||
|
||||
|
||||
def check_cxx(command, args, expected):
|
||||
with set_env(SPACK_TEST_COMMAND=command):
|
||||
assert expected == cxx(*args, output=str).strip().split()
|
||||
|
||||
|
||||
def check_fc(command, args, expected):
|
||||
with set_env(SPACK_TEST_COMMAND=command):
|
||||
assert expected == fc(*args, output=str).strip().split()
|
||||
|
||||
|
||||
def check_ld(command, args, expected):
|
||||
with set_env(SPACK_TEST_COMMAND=command):
|
||||
assert expected == ld(*args, output=str).strip().split()
|
||||
|
||||
|
||||
def check_cpp(command, args, expected):
|
||||
with set_env(SPACK_TEST_COMMAND=command):
|
||||
assert expected == cpp(*args, output=str).strip().split()
|
||||
def dump_mode(cc, args):
|
||||
"""Make cc dump the mode it detects, and return it."""
|
||||
with set_env(SPACK_TEST_COMMAND='dump-mode'):
|
||||
return cc(*args, output=str).strip()
|
||||
|
||||
|
||||
def test_vcheck_mode():
|
||||
check_cc(
|
||||
'dump-mode', ['-I/include', '--version'], ['vcheck'])
|
||||
check_cc(
|
||||
'dump-mode', ['-I/include', '-V'], ['vcheck'])
|
||||
check_cc(
|
||||
'dump-mode', ['-I/include', '-v'], ['vcheck'])
|
||||
check_cc(
|
||||
'dump-mode', ['-I/include', '-dumpversion'], ['vcheck'])
|
||||
check_cc(
|
||||
'dump-mode', ['-I/include', '--version', '-c'], ['vcheck'])
|
||||
check_cc(
|
||||
'dump-mode', ['-I/include', '-V', '-o', 'output'], ['vcheck'])
|
||||
assert dump_mode(cc, ['-I/include', '--version']) == 'vcheck'
|
||||
assert dump_mode(cc, ['-I/include', '-V']) == 'vcheck'
|
||||
assert dump_mode(cc, ['-I/include', '-v']) == 'vcheck'
|
||||
assert dump_mode(cc, ['-I/include', '-dumpversion']) == 'vcheck'
|
||||
assert dump_mode(cc, ['-I/include', '--version', '-c']) == 'vcheck'
|
||||
assert dump_mode(cc, ['-I/include', '-V', '-o', 'output']) == 'vcheck'
|
||||
|
||||
|
||||
def test_cpp_mode():
|
||||
check_cc('dump-mode', ['-E'], ['cpp'])
|
||||
check_cpp('dump-mode', [], ['cpp'])
|
||||
assert dump_mode(cc, ['-E']) == 'cpp'
|
||||
assert dump_mode(cxx, ['-E']) == 'cpp'
|
||||
assert dump_mode(cpp, []) == 'cpp'
|
||||
|
||||
|
||||
def test_as_mode():
|
||||
check_cc('dump-mode', ['-S'], ['as'])
|
||||
assert dump_mode(cc, ['-S']) == 'as'
|
||||
|
||||
|
||||
def test_ccld_mode():
|
||||
check_cc(
|
||||
'dump-mode', [], ['ccld'])
|
||||
check_cc(
|
||||
'dump-mode', ['foo.c', '-o', 'foo'], ['ccld'])
|
||||
check_cc(
|
||||
'dump-mode', ['foo.c', '-o', 'foo', '-Wl,-rpath,foo'], ['ccld'])
|
||||
check_cc(
|
||||
'dump-mode',
|
||||
['foo.o', 'bar.o', 'baz.o', '-o', 'foo', '-Wl,-rpath,foo'], ['ccld'])
|
||||
assert dump_mode(cc, []) == 'ccld'
|
||||
assert dump_mode(cc, ['foo.c', '-o', 'foo']) == 'ccld'
|
||||
assert dump_mode(cc, ['foo.c', '-o', 'foo', '-Wl,-rpath,foo']) == 'ccld'
|
||||
assert dump_mode(cc, [
|
||||
'foo.o', 'bar.o', 'baz.o', '-o', 'foo', '-Wl,-rpath,foo']) == 'ccld'
|
||||
|
||||
|
||||
def test_ld_mode():
|
||||
check_ld('dump-mode', [], ['ld'])
|
||||
check_ld(
|
||||
'dump-mode',
|
||||
['foo.o', 'bar.o', 'baz.o', '-o', 'foo', '-Wl,-rpath,foo'], ['ld'])
|
||||
assert dump_mode(ld, []) == 'ld'
|
||||
assert dump_mode(ld, [
|
||||
'foo.o', 'bar.o', 'baz.o', '-o', 'foo', '-Wl,-rpath,foo']) == 'ld'
|
||||
|
||||
|
||||
def test_ld_flags(wrapper_flags):
|
||||
check_ld(
|
||||
'dump-args', test_args,
|
||||
check_args(
|
||||
ld, test_args,
|
||||
['ld'] +
|
||||
spack_ldflags +
|
||||
test_include_paths +
|
||||
@ -260,8 +242,8 @@ def test_ld_flags(wrapper_flags):
|
||||
|
||||
|
||||
def test_cpp_flags(wrapper_flags):
|
||||
check_cpp(
|
||||
'dump-args', test_args,
|
||||
check_args(
|
||||
cpp, test_args,
|
||||
['cpp'] +
|
||||
spack_cppflags +
|
||||
test_include_paths +
|
||||
@ -270,8 +252,8 @@ def test_cpp_flags(wrapper_flags):
|
||||
|
||||
|
||||
def test_cc_flags(wrapper_flags):
|
||||
check_cc(
|
||||
'dump-args', test_args,
|
||||
check_args(
|
||||
cc, test_args,
|
||||
[real_cc] +
|
||||
spack_cppflags +
|
||||
spack_cflags +
|
||||
@ -285,8 +267,8 @@ def test_cc_flags(wrapper_flags):
|
||||
|
||||
|
||||
def test_cxx_flags(wrapper_flags):
|
||||
check_cxx(
|
||||
'dump-args', test_args,
|
||||
check_args(
|
||||
cxx, test_args,
|
||||
[real_cc] +
|
||||
spack_cppflags +
|
||||
spack_cxxflags +
|
||||
@ -300,8 +282,8 @@ def test_cxx_flags(wrapper_flags):
|
||||
|
||||
|
||||
def test_fc_flags(wrapper_flags):
|
||||
check_fc(
|
||||
'dump-args', test_args,
|
||||
check_args(
|
||||
fc, test_args,
|
||||
[real_cc] +
|
||||
spack_fflags +
|
||||
spack_cppflags +
|
||||
@ -316,8 +298,8 @@ def test_fc_flags(wrapper_flags):
|
||||
|
||||
def test_dep_rpath():
|
||||
"""Ensure RPATHs for root package are added."""
|
||||
check_cc(
|
||||
'dump-args', test_args,
|
||||
check_args(
|
||||
cc, test_args,
|
||||
[real_cc] +
|
||||
test_include_paths +
|
||||
test_library_paths +
|
||||
@ -331,8 +313,8 @@ def test_dep_include(dep4):
|
||||
with set_env(SPACK_DEPENDENCIES=dep4,
|
||||
SPACK_RPATH_DEPS=dep4,
|
||||
SPACK_LINK_DEPS=dep4):
|
||||
check_cc(
|
||||
'dump-args', test_args,
|
||||
check_args(
|
||||
cc, test_args,
|
||||
[real_cc] +
|
||||
test_include_paths +
|
||||
['-I' + dep4 + '/include'] +
|
||||
@ -347,8 +329,8 @@ def test_dep_lib(dep2):
|
||||
with set_env(SPACK_DEPENDENCIES=dep2,
|
||||
SPACK_RPATH_DEPS=dep2,
|
||||
SPACK_LINK_DEPS=dep2):
|
||||
check_cc(
|
||||
'dump-args', test_args,
|
||||
check_args(
|
||||
cc, test_args,
|
||||
[real_cc] +
|
||||
test_include_paths +
|
||||
test_library_paths +
|
||||
@ -363,8 +345,8 @@ def test_dep_lib_no_rpath(dep2):
|
||||
"""Ensure a single dependency link flag is added with no dep RPATH."""
|
||||
with set_env(SPACK_DEPENDENCIES=dep2,
|
||||
SPACK_LINK_DEPS=dep2):
|
||||
check_cc(
|
||||
'dump-args', test_args,
|
||||
check_args(
|
||||
cc, test_args,
|
||||
[real_cc] +
|
||||
test_include_paths +
|
||||
test_library_paths +
|
||||
@ -378,8 +360,8 @@ def test_dep_lib_no_lib(dep2):
|
||||
"""Ensure a single dependency RPATH is added with no -L."""
|
||||
with set_env(SPACK_DEPENDENCIES=dep2,
|
||||
SPACK_RPATH_DEPS=dep2):
|
||||
check_cc(
|
||||
'dump-args', test_args,
|
||||
check_args(
|
||||
cc, test_args,
|
||||
[real_cc] +
|
||||
test_include_paths +
|
||||
test_library_paths +
|
||||
@ -395,8 +377,8 @@ def test_ccld_deps(dep1, dep2, dep3, dep4):
|
||||
with set_env(SPACK_DEPENDENCIES=deps,
|
||||
SPACK_RPATH_DEPS=deps,
|
||||
SPACK_LINK_DEPS=deps):
|
||||
check_cc(
|
||||
'dump-args', test_args,
|
||||
check_args(
|
||||
cc, test_args,
|
||||
[real_cc] +
|
||||
test_include_paths +
|
||||
['-I' + dep1 + '/include',
|
||||
@ -420,8 +402,8 @@ def test_cc_deps(dep1, dep2, dep3, dep4):
|
||||
with set_env(SPACK_DEPENDENCIES=deps,
|
||||
SPACK_RPATH_DEPS=deps,
|
||||
SPACK_LINK_DEPS=deps):
|
||||
check_cc(
|
||||
'dump-args', ['-c'] + test_args,
|
||||
check_args(
|
||||
cc, ['-c'] + test_args,
|
||||
[real_cc] +
|
||||
test_include_paths +
|
||||
['-I' + dep1 + '/include',
|
||||
@ -444,8 +426,8 @@ def test_ccld_with_system_dirs(dep1, dep2, dep3, dep4):
|
||||
'-Wl,-rpath,/usr/lib64',
|
||||
'-I/usr/local/include',
|
||||
'-L/lib64/']
|
||||
check_cc(
|
||||
'dump-args', sys_path_args + test_args,
|
||||
check_args(
|
||||
cc, sys_path_args + test_args,
|
||||
[real_cc] +
|
||||
test_include_paths +
|
||||
['-I' + dep1 + '/include',
|
||||
@ -474,8 +456,8 @@ def test_ld_deps(dep1, dep2, dep3, dep4):
|
||||
with set_env(SPACK_DEPENDENCIES=deps,
|
||||
SPACK_RPATH_DEPS=deps,
|
||||
SPACK_LINK_DEPS=deps):
|
||||
check_ld(
|
||||
'dump-args', test_args,
|
||||
check_args(
|
||||
ld, test_args,
|
||||
['ld'] +
|
||||
test_include_paths +
|
||||
test_library_paths +
|
||||
@ -495,8 +477,8 @@ def test_ld_deps_no_rpath(dep1, dep2, dep3, dep4):
|
||||
deps = ':'.join((dep1, dep2, dep3, dep4))
|
||||
with set_env(SPACK_DEPENDENCIES=deps,
|
||||
SPACK_LINK_DEPS=deps):
|
||||
check_ld(
|
||||
'dump-args', test_args,
|
||||
check_args(
|
||||
ld, test_args,
|
||||
['ld'] +
|
||||
test_include_paths +
|
||||
test_library_paths +
|
||||
@ -513,8 +495,8 @@ def test_ld_deps_no_link(dep1, dep2, dep3, dep4):
|
||||
deps = ':'.join((dep1, dep2, dep3, dep4))
|
||||
with set_env(SPACK_DEPENDENCIES=deps,
|
||||
SPACK_RPATH_DEPS=deps):
|
||||
check_ld(
|
||||
'dump-args', test_args,
|
||||
check_args(
|
||||
ld, test_args,
|
||||
['ld'] +
|
||||
test_include_paths +
|
||||
test_library_paths +
|
||||
@ -536,8 +518,8 @@ def test_ld_deps_partial(dep1):
|
||||
# TODO: do we need to add RPATHs on other platforms like Linux?
|
||||
# TODO: Can't we treat them the same?
|
||||
os.environ['SPACK_SHORT_SPEC'] = "foo@1.2=linux-x86_64"
|
||||
check_ld(
|
||||
'dump-args', ['-r'] + test_args,
|
||||
check_args(
|
||||
ld, ['-r'] + test_args,
|
||||
['ld'] +
|
||||
test_include_paths +
|
||||
test_library_paths +
|
||||
@ -551,8 +533,8 @@ def test_ld_deps_partial(dep1):
|
||||
# rpaths from the underlying command will still appear
|
||||
# Spack will not add its own rpaths.
|
||||
os.environ['SPACK_SHORT_SPEC'] = "foo@1.2=darwin-x86_64"
|
||||
check_ld(
|
||||
'dump-args', ['-r'] + test_args,
|
||||
check_args(
|
||||
ld, ['-r'] + test_args,
|
||||
['ld'] +
|
||||
test_include_paths +
|
||||
test_library_paths +
|
||||
@ -564,8 +546,8 @@ def test_ld_deps_partial(dep1):
|
||||
|
||||
def test_ccache_prepend_for_cc():
|
||||
with set_env(SPACK_CCACHE_BINARY='ccache'):
|
||||
check_cc(
|
||||
'dump-args', test_args,
|
||||
check_args(
|
||||
cc, test_args,
|
||||
['ccache'] + # ccache prepended in cc mode
|
||||
[real_cc] +
|
||||
test_include_paths +
|
||||
@ -576,8 +558,8 @@ def test_ccache_prepend_for_cc():
|
||||
|
||||
|
||||
def test_no_ccache_prepend_for_fc():
|
||||
check_fc(
|
||||
'dump-args', test_args,
|
||||
check_args(
|
||||
fc, test_args,
|
||||
# no ccache for Fortran
|
||||
[real_cc] +
|
||||
test_include_paths +
|
||||
|
Loading…
Reference in New Issue
Block a user