Skip to content

Commit

Permalink
WIP: add initial support for llvm-flang
Browse files Browse the repository at this point in the history
  • Loading branch information
h-vetinari committed Jun 14, 2024
1 parent 0352c90 commit 72cfdc5
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 10 deletions.
4 changes: 2 additions & 2 deletions docs/markdown/Contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ Subsets of project tests can be selected with
time when only a certain part of Meson is being tested.
For example, a useful and easy contribution to Meson is making
sure the full set of compilers is supported. One could for example test
various Fortran compilers by setting `FC=ifort` or `FC=flang` or similar
with `./run_project_test.py --only fortran`.
various Fortran compilers by setting `FC=ifort`, `FC=flang` or
`FC=flang-new` or similar with `./run_project_test.py --only fortran`.
Some families of tests require a particular backend to run.
For example, all the CUDA project tests run and pass on Windows via
`./run_project_tests.py --only cuda --backend ninja`
Expand Down
3 changes: 2 additions & 1 deletion docs/markdown/Reference-tables.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ These are return values of the `get_id` (Compiler family) and
| clang-cl | The Clang compiler (MSVC compatible driver) | msvc |
| dmd | D lang reference compiler | |
| emscripten| Emscripten WASM compiler | |
| flang | Flang Fortran compiler | |
| flang | Flang Fortran compiler (LLVM-based) | |
| flang | Classic Flang Fortran compiler | |
| g95 | The G95 Fortran compiler | |
| gcc | The GNU Compiler Collection | gcc |
| intel | Intel compiler (Linux and Mac) | gcc |
Expand Down
28 changes: 24 additions & 4 deletions mesonbuild/compilers/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
defaults['c'] = ['icl', 'cl', 'cc', 'gcc', 'clang', 'clang-cl', 'pgcc']
# There is currently no pgc++ for Windows, only for Mac and Linux.
defaults['cpp'] = ['icl', 'cl', 'c++', 'g++', 'clang++', 'clang-cl']
defaults['fortran'] = ['ifort', 'gfortran', 'flang', 'pgfortran', 'g95']
# the binary flang-new will be renamed to flang in the foreseeable future
defaults['fortran'] = ['ifort', 'gfortran', 'flang-new', 'flang', 'pgfortran', 'g95']
defaults['objc'] = ['clang-cl', 'gcc']
defaults['objcpp'] = ['clang-cl', 'g++']
defaults['cs'] = ['csc', 'mcs']
Expand All @@ -60,7 +61,8 @@
defaults['cpp'] = ['c++', 'g++', 'clang++', 'nvc++', 'pgc++', 'icpc', 'icpx']
defaults['objc'] = ['clang', 'gcc']
defaults['objcpp'] = ['clang++', 'g++']
defaults['fortran'] = ['gfortran', 'flang', 'nvfortran', 'pgfortran', 'ifort', 'ifx', 'g95']
# the binary flang-new will be renamed to flang in the foreseeable future
defaults['fortran'] = ['gfortran', 'flang-new', 'flang', 'nvfortran', 'pgfortran', 'ifort', 'ifx', 'g95']
defaults['cs'] = ['mcs', 'csc']
defaults['d'] = ['ldc2', 'ldc', 'gdc', 'dmd']
defaults['java'] = ['javac']
Expand Down Expand Up @@ -659,6 +661,13 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C
info = env.machines[for_machine]
cls: T.Type[FortranCompiler]
for compiler in compilers:
# capture help text for possible fallback
try:
_, help_out, help_err = Popen_safe_logged(compiler + ["--help"], msg='Detecting compiler via')
except OSError as e:
popen_exceptions[join_args(compiler + ["--help"])] = e
help_out = help_err = ""

for arg in ['--version', '-V']:
try:
p, out, err = Popen_safe_logged(compiler + [arg], msg='Detecting compiler via')
Expand Down Expand Up @@ -776,8 +785,7 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C
compiler, version, for_machine, is_cross, info,
full_version=full_version, linker=linker)

if 'flang' in out or 'clang' in out:
cls = fortran.FlangFortranCompiler
def _get_linker_try_windows(cls):
linker = None
if 'windows' in out or env.machines[for_machine].is_windows():
# If we're in a MINGW context this actually will use a gnu
Expand All @@ -793,6 +801,18 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C
if linker is None:
linker = guess_nix_linker(env, compiler, cls,
version, for_machine)
return linker

if 'flang-new' in out or 'flang LLVM compiler' in help_out:
cls = LlvmFlangFortranCompiler
linker = _get_linker_try_windows(cls)
return cls(
compiler, version, for_machine, is_cross, info,
exe_wrap, full_version=full_version, linker=linker)

if 'flang' in out or 'clang' in out:
cls = fortran.ClassicFlangFortranCompiler
linker = _get_linker_try_windows(cls)
return cls(
compiler, version, for_machine, is_cross, info,
full_version=full_version, linker=linker)
Expand Down
60 changes: 57 additions & 3 deletions mesonbuild/compilers/fortran.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
CompileCheckMode,
)
from .mixins.clike import CLikeCompiler
from .mixins.gnu import GnuCompiler, gnu_optimization_args
from .mixins.gnu import GnuCompiler, gnu_optimization_args, gnu_symbol_visibility_args

Check notice

Code scanning / CodeQL

Unused import Note

Import of 'gnu_symbol_visibility_args' is not used.
from .mixins.intel import IntelGnuLikeCompiler, IntelVisualStudioLikeCompiler
from .mixins.clang import ClangCompiler
from .mixins.elbrus import ElbrusCompiler
Expand Down Expand Up @@ -430,7 +430,61 @@ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoic
'everything': default_warn_args + ['-Mdclchk']}


class FlangFortranCompiler(ClangCompiler, FortranCompiler):
class LlvmFlangFortranCompiler(ClangCompiler, FortranCompiler):

Check warning

Code scanning / CodeQL

Conflicting attributes in base classes Warning

Base classes have conflicting values for attribute 'get_include_args':
Function get_include_args
and
Function get_include_args
.
Base classes have conflicting values for attribute 'get_pic_args':
Function get_pic_args
and
Function get_pic_args
.
Base classes have conflicting values for attribute 'get_pch_use_args':
Function get_pch_use_args
and
Function get_pch_use_args
.
Base classes have conflicting values for attribute 'get_optimization_args':
Function get_optimization_args
and
Function get_optimization_args
.
Base classes have conflicting values for attribute 'get_debug_args':
Function get_debug_args
and
Function get_debug_args
.
Base classes have conflicting values for attribute 'compute_parameters_with_absolute_paths':
Function compute_parameters_with_absolute_paths
and
Function compute_parameters_with_absolute_paths
.
Base classes have conflicting values for attribute 'get_output_args':
Function get_output_args
and
Function get_output_args
.
Base classes have conflicting values for attribute 'get_compile_only_args':
Function get_compile_only_args
and
Function get_compile_only_args
.
Base classes have conflicting values for attribute 'get_has_func_attribute_extra_args':
Function get_has_func_attribute_extra_args
and
Function get_has_func_attribute_extra_args
.
Base classes have conflicting values for attribute 'linker_to_compiler_args':
Function linker_to_compiler_args
and
Function linker_to_compiler_args
.
Base classes have conflicting values for attribute 'get_compiler_dirs':
Function get_compiler_dirs
and
Function get_compiler_dirs
.
Base classes have conflicting values for attribute 'get_default_include_dirs':
Function get_default_include_dirs
and
Function get_default_include_dirs
.

id = 'llvm-flang'

def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool,
info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None,
linker: T.Optional['DynamicLinker'] = None,
full_version: T.Optional[str] = None):
FortranCompiler.__init__(self, exelist, version, for_machine,
is_cross, info, exe_wrapper, linker=linker,
full_version=full_version)

Check failure

Code scanning / CodeQL

Wrong number of arguments in a call Error

Call to
method FortranCompiler.__init__
with too many arguments; should be no more than 8.
ClangCompiler.__init__(self, {})
default_warn_args = ['-Wall']
self.warn_args = {'0': [],
'1': default_warn_args,
'2': default_warn_args,
'3': default_warn_args,
'everything': default_warn_args}

def get_colorout_args(self, colortype: str) -> T.List[str]:
# clang's -fdiagnostics-color=... isn't known by flang (as of v18)
return []

def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
return []

# llvm-flang doesn't support -module (even though classic flang did), see
# https://github.com/llvm/llvm-project/issues/66969
def get_module_outdir_args(self, path: str) -> T.List[str]:
return ['-module-dir', path]

def gnu_symbol_visibility_args(self, vistype: str) -> T.List[str]:
# flang doesn't support symbol visibility flag yet, see
# https://github.com/llvm/llvm-project/issues/92459
return []

def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]:
# We need to apply the search prefix here, as these link arguments may
# be passed to a different compiler with a different set of default
# search paths, such as when using Clang for C/C++ and gfortran for
# fortran,
# XXX: Untested....
search_dirs: T.List[str] = []
for d in self.get_compiler_dirs(env, 'libraries'):
search_dirs.append(f'-L{d}')
# does not automatically link to Fortran_main anymore after
# https://github.com/llvm/llvm-project/commit/9d6837d595719904720e5ff68ec1f1a2665bdc2f
# note that this changed again in flang 19 with
# https://github.com/llvm/llvm-project/commit/8d5386669ed63548daf1bee415596582d6d78d7d;
# it seems flang 18 doesn't work if something accidentally includes a program unit, see
# https://github.com/llvm/llvm-project/issues/92496
return search_dirs + ['-lFortranRuntime', '-lFortranDecimal']


class ClassicFlangFortranCompiler(ClangCompiler, FortranCompiler):

Check warning

Code scanning / CodeQL

Conflicting attributes in base classes Warning

Base classes have conflicting values for attribute 'get_include_args':
Function get_include_args
and
Function get_include_args
.
Base classes have conflicting values for attribute 'get_pic_args':
Function get_pic_args
and
Function get_pic_args
.
Base classes have conflicting values for attribute 'get_pch_use_args':
Function get_pch_use_args
and
Function get_pch_use_args
.
Base classes have conflicting values for attribute 'get_optimization_args':
Function get_optimization_args
and
Function get_optimization_args
.
Base classes have conflicting values for attribute 'get_debug_args':
Function get_debug_args
and
Function get_debug_args
.
Base classes have conflicting values for attribute 'compute_parameters_with_absolute_paths':
Function compute_parameters_with_absolute_paths
and
Function compute_parameters_with_absolute_paths
.
Base classes have conflicting values for attribute 'get_output_args':
Function get_output_args
and
Function get_output_args
.
Base classes have conflicting values for attribute 'get_compile_only_args':
Function get_compile_only_args
and
Function get_compile_only_args
.
Base classes have conflicting values for attribute 'get_has_func_attribute_extra_args':
Function get_has_func_attribute_extra_args
and
Function get_has_func_attribute_extra_args
.
Base classes have conflicting values for attribute 'linker_to_compiler_args':
Function linker_to_compiler_args
and
Function linker_to_compiler_args
.
Base classes have conflicting values for attribute 'get_compiler_dirs':
Function get_compiler_dirs
and
Function get_compiler_dirs
.
Base classes have conflicting values for attribute 'get_default_include_dirs':
Function get_default_include_dirs
and
Function get_default_include_dirs
.

id = 'flang'

Expand Down Expand Up @@ -460,7 +514,7 @@ def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]:
search_dirs.append(f'-L{d}')
return search_dirs + ['-lflang', '-lpgmath']

class ArmLtdFlangFortranCompiler(FlangFortranCompiler):
class ArmLtdFlangFortranCompiler(ClassicFlangFortranCompiler):

id = 'armltdflang'

Expand Down
1 change: 1 addition & 0 deletions run_project_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1080,6 +1080,7 @@ def detect_tests_to_run(only: T.Dict[str, T.List[str]], use_tmp: bool) -> T.List
"""

skip_fortran = not(shutil.which('gfortran') or
shutil.which('flang-new') or
shutil.which('flang') or
shutil.which('pgfortran') or
shutil.which('nagfor') or
Expand Down

0 comments on commit 72cfdc5

Please sign in to comment.