Merge pull request #5039 from scivision/submod
BUGFIX: allow Fortran submodule to have same name as module
This commit is contained in:
commit
6253bbc6cc
|
@ -36,6 +36,8 @@ from ..mesonlib import get_compiler_for_source, has_path_sep
|
||||||
from .backends import CleanTrees
|
from .backends import CleanTrees
|
||||||
from ..build import InvalidArguments
|
from ..build import InvalidArguments
|
||||||
|
|
||||||
|
FORTRAN_SUBMOD_PAT = r"\s*submodule\s*\((\w+:?\w+)\)\s*(\w+)\s*$"
|
||||||
|
|
||||||
if mesonlib.is_windows():
|
if mesonlib.is_windows():
|
||||||
quote_func = lambda s: '"{}"'.format(s)
|
quote_func = lambda s: '"{}"'.format(s)
|
||||||
execute_wrapper = 'cmd /c'
|
execute_wrapper = 'cmd /c'
|
||||||
|
@ -1812,6 +1814,9 @@ rule FORTRAN_DEP_HACK%s
|
||||||
elem.write(outfile)
|
elem.write(outfile)
|
||||||
|
|
||||||
def scan_fortran_module_outputs(self, target):
|
def scan_fortran_module_outputs(self, target):
|
||||||
|
"""
|
||||||
|
Find all module and submodule made available in a Fortran code file.
|
||||||
|
"""
|
||||||
compiler = None
|
compiler = None
|
||||||
for lang, c in self.build.compilers.items():
|
for lang, c in self.build.compilers.items():
|
||||||
if lang == 'fortran':
|
if lang == 'fortran':
|
||||||
|
@ -1822,8 +1827,9 @@ rule FORTRAN_DEP_HACK%s
|
||||||
return
|
return
|
||||||
|
|
||||||
modre = re.compile(r"\s*\bmodule\b\s+(\w+)\s*$", re.IGNORECASE)
|
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 = {}
|
module_files = {}
|
||||||
|
submodule_files = {}
|
||||||
for s in target.get_sources():
|
for s in target.get_sources():
|
||||||
# FIXME, does not work for Fortran sources generated by
|
# FIXME, does not work for Fortran sources generated by
|
||||||
# custom_target() and generator() as those are run after
|
# custom_target() and generator() as those are run after
|
||||||
|
@ -1847,19 +1853,22 @@ rule FORTRAN_DEP_HACK%s
|
||||||
else:
|
else:
|
||||||
submodmatch = submodre.match(line)
|
submodmatch = submodre.match(line)
|
||||||
if submodmatch is not None:
|
if submodmatch is not None:
|
||||||
submodname = submodmatch.group(2).lower()
|
# '_' is arbitrarily used to distinguish submod from mod.
|
||||||
if submodname in module_files:
|
parents = submodmatch.group(1).lower().split(':')
|
||||||
|
submodname = parents[0] + '_' + submodmatch.group(2).lower()
|
||||||
|
|
||||||
|
if submodname in submodule_files:
|
||||||
raise InvalidArguments(
|
raise InvalidArguments(
|
||||||
'Namespace collision: submodule %s defined in '
|
'Namespace collision: submodule %s defined in '
|
||||||
'two files %s and %s.' %
|
'two files %s and %s.' %
|
||||||
(submodname, module_files[submodname], s))
|
(submodname, submodule_files[submodname], s))
|
||||||
module_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]:
|
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))
|
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)
|
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)
|
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 = []
|
mod_files = []
|
||||||
src = Path(src)
|
src = Path(src)
|
||||||
|
@ -2822,10 +2831,11 @@ def _scan_fortran_file_deps(src: str, srcdir: Path, dirname: Path, tdeps, compil
|
||||||
assert len(parents) in (1, 2), (
|
assert len(parents) in (1, 2), (
|
||||||
'submodule ancestry must be specified as'
|
'submodule ancestry must be specified as'
|
||||||
' ancestor:parent but Meson found {}'.parents)
|
' ancestor:parent but Meson found {}'.parents)
|
||||||
for parent in parents:
|
|
||||||
if parent not in tdeps:
|
ancestor_child = '_'.join(parents)
|
||||||
raise MesonException("submodule {} relies on parent module {} that was not found.".format(submodmatch.group(2).lower(), parent))
|
if ancestor_child not in tdeps:
|
||||||
submodsrcfile = srcdir / tdeps[parent].fname
|
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 not submodsrcfile.is_file():
|
||||||
if submodsrcfile.name != src.name: # generated source file
|
if submodsrcfile.name != src.name: # generated source file
|
||||||
pass
|
pass
|
||||||
|
@ -2833,6 +2843,6 @@ def _scan_fortran_file_deps(src: str, srcdir: Path, dirname: Path, tdeps, compil
|
||||||
continue
|
continue
|
||||||
elif submodsrcfile.samefile(src): # self-reference
|
elif submodsrcfile.samefile(src): # self-reference
|
||||||
continue
|
continue
|
||||||
mod_name = compiler.module_name_to_filename(parent)
|
mod_name = compiler.module_name_to_filename(ancestor_child)
|
||||||
mod_files.append(str(dirname / mod_name))
|
mod_files.append(str(dirname / mod_name))
|
||||||
return mod_files
|
return mod_files
|
||||||
|
|
|
@ -180,7 +180,18 @@ class FortranCompiler(Compiler):
|
||||||
return parameter_list
|
return parameter_list
|
||||||
|
|
||||||
def module_name_to_filename(self, module_name: str) -> str:
|
def module_name_to_filename(self, module_name: str) -> str:
|
||||||
return module_name.lower() + '.mod'
|
if '_' in module_name: # submodule
|
||||||
|
s = module_name.lower()
|
||||||
|
if self.id in ('gcc', 'intel'):
|
||||||
|
filename = s.replace('_', '@') + '.smod'
|
||||||
|
elif self.id in ('pgi', 'flang'):
|
||||||
|
filename = s.replace('_', '-') + '.mod'
|
||||||
|
else:
|
||||||
|
filename = s + '.mod'
|
||||||
|
else: # module
|
||||||
|
filename = module_name.lower() + '.mod'
|
||||||
|
|
||||||
|
return filename
|
||||||
|
|
||||||
def get_std_shared_lib_link_args(self):
|
def get_std_shared_lib_link_args(self):
|
||||||
return CCompiler.get_std_shared_lib_link_args(self)
|
return CCompiler.get_std_shared_lib_link_args(self)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
submodule (mother) daughter
|
submodule (parent) parent
|
||||||
|
|
||||||
contains
|
contains
|
||||||
|
|
||||||
|
@ -6,5 +6,5 @@ module procedure pi2tau
|
||||||
pi2tau = 2*pi
|
pi2tau = 2*pi
|
||||||
end procedure pi2tau
|
end procedure pi2tau
|
||||||
|
|
||||||
end submodule daughter
|
end submodule parent
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
module mother
|
module parent
|
||||||
real, parameter :: pi = 4.*atan(1.)
|
real, parameter :: pi = 4.*atan(1.)
|
||||||
real :: tau
|
real :: tau
|
||||||
|
|
||||||
|
@ -8,13 +8,10 @@ module elemental real function pi2tau(pi)
|
||||||
end function pi2tau
|
end function pi2tau
|
||||||
end interface
|
end interface
|
||||||
|
|
||||||
contains
|
end module parent
|
||||||
|
|
||||||
end module mother
|
|
||||||
|
|
||||||
|
|
||||||
program hier1
|
use parent
|
||||||
use mother
|
|
||||||
|
|
||||||
tau = pi2tau(pi)
|
tau = pi2tau(pi)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue