summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xlib/spack/env/cc244
-rw-r--r--lib/spack/spack/build_environment.py29
-rw-r--r--lib/spack/spack/test/build_environment.py3
-rw-r--r--lib/spack/spack/test/cc.py110
-rw-r--r--lib/spack/spack/util/environment.py2
5 files changed, 286 insertions, 102 deletions
diff --git a/lib/spack/env/cc b/lib/spack/env/cc
index 6c4db38ba1..52fc8f524d 100755
--- a/lib/spack/env/cc
+++ b/lib/spack/env/cc
@@ -47,7 +47,8 @@ SPACK_F77_RPATH_ARG
SPACK_FC_RPATH_ARG
SPACK_LINKER_ARG
SPACK_SHORT_SPEC
-SPACK_SYSTEM_DIRS"
+SPACK_SYSTEM_DIRS
+SPACK_MANAGED_DIRS"
# Optional parameters that aren't required to be set
@@ -173,21 +174,17 @@ preextend() {
unset IFS
}
-# system_dir PATH
-# test whether a path is a system directory
-system_dir() {
- IFS=':' # SPACK_SYSTEM_DIRS is colon-separated
- path="$1"
- for sd in $SPACK_SYSTEM_DIRS; do
- if [ "${path}" = "${sd}" ] || [ "${path}" = "${sd}/" ]; then
- # success if path starts with a system prefix
- unset IFS
- return 0
- fi
- done
- unset IFS
- return 1 # fail if path starts no system prefix
+# eval this because SPACK_MANAGED_DIRS and SPACK_SYSTEM_DIRS are inputs we don't wanna loop over.
+# moving the eval inside the function would eval it every call.
+eval "\
+path_order() {
+case \"\$1\" in
+ $SPACK_MANAGED_DIRS) return 0 ;;
+ $SPACK_SYSTEM_DIRS) return 2 ;;
+ /*) return 1 ;;
+esac
}
+"
# Fail with a clear message if the input contains any bell characters.
if eval "[ \"\${*#*${lsep}}\" != \"\$*\" ]"; then
@@ -420,11 +417,12 @@ input_command="$*"
parse_Wl() {
while [ $# -ne 0 ]; do
if [ "$wl_expect_rpath" = yes ]; then
- if system_dir "$1"; then
- append return_system_rpath_dirs_list "$1"
- else
- append return_rpath_dirs_list "$1"
- fi
+ path_order "$1"
+ case $? in
+ 0) append return_spack_store_rpath_dirs_list "$1" ;;
+ 1) append return_rpath_dirs_list "$1" ;;
+ 2) append return_system_rpath_dirs_list "$1" ;;
+ esac
wl_expect_rpath=no
else
case "$1" in
@@ -432,21 +430,25 @@ parse_Wl() {
arg="${1#-rpath=}"
if [ -z "$arg" ]; then
shift; continue
- elif system_dir "$arg"; then
- append return_system_rpath_dirs_list "$arg"
- else
- append return_rpath_dirs_list "$arg"
fi
+ path_order "$arg"
+ case $? in
+ 0) append return_spack_store_rpath_dirs_list "$arg" ;;
+ 1) append return_rpath_dirs_list "$arg" ;;
+ 2) append return_system_rpath_dirs_list "$arg" ;;
+ esac
;;
--rpath=*)
arg="${1#--rpath=}"
if [ -z "$arg" ]; then
shift; continue
- elif system_dir "$arg"; then
- append return_system_rpath_dirs_list "$arg"
- else
- append return_rpath_dirs_list "$arg"
fi
+ path_order "$arg"
+ case $? in
+ 0) append return_spack_store_rpath_dirs_list "$arg" ;;
+ 1) append return_rpath_dirs_list "$arg" ;;
+ 2) append return_system_rpath_dirs_list "$arg" ;;
+ esac
;;
-rpath|--rpath)
wl_expect_rpath=yes
@@ -473,12 +475,20 @@ categorize_arguments() {
return_other_args_list=""
return_isystem_was_used=""
+
+ return_isystem_spack_store_include_dirs_list=""
return_isystem_system_include_dirs_list=""
return_isystem_include_dirs_list=""
+
+ return_spack_store_include_dirs_list=""
return_system_include_dirs_list=""
return_include_dirs_list=""
+
+ return_spack_store_lib_dirs_list=""
return_system_lib_dirs_list=""
return_lib_dirs_list=""
+
+ return_spack_store_rpath_dirs_list=""
return_system_rpath_dirs_list=""
return_rpath_dirs_list=""
@@ -546,29 +556,32 @@ categorize_arguments() {
arg="${1#-isystem}"
return_isystem_was_used=true
if [ -z "$arg" ]; then shift; arg="$1"; fi
- if system_dir "$arg"; then
- append return_isystem_system_include_dirs_list "$arg"
- else
- append return_isystem_include_dirs_list "$arg"
- fi
+ path_order "$arg"
+ case $? in
+ 0) append return_isystem_spack_store_include_dirs_list "$arg" ;;
+ 1) append return_isystem_include_dirs_list "$arg" ;;
+ 2) append return_isystem_system_include_dirs_list "$arg" ;;
+ esac
;;
-I*)
arg="${1#-I}"
if [ -z "$arg" ]; then shift; arg="$1"; fi
- if system_dir "$arg"; then
- append return_system_include_dirs_list "$arg"
- else
- append return_include_dirs_list "$arg"
- fi
+ path_order "$arg"
+ case $? in
+ 0) append return_spack_store_include_dirs_list "$arg" ;;
+ 1) append return_include_dirs_list "$arg" ;;
+ 2) append return_system_include_dirs_list "$arg" ;;
+ esac
;;
-L*)
arg="${1#-L}"
if [ -z "$arg" ]; then shift; arg="$1"; fi
- if system_dir "$arg"; then
- append return_system_lib_dirs_list "$arg"
- else
- append return_lib_dirs_list "$arg"
- fi
+ path_order "$arg"
+ case $? in
+ 0) append return_spack_store_lib_dirs_list "$arg" ;;
+ 1) append return_lib_dirs_list "$arg" ;;
+ 2) append return_system_lib_dirs_list "$arg" ;;
+ esac
;;
-l*)
# -loopopt=0 is generated erroneously in autoconf <= 2.69,
@@ -601,29 +614,32 @@ categorize_arguments() {
break
elif [ "$xlinker_expect_rpath" = yes ]; then
# Register the path of -Xlinker -rpath <other args> -Xlinker <path>
- if system_dir "$1"; then
- append return_system_rpath_dirs_list "$1"
- else
- append return_rpath_dirs_list "$1"
- fi
+ path_order "$1"
+ case $? in
+ 0) append return_spack_store_rpath_dirs_list "$1" ;;
+ 1) append return_rpath_dirs_list "$1" ;;
+ 2) append return_system_rpath_dirs_list "$1" ;;
+ esac
xlinker_expect_rpath=no
else
case "$1" in
-rpath=*)
arg="${1#-rpath=}"
- if system_dir "$arg"; then
- append return_system_rpath_dirs_list "$arg"
- else
- append return_rpath_dirs_list "$arg"
- fi
+ path_order "$arg"
+ case $? in
+ 0) append return_spack_store_rpath_dirs_list "$arg" ;;
+ 1) append return_rpath_dirs_list "$arg" ;;
+ 2) append return_system_rpath_dirs_list "$arg" ;;
+ esac
;;
--rpath=*)
arg="${1#--rpath=}"
- if system_dir "$arg"; then
- append return_system_rpath_dirs_list "$arg"
- else
- append return_rpath_dirs_list "$arg"
- fi
+ path_order "$arg"
+ case $? in
+ 0) append return_spack_store_rpath_dirs_list "$arg" ;;
+ 1) append return_rpath_dirs_list "$arg" ;;
+ 2) append return_system_rpath_dirs_list "$arg" ;;
+ esac
;;
-rpath|--rpath)
xlinker_expect_rpath=yes
@@ -661,16 +677,25 @@ categorize_arguments() {
}
categorize_arguments "$@"
- include_dirs_list="$return_include_dirs_list"
- lib_dirs_list="$return_lib_dirs_list"
- rpath_dirs_list="$return_rpath_dirs_list"
- system_include_dirs_list="$return_system_include_dirs_list"
- system_lib_dirs_list="$return_system_lib_dirs_list"
- system_rpath_dirs_list="$return_system_rpath_dirs_list"
- isystem_was_used="$return_isystem_was_used"
- isystem_system_include_dirs_list="$return_isystem_system_include_dirs_list"
- isystem_include_dirs_list="$return_isystem_include_dirs_list"
- other_args_list="$return_other_args_list"
+
+spack_store_include_dirs_list="$return_spack_store_include_dirs_list"
+system_include_dirs_list="$return_system_include_dirs_list"
+include_dirs_list="$return_include_dirs_list"
+
+spack_store_lib_dirs_list="$return_spack_store_lib_dirs_list"
+system_lib_dirs_list="$return_system_lib_dirs_list"
+lib_dirs_list="$return_lib_dirs_list"
+
+spack_store_rpath_dirs_list="$return_spack_store_rpath_dirs_list"
+system_rpath_dirs_list="$return_system_rpath_dirs_list"
+rpath_dirs_list="$return_rpath_dirs_list"
+
+isystem_spack_store_include_dirs_list="$return_isystem_spack_store_include_dirs_list"
+isystem_system_include_dirs_list="$return_isystem_system_include_dirs_list"
+isystem_include_dirs_list="$return_isystem_include_dirs_list"
+
+isystem_was_used="$return_isystem_was_used"
+other_args_list="$return_other_args_list"
#
# Add flags from Spack's cppflags, cflags, cxxflags, fcflags, fflags, and
@@ -738,16 +763,25 @@ esac
IFS="$lsep"
categorize_arguments $spack_flags_list
unset IFS
- spack_flags_include_dirs_list="$return_include_dirs_list"
- spack_flags_lib_dirs_list="$return_lib_dirs_list"
- spack_flags_rpath_dirs_list="$return_rpath_dirs_list"
- spack_flags_system_include_dirs_list="$return_system_include_dirs_list"
- spack_flags_system_lib_dirs_list="$return_system_lib_dirs_list"
- spack_flags_system_rpath_dirs_list="$return_system_rpath_dirs_list"
- spack_flags_isystem_was_used="$return_isystem_was_used"
- spack_flags_isystem_system_include_dirs_list="$return_isystem_system_include_dirs_list"
- spack_flags_isystem_include_dirs_list="$return_isystem_include_dirs_list"
- spack_flags_other_args_list="$return_other_args_list"
+
+spack_flags_isystem_spack_store_include_dirs_list="$return_isystem_spack_store_include_dirs_list"
+spack_flags_isystem_system_include_dirs_list="$return_isystem_system_include_dirs_list"
+spack_flags_isystem_include_dirs_list="$return_isystem_include_dirs_list"
+
+spack_flags_spack_store_include_dirs_list="$return_spack_store_include_dirs_list"
+spack_flags_system_include_dirs_list="$return_system_include_dirs_list"
+spack_flags_include_dirs_list="$return_include_dirs_list"
+
+spack_flags_spack_store_lib_dirs_list="$return_spack_store_lib_dirs_list"
+spack_flags_system_lib_dirs_list="$return_system_lib_dirs_list"
+spack_flags_lib_dirs_list="$return_lib_dirs_list"
+
+spack_flags_spack_store_rpath_dirs_list="$return_spack_store_rpath_dirs_list"
+spack_flags_system_rpath_dirs_list="$return_system_rpath_dirs_list"
+spack_flags_rpath_dirs_list="$return_rpath_dirs_list"
+
+spack_flags_isystem_was_used="$return_isystem_was_used"
+spack_flags_other_args_list="$return_other_args_list"
# On macOS insert headerpad_max_install_names linker flag
@@ -767,11 +801,13 @@ if [ "$mode" = ccld ] || [ "$mode" = ld ]; then
# Append RPATH directories. Note that in the case of the
# top-level package these directories may not exist yet. For dependencies
# it is assumed that paths have already been confirmed.
+ extend spack_store_rpath_dirs_list SPACK_STORE_RPATH_DIRS
extend rpath_dirs_list SPACK_RPATH_DIRS
fi
fi
if [ "$mode" = ccld ] || [ "$mode" = ld ]; then
+ extend spack_store_lib_dirs_list SPACK_STORE_LINK_DIRS
extend lib_dirs_list SPACK_LINK_DIRS
fi
@@ -798,38 +834,50 @@ case "$mode" in
;;
esac
+case "$mode" in
+ cpp|cc|as|ccld)
+ if [ "$spack_flags_isystem_was_used" = "true" ] || [ "$isystem_was_used" = "true" ]; then
+ extend isystem_spack_store_include_dirs_list SPACK_STORE_INCLUDE_DIRS
+ extend isystem_include_dirs_list SPACK_INCLUDE_DIRS
+ else
+ extend spack_store_include_dirs_list SPACK_STORE_INCLUDE_DIRS
+ extend include_dirs_list SPACK_INCLUDE_DIRS
+ fi
+ ;;
+esac
+
#
# Finally, reassemble the command line.
#
args_list="$flags_list"
-# Insert include directories just prior to any system include directories
+# Include search paths partitioned by (in store, non-sytem, system)
# NOTE: adding ${lsep} to the prefix here turns every added element into two
-extend args_list spack_flags_include_dirs_list "-I"
-extend args_list include_dirs_list "-I"
+extend args_list spack_flags_spack_store_include_dirs_list -I
+extend args_list spack_store_include_dirs_list -I
+
+extend args_list spack_flags_include_dirs_list -I
+extend args_list include_dirs_list -I
+
+extend args_list spack_flags_isystem_spack_store_include_dirs_list "-isystem${lsep}"
+extend args_list isystem_spack_store_include_dirs_list "-isystem${lsep}"
+
extend args_list spack_flags_isystem_include_dirs_list "-isystem${lsep}"
extend args_list isystem_include_dirs_list "-isystem${lsep}"
-case "$mode" in
- cpp|cc|as|ccld)
- if [ "$spack_flags_isystem_was_used" = "true" ]; then
- extend args_list SPACK_INCLUDE_DIRS "-isystem${lsep}"
- elif [ "$isystem_was_used" = "true" ]; then
- extend args_list SPACK_INCLUDE_DIRS "-isystem${lsep}"
- else
- extend args_list SPACK_INCLUDE_DIRS "-I"
- fi
- ;;
-esac
-
extend args_list spack_flags_system_include_dirs_list -I
extend args_list system_include_dirs_list -I
+
extend args_list spack_flags_isystem_system_include_dirs_list "-isystem${lsep}"
extend args_list isystem_system_include_dirs_list "-isystem${lsep}"
-# Library search paths
+# Library search paths partitioned by (in store, non-sytem, system)
+extend args_list spack_flags_spack_store_lib_dirs_list "-L"
+extend args_list spack_store_lib_dirs_list "-L"
+
extend args_list spack_flags_lib_dirs_list "-L"
extend args_list lib_dirs_list "-L"
+
extend args_list spack_flags_system_lib_dirs_list "-L"
extend args_list system_lib_dirs_list "-L"
@@ -839,8 +887,12 @@ case "$mode" in
if [ -n "$dtags_to_add" ] ; then
append args_list "$linker_arg$dtags_to_add"
fi
+ extend args_list spack_flags_spack_store_rpath_dirs_list "$rpath"
+ extend args_list spack_store_rpath_dirs_list "$rpath"
+
extend args_list spack_flags_rpath_dirs_list "$rpath"
extend args_list rpath_dirs_list "$rpath"
+
extend args_list spack_flags_system_rpath_dirs_list "$rpath"
extend args_list system_rpath_dirs_list "$rpath"
;;
@@ -848,8 +900,12 @@ case "$mode" in
if [ -n "$dtags_to_add" ] ; then
append args_list "$dtags_to_add"
fi
+ extend args_list spack_flags_spack_store_rpath_dirs_list "-rpath${lsep}"
+ extend args_list spack_store_rpath_dirs_list "-rpath${lsep}"
+
extend args_list spack_flags_rpath_dirs_list "-rpath${lsep}"
extend args_list rpath_dirs_list "-rpath${lsep}"
+
extend args_list spack_flags_system_rpath_dirs_list "-rpath${lsep}"
extend args_list system_rpath_dirs_list "-rpath${lsep}"
;;
diff --git a/lib/spack/spack/build_environment.py b/lib/spack/spack/build_environment.py
index a567951918..86934daf24 100644
--- a/lib/spack/spack/build_environment.py
+++ b/lib/spack/spack/build_environment.py
@@ -68,6 +68,7 @@ import spack.platforms
import spack.repo
import spack.schema.environment
import spack.spec
+import spack.stage
import spack.store
import spack.subprocess_context
import spack.user_environment
@@ -80,7 +81,7 @@ from spack.install_test import spack_install_test_log
from spack.installer import InstallError
from spack.util.cpus import determine_number_of_jobs
from spack.util.environment import (
- SYSTEM_DIRS,
+ SYSTEM_DIR_CASE_ENTRY,
EnvironmentModifications,
env_flag,
filter_system_paths,
@@ -103,9 +104,13 @@ SPACK_NO_PARALLEL_MAKE = "SPACK_NO_PARALLEL_MAKE"
# Spack's compiler wrappers.
#
SPACK_ENV_PATH = "SPACK_ENV_PATH"
+SPACK_MANAGED_DIRS = "SPACK_MANAGED_DIRS"
SPACK_INCLUDE_DIRS = "SPACK_INCLUDE_DIRS"
SPACK_LINK_DIRS = "SPACK_LINK_DIRS"
SPACK_RPATH_DIRS = "SPACK_RPATH_DIRS"
+SPACK_STORE_INCLUDE_DIRS = "SPACK_STORE_INCLUDE_DIRS"
+SPACK_STORE_LINK_DIRS = "SPACK_STORE_LINK_DIRS"
+SPACK_STORE_RPATH_DIRS = "SPACK_STORE_RPATH_DIRS"
SPACK_RPATH_DEPS = "SPACK_RPATH_DEPS"
SPACK_LINK_DEPS = "SPACK_LINK_DEPS"
SPACK_PREFIX = "SPACK_PREFIX"
@@ -418,7 +423,7 @@ def set_compiler_environment_variables(pkg, env):
env.set("SPACK_COMPILER_SPEC", str(spec.compiler))
- env.set("SPACK_SYSTEM_DIRS", ":".join(SYSTEM_DIRS))
+ env.set("SPACK_SYSTEM_DIRS", SYSTEM_DIR_CASE_ENTRY)
compiler.setup_custom_environment(pkg, env)
@@ -546,9 +551,23 @@ def set_wrapper_variables(pkg, env):
include_dirs = list(dedupe(filter_system_paths(include_dirs)))
rpath_dirs = list(dedupe(filter_system_paths(rpath_dirs)))
- env.set(SPACK_LINK_DIRS, ":".join(link_dirs))
- env.set(SPACK_INCLUDE_DIRS, ":".join(include_dirs))
- env.set(SPACK_RPATH_DIRS, ":".join(rpath_dirs))
+ spack_managed_dirs: List[str] = [
+ spack.stage.get_stage_root(),
+ spack.store.STORE.db.root,
+ *(db.root for db in spack.store.STORE.db.upstream_dbs),
+ ]
+
+ env.set(SPACK_MANAGED_DIRS, "|".join(f'"{p}/"*' for p in spack_managed_dirs))
+ is_spack_managed = lambda p: any(p.startswith(store) for store in spack_managed_dirs)
+ link_dirs_spack, link_dirs_system = stable_partition(link_dirs, is_spack_managed)
+ include_dirs_spack, include_dirs_system = stable_partition(include_dirs, is_spack_managed)
+ rpath_dirs_spack, rpath_dirs_system = stable_partition(rpath_dirs, is_spack_managed)
+ env.set(SPACK_LINK_DIRS, ":".join(link_dirs_system))
+ env.set(SPACK_INCLUDE_DIRS, ":".join(include_dirs_system))
+ env.set(SPACK_RPATH_DIRS, ":".join(rpath_dirs_system))
+ env.set(SPACK_STORE_LINK_DIRS, ":".join(link_dirs_spack))
+ env.set(SPACK_STORE_INCLUDE_DIRS, ":".join(include_dirs_spack))
+ env.set(SPACK_STORE_RPATH_DIRS, ":".join(rpath_dirs_spack))
def set_package_py_globals(pkg, context: Context = Context.BUILD):
diff --git a/lib/spack/spack/test/build_environment.py b/lib/spack/spack/test/build_environment.py
index 1f2d9e904f..cb47ee5977 100644
--- a/lib/spack/spack/test/build_environment.py
+++ b/lib/spack/spack/test/build_environment.py
@@ -63,7 +63,8 @@ def build_environment(working_env):
os.environ["SPACK_LINKER_ARG"] = "-Wl,"
os.environ["SPACK_DTAGS_TO_ADD"] = "--disable-new-dtags"
os.environ["SPACK_DTAGS_TO_STRIP"] = "--enable-new-dtags"
- os.environ["SPACK_SYSTEM_DIRS"] = "/usr/include /usr/lib"
+ os.environ["SPACK_SYSTEM_DIRS"] = "/usr/include|/usr/lib"
+ os.environ["SPACK_MANAGED_DIRS"] = f"{prefix}/opt/spack"
os.environ["SPACK_TARGET_ARGS"] = ""
if "SPACK_DEPENDENCIES" in os.environ:
diff --git a/lib/spack/spack/test/cc.py b/lib/spack/spack/test/cc.py
index 25aab774a7..4bd7bf5c3d 100644
--- a/lib/spack/spack/test/cc.py
+++ b/lib/spack/spack/test/cc.py
@@ -15,7 +15,7 @@ import spack.build_environment
import spack.config
import spack.spec
from spack.paths import build_env_path
-from spack.util.environment import SYSTEM_DIRS, set_env
+from spack.util.environment import SYSTEM_DIR_CASE_ENTRY, set_env
from spack.util.executable import Executable, ProcessError
#
@@ -159,7 +159,8 @@ def wrapper_environment(working_env):
SPACK_DEBUG_LOG_ID="foo-hashabc",
SPACK_COMPILER_SPEC="gcc@4.4.7",
SPACK_SHORT_SPEC="foo@1.2 arch=linux-rhel6-x86_64 /hashabc",
- SPACK_SYSTEM_DIRS=":".join(SYSTEM_DIRS),
+ SPACK_SYSTEM_DIRS=SYSTEM_DIR_CASE_ENTRY,
+ SPACK_MANAGED_DIRS="/path/to/spack-1/opt/spack/*|/path/to/spack-2/opt/spack/*",
SPACK_CC_RPATH_ARG="-Wl,-rpath,",
SPACK_CXX_RPATH_ARG="-Wl,-rpath,",
SPACK_F77_RPATH_ARG="-Wl,-rpath,",
@@ -907,3 +908,108 @@ def test_linker_strips_loopopt(wrapper_environment, wrapper_flags):
result = cc(*(test_args + ["-loopopt=0", "-c", "x.c"]), output=str)
result = result.strip().split("\n")
assert "-loopopt=0" in result
+
+
+def test_spack_managed_dirs_are_prioritized(wrapper_environment):
+ # We have two different stores with 5 packages divided over them
+ pkg1 = "/path/to/spack-1/opt/spack/linux-ubuntu22.04-zen2/gcc-13.2.0/pkg-1.0-abcdef"
+ pkg2 = "/path/to/spack-1/opt/spack/linux-ubuntu22.04-zen2/gcc-13.2.0/pkg-2.0-abcdef"
+ pkg3 = "/path/to/spack-2/opt/spack/linux-ubuntu22.04-zen2/gcc-13.2.0/pkg-3.0-abcdef"
+ pkg4 = "/path/to/spack-2/opt/spack/linux-ubuntu22.04-zen2/gcc-13.2.0/pkg-4.0-abcdef"
+ pkg5 = "/path/to/spack-2/opt/spack/linux-ubuntu22.04-zen2/gcc-13.2.0/pkg-5.0-abcdef"
+
+ variables = {
+ # cppflags, ldflags from the command line, config or package.py take highest priority
+ "SPACK_CPPFLAGS": f"-I/usr/local/include -I/external-1/include -I{pkg1}/include",
+ "SPACK_LDFLAGS": f"-L/usr/local/lib -L/external-1/lib -L{pkg1}/lib "
+ f"-Wl,-rpath,/usr/local/lib -Wl,-rpath,/external-1/lib -Wl,-rpath,{pkg1}/lib",
+ # automatic -L, -Wl,-rpath, -I flags from dependencies -- on the spack side they are
+ # already partitioned into "spack owned prefixes" and "non-spack owned prefixes"
+ "SPACK_STORE_LINK_DIRS": f"{pkg4}/lib:{pkg5}/lib",
+ "SPACK_STORE_RPATH_DIRS": f"{pkg4}/lib:{pkg5}/lib",
+ "SPACK_STORE_INCLUDE_DIRS": f"{pkg4}/include:{pkg5}/include",
+ "SPACK_LINK_DIRS": "/external-3/lib:/external-4/lib",
+ "SPACK_RPATH_DIRS": "/external-3/lib:/external-4/lib",
+ "SPACK_INCLUDE_DIRS": "/external-3/include:/external-4/include",
+ }
+
+ with set_env(SPACK_TEST_COMMAND="dump-args", **variables):
+ effective_call = (
+ cc(
+ # system paths
+ "-I/usr/include",
+ "-L/usr/lib",
+ "-Wl,-rpath,/usr/lib",
+ # some other externals
+ "-I/external-2/include",
+ "-L/external-2/lib",
+ "-Wl,-rpath,/external-2/lib",
+ # relative paths are considered "spack managed" since they are in the stage dir
+ "-I..",
+ "-L..",
+ "-Wl,-rpath,..", # pathological but simpler for the test.
+ # spack store paths
+ f"-I{pkg2}/include",
+ f"-I{pkg3}/include",
+ f"-L{pkg2}/lib",
+ f"-L{pkg3}/lib",
+ f"-Wl,-rpath,{pkg2}/lib",
+ f"-Wl,-rpath,{pkg3}/lib",
+ "hello.c",
+ "-o",
+ "hello",
+ output=str,
+ )
+ .strip()
+ .split("\n")
+ )
+
+ dash_I = [flag[2:] for flag in effective_call if flag.startswith("-I")]
+ dash_L = [flag[2:] for flag in effective_call if flag.startswith("-L")]
+ dash_Wl_rpath = [flag[11:] for flag in effective_call if flag.startswith("-Wl,-rpath")]
+
+ assert dash_I == [
+ # spack owned dirs from SPACK_*FLAGS
+ f"{pkg1}/include",
+ # spack owned dirs from command line & automatic flags for deps (in that order)]
+ "..",
+ f"{pkg2}/include", # from command line
+ f"{pkg3}/include", # from command line
+ f"{pkg4}/include", # from SPACK_STORE_INCLUDE_DIRS
+ f"{pkg5}/include", # from SPACK_STORE_INCLUDE_DIRS
+ # non-system dirs from SPACK_*FLAGS
+ "/external-1/include",
+ # non-system dirs from command line & automatic flags for deps (in that order)
+ "/external-2/include", # from command line
+ "/external-3/include", # from SPACK_INCLUDE_DIRS
+ "/external-4/include", # from SPACK_INCLUDE_DIRS
+ # system dirs from SPACK_*FLAGS
+ "/usr/local/include",
+ # system dirs from command line
+ "/usr/include",
+ ]
+
+ assert (
+ dash_L
+ == dash_Wl_rpath
+ == [
+ # spack owned dirs from SPACK_*FLAGS
+ f"{pkg1}/lib",
+ # spack owned dirs from command line & automatic flags for deps (in that order)
+ "..",
+ f"{pkg2}/lib", # from command line
+ f"{pkg3}/lib", # from command line
+ f"{pkg4}/lib", # from SPACK_STORE_LINK_DIRS
+ f"{pkg5}/lib", # from SPACK_STORE_LINK_DIRS
+ # non-system dirs from SPACK_*FLAGS
+ "/external-1/lib",
+ # non-system dirs from command line & automatic flags for deps (in that order)
+ "/external-2/lib", # from command line
+ "/external-3/lib", # from SPACK_LINK_DIRS
+ "/external-4/lib", # from SPACK_LINK_DIRS
+ # system dirs from SPACK_*FLAGS
+ "/usr/local/lib",
+ # system dirs from command line
+ "/usr/lib",
+ ]
+ )
diff --git a/lib/spack/spack/util/environment.py b/lib/spack/spack/util/environment.py
index d2f56dd4a7..af15cd2764 100644
--- a/lib/spack/spack/util/environment.py
+++ b/lib/spack/spack/util/environment.py
@@ -36,6 +36,8 @@ else:
SYSTEM_DIRS = [os.path.join(p, s) for s in SUFFIXES for p in SYSTEM_PATHS] + SYSTEM_PATHS
+#: used in the compiler wrapper's `/usr/lib|/usr/lib64|...)` case entry
+SYSTEM_DIR_CASE_ENTRY = "|".join(sorted(f'"{d}{suff}"' for d in SYSTEM_DIRS for suff in ("", "/")))
_SHELL_SET_STRINGS = {
"sh": "export {0}={1};\n",