#=============================================================================== # 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) cmake_policy(SET CMP0053 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_GPU "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} 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(scitools 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(backports.weakref REQUIRED) find_python_module(argparse_color_formatter REQUIRED) find_python_module(primefac REQUIRED) find_python_module(graph_tool REQUIRED) find_python_module(pyopencl REQUIRED) find_python_module(pyfftw REQUIRED) find_python_module(gpyfft REQUIRED) # --- MPI --- if(USE_MPI) find_package(MPI REQUIRED) find_python_module(mpi4py REQUIRED) endif() # --- PLOT -- find_python_module(matplotlib) if(NOT matplotlib_FOUND) find_python_module(Gnuplot) 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 ON) set(FIND_FFTW_DEBUG OFF) set(FIND_FFTW_SHARED_ONLY ON) 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_GPU) 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 -DBLOCKING_SEND_PLUS -DBLOCKING_SEND") append_Fortran_FLAGS("-Wall -fPIC -ffree-line-length-none -cpp") 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.") # # ====== Create a Target to generate the documentation ====== # find_package(Doxygen) # if(DOXYGEN_FOUND) # find_file(DOXY name doxypy.py PATH ENV{PATH}) # if(DOXY-NOTFOUND) # message(STATUS "Warning, doxypy seems to be missing on your system. You may not be able to properly generate the documentation.") # endif() # configure_file(${CMAKE_SOURCE_DIR}/docs/config/hysop.doxyfile.in ${CMAKE_BINARY_DIR}/docs/config/hysop.doxyfile) # add_custom_target(doc COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/docs/config/hysop.doxyfile # COMMENT "Generate hysop documentation using doxygen.") # else() # message(STATUS "Warning : cmake cannot find doxygen on your system. It means you will not be able to generate documentation for hysop.") # add_custom_target(doc COMMAND echo "Doxygen was not found on your system. Documentation generation is not possible." # COMMENT "Generate hysop documentation using doxygen.") # endif() # ============= 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 GPU : ${WITH_GPU}") 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 : simple.") 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)