From bd2394e8724a7a95f8beeb3839707e495be41fc0 Mon Sep 17 00:00:00 2001 From: Jonas Lundholm Bertelsen Date: Wed, 20 Jan 2021 18:11:02 +0100 Subject: Use case-insensitive suffix check for fortran In Fortran it is common to use capital F in the suffix (eg. '.F90') if the source file makes use of preprocessor statements. Such files should probably be treated like all other fortran files by meson. Case insensitivity for suffixes was already implemented several places in meson before this. So most likely, the few places changed here were oversights anyway. --- mesonbuild/backend/ninjabackend.py | 4 ++-- mesonbuild/scripts/depscan.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index d66708c..a008795 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -637,7 +637,7 @@ int dummy; if self.environment.is_llvm_ir(source) or \ self.environment.is_assembly(source): return False - suffix = os.path.splitext(source)[1][1:] + suffix = os.path.splitext(source)[1][1:].lower() for lang in self.langs_cant_unity: if lang not in target.compilers: continue @@ -925,7 +925,7 @@ int dummy; all_suffixes = set(compilers.lang_suffixes['cpp']) | set(compilers.lang_suffixes['fortran']) selected_sources = [] for source in compiled_sources: - ext = os.path.splitext(source)[1][1:] + ext = os.path.splitext(source)[1][1:].lower() if ext in all_suffixes: selected_sources.append(source) return selected_sources diff --git a/mesonbuild/scripts/depscan.py b/mesonbuild/scripts/depscan.py index df7df48..c85f8e7 100644 --- a/mesonbuild/scripts/depscan.py +++ b/mesonbuild/scripts/depscan.py @@ -46,7 +46,7 @@ class DependencyScanner: self.sources_with_exports = [] # type: T.List[str] def scan_file(self, fname: str) -> None: - suffix = os.path.splitext(fname)[1][1:] + suffix = os.path.splitext(fname)[1][1:].lower() if suffix in lang_suffixes['fortran']: self.scan_fortran_file(fname) elif suffix in lang_suffixes['cpp']: @@ -131,7 +131,7 @@ class DependencyScanner: return objname def module_name_for(self, src: str) -> str: - suffix= os.path.splitext(src)[1][1:] + suffix = os.path.splitext(src)[1][1:].lower() if suffix in lang_suffixes['fortran']: exported = self.exports[src] # Module foo:bar goes to a file name foo@bar.smod -- cgit v1.1 From ea34a92632a0622bd140ec8160dd721e1f6ba040 Mon Sep 17 00:00:00 2001 From: Jonas Lundholm Bertelsen Date: Wed, 20 Jan 2021 18:18:54 +0100 Subject: When iterating link_targets, include link_whole_targets too (fortran) This fixes fortran includes and fortran orderdeps for libraries that were under link_whole_targets. --- mesonbuild/backend/backends.py | 3 ++- mesonbuild/backend/ninjabackend.py | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index ced1d7d..31ea1dd 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -14,6 +14,7 @@ from collections import OrderedDict from functools import lru_cache +from itertools import chain from pathlib import Path import enum import json @@ -767,7 +768,7 @@ class Backend: # pkg-config puts the thread flags itself via `Cflags:` # Fortran requires extra include directives. if compiler.language == 'fortran': - for lt in target.link_targets: + for lt in chain(target.link_targets, target.link_whole_targets): priv_dir = self.get_target_private_dir(lt) commands += compiler.get_include_args(priv_dir, False) return commands diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index a008795..6a80299 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2595,7 +2595,10 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) def get_fortran_orderdeps(self, target, compiler): if compiler.language != 'fortran': return [] - return [os.path.join(self.get_target_dir(lt), lt.get_filename()) for lt in target.link_targets] + return [ + os.path.join(self.get_target_dir(lt), lt.get_filename()) + for lt in itertools.chain(target.link_targets, target.link_whole_targets) + ] def generate_msvc_pch_command(self, target, compiler, pch): header = pch[0] -- cgit v1.1 From 2636eebd64221909157d93509ac72a5990f85060 Mon Sep 17 00:00:00 2001 From: Jonas Lundholm Bertelsen Date: Wed, 20 Jan 2021 21:51:56 +0100 Subject: Unity build reverts to normal for fortran fix The `determine_ext_objs` function did not take into account that fortran (and d) does not support unity builds. This caused failures in some cases. --- mesonbuild/backend/backends.py | 8 ++++++++ mesonbuild/backend/ninjabackend.py | 9 ++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 31ea1dd..8143941 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -45,6 +45,11 @@ if T.TYPE_CHECKING: InstallType = T.List[T.Tuple[str, str, T.Optional['FileMode']]] InstallSubdirsType = T.List[T.Tuple[str, str, T.Optional['FileMode'], T.Tuple[T.Set[str], T.Set[str]]]] +# Languages that can mix with C or C++ but don't support unity builds yet +# because the syntax we use for unity builds is specific to C/++/ObjC/++. +# Assembly files cannot be unitified and neither can LLVM IR files +LANGS_CANT_UNITY = ('d', 'fortran') + class TestProtocol(enum.Enum): EXITCODE = 0 @@ -637,6 +642,9 @@ class Backend: unity_size = self.get_option_for_target(OptionKey('unity_size'), extobj.target) for comp, srcs in compsrcs.items(): + if comp.language in LANGS_CANT_UNITY: + sources += srcs + continue for i in range(len(srcs) // unity_size + 1): osrc = self.get_unity_source_file(extobj.target, comp.get_default_suffix(), i) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 6a80299..b121d42 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -626,11 +626,6 @@ int dummy; srcs[f] = s return srcs - # Languages that can mix with C or C++ but don't support unity builds yet - # because the syntax we use for unity builds is specific to C/++/ObjC/++. - # Assembly files cannot be unitified and neither can LLVM IR files - langs_cant_unity = ('d', 'fortran') - def get_target_source_can_unity(self, target, source): if isinstance(source, File): source = source.fname @@ -638,7 +633,7 @@ int dummy; self.environment.is_assembly(source): return False suffix = os.path.splitext(source)[1][1:].lower() - for lang in self.langs_cant_unity: + for lang in backends.LANGS_CANT_UNITY: if lang not in target.compilers: continue if suffix in target.compilers[lang].file_suffixes: @@ -769,7 +764,7 @@ int dummy; if is_unity: # Warn about incompatible sources if a unity build is enabled langs = set(target.compilers.keys()) - langs_cant = langs.intersection(self.langs_cant_unity) + langs_cant = langs.intersection(backends.LANGS_CANT_UNITY) if langs_cant: langs_are = langs = ', '.join(langs_cant).upper() langs_are += ' are' if len(langs_cant) > 1 else ' is' -- cgit v1.1 From d3ae808742d56f298ef480ae54cc0c64af35a34e Mon Sep 17 00:00:00 2001 From: Jonas Lundholm Bertelsen Date: Wed, 20 Jan 2021 18:22:01 +0100 Subject: Add fortran test with an install:yes static library This adds a test which makes use of an install:yes static library that depends on another static library. This triggers a promotion to link_whole_target inside meson which takes different code paths in certain places. Also makes use of .F90 source (capital F) to test for case (in)sensitivity. --- test cases/fortran/21 install static/main.f90 | 4 ++++ test cases/fortran/21 install static/main_lib.f90 | 16 ++++++++++++++++ test cases/fortran/21 install static/meson.build | 20 ++++++++++++++++++++ .../subprojects/static_hello/meson.build | 12 ++++++++++++ .../subprojects/static_hello/static_hello.f90 | 17 +++++++++++++++++ test cases/fortran/21 install static/test.json | 5 +++++ 6 files changed, 74 insertions(+) create mode 100644 test cases/fortran/21 install static/main.f90 create mode 100644 test cases/fortran/21 install static/main_lib.f90 create mode 100644 test cases/fortran/21 install static/meson.build create mode 100644 test cases/fortran/21 install static/subprojects/static_hello/meson.build create mode 100644 test cases/fortran/21 install static/subprojects/static_hello/static_hello.f90 create mode 100644 test cases/fortran/21 install static/test.json diff --git a/test cases/fortran/21 install static/main.f90 b/test cases/fortran/21 install static/main.f90 new file mode 100644 index 0000000..c83a6a0 --- /dev/null +++ b/test cases/fortran/21 install static/main.f90 @@ -0,0 +1,4 @@ +use main_lib +implicit none +call main_hello() +end program \ No newline at end of file diff --git a/test cases/fortran/21 install static/main_lib.f90 b/test cases/fortran/21 install static/main_lib.f90 new file mode 100644 index 0000000..5f3cb45 --- /dev/null +++ b/test cases/fortran/21 install static/main_lib.f90 @@ -0,0 +1,16 @@ +module main_lib + + use static_hello + implicit none + + private + public :: main_hello + + contains + + subroutine main_hello + call static_say_hello() + print *, "Main hello routine finished." + end subroutine main_hello + +end module main_lib diff --git a/test cases/fortran/21 install static/meson.build b/test cases/fortran/21 install static/meson.build new file mode 100644 index 0000000..a91613f --- /dev/null +++ b/test cases/fortran/21 install static/meson.build @@ -0,0 +1,20 @@ +# Based on 'fortran/5 static', but: +# - Uses a subproject dependency +# - Is an install:true static library to trigger certain codepath (promotion to link_whole) +# - Does fortran code 'generation' with configure_file +# - Uses .F90 ext (capital F typically denotes a dependence on preprocessor treatment, which however is not used) +project('try-static-subproject-dependency', 'fortran', default_options: ['default_library=static']) + +static_dep = dependency('static_hello', fallback: ['static_hello', 'static_hello_dep']) + +mainsrc = 'main_lib.f90' +mainsrc = configure_file( + command: [find_program('cp'), '@INPUT@', '@OUTPUT@'], + input: mainsrc, + output: 'main_lib_output.F90' +) +main_lib = library('mainstatic', mainsrc, dependencies: static_dep, install: true) +main_dep = declare_dependency(link_with: main_lib) + +main_exe = executable('main_exe', 'main.f90', dependencies: main_dep) +test('static_subproject_test', main_exe) diff --git a/test cases/fortran/21 install static/subprojects/static_hello/meson.build b/test cases/fortran/21 install static/subprojects/static_hello/meson.build new file mode 100644 index 0000000..7edca39 --- /dev/null +++ b/test cases/fortran/21 install static/subprojects/static_hello/meson.build @@ -0,0 +1,12 @@ +project('static-hello', 'fortran') + +# staticlibsource = 'static_hello.f90' +staticlibsource = configure_file( + command: [find_program('cp'), '@INPUT@', '@OUTPUT@'], + input: 'static_hello.f90', + output: 'static_hello_output.F90' +) + +static_hello_lib = static_library('static_hello', staticlibsource, install: false) + +static_hello_dep = declare_dependency(link_with: static_hello_lib) diff --git a/test cases/fortran/21 install static/subprojects/static_hello/static_hello.f90 b/test cases/fortran/21 install static/subprojects/static_hello/static_hello.f90 new file mode 100644 index 0000000..5407560 --- /dev/null +++ b/test cases/fortran/21 install static/subprojects/static_hello/static_hello.f90 @@ -0,0 +1,17 @@ +module static_hello +implicit none + +private +public :: static_say_hello + +interface static_say_hello + module procedure say_hello +end interface static_say_hello + +contains + +subroutine say_hello + print *, "Static library called." +end subroutine say_hello + +end module static_hello diff --git a/test cases/fortran/21 install static/test.json b/test cases/fortran/21 install static/test.json new file mode 100644 index 0000000..b31e91d --- /dev/null +++ b/test cases/fortran/21 install static/test.json @@ -0,0 +1,5 @@ +{ + "installed": [ + {"file": "usr/lib/libmainstatic.a", "type": "file"} + ] +} \ No newline at end of file -- cgit v1.1