Skip to content
Snippets Groups Projects
Select Git revision
  • 605e73a47a07434479711a69de0ea4bba5bcacf5
  • develop default protected
  • feature/kinetic-schemes
  • feature/reconstruction
  • feature/local-dt-fsi
  • feature/composite-scheme-sources
  • feature/composite-scheme-other-fluxes
  • feature/serraille
  • feature/variational-hydro
  • feature/composite-scheme
  • hyperplastic
  • feature/polynomials
  • feature/gks
  • feature/implicit-solver-o2
  • feature/coupling_module
  • feature/implicit-solver
  • feature/merge-local-dt-fsi
  • master protected
  • feature/escobar-smoother
  • feature/hypoelasticity-clean
  • feature/hypoelasticity
  • v0.5.0 protected
  • v0.4.1 protected
  • v0.4.0 protected
  • v0.3.0 protected
  • v0.2.0 protected
  • v0.1.0 protected
  • Kidder
  • v0.0.4 protected
  • v0.0.3 protected
  • v0.0.2 protected
  • v0 protected
  • v0.0.1 protected
33 results

CMakeLists.txt

Blame
  • CMakeLists.txt 15.26 KiB
    cmake_minimum_required (VERSION 3.10)
    
    # CMake utils
    list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
    
    # Forbids in-source builds
    include(CheckNotInSources)
    
    #------------------------------------------------------
    #----------------- Main configuration -----------------
    #------------------------------------------------------
    
    # custom variable allowing to define version suffixes such as -rc*, -beta*, ...
    set(PUGS_VERSION "0.4.1")
    
    # deduce PUGS_SHORT_VERSION using regex
    string(REGEX MATCH "^[0-9]+\.[0-9]+\.[0-9]+" PUGS_SHORT_VERSION ${PUGS_VERSION})
    if("${PUGS_SHORT_VERSION}" STREQUAL "")
      message(FATAL_ERROR "Unable to compute short version from PUGS_VERSION=${PUGS_VERSION}")
    endif()
    
    # set project version as PUGS_SHORT_VERSION
    project (Pugs VERSION ${PUGS_SHORT_VERSION})
    
    #------------------------------------------------------
    
    set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
    
    #------------------------------------------------------
    
    set(PUGS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
    set(PUGS_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
    
    # Change RelWithDebInfo to compile assertions
    SET("CMAKE_CXX_FLAGS_RELWITHDEBINFO"
       "-g -O2"
      CACHE STRING "Flags used by the compiler during release builds with debug info and assertions"
      FORCE )
    SET("CMAKE_C_FLAGS_RELWITHDEBINFO"
       "-g -O2"
      CACHE STRING "Flags used by the compiler during release builds with debug info and assertions"
      FORCE )
    
    # Add new build types
    set(CMAKE_CXX_FLAGS_COVERAGE
      "-g -O0 --coverage"
      CACHE STRING "Flags used by the C++ compiler during coverage builds."
      FORCE )
    set(CMAKE_C_FLAGS_COVERAGE
      "-g -O0 --coverage"
      CACHE STRING "Flags used by the C compiler during coverage builds."
      FORCE )
    set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
      "--coverage"
      CACHE STRING "Flags used for linking binaries during coverage builds."
      FORCE )
    set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
      "--coverage"
      CACHE STRING "Flags used by the shared libraries linker during coverage builds."
      FORCE )
    mark_as_advanced(
      CMAKE_CXX_FLAGS_COVERAGE
      CMAKE_C_FLAGS_COVERAGE
      CMAKE_EXE_LINKER_FLAGS_COVERAGE
      CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
    
    if(CMAKE_BUILD_TYPE)
      string(REGEX MATCH "(Debug|Release|RelWithDebInfo|MinSizeRel|Coverage)" VALID_BUILD_TYPE "${CMAKE_BUILD_TYPE}")
      if(NOT VALID_BUILD_TYPE)
        message(FATAL_ERROR "Invalid CMAKE_BUILD_TYPE: '${CMAKE_BUILD_TYPE}'")
      endif()
    endif()
    
    # Default build type is RelWIthDebInfo
    if(NOT CMAKE_BUILD_TYPE)
      set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
          "Choose the type of build: Debug Release RelWithDebInfo MinSizeRel Coverage."
          FORCE)
    endif()
    
    #------------------------------------------------------
    
    # Checks if compiler version is compatible with Pugs sources
    set(GNU_CXX_MIN_VERSION "8.0.0")
    set(CLANG_CXX_MIN_VERSION "8.0.0")
    
    # Pugs default compiler flags
    set(PUGS_CXX_FLAGS "${PUGS_CXX_FLAGS} -Wall -Wextra -pedantic")
    
    if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
      if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "${GNU_CXX_MIN_VERSION}")
        message(FATAL_ERROR "Pugs build requires at least g++-${GNU_CXX_MIN_VERSION}")
      endif()
    elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
      if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "${CLANG_CXX_MIN_VERSION}")
        message(FATAL_ERROR "Pugs build requires at least llvm/clang ++-${CLANG_CXX_MIN_VERSION}")
      endif()
      set(PUGS_CXX_FLAGS "${PUGS_CXX_FLAGS} -Wsign-compare -Wunused -Wunused-member-function -Wunused-private-field")
    endif()
    
    if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
      if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0.0")
        set(PUGS_STD_LINK_FLAGS "-lstdc++fs")
      endif()
    endif()
    
    #------------------------------------------------------
    # defaults use of MPI
    set(PUGS_ENABLE_MPI AUTO CACHE STRING
      "Choose one of: AUTO ON OFF")
    
    if (NOT PUGS_ENABLE_MPI MATCHES "^(AUTO|ON|OFF)$")
      message(FATAL_ERROR "PUGS_ENABLE_MPI='${PUGS_ENABLE_MPI}'. Must be set to one of AUTO, ON or OFF")
    endif()
    
    # checks for MPI
    if (PUGS_ENABLE_MPI MATCHES "^(AUTO|ON)$")
      set(MPI_DETERMINE_LIBRARY_VERSION TRUE)
      find_package(MPI)
    endif()
    
    
    #------------------------------------------------------
    # Search for ParMETIS
    
    if(${MPI_FOUND})
      find_package(ParMETIS)
      if (NOT PARMETIS_LIBRARIES)
        if(PUGS_ENABLE_MPI MATCHES "^AUTO$")
          message(STATUS "MPI support deactivated: ParMETIS cannot be found!")
          unset(MPI_FOUND)
          unset(MPI_CXX_LINK_FLAGS)
          unset(MPI_CXX_LIBRARIES)
        else()
          message(FATAL_ERROR "MPI support requires ParMETIS which cannot be found!")
        endif()
      endif()
    endif()
    
    # -----------------------------------------------------
    
    if (${MPI_FOUND})
      set(PUGS_CXX_FLAGS "${PUGS_CXX_FLAGS} ${MPI_CXX_COMPILER_FLAGS}")
      include_directories(SYSTEM ${MPI_CXX_INCLUDE_DIRS})
    elseif(PUGS_ENABLE_MPI STREQUAL "ON")
      message(FATAL_ERROR "Could not find MPI library while requested")
    endif()
    
    set(PUGS_HAS_MPI ${MPI_FOUND})
    
    #------------------------------------------------------
    # search for clang-format
    
    find_program(CLANG_FORMAT clang-format)
    if (CLANG_FORMAT)
      add_custom_target(clang-format
        COMMAND ${CMAKE_COMMAND}
        -DPUGS_SOURCE_DIR="${PUGS_SOURCE_DIR}"
        -DCLANG_FORMAT="${CLANG_FORMAT}"
        -P ${PUGS_SOURCE_DIR}/cmake/ClangFormatProcess.cmake
        COMMENT "running ${CLANG_FORMAT} ...")
    else ()
      message(STATUS "clang-format no found!")
    endif()
    
    #------------------------------------------------------
    # search for clazy-standalone
    
    find_program(CLAZY_STANDALONE clazy-standalone)
    if (CLAZY_STANDALONE)
      add_custom_target(clazy-standalone
        COMMAND ${CMAKE_COMMAND}
        -DPUGS_SOURCE_DIR="${PUGS_SOURCE_DIR}"
        -DPUGS_BINARY_DIR="${PUGS_BINARY_DIR}"
        -DCLAZY_STANDALONE="${CLAZY_STANDALONE}"
        -P ${PUGS_SOURCE_DIR}/cmake/ClazyStandaloneProcess.cmake
        COMMENT "running ${CLAZY_STANDALONE} ..."
        )
    else ()
      message(STATUS "clazy-standalone no found!")
    endif()
    
    #------------------------------------------------------
    # C++ 17 flags
    set(CMAKE_CXX_STANDARD "17")
    
    #------------------------------------------------------
    # Kokkos configuration
    
    set(KOKKOS_SOURCE_DIR "${PUGS_SOURCE_DIR}/packages/kokkos")
    set(KOKKOS_BINARY_DIR "${PUGS_BINARY_DIR}/packages/kokkos")
    
    # setting Kokkos defaults to OpenMP when available
    find_package(OpenMP)
    if(OpenMP_CXX_FOUND)
      set(Kokkos_ENABLE_OPENMP ON CACHE BOOL "")
    endif()
    
    if("${Kokkos_ENABLE_OPENMP}" STREQUAL "ON")
      set(PUGS_CXX_FLAGS "${PUGS_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
      set(OPENMP_LINK_FLAGS OpenMP::OpenMP_CXX)
    endif()
    
    add_subdirectory("${PUGS_SOURCE_DIR}/packages/kokkos")
    
    # set as SYSTEM for static analysis
    include_directories(SYSTEM ${KOKKOS_SOURCE_DIR}/core/src)
    include_directories(SYSTEM ${KOKKOS_SOURCE_DIR}/containers/src)
    include_directories(SYSTEM ${KOKKOS_BINARY_DIR})
    
    set(PUGS_BUILD_KOKKOS_DEVICES "")
    if(${Kokkos_ENABLE_PTHREAD})
      list(APPEND PUGS_BUILD_KOKKOS_DEVICES "Threads")
    endif()
    
    if(${Kokkos_ENABLE_CUDA})
      list(APPEND PUGS_BUILD_KOKKOS_DEVICES "CUDA")
    endif()
    
    if(${Kokkos_ENABLE_QTHREADS})
      list(APPEND PUGS_BUILD_KOKKOS_DEVICES "QThreads")
    endif()
    
    if(${Kokkos_ENABLE_HPX})
      list(APPEND PUGS_BUILD_KOKKOS_DEVICES "HPX")
    endif()
    
    if(${Kokkos_ENABLE_OPENMP})
      list(APPEND PUGS_BUILD_KOKKOS_DEVICES "OpenMP")
    endif()
    
    if(${Kokkos_ENABLE_OPENMPTARGET})
      list(APPEND PUGS_BUILD_KOKKOS_DEVICES "OpenMPTarget")
    endif()
    
    if(${Kokkos_ENABLE_HWLOC})
      list(APPEND PUGS_BUILD_KOKKOS_DEVICES "HWLoc")
    endif()
    
    if(${Kokkos_ENABLE_MPI})
      list(APPEND PUGS_BUILD_KOKKOS_DEVICES "Kokkos/MPI")
    endif()
    
    if(${Kokkos_ENABLE_CUDA_UVM})
      list(APPEND PUGS_BUILD_KOKKOS_DEVICES "CUDA UVM")
    endif()
    
    #------------------------------------------------------
    # Compiler flags
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PUGS_CXX_FLAGS}")
    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${PUGS_CXX_FLAGS}")
    set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${PUGS_CXX_FLAGS}")
    
    # Add debug mode for Standard C++ library (not for AppleClang since it is broken)
    if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
      set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_GLIBCXX_DEBUG -D_LIBCPP_DEBUG=1")
      set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -D_GLIBCXX_DEBUG -D_LIBCPP_DEBUG=1")
    endif()
    
    #------------------------------------------------------
    
    # Rang (colors? Useless thus necessary!)
    include_directories(${PUGS_SOURCE_DIR}/packages/rang/include)
    
    # CLI11
    include_directories(${PUGS_SOURCE_DIR}/packages/CLI11/include)
    
    # PEGTL
    include_directories(SYSTEM ${PUGS_SOURCE_DIR}/packages/PEGTL/include/tao)
    
    # Pugs src
    add_subdirectory(${PUGS_SOURCE_DIR}/src)
    include_directories(${PUGS_SOURCE_DIR}/src)
    include_directories(${PUGS_BINARY_DIR}/src)
    
    # Pugs tests
    set(CATCH_MODULE_PATH "${PUGS_SOURCE_DIR}/packages/Catch2")
    include("${CATCH_MODULE_PATH}/contrib/ParseAndAddCatchTests.cmake")
    add_subdirectory("${CATCH_MODULE_PATH}")
    
    add_subdirectory(tests)
    enable_testing()
    
    add_custom_target(run_unit_tests
      COMMAND ${CMAKE_CTEST_COMMAND}
      DEPENDS unit_tests mpi_unit_tests
      COMMENT "Executing unit tests."
      )
    
    # unit tests coverage
    
    if("${CMAKE_BUILD_TYPE}" STREQUAL "Coverage")
      find_program(LCOV lcov)
      if(NOT LCOV)
        message(FATAL_ERROR "lcov not found, cannot perform coverage.")
      endif()
    
      if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
        string(REGEX MATCH "^[0-9]+" GCC_VERSION
          "${CMAKE_CXX_COMPILER_VERSION}")
        find_program(GCOV_BIN NAMES gcov-${GCC_VERSION} gcov
          HINTS ${COMPILER_PATH})
      elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
        string(REGEX MATCH "^[0-9]+" LLVM_VERSION
          "${CMAKE_CXX_COMPILER_VERSION}")
    
        if(LLVM_VERSION VERSION_GREATER 7)
          find_program(LLVM_COV_BIN NAMES "llvm-cov-${LLVM_VERSION}"
            "llvm-cov" HINTS ${COMPILER_PATH})
          mark_as_advanced(LLVM_COV_BIN)
    
          if (LLVM_COV_BIN)
            file(MAKE_DIRECTORY "${PUGS_BINARY_DIR}/tools/tmp")
    
            file(WRITE "${PUGS_BINARY_DIR}/tools/tmp/llvm-cov.sh" "#! /bin/sh\n")
            file(APPEND "${PUGS_BINARY_DIR}/tools/tmp/llvm-cov.sh" "'${LLVM_COV_BIN}' gcov \"\$@\"\n")
    
            file(COPY "${PUGS_BINARY_DIR}/tools/tmp/llvm-cov.sh"
                 DESTINATION "${PUGS_BINARY_DIR}/tools"
                 FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE)
    
            set(GCOV_BIN "${PUGS_BINARY_DIR}/tools/llvm-cov.sh")
          endif()
        endif()
      endif()
    
      if(NOT GCOV_BIN)
         message(FATAL_ERROR "Cannot find a proper gcov tool, cannot perform coverage.")
      endif()
    
      find_program(FASTCOV fastcov fastcov.py)
    
      if (FASTCOV AND (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "9"))
    
        add_custom_target(coverage
          ALL # in coverage mode we do coverage!
    
          # zero all counters
          COMMAND ${FASTCOV} -q -z
    
          # Run tests
          COMMAND ${CMAKE_CTEST_COMMAND}
    
          COMMAND ${FASTCOV} -q --gcov "${GCOV_BIN}"
          --include "${PUGS_SOURCE_DIR}/src"
          --exclude "${PUGS_SOURCE_DIR}/src/main.cpp" "${PUGS_SOURCE_DIR}/src/utils/BacktraceManager.*"
          --lcov -o coverage.info -n
    
          COMMAND ${LCOV} --gcov "${GCOV_BIN}" --list coverage.info
    
          DEPENDS unit_tests mpi_unit_tests
          COMMENT "Running test coverage."
          WORKING_DIRECTORY "${PUGS_BINARY_DIR}"
          )
    
      else()
    
        add_custom_target(coverage
          ALL # in coverage mode we do coverage!
          # Cleanup previously generated profiling data
          COMMAND ${LCOV} -q --gcov "${GCOV_BIN}" --base-directory "${PUGS_BINARY_DIR}/src" --directory "${PUGS_BINARY_DIR}" --zerocounters
          # Initialize profiling data with zero coverage for every instrumented line of the project
          # This way the percentage of total lines covered will always be correct, even when not all source code files were loaded during the test(s)
          COMMAND ${LCOV} -q --gcov "${GCOV_BIN}" --base-directory "${PUGS_BINARY_DIR}/src" --directory "${PUGS_BINARY_DIR}" --capture --initial --output-file coverage_base.info
          # Run tests
          COMMAND ${CMAKE_CTEST_COMMAND}
          # Collect data from executions
          COMMAND ${LCOV} --gcov "${GCOV_BIN}" --base-directory "${PUGS_BINARY_DIR}/src" --directory "${PUGS_BINARY_DIR}" --capture --output-file coverage_ctest.info
          # Combine base and ctest results
          COMMAND ${LCOV} --gcov "${GCOV_BIN}" -q --add-tracefile coverage_base.info --add-tracefile coverage_ctest.info --output-file coverage_full.info
          # Extract only project data (--no-capture or --remove options may be used to select collected data)
          COMMAND ${LCOV} --gcov "${GCOV_BIN}" -q --extract coverage_full.info "'${PUGS_SOURCE_DIR}/src/*'" --output-file coverage_extract.info
    
          # Remove unwanted stuff
          COMMAND ${LCOV} --gcov "${GCOV_BIN}" --remove coverage_extract.info  --output-file coverage.info
          '${PUGS_SOURCE_DIR}/src/main.cpp'
          '${PUGS_SOURCE_DIR}/src/utils/BacktraceManager.*'
    
          COMMAND ${LCOV} --gcov "${GCOV_BIN}" --list coverage.info
    
          DEPENDS unit_tests mpi_unit_tests
          COMMENT "Running test coverage."
          WORKING_DIRECTORY "${PUGS_BINARY_DIR}"
          )
      endif()
    
      find_program(GENHTML genhtml)
      if(NOT GENHTML)
        message(WARNING "genhtml not found, cannot perform report-coverage.")
      else()
        add_custom_target(coverage-report
          ALL
          COMMAND ${CMAKE_COMMAND} -E remove_directory "${PUGS_BINARY_DIR}/coverage"
          COMMAND ${CMAKE_COMMAND} -E make_directory "${PUGS_BINARY_DIR}/coverage"
          COMMAND ${GENHTML} --demangle-cpp -q -o coverage -t "${CMAKE_PROJECT_NAME} test coverage" --ignore-errors source --legend --num-spaces 2 coverage.info
          DEPENDS coverage
          COMMENT "Building coverage html report."
          WORKING_DIRECTORY "${PUGS_BINARY_DIR}"
          )
      endif()
    endif()
    
    # -----------------------------------------------------
    
    link_libraries("-rdynamic")
    
    # ------------------- Source files --------------------
    # Pugs binary
    add_executable(
      pugs
      src/main.cpp)
    
    # Libraries
    target_link_libraries(
      pugs
      PugsMesh
      PugsUtils
      PugsLanguage
      PugsLanguageAST
      PugsLanguageModules
      PugsLanguageAlgorithms
      PugsMesh
      PugsUtils
      PugsLanguageUtils
      kokkos
      ${PARMETIS_LIBRARIES}
      ${MPI_CXX_LINK_FLAGS} ${MPI_CXX_LIBRARIES}
      ${KOKKOS_CXX_FLAGS}
      ${OPENMP_LINK_FLAGS}
      ${PUGS_STD_LINK_FLAGS}
      stdc++fs
      )
    
    # ---------------------- Doxygen ----------------------
    include(PugsDoxygen)
    
    # ------------------- Installation --------------------
    # temporary version workaround
    if(${CMAKE_VERSION} VERSION_LESS "3.13.0")
      install(TARGETS pugs
        RUNTIME DESTINATION bin
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib)
    else()
      install(TARGETS pugs PugsMesh PugsUtils PugsLanguage
        RUNTIME DESTINATION bin
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib)
    endif()
    
    message("")
    message("====== pugs build options ======")
    message(STATUS "version: ${PUGS_VERSION}")
    message(STATUS "build type: ${CMAKE_BUILD_TYPE}")
    message(STATUS "compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
    message(STATUS "kokkos devices: ${PUGS_BUILD_KOKKOS_DEVICES}")
    
    if (MPI_FOUND)
      message(STATUS "MPI: ${MPI_CXX_LIBRARY_VERSION_STRING}")
    else()
      if(NOT PARMETIS_LIBRARIES)
        message(STATUS "MPI: deactivated: ParMETIS cannot be found!")
      else()
        message(STATUS "MPI: not found!")
      endif()
    endif()
    
    if(CLANG_FORMAT)
      message(STATUS "clang-format: ${CLANG_FORMAT}")
    else()
      message(STATUS "clang-format: not found!")
    endif()
    
    if(CLAZY_STANDALONE)
      message(STATUS "clazy-standalone: ${CLAZY_STANDALONE}")
    else()
      message(STATUS "clazy-standalone: no found!")
    endif()
    
    if (DOXYGEN_FOUND)
      message(STATUS "doxygen: ${DOXYGEN_EXECUTABLE}")
    else()
      message(STATUS "doxygen: no found!")
    endif()
    
    message("================================")
    message("")