import os import subprocess ############################################################################### def filtered_glob(env, pattern, omit=[], ondisk=True, source=False, strings=False): return list(filter( lambda f: os.path.basename(f.path) not in omit, env.Glob(pattern))) # Create a builder for f2py def f2py_generator(source, target, env, for_signature): suffix = ".so" main = source[0] objects = " ".join(o.get_path() for o in source[1:] if str(o).endswith('.o')) moduledir = os.path.dirname(target[0].abspath) modulefile = str(target[0]) modulename = modulefile.replace(suffix, '').replace('/', '.') compiler = env['FORTRAN'] cmd = f"$F2PY --fcompiler={compiler} " cmd += f" $F2PY_OPTS -m {modulename} -c {objects} {main}" cmd += f" && cp {'/'.join(modulename.split('.'))}.*.so {modulefile}" #cmd += " 1>/dev/null 2>/dev/null" return cmd def install_module(env, module): destdir = os.path.dirname(module[0].srcnode().abspath) env.Install(destdir, module) env.Alias('install', destdir) return None f2py_bld = Builder(generator=f2py_generator) # define the default build environment std = Environment(tools=['default', 'fortran'], F2PY_OPTS=[], LIBS=[]) std.AddMethod(filtered_glob, "FilteredGlob") std.AddMethod(install_module, "InstallModule") std['BUILDERS']['F2py'] = f2py_bld ############################################################################### # Define the command line options AddOption('--dbg', dest='dbg', action='store_true', help='add debugging symbols') AddOption('--verbose', dest='verbose', action='store_true', help='add debugging symbols') AddOption('--compiler', dest='compiler', default='gfortran', choices=['gfortran', 'ifort'], help='The Fortran compiler to use') AddOption('--f2py_path', dest='f2py_path', default='f2py3', help='The full path to the f2py compiler') # define environments gfortran_env = std.Clone(tools=['gfortran']) gfortran_env.Replace(FORTRANFLAGS=['-fPIC', '-O2', '-ffast-math']) ifort_env = std.Clone(tools=['ifort']) # parse options if GetOption('compiler') == 'gfortran': env = gfortran_env env.Append(F2PY_OPTS='--opt=-O2') elif GetOption('compiler') == 'ifort': env = ifort_env f2py_path = GetOption('f2py_path') p = subprocess.run(['which', f2py_path], stdout=subprocess.PIPE) if p.returncode != 0: raise Exception('Invalid path for f2py compiler!') else: env.Append(F2PY=p.stdout.decode('utf8').strip()) if GetOption('dbg'): gfortran_env.Append(FORTRANFLAGS = ['-g', '-Wall', '-Wextra', '-Warray-temporaries', '-Wconversion', '-fbacktrace', '-ffree-line-length-0', '-fcheck=all', '-ffpe-trap=zero,overflow,underflow', '-finit-real=nan'], F2PY_OPTS = ['--debug-capi', '--debug']) if GetOption('verbose'): env.Replace(FORTRANCOMSTR = "") Export('env') #SConscript('msspec/spec/fortran/SConstruct') #SConscript('msspec/phagen/fortran/SConstruct') SConscript('msspec/spec/fortran/SConstruct', variant_dir='build/build_spec') SConscript('msspec/phagen/fortran/SConstruct', variant_dir='build/build_phagen')