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
This commit is contained in:
Sylvain Tricot 2020-03-26 18:19:26 +01:00
parent 44b3145b65
commit f7caa5eef7
3 changed files with 171 additions and 95 deletions

94
SConstruct Normal file
View File

@ -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'])

View File

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

View File

@ -1,111 +1,77 @@
from sysconfig import get_config_var # imports
import os try:
Import('env', 'conf')
# Define the command line options except:
AddOption('--dbg', SConscript(['../../../../SConstruct'])
dest='dbg', finally:
action='store_true', Import('env', 'conf')
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 = "")
# Configuration: # Configuration:
conf = Configure(env, custom_tests = { 'CheckPKG' : CheckPKG})
if conf.CheckPKG('lapack'): if conf.CheckPKG('lapack'):
env.ParseConfig("pkg-config lapack --libs") env.ParseConfig("pkg-config lapack --libs")
conf.Finish() 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'], #for f in eig_mi:
'memalloc_src' : ['memalloc/modules.f', 'memalloc/allocation.f'], # print(f)
'cluster_gen_src' : Glob('cluster_gen/*.f'), #exit()
'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')}
if 'lapack' in env['LIBS']: if 'lapack' in env['LIBS']:
env.Append(F2PY_OPTS = "-llapack") env.Append(F2PY_OPTS = "-llapack")
for k,files in sources.items(): eig_mi = [f for f in eig_mi if str(f).find('lapack') == -1]
sources[k] = [_ for _ in files if str(_).find('lapack') == -1] phd_mi_noso_nosp_nosym = [f for f in phd_mi_noso_nosp_nosym if str(f).find('lapack') == -1]
objects = {} sources = dim_mod + memalloc + cluster_gen + common_sub + renormalization + phd_se_noso_nosp_nosym
for k, v in sources.items(): sources += phd_mi_noso_nosp_nosym + eig_common + eig_pw + eig_mi
objects[k.replace('_src', '_obj')] = env.Object(v)
Requires(objects['memalloc_obj'], objects['dim_mod_obj'])
# 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 = { # define Python extensions
'phd_se_noso_nosp_nosym': 'phd_se_noso_nosp_nosym/main.f', common_deps = dim_mod_obj + memalloc_obj + cluster_gen_obj + common_sub_obj
'phd_mi_noso_nosp_nosym': 'phd_mi_noso_nosp_nosym/main.f', deps = common_deps + renormalization_obj + phd_se_noso_nosp_nosym_obj
'eig_mi' : 'eig/mi/main.f', phd_se_mod = env.F2PY('_phd_se_noso_nosp_nosym', ['phd_se_noso_nosp_nosym/main.f'] + deps)
'eig_pw' : 'eig/pw/main.f',} Requires(phd_se_mod, deps)
modules = {} env.Alias('phd_se', phd_se_mod)
for k, v in shared_objects.items(): deps = common_deps + renormalization_obj + phd_mi_noso_nosp_nosym_obj
cmd = "f2py3 -I. " + " ".join([str(_) for _ in objects if str(_).endswith('.o')]) + f"$F2PY_OPTS -c -m {k} $SOURCE" phd_mi_mod = env.F2PY('_phd_mi_noso_nosp_nosym', ['phd_mi_noso_nosp_nosym/main.f'] + deps)
cmd += "2>/dev/null 1>/dev/null" Requires(phd_mi_mod, deps)
modules[k + suffix] = env.Command(k + suffix, v, Action(cmd, '$FORTRANCOMSTR')) env.Alias('phd_mi', phd_mi_mod)
Requires(modules[k + suffix], objects.values())
#for k,v in env.items(): deps = common_deps + renormalization_obj + eig_common_obj + eig_mi_obj
# print(k,v) 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)