Basic Fortran support.

pull/15/head
Jussi Pakkanen 11 years ago
parent 0f79b0336f
commit a77551f3d7
  1. 1
      backends.py
  2. 167
      environment.py
  3. 4
      interpreter.py
  4. 4
      test cases/fortran/1 basic/meson.build
  5. 3
      test cases/fortran/1 basic/simple.f95

@ -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:

@ -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

@ -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())

@ -0,0 +1,4 @@
project('simple fortran', 'fortran')
e = executable('simple', 'simple.f95')
test('Simple Fortran', e)

@ -0,0 +1,3 @@
program prog
print *, "Fortran compilation is working."
end program prog
Loading…
Cancel
Save