aboutsummaryrefslogtreecommitdiff
path: root/environment.py
diff options
context:
space:
mode:
Diffstat (limited to 'environment.py')
-rw-r--r--environment.py167
1 files changed, 156 insertions, 11 deletions
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