diff options
author | Michael Hirsch, Ph.D <scivision@users.noreply.github.com> | 2019-02-05 16:41:44 -0500 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2019-02-05 22:41:44 +0100 |
commit | 70e6f4198c13c42e1640e4c80ada8f772b77042b (patch) | |
tree | 8307b98e05420a7a9e76dedad510c7c260d740d7 | |
parent | db61d018ce575f3b5524ded328373faebdf879b7 (diff) | |
download | meson-70e6f4198c13c42e1640e4c80ada8f772b77042b.zip meson-70e6f4198c13c42e1640e4c80ada8f772b77042b.tar.gz meson-70e6f4198c13c42e1640e4c80ada8f772b77042b.tar.bz2 |
Fortran 2008 submodule (#4874)
-rw-r--r-- | docs/markdown/snippets/fortran_submodule.md | 12 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 39 | ||||
-rw-r--r-- | mesonbuild/compilers/fortran.py | 2 | ||||
-rw-r--r-- | test cases/fortran/12 submodule/a1.f90 | 25 | ||||
-rw-r--r-- | test cases/fortran/12 submodule/a2.f90 | 10 | ||||
-rw-r--r-- | test cases/fortran/12 submodule/a3.f90 | 10 | ||||
-rw-r--r-- | test cases/fortran/12 submodule/child.f90 | 10 | ||||
-rw-r--r-- | test cases/fortran/12 submodule/meson.build | 7 | ||||
-rw-r--r-- | test cases/fortran/12 submodule/parent.f90 | 23 |
9 files changed, 131 insertions, 7 deletions
diff --git a/docs/markdown/snippets/fortran_submodule.md b/docs/markdown/snippets/fortran_submodule.md new file mode 100644 index 0000000..9e4b9cc --- /dev/null +++ b/docs/markdown/snippets/fortran_submodule.md @@ -0,0 +1,12 @@ +## Fortran submodule support + +Initial support for Fortran ``submodule`` was added, where the submodule is in +the same or different file than the parent ``module``. +The submodule hierarchy specified in the source Fortran code `submodule` +statements are used by Meson to resolve source file dependencies. +For example: + +```fortran +submodule (ancestor:parent) child +``` + diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 87f9b38..463e999 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - +from typing import List import os import re import shlex @@ -29,7 +29,7 @@ from .. import build from .. import mlog from .. import dependencies from .. import compilers -from ..compilers import CompilerArgs, CCompiler, VisualStudioCCompiler +from ..compilers import CompilerArgs, CCompiler, VisualStudioCCompiler, FortranCompiler from ..linkers import ArLinker from ..mesonlib import File, MachineChoice, MesonException, OrderedSet from ..mesonlib import get_compiler_for_source, has_path_sep @@ -1826,7 +1826,8 @@ rule FORTRAN_DEP_HACK%s if compiler is None: self.fortran_deps[target.get_basename()] = {} return - modre = re.compile(r"\bmodule\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) module_files = {} for s in target.get_sources(): # FIXME, does not work for Fortran sources generated by @@ -1849,11 +1850,23 @@ rule FORTRAN_DEP_HACK%s 'two files %s and %s.' % (modname, module_files[modname], s)) module_files[modname] = s + else: + submodmatch = submodre.match(line) + if submodmatch is not None: + submodname = submodmatch.group(2).lower() + if submodname in module_files: + raise InvalidArguments( + 'Namespace collision: submodule %s defined in ' + 'two files %s and %s.' % + (submodname, module_files[submodname], s)) + module_files[submodname] = s + self.fortran_deps[target.get_basename()] = module_files - def get_fortran_deps(self, compiler, src, target): + def get_fortran_deps(self, compiler: FortranCompiler, src: str, target) -> List[str]: mod_files = [] usere = re.compile(r"\s*use\s+(\w+)", re.IGNORECASE) + submodre = re.compile(r"\s*\bsubmodule\b\s+\((\w+:?\w+)\)\s+(\w+)\s*$", re.IGNORECASE) dirname = self.get_target_private_dir(target) tdeps = self.fortran_deps[target.get_basename()] with open(src) as f: @@ -1879,9 +1892,23 @@ rule FORTRAN_DEP_HACK%s # the same name. if mod_source_file.fname == os.path.basename(src): continue - mod_name = compiler.module_name_to_filename( - usematch.group(1)) + mod_name = compiler.module_name_to_filename(usename) mod_files.append(os.path.join(dirname, mod_name)) + else: + submodmatch = submodre.match(line) + if submodmatch is not None: + parents = submodmatch.group(1).lower().split(':') + 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)) + if tdeps[parent].fname == os.path.basename(src): # same file + continue + mod_name = compiler.module_name_to_filename(parent) + mod_files.append(os.path.join(dirname, mod_name)) + return mod_files def get_cross_stdlib_args(self, target, compiler): diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index eea1660..8c50736 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -179,7 +179,7 @@ class FortranCompiler(Compiler): return parameter_list - def module_name_to_filename(self, module_name): + def module_name_to_filename(self, module_name: str) -> str: return module_name.lower() + '.mod' def get_std_shared_lib_link_args(self): diff --git a/test cases/fortran/12 submodule/a1.f90 b/test cases/fortran/12 submodule/a1.f90 new file mode 100644 index 0000000..cb44916 --- /dev/null +++ b/test cases/fortran/12 submodule/a1.f90 @@ -0,0 +1,25 @@ +module a1 +implicit none + +interface +module elemental real function pi2tau(pi) + real, intent(in) :: pi +end function pi2tau + +module real function get_pi() +end function get_pi +end interface + +end module a1 + +program hierN + +use a1 + +pi = get_pi() + +tau = pi2tau(pi) + +print *,'pi=',pi,'tau=',tau + +end program diff --git a/test cases/fortran/12 submodule/a2.f90 b/test cases/fortran/12 submodule/a2.f90 new file mode 100644 index 0000000..b3ce1f0 --- /dev/null +++ b/test cases/fortran/12 submodule/a2.f90 @@ -0,0 +1,10 @@ +submodule (a1) a2 + +contains + +module procedure pi2tau + pi2tau = 2*pi +end procedure pi2tau + + +end submodule a2 diff --git a/test cases/fortran/12 submodule/a3.f90 b/test cases/fortran/12 submodule/a3.f90 new file mode 100644 index 0000000..d6929b0 --- /dev/null +++ b/test cases/fortran/12 submodule/a3.f90 @@ -0,0 +1,10 @@ +submodule (a1:a2) a3 + +contains + +module procedure get_pi + get_pi = 4.*atan(1.) +end procedure get_pi + + +end submodule a3 diff --git a/test cases/fortran/12 submodule/child.f90 b/test cases/fortran/12 submodule/child.f90 new file mode 100644 index 0000000..aa5bb5e --- /dev/null +++ b/test cases/fortran/12 submodule/child.f90 @@ -0,0 +1,10 @@ +submodule (mother) daughter + +contains + +module procedure pi2tau + pi2tau = 2*pi +end procedure pi2tau + +end submodule daughter + diff --git a/test cases/fortran/12 submodule/meson.build b/test cases/fortran/12 submodule/meson.build new file mode 100644 index 0000000..cd62a30 --- /dev/null +++ b/test cases/fortran/12 submodule/meson.build @@ -0,0 +1,7 @@ +project('submodule single level', 'fortran') + +hier2 = executable('single', 'parent.f90','child.f90') +test('single-level hierarchy', hier2) + +hierN = executable('multi', 'a1.f90', 'a2.f90', 'a3.f90') +test('multi-level hierarchy', hierN) diff --git a/test cases/fortran/12 submodule/parent.f90 b/test cases/fortran/12 submodule/parent.f90 new file mode 100644 index 0000000..05fe431 --- /dev/null +++ b/test cases/fortran/12 submodule/parent.f90 @@ -0,0 +1,23 @@ +module mother +real, parameter :: pi = 4.*atan(1.) +real :: tau + +interface +module elemental real function pi2tau(pi) + real, intent(in) :: pi +end function pi2tau +end interface + +contains + +end module mother + + +program hier1 +use mother + +tau = pi2tau(pi) + +print *,'pi=',pi, 'tau=', tau + +end program |