Skip to content

Commit

Permalink
Add some quality-of-life CMake defaults (#847)
Browse files Browse the repository at this point in the history
* Define Celeritas_set_default and use for default options

* Add some nice cmake defaults that vecgeom uses

* Print defaults for core geo/rng

* Update deprecated CMake options

* Add documentation comments to address remaining review options

Note that with this change `BUILD_SHARED_LIBS` is not a cache variable so won't show up in ccmake.
  • Loading branch information
sethrj committed Jul 12, 2023
1 parent cdeb6e2 commit b427fde
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 65 deletions.
155 changes: 92 additions & 63 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ include(CMakeDependentOption)
include(CMakePackageConfigHelpers)

#----------------------------------------------------------------------------#
# OPTIONS
# MAIN OPTIONS
#----------------------------------------------------------------------------#

# NOTE: languages must be *first* because their settings affect the
Expand Down Expand Up @@ -59,49 +59,25 @@ option(CELERITAS_BUILD_DEMOS "Build Celeritas demonstration mini-apps"
${CELERITAS_USE_JSON})
option(CELERITAS_BUILD_TESTS "Build Celeritas unit tests" ON)

if(CMAKE_VERSION VERSION_LESS 3.13 AND CELERITAS_USE_CUDA AND CELERITAS_USE_MPI)
message(FATAL_ERROR "Celeritas requires CMake 3.13 or higher "
"when building with CUDA + MPI.")
endif()
if(CMAKE_VERSION VERSION_LESS 3.18 AND CELERITAS_USE_CUDA
AND CELERITAS_USE_VecGeom)
message(FATAL_ERROR "VecGeom+CUDA requires CMake 3.18 or higher to support "
"\"Separable compilation\".")
endif()
if(CMAKE_VERSION VERSION_LESS 3.18 AND CMAKE_CUDA_ARCHITECTURES)
message(FATAL_ERROR "The CMAKE_CUDA_ARCHITECTURES flag is not compatible "
"with this version of CMake. Set CMAKE_CUDA_FLAGS.")
endif()

if(CMAKE_VERSION VERSION_LESS 3.22 AND CELERITAS_USE_HIP)
message(WARNING "HIP support is immature; CMake 3.22+ is recommended.")
endif()
# Assertion handling
option(CELERITAS_DEBUG "Enable runtime assertions" ON)

# Library
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
if(NOT DEFINED CMAKE_INSTALL_RPATH_USE_LINK_PATH)
# Inform installed binaries of external library rpaths
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON)
endif()
if(BUILD_SHARED_LIBS AND NOT DEFINED CMAKE_INSTALL_RPATH)
# Inform installed binaries of internal library rpaths
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_FULL_LIBDIR}")
# Secondary testing options
if(NOT CELERITAS_DEBUG OR CELERITAS_USE_VecGeom)
set(_default_lock ON)
else()
set(_default_lock OFF)
endif()
cmake_dependent_option(CELERITAS_TEST_RESOURCE_LOCK
"Only run one GPU-enabled test at a time" "${_default_lock}"
"CELERITAS_BUILD_TESTS" OFF
)

# Build flags
option(CELERITAS_DEBUG "Enable runtime assertions" ON)
if(DEFINED CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE)
if(CELERITAS_DEBUG)
set(_default_build_type "Debug")
else()
set(_default_build_type "Release")
endif()
set(CMAKE_BUILD_TYPE "${_default_build_type}" CACHE STRING "Build type" FORCE)
message(STATUS "Set default CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
unset(_default_build_type)
endif()
#----------------------------------------------------------------------------#
# CELERITAS CORE IMPLEMENTATION OPTIONS
#----------------------------------------------------------------------------#

# Define CELERITAS_CORE_RNG option for random number generator selection
# CELERITAS_CORE_RNG: random number generator selection
celeritas_setup_option(CELERITAS_CORE_RNG xorwow)
celeritas_setup_option(CELERITAS_CORE_RNG cuRAND CELERITAS_USE_CUDA)
celeritas_setup_option(CELERITAS_CORE_RNG hipRAND CELERITAS_USE_HIP)
Expand All @@ -110,7 +86,7 @@ celeritas_setup_option(CELERITAS_CORE_RNG hipRAND CELERITAS_USE_HIP)
celeritas_define_options(CELERITAS_CORE_RNG
"Celeritas runtime random number generator")

# Runtime geometry selection: default to VecGeom if available
# CELERITAS_CORE_GEO: runtime geometry selection
if(CELERITAS_USE_VecGeom AND NOT CELERITAS_USE_HIP)
set(_allow_vecgeom TRUE)
else()
Expand All @@ -132,22 +108,83 @@ celeritas_setup_option(CELERITAS_CORE_GEO ORANGE)
celeritas_setup_option(CELERITAS_CORE_GEO Geant4 _allow_g4)
celeritas_define_options(CELERITAS_CORE_GEO "Celeritas runtime geometry")

if(NOT CELERITAS_DEBUG OR CELERITAS_USE_VecGeom)
set(_default_lock ON)
else()
set(_default_lock OFF)
#----------------------------------------------------------------------------#
# CMAKE VERSION CHECKS
#----------------------------------------------------------------------------#

if(CMAKE_VERSION VERSION_LESS 3.13 AND CELERITAS_USE_CUDA AND CELERITAS_USE_MPI)
message(FATAL_ERROR "Celeritas requires CMake 3.13 or higher "
"when building with CUDA + MPI.")
endif()
if(CMAKE_VERSION VERSION_LESS 3.18 AND CELERITAS_USE_CUDA
AND CELERITAS_USE_VecGeom)
message(FATAL_ERROR "VecGeom+CUDA requires CMake 3.18 or higher to support "
"\"Separable compilation\".")
endif()
if(CMAKE_VERSION VERSION_LESS 3.18 AND CMAKE_CUDA_ARCHITECTURES)
message(FATAL_ERROR "The CMAKE_CUDA_ARCHITECTURES flag is not compatible "
"with this version of CMake. Set CMAKE_CUDA_FLAGS.")
endif()
if(CMAKE_VERSION VERSION_LESS 3.22 AND CELERITAS_USE_HIP)
message(WARNING "HIP support is immature; CMake 3.22+ is recommended.")
endif()
cmake_dependent_option(CELERITAS_TEST_RESOURCE_LOCK
"Only run one GPU-enabled test at a time" "${_default_lock}"
"CELERITAS_BUILD_TESTS" OFF
)

if(NOT DEFINED CMAKE_CXX_STANDARD)
# Default CMake standard to C++17 for this directory and underneath
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_EXTENSIONS OFF)
#----------------------------------------------------------------------------#
# CMAKE INTRINSIC OPTIONS
#
# These are generally used to initialize properties on targets, and it's
# possible Celeritas is being built inside another project. Instead of saving
# these as cache variables (which change the defaults project-wide, including
# changing behavior of other code that was loaded before Celeritas) set them as
# local variables to be inherited underneath Celeritas.
#----------------------------------------------------------------------------#

### Configuration ###
celeritas_set_default(CMAKE_EXPORT_NO_PACKAGE_REGISTRY ON)
celeritas_set_default(CMAKE_FIND_USE_PACKAGE_REGISTRY FALSE)
celeritas_set_default(CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY FALSE)

### Build flags ###
# Default to debug or released based on value of CELERITAS_DEBUG
if(DEFINED CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE)
if(CELERITAS_DEBUG)
set(_default_build_type "Debug")
else()
set(_default_build_type "Release")
endif()
set(CMAKE_BUILD_TYPE "${_default_build_type}" CACHE STRING "Build type" FORCE)
message(STATUS "Set default CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
unset(_default_build_type)
endif()
# Default to using C++17 everywhere
celeritas_set_default(CMAKE_CXX_STANDARD 17)
celeritas_set_default(CMAKE_CXX_EXTENSIONS OFF)
if(CELERITAS_USE_CUDA)
# Default to setting CUDA C++ standard the same as C++
celeritas_set_default(CMAKE_CUDA_STANDARD ${CMAKE_CXX_STANDARD})
celeritas_set_default(CMAKE_CUDA_EXTENSIONS ${CMAKE_CXX_EXTENSIONS})
endif()

### Linking flags ###
# Default to building shared libraries (*not* a cache variable)
celeritas_set_default(BUILD_SHARED_LIBS ON)
# Inform installed binaries of external library rpaths
celeritas_set_default(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON)
if(BUILD_SHARED_LIBS)
# Inform installed binaries of internal library rpaths
celeritas_set_default(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_FULL_LIBDIR}")
# Do not relink libs/binaries when dependent shared libs change
celeritas_set_default(CMAKE_LINK_DEPENDS_NO_SHARED ON)
endif()

### Installation flags ###
# When developing add checking for proper usage of `install(`
if(CELERITAS_DEBUG)
celeritas_set_default(CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION ON)
endif()
# Avoid printing details about already installed files
celeritas_set_default(CMAKE_INSTALL_MESSAGE LAZY)

#----------------------------------------------------------------------------#
# Output locations for Celeritas products (used by CeleritasLibrary.cmake,
# CeleritasUtils.cmake, install code below) will mirror the installation layout
Expand All @@ -168,15 +205,7 @@ if(CELERITAS_USE_CUDA)
# Use host compiler by default to ensure ABI consistency
set(CMAKE_CUDA_HOST_COMPILER "${CMAKE_CXX_COMPILER}" CACHE STRING
"Set to CMAKE_CXX_COMPILER by Celeritas CMakeLists")

enable_language(CUDA)

if(NOT DEFINED CMAKE_CUDA_STANDARD)
set(CMAKE_CUDA_STANDARD ${CMAKE_CXX_STANDARD})
set(CMAKE_CUDA_EXTENSIONS ${CMAKE_CXX_EXTENSIONS})
endif()
unset(CMAKE_CUDA_FLAGS_DEBUG_INIT)

find_package(CUDAToolkit REQUIRED QUIET)
elseif(CELERITAS_USE_HIP)
enable_language(HIP)
Expand Down Expand Up @@ -337,7 +366,7 @@ if(CELERITAS_USE_SWIG)
endif()

#----------------------------------------------------------------------------#
# TESTS
# UNIT TESTS
#----------------------------------------------------------------------------#

if(CELERITAS_BUILD_TESTS)
Expand All @@ -346,7 +375,7 @@ if(CELERITAS_BUILD_TESTS)
endif()

#----------------------------------------------------------------------------#
# DEMO/HELPER APPS
# APPLICATIONS AND BINARIES
#----------------------------------------------------------------------------#

add_subdirectory(app)
Expand Down
24 changes: 22 additions & 2 deletions cmake/CeleritasUtils.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ CMake configuration utility functions for Celeritas.
packages. If given, the ``<find_package>`` package name will searched for
instead of ``<package>``.

.. command:: celeritas_set_default

Set a locally-scoped value for the given variable if it is undefined.

.. command:: celeritas_check_python_module

Determine whether a given Python module is available with the current
Expand Down Expand Up @@ -195,6 +199,15 @@ endmacro()

#-----------------------------------------------------------------------------#

function(celeritas_set_default name value)
if(NOT DEFINED ${name})
message(VERBOSE "Celeritas: set default ${name}=${value}")
set(${name} "${value}" PARENT_SCOPE)
endif()
endfunction()

#-----------------------------------------------------------------------------#

function(celeritas_check_python_module varname module)
set(_cache_name CELERITAS_CHECK_PYTHON_MODULE_${module})
if(DEFINED ${_cache_name})
Expand Down Expand Up @@ -342,13 +355,15 @@ function(celeritas_define_options var doc)
set(${var} "" CACHE STRING "${doc}")
set_property(CACHE ${var} PROPERTY STRINGS "${${var}_OPTIONS}")

if("${${var}}" STREQUAL "")
set(_val "${${var}}")
if(_val STREQUAL "")
# Dynamic default option: set as core variable in parent scope
list(GET ${var}_OPTIONS 0 _default)
set(${var} "${_default}" PARENT_SCOPE)
set(_val "${_default}")
else()
# User-provided value: check against list
list(FIND ${var}_OPTIONS "${${var}}" _index)
list(FIND ${var}_OPTIONS "${_val}" _index)
if(_index EQUAL -1)
string(JOIN "," _optlist ${${var}_OPTIONS})
celeritas_error_incompatible_option(
Expand All @@ -357,6 +372,11 @@ function(celeritas_define_options var doc)
)
endif()
endif()
set(_last_var _LAST_${var})
if(NOT ${var} STREQUAL ${_last_var}) # compare *values* of variable names
message(STATUS "Set ${var}=${_val}")
set(${_last_var} "${_val}" CACHE INTERNAL "")
endif()
endfunction()

#-----------------------------------------------------------------------------#
Expand Down

0 comments on commit b427fde

Please sign in to comment.