Refactored _find_matches_in_path
Now the function takes a compiler language and computes the compiler names and detection function. Skipping values while iterating has been changed to filter input values + iterate without jumps.
This commit is contained in:
parent
0a8f4ad42e
commit
cae7e075a6
@ -255,7 +255,7 @@ def find_compilers(self, *path_hints):
|
||||
clist = [comp for cl in compiler_lists for comp in cl]
|
||||
return clist
|
||||
|
||||
def find_compiler(self, cmp_cls, *path):
|
||||
def find_compiler(self, cmp_cls, *search_paths):
|
||||
"""Try to find the given type of compiler in the user's
|
||||
environment. For each set of compilers found, this returns
|
||||
compiler objects with the cc, cxx, f77, fc paths and the
|
||||
@ -268,24 +268,24 @@ def find_compiler(self, cmp_cls, *path):
|
||||
"""
|
||||
dicts = mp.parmap(
|
||||
lambda t: cmp_cls._find_matches_in_path(*t),
|
||||
[(cmp_cls.cc_names, cmp_cls.cc_version) + tuple(path),
|
||||
(cmp_cls.cxx_names, cmp_cls.cxx_version) + tuple(path),
|
||||
(cmp_cls.f77_names, cmp_cls.f77_version) + tuple(path),
|
||||
(cmp_cls.fc_names, cmp_cls.fc_version) + tuple(path)])
|
||||
[('cc',) + tuple(search_paths), ('cxx',) + tuple(search_paths),
|
||||
('f77',) + tuple(search_paths), ('fc',) + tuple(search_paths)])
|
||||
|
||||
all_keys = set()
|
||||
for d in dicts:
|
||||
all_keys.update(d)
|
||||
all_keys = set(key for d in dicts for key in d)
|
||||
|
||||
# Skip compilers with unknown version
|
||||
def has_known_version(x):
|
||||
"""Returns True if the key has not an unknown version."""
|
||||
version, _, _ = x
|
||||
return version != 'unknown'
|
||||
|
||||
valid_keys = filter(has_known_version, all_keys)
|
||||
|
||||
compilers = {}
|
||||
for k in all_keys:
|
||||
ver, pre, suf = k
|
||||
for k in valid_keys:
|
||||
ver, _, _ = k
|
||||
|
||||
# Skip compilers with unknown version.
|
||||
if ver == 'unknown':
|
||||
continue
|
||||
|
||||
paths = tuple(pn[k] if k in pn else None for pn in dicts)
|
||||
paths = tuple(pn.get(k, None) for pn in dicts)
|
||||
spec = spack.spec.CompilerSpec(cmp_cls.name, ver)
|
||||
|
||||
if ver in compilers:
|
||||
|
@ -249,37 +249,58 @@ def fc_version(cls, fc):
|
||||
return cls.default_version(fc)
|
||||
|
||||
@classmethod
|
||||
def _find_matches_in_path(cls, compiler_names, detect_version, *path):
|
||||
"""Finds compilers in the paths supplied.
|
||||
def _find_matches_in_path(cls, compiler_language, *search_paths):
|
||||
"""Finds compilers for a given language in the paths supplied.
|
||||
|
||||
Looks for all combinations of ``compiler_names`` with the
|
||||
``prefixes`` and ``suffixes`` defined for this compiler
|
||||
class. If any compilers match the compiler_names,
|
||||
prefixes, or suffixes, uses ``detect_version`` to figure
|
||||
out what version the compiler is.
|
||||
Looks for all combinations of ``compiler_names`` with the
|
||||
``prefixes`` and ``suffixes`` defined for this compiler
|
||||
class. If any compilers match the compiler_names,
|
||||
prefixes, or suffixes, uses ``detect_version`` to figure
|
||||
out what version the compiler is.
|
||||
|
||||
This returns a dict with compilers grouped by (prefix,
|
||||
suffix, version) tuples. This can be further organized by
|
||||
find().
|
||||
Args:
|
||||
compiler_language (str): language of the compiler (either
|
||||
'cc', 'cxx', 'f77' or 'fc')
|
||||
|
||||
*search_paths (list of paths): paths where to look for a
|
||||
compiler
|
||||
|
||||
Returns:
|
||||
Dictionary with compilers grouped by (version, prefix, suffix)
|
||||
tuples.
|
||||
"""
|
||||
def is_accessible_dir(x):
|
||||
"""Returns True if the argument is an accessible directory."""
|
||||
return os.path.isdir(x) and os.access(x, os.R_OK | os.X_OK)
|
||||
|
||||
# Select accessible directories
|
||||
search_directories = filter(is_accessible_dir, search_paths)
|
||||
|
||||
# Get compiler names and the callback to detect their versions
|
||||
compiler_names = getattr(cls, '{0}_names'.format(compiler_language))
|
||||
detect_version = getattr(cls, '{0}_version'.format(compiler_language))
|
||||
|
||||
# Compile all the regular expressions used for files beforehand
|
||||
prefixes = [''] + cls.prefixes
|
||||
suffixes = [''] + cls.suffixes
|
||||
regexp_fmt = r'^({0}){1}({2})$'
|
||||
search_regexps = [
|
||||
re.compile(regexp_fmt.format(prefix, re.escape(name), suffix))
|
||||
for prefix, name, suffix in
|
||||
itertools.product(prefixes, compiler_names, suffixes)
|
||||
]
|
||||
|
||||
# Select only the files matching a regexp
|
||||
checks = []
|
||||
for directory in path:
|
||||
if not (os.path.isdir(directory) and
|
||||
os.access(directory, os.R_OK | os.X_OK)):
|
||||
continue
|
||||
|
||||
files = os.listdir(directory)
|
||||
for exe in files:
|
||||
full_path = os.path.join(directory, exe)
|
||||
|
||||
prod = itertools.product(prefixes, compiler_names, suffixes)
|
||||
for pre, name, suf in prod:
|
||||
regex = r'^(%s)%s(%s)$' % (pre, re.escape(name), suf)
|
||||
|
||||
match = re.match(regex, exe)
|
||||
for d in search_directories:
|
||||
# Only select actual files, use the full path
|
||||
files = filter(
|
||||
os.path.isfile, [os.path.join(d, f) for f in os.listdir(d)]
|
||||
)
|
||||
for full_path in files:
|
||||
file = os.path.basename(full_path)
|
||||
for regexp in search_regexps:
|
||||
match = regexp.match(file)
|
||||
if match:
|
||||
key = (full_path,) + match.groups() + (detect_version,)
|
||||
checks.append(key)
|
||||
|
Loading…
Reference in New Issue
Block a user