diff options
-rw-r--r-- | backends.py | 1 | ||||
-rw-r--r-- | environment.py | 167 | ||||
-rw-r--r-- | interpreter.py | 4 | ||||
-rw-r--r-- | test cases/fortran/1 basic/meson.build | 4 | ||||
-rw-r--r-- | test cases/fortran/1 basic/simple.f95 | 3 |
5 files changed, 167 insertions, 12 deletions
diff --git a/backends.py b/backends.py index 380af92..d94f146 100644 --- a/backends.py +++ b/backends.py @@ -372,7 +372,6 @@ class Backend(): commands += self.environment.coredata.external_args[compiler.get_language()] commands += target.get_extra_args(compiler.get_language()) if self.environment.coredata.buildtype != 'plain': - commands += compiler.get_debug_args() commands += compiler.get_std_warn_args() commands += compiler.get_buildtype_args(self.environment.coredata.buildtype) if self.environment.coredata.coverage: diff --git a/environment.py b/environment.py index 8e3eadb..165f0f0 100644 --- a/environment.py +++ b/environment.py @@ -67,6 +67,18 @@ mono_buildtype_args = {'plain' : [], 'debugoptimized': ['-debug', '-optimize+'], 'release' : ['-optimize+']} +def build_unix_rpath_args(build_dir, rpath_paths, install_rpath): + if len(rpath_paths) == 0 and len(install_rpath) == 0: + return [] + paths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths]) + if len(paths) < len(install_rpath): + padding = 'X'*(len(install_rpath) - len(paths)) + if len(paths) == 0: + paths = padding + else: + paths = paths + ':' + padding + return ['-Wl,-rpath,' + paths] + class CCompiler(): def __init__(self, exelist, version, is_cross, exe_wrapper=None): if type(exelist) == type(''): @@ -103,16 +115,7 @@ class CCompiler(): # The default behaviour is this, override in # OSX and MSVC. def build_rpath_args(self, build_dir, rpath_paths, install_rpath): - if len(rpath_paths) == 0 and len(install_rpath) == 0: - return [] - paths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths]) - if len(paths) < len(install_rpath): - padding = 'X'*(len(install_rpath) - len(paths)) - if len(paths) == 0: - paths = padding - else: - paths = paths + ':' + padding - return ['-Wl,-rpath,' + paths] + return build_unix_rpath_args(build_dir, rpath_paths, install_rpath) def get_id(self): return self.id @@ -131,7 +134,7 @@ class CCompiler(): def get_exelist(self): return self.exelist[:] - + def get_linker_exelist(self): return self.exelist[:] @@ -1104,6 +1107,110 @@ class ClangCPPCompiler(CPPCompiler): def get_pch_suffix(self): return 'pch' +class GnuFortranCompiler(): + std_warn_args = ['-Wall'] + + def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None): + super().__init__() + self.exelist = exelist + self.version = version + self.gcc_type = gcc_type + self.is_cross = is_cross + self.exe_wrapper = exe_wrapper + self.id = 'gcc' + self.language = 'fortran' + + def get_id(self): + return self.id + + def get_exelist(self): + return self.exelist + + def get_language(self): + return self.language + + def needs_static_linker(self): + return True + + def sanity_check(self, work_dir): + source_name = os.path.join(work_dir, 'sanitycheckf.f95') + binary_name = os.path.join(work_dir, 'sanitycheckf') + ofile = open(source_name, 'w') + ofile.write('''program prog + print *, "Fortran compilation is working." +end program prog +''') + ofile.close() + pc = subprocess.Popen(self.exelist + [source_name, '-o', binary_name]) + pc.wait() + if pc.returncode != 0: + raise EnvironmentException('Compiler %s can not compile programs.' % self.name_string()) + if self.is_cross: + if self.exe_wrapper is None: + # Can't check if the binaries run so we have to assume they do + return + cmdlist = self.exe_wrapper + [binary_name] + else: + cmdlist = [binary_name] + pe = subprocess.Popen(cmdlist) + pe.wait() + if pe.returncode != 0: + raise EnvironmentException('Executables created by Fortran compiler %s are not runnable.' % self.name_string()) + + def get_always_args(self): + return ['-pipe'] + + def get_linker_always_args(self): + return [] + + def get_std_warn_args(self): + return GnuFortranCompiler.std_warn_args + + def get_buildtype_args(self, buildtype): + return gnulike_buildtype_args[buildtype] + + def get_buildtype_linker_args(self, buildtype): + return gnulike_buildtype_linker_args[buildtype] + + def split_shlib_to_parts(self, fname): + return (os.path.split(fname)[0], fname) + + def get_soname_args(self, shlib_name, path, soversion): + return get_gcc_soname_args(self.gcc_type, shlib_name, path, soversion) + + def get_dependency_gen_args(self, outtarget, outfile): + return ['-cpp', '-MMD', '-MQ', outtarget] + + def get_output_args(self, target): + return ['-o', target] + + def get_compile_only_args(self): + return ['-c'] + + def get_linker_exelist(self): + return self.exelist[:] + + def get_linker_output_args(self, outputname): + return ['-o', outputname] + + def can_compile(self, src): + if src.lower().endswith('.f95'): + return True + return False + + def get_include_arg(self, path): + return '-I' + path + + def get_depfile_suffix(self): + return 'd' + + def get_std_exe_link_args(self): + return [] + + def build_rpath_args(self, build_dir, rpath_paths, install_rpath): + return build_unix_rpath_args(build_dir, rpath_paths, install_rpath) + + class VisualStudioLinker(): always_args = ['/NOLOGO'] def __init__(self, exelist): @@ -1273,6 +1380,7 @@ class Environment(): self.default_cpp = ['c++'] self.default_objc = ['cc'] self.default_objcpp = ['c++'] + self.default_fortran = ['gfortran'] self.default_static_linker = 'ar' self.vs_static_linker = 'lib' @@ -1386,6 +1494,43 @@ class Environment(): return VisualStudioCCompiler([compiler], version, is_cross, exe_wrap) raise EnvironmentException('Unknown compiler(s): "' + ', '.join(compilers) + '"') + def detect_fortran_compiler(self, want_cross): + evar = 'FC' + if self.is_cross_build() and want_cross: + compilers = [self.cross_info['fortran']] + ccache = [] + is_cross = True + exe_wrap = self.cross_info.get('exe_wrapper', None) + elif evar in os.environ: + compilers = os.environ[evar].split() + ccache = [] + is_cross = False + exe_wrap = None + else: + compilers = self.default_fortran + ccache = self.detect_ccache() + is_cross = False + exe_wrap = None + for compiler in compilers: + try: + arg = '--version' + p = subprocess.Popen([compiler] + [arg], stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + except OSError: + continue + (out, err) = p.communicate() + out = out.decode() + err = err.decode() + vmatch = re.search(Environment.version_regex, out) + if vmatch: + version = vmatch.group(0) + else: + version = 'unknown version' + if 'GNU Fortran' in out: + gcc_type = GCC_STANDARD + return GnuFortranCompiler([compiler], version, gcc_type, is_cross, exe_wrap) + raise EnvironmentException('Unknown compiler(s): "' + ', '.join(compilers) + '"') + def get_scratch_dir(self): return self.scratch_dir diff --git a/interpreter.py b/interpreter.py index b58c3eb..776a897 100644 --- a/interpreter.py +++ b/interpreter.py @@ -983,6 +983,10 @@ class Interpreter(): comp = self.environment.detect_rust_compiler() if is_cross: cross_comp = comp # FIXME, probably not correct. + elif lang == 'fortran': + comp = self.environment.detect_fortran_compiler(False) + if is_cross: + cross_comp = self.environment.detect_fortran_compiler(True) else: raise InvalidCode('Tried to use unknown language "%s".' % lang) comp.sanity_check(self.environment.get_scratch_dir()) diff --git a/test cases/fortran/1 basic/meson.build b/test cases/fortran/1 basic/meson.build new file mode 100644 index 0000000..78f40b5 --- /dev/null +++ b/test cases/fortran/1 basic/meson.build @@ -0,0 +1,4 @@ +project('simple fortran', 'fortran') + +e = executable('simple', 'simple.f95') +test('Simple Fortran', e) diff --git a/test cases/fortran/1 basic/simple.f95 b/test cases/fortran/1 basic/simple.f95 new file mode 100644 index 0000000..e0fb1d8 --- /dev/null +++ b/test cases/fortran/1 basic/simple.f95 @@ -0,0 +1,3 @@ +program prog + print *, "Fortran compilation is working." +end program prog |