Newer
Older
from numpy.distutils.misc_util import Configuration
Jean-Baptiste Keck
committed
Jean-Matthieu Etancelin
committed
import os
Jean-Baptiste Keck
committed
import re
Jean-Baptiste Keck
committed
import fnmatch
# tools to deal with fortran dependencies.
import sys
# --- Check if c++ interface is enabled ---
enable_cpp = "@USE_CXX@"
if enable_cpp:
swig_executable = find_executable("@SWIG_EXECUTABLE@")
Jean-Baptiste Keck
committed
def parseCMakeVar(var):
"""post-process cmake list-like variable
Example::
a = parseCMakeVar("var1;var2;var3;")
# --> a = ['var', 'var2', 'var3']
"""
Jean-Baptiste Keck
committed
if var != "":
res = list(set(var.split(';')))
# list/set stuff to avoid duplicates
# remove empty strings to avoid '-I -I' things leading to bugs
if res.count(''):
res.remove('')
return res
Jean-Baptiste Keck
committed
else:
Jean-Baptiste Keck
committed
def parseCMakeDefines(var):
"""post-process cmake variables, corresponding
to pre-processor definitions.
Example::
res = parseCMakeDefines("-DVAR=VAL1:-DVAR2=VAL2:-DVAR3=VAL3")
# --> res = [('VAR', 'VAL1'), ('VAR2', 'VAL2'), ('VAR3', 'VAL3')]
"""
Jean-Baptiste Keck
committed
defines = parseCMakeVar(var)
Jean-Baptiste Keck
committed
return None
# regex to match compiler defines like -DMACRO_NAME or
# -DMACRO_NAME = MACRO_VALUE
Jean-Baptiste Keck
committed
p = re.compile('\s*(?:-D)?\s*(\w+)(?:\s*=\s*(\w+))?\s*')
res = list()
for d in defines:
m = p.match(d)
if m:
res.append(m.group(1,2))
else:
print "\tWarning: Could extract cmake define from '", d, "'."
Jean-Baptiste Keck
committed
return res
hysop_link_libraries = parseCMakeVar("@HYSOP_LINK_LIBRARIES@")
#hysop_link_libraries_names = set([])
#hysop_link_libraries_dirs = set([])
#link_list = ""
# for lib in hysop_link_libraries:
# hysop_link_libraries_names.add(os.path.basename(lib))
# hysop_link_libraries_dirs.add(os.path.dirname(lib))
# link_list += lib + " "
# hysop_link_libraries_names = list(hysop_link_libraries_names)
# hysop_link_libraries_dirs = list(hysop_link_libraries_dirs)
def create_fortran_extension(name, pyf_file=None, src_dirs=None, sources=None,
libdir=None, libs=None, debug_mode=0):
"""Create a new f2py module from fortran files
Parameters
----------
name: string
python module name
pyf_file: string, optional
f2py interface file (absolute path)
src_dirs: list, optional
all directories containing fortran sources (absolute path)
that must be taken into account. Warning: dir. scan is not
recursive.
sources: list, optional
all fortran files that must be taken into account
libs: list of strings, optional
names of all libraries to be linked with to build f2py module
--> for -l option
libdir: list of strings, optional
list of directories, absolute path to libraries listed in libs
--> for -L... option
debug_mode: boolean, optional
if true enable f2py debug mode, default=False
Notes
-----
* either sources or src_dirs is required but both
can be used simultaneously.
* only .f90 and .f95 files are taken into account.
if sources is None:
sources = []
assert src_dirs is not None
for sdir in src_dirs:
sources += glob.glob(os.path.join(sdir, '*.f95'))
sources += glob.glob(os.path.join(sdir, '*.f90'))
# Reorder source list with fortran modules
# dependencies. It seems that this is not taken into
# account in f2py or distutils.
if pyf_file is not None:
sources.append(pyf_file)
sources = sort_f90.sort(sources)
# --- set f2py options ---
f2py_options = ['--no-lower', '--no-wrap-functions']
options = []
if debug_mode == 0:
options.append(('F2PY_REPORT_ON_ARRAY_COPY', '1'))
if os.uname()[0] == 'Linux':
options.append(('F2PY_REPORT_ATEXIT', '1'))
# --- set include dir ---
inc_dir = parseCMakeVar("@MPI_Fortran_INCLUDE_PATH@")
inc_dir.append('@CMAKE_Fortran_MODULE_DIRECTORY@')
# --- set compilation flags ---
Jean-Baptiste Keck
committed
#includes = parseCMakeVar("@FORTRAN_INCLUDE_DIRS@")
#if(includes != None):
# for exti in includes:
#i nc_dir.append(exti)
#libs += hysop_link_libraries_names
#libdir += hysop_link_libraries_dirs
# we trust cmake for external libraries and
# add them to linker, without using libraries option
extra_link_args = hysop_link_libraries
ext_fort = Extension(name=name,
sources=sources,
f2py_options=f2py_options,
include_dirs=inc_dir,
define_macros=options,
library_dirs=libdir,
libraries=libs,
extra_f90_compile_args=fortran_flags,
extra_link_args=extra_link_args
Jean-Baptiste Keck
committed
def create_swig_extension(name, inc_dirs, src_dirs=None, sources=None):
"""Create a python module from C++ files, using swig
Parameters
----------
name: string
module name
inc_dirs: list
list of directories for includes (-I ...), absolute path
containing headers (.hpp) and swig files (.i)
sources: list, optional
all c++ files that must be taken into account
src_dirs: list, optional
all directories containing fortran sources (absolute path)
that must be taken into account. Warning: no recursive scan
in src_dirs.
Notes
-----
* either sources, src_dirs or inc_dirs is required but all
can be used simultaneously.
* only .cpp files are taken into account.
* main config file for swig is assumed to be
name.i in CMAKE_SOURCE_DIR/swig/
swig_dir = os.path.join('@CMAKE_SOURCE_DIR@', 'swig')
swig_config_file = os.path.join(swig_dir, name + '.i')
Jean-Baptiste Keck
committed
include_dirs = set(inc_dirs)
if sources is None:
sources = []
assert src_dirs is not None or inc_dirs is not None
if(src_dirs is None):
assert(inc_dirs is not None)
for idir in inc_dirs:
#sources += glob.glob(os.path.join(idir, '**/*.cpp'), recursive=True)
for root, dirnames, filenames in os.walk(idir):
for filename in fnmatch.filter(filenames, '*.cpp'):
sources.append(os.path.join(root, filename))
else:
for sdir in src_dirs:
sources += glob.glob(os.path.join(sdir, '*.cpp'))
Jean-Baptiste Keck
committed
Jean-Baptiste Keck
committed
include_dirs = list(include_dirs)
name = 'hysop._' + name
swig_opts = ['-I' + swig_dir,
Jean-Baptiste Keck
committed
'-O', '-Wextra', '-Werror',
'-c++', '-extranative', '-safecstrings']
Jean-Baptiste Keck
committed
extern_includes = parseCMakeVar("@CXX_EXT_INCLUDES@")
Jean-Baptiste Keck
committed
for exti in extern_includes:
include_dirs.append(exti)
Jean-Baptiste Keck
committed
libraries = parseCMakeVar("@CXX_EXT_LIBS@")
library_dirs = parseCMakeVar("@CXX_EXT_LIB_DIRS@")
extra_compile_args = parseCMakeVar("@CXX_FLAGS@")
extra_link_args = parseCMakeVar("@CXX_LINKER_FLAGS@")
define_macros = parseCMakeDefines("@CXX_EXTRA_DEFINES@")
swig_ext = Extension(name, sources=sources, language='c++',
swig_opts=swig_opts,
Jean-Baptiste Keck
committed
include_dirs=include_dirs,
library_dirs=library_dirs,
libraries=libraries,
define_macros=define_macros,
Jean-Baptiste Keck
committed
runtime_library_dirs=library_dirs,
Jean-Baptiste Keck
committed
extra_compile_args=extra_compile_args,
extra_link_args=extra_link_args)
# ------------ Set list of packages required to build the module -------------
with_test = "@WITH_TESTS@" is "ON"
if with_test:
packages = find_packages(exclude=["*gpu*"], where="@CMAKE_SOURCE_DIR@")
packages = find_packages(exclude=["*tests*", "*gpu*"],
where="@CMAKE_SOURCE_DIR@")
if "@WITH_GPU@" is "ON":
if with_test:
packages.append('hysop.gpu.tests')
Jean-Matthieu Etancelin
committed
DISTUTILS_DEBUG = 1
# ------------ Extensions (f2py, cython, ...) setup ------------
ext_modules = []
# Check if fortran interface is enabled
if enable_fortran is "ON":
fortran_root = \
'@CMAKE_SOURCE_DIR@/hysop'
hysop_libdir = [] ##### ['@CMAKE_BINARY_DIR@/src']
#####hysoplib = ['@HYSOP_LIBRARY_NAME@']
f2py_options = ['--no-lower']
# -- list of directories which contains fortran sources --
# path must be relative to hysop package directory
subdirs = ['common_f', ]
withfftw = "@WITH_FFTW@"
if withfftw is "ON":
# fortran_src.add('f2py/fftw2py.f90')
subdirs.append(os.path.join('numerics/fftw_f'))
#fortran_src.add('f2py/fftw2py.f90')
fftwdir = '@FFTWLIB@'
#hysoplib.append('fftw3')
#hysoplib.append('fftw3_mpi')
withscales = '@WITH_SCALES@'
if withscales is "ON":
fortran_src.add('f2py/scales2py.f90')
# -- set full path to fortran sources --
fortran_src = list(fortran_src)
for i in xrange(len(fortran_src)):
fortran_src[i] = os.path.join(fortran_root, fortran_src[i])
precision_file = os.path.join('@GENERATED_FORTRAN_FILES_DIR@',
'precision.f95')
fortran_src.insert(0, precision_file)
# === Draft for future implementation of fortran interface ===
# -- f2py signature file --
pyf_file = os.path.join('@GENERATED_FORTRAN_FILES_DIR@', 'f2hysop.pyf')
# change from relative path in subdirs to absolute path in num_dirs
num_dirs = []
for sd in subdirs:
num_dirs.append(os.path.join(fortran_root, sd))
# create python interface to fortran sources
# For the moment, it includes the 'old' interface
# to scales and fftw (in sources) and the new
# interface, in src_dirs
ext['f2hysop'] = create_fortran_extension(
name='hysop.f2hysop',
sources=fortran_src,
pyf_file=pyf_file,
src_dirs=num_dirs)
for ex in ext:
ext_modules.append(ext[ex])
# --- C++ files and swig interface --
Franck Pérignon
committed
if enable_cpp is "ON":
swig_include_dirs = [os.path.join('@CMAKE_SOURCE_DIR@','swig')]
cpp_include_dirs = ['src/fftw','src/hysop++/src']
for d in cpp_include_dirs:
swig_include_dirs.append(os.path.join('@CMAKE_SOURCE_DIR@', d))
cpp2hysop = "@CPP_2_HYSOP@"
ext[cpp2hysop] = create_swig_extension(name=cpp2hysop,
inc_dirs=swig_include_dirs)
for ex in ext:
ext_modules.append(ext[ex])
if "@WITH_GPU@" is "ON":
cl_src_dirs = ["cl_src", "cl_src/kernels",
"cl_src/advection", "cl_src/remeshing"]
for cl_dir in cl_src_dirs:
data_files.append(
('./hysop/gpu/' + cl_dir,
['@CMAKE_SOURCE_DIR@/hysop/gpu/' + cl_dir + '/'
+ cl_file
for cl_file in os.listdir(
'@CMAKE_SOURCE_DIR@/hysop/gpu/' + cl_dir + '/')
if cl_file[0] != '.' and cl_file[0] != '#' and cl_file[-3:] == '.cl']))
descr = 'Hybrid Computation with Particles.'
Jean-Baptiste Keck
committed
authors = 'G.H Cottet, J.M Etancelin, J.B Keck, C.Mimeau, F.Pérignon, C. Picard'
# authors = 'HySoP development team'
config = Configuration(
name='@PACKAGE_NAME@',
version='@HYSOP_VERSION@',
description=descr,
author=authors,
author_email='hysop-members@lists.forge.imag.fr',
url='https://forge.imag.fr/projects/hysop/',
license='GNU General Public License (GPLv3)',
package_dir={'': '@CMAKE_SOURCE_DIR@'},
ext_modules=ext_modules,
packages=packages,
data_files=data_files,
setup(**config.todict())