-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove CMake < 3.18 support and modernise CMake
CMake < 3.18 was already deprecated as 3.18 is required for c++17 CUDA + Updates the readme version requirements + Updates CMake Minimum required statements + Removes workarounds for old CMake versions + Use FindCUDAToolkit now it is always available + Switch to linking against the shared cuda runtime library, rather than implicit default of static on some platforms + Create INTERFACE library targets for header only libraries. This enforces the use of SYSTEM on includes + Create ALIAS library targets for 3rd party dependencies, for consistency + Stops the modification of CMAKE_<LANGUAGE>_FLAGS which is poor form + Switches from global defines/includes/links to per-target through the use of target specific functions + Ensure packages are available where they are used + Prevent in-source CMake builds + Use PUBLIC/INTERFACE/PRIVATE for link libraries etc. This may currently be excessivly public + Inherit visualisation dependency from target, required vis repo update. + Cmake organisation + Adjusts swig/python CMake to re-use components from elsewhere more + This file could do with work still + Misc other CMake changes
- Loading branch information
Showing
34 changed files
with
733 additions
and
637 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Define a cmake function which emits a fatal error if the source directory and binary directory are the same. | ||
function(EnforceOutOfSourceBuilds) | ||
# Resolve paths before comparioson to ensure comparions are accurate | ||
get_filename_component(source_dir "${CMAKE_SOURCE_DIR}" REALPATH) | ||
get_filename_component(binary_dir "${CMAKE_BINARY_DIR}" REALPATH) | ||
|
||
if("${source_dir}" STREQUAL "${binary_dir}") | ||
message(FATAL_ERROR | ||
" In-source CMake builds are not allowed.\n" | ||
" Use a build directory i.e. cmake -B build.\n" | ||
" You may have to clear/delete the generated CMakeCache.txt and CMakeFiles/:\n" | ||
" ${binary_dir}/CMakeCache.txt\n" | ||
" ${binary_dir}/CMakeFiles/\n") | ||
endif() | ||
endfunction() | ||
|
||
# Call the function imediately, so the file only needs to be included. | ||
EnforceOutOfSourceBuilds() | ||
|
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,120 +1,134 @@ | ||
# Build a list of gencode arguments, based on CUDA verison. | ||
# Accepts user override via CUDA_ARCH | ||
|
||
# CMAKE > 3.18 introduces CUDA_ARCHITECTURES as a cmake-native way of generating gencodes (Policy CMP0104). Set the value to OFF to prevent errors for it being not provided. | ||
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.18") | ||
set(CMAKE_CUDA_ARCHITECTURES "OFF") | ||
endif() | ||
|
||
|
||
# Check if any have been provided by the users | ||
string(LENGTH "${CUDA_ARCH}" CUDA_ARCH_LENGTH) | ||
|
||
# Define the default compute capabilites incase not provided by the user | ||
set(DEFAULT_CUDA_ARCH "35;50;60;70;80;") | ||
|
||
# Get the valid options for the current compiler. | ||
# Run nvcc --help to get the help string which contains all valid compute_ sm_ for that version. | ||
execute_process(COMMAND ${CMAKE_CUDA_COMPILER} "--help" OUTPUT_VARIABLE NVCC_HELP_STR ERROR_VARIABLE NVCC_HELP_STR) | ||
# Match all comptue_XX or sm_XXs | ||
string(REGEX MATCHALL "'(sm|compute)_[0-9]+'" SUPPORTED_CUDA_ARCH "${NVCC_HELP_STR}" ) | ||
# Strip just the numeric component | ||
string(REGEX REPLACE "'(sm|compute)_([0-9]+)'" "\\2" SUPPORTED_CUDA_ARCH "${SUPPORTED_CUDA_ARCH}" ) | ||
# Remove dupes and sort to build the correct list of supported CUDA_ARCH. | ||
list(REMOVE_DUPLICATES SUPPORTED_CUDA_ARCH) | ||
list(REMOVE_ITEM SUPPORTED_CUDA_ARCH "") | ||
list(SORT SUPPORTED_CUDA_ARCH) | ||
|
||
# Update defaults to only be those supported | ||
# @todo might be better to instead do a dry run compilation with each gencode to validate? | ||
foreach(ARCH IN LISTS DEFAULT_CUDA_ARCH) | ||
if (NOT ARCH IN_LIST SUPPORTED_CUDA_ARCH) | ||
list(REMOVE_ITEM DEFAULT_CUDA_ARCH "${ARCH}") | ||
# Provides a per target function to set gencode compiler options. | ||
# Function to suppress compiler warnings for a given target | ||
# If the cmake variable CUDA_ARCH is set, to a non emtpy list or space separated string this will be used instead. | ||
# @todo - find a way to warn about deprecated architectures once and only once (at cmake time?) Might need to just try compiling with old warnings and capture / post process the output. | ||
# @todo - figure out how to do this once and only once as a function rather than a macro. | ||
macro(SetCUDAGencodes) | ||
# @todo - only get the available gencodes from nvcc once, rather than per target. | ||
|
||
# Parse the expected arguments, prefixing variables. | ||
cmake_parse_arguments( | ||
SCG | ||
"" | ||
"TARGET" | ||
"" | ||
${ARGN} | ||
) | ||
# Ensure that a target has been passed, and that it is a valid target. | ||
if(NOT SCG_TARGET) | ||
message( FATAL_ERROR "SetCUDAGencodes: 'TARGET' argument required." ) | ||
elseif(NOT TARGET ${SCG_TARGET} ) | ||
message( FATAL_ERROR "SetCUDAGencodes: TARGET '${SCG_TARGET}' is not a valid target" ) | ||
endif() | ||
list(REMOVE_DUPLICATES CUDA_ARCH) | ||
list(REMOVE_ITEM CUDA_ARCH "") | ||
list(SORT CUDA_ARCH) | ||
endforeach() | ||
|
||
|
||
if(NOT CUDA_ARCH_LENGTH EQUAL 0) | ||
# Convert user provided string argument to a list. | ||
string (REPLACE " " ";" CUDA_ARCH "${CUDA_ARCH}") | ||
string (REPLACE "," ";" CUDA_ARCH "${CUDA_ARCH}") | ||
|
||
# Remove duplicates, empty items and sort. | ||
list(REMOVE_DUPLICATES CUDA_ARCH) | ||
list(REMOVE_ITEM CUDA_ARCH "") | ||
list(SORT CUDA_ARCH) | ||
|
||
# Validate the list. | ||
foreach(ARCH IN LISTS CUDA_ARCH) | ||
if (NOT ARCH IN_LIST SUPPORTED_CUDA_ARCH) | ||
message(WARNING | ||
" CUDA_ARCH '${ARCH}' not supported by CUDA ${CMAKE_CUDA_COMPILER_VERSION} and is being ignored.\n" | ||
" Choose from: ${SUPPORTED_CUDA_ARCH}") | ||
list(REMOVE_ITEM CUDA_ARCH "${ARCH}") | ||
endif() | ||
endforeach() | ||
|
||
# @todo - validate that the CUDA_ARCH provided are supported by the compiler | ||
endif() | ||
|
||
# If the list is empty post validation, set it to the (validated) defaults | ||
list(LENGTH CUDA_ARCH CUDA_ARCH_LENGTH) | ||
if(CUDA_ARCH_LENGTH EQUAL 0) | ||
set(CUDA_ARCH ${DEFAULT_CUDA_ARCH}) | ||
endif() | ||
|
||
# Propagate the validated values to the parent scope, to reduce warning duplication. | ||
get_directory_property(hasParent PARENT_DIRECTORY) | ||
if(hasParent) | ||
set(CUDA_ARCH ${CUDA_ARCH} PARENT_SCOPE) | ||
endif() | ||
# If the list is somehow empty now, do not set any gencodes arguments, instead using the compiler defaults. | ||
list(LENGTH CUDA_ARCH CUDA_ARCH_LENGTH) | ||
if(NOT CUDA_ARCH_LENGTH EQUAL 0) | ||
# Only do this if required.I.e. CUDA_ARCH is the same as the last time this file was included | ||
if(NOT CUDA_ARCH_APPLIED EQUAL CUDA_ARCH) | ||
message(STATUS "Generating Compute Capabilities: ${CUDA_ARCH}") | ||
# CMAKE > 3.18 introduces CUDA_ARCHITECTURES as a cmake-native way of generating gencodes (Policy CMP0104). Set the value to OFF to prevent errors for it being not provided. | ||
# We manually set gencode arguments, so we can (potentially) use LTO and are not restricted to CMake's availble options. | ||
set_property(TARGET ${SCG_TARGET} PROPERTY CUDA_ARCHITECTURES OFF) | ||
|
||
# Define the default compute capabilites incase not provided by the user | ||
set(DEFAULT_CUDA_ARCH "35;50;60;70;80;") | ||
|
||
# Determine if the user has provided a non default CUDA_ARCH value | ||
string(LENGTH "${CUDA_ARCH}" CUDA_ARCH_LENGTH) | ||
|
||
# Query NVCC in order to filter the provided list. | ||
# @todo only do this once, and re-use the output for a given cmake configure? | ||
|
||
# Get the valid options for the current compiler. | ||
# Run nvcc --help to get the help string which contains all valid compute_ sm_ for that version. | ||
if(NOT DEFINED SUPPORTED_CUDA_ARCH) | ||
execute_process(COMMAND ${CMAKE_CUDA_COMPILER} "--help" OUTPUT_VARIABLE NVCC_HELP_STR ERROR_VARIABLE NVCC_HELP_STR) | ||
# Match all comptue_XX or sm_XXs | ||
string(REGEX MATCHALL "'(sm|compute)_[0-9]+'" SUPPORTED_CUDA_ARCH "${NVCC_HELP_STR}" ) | ||
# Strip just the numeric component | ||
string(REGEX REPLACE "'(sm|compute)_([0-9]+)'" "\\2" SUPPORTED_CUDA_ARCH "${SUPPORTED_CUDA_ARCH}" ) | ||
# Remove dupes and sort to build the correct list of supported CUDA_ARCH. | ||
list(REMOVE_DUPLICATES SUPPORTED_CUDA_ARCH) | ||
list(REMOVE_ITEM SUPPORTED_CUDA_ARCH "") | ||
list(SORT SUPPORTED_CUDA_ARCH) | ||
|
||
# Store the supported arch's once and only once. This could be a cache var given the cuda compiler should not be able to change without clearing th cache? | ||
get_directory_property(hasParent PARENT_DIRECTORY) | ||
if(hasParent) | ||
set(CUDA_ARCH_APPLIED "${CUDA_ARCH}" PARENT_SCOPE ) | ||
set(SUPPORTED_CUDA_ARCH ${SUPPORTED_CUDA_ARCH} PARENT_SCOPE) | ||
endif() | ||
endif() | ||
set(GENCODES_FLAGS) | ||
set(MIN_CUDA_ARCH) | ||
# Convert to gencode arguments | ||
|
||
foreach(ARCH IN LISTS CUDA_ARCH) | ||
set(GENCODES_FLAGS "${GENCODES_FLAGS} -gencode arch=compute_${ARCH},code=sm_${ARCH}") | ||
|
||
|
||
# Update defaults to only be those supported | ||
# @todo might be better to instead do a dry run compilation with each gencode to validate? | ||
foreach(ARCH IN LISTS DEFAULT_CUDA_ARCH) | ||
if (NOT ARCH IN_LIST SUPPORTED_CUDA_ARCH) | ||
list(REMOVE_ITEM DEFAULT_CUDA_ARCH "${ARCH}") | ||
endif() | ||
list(REMOVE_DUPLICATES CUDA_ARCH) | ||
list(REMOVE_ITEM CUDA_ARCH "") | ||
list(SORT CUDA_ARCH) | ||
endforeach() | ||
|
||
# Add the last arch again as compute_, compute_ to enable forward looking JIT | ||
list(GET CUDA_ARCH -1 LAST_ARCH) | ||
set(GENCODES_FLAGS "${GENCODES_FLAGS} -gencode arch=compute_${LAST_ARCH},code=compute_${LAST_ARCH}") | ||
|
||
# Get the minimum device architecture to pass through to nvcc to enable graceful failure prior to cuda execution. | ||
list(GET CUDA_ARCH 0 MIN_CUDA_ARCH) | ||
|
||
# Set the gencode flags on NVCC | ||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} ${GENCODES_FLAGS}") | ||
if(NOT CUDA_ARCH_LENGTH EQUAL 0) | ||
# Convert user provided string argument to a list. | ||
string (REPLACE " " ";" CUDA_ARCH "${CUDA_ARCH}") | ||
string (REPLACE "," ";" CUDA_ARCH "${CUDA_ARCH}") | ||
|
||
# Remove duplicates, empty items and sort. | ||
list(REMOVE_DUPLICATES CUDA_ARCH) | ||
list(REMOVE_ITEM CUDA_ARCH "") | ||
list(SORT CUDA_ARCH) | ||
|
||
# Validate the list. | ||
foreach(ARCH IN LISTS CUDA_ARCH) | ||
if (NOT ARCH IN_LIST SUPPORTED_CUDA_ARCH) | ||
message(WARNING | ||
" CUDA_ARCH '${ARCH}' not supported by CUDA ${CMAKE_CUDA_COMPILER_VERSION} and is being ignored.\n" | ||
" Choose from: ${SUPPORTED_CUDA_ARCH}") | ||
list(REMOVE_ITEM CUDA_ARCH "${ARCH}") | ||
endif() | ||
endforeach() | ||
endif() | ||
|
||
# Set the minimum arch flags for all compilers | ||
set(CMAKE_CC_FLAGS "${CMAKE_C_FLAGS} -DMIN_CUDA_ARCH=${MIN_CUDA_ARCH}") | ||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMIN_CUDA_ARCH=${MIN_CUDA_ARCH}") | ||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -DMIN_CUDA_ARCH=${MIN_CUDA_ARCH}") | ||
else() | ||
message(STATUS "Generating default CUDA Compute Capabilities ${CUDA_ARCH}") | ||
endif() | ||
|
||
# Supress deprecated architecture warnings, as they are not fitered out by checking against nvcc help. | ||
# Ideally a warning would be output once at config time (i.e. above) and not at every file compilation. | ||
# But this is challenging due to multiline string detection. | ||
# Could potentially compile a simple program, without this flag to detect if its valid/deprecated? Would likely increase build time. | ||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Wno-deprecated-gpu-targets") | ||
# If the list is empty post validation, set it to the (validated) defaults | ||
list(LENGTH CUDA_ARCH CUDA_ARCH_LENGTH) | ||
if(CUDA_ARCH_LENGTH EQUAL 0) | ||
set(CUDA_ARCH ${DEFAULT_CUDA_ARCH}) | ||
endif() | ||
|
||
# If CUDA 11.2+, can build multiple architectures in parallel. Note this will be multiplicative against the number of threads launched for parallel cmake build, which may anger some systems. | ||
if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "11.2" AND USE_NVCC_THREADS AND DEFINED NVCC_THREADS AND NVCC_THREADS GREATER_EQUAL 0) | ||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --threads ${NVCC_THREADS}") | ||
endif() | ||
# Propagate the validated values to the parent scope, to reduce warning duplication. | ||
get_directory_property(hasParent PARENT_DIRECTORY) | ||
if(hasParent) | ||
set(CUDA_ARCH ${CUDA_ARCH} PARENT_SCOPE) | ||
endif() | ||
|
||
# If the list is somehow empty now, do not set any gencodes arguments, instead using the compiler defaults. | ||
list(LENGTH CUDA_ARCH CUDA_ARCH_LENGTH) | ||
if(NOT CUDA_ARCH_LENGTH EQUAL 0) | ||
# Only do this if required.I.e. CUDA_ARCH is the same as the last time this file was included | ||
if(NOT CUDA_ARCH_APPLIED EQUAL CUDA_ARCH) | ||
message(STATUS "Generating Compute Capabilities: ${CUDA_ARCH}") | ||
if(hasParent) | ||
set(CUDA_ARCH_APPLIED "${CUDA_ARCH}" PARENT_SCOPE ) | ||
endif() | ||
endif() | ||
set(MIN_CUDA_ARCH) | ||
# Convert to gencode arguments | ||
|
||
foreach(ARCH IN LISTS CUDA_ARCH) | ||
target_compile_options(${SCG_TARGET} PRIVATE "$<$<COMPILE_LANGUAGE:CUDA>:SHELL:-gencode arch=compute_${ARCH}$<COMMA>code=sm_${ARCH}>") | ||
target_link_options(${SCG_TARGET} PRIVATE "$<DEVICE_LINK:SHELL:-gencode arch=compute_${ARCH}$<COMMA>code=sm_${ARCH}>") | ||
endforeach() | ||
|
||
# Add the last arch again as compute_, compute_ to enable forward looking JIT | ||
list(GET CUDA_ARCH -1 LAST_ARCH) | ||
target_compile_options(${SCG_TARGET} PRIVATE "$<$<COMPILE_LANGUAGE:CUDA>:SHELL:-gencode arch=compute_${LAST_ARCH}$<COMMA>code=compute_${LAST_ARCH}>") | ||
target_link_options(${SCG_TARGET} PRIVATE "$<DEVICE_LINK:SHELL:-gencode arch=compute_${LAST_ARCH}$<COMMA>code=compute_${LAST_ARCH}>") | ||
|
||
# Get the minimum device architecture to pass through to nvcc to enable graceful failure prior to cuda execution. | ||
list(GET CUDA_ARCH 0 MIN_CUDA_ARCH) | ||
|
||
# Set the minimum arch flags for all compilers | ||
target_compile_definitions(${SCG_TARGET} PRIVATE -DMIN_CUDA_ARCH=${MIN_CUDA_ARCH}) | ||
else() | ||
message(STATUS "Generating default CUDA Compute Capabilities ${CUDA_ARCH}") | ||
endif() | ||
endmacro() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
Oops, something went wrong.