From 5b4ebb564164af37db374df383a697852262be2f Mon Sep 17 00:00:00 2001 From: "Michael Hirsch, Ph.D" Date: Mon, 25 Nov 2019 02:10:48 -0500 Subject: [PATCH] quality / test: Fortran type hinting enhance fortran args tests --- mesonbuild/compilers/fortran.py | 31 +++++++++++---------- mesonbuild/compilers/mixins/clike.py | 10 ++++--- mesonbuild/interpreter.py | 18 ++++++------ test cases/fortran/18 first_arg/main.f90 | 2 ++ test cases/fortran/18 first_arg/meson.build | 20 +++++++++++++ 5 files changed, 53 insertions(+), 28 deletions(-) create mode 100644 test cases/fortran/18 first_arg/main.f90 diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index c4451c104..16a93f50d 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -142,14 +142,15 @@ class FortranCompiler(CLikeCompiler, Compiler): return filename def find_library(self, libname, env, extra_dirs, libtype: LibType = LibType.PREFER_SHARED): - code = '''stop; end program''' + code = 'stop; end program' return self.find_library_impl(libname, env, extra_dirs, code, libtype) - def has_multi_arguments(self, args, env): + def has_multi_arguments(self, args: T.Sequence[str], env): for arg in args[:]: # some compilers, e.g. GCC, don't warn for unsupported warning-disable # flags, so when we are testing a flag like "-Wno-forgotten-towel", also # check the equivalent enable flag too "-Wforgotten-towel" + # GCC does error for "-fno-foobar" if arg.startswith('-Wno-'): args.append('-W' + arg[5:]) if arg.startswith('-Wl,'): @@ -197,16 +198,16 @@ class GnuFortranCompiler(GnuCompiler, FortranCompiler): args.append('-std=' + std.value) return args - def get_dependency_gen_args(self, outtarget, outfile): + def get_dependency_gen_args(self, outtarget, outfile) -> T.List[str]: # Disabled until this is fixed: # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62162 # return ['-cpp', '-MD', '-MQ', outtarget] return [] - def get_module_outdir_args(self, path): + def get_module_outdir_args(self, path: str) -> T.List[str]: return ['-J' + path] - def language_stdlib_only_link_flags(self): + def language_stdlib_only_link_flags(self) -> T.List[str]: return ['-lgfortran', '-lm'] class ElbrusFortranCompiler(GnuFortranCompiler, ElbrusCompiler): @@ -233,7 +234,7 @@ class G95FortranCompiler(FortranCompiler): '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-pedantic']} - def get_module_outdir_args(self, path): + def get_module_outdir_args(self, path: str) -> T.List[str]: return ['-fmod=' + path] def get_no_warn_args(self): @@ -251,7 +252,7 @@ class SunFortranCompiler(FortranCompiler): FortranCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrapper, **kwargs) self.id = 'sun' - def get_dependency_gen_args(self, outtarget, outfile): + def get_dependency_gen_args(self, outtarget, outfile) -> T.List[str]: return ['-fpp'] def get_always_args(self): @@ -263,10 +264,10 @@ class SunFortranCompiler(FortranCompiler): def get_module_incdir_args(self): return ('-M', ) - def get_module_outdir_args(self, path): + def get_module_outdir_args(self, path: str) -> T.List[str]: return ['-moddir=' + path] - def openmp_flags(self): + def openmp_flags(self) -> T.List[str]: return ['-xopenmp'] @@ -304,7 +305,7 @@ class IntelFortranCompiler(IntelGnuLikeCompiler, FortranCompiler): args.append('-stand=' + stds[std.value]) return args - def get_preprocess_only_args(self): + def get_preprocess_only_args(self) -> T.List[str]: return ['-cpp', '-EP'] def get_always_args(self): @@ -313,7 +314,7 @@ class IntelFortranCompiler(IntelGnuLikeCompiler, FortranCompiler): val.remove('-pipe') return val - def language_stdlib_only_link_flags(self): + def language_stdlib_only_link_flags(self) -> T.List[str]: return ['-lifcore', '-limf'] def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: @@ -371,7 +372,7 @@ class PathScaleFortranCompiler(FortranCompiler): '2': default_warn_args, '3': default_warn_args} - def openmp_flags(self): + def openmp_flags(self) -> T.List[str]: return ['-mp'] @@ -423,7 +424,7 @@ class Open64FortranCompiler(FortranCompiler): '2': default_warn_args, '3': default_warn_args} - def openmp_flags(self): + def openmp_flags(self) -> T.List[str]: return ['-mp'] @@ -438,8 +439,8 @@ class NAGFortranCompiler(FortranCompiler): def get_warn_args(self, level): return [] - def get_module_outdir_args(self, path): + def get_module_outdir_args(self, path) -> T.List[str]: return ['-mdir', path] - def openmp_flags(self): + def openmp_flags(self) -> T.List[str]: return ['-openmp'] diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index 6b09b9710..93c1a7ce6 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -319,7 +319,7 @@ class CLikeCompiler: cargs += self.get_compiler_args_for_mode(mode) return cargs, largs - def _get_compiler_check_args(self, env, extra_args, dependencies, mode='compile'): + def _get_compiler_check_args(self, env, extra_args: list, dependencies, mode: str = 'compile') -> T.List[str]: if extra_args is None: extra_args = [] else: @@ -354,11 +354,13 @@ class CLikeCompiler: args = cargs + extra_args + largs return args - def compiles(self, code, env, *, extra_args=None, dependencies=None, mode='compile', disable_cache=False): + def compiles(self, code: str, env, *, + extra_args: T.Sequence[T.Union[T.Sequence[str], str]] = None, + dependencies=None, mode: str = 'compile', disable_cache=False) -> T.Tuple[bool, bool]: with self._build_wrapper(code, env, extra_args, dependencies, mode, disable_cache=disable_cache) as p: return p.returncode == 0, p.cached - def _build_wrapper(self, code, env, extra_args, dependencies=None, mode='compile', want_output=False, disable_cache=False, temp_dir=None): + def _build_wrapper(self, code: str, env, extra_args, dependencies=None, mode: str = 'compile', want_output: bool = False, disable_cache: bool = False, temp_dir=None) -> T.Tuple[bool, bool]: args = self._get_compiler_check_args(env, extra_args, dependencies, mode) if disable_cache or want_output: return self.compile(code, extra_args=args, mode=mode, want_output=want_output, temp_dir=env.scratch_dir) @@ -1074,7 +1076,7 @@ class CLikeCompiler: def linker_to_compiler_args(self, args): return args - def has_arguments(self, args, env, code, mode): + def has_arguments(self, args: T.Sequence[str], env, code: str, mode: str) -> T.Tuple[bool, bool]: return self.compiles(code, env, extra_args=args, mode=mode) def has_multi_arguments(self, args, env): diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index ec28f2e33..3c0187a1e 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1,4 +1,4 @@ -# Copyright 2012-2018 The Meson development team +# Copyright 2012-2019 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -1621,14 +1621,14 @@ class CompilerHolder(InterpreterObject): return ExternalLibraryHolder(lib, self.subproject) @permittedKwargs({}) - def has_argument_method(self, args, kwargs): + def has_argument_method(self, args: T.Sequence[str], kwargs) -> bool: args = mesonlib.stringlistify(args) if len(args) != 1: raise InterpreterException('has_argument takes exactly one argument.') return self.has_multi_arguments_method(args, kwargs) @permittedKwargs({}) - def has_multi_arguments_method(self, args, kwargs): + def has_multi_arguments_method(self, args: T.Sequence[str], kwargs: dict): args = mesonlib.stringlistify(args) result, cached = self.compiler.has_multi_arguments(args, self.environment) if result: @@ -1653,11 +1653,11 @@ class CompilerHolder(InterpreterObject): return supported_args @permittedKwargs({}) - def first_supported_argument_method(self, args, kwargs): - for i in mesonlib.stringlistify(args): - if self.has_argument_method(i, kwargs): - mlog.log('First supported argument:', mlog.bold(i)) - return [i] + def first_supported_argument_method(self, args: T.Sequence[str], kwargs: dict) -> T.List[str]: + for arg in mesonlib.stringlistify(args): + if self.has_argument_method(arg, kwargs): + mlog.log('First supported argument:', mlog.bold(arg)) + return [arg] mlog.log('First supported argument:', mlog.red('None')) return [] @@ -3601,7 +3601,7 @@ external dependencies (including libraries) must go to "dependencies".''') if 'input' not in kwargs or 'output' not in kwargs: raise InterpreterException('Keyword arguments input and output must exist') if 'fallback' not in kwargs: - FeatureNew('T.Optional fallback in vcs_tag', '0.41.0').use(self.subproject) + FeatureNew('Optional fallback in vcs_tag', '0.41.0').use(self.subproject) fallback = kwargs.pop('fallback', self.project_version) if not isinstance(fallback, str): raise InterpreterException('Keyword argument fallback must be a string.') diff --git a/test cases/fortran/18 first_arg/main.f90 b/test cases/fortran/18 first_arg/main.f90 new file mode 100644 index 000000000..d0097a2ab --- /dev/null +++ b/test cases/fortran/18 first_arg/main.f90 @@ -0,0 +1,2 @@ +i = 3 +end program diff --git a/test cases/fortran/18 first_arg/meson.build b/test cases/fortran/18 first_arg/meson.build index 874f4db54..63021f2a3 100644 --- a/test cases/fortran/18 first_arg/meson.build +++ b/test cases/fortran/18 first_arg/meson.build @@ -24,3 +24,23 @@ l2 = fc.first_supported_argument(isnt_arg, isnt_arg, isnt_arg) assert(l1.length() == 1, 'First supported returned wrong result.') assert(l1.get(0) == is_arg, 'First supported returned wrong argument.') assert(l2.length() == 0, 'First supported did not return empty array.') + +# --- test with an actual program, here for implicit none + +in0 = fc.first_supported_argument('-fimplicit-none', '-Mdclchk', '/warn:declarations', '-warn').get(0, '') +impnone = { +'intel-cl': '/warn:declarations', +'intel': '-warn', +'gcc': '-fimplicit-none', +'pgi': '-Mdclchk', +} + +arg = impnone.get(fc.get_id(), '') +if arg != '' + assert(in0 == arg, 'implicit none argument ' + arg + ' not matching ' + in0) +endif + +in1 = fc.get_supported_arguments('-fimplicit-none', '/warn:declarations', '/warn:errors', '-Mdclchk') +if in1.length() > 0 + assert(not fc.compiles(files('main.f90'), args: in1, name:'will fail implicit none'), 'implicit none should have failed') +endif