From f7caa5eef7ea0ca1dc3c354eca3234a9ded0169e Mon Sep 17 00:00:00 2001 From: Sylvain Tricot Date: Thu, 26 Mar 2020 18:19:26 +0100 Subject: [PATCH] Move to SCons building tool instead of make. The scons python module is now used to build the code extension. It is an all python solution and is easier to read than a Makefile --- SConstruct | 94 ++++++++++++++++ src/msspec/phagen/fortran/SConstruct | 16 +++ src/msspec/spec/fortran/SConstruct | 156 +++++++++++---------------- 3 files changed, 171 insertions(+), 95 deletions(-) create mode 100644 SConstruct create mode 100644 src/msspec/phagen/fortran/SConstruct diff --git a/SConstruct b/SConstruct new file mode 100644 index 0000000..9545e5d --- /dev/null +++ b/SConstruct @@ -0,0 +1,94 @@ +from sysconfig import get_config_var +import os + +# 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') + +def CheckPKGConfig(context, version): + context.Message( 'Checking for pkg-config... ' ) + ret = context.TryAction('pkg-config --atleast-pkgconfig-version=%s' % version)[0] + context.Result( ret ) + return ret + +def CheckPKG(context, name): + context.Message( 'Checking for %s... ' % name ) + ret = context.TryAction('pkg-config --exists \'%s\'' % name)[0] + context.Result( ret ) + return ret + +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))) + + + +# define the default build environment +std = Environment(tools=['default', 'fortran'], F2PY_OPTS=[], FORTRANCOMSTR = "building $TARGET ...", LIBS=[]) +std.AddMethod(filtered_glob, "FilteredGlob"); + +# define environments +gfortran_env = std.Clone(tools=['gfortran']) +gfortran_env.Replace(FORTRANFLAGS=['-fPIC', '-O2', '-ffast-math', '-fno-automatic']) + +ifort_env = std.Clone(tools=['ifort']) + +# parse options +if GetOption('compiler') == 'gfortran': + env = gfortran_env +elif GetOption('compiler') == 'ifort': + env = ifort_env + +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 = "") + + +conf = Configure(env, custom_tests = { 'CheckPKG' : CheckPKG}) +suffix = get_config_var('EXT_SUFFIX') + +# Create a builder for f2py +def create_f2py_cmd(source, target, env, for_signature): + objects = source[1:] + cmd = "f2py3 " + cmd += " ".join([o.get_path() for o in objects if str(o).endswith('o')]) + cmd += f" $F2PY_OPTS -m {str(target[0]).replace(suffix,'').replace('/', '.')} -c {source[0]}" + return cmd + +def modify_targets(target, source, env): + target[0] = str(target[0]) + suffix + #print(target[0]) + return target, source + +bld = Builder(generator=create_f2py_cmd, emitter = modify_targets) +env['BUILDERS']['F2PY'] = bld + + + +# exports +Export('env', 'conf') + + +SConscript(['src/msspec/spec/fortran/SConstruct', + 'src/msspec/phagen/fortran/SConstruct']) diff --git a/src/msspec/phagen/fortran/SConstruct b/src/msspec/phagen/fortran/SConstruct new file mode 100644 index 0000000..7b389d8 --- /dev/null +++ b/src/msspec/phagen/fortran/SConstruct @@ -0,0 +1,16 @@ + +try: + Import('env') +except: + SConscript(['../../../../SConstruct']) +finally: + Import('env') + + +objects_src= ['phagen_scf_2.1_dp.f'] +objects = env.Object(objects_src) + +module = env.F2PY('libphagen', ['main.f'] + objects) +Requires(module, objects) + +env.Alias('phagen', module) diff --git a/src/msspec/spec/fortran/SConstruct b/src/msspec/spec/fortran/SConstruct index 53ba2c0..5b0e405 100644 --- a/src/msspec/spec/fortran/SConstruct +++ b/src/msspec/spec/fortran/SConstruct @@ -1,111 +1,77 @@ -from sysconfig import get_config_var -import os - -# 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') - -def CheckPKGConfig(context, version): - context.Message( 'Checking for pkg-config... ' ) - ret = context.TryAction('pkg-config --atleast-pkgconfig-version=%s' % version)[0] - context.Result( ret ) - return ret - -def CheckPKG(context, name): - context.Message( 'Checking for %s... ' % name ) - ret = context.TryAction('pkg-config --exists \'%s\'' % name)[0] - context.Result( ret ) - return ret - - - - -# define environments -std = Environment(tools=['default', 'fortran'], F2PY_OPTS=[], FORTRANCOMSTR = "building $TARGET ...") - -gfortran_env = std.Clone(tools=['gfortran']) -gfortran_env.Replace(FORTRANFLAGS=['-fPIC', '-O2', '-ffast-math', '-fno-automatic']) - -ifort_env = std.Clone(tools=['ifort']) - -# parse options -if GetOption('compiler') == 'gfortran': - env = gfortran_env -elif GetOption('compiler') == 'ifort': - env = ifort_env - -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 = "") +# imports +try: + Import('env', 'conf') +except: + SConscript(['../../../../SConstruct']) +finally: + Import('env', 'conf') # Configuration: -conf = Configure(env, custom_tests = { 'CheckPKG' : CheckPKG}) - if conf.CheckPKG('lapack'): - env.ParseConfig("pkg-config lapack --libs") - + env.ParseConfig("pkg-config lapack --libs") conf.Finish() +dir = Dir('.').get_abspath() +env.Append(FORTRANFLAGS=['-I' + dir,'-J' + dir]) +env.Append(F2PY_OPTS=['-I' + dir]) -suffix = get_config_var('EXT_SUFFIX') +# define sources +dim_mod = ['memalloc/dim_mod.f'] +memalloc = ['memalloc/modules.f', 'memalloc/allocation.f'] +cluster_gen = Glob('cluster_gen/*.f') +common_sub = Glob('common_sub/*.f') +renormalization = Glob('renormalization/*.f') +phd_se_noso_nosp_nosym = env.FilteredGlob('phd_se_noso_nosp_nosym/*.f', omit=['main.f']) +phd_mi_noso_nosp_nosym = env.FilteredGlob('phd_mi_noso_nosp_nosym/*.f', omit=['main.f']) +eig_common = Glob('eig/common/*.f') +eig_mi = env.FilteredGlob('eig/mi/*.f', omit=['main.f']) +eig_pw = env.FilteredGlob('eig/pw/*.f', omit=['main.f']) -sources = { - 'dim_mod_src' : ['memalloc/dim_mod.f'], - 'memalloc_src' : ['memalloc/modules.f', 'memalloc/allocation.f'], - 'cluster_gen_src' : Glob('cluster_gen/*.f'), - 'common_sub_src' : Glob('common_sub/*.f'), - 'renormalization_src' : Glob('renormalization/*.f'), - 'phd_se_noso_nosp_nosym_src': Glob('phd_se_noso_nosp_nosym/*.f'), - 'phd_mi_noso_nosp_nosym_src': Glob('phd_mi_noso_nosp_nosym/*.f'), - 'eig_common_src' : Glob('eig/common/*.f'), - 'eig_mi_src' : Glob('eig/mi/*.f'), - 'eig_pw_src' : Glob('eig/pw/*.f')} + +#for f in eig_mi: +# print(f) +#exit() if 'lapack' in env['LIBS']: - env.Append(F2PY_OPTS = "-llapack") - for k,files in sources.items(): - sources[k] = [_ for _ in files if str(_).find('lapack') == -1] + env.Append(F2PY_OPTS = "-llapack") + eig_mi = [f for f in eig_mi if str(f).find('lapack') == -1] + phd_mi_noso_nosp_nosym = [f for f in phd_mi_noso_nosp_nosym if str(f).find('lapack') == -1] -objects = {} -for k, v in sources.items(): - objects[k.replace('_src', '_obj')] = env.Object(v) - -Requires(objects['memalloc_obj'], objects['dim_mod_obj']) +sources = dim_mod + memalloc + cluster_gen + common_sub + renormalization + phd_se_noso_nosp_nosym +sources += phd_mi_noso_nosp_nosym + eig_common + eig_pw + eig_mi +# define objects +dim_mod_obj = env.Object(dim_mod) +memalloc_obj = env.Object(memalloc) +cluster_gen_obj = env.Object(cluster_gen) +common_sub_obj = env.Object(common_sub) +renormalization_obj = env.Object(renormalization) +phd_se_noso_nosp_nosym_obj = env.Object(phd_se_noso_nosp_nosym) +phd_mi_noso_nosp_nosym_obj = env.Object(phd_mi_noso_nosp_nosym) +eig_common_obj = env.Object(eig_common) +eig_pw_obj = env.Object(eig_pw) +eig_mi_obj = env.Object(eig_mi) +Requires(memalloc_obj, dim_mod_obj) -shared_objects = { - 'phd_se_noso_nosp_nosym': 'phd_se_noso_nosp_nosym/main.f', - 'phd_mi_noso_nosp_nosym': 'phd_mi_noso_nosp_nosym/main.f', - 'eig_mi' : 'eig/mi/main.f', - 'eig_pw' : 'eig/pw/main.f',} -modules = {} +# define Python extensions +common_deps = dim_mod_obj + memalloc_obj + cluster_gen_obj + common_sub_obj +deps = common_deps + renormalization_obj + phd_se_noso_nosp_nosym_obj +phd_se_mod = env.F2PY('_phd_se_noso_nosp_nosym', ['phd_se_noso_nosp_nosym/main.f'] + deps) +Requires(phd_se_mod, deps) +env.Alias('phd_se', phd_se_mod) -for k, v in shared_objects.items(): - cmd = "f2py3 -I. " + " ".join([str(_) for _ in objects if str(_).endswith('.o')]) + f"$F2PY_OPTS -c -m {k} $SOURCE" - cmd += "2>/dev/null 1>/dev/null" - modules[k + suffix] = env.Command(k + suffix, v, Action(cmd, '$FORTRANCOMSTR')) - Requires(modules[k + suffix], objects.values()) +deps = common_deps + renormalization_obj + phd_mi_noso_nosp_nosym_obj +phd_mi_mod = env.F2PY('_phd_mi_noso_nosp_nosym', ['phd_mi_noso_nosp_nosym/main.f'] + deps) +Requires(phd_mi_mod, deps) +env.Alias('phd_mi', phd_mi_mod) -#for k,v in env.items(): -# print(k,v) +deps = common_deps + renormalization_obj + eig_common_obj + eig_mi_obj +eig_mi_mod = env.F2PY('_eig_mi', ['eig/mi/main.f'] + deps) +Requires(eig_mi_mod, deps) +env.Alias('eig_mi', eig_mi_mod) -#exit() +deps = common_deps + renormalization_obj + eig_common_obj + eig_pw_obj +eig_pw_mod = env.F2PY('_eig_pw', ['eig/pw/main.f'] + deps) +Requires(eig_pw_mod, deps) +env.Alias('eig_pw', eig_pw_mod)