cmake_minimum_required (VERSION 3.19) # CMake utils list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") set(CMAKE_INSTALL_LIBDIR "lib") set(CMAKE_INSTALL_INCLUDEDIR "include") set(CMAKE_INSTALL_BINDIR "bin") # Forbids in-source builds include(CheckNotInSources) # Check for some headers include(CheckIncludeFileCXX) # use PkgConfig to find packages find_package(PkgConfig REQUIRED) #------------------------------------------------------ #----------------- Main configuration ----------------- #------------------------------------------------------ # custom variable allowing to define version suffixes such as -rc*, -beta*, ... set(PUGS_VERSION "0.5.0") # 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}) # ----------------------------------------------------- # dynamic libraries set(CMAKE_POSITION_INDEPENDENT_CODE ON) link_libraries("-rdynamic") set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") #------------------------------------------------------ set(CMAKE_CONFIGURATION_TYPES "Release;Debug;Coverage" CACHE STRING INTERNAL FORCE ) #------------------------------------------------------ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) #------------------------------------------------------ set(PUGS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") set(PUGS_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}") # 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 "^(Release|Debug|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 Release if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build: Release Debug Coverage." FORCE) endif() #------------------------------------------------------ # default build shared libraries if (NOT BUILD_SHARED_LIBS) set(BUILD_SHARED_LIBS ON CACHE STRING "" FORCE) endif() #------------------------------------------------------ # Checks if compiler version is compatible with Pugs sources set(GNU_CXX_MIN_VERSION "10.0.0") set(CLANG_CXX_MIN_VERSION "14.0.0") #------------------------------------------------------ # Change Kokkos namespace to avoid conflicts set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DKokkos=InlineKokkos") #------------------------------------------------------ # Pugs default compiler flags set(PUGS_CXX_FLAGS "${PUGS_CXX_FLAGS} -Wall -Wextra -pedantic -Wshadow -Wsign-compare -Wunused") 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} -Wunused-member-function -Wunused-private-field") endif() #------------------------------------------------------ include (TestBigEndian) TEST_BIG_ENDIAN(IS_BIG_ENDIAN) if(IS_BIG_ENDIAN) set(PUGS_LITTLE_ENDIAN FALSE) else() set(PUGS_LITTLE_ENDIAN TRUE) 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() # Check for MPI if (PUGS_ENABLE_MPI MATCHES "^(AUTO|ON)$") set(MPI_DETERMINE_LIBRARY_VERSION TRUE) find_package(MPI) endif() #------------------------------------------------------ # Search for ParMETIS find_package(ParMETIS) if(PARMETIS_LIBRARIES AND MPI_FOUND) add_library(PkgConfig::ParMETIS STATIC IMPORTED) set_property(TARGET PkgConfig::ParMETIS PROPERTY IMPORTED_LOCATION "${PARMETIS_LIBRARIES}") set(PUGS_HAS_PARMETIS TRUE) set(PARMETIS_TARGET PkgConfig::ParMETIS) else() unset(PUGS_HAS_PARMETIS) endif() #------------------------------------------------------ # Search for PTScotch find_package(PTScotch) if (PTScotch_FOUND AND MPI_FOUND) add_library(PkgConfig::PTScotch STATIC IMPORTED) set_property(TARGET PkgConfig::PTScotch PROPERTY IMPORTED_LOCATION "${PTSCOTCH_LIBRARY}") set_property(TARGET PkgConfig::PTScotch PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${PTSCOTCH_INCLUDE_DIR}") set(PTSCOTCH_TARGET PkgConfig::PTScotch) include_directories(SYSTEM "${PTSCOTCH_INCLUDE_DIR}") set(PUGS_HAS_PTSCOTCH TRUE) else() set(PTSCOTCH_LIBRARY "") unset(PUGS_HAS_PTSCOTCH) endif() #------------------------------------------------------ if(${MPI_FOUND}) if ((NOT PARMETIS_LIBRARIES) AND (NOT PTSCOTCH_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() else() if(PUGS_ENABLE_MPI MATCHES "^ON$") message(FATAL_ERROR "Cannot find MPI!") endif() endif() #------------------------------------------------------ # Check for PETSc # defaults use PETSc set(PUGS_ENABLE_PETSC AUTO CACHE STRING "Choose one of: AUTO ON OFF") if (PUGS_ENABLE_PETSC MATCHES "^(AUTO|ON)$") if (MPI_FOUND) # PETSc support is deactivated if MPI is not found pkg_check_modules(PETSC IMPORTED_TARGET GLOBAL PETSc) if (${PETSC_FOUND}) set_property(TARGET PkgConfig::PETSC PROPERTY IMPORTED_LOCATION "${PETSC_LIBRARIES}" ) set_property(TARGET PkgConfig::PETSC PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${PETSC_INCLUDE_DIRS}" ) set(PETSC_TARGET PkgConfig::PETSC) endif() else() message(STATUS "PETSc support is deactivated since pugs will not be build with MPI support") set(PETSC_FOUND FALSE) unset(PUGS_HAS_PETSC) endif() set(PUGS_HAS_PETSC ${PETSC_FOUND}) else() unset(PUGS_HAS_PETSC) endif() if (${PETSC_FOUND}) include_directories(SYSTEM "${PETSC_INCLUDE_DIRS}") else() if (PUGS_ENABLE_PETSC MATCHES "^ON$") message(FATAL_ERROR "Could not find PETSc!") endif() endif() #------------------------------------------------------ # Check for SLEPc # defaults use SLEPc set(PUGS_ENABLE_SLEPC AUTO CACHE STRING "Choose one of: AUTO ON OFF") if (PUGS_ENABLE_SLEPC MATCHES "^(AUTO|ON)$") if (PETSC_FOUND) # SLEPc support is deactivated if PETSc is not found pkg_check_modules(SLEPC IMPORTED_TARGET GLOBAL SLEPc) if (${SLEPC_FOUND}) set_property(TARGET PkgConfig::SLEPC PROPERTY IMPORTED_LOCATION "${SLEPC_LIBRARIES}" ) set_property(TARGET PkgConfig::SLEPC PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${SLEPC_INCLUDE_DIRS}" ) set(SLEPC_TARGET PkgConfig::SLEPC) endif() else() message(STATUS "SLEPc support is deactivated since pugs will not be build with PETSc support") set(SLEPC_FOUND FALSE) unset(PUGS_HAS_SLEPC) endif() set(PUGS_HAS_SLEPC ${SLEPC_FOUND}) else() unset(PUGS_HAS_SLEPC) endif() if (${SLEPC_FOUND}) include_directories(SYSTEM "${SLEPC_INCLUDE_DIRS}") else() if (PUGS_ENABLE_SLEPC MATCHES "^ON$") message(FATAL_ERROR "Could not find SLEPc!") endif() endif() # ----------------------------------------------------- # Check for Eigen3 # defaults use Eigen3 set(PUGS_ENABLE_EIGEN3 AUTO CACHE STRING "Choose one of: AUTO ON OFF") if (PUGS_ENABLE_EIGEN3 MATCHES "^(AUTO|ON)$") find_package (Eigen3 NO_MODULE) if (TARGET Eigen3::Eigen) set(EIGEN3_TARGET Eigen3::Eigen) set(EIGEN3_FOUND TRUE) else() set(EIGEN3_FOUND FALSE) endif (TARGET Eigen3::Eigen) set(PUGS_HAS_EIGEN3 ${EIGEN3_FOUND}) else() unset(PUGS_HAS_EIGEN3) 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 HDF5 set(PUGS_ENABLE_HDF5 AUTO CACHE STRING "Choose one of: AUTO ON OFF") if (PUGS_ENABLE_HDF5 MATCHES "^(AUTO|ON)$") if (MPI_FOUND) # May be risky. (make to show pugs build options) set(HDF5_PREFER_PARALLEL TRUE) find_package(HDF5) if (HDF5_FOUND) # HighFive set(HIGHFIVE_USE_BOOST OFF) # no Boost set(HIGHFIVE_BUILD_DOCS OFF) # no doc set(HIGHFIVE_UNIT_TESTS OFF) # no unit tests set(HIGHFIVE_UNIT_TESTS OFF) # no unit tests set(HIGHFIVE_EXAMPLES OFF) # no examples add_subdirectory(${PUGS_SOURCE_DIR}/packages/HighFive/) set(HIGHFIVE_TARGET HighFive::HighFive) add_library(PkgConfig::HDF5 STATIC IMPORTED) set_property(TARGET PkgConfig::HDF5 PROPERTY IMPORTED_LOCATION "${HDF5_LIBRARIES}") set_property(TARGET PkgConfig::HDF5 PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${HDF5_INCLUDE_DIRS}") set(HDF5_TARGET PkgConfig::HDF5) endif() else() message(STATUS "HDF5 support is deactivated since pugs will not be build with MPI support") set(HDF5_FOUND FALSE) endif() set(PUGS_HAS_HDF5 ${HDF5_FOUND}) else() unset(HIGHFIVE_TARGET) unset(HDF5_TARGET) unset(PUGS_HAS_HDF5) endif() #------------------------------------------------------ # search for libslurm find_package(Slurm) set(PUGS_HAS_SLURM ${SLURM_FOUND}) if (SLURM_FOUND) add_library(PkgConfig::Slurm STATIC IMPORTED) set_property(TARGET PkgConfig::Slurm PROPERTY IMPORTED_LOCATION "${SLURM_LIBRARY}") set_property(TARGET PkgConfig::Slurm PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${SLURM_INCLUDE_DIR}") set(SLURM_TARGET PkgConfig::Slurm) include_directories(SYSTEM "${SLURM_INCLUDE_DIR}") else() set(SLURM_LIBRARY "") endif() #------------------------------------------------------ # 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++ 20 flags set(CMAKE_CXX_STANDARD "20") #------------------------------------------------------ # Kokkos configuration set(KOKKOS_SOURCE_DIR "${PUGS_SOURCE_DIR}/packages/kokkos") set(KOKKOS_BINARY_DIR "${PUGS_BINARY_DIR}/packages/kokkos") # test since mdspan is not supported by g++-10 and clang-11 (used in CI) check_include_file_cxx("mdspan" CXX_MDSPAN_SUPPORT) if (NOT DEFINED ${CXX_MDSPAN_SUPPORT}) message(STATUS "Kokkos_ENABLE_IMPL_MDSPAN is deactivated since standard library does not support mdspan") set(Kokkos_ENABLE_IMPL_MDSPAN OFF CACHE BOOL "") endif() # disable Kokkos deprecation warnings by default set(Kokkos_ENABLE_DEPRECATION_WARNINGS OFF CACHE BOOL "") # 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_SOURCE_DIR}/tpls/desul/include") include_directories(SYSTEM "${KOKKOS_BINARY_DIR}/core/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}") message(STATUS "CMAKE_CXX_FLAGS = ${CMAKE_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") endif() #------------------------------------------------------ # Rang (colors? Useless thus necessary!) add_subdirectory(${PUGS_SOURCE_DIR}/packages/rang/) include_directories(SYSTEM "${PUGS_SOURCE_DIR}/packages/rang/include") # CLI11 include_directories(SYSTEM "${PUGS_SOURCE_DIR}/packages/CLI11/include") # PEGTL add_subdirectory(${PUGS_SOURCE_DIR}/packages/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") add_subdirectory("${CATCH_MODULE_PATH}") target_compile_options(Catch2 PRIVATE "-w") target_compile_options(Catch2WithMain PRIVATE "-w") add_subdirectory(tests) if(${PUGS_HAS_MPI}) set(MPIEXEC_OPTION_FLAGS --oversubscribe) if (NOT "$ENV{GITLAB_CI}" STREQUAL "") set(MPIEXEC_OPTION_FLAGS ${MPIEXEC_OPTION_FLAGS} --allow-run-as-root) endif() set(MPIEXEC_NUMPROC 3) set(MPIEXEC_PATH_FLAG --path) set(MPI_LAUNCHER ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MPIEXEC_NUMPROC} ${MPIEXEC_OPTION_FLAGS}) endif() add_custom_target(all_unit_tests DEPENDS unit_tests mpi_unit_tests ) add_custom_target(check DEPENDS test ) add_custom_target(test DEPENDS run_all_unit_tests ) add_custom_target(run_all_unit_tests DEPENDS run_mpi_unit_tests ) if(PUGS_HAS_MPI) set(RUN_MPI_UNIT_TESTS_COMMENT "Running mpi_unit_tests [using ${MPIEXEC_NUMPROC} procs]") else() set(RUN_MPI_UNIT_TESTS_COMMENT "Running mpi_unit_tests [sequentially]") endif() add_custom_target(run_mpi_unit_tests COMMAND ${MPI_LAUNCHER} "${PUGS_BINARY_DIR}/mpi_unit_tests" WORKING_DIRECTORY ${PUGS_BINARY_DIR} DEPENDS run_unit_tests COMMENT ${RUN_MPI_UNIT_TESTS_COMMENT} ) add_custom_target(run_unit_tests COMMAND "${PUGS_BINARY_DIR}/unit_tests" DEPENDS all_unit_tests COMMENT "Running unit_tests" ) # unit tests coverage if("${CMAKE_BUILD_TYPE}" STREQUAL "Coverage") file(GLOB_RECURSE GCNO_FILE_LIST RELATIVE "${PUGS_BINARY_DIR}" "*.gcno") list(FILTER GCNO_FILE_LIST EXCLUDE REGEX "^\.\./.*" ) file(GLOB_RECURSE GCDA_FILE_LIST RELATIVE "${PUGS_BINARY_DIR}" "*.gcda") list(FILTER GCDA_FILE_LIST EXCLUDE REGEX "^\.\./.*" ) foreach(COV_INFO_FILE IN LISTS GCNO_FILE_LIST GCDA_FILE_LIST) string(REGEX REPLACE "/CMakeFiles/.*\.dir/" "/" COV_SRC_FILE "${PUGS_SOURCE_DIR}/${COV_INFO_FILE}") string(REGEX REPLACE "\.gcda$" "" COV_SRC_FILE "${COV_SRC_FILE}") string(REGEX REPLACE "\.gcno$" "" COV_SRC_FILE "${COV_SRC_FILE}") if (NOT EXISTS "${COV_SRC_FILE}") file(REMOVE "${PUGS_BINARY_DIR}/${COV_INFO_FILE}") message(STATUS "removed file ${COV_INFO_FILE}: no longer needed") endif() endforeach() 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) add_custom_target(coverage_unit_tests ALL # in coverage mode we do coverage! COMMAND "${PUGS_BINARY_DIR}/unit_tests" COMMENT "Running unit_tests" DEPENDS coverage_zero_counters ) add_custom_target(coverage_mpi_unit_tests ALL # in coverage mode we do coverage! COMMAND ${MPI_LAUNCHER} "mpi_unit_tests" COMMENT "Running mpi_unit_tests" DEPENDS coverage_unit_tests ) add_custom_target(coverage_run_all_unit_tests ALL # in coverage mode we do coverage! DEPENDS coverage_mpi_unit_tests ) if (FASTCOV AND (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "9")) add_custom_target(coverage_zero_counters ALL # in coverage mode we do coverage! # zero all counters COMMAND ${FASTCOV} -q -z --gcov "${GCOV_BIN}" DEPENDS all_unit_tests ) add_custom_target(coverage ALL # in coverage mode we do coverage! COMMAND ${FASTCOV} --gcov "${GCOV_BIN}" --include "${PUGS_SOURCE_DIR}/src" --exclude "${PUGS_SOURCE_DIR}/src/main.cpp" "${PUGS_SOURCE_DIR}/src/utils/BacktraceManager.*" "${PUGS_SOURCE_DIR}/src/utils/FPEManager.*" "${PUGS_SOURCE_DIR}/src/utils/SignalManager.*" "${PUGS_SOURCE_DIR}/src/utils/checkpointing/pugs_checkpoint_main.cpp" --lcov -o coverage.info -n COMMAND ${LCOV} --gcov "${GCOV_BIN}" --list coverage.info DEPENDS coverage_run_all_unit_tests COMMENT "Running test coverage." WORKING_DIRECTORY "${PUGS_BINARY_DIR}" ) else() add_custom_target(coverage_zero_counters 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 DEPENDS all_unit_tests ) add_custom_target(coverage # 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 coverage_run_all_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() # ------------------- Source files -------------------- # Pugs binary add_executable( pugs src/main.cpp) # Libraries target_link_libraries( pugs PugsMesh PugsAlgebra PugsAnalysis PugsCheckpointing PugsDev PugsUtils PugsLanguage PugsLanguageAST PugsLanguageModules PugsLanguageAlgorithms PugsMesh PugsAlgebra PugsScheme PugsUtils PugsOutput PugsLanguageUtils PugsCheckpointing Kokkos::kokkos ${PETSC_TARGET} ${SLEPC_TARGET} ${PARMETIS_TARGET} ${MPI_CXX_LINK_FLAGS} ${MPI_CXX_LIBRARIES} ${KOKKOS_CXX_FLAGS} ${OPENMP_LINK_FLAGS} ${PUGS_STD_LINK_FLAGS} ${HIGHFIVE_TARGET} ${SLURM_TARGET} stdc++fs ) target_include_directories(pugs PUBLIC ${PETSC_INCLUDE_DIRS}) target_include_directories(pugs PUBLIC ${HDF5_INCLUDE_DIRS}) # Checkpoint management tool add_executable( pugs_checkpoint src/utils/checkpointing/pugs_checkpoint_main.cpp ) target_link_libraries( pugs_checkpoint PugsCheckpointing PugsUtils PugsMesh PugsOutput PugsLanguage PugsLanguageAST PugsLanguageModules PugsLanguageUtils PugsScheme PugsDev PugsAnalysis PugsAlgebra PugsMesh PugsOutput Kokkos::kokkos ${PETSC_TARGET} ${SLEPC_TARGET} ${PARMETIS_TARGET} ${MPI_CXX_LINK_FLAGS} ${MPI_CXX_LIBRARIES} ${KOKKOS_CXX_FLAGS} ${OPENMP_LINK_FLAGS} ${PUGS_STD_LINK_FLAGS} ${HIGHFIVE_TARGET} ${SLURM_TARGET} stdc++fs ) # -------------------- Documentation -------------------- include(PugsDoc) # -------------------- Doxygen -------------------------- include(PugsDoxygen) # -------------------- Installation --------------------- install(TARGETS pugs pugs_checkpoint PugsAlgebra PugsAnalysis PugsCheckpointing PugsDev PugsUtils PugsLanguage PugsLanguageAST PugsLanguageModules PugsLanguageUtils PugsMesh PugsOutput PugsScheme kokkos Catch2 EXPORT "${PROJECT_NAME}Targets" RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib ) include(CMakePackageConfigHelpers) write_basic_package_version_file( PugsConfigVersion.cmake VERSION ${PACKAGE_VERSION} COMPATIBILITY AnyNewerVersion ) install(EXPORT PugsTargets FILE PugsTargets.cmake NAMESPACE Pugs:: DESTINATION lib/cmake/pugs ) # ------------------- Build options ------------------- message("") message("====== pugs build options ======") message(" version: ${PUGS_VERSION}") message(" build type: ${CMAKE_BUILD_TYPE}") message(" compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}") message(" kokkos devices: ${PUGS_BUILD_KOKKOS_DEVICES}") if (MPI_FOUND) message(" MPI: ${MPI_CXX_LIBRARY_VERSION_STRING}") else() if (PUGS_ENABLE_MPI MATCHES "^OFF$") message(" MPI: explicitly deactivated!") elseif((NOT DEFINED PUGS_HAS_PARMETIS) AND (NOT DEFINED PUGS_HAS_PTSCOTCH)) message(" MPI: deactivated: ParMETIS and PTScotch cannot be found!") else() if (PUGS_ENABLE_MPI MATCHES "^(AUTO|ON)$") message(" MPI: not found!") else() message(" MPI: explicitly deactivated!") endif() endif() endif() if (PUGS_HAS_PARMETIS) message(" ParMETIS: ${PARMETIS_LIBRARIES}") else() if (PUGS_HAS_MPI) message(" ParMETIS: not found!") else() message(" ParMETIS: deactivated (MPI not found)") endif() endif() if (PUGS_HAS_PTSCOTCH) message(" PTScotch: ${PTSCOTCH_LIBRARIES}") else() if (PUGS_HAS_MPI) message(" PTScotch: not found!") else() message(" PTScotch: deactivated (MPI not found)") endif() endif() if (PETSC_FOUND) message(" PETSc: ${PETSC_VERSION}") else() if (PUGS_ENABLE_PETSC MATCHES "^(AUTO|ON)$") message(" PETSc: not found!") else() message(" PETSc: explicitly deactivated!") endif() endif() if (SLEPC_FOUND) message(" SLEPc: ${SLEPC_VERSION}") else() if (PUGS_ENABLE_SLEPC MATCHES "^(AUTO|ON)$") message(" SLEPc: not found!") else() message(" SLEPc: explicitly deactivated!") endif() endif() if (EIGEN3_FOUND) message(" Eigen3: ${Eigen3_VERSION}") else() if (PUGS_ENABLE_EIGEN3 MATCHES "^(AUTO|ON)$") message(" Eigen3: not found!") else() message(" Eigen3: explicitly deactivated!") endif() endif() if (HDF5_FOUND) message(" HDF5: ${HDF5_VERSION} parallel: ${HDF5_IS_PARALLEL}") else() if (PUGS_ENABLE_HDF5 MATCHES "^(AUTO|ON)$") message(" HDF5: not found!") else() message(" HDF5: explicitly deactivated!") endif() endif() if (SLURM_FOUND) message(" SLURM library: ${SLURM_LIBRARY}") else() message(" SLURM library: not found!") endif() message("----------- utilities ----------") if(CLANG_FORMAT) message(" clang-format: ${CLANG_FORMAT}") else() message(" clang-format: not found!") endif() if(CLAZY_STANDALONE) message(" clazy-standalone: ${CLAZY_STANDALONE}") else() message(" clazy-standalone: not found!") endif() if (DOXYGEN_FOUND) message(" doxygen: ${DOXYGEN_EXECUTABLE}") else() message(" doxygen: not found!") endif() if (EMACS) message(" emacs: ${EMACS}") else() message(" emacs: not found!") endif() if (GNUPLOT_FOUND) message(" gnuplot: ${GNUPLOT}") else() message(" gnuplot: not found!") endif() if (GMSH) message(" gmsh: ${GMSH}") else() message(" gmsh: not found!") endif() if (PYGMENTIZE) message(" pygmentize: ${PYGMENTIZE}") else() message(" pygmentize: not found!") endif() if (LATEX_PDFLATEX_FOUND) message(" pdflatex: ${PDFLATEX_COMPILER}") else() message(" pdflatex: not found!") endif() if (NOT EMACS OR NOT GNUPLOT_FOUND OR NOT GMSH) message(" ** Cannot build documentation: missing ") elseif(NOT LATEX_PDFLATEX_FOUND OR NOT PYGMENTIZE) message(" ** Cannot build pdf documentation: missing") endif() if (NOT EMACS) message(" - emacs") endif() if (NOT GNUPLOT_FOUND) message(" - gnuplot") endif() if (NOT GMSH) message(" - gmsh") endif() if (NOT LATEX_PDFLATEX_FOUND) message(" - pdflatex") endif() if (NOT PYGMENTIZE) message(" - pygmentize") endif() message("================================") message("") configure_file( ${PUGS_SOURCE_DIR}/cmake/PugsCompileFlags.cmake.in ${PUGS_BINARY_DIR}/cmake/PugsCompileFlags.cmake @ONLY ) install( FILES ${PUGS_BINARY_DIR}/cmake/PugsCompileFlags.cmake DESTINATION lib/cmake/pugs ) # Ugly patch to install user headers for Catch2 (for plugins) install( DIRECTORY "${PUGS_BINARY_DIR}/packages/Catch2/generated-includes/catch2" # Also install the generated header DESTINATION "include" FILES_MATCHING PATTERN "*.hpp" )