Skip to content
Snippets Groups Projects
CMakeLists.txt 24.1 KiB
Newer Older
#[[
Copyright (C) HySoP 2011-2022

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
]]
Franck Pérignon's avatar
Franck Pérignon committed
cmake_minimum_required(VERSION 3.0.2)

if(POLICY CMP0053)
Jean-Baptiste Keck's avatar
Jean-Baptiste Keck committed
    # Simplify variable reference and escape sequence evaluation (cmake 3.1)
Franck Pérignon's avatar
Franck Pérignon committed
  cmake_policy(SET CMP0053 NEW)
Franck Pérignon's avatar
Franck Pérignon committed
endif()
Jean-Baptiste Keck's avatar
Jean-Baptiste Keck committed
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
Franck Pérignon's avatar
Franck Pérignon committed
include(MyTools)
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)
Franck Pérignon's avatar
Franck Pérignon committed
option(BUILD_SHARED_LIBS "Enable dynamic library build, default = ON." ON)
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)
Franck Pérignon's avatar
Franck Pérignon committed
option(WITH_FFTW "Link with fftw library (required for some HySoP solvers), default = ON" ON)
Franck Pérignon's avatar
Franck Pérignon committed
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(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)
Franck Pérignon's avatar
Franck Pérignon committed
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(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)
Franck Pérignon's avatar
Franck Pérignon committed
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)
Franck Pérignon's avatar
Franck Pérignon committed
# 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()
Franck Pérignon's avatar
Franck Pérignon committed

Franck Pérignon's avatar
Franck Pérignon committed
if(NOT USE_MPI)
  message(FATAL_ERROR "Non-mpi version of hysop has been depcecated, please enable mpi.")
Franck Pérignon's avatar
Franck Pérignon committed
endif()

# Fortran interface is not used by default.
set(USE_FORTRAN "OFF")
Franck Pérignon's avatar
Franck Pérignon committed
if(WITH_FFTW OR WITH_SCALES OR WITH_EXTRAS)
  set(USE_FORTRAN "ON")
# 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()

Franck Pérignon's avatar
Franck Pérignon committed
set(PROJECT_NAME hysop)
Franck Pérignon's avatar
Franck Pérignon committed
# This name will be used as the Python Package name
Franck Pérignon's avatar
Franck Pérignon committed
set(PACKAGE_NAME "hysop")
# --- The name (without extension) of the lib to be created ---
set(PROJECT_LIBRARY_NAME ${PROJECT_NAME})
# 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.
Franck Pérignon's avatar
Franck Pérignon committed
if(USE_FORTRAN)
Franck Pérignon's avatar
Franck Pérignon committed
include(HysopVersion)
project(${PROJECT_NAME} ${LANGLIST})
Franck Pérignon's avatar
Franck Pérignon committed
set(HYSOP_LIBRARY_NAME hysop)
Franck Pérignon's avatar
Franck Pérignon committed
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 =============
Franck Pérignon's avatar
Franck Pérignon committed
# - Global setup (interp and lib) -
find_package (Python3 REQUIRED COMPONENTS Interpreter Development)
if(Python3_VERSION VERSION_LESS "3.8")
    message(FATAL_ERROR "HySoP requires Python3.8 or later.")
endif()
set(PYTHON_EXECUTABLE "${Python3_EXECUTABLE}")
Franck Pérignon's avatar
Franck Pérignon committed
# - python packages -
Jean-Baptiste Keck's avatar
Jean-Baptiste Keck committed
find_python_module(numpy        REQUIRED)
find_python_module(scipy        REQUIRED)
find_python_module(sympy        REQUIRED)
find_python_module(h5py         REQUIRED)
Jean-Baptiste Keck's avatar
Jean-Baptiste Keck committed
find_python_module(psutil       REQUIRED)
find_python_module(cpuinfo      REQUIRED)
find_python_module(gmpy2        REQUIRED)
find_python_module(editdistance REQUIRED)
Jean-Baptiste Keck's avatar
Jean-Baptiste Keck committed
find_python_module(portalocker  REQUIRED)
find_python_module(tee          REQUIRED)
find_python_module(colors       REQUIRED) # corresponds ansicolor package
find_python_module(primefac     REQUIRED)
find_python_module(networkx     REQUIRED)
find_python_module(pyfftw       REQUIRED)
find_python_module(zarr         REQUIRED)
find_python_module(numcodecs    REQUIRED)
find_python_module(jsonpickle   REQUIRED)
find_python_module(argparse_color_formatter REQUIRED)
find_python_module(numba OPTIONAL)      # c++ jit compiler, required for CPU spectral filters
find_python_module(hptt OPTIONAL)       # high performance cpu tensor transpose (fallback to numpy)
find_python_module(flint OPTIONAL)      # high performance linear system solver (fallback to sympy)
find_python_module(tbb OPTIONAL)        # additional numba threading backend (fallback to pthreads)
find_python_module(mkl_fft OPTIONAL)    # additional fft backend, faster then FFTW, faster then clFFT on CPU OpenCL platforms.
find_python_module(cairo OPTIONAL)      # additional plotting backend
find_python_module(matplotlib OPTIONAL) # required for general plots
find_python_module(pyvis OPTIONAL)      # required for graph plots
find_python_module(memory_tempfile OPTIONAL) # enable in memory HDF5 I/O to call paraview during simulation
# Some opencl related python package fails to import on non OpenCL machines (cluster's frontend for instance)
if(${OpenCL_LIBRARY})
  find_python_module(pyopencl REQUIRED)
  find_python_module(mako     REQUIRED)
  find_python_module(gpyfft   REQUIRED)
  find_python_module(pyopencl OPTIONAL)
  find_python_module(mako     OPTIONAL)
  find_python_module(gpyfft   OPTIONAL)
Franck Pérignon's avatar
Franck Pérignon committed
# --- MPI ---
if(USE_MPI)
Franck Pérignon's avatar
Franck Pérignon committed
  find_package(MPI REQUIRED)
Franck Pérignon's avatar
Franck Pérignon committed
  find_python_module(mpi4py REQUIRED)
endif()
Franck Pérignon's avatar
Franck Pérignon committed
# --- Wheel, required for a proper build/install process ---
find_python_module(wheel REQUIRED)
# Find python build dir name --> needed for tests and doc
if(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 =============

Franck Pérignon's avatar
Franck Pérignon committed
# --- 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)
Franck Pérignon's avatar
Franck Pérignon committed
    set(dirlist)

    foreach(_file ${FFTW_LIBRARIES})
      get_filename_component(_name ${_file} DIRECTORY)
      list(FIND dirlist "${_name}" isin)
Franck Pérignon's avatar
Franck Pérignon committed
      if(isin EQUAL -1)
	    list(APPEND dirlist ${_name})
Franck Pérignon's avatar
Franck Pérignon committed
      endif()
    endforeach()
    set(FFTWLIB ${dirlist} CACHE PATH "fftw libraries dir")
    add_definitions(${FFTW_DEFINES})
Franck Pérignon's avatar
Franck Pérignon committed
if(WITH_EXTRAS)
  # Arnoldi solver needs zgeev, which means lapack
  compile_with(LAPACK)
Franck Pérignon's avatar
Franck Pérignon committed
  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")
Franck Pérignon's avatar
Franck Pérignon committed
endif()
# ========= Check parallel hdf5 availability =========
if(WITH_PARALLEL_COMPRESSED_HDF5)
      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")
else()
    set(H5PY_PARALLEL_COMPRESSION_ENABLED "OFF")
Franck Pérignon's avatar
Franck Pérignon committed
# ========= Check which opencl devices are available on the system =========
Franck Pérignon's avatar
Franck Pérignon committed
  execute_process(
    COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/cmake/opencl_explore.py "EXPLORE")
Franck Pérignon's avatar
Franck Pérignon committed
  execute_process(
    COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/cmake/opencl_explore.py
Franck Pérignon's avatar
Franck Pérignon committed
  execute_process(
    COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/cmake/opencl_explore.py "EXPLORE" CPU)
Franck Pérignon's avatar
Franck Pérignon committed
  execute_process(
    COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/cmake/opencl_explore.py CPU
Franck Pérignon's avatar
Franck Pérignon committed

string(REPLACE " " ";" MY_LIST "${OPENCL_DEFAULT_OPENCL_ID}")
list(LENGTH MY_LIST MY_LIST_LENGTH)
if (${MY_LIST_LENGTH} LESS 2)
    message(FATAL_ERROR "Could not determine default OpenCL device, try to execute '${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/cmake/opencl_explore.py' locally to determine the problem.")
endif()
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)
Franck Pérignon's avatar
Franck Pérignon committed
# =========== 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)
Franck Pérignon's avatar
Franck Pérignon committed
# ====== 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)
Franck Pérignon's avatar
Franck Pérignon committed
  # if fortran is enabled, explicit setup of the compiler is required.
  if (CMAKE_Fortran_COMPILER_ID MATCHES "Intel")
    add_custom_target(wheel ALL
      COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/setup.py bdist_wheel build -c intel --fcompiler intel config_fc  --f90exec=${CMAKE_Fortran_COMPILER}
      COMMENT "create wheel file for ${PACKAGE_NAME} package"
      DEPENDS ${HYSOP_LIBRARY_NAME}
      )
  else()
    add_custom_target(wheel ALL
Franck Pérignon's avatar
Franck Pérignon committed
      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}
Franck Pérignon's avatar
Franck Pérignon committed
      )
Franck Pérignon's avatar
Franck Pérignon committed
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"
Franck Pérignon's avatar
Franck Pérignon committed
    )
Franck Pérignon's avatar
Franck Pérignon committed
endif()

Franck Pérignon's avatar
Franck Pérignon committed
#  ====== Create (and setup) install/uninstall targets ======
# --> set installation dir
# --> set options for python install
# --> create install/uninstall targets
Franck Pérignon's avatar
Franck Pérignon committed
include(HySoPInstallSetup)
Franck Pérignon's avatar
Franck Pérignon committed
# 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.f90 file/module and constant.py
  # -- Variables required in fortran files --
Franck Pérignon's avatar
Franck Pérignon committed
  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 --
Franck Pérignon's avatar
Franck Pérignon committed
  set(f2pymap_for_real double)
Franck Pérignon's avatar
Franck Pérignon committed
  set(WORKING_PRECISION sp)
  set(MPI_PRECISION MPI_FLOAT)
  set(PYTHON_PREC np.float32)
  set(MPI_PYTHON_PREC MPI.FLOAT)
Franck Pérignon's avatar
Franck Pérignon committed
  set(f2pymap_for_real float)
# 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()


Franck Pérignon's avatar
Franck Pérignon committed
if(USE_FORTRAN)
Franck Pérignon's avatar
Franck Pérignon committed
  # 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}/cmake/sort_f90.py ${CMAKE_BINARY_DIR}/sort_f90.py)
Franck Pérignon's avatar
Franck Pérignon committed

  # --- Generate f2py_f2cmap file ---
  if(EXISTS ${CMAKE_SOURCE_DIR}/cmake/f2py_f2cmap.in)
Franck Pérignon's avatar
Franck Pérignon committed
	message(STATUS "Generate f2py map file ...")
	configure_file(${CMAKE_SOURCE_DIR}/cmake/f2py_f2cmap.in
Franck Pérignon's avatar
Franck Pérignon committed
      ${CMAKE_BINARY_DIR}/.f2py_f2cmap)
  endif()
Franck Pérignon's avatar
Franck Pérignon committed

  # --- 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'
Jean-Baptiste Keck's avatar
Jean-Baptiste Keck committed
  set(F_2_HYSOP "f2hysop")
Franck Pérignon's avatar
Franck Pérignon committed
  include(fortran_utils)
Jean-Baptiste Keck's avatar
Jean-Baptiste Keck committed
  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.
Franck Pérignon's avatar
Franck Pérignon committed
  # --- 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("-fPIC -cpp")
  if (CMAKE_Fortran_COMPILER_ID MATCHES "Intel")
    append_Fortran_FLAGS("-fast")
  endif()
  if (CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
    append_Fortran_FLAGS("-Wall -ffree-line-length-none")
    append_Fortran_FLAGS("-Wno-unused-dummy-argument -Wno-integer-division -Wno-unused-value -Wno-maybe-uninitialized -Wno-unused-function")
    if (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
Franck Pérignon's avatar
Franck Pérignon committed
    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.
Franck Pérignon's avatar
Franck Pérignon committed
    list(APPEND HYSOP_LINK_LIBRARIES ${MPI_Fortran_LIBRARIES} )
  set(Fortran_FLAGS ${CMAKE_Fortran_FLAGS})
  append_flags(Fortran_FLAGS ${CMAKE_Fortran_FLAGS_${CMAKE_BUILD_TYPE}})
  # --- Generate precision.f90 and precision.pyf files ---
  if(EXISTS ${CMAKE_SOURCE_DIR}/cmake/precision.conf.in)
    message(STATUS "Generate precision.f90 file ...")
    configure_file(${CMAKE_SOURCE_DIR}/cmake/precision.conf.in
    configure_file(${CMAKE_SOURCE_DIR}/cmake/precision.conf.in
      ${GENERATED_FORTRAN_FILES_DIR}/precision.pyf)
Jean-Baptiste Keck's avatar
Jean-Baptiste Keck committed
if(USE_FORTRAN)
Jean-Baptiste Keck's avatar
Jean-Baptiste Keck committed
  set(FORTRAN_INCLUDE_DIRS ${FFTW_INCLUDE_DIRS})
Franck Pérignon's avatar
Franck Pérignon committed

# Append pythonlib to hysop link floags
list(APPEND HYSOP_LINK_LIBRARIES ${PYTHON_LIBRARIES} )

# ====== Generates python files required for build/install process ======
Franck Pérignon's avatar
Franck Pérignon committed
# 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.
Franck Pérignon's avatar
Franck Pérignon committed
if(EXISTS ${CMAKE_SOURCE_DIR}/hysop/__init__.py.in)
  message(STATUS "Generate __init__.py file ...")
Franck Pérignon's avatar
Franck Pérignon committed
  file(REMOVE ${CMAKE_SOURCE_DIR}/hysop/__init__.py)
  configure_file(hysop/__init__.py.in ${CMAKE_SOURCE_DIR}/hysop/__init__.py)
Franck Pérignon's avatar
Franck Pérignon committed
# =========== 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)
Franck Pérignon's avatar
Franck Pérignon committed
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()
Franck Pérignon's avatar
Franck Pérignon committed
# ====== 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
Franck Pérignon's avatar
Franck Pérignon committed
  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)")
    set(TEST_TIMEOUT 3600 CACHE STRING "Default value for test runtime limit (in seconds)")
  endif()
  include(CTest)
Franck Pérignon's avatar
Franck Pérignon committed
  # 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()
Franck Pérignon's avatar
Franck Pérignon committed
  if(NOT USE_MPI)
    set(WITH_MPI_TESTS "OFF")
  endif()
Franck Pérignon's avatar
Franck Pérignon committed
  include(hysop_tests)
Franck Pérignon's avatar
Franck Pérignon committed
# ============= Documentation setup =============
if(WITH_DOCUMENTATION)
  add_subdirectory(docs)
endif()
# ============= Summary =============
if(VERBOSE_MODE)
Franck Pérignon's avatar
Franck Pérignon committed
  message("\n====================== End of configuration process ======================")
  message("\n Summary: ")
  message(STATUS " Python libraries : ${Python_LIBRARY_DIRS}")
  message(STATUS " Python include : ${Python_INCLUDE_DIRS}")
  message(STATUS " Python version : ${Python_VERSION}")
  message(STATUS " Python executable : ${PYTHON_EXECUTABLE}")
Franck Pérignon's avatar
Franck Pérignon committed
  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}")
Franck Pérignon's avatar
Franck Pérignon committed
  if(USE_FORTRAN)
    message(STATUS " Fortran compiler : ${CMAKE_Fortran_COMPILER}")
Franck Pérignon's avatar
Franck Pérignon committed
  else()
Franck Pérignon's avatar
Franck Pérignon committed
    message(WARNING "You deactivate fortran to python interface generation. This will disable the fortran interface, including fftw and scales fonctionnalities.")
  message(STATUS " Sources are in : ${CMAKE_SOURCE_DIR}")
  message(STATUS " Build is done in : ${CMAKE_BINARY_DIR}")
  message(STATUS " Project uses MPI : ${USE_MPI}")
Franck Pérignon's avatar
Franck Pérignon committed
  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}")
Jean-Baptiste Keck's avatar
Jean-Baptiste Keck committed
  message(STATUS " ${PROJECT_NAME} profile mode : ${PROFILE}")
  message(STATUS " ${PROJECT_NAME} debug   mode : ${DEBUG}")
  message(STATUS " Enable -OO run? : ${OPTIM}")
Jean-Baptiste Keck's avatar
Jean-Baptiste Keck committed
      message(STATUS " Default real numbers precision : double.")
      message(STATUS " Default real numbers precision : single.")
  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. ")
Franck Pérignon's avatar
Franck Pérignon committed
  message(STATUS " 'make doc' to generate doxygen documentation for hysop.")
Franck Pérignon's avatar
Franck Pérignon committed
  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.")
Franck Pérignon's avatar
Franck Pérignon committed
  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")