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 not extract cmake define from '", d, "'."
Jean-Baptiste Keck
committed
return res
hysop_link_libraries = parseCMakeVar("@HYSOP_LINK_LIBRARIES@")
# deal with macosx framework ...
extra_flags = []
for lib in hysop_link_libraries:
res = lib.find('framework')
if res >= 0:
filename = os.path.basename(lib)
hysop_link_libraries.pop(index)
filename = filename.split('.')[0]
extra_flags.append('-framework ' + filename)
hysop_link_libraries += extra_flags
# hysop_link_libraries_names = set()
# hysop_link_libraries_dirs = set()
# hysop_link_libraries_names.add(os.path.basename(lib))
# hysop_link_libraries_dirs.add(os.path.dirname(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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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 = []
options.append(('F2PY_REPORT_ON_ARRAY_COPY', '1'))
if os.uname()[0] == 'Linux':
options.append(('F2PY_REPORT_ATEXIT', '1'))
inc_dir = parseCMakeVar("@FORTRAN_INCLUDE_DIRS@")
inc_dir += parseCMakeVar("@MPI_Fortran_INCLUDE_PATH@")
inc_dir += parseCMakeVar('@CMAKE_Fortran_MODULE_DIRECTORY@')
# --- set include dir ---
# inc_dir += hysop_link_libraries_dirs
# --- set external libraries ---
# libs += hysop_link_libraries_names
# we trust cmake for external libraries and
# add them to linker, without using libraries option
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@")
for exti in extern_includes:
include_dirs.append(exti)
Jean-Baptiste Keck
committed
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":
subdirs.append(os.path.join('numerics', 'fftw_f'))
fftwdir = '@FFTWLIB@'
withscales = '@WITH_SCALES@'
if withscales is "ON":
subdirs.append('scales_f')
#fortran_src.add('f2py/scales2py.f90')
# -- other fortran sources --
withextras = '@WITH_EXTRAS@'
if withextras is "ON":
subdirs.append(os.path.join('numerics', 'extras_f'))
# -- 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())