|
|
|
@ -36,6 +36,8 @@ from ..mesonlib import get_compiler_for_source, has_path_sep |
|
|
|
|
from .backends import CleanTrees |
|
|
|
|
from ..build import InvalidArguments |
|
|
|
|
|
|
|
|
|
FORTRAN_SUBMOD_PAT = r"\s*submodule\s*\((\w+:?\w+)\)\s*(\w+)\s*$" |
|
|
|
|
|
|
|
|
|
if mesonlib.is_windows(): |
|
|
|
|
quote_func = lambda s: '"{}"'.format(s) |
|
|
|
|
execute_wrapper = 'cmd /c' |
|
|
|
@ -1812,6 +1814,9 @@ rule FORTRAN_DEP_HACK%s |
|
|
|
|
elem.write(outfile) |
|
|
|
|
|
|
|
|
|
def scan_fortran_module_outputs(self, target): |
|
|
|
|
""" |
|
|
|
|
Find all module and submodule made available in a Fortran code file. |
|
|
|
|
""" |
|
|
|
|
compiler = None |
|
|
|
|
for lang, c in self.build.compilers.items(): |
|
|
|
|
if lang == 'fortran': |
|
|
|
@ -1822,8 +1827,9 @@ rule FORTRAN_DEP_HACK%s |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
modre = re.compile(r"\s*\bmodule\b\s+(\w+)\s*$", re.IGNORECASE) |
|
|
|
|
submodre = re.compile(r"\s*\bsubmodule\b\s+\((\w+:?\w+)\)\s+(\w+)\s*$", re.IGNORECASE) |
|
|
|
|
submodre = re.compile(FORTRAN_SUBMOD_PAT, re.IGNORECASE) |
|
|
|
|
module_files = {} |
|
|
|
|
submodule_files = {} |
|
|
|
|
for s in target.get_sources(): |
|
|
|
|
# FIXME, does not work for Fortran sources generated by |
|
|
|
|
# custom_target() and generator() as those are run after |
|
|
|
@ -1847,19 +1853,22 @@ rule FORTRAN_DEP_HACK%s |
|
|
|
|
else: |
|
|
|
|
submodmatch = submodre.match(line) |
|
|
|
|
if submodmatch is not None: |
|
|
|
|
submodname = submodmatch.group(2).lower() |
|
|
|
|
if submodname in module_files: |
|
|
|
|
# '_' is arbitrarily used to distinguish submod from mod. |
|
|
|
|
parents = submodmatch.group(1).lower().split(':') |
|
|
|
|
submodname = parents[0] + '_' + submodmatch.group(2).lower() |
|
|
|
|
|
|
|
|
|
if submodname in submodule_files: |
|
|
|
|
raise InvalidArguments( |
|
|
|
|
'Namespace collision: submodule %s defined in ' |
|
|
|
|
'two files %s and %s.' % |
|
|
|
|
(submodname, module_files[submodname], s)) |
|
|
|
|
module_files[submodname] = s |
|
|
|
|
(submodname, submodule_files[submodname], s)) |
|
|
|
|
submodule_files[submodname] = s |
|
|
|
|
|
|
|
|
|
self.fortran_deps[target.get_basename()] = module_files |
|
|
|
|
self.fortran_deps[target.get_basename()] = {**module_files, **submodule_files} |
|
|
|
|
|
|
|
|
|
def get_fortran_deps(self, compiler: FortranCompiler, src: str, target) -> List[str]: |
|
|
|
|
""" |
|
|
|
|
Find all modules and submodules needed by a target |
|
|
|
|
Find all module and submodule needed by a Fortran target |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
dirname = Path(self.get_target_private_dir(target)) |
|
|
|
@ -2774,7 +2783,7 @@ def _scan_fortran_file_deps(src: str, srcdir: Path, dirname: Path, tdeps, compil |
|
|
|
|
|
|
|
|
|
incre = re.compile(r"#?include\s*['\"](\w+\.\w+)['\"]\s*$", re.IGNORECASE) |
|
|
|
|
usere = re.compile(r"\s*use,?\s*(?:non_intrinsic)?\s*(?:::)?\s*(\w+)", re.IGNORECASE) |
|
|
|
|
submodre = re.compile(r"\s*\bsubmodule\b\s+\((\w+:?\w+)\)\s+(\w+)\s*$", re.IGNORECASE) |
|
|
|
|
submodre = re.compile(FORTRAN_SUBMOD_PAT, re.IGNORECASE) |
|
|
|
|
|
|
|
|
|
mod_files = [] |
|
|
|
|
src = Path(src) |
|
|
|
@ -2822,17 +2831,18 @@ def _scan_fortran_file_deps(src: str, srcdir: Path, dirname: Path, tdeps, compil |
|
|
|
|
assert len(parents) in (1, 2), ( |
|
|
|
|
'submodule ancestry must be specified as' |
|
|
|
|
' ancestor:parent but Meson found {}'.parents) |
|
|
|
|
for parent in parents: |
|
|
|
|
if parent not in tdeps: |
|
|
|
|
raise MesonException("submodule {} relies on parent module {} that was not found.".format(submodmatch.group(2).lower(), parent)) |
|
|
|
|
submodsrcfile = srcdir / tdeps[parent].fname |
|
|
|
|
if not submodsrcfile.is_file(): |
|
|
|
|
if submodsrcfile.name != src.name: # generated source file |
|
|
|
|
pass |
|
|
|
|
else: # subproject |
|
|
|
|
continue |
|
|
|
|
elif submodsrcfile.samefile(src): # self-reference |
|
|
|
|
|
|
|
|
|
ancestor_child = '_'.join(parents) |
|
|
|
|
if ancestor_child not in tdeps: |
|
|
|
|
raise MesonException("submodule {} relies on ancestor module {} that was not found.".format(submodmatch.group(2).lower(), ancestor_child.split('_')[0])) |
|
|
|
|
submodsrcfile = srcdir / tdeps[ancestor_child].fname |
|
|
|
|
if not submodsrcfile.is_file(): |
|
|
|
|
if submodsrcfile.name != src.name: # generated source file |
|
|
|
|
pass |
|
|
|
|
else: # subproject |
|
|
|
|
continue |
|
|
|
|
mod_name = compiler.module_name_to_filename(parent) |
|
|
|
|
mod_files.append(str(dirname / mod_name)) |
|
|
|
|
elif submodsrcfile.samefile(src): # self-reference |
|
|
|
|
continue |
|
|
|
|
mod_name = compiler.module_name_to_filename(ancestor_child) |
|
|
|
|
mod_files.append(str(dirname / mod_name)) |
|
|
|
|
return mod_files |
|
|
|
|