aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends.py1
-rw-r--r--environment.py167
-rw-r--r--interpreter.py4
-rw-r--r--test cases/fortran/1 basic/meson.build4
-rw-r--r--test cases/fortran/1 basic/simple.f953
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