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
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)
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
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)
# 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)
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 = {}
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 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 + 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)
#for k,v in env.items():
# print(k,v)
#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)