#============================================================================= # Adds the following DIY library targets: # 1. diy: The main diy interface library and the only target for # header-only mode. # 2. diympi: Generated when `build_diy_mpi_lib` and `mpi` are turned on. # Isolates the MPI dependent part of diy into a library. # 3. diympi_nompi: Generated when `build_diy_mpi_lib` is on and either `mpi` # is off or `build_diy_nompi_lib` is on. # # Both mpi and non-mpi libraries can be generated by turning on `build_diy_mpi_lib` # and `build_diy_nompi_lib`. In this case, one of these targets must be explicitly # specified when linking againts diy. #============================================================================= project (DIY) cmake_minimum_required (VERSION 3.9) list (APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) include(CMakeDependentOption) # Provides an option if it is not already defined. # This can be replaced when CMake 3.13 is our cmake_minimum_required macro (diy_option variable) if (NOT DEFINED "${variable}") option("${variable}" ${ARGN}) endif () endmacro () macro (diy_dependent_option variable) if (NOT DEFINED "${variable}") cmake_dependent_option("${variable}" ${ARGN}) endif () endmacro () set (compiler_supports_sanitizers OFF) if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set (compiler_supports_sanitizers ON) endif () diy_option (threads "Build DIY with threading" ON) diy_option (log "Build DIY with logging" OFF) diy_option (profile "Build DIY with profiling" OFF) diy_option (caliper "Build DIY with caliper" OFF) diy_option (mpi "Build DIY with mpi" ON) diy_option (wrapped_mpi "MPI compiler wrapper requires no further MPI libraries" OFF) diy_option (build_diy_mpi_lib "Build diy::mpi as a library" OFF) diy_dependent_option (BUILD_SHARED_LIBS "Create shared libraries if on" ON "build_diy_mpi_lib" OFF) diy_dependent_option (build_diy_nompi_lib "Also build the nompi version of diy::mpi" OFF "mpi;build_diy_mpi_lib" OFF) diy_option (build_examples "Build DIY examples" ON) diy_option (build_tests "Build DIY tests" ON) diy_option (python "Build Python bindings" OFF) cmake_dependent_option (enable_sanitizers "Build DIY with sanitizer support" OFF "compiler_supports_sanitizers" OFF) # Default to Release if (NOT CMAKE_BUILD_TYPE) set (CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE) set_property (CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif (NOT CMAKE_BUILD_TYPE) set (diy_definitions "") set (diy_include_directories "") set (diy_include_thirdparty_directories "") set (diy_libraries "") # Debugging if (${CMAKE_BUILD_TYPE} STREQUAL "Debug" OR ${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo") list (APPEND diy_definitions "-DVTKMDIY_DEBUG") endif () # Logging if (log) list (APPEND diy_definitions "-DVTMDIY_USE_SPDLOG") find_package (spdlog REQUIRED) endif() # Profiling if (profile) list (APPEND diy_definitions "-DVTKMDIY_PROFILE") endif() if (caliper) list (APPEND diy_definitions "-DVTKMDIY_USE_CALIPER") find_package (caliper) list (APPEND diy_include_thirdparty_directories $) list (APPEND diy_libraries caliper caliper-mpi) endif() # Threads if (NOT threads) list (APPEND diy_definitions "-DVTKMDIY_NO_THREADS") else (NOT threads) find_package (Threads) list (APPEND diy_libraries ${CMAKE_THREAD_LIBS_INIT}) endif (NOT threads) # MPI if (mpi AND NOT wrapped_mpi) find_package(MPI REQUIRED) endif() # configuration variables for diy build and install # if diy is a sub-project, the following variables allow the parent project to # easily customize the library if (NOT DEFINED diy_prefix) set(diy_prefix "diy") endif() if (NOT DEFINED diy_install_include_dir) set(diy_install_include_dir "include") endif() if (NOT DEFINED diy_install_bin_dir) set(diy_install_bin_dir "bin") endif() if (NOT DEFINED diy_install_lib_dir) set(diy_install_lib_dir "lib") endif() if (NOT DEFINED diy_export_name) set(diy_export_name "diy_targets") endif() if (NOT DEFINED diy_development_component) set(diy_development_component "development") endif() if (NOT DEFINED diy_runtime_component) set(diy_runtime_component "runtime") endif() if (NOT DEFINED CMAKE_ARCHIVE_OUTPUT_DIRECTORY) set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") endif() if (NOT DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY) set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") endif() # for diy_developer_flags include(DIYCompilerFlags) function(add_diy_mpi_library use_mpi) set (sources "include/${diy_prefix}/mpi/collectives.cpp" "include/${diy_prefix}/mpi/communicator.cpp" "include/${diy_prefix}/mpi/datatypes.cpp" "include/${diy_prefix}/mpi/environment.cpp" "include/${diy_prefix}/mpi/io.cpp" "include/${diy_prefix}/mpi/operations.cpp" "include/${diy_prefix}/mpi/point-to-point.cpp" "include/${diy_prefix}/mpi/request.cpp" "include/${diy_prefix}/mpi/status.cpp" "include/${diy_prefix}/mpi/window.cpp") if (use_mpi) set (lib_name ${diy_prefix}mpi) set (has_mpi_val 1) else() set (lib_name ${diy_prefix}mpi_nompi) set (has_mpi_val 0) endif() add_library(${lib_name} ${sources}) set_target_properties(${lib_name} PROPERTIES POSITION_INDEPENDENT_CODE ON) target_compile_features(${lib_name} PRIVATE cxx_std_14) target_compile_definitions(${lib_name} PRIVATE -DVTKMDIY_HAS_MPI=${has_mpi_val} PRIVATE -Ddiy=${diy_prefix} # mangle diy namespace PRIVATE ${diy_definitions}) target_include_directories(${lib_name} SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/include) # for types.hpp target_include_directories(${lib_name} SYSTEM PRIVATE ${diy_include_directories}) # for mpitypes.hpp target_include_directories(${lib_name} SYSTEM PRIVATE ${diy_include_thirdparty_directories}) target_link_libraries(${lib_name} PRIVATE diy_developer_flags) if (log) target_link_libraries(${lib_name} PUBLIC spdlog::spdlog_header_only) endif () if (use_mpi AND TARGET MPI::MPI_CXX) target_link_libraries(${lib_name} PRIVATE MPI::MPI_CXX) endif() endfunction() # create the targets set (diy_targets) if (build_diy_mpi_lib) include(DIYConfigureMPI) # To be interchangeable, these libraries should only have PRIVATE properties. # Properties that should be public should also be part of the core diy target. list(APPEND diy_definitions -DVTKMDIY_MPI_AS_LIB) list(APPEND diy_include_directories "$" "$") # macro required for proper export macros for static vs shared builds if (NOT BUILD_SHARED_LIBS) list(APPEND diy_definitions -DVTKMDIY_MPI_STATIC_BUILD) endif() if (mpi) add_diy_mpi_library(ON) list(APPEND diy_targets ${diy_prefix}mpi) endif() if ((NOT mpi) OR build_diy_nompi_lib) add_diy_mpi_library(OFF) list(APPEND diy_targets ${diy_prefix}mpi_nompi) endif() endif() # build_diy_mpi_lib add_library(${diy_prefix} INTERFACE) target_compile_features(${diy_prefix} INTERFACE cxx_std_14) target_compile_definitions(${diy_prefix} INTERFACE ${diy_definitions}) target_include_directories(${diy_prefix} SYSTEM INTERFACE "$" "$") target_include_directories(${diy_prefix} SYSTEM INTERFACE ${diy_include_thirdparty_directories}) if (diy_include_directories) target_include_directories(${diy_prefix} SYSTEM INTERFACE ${diy_include_directories}) endif() if (log) target_link_libraries(${diy_prefix} INTERFACE spdlog::spdlog_header_only) endif () target_link_libraries(${diy_prefix} INTERFACE ${diy_libraries}) if (NOT build_diy_mpi_lib) if (mpi) target_compile_definitions(${diy_prefix} INTERFACE -DVTKMDIY_HAS_MPI=1) if (TARGET MPI::MPI_CXX) target_link_libraries(${diy_prefix} INTERFACE MPI::MPI_CXX) endif() else() target_compile_definitions(${diy_prefix} INTERFACE -DVTKMDIY_HAS_MPI=0) endif() elseif (NOT build_diy_nompi_lib) if (mpi) target_link_libraries(${diy_prefix} INTERFACE ${diy_prefix}mpi) else() target_link_libraries(${diy_prefix} INTERFACE ${diy_prefix}mpi_nompi) endif() endif() list(APPEND diy_targets ${diy_prefix} diy_developer_flags) # libraries used by examples and tests set(libraries ${diy_prefix}) if (${diy_prefix}mpi IN_LIST diy_targets) list(APPEND libraries ${diy_prefix}mpi) elseif (${diy_prefix}mpi_nompi IN_LIST diy_targets) list(APPEND libraries ${diy_prefix}mpi_nompi) endif() list(APPEND libraries diy_developer_flags) # Sanitizers if (enable_sanitizers) set(sanitizer "address" CACHE STRING "The sanitizer to use") string (APPEND CMAKE_CXX_FLAGS " -fsanitize=${sanitizer}") string (APPEND CMAKE_C_FLAGS " -fsanitize=${sanitizer}") string (APPEND CMAKE_EXE_LINKER_FLAGS " -fsanitize=${sanitizer}") string (APPEND CMAKE_SHARED_LINKER_FLAGS " -fsanitize=${sanitizer}") endif () # enable testing and CDash dashboard submission enable_testing () include (CTest) if (build_examples) add_subdirectory (examples) endif (build_examples) if (build_tests) add_subdirectory (tests) endif (build_tests) # configure find_package script include(CMakePackageConfigHelpers) configure_package_config_file( "${PROJECT_SOURCE_DIR}/cmake/diy-config.cmake.in" "${PROJECT_BINARY_DIR}/diy-config.cmake" INSTALL_DESTINATION ".") # install targets if (NOT DEFINED diy_install_only_libraries) # defined by parent project if building for binary distribution install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/${diy_prefix} DESTINATION ${diy_install_include_dir} COMPONENT ${diy_development_component}) if (build_diy_mpi_lib) install(FILES ${PROJECT_BINARY_DIR}/include/${diy_prefix}/mpi/mpitypes.hpp DESTINATION ${diy_install_include_dir}/${diy_prefix}/mpi COMPONENT ${diy_development_component}) endif() endif() install(TARGETS ${diy_targets} EXPORT ${diy_export_name} ARCHIVE DESTINATION ${diy_install_lib_dir} COMPONENT ${diy_development_component} LIBRARY DESTINATION ${diy_install_lib_dir} COMPONENT ${diy_runtime_component} RUNTIME DESTINATION ${diy_install_bin_dir} COMPONENT ${diy_runtime_component}) if (CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) # Only generate these files when diy is the main project export(EXPORT ${diy_export_name} NAMESPACE DIY:: FILE "${PROJECT_BINARY_DIR}/diy-targets.cmake") install(EXPORT ${diy_export_name} NAMESPACE DIY:: DESTINATION "." FILE diy-targets.cmake COMPONENT ${diy_development_component}) install(FILES "${PROJECT_BINARY_DIR}/diy-config.cmake" DESTINATION "." COMPONENT ${diy_development_component}) endif() if (python) add_subdirectory(bindings/python) endif (python)