aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Hirsch, Ph.D <scivision@users.noreply.github.com>2019-02-05 16:41:44 -0500
committerJussi Pakkanen <jpakkane@gmail.com>2019-02-05 22:41:44 +0100
commit70e6f4198c13c42e1640e4c80ada8f772b77042b (patch)
tree8307b98e05420a7a9e76dedad510c7c260d740d7
parentdb61d018ce575f3b5524ded328373faebdf879b7 (diff)
downloadmeson-70e6f4198c13c42e1640e4c80ada8f772b77042b.zip
meson-70e6f4198c13c42e1640e4c80ada8f772b77042b.tar.gz
meson-70e6f4198c13c42e1640e4c80ada8f772b77042b.tar.bz2
Fortran 2008 submodule (#4874)
-rw-r--r--docs/markdown/snippets/fortran_submodule.md12
-rw-r--r--mesonbuild/backend/ninjabackend.py39
-rw-r--r--mesonbuild/compilers/fortran.py2
-rw-r--r--test cases/fortran/12 submodule/a1.f9025
-rw-r--r--test cases/fortran/12 submodule/a2.f9010
-rw-r--r--test cases/fortran/12 submodule/a3.f9010
-rw-r--r--test cases/fortran/12 submodule/child.f9010
-rw-r--r--test cases/fortran/12 submodule/meson.build7
-rw-r--r--test cases/fortran/12 submodule/parent.f9023
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