-
Jean-Baptiste Keck authoredJean-Baptiste Keck authored
CMakeLists.txt 28.31 KiB
#===============================================================================
# cmake utility to compile and install hysop python modules and libraries
#
# It includes :
# - high level python interface to HySoP routines
# - HySoP fortran library (with fftw solver and scales interface)
# - HySoP C++ library (poisson solver)
#
# HySoP depends (optionally) on :
# - scales (WITH_SCALES=ON, default)
#
# LJK-CNRS, F. Pérignon, june 2012
#
#===============================================================================
#
# ============= Global cmake Settings =============
# Set minimum version for cmake
cmake_minimum_required(VERSION 3.0.2)
if(POLICY CMP0053)
# Simplify variable reference and escape sequence evaluation (cmake 3.1)
cmake_policy(SET CMP0053 NEW)
endif()
if(POLICY CMP0074)
# find_package(<PackageName>) commands will first search prefixes specified by the <PackageName>_ROOT (cmake 3.12)
cmake_policy(SET CMP0074 NEW)
endif()
# Set cmake modules directory (i.e. the one which contains all user-defined FindXXX.cmake files among other things)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
# Force out-of-source build
include(OutOfSourceBuild)
# Some usefull macros
include(MyTools)
# User defined options
option(VERBOSE_MODE "Print cmake-hysop state summary. Default = on" ON)
option(DOUBLEPREC "Set default HySoP floating point precision. Default = on, ie double precision else single precision will be used." ON)
option(USE_MPI "Compile and link HySoP with mpi when this mode is enable. Default = on. WARNING: off mode is bugged." ON)
option(WITH_TESTS "Enable testing. Default = OFF" ON)
option(BUILD_SHARED_LIBS "Enable dynamic library build, default = ON." ON)
option(USE_CXX "Expand hysop with some new functions from a generated c++ to python interface, wrapped into hysop.cpp2hysop module. Default = ON." OFF)
option(WITH_SCALES "compile/create scales lib and link it with HySoP. Default = ON." ON)
option(WITH_PARALLEL_COMPRESSED_HDF5 "Try to enable parallel compressed hdf5 interface. Default = ON." ON)
option(WITH_FFTW "Link with fftw library (required for some HySoP solvers), default = ON" ON)
option(WITH_EXTRAS "Link with some extra fortran libraries (like arnoldi solver), default = OFF" OFF)
option(WITH_OPENCL "Use of GPU (required for some HySoP solvers), default = ON" ON)
option(WITH_MAIN_FORTRAN "Create an executable (test purpose) from fortran sources in src/main, linked with libhysop, default = OFF" OFF)
option(WITH_MAIN_CXX "Create an executable (test purpose) from cxx sources in src/hysop++/main, linked with libhysop, default = OFF" OFF)
option(PROFILE "Enable profiling mode for HySoP. Can also be enabled with HYSOP_PROFILE environment variable. Default = OFF" OFF)
option(VERBOSE "Enable verbose mode for HySoP. Can also be enabled with HYSOP_VERBOSE environment variable. Default = OFF" OFF)
option(DEBUG "Enable debug mode for HySoP. Can also be enabled with HYSOP_DEBUG environment variable. Default = OFF" OFF)
option(FULL_TEST "Enable all test options (pep8, mpi ...) - Default = OFF" OFF)
option(OPTIM "To allow python -OO run, some packages must be deactivated. Set this option to 'ON' to do so. Default = OFF" OFF)
option(WITH_MPI_TESTS "Enable mpi tests. Default = OFF." OFF)
option(WITH_GOOGLE_TESTS "Enable google tests (c++). Default = OFF." OFF)
option(FORTRAN_LAYOUT "Choose default data layout ('fortran', column-major or 'C' order, row-major) for arrays. Default = column-major." OFF)
option(WITH_DOCUMENTATION "Build Documentation. Default = OFF" OFF)
option(ENABLE_LONG_TESTS "Enable tests that may run for long time with important memory print. Default = OFF." OFF)
option(DEV_MODE "Enable devel mode (aggressive checking of warnings ..). Default = ON." ON)
# Set python install mode:
# - user --> behave as 'python setup.py install --user'
# - standard --> install in python site-package (ie behave as python setup.py install)
# - prefix --> install in python CMAKE_INSTALL_PREFIX (ie behave as python setup.py install --prefix=CMAKE_INSTALL_PREFIX)
set(HYSOP_INSTALL "user" CACHE STRING "Install mode for hysop python package")
# Install lib directory 32, 64 etc. on Fedora, Debian
# http://public.kitware.com/Bug/view.php?id=11964
# See also http://www.cmake.org/cmake/help/v3.0/module/GNUInstallDirs.html?highlight=gnuinstalldirs
include(GNUInstallDirs)
# Set prefix path for libraries installation
# --> means that any library target will be installed
# in CMAKE_INSTALL_PREFIX/_install_lib
if(${PROJECT_NAME}_INSTALL_LIB_DIR)
set(_install_lib ${${PROJECT_NAME}_INSTALL_LIB_DIR})
else()
ASSERT(CMAKE_INSTALL_LIBDIR)
set(_install_lib ${CMAKE_INSTALL_LIBDIR})
set(${PROJECT_NAME}_INSTALL_LIB_DIR ${_install_lib})
endif()
if(NOT USE_MPI)
message(FATAL_ERROR "Non-mpi version of hysop has been depcecated, please enable mpi.")
endif()
# Fortran interface is not used by default.
set(USE_FORTRAN "OFF")
if(WITH_FFTW OR WITH_SCALES OR WITH_EXTRAS)
set(USE_FORTRAN "ON")
endif()
if(NOT USE_CXX)
set(WITH_MAIN_CXX "OFF")
set(WITH_GOOGLE_TESTS "OFF")
endif()
# Force a default build type if not provided by user
# CMAKE_BUILD_TYPE = empty, Debug, Release, RelWithDebInfo or MinSizeRel.
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE RELEASE CACHE STRING
"Choose the type of build, options are: None Debug Release."
FORCE)
endif()
# cmake project name
set(PROJECT_NAME hysop)
# --- Name for the package ---
# This name will be used as the Python Package name
set(PACKAGE_NAME "hysop")
# --- The name (without extension) of the lib to be created ---
set(PROJECT_LIBRARY_NAME ${PROJECT_NAME})
# ============= The project =============
# Set project name and project languages
# => this automatically defines:
# - ${PROJECT_NAME}_BINARY_DIR : where you have run cmake, i.e. the place for compilation
# - ${PROJECT_NAME}_SOURCE_DIR : where sources (.f and .h and this CMakeLists.txt) are located
# Note that because of OutOfSourceBuild, binary_dir and source_dir must be different.
set(LANGLIST)
if(USE_CXX)
set(LANGLIST ${LANGLIST} C CXX)
endif()
if(USE_FORTRAN)
set(LANGLIST ${LANGLIST} C Fortran)
endif()
include(HysopVersion)
project(${PROJECT_NAME} ${LANGLIST})
set(HYSOP_LIBRARY_NAME hysop)
set(HYSOP_INCLUDE_DIRECTORIES
CACHE INTERNAL "Include directories for external dependencies.")
set(HYSOP_LINK_LIBRARIES CACHE INTERNAL "List of external libraries.")
# ============= Python and its packages =============
# - Global setup (interp and lib) -
find_package(PythonFull REQUIRED)
include(FindPythonModule)
# - python packages -
find_python_module(numpy REQUIRED)
find_python_module(scipy REQUIRED)
find_python_module(h5py REQUIRED)
find_python_module(sympy REQUIRED)
find_python_module(psutil REQUIRED)
find_python_module(cpuinfo REQUIRED)
find_python_module(gmpy2 REQUIRED)
find_python_module(subprocess32 REQUIRED)
find_python_module(editdistance REQUIRED)
find_python_module(portalocker REQUIRED)
find_python_module(tee REQUIRED)
find_python_module(colors REQUIRED) # ansicolor package
find_python_module(argparse_color_formatter REQUIRED)
find_python_module(primefac REQUIRED)
find_python_module(networkx REQUIRED)
find_python_module(pyfftw REQUIRED)
find_python_module(matplotlib OPTIONAL)
find_python_module(pyvis OPTIONAL)
find_package( OpenCL )
if(${OpenCL_LIBRARY}) # Some opencl related python package fails to import on non OpenCL machines (cluster's frontend for instance)
find_python_module(pyopencl REQUIRED)
find_python_module(gpyfft REQUIRED)
else()
find_python_module(pyopencl )
find_python_module(gpyfft )
endif()
# --- MPI ---
if(USE_MPI)
find_package(MPI REQUIRED)
find_python_module(mpi4py REQUIRED)
endif()
# --- Wheel, required for a proper build/install process ---
find_python_module(wheel REQUIRED)
if(USE_CXX)
find_package(SWIG 3.0.2 REQUIRED)
# WARNING FP : for cmake < 3.0 UseSWIG.cmake
# does not work properly (bug for swig outdir)
if(CMAKE_VERSION VERSION_LESS 3.0.0)
set(SWIG_USE_FILE ${CMAKE_SOURCE_DIR}/cmake/UseSWIG.cmake)
endif()
include(${SWIG_USE_FILE})
endif()
# Find python build dir name --> needed for tests and doc
if(USE_CXX OR USE_FORTRAN)
execute_process(
COMMAND ${PYTHON_EXECUTABLE} -c "import distutils.util as ut ; import distutils.sysconfig as sy; print('lib.'+ut.get_platform()+'-'+sy.get_python_version())"
OUTPUT_VARIABLE ${PROJECT_NAME}_PYTHON_BUILD_DIR)
string(STRIP ${${PROJECT_NAME}_PYTHON_BUILD_DIR} ${PROJECT_NAME}_PYTHON_BUILD_DIR)
set(HYSOP_BUILD_PYTHONPATH ${CMAKE_BINARY_DIR}/build/${${PROJECT_NAME}_PYTHON_BUILD_DIR} CACHE INTERNAL "Python package build path")
else()
set(HYSOP_BUILD_PYTHONPATH ${CMAKE_BINARY_DIR}/build/lib CACHE INTERNAL "Python package build path")
endif()
# ============= Other dependencies =============
# --- FFTW ---
if(WITH_FFTW)
set(FIND_FFTW_VERBOSE CACHE BOOL OFF)
set(FIND_FFTW_DEBUG CACHE BOOL OFF)
compile_with(FFTW
REQUIRED COMPONENTS Fftw3f Fftw3d
Fftw3f-mpi Fftw3d-mpi
OPTIONAL_COMPONENTS
Fftw3f-threads Fftw3d-threads
Fftw3l Fftw3l-mpi Fftw3l-threads
Fftw3q Fftw3q-threads)
set(dirlist)
foreach(_file ${FFTW_LIBRARIES})
get_filename_component(_name ${_file} DIRECTORY)
list(FIND dirlist "${_name}" isin)
if(isin EQUAL -1)
list(APPEND dirlist ${_name})
endif()
endforeach()
set(FFTWLIB ${dirlist} CACHE PATH "fftw libraries dir")
add_definitions(${FFTW_DEFINES})
endif()
if(USE_CXX)
compile_with(Boost REQUIRED)
endif()
if(WITH_EXTRAS)
# Arnoldi solver needs zgeev, which means lapack
compile_with(LAPACK)
foreach(_file ${LAPACK_LIBRARY})
get_filename_component(_name ${_file} DIRECTORY)
list(FIND dirlist ${_name} isin)
if(isin EQUAL -1)
list(APPEND dirlist ${_name})
endif()
endforeach()
set(EXTRASLIB ${dirlist} CACHE PATH "extras libraries dir")
endif()
# ========= Check parallel hdf5 availability =========
if(WITH_PARALLEL_COMPRESSED_HDF5)
execute_process(
COMMAND ${PYTHON_EXECUTABLE} -c "import h5py; print('.'.join(str(_) for _ in h5py.h5.get_libversion()))"
OUTPUT_VARIABLE LIB_HDF5_VERSION)
string(REGEX REPLACE "\n$" "" LIB_HDF5_VERSION "${LIB_HDF5_VERSION}")
execute_process(
COMMAND ${PYTHON_EXECUTABLE} -c "import h5py; print(h5py.h5.get_libversion() >= (1,10,2) )"
OUTPUT_VARIABLE H5PY_PARALLEL_COMPRESSION_ENABLED)
if(H5PY_PARALLEL_COMPRESSION_ENABLED EQUAL "False")
message(WARNING "Your hdf5 library is too old to support parallel compression support. Minimal version is 1.10.2 but h5py was linked to version $LIB_HDF5_VERSION. Parallel HDF5 compression will be disabled.")
set(H5PY_PARALLEL_COMPRESSION_ENABLED "OFF")
else()
message(STATUS "Found h5py linked against libhdf5 version ${LIB_HDF5_VERSION}. Parallel HDF5 compression will enabled.")
set(H5PY_PARALLEL_COMPRESSION_ENABLED "ON")
endif()
else()
set(H5PY_PARALLEL_COMPRESSION_ENABLED "OFF")
endif()
# ========= Check which opencl devices are available on the system =========
if(WITH_OPENCL)
execute_process(
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/opencl_explore.py "EXPLORE")
execute_process(
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/opencl_explore.py
OUTPUT_VARIABLE OPENCL_DEFAULT_OPENCL_ID)
else()
execute_process(
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/opencl_explore.py "EXPLORE" CPU)
execute_process(
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/opencl_explore.py CPU
OUTPUT_VARIABLE OPENCL_DEFAULT_OPENCL_ID)
endif()
string(REPLACE " " ";" MY_LIST ${OPENCL_DEFAULT_OPENCL_ID})
list(GET MY_LIST 0 OPENCL_DEFAULT_OPENCL_PLATFORM_ID)
list(GET MY_LIST 1 OPENCL_DEFAULT_OPENCL_DEVICE_ID)
display(OPENCL_DEFAULT_OPENCL_PLATFORM_ID)
display(OPENCL_DEFAULT_OPENCL_DEVICE_ID)
# =========== RPATH stuff ===========
# Doc :
# - https://cmake.org/Wiki/CMake_RPATH_handling
# - https://cmake.org/cmake/help/git-master/manual/cmake-packages.7.html#creating-packages
# - http://matthew-brett.github.io/docosx/mac_runtime_link.html
# Force MACOSX_RPATH, whatever the cmake version is.
# RPATH management on macosx with cmake is quite a mess, so please
# think hard before changing the following lines ...
set(CMAKE_MACOSX_RPATH 1)
# don't skip the full RPATH for the build tree
# except if explicitely asked by user
if(FORCE_SKIP_RPATH)
set(CMAKE_SKIP_BUILD_RPATH TRUE)
else()
set(CMAKE_SKIP_BUILD_RPATH FALSE)
endif()
# when building, don't use the install RPATH already
# (but later on when installing)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "${HYSOP_PYTHON_INSTALL_DIR}/${PACKAGE_NAME}")
# add the automatically determined parts of the RPATH
# which point to directories outside the build tree to the install RPATH
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
# ====== Create (and setup) build target ======
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${CMAKE_BINARY_DIR}/build)
set(PYTHON_SETUP "${CMAKE_CURRENT_BINARY_DIR}/setup.py")
if(USE_FORTRAN)
# if fortran is enabled, explicit setup of the compiler is required.
add_custom_target(wheel ALL
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/setup.py bdist_wheel build config_fc --f90exec=${CMAKE_Fortran_COMPILER}#-d ${CMAKE_BINARY_DIR}/wheel/
COMMENT "create wheel file for ${PACKAGE_NAME} package"
DEPENDS ${HYSOP_LIBRARY_NAME}
)
else()
add_custom_target(wheel ALL
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/setup.py bdist_wheel #-d ${CMAKE_BINARY_DIR}/wheel/
COMMENT "create wheel file for ${PACKAGE_NAME} package"
)
endif()
# ====== Create (and setup) install/uninstall targets ======
#
# --> set installation dir
# --> set options for python install
# --> create install/uninstall targets
include(HySoPInstallSetup)
# Remark : this must be done before add_subdir below, since install process in src needs CMAKE_INSTALL_PREFIX
# to be properly set.
# # ============= Extra setup =============
# set precision for real numbers
# used to generate precision.f95 file/module and constant.py
if(DOUBLEPREC)
# -- Variables required in fortran files --
set(WORKING_PRECISION dp)
set(MPI_PRECISION MPI_DOUBLE_PRECISION)
# -- Variables required in python files --
set(PYTHON_PREC np.float64)
set(MPI_PYTHON_PREC MPI.DOUBLE)
# -- f2py stuff --
set(f2pymap_for_real double)
else()
set(WORKING_PRECISION sp)
set(MPI_PRECISION MPI_FLOAT)
set(PYTHON_PREC np.float32)
set(MPI_PYTHON_PREC MPI.FLOAT)
set(f2pymap_for_real float)
endif()
# set data layout ('fortran' order or 'C' order) in python (numpy).
if(FORTRAN_LAYOUT)
set(DATA_LAYOUT 'F')
else()
set(DATA_LAYOUT 'C')
endif()
if(EXISTS ${CMAKE_SOURCE_DIR}/${PACKAGE_NAME}/constants.py.in)
message(STATUS "Generate constant.py file ...")
configure_file(${CMAKE_SOURCE_DIR}/${PACKAGE_NAME}/constants.py.in
${CMAKE_SOURCE_DIR}/${PACKAGE_NAME}/constants.py)
endif()
if(USE_FORTRAN)
# Path to fortran-related generated files (.pyf, precision ...)
set(GENERATED_FORTRAN_FILES_DIR ${CMAKE_BINARY_DIR}/generated_fortran/)
# --- copy sort_f90 file to build ---
# Required for setup.py to handle fortran files dependencies
configure_file(${CMAKE_SOURCE_DIR}/sort_f90.py ${CMAKE_BINARY_DIR}/sort_f90.py)
# --- Generate f2py_f2cmap file ---
if(EXISTS ${CMAKE_SOURCE_DIR}/f2py_f2cmap.in)
message(STATUS "Generate f2py map file ...")
configure_file(${CMAKE_SOURCE_DIR}/f2py_f2cmap.in
${CMAKE_BINARY_DIR}/.f2py_f2cmap)
endif()
# --- Create top-level pyf file ---
# -> depends on cmake config. This file
# includes the other required pyf files.
# For example, if WITH_FFTW is ON, then
# add a line 'include fftw2py.py'
set(F_2_HYSOP "f2hysop")
include(fortran_utils)
write_main_pyf_file(${F_2_HYSOP})
# f2py failed with:
# real(kind=wp), dimension(:) :: tab
# whit wp = real64 or real32 from iso_fortran_env
# a const parameter defined in another module
# AND tab is an assumed shaped array, even when using a f2py_f2cmap file.
# The solution is to set directly real(kind=8) in pyf file.
# --- fortran libraries setup ---
# Set module files directory (i.e. where .mod will be created)
set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/Modules)
# Add compilation flags:
append_Fortran_FLAGS("-Wall -fPIC -ffree-line-length-none -cpp")
append_Fortran_FLAGS("-Wno-unused-dummy-argument -Wno-integer-division -Wno-unused-value -Wno-maybe-uninitialized -Wno-unused-function")
if (CMAKE_Fortran_COMPILER_ID MATCHES "GNU" AND CMAKE_Fortran_COMPILER_VERSION GREATER_EQUAL 10.0)
append_Fortran_FLAGS("-fallow-argument-mismatch")
endif()
if(USE_MPI)
# -I
include_directories(${MPI_Fortran_INCLUDE_PATH})
# Add compilation/link flags
list(APPEND ${HYSOP_LIBRARY_NAME}_LINK_FLAGS ${MPI_Fortran_LINK_FLAGS})
append_Fortran_flags(${MPI_Fortran_COMPILE_FLAGS})
# Append mpi libraries to the list of libraries linked with libhysop.
list(APPEND HYSOP_LINK_LIBRARIES ${MPI_Fortran_LIBRARIES} )
endif(USE_MPI)
set(Fortran_FLAGS ${CMAKE_Fortran_FLAGS})
append_flags(Fortran_FLAGS ${CMAKE_Fortran_FLAGS_${CMAKE_BUILD_TYPE}})
# --- Generate precision.f95 and precision.pyf files ---
if(EXISTS ${CMAKE_SOURCE_DIR}/precision.conf.in)
message(STATUS "Generate precision.f95 file ...")
configure_file(${CMAKE_SOURCE_DIR}/precision.conf.in
${GENERATED_FORTRAN_FILES_DIR}/precision.f95)
configure_file(${CMAKE_SOURCE_DIR}/precision.conf.in
${GENERATED_FORTRAN_FILES_DIR}/precision.pyf)
endif()
endif()
if(USE_FORTRAN)
add_subdirectory(src)
set(FORTRAN_INCLUDE_DIRS ${FFTW_INCLUDE_DIRS})
endif()
if(USE_CXX)
#C++ variables used by setup.py.in for swig
if(DEV_MODE)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(CXX_WARNING_FLAGS "-W -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-unused-local-typedefs -Wno-missing-braces")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CXX_WARNING_FLAGS "-W -Wall -Wextra -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-local-typedefs -Wno-deprecated-declarations")
#elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
#elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
else()
set(CXX_WARNING_FLAGS "")
endif()
endif()
list(APPEND CMAKE_CXX_FLAGS "${CXX_WARNING_FLAGS} ${FFTW_COMPILE_FLAGS} -fPIC -std=c++11")
if(APPLE)
list(APPEND CMAKE_EXE_LINKER_FLAGS "-ldl -lutil")
else()
list(APPEND CMAKE_EXE_LINKER_FLAGS "-Wl,--no-as-needed -ldl -lutil")
endif()
set(CXX_FLAGS ${CMAKE_CXX_FLAGS})
set(CXX_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS})
set(CXX_EXTRA_DEFINES ${FFTW_DEFINES} "-DHAS_EXTERN_TEMPLATES")
set(CXX_EXT_INCLUDES ${Boost_INCLUDE_DIR} ${PYTHON_INCLUDE_DIR} ${FFTW_INCLUDE_DIRS})
set(CXX_EXT_LIBS ${Boost_LIBRARIES} ${PYTHON_LIBRARIES} ${FFTW_LIBRARIES})
set(CXX_EXT_LIB_DIR ${Boost_LIBRARY_DIRS} ${PYTHON_LIBRARY_DIRS} ${FFTW_LIBRARY_DIRS})
set(CMAKE_INCLUDE_SYSTEM_FLAG_C "-isystem ")
set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "-isystem ")
#swig package name (lib name generated by swig)
set(CPP_2_HYSOP "cpp2hysop")
endif()
# Append pythonlib to hysop link floags
list(APPEND HYSOP_LINK_LIBRARIES ${PYTHON_LIBRARIES} )
# ====== Generates python files required for build/install process ======
# The file setup.py will be generated from setup.py.in.
if(EXISTS ${CMAKE_SOURCE_DIR}/setup.py.in)
message(STATUS "Generate setup.py file ...")
configure_file(setup.py.in setup.py)
endif()
# The file __init__.py will be generated from __init__.py.in.
if(EXISTS ${CMAKE_SOURCE_DIR}/hysop/__init__.py.in)
message(STATUS "Generate __init__.py file ...")
file(REMOVE ${CMAKE_SOURCE_DIR}/hysop/__init__.py)
configure_file(hysop/__init__.py.in ${CMAKE_SOURCE_DIR}/hysop/__init__.py)
endif()
if(EXISTS ${CMAKE_SOURCE_DIR}/hysop/mpi/__init__.py.in)
message(STATUS "Generate mpi/__init__.py file ...")
file(REMOVE ${CMAKE_SOURCE_DIR}/hysop/mpi/__init__.py)
configure_file(hysop/mpi/__init__.py.in ${CMAKE_SOURCE_DIR}/hysop/mpi/__init__.py)
endif()
# Hysop C++ library is generated in setup.py by swig
# --- C++ main and tests ---
if(USE_CXX)
get_filename_component(CXX_DIR "${CMAKE_SOURCE_DIR}/src/hysop++" ABSOLUTE)
get_filename_component(CXX_MAIN_DIR "${CXX_DIR}/main" ABSOLUTE)
get_filename_component(CXX_TEST_DIR "${CXX_DIR}/tests" ABSOLUTE)
get_filename_component(CXX_SOURCE_DIR "${CXX_DIR}/src" ABSOLUTE)
include_directories(${CXX_SOURCE_DIR})
include_directories(SYSTEM ${CXX_EXT_INCLUDES})
link_directories(${CXX_EXT_LIB_DIRS})
add_definitions(${CXX_EXTRA_DEFINES})
if(WITH_MAIN_CXX OR WITH_GOOGLE_TESTS)
if(APPLE) #swig only generates a bundle, need to generate another static library...
set(HYSOP_CXX_LIBRARY_DYLIB "cpp2hysop_dylib")
file(GLOB_RECURSE source_files ${CXX_SOURCE_DIR}/*.cpp)
add_library(${HYSOP_CXX_LIBRARY_DYLIB} STATIC ${source_files})
target_link_libraries(${HYSOP_CXX_LIBRARY_DYLIB} ${EXT_LIBRARIES})
set(HYSOP_CXX_LIBRARY ${HYSOP_CXX_LIBRARY_DYLIB})
set(HYSOP_CXX_LIBRARY_DEP cpp2hysop_dylib)
else() #nothing to do on other platforms bundle <=> dynamic libraries, so just copy the swig generated one
set(HYSOP_CXX_LIBRARY_BUNDLE "${CMAKE_CURRENT_BINARY_DIR}/libcpp2hysop_bundle.so")
add_custom_target(cpp2hysop_bundle
DEPENDS wheel
COMMAND cp `find ${CMAKE_CURRENT_BINARY_DIR}/build -name _${CPP_2_HYSOP}.so` ${HYSOP_CXX_LIBRARY_BUNDLE}
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
COMMENT "Copy swig c++ library to link")
set(HYSOP_CXX_LIBRARY ${HYSOP_CXX_LIBRARY_BUNDLE})
set(HYSOP_CXX_LIBRARY_DEP cpp2hysop_bundle)
endif()
endif()
if(WITH_MAIN_CXX)
list(APPEND cxx_executable_sources "${CXX_MAIN_DIR}/planner.cpp")
list(APPEND cxx_executable_sources "${CXX_MAIN_DIR}/diffSolver.cpp")
list(APPEND cxx_executable_sources "${CXX_MAIN_DIR}/poissonSolver.cpp")
foreach(cxx_main_source ${cxx_executable_sources})
get_filename_component(cxx_exec_name "${cxx_main_source}" NAME_WE)
add_executable(${cxx_exec_name} ${cxx_main_source})
add_dependencies(${cxx_exec_name} ${HYSOP_CXX_LIBRARY_DEP})
target_link_libraries(${cxx_exec_name} ${HYSOP_CXX_LIBRARY} ${CXX_EXT_LIBS})
endforeach()
endif()
if(WITH_GOOGLE_TESTS)
add_subdirectory(${CXX_TEST_DIR})
endif()
endif()
# =========== RPATH stuff ===========
# Doc :
# - https://cmake.org/Wiki/CMake_RPATH_handling
# - https://cmake.org/cmake/help/git-master/manual/cmake-packages.7.html#creating-packages
# - http://matthew-brett.github.io/docosx/mac_runtime_link.html
# Force MACOSX_RPATH, whatever the cmake version is.
# RPATH management on macosx with cmake is quite a mess, so please
# think hard before changing the following lines ...
set(CMAKE_MACOSX_RPATH 1)
# don't skip the full RPATH for the build tree
# except if explicitely asked by user
if(FORCE_SKIP_RPATH)
set(CMAKE_SKIP_BUILD_RPATH TRUE)
else()
set(CMAKE_SKIP_BUILD_RPATH FALSE)
endif()
# when building, don't use the install RPATH already
# (but later on when installing)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${PACKAGE_NAME}")
# add the automatically determined parts of the RPATH
# which point to directories outside the build tree to the install RPATH
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
# the RPATH to be used when installing, but only if it's not a system directory
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/${PACKAGE_NAME}" isSystemDir)
if("${isSystemDir}" STREQUAL "-1")
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${PACKAGE_NAME}")
endif()
# ====== Create a Target to clean sources (remove .pyc files) and build dir ======
file(GLOB_RECURSE PYCFILES "${CMAKE_SOURCE_DIR}/*.pyc")
add_custom_target(pyclean COMMAND rm -f ${PYCFILES}
COMMAND make clean
COMMAND rm -rf ${CMAKE_BINARY_DIR}/build ${CMAKE_BINARY_DIR}/DoxygenGeneratedDoc
COMMAND rm ${CMAKE_SOURCE_DIR}/hysop/__init__.py
COMMENT "clean hysop sources and build.")
# ============= Tests =============
if(WITH_TESTS)
if(NOT ENABLE_LONG_TESTS)
set(TEST_TIMEOUT 360 CACHE STRING "Default value for test runtime limit (in seconds)")
else()
set(TEST_TIMEOUT 3600 CACHE STRING "Default value for test runtime limit (in seconds)")
endif()
include(CTest)
# Number of mpi processes used to run tests.
include(ProcessorCount)
ProcessorCount(NBPROCS_FOR_TESTS)
if(NOT N EQUAL 0)
set(CTEST_BUILD_FLAGS -j${NBPROCS_FOR_TESTS})
set(ctest_test_args ${ctest_test_args} PARALLEL_LEVEL ${NBPROCS_FOR_TESTS})
endif()
if(NOT USE_MPI)
set(WITH_MPI_TESTS "OFF")
endif()
include(hysop_tests)
endif(WITH_TESTS)
# ============= Documentation setup =============
if(WITH_DOCUMENTATION)
add_subdirectory(docs)
endif()
# ============= Summary =============
if(VERBOSE_MODE)
message("\n====================== End of configuration process ======================")
message("\n Summary: ")
message(STATUS " Python libraries : ${PYTHON_LIBRARIES}")
message(STATUS " Python include : ${PYTHON_INCLUDE_DIRS}")
message(STATUS " Python version : ${PYTHON_VERSION_STRING}")
message(STATUS " Python executable : ${PYTHON_EXECUTABLE}")
message(STATUS " Install mode is `${HYSOP_INSTALL}` and ${PACKAGE_NAME} will be installed in : ${HYSOP_PYTHON_INSTALL_DIR}")
message(STATUS " ${PACKAGE_NAME} will be built in ${HYSOP_BUILD_PYTHONPATH}")
if(USE_FORTRAN)
message(STATUS " Fortran compiler : ${CMAKE_Fortran_COMPILER}")
else()
message(WARNING "You deactivate fortran to python interface generation. This will disable the fortran interface, including fftw and scales fonctionnalities.")
endif()
if(USE_CXX)
message(STATUS " CXX compiler : ${CMAKE_CXX_COMPILER}")
else()
message(WARNING "You deactivate c++ to python interface generation. This will disable the Aitken-Schwarz Poisson solver.")
endif()
message(STATUS " Sources are in : ${CMAKE_SOURCE_DIR}")
message(STATUS " Build is done in : ${CMAKE_BINARY_DIR}")
message(STATUS " Project uses MPI : ${USE_MPI}")
message(STATUS " Project uses Scales : ${WITH_SCALES}")
message(STATUS " Project uses FFTW : ${WITH_FFTW}")
message(STATUS " Project uses OpenCL : ${WITH_OPENCL}")
message(STATUS " Project uses parallel HDF5 interface : ${H5PY_PARALLEL_COMPRESSION_ENABLED}")
message(STATUS " ${PROJECT_NAME} profile mode : ${PROFILE}")
message(STATUS " ${PROJECT_NAME} debug mode : ${DEBUG}")
message(STATUS " Enable -OO run? : ${OPTIM}")
if(DOUBLEPREC)
message(STATUS " Default real numbers precision : double.")
else()
message(STATUS " Default real numbers precision : single.")
endif()
message(STATUS "====================== ======= ======================")
message(STATUS " ")
message(STATUS "Try :")
message(STATUS " 'make -jN' to build the project, N being the number of available processes.")
message(STATUS " 'make install' to install python modules and their dependencies. ")
message(STATUS " 'make doc' to generate doxygen documentation for hysop.")
message(STATUS " 'make test' to run some test (after the build! Do not use -j with this target).")
message(STATUS " 'make clean' to clean build directory.")
message(STATUS " 'make uninstall' to clean install directory. Dry-run (make -n uninstall) is advisable to check what will really be deleted.")
message(STATUS "\n\n/!\\ Warning /!\\ : depending on your python environment configuration, you may need to set PYTHONPATH.")
message("Try to run python -c 'import hysop'. If it fails, add ${HYSOP_PYTHON_INSTALL_DIR} to PYTHONPATH environment variable.")
message("Example : \n export PYTHONPATH=${HYSOP_PYTHON_INSTALL_DIR}/:\${PYTHONPATH}\n")
endif()
# Add custom target to install compiled libraries locally
add_custom_target(update_libs
COMMAND find ${CMAKE_SOURCE_DIR}/hysop/ -name '*.so' -type f -delete
COMMAND find ${CMAKE_BINARY_DIR} -name '*.so' -type f -print0 | xargs -0 cp -t ${CMAKE_SOURCE_DIR}/hysop/
COMMAND [ -f "$ENV{HOME}/.hysop.__init__.py" ] && rm ${CMAKE_SOURCE_DIR}/hysop/__init__.py
COMMAND [ -f "$ENV{HOME}/.hysop.__init__.py" ] && cp $ENV{HOME}/.hysop.__init__.py ${CMAKE_SOURCE_DIR}/hysop/__init__.py
DEPENDS wheel)