|
69 | 69 | from easybuild.tools.systemtools import LINUX, get_os_type |
70 | 70 | from easybuild.tools.toolchain.options import ToolchainOptions |
71 | 71 | from easybuild.tools.toolchain.toolchainvariables import ToolchainVariables |
72 | | -from easybuild.tools.utilities import nub, trace_msg |
| 72 | +from easybuild.tools.utilities import nub, unique_ordered_extend, trace_msg |
73 | 73 |
|
74 | 74 |
|
75 | 75 | _log = fancylogger.getLogger('tools.toolchain', fname=False) |
|
95 | 95 | TOOLCHAIN_CAPABILITY_LAPACK_FAMILY, |
96 | 96 | TOOLCHAIN_CAPABILITY_MPI_FAMILY, |
97 | 97 | ] |
| 98 | +# modes to handle CPP header search paths |
| 99 | +# see: https://gcc.gnu.org/onlinedocs/cpp/Environment-Variables.html |
| 100 | +SEARCH_PATH_CPP_HEADERS_FLAGS = "CPPFLAGS" |
| 101 | +SEARCH_PATH_CPP_HEADERS_CPATH = "CPATH" |
| 102 | +SEARCH_PATH_CPP_HEADERS_INCLUDE = "INCLUDE_PATHS" |
| 103 | +SEARCH_PATH_CPP_HEADERS = { |
| 104 | + SEARCH_PATH_CPP_HEADERS_FLAGS: ["CPPFLAGS"], |
| 105 | + SEARCH_PATH_CPP_HEADERS_CPATH: ["CPATH"], |
| 106 | + SEARCH_PATH_CPP_HEADERS_INCLUDE: ["C_INCLUDE_PATH", "CPLUS_INCLUDE_PATH", "OBJC_INCLUDE_PATH"], |
| 107 | +} |
| 108 | +DEFAULT_SEARCH_PATH_CPP_HEADERS = SEARCH_PATH_CPP_HEADERS_FLAGS |
98 | 109 |
|
99 | 110 |
|
100 | 111 | def is_system_toolchain(tc_name): |
@@ -850,7 +861,7 @@ def prepare(self, onlymod=None, deps=None, silent=False, loadmod=True, |
850 | 861 | else: |
851 | 862 | self.log.debug("prepare: set additional variables onlymod=%s", onlymod) |
852 | 863 |
|
853 | | - # add LDFLAGS and CPPFLAGS from dependencies to self.vars |
| 864 | + # add linker and preprocessor paths of dependencies to self.vars |
854 | 865 | self._add_dependency_variables() |
855 | 866 | self.generate_vars() |
856 | 867 | self._setenv_variables(onlymod, verbose=not silent) |
@@ -1049,39 +1060,71 @@ def handle_sysroot(self): |
1049 | 1060 | setvar('PKG_CONFIG_PATH', os.pathsep.join(pkg_config_path)) |
1050 | 1061 |
|
1051 | 1062 | def _add_dependency_variables(self, names=None, cpp=None, ld=None): |
1052 | | - """ Add LDFLAGS and CPPFLAGS to the self.variables based on the dependencies |
1053 | | - names should be a list of strings containing the name of the dependency |
1054 | 1063 | """ |
1055 | | - cpp_paths = ['include'] |
1056 | | - ld_paths = ['lib64', 'lib'] |
1057 | | - |
1058 | | - if cpp is not None: |
1059 | | - for p in cpp: |
1060 | | - if p not in cpp_paths: |
1061 | | - cpp_paths.append(p) |
1062 | | - if ld is not None: |
1063 | | - for p in ld: |
1064 | | - if p not in ld_paths: |
1065 | | - ld_paths.append(p) |
1066 | | - |
1067 | | - if not names: |
1068 | | - deps = self.dependencies |
1069 | | - else: |
1070 | | - deps = [{'name': name} for name in names if name is not None] |
| 1064 | + Add linker and preprocessor paths of dependencies to self.variables |
| 1065 | + :names: list of strings containing the name of the dependency |
| 1066 | + """ |
| 1067 | + # collect dependencies |
| 1068 | + dependencies = self.dependencies if names is None else [{"name": name} for name in names if name] |
1071 | 1069 |
|
1072 | 1070 | # collect software install prefixes for dependencies |
1073 | | - roots = [] |
1074 | | - for dep in deps: |
1075 | | - if dep.get('external_module', False): |
| 1071 | + dependency_roots = [] |
| 1072 | + for dep in dependencies: |
| 1073 | + if dep.get("external_module", False): |
1076 | 1074 | # for software names provided via external modules, install prefix may be unknown |
1077 | | - names = dep['external_module_metadata'].get('name', []) |
1078 | | - roots.extend([root for root in self.get_software_root(names) if root is not None]) |
| 1075 | + names = dep["external_module_metadata"].get("name", []) |
| 1076 | + dependency_roots.extend([root for root in self.get_software_root(names) if root is not None]) |
1079 | 1077 | else: |
1080 | | - roots.extend(self.get_software_root(dep['name'])) |
| 1078 | + dependency_roots.extend(self.get_software_root(dep["name"])) |
| 1079 | + |
| 1080 | + for root in dependency_roots: |
| 1081 | + self._add_dependency_cpp_headers(root, extra_dirs=cpp) |
| 1082 | + self._add_dependency_linker_paths(root, extra_dirs=ld) |
| 1083 | + |
| 1084 | + def _add_dependency_cpp_headers(self, dep_root, extra_dirs=None): |
| 1085 | + """ |
| 1086 | + Append prepocessor paths for given dependency root directory |
| 1087 | + """ |
| 1088 | + if extra_dirs is None: |
| 1089 | + extra_dirs = () |
| 1090 | + |
| 1091 | + header_dirs = ["include"] |
| 1092 | + header_dirs = unique_ordered_extend(header_dirs, extra_dirs) |
| 1093 | + |
| 1094 | + # mode of operation is defined by search-path-cpp-headers option |
| 1095 | + # toolchain option has precedence over build option |
| 1096 | + cpp_headers_mode = DEFAULT_SEARCH_PATH_CPP_HEADERS |
| 1097 | + build_opt = build_option("search_path_cpp_headers") |
| 1098 | + if self.options.get("search-path-cpp-headers") is not None: |
| 1099 | + cpp_headers_mode = self.options.option("search-path-cpp-headers") |
| 1100 | + self.log.debug("search-path-cpp-headers set by toolchain option: %s", cpp_headers_mode) |
| 1101 | + elif build_opt is not None: |
| 1102 | + cpp_headers_mode = build_opt |
| 1103 | + self.log.debug("search-path-cpp-headers set by build option: %s", cpp_headers_mode) |
| 1104 | + |
| 1105 | + if cpp_headers_mode not in SEARCH_PATH_CPP_HEADERS: |
| 1106 | + raise EasyBuildError( |
| 1107 | + "Unknown value selected for option search-path-cpp-headers: %s. Choose one of: %s", |
| 1108 | + cpp_headers_mode, ", ".join(SEARCH_PATH_CPP_HEADERS) |
| 1109 | + ) |
| 1110 | + |
| 1111 | + for env_var in SEARCH_PATH_CPP_HEADERS[cpp_headers_mode]: |
| 1112 | + self.log.debug("Adding header paths to toolchain variable '%s': %s", env_var, dep_root) |
| 1113 | + self.variables.append_subdirs(env_var, dep_root, subdirs=header_dirs) |
| 1114 | + |
| 1115 | + def _add_dependency_linker_paths(self, dep_root, extra_dirs=None): |
| 1116 | + """ |
| 1117 | + Append linker paths for given dependency root directory |
| 1118 | + """ |
| 1119 | + if extra_dirs is None: |
| 1120 | + extra_dirs = () |
| 1121 | + |
| 1122 | + lib_dirs = ["lib64", "lib"] |
| 1123 | + lib_dirs = unique_ordered_extend(lib_dirs, extra_dirs) |
1081 | 1124 |
|
1082 | | - for root in roots: |
1083 | | - self.variables.append_subdirs("CPPFLAGS", root, subdirs=cpp_paths) |
1084 | | - self.variables.append_subdirs("LDFLAGS", root, subdirs=ld_paths) |
| 1125 | + env_var = "LDFLAGS" |
| 1126 | + self.log.debug("Adding lib paths to toolchain variable '%s': %s", env_var, dep_root) |
| 1127 | + self.variables.append_subdirs(env_var, dep_root, subdirs=lib_dirs) |
1085 | 1128 |
|
1086 | 1129 | def _setenv_variables(self, donotset=None, verbose=True): |
1087 | 1130 | """Actually set the environment variables""" |
|
0 commit comments