From 646e8349475a3d94186585fcb9480209b887aa99 Mon Sep 17 00:00:00 2001 From: Peter Heywood Date: Tue, 24 Aug 2021 19:02:12 +0100 Subject: [PATCH] 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__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 --- CMakeLists.txt | 18 +- README.md | 1 - cmake/OutOfSourceOnly.cmake | 19 + cmake/common.cmake | 396 ++++++------------ cmake/cuda_arch.cmake | 232 +++++----- cmake/cxxstd.cmake | 15 +- cmake/{ => dependencies}/Jitify.cmake | 7 +- cmake/{ => dependencies}/Thrust.cmake | 0 cmake/{ => dependencies}/Tinyxml2.cmake | 25 +- cmake/{ => dependencies}/doxygen.cmake | 0 .../flamegpu2-visualiser.cmake | 0 cmake/{ => dependencies}/glm.cmake | 0 cmake/{ => dependencies}/googletest.cmake | 2 +- cmake/{ => dependencies}/rapidjson.cmake | 6 + cmake/modules/FindJitify.cmake | 4 + cmake/modules/FindNVRTC.cmake | 56 --- cmake/modules/FindNVTX.cmake | 22 + cmake/modules/Findglm.cmake | 6 +- cmake/version.cmake | 13 +- cmake/warnings.cmake | 211 +++++++--- examples/boids_bruteforce/CMakeLists.txt | 4 +- .../CMakeLists.txt | 4 +- examples/boids_rtc_bruteforce/CMakeLists.txt | 4 +- examples/boids_rtc_spatial3D/CMakeLists.txt | 4 +- examples/boids_spatial3D/CMakeLists.txt | 4 +- examples/circles_bruteforce/CMakeLists.txt | 4 +- examples/circles_spatial3D/CMakeLists.txt | 4 +- examples/game_of_life/CMakeLists.txt | 4 +- examples/host_functions/CMakeLists.txt | 4 +- src/CMakeLists.txt | 195 +++++++-- swig/CMakeLists.txt | 13 +- swig/python/CMakeLists.txt | 71 ++-- swig/python/setup.py.in | 2 +- tests/CMakeLists.txt | 20 +- 34 files changed, 733 insertions(+), 637 deletions(-) create mode 100644 cmake/OutOfSourceOnly.cmake rename cmake/{ => dependencies}/Jitify.cmake (81%) rename cmake/{ => dependencies}/Thrust.cmake (100%) rename cmake/{ => dependencies}/Tinyxml2.cmake (66%) rename cmake/{ => dependencies}/doxygen.cmake (100%) rename cmake/{ => dependencies}/flamegpu2-visualiser.cmake (100%) rename cmake/{ => dependencies}/glm.cmake (100%) rename cmake/{ => dependencies}/googletest.cmake (95%) rename cmake/{ => dependencies}/rapidjson.cmake (89%) delete mode 100644 cmake/modules/FindNVRTC.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 6783ad32a..ff326ad1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,13 @@ -# CMake 3.15+ for Thrust/Cub support -cmake_minimum_required(VERSION VERSION 3.15 FATAL_ERROR) +# Minimum CMake version 3.18 for CUDA --std=c++17 +cmake_minimum_required(VERSION VERSION 3.18 FATAL_ERROR) -# Emit a deprecation warning if CMAKE < 3.18 which is required for c++17 in the future. -set(CMAKE_MINIMUM_SUPPORTED_VERSION 3.18) -if(${CMAKE_VERSION} VERSION_LESS ${CMAKE_MINIMUM_SUPPORTED_VERSION}) - message(DEPRECATION "Support for CMake < ${CMAKE_MINIMUM_SUPPORTED_VERSION} is deprecated and will be removed in a future release.") -endif() +project(FLAMEGPU LANGUAGES NONE) +# Find the root directory +get_filename_component(FLAMEGPU_ROOT ${CMAKE_CURRENT_SOURCE_DIR} REALPATH) -project(FLAMEGPU LANGUAGES NONE) +# Ensure this is not an in-source build +include(${FLAMEGPU_ROOT}/cmake/OutOfSourceOnly.cmake) # Don't create installation scripts (and hide CMAKE_INSTALL_PREFIX from cmake-gui) set(CMAKE_SKIP_INSTALL_RULES TRUE) @@ -69,8 +68,7 @@ endif() # If CUDA is not available, or the minimum version is too low only build the docs. if(DOCUMENTATION_ONLY_BUILD) # Not able to build code, so just make docs - get_filename_component(FLAMEGPU_ROOT ${CMAKE_CURRENT_SOURCE_DIR} REALPATH) - include(./cmake/doxygen.cmake) + include(./cmake/dependencies/doxygen.cmake) if(${BUILD_API_DOCUMENTATION}) create_doxygen_target("${FLAMEGPU_ROOT}" "${CMAKE_CURRENT_BINARY_DIR}" "") endif() diff --git a/README.md b/README.md index 6d88320bb..aad24641b 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,6 @@ This is used to build the FLAMEGPU2 library, examples, tests and documentation. Building FLAME GPU has the following requirements. There are also optional dependencies which are required for some components, such as Documentation or Python bindings. + [CMake](https://cmake.org/download/) `>= 3.18` - + CMake `>= 3.15` currently works, but support will be dropped in a future release. + [CUDA](https://developer.nvidia.com/cuda-downloads) `>= 11.0` and a [Compute Capability](https://developer.nvidia.com/cuda-gpus) `>= 3.5` NVIDIA GPU. + CUDA `>= 10.0` currently works, but support will be dropped in a future release. + C++17 capable C++ compiler (host), compatible with the installed CUDA version diff --git a/cmake/OutOfSourceOnly.cmake b/cmake/OutOfSourceOnly.cmake new file mode 100644 index 000000000..2041e4513 --- /dev/null +++ b/cmake/OutOfSourceOnly.cmake @@ -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() + diff --git a/cmake/common.cmake b/cmake/common.cmake index 65f7d08e1..3a2f8b96b 100644 --- a/cmake/common.cmake +++ b/cmake/common.cmake @@ -1,25 +1,30 @@ message(STATUS "-----Configuring Project: ${PROJECT_NAME}-----") include_guard(DIRECTORY) -if(NOT CMAKE_VERSION VERSION_LESS 3.18) - cmake_policy(SET CMP0105 NEW) # Use separate device link options -endif() + +# Policy to enable use of separate device link options, introduced in CMake 3.18 +cmake_policy(SET CMP0105 NEW) + # Add custom modules directory set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/modules/ ${CMAKE_MODULE_PATH}) +# Ensure this is not an in-source build +# This might be a little aggressive to go in comon. +include(${FLAMEGPU_ROOT}/cmake/OutOfSourceOnly.cmake) + # include CUDA_ARCH processing code. # Uses -DCUDA_ARCH values (and modifies if appropriate). -# Adds -gencode argumetns to CMAKE_CUDA_FLAGS -# Adds -DMIN_COMPUTE_CAPABILITY=VALUE macro to CMAKE_CC_FLAGS, CMAKE_CXX_FLAGS and CMAKE_CUDA_FLAGS. +# Adds -gencode argumetns to cuda compiler options +# Adds -DMIN_COMPUTE_CAPABILITY=VALUE compiler defintions for C, CXX and CUDA include(${CMAKE_CURRENT_LIST_DIR}/cuda_arch.cmake) # Ensure that other dependencies are downloaded and available. -# This could potentially go in the src cmake.list, once headers do not include third party headers. -include(${CMAKE_CURRENT_LIST_DIR}/Thrust.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/Jitify.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/Tinyxml2.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/rapidjson.cmake) +# As flamegpu is a static library, linking only only occurs at consumption not generation, so dependent targets must also know of PRIVATE shared library dependencies such as tinyxml2 and rapidjson, as well any intentionalyl public dependencies (for include dirs) +include(${CMAKE_CURRENT_LIST_DIR}/dependencies/Thrust.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/dependencies/Jitify.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/dependencies/Tinyxml2.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/dependencies/rapidjson.cmake) if(USE_GLM) -include(${CMAKE_CURRENT_LIST_DIR}/glm.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/dependencies/glm.cmake) endif() # Common rules for other cmake files @@ -36,12 +41,6 @@ mark_as_advanced(CMAKE_USE_FOLDERS) include(${CMAKE_CURRENT_LIST_DIR}/warnings.cmake) include(${CMAKE_CURRENT_LIST_DIR}/cxxstd.cmake) -# Cmake 3.16 has an issue with the order of CUDA includes when using SYSTEM for user-provided thrust. Avoid this by not using SYSTEM for cmake 3.16 -set(INCLUDE_SYSTEM_FLAG SYSTEM) -if(${CMAKE_VERSION} VERSION_GREATER "3.16" AND ${CMAKE_VERSION} VERSION_LESS "3.17") - set(INCLUDE_SYSTEM_FLAG "") -endif() - # Set a default build type if not passed get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(${GENERATOR_IS_MULTI_CONFIG}) @@ -62,59 +61,47 @@ endif() # Ask Cmake to output compile_commands.json (if supported). This is useful for vscode include paths, clang-tidy/clang-format etc set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "Control the output of compile_commands.json") -# Declare variables to track extra include dirs / link dirs / link libraries -set(FLAMEGPU_DEPENDENCY_INCLUDE_DIRECTORIES) -set(FLAMEGPU_DEPENDENCY_LINK_LIBRARIES) +# Use the FindCUDATooklit package (CMake > 3.17) to find other parts of the cuda toolkit not provided by the CMake language support +find_package(CUDAToolkit REQUIRED) -# NVRTC.lib/CUDA.lib +# Control how we link against the cuda runtime library (CMake >= 3.17) +# We may wish to use static or none instead, subject to python library handling. +set(CMAKE_CUDA_RUNTIME_LIBRARY shared) -find_package(NVRTC REQUIRED) -if(NVRTC_FOUND) - set(FLAMEGPU_DEPENDENCY_INCLUDE_DIRECTORIES ${FLAMEGPU_DEPENDENCY_INCLUDE_DIRECTORIES} "${NVRTC_INCLUDE_DIRS}") - set(FLAMEGPU_DEPENDENCY_LINK_LIBRARIES ${FLAMEGPU_DEPENDENCY_LINK_LIBRARIES} ${NVRTC_LIBRARIES}) - # Also add the driver api - set(FLAMEGPU_DEPENDENCY_LINK_LIBRARIES ${FLAMEGPU_DEPENDENCY_LINK_LIBRARIES} cuda) -else() - message("nvrtc not found @todo gracefully handle this") +# Ensure the cuda driver API is available, and save it to the list of link targets. +if(NOT TARGET CUDA::cuda_driver) + message(FATAL_ERROR "CUDA::cuda_driver is required.") endif() +# Ensure the nvrtc is available, and save it to the list of link targets. +if(NOT TARGET CUDA::nvrtc) + message(FATAL_ERROR "CUDA::nvrtc is required.") +endif() -# If NVTX is enabled, find the library and update variables accordingly. +# Ensure that jitify is available. Must be available at binary link time due to flamegpu being a static library. This check may be redundant. +if(NOT TARGET Jitify::jitify) + message(FATAL_ERROR "Jitify is a required dependency") +endif() + +# Ensure that + +# @todo - why do we not have to link against curand? Is that only required for the host API? Use CUDA::curand if required. + +# If NVTX is enabled, find the library and update variables accordingly. if(USE_NVTX) - # Find the nvtx library using custom cmake module + # Find the nvtx library using custom cmake module, providing imported targets + # Do not use CUDA::nvToolsExt as this always uses NVTX1 not 3. find_package(NVTX) - # If it was found, use it. - if(NVTX_FOUND) - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -DUSE_NVTX=${NVTX_VERSION}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_NVTX=${NVTX_VERSION}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_NVTX=${NVTX_VERSION}") - set(FLAMEGPU_DEPENDENCY_INCLUDE_DIRECTORIES ${FLAMEGPU_DEPENDENCY_INCLUDE_DIRECTORIES} "${NVTX_INCLUDE_DIRS}") - if(NVTX_VERSION VERSION_LESS "3") - set(FLAMEGPU_DEPENDENCY_LINK_LIBRARIES ${FLAMEGPU_DEPENDENCY_LINK_LIBRARIES} ${NVTX_LIBRARIES}) - endif() - else() - # If not found, disable. - message("-- NVTX not available") + # If the targets were not found, emit a warning + if(NOT TARGET NVTX::nvtx) + # If not found, emit a warning and continue without NVTX + message(WARNING "NVTX could not be found. Proceeding with USE_NVTX=OFF") if(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) SET(USE_NVTX "OFF" PARENT_SCOPE) endif() endif() endif(USE_NVTX) -# If jitify was found, add it to the include dirs. -if(Jitify_FOUND) - set(FLAMEGPU_DEPENDENCY_INCLUDE_DIRECTORIES ${FLAMEGPU_DEPENDENCY_INCLUDE_DIRECTORIES} "${Jitify_INCLUDE_DIRS}") -endif() - -# If gcc, need to add linker flag for std::experimental::filesystem pre c++17 -if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(FLAMEGPU_DEPENDENCY_LINK_LIBRARIES ${FLAMEGPU_DEPENDENCY_LINK_LIBRARIES} "-lstdc++fs") -endif() - -# Logging for jitify compilation -set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -DJITIFY_PRINT_LOG") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DJITIFY_PRINT_LOG") - # Set the minimum supported cuda version, if not already set. Currently duplicated due to docs only build logic. # CUDA 10.0 is the current minimum working but deprecated verison, which will be removed. if(NOT DEFINED MINIMUM_CUDA_VERSION) @@ -134,33 +121,6 @@ if(NOT DEFINED MINIMUM_SUPPORTED_CUDA_VERSION) endif() endif() -# Specify some additional compiler flags -# CUDA debug symbols -set(CMAKE_CUDA_FLAGS_DEBUG "${CMAKE_CUDA_FLAGS_DEBUG} -G -D_DEBUG -DDEBUG") - -# Lineinfo for non -G release -set(CMAKE_CUDA_FLAGS_RELEASE "${CMAKE_CUDA_FLAGS_RELEASE} -lineinfo") - -# Addresses a cub::histogram warning -set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --expt-relaxed-constexpr") - -# On windows, define NOMINMAX to remove the annoying defined min and max macros -if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - add_compile_definitions(NOMINMAX) -endif() - -# MSVC handling of SYSTEM for external includes. -if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.10) - # These flags don't currently have any effect on how CMake passes system-private includes to msvc (VS 2017+) - set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "/external:I") - set(CMAKE_INCLUDE_SYSTEM_FLAG_CUDA "/external:I") - # VS 2017+ - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /experimental:external") - endif() -endif() - -# Common CUDA args # Define a function to add a lint target. find_file(CPPLINT NAMES cpplint cpplint.exe) if(CPPLINT) @@ -238,8 +198,78 @@ else() endif() endif() +# Define a function which can be used to set common compiler options for a target +# We do not want to force these options on end users (although they should be used ideally), hence not just public properties on the library target +# Function to suppress compiler warnings for a given target +function(CommonCompilerSettings) + # Parse the expected arguments, prefixing variables. + cmake_parse_arguments( + CCS + "" + "TARGET" + "" + ${ARGN} + ) + + # Ensure that a target has been passed, and that it is a valid target. + if(NOT CCS_TARGET) + message( FATAL_ERROR "function(CommonCompilerSettings): 'TARGET' argument required") + elseif(NOT TARGET ${CCS_TARGET} ) + message( FATAL_ERROR "function(CommonCompilerSettings): TARGET '${CCS_TARGET}' is not a valid target") + endif() + + # Add device debugging symbols to device builds of CUDA objects + target_compile_options(${CCS_TARGET} PRIVATE "$<$,$>:-G>") + # Ensure DEBUG and _DEBUG are defined for Debug builds + target_compile_definitions(${CCS_TARGET} PRIVATE $<$,$>:DEBUG>) + target_compile_definitions(${CCS_TARGET} PRIVATE $<$,$>:_DEBUG>) + # Enable -lineinfo for Release builds, for improved profiling output. + target_compile_options(${CCS_TARGET} PRIVATE "$<$,$>:-lineinfo>") + + # Set an NVCC flag which allows host constexpr to be used on the device. + target_compile_options(${CCS_TARGET} PRIVATE "$<$:--expt-relaxed-constexpr>") + + # Prevent windows.h from defining max and min. + if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + target_compile_definitions(${CCS_TARGET} PRIVATE NOMINMAX) + endif() + + # Pass the SEATBELTS macro, which when set to off/0 (for non debug builds) removes expensive operations. + if (SEATBELTS) + # If on, all build configs have seatbelts + target_compile_definitions(${CCS_TARGET} PRIVATE SEATBELTS=1) + else() + # Id off, debug builds have seatbelts, non debug builds do not. + target_compile_definitions(${CCS_TARGET} PRIVATE $,SEATBELTS=1,SEATBELTS=0>) + endif() + + # MSVC handling of SYSTEM for external includes. + if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.10) + # These flags don't currently have any effect on how CMake passes system-private includes to msvc (VS 2017+) + set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "/external:I") + set(CMAKE_INCLUDE_SYSTEM_FLAG_CUDA "/external:I") + # VS 2017+ + target_compile_options(${CCS_TARGET} PRIVATE "$<$:/experimental:external>") + endif() + + # Enable parallel compilation + if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + target_compile_options(${CCS_TARGET} PRIVATE "$<$:SHELL:-Xcompiler /MP>") + target_compile_options(${CCS_TARGET} PRIVATE "$<$:/MP>") + 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 lead to processes being killed, or excessive memory being consumed. + if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "11.2" AND USE_NVCC_THREADS AND DEFINED NVCC_THREADS AND NVCC_THREADS GREATER_EQUAL 0) + target_compile_options(${CCS_TARGET} PRIVATE "$<$:SHELL:--threads ${NVCC_THREADS}>") + endif() + +endfunction() + # Function to mask some of the steps to create an executable which links against the static library function(add_flamegpu_executable NAME SRC FLAMEGPU_ROOT PROJECT_ROOT IS_EXAMPLE) + # @todo - correctly set PUBLIC/PRIVATE/INTERFACE for executables created with this utility function + # Parse optional arugments. cmake_parse_arguments( ADD_FLAMEGPU_EXECUTABLE @@ -268,47 +298,28 @@ function(add_flamegpu_executable NAME SRC FLAMEGPU_ROOT PROJECT_ROOT IS_EXAMPLE) add_executable(${NAME} ${SRC}) # Set target level warnings. - EnableCompilerWarnings(TARGET "${NAME}") - - # @todo - Once public/private/interface is perfected on the library, some includes may need adding back here. - - # Add extra linker targets - target_link_libraries(${NAME} ${FLAMEGPU_DEPENDENCY_LINK_LIBRARIES}) - + EnableFLAMEGPUCompilerWarnings(TARGET "${NAME}") + # Apply common compiler settings + CommonCompilerSettings(TARGET "${NAME}") + # Set the cuda gencodes, potentially using the user-provided CUDA_ARCH + SetCUDAGencodes(TARGET "${PROJECT_NAME}") + # Enable RDC for the target set_property(TARGET ${NAME} PROPERTY CUDA_SEPARABLE_COMPILATION ON) # Link against the flamegpu static library target. - if (TARGET flamegpu) - target_link_libraries(${NAME} flamegpu) - # Workaround for incremental rebuilds on MSVC, where device link was not being performed. - # https://github.com/FLAMEGPU/FLAMEGPU2/issues/483 - if(MSVC AND CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "11.1") - # Provide the absolute path to the lib file, rather than the relative version cmake provides. - target_link_libraries(${NAME} "${CMAKE_CURRENT_BINARY_DIR}/$") - endif() + target_link_libraries(${NAME} flamegpu) + # Workaround for incremental rebuilds on MSVC, where device link was not being performed. + # https://github.com/FLAMEGPU/FLAMEGPU2/issues/483 + if(MSVC AND CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "11.1") + # Provide the absolute path to the lib file, rather than the relative version cmake provides. + target_link_libraries(${NAME} "${CMAKE_CURRENT_BINARY_DIR}/$") endif() - - # Configure device link options - if(NOT CMAKE_VERSION VERSION_LESS 3.18) - if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - # Suppress Fatbinc warnings on msvc at link time. - target_link_options(${NAME} PRIVATE "$") - endif() - if(WARNINGS_AS_ERRORS) - if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - target_link_options(${NAME} PRIVATE "$") - else() - target_link_options(${NAME} PRIVATE "$") - endif() - endif() - endif() - + # Activate visualisation if requested if (VISUALISATION) - target_include_directories(${NAME} PUBLIC "${VISUALISATION_ROOT}/include") # Copy DLLs - # @todo - this would be better to be a post flamegpu2-visualiser build step, so it's only done once not N times? + # @todo clean this up. It would be much better if it were dynamic based on the visualisers's runtime dependencies too. if(WIN32) # sdl # if(NOT sdl2_FOUND) @@ -344,26 +355,8 @@ function(add_flamegpu_executable NAME SRC FLAMEGPU_ROOT PROJECT_ROOT IS_EXAMPLE) ${IL_RUNTIME_LIBRARIES} # <--this is in-file $) endif() - add_compile_definitions(VISUALISATION) - - # Make GLM accessible via include - if (USE_GLM) - if(glm_FOUND) - target_include_directories(${NAME} PUBLIC "${glm_INCLUDE_DIRS}") - else() - message(WARNING "USE_GLM enabled, but glm_FOUND is False.") - endif() - add_compile_definitions(USE_GLM) - endif() - endif() - - # Pass the SEATBELTS macro, which when set to off/0 (for non debug builds) removes expensive operations. - if (SEATBELTS) - # If on, all build configs have seatbelts - add_compile_definitions(SEATBELTS=1) - else() - # Id off, debug builds have seatbelts, non debug builds do not. - add_compile_definitions($,SEATBELTS=1,SEATBELTS=0>) + # @todo - this could be inherrited instead? + target_compile_definitions(${NAME} PRIVATE VISUALISATION) endif() # Flag the new linter target and the files to be linted, and pass optional exclusions filters (regex) @@ -398,135 +391,6 @@ function(add_flamegpu_executable NAME SRC FLAMEGPU_ROOT PROJECT_ROOT IS_EXAMPLE) endif() endfunction() -# Function to mask some of the flag setting for the static library -function(add_flamegpu_library NAME SRC FLAMEGPU_ROOT) - # Define which source files are required for the target executable - add_library(${NAME} STATIC ${SRC}) - - # Set target level warnings. - EnableCompilerWarnings(TARGET "${NAME}") - - # enable "fpic" for linux to allow shared libraries to be build from the static library (required for swig) - set_property(TARGET ${NAME} PROPERTY POSITION_INDEPENDENT_CODE ON) - - # Activate visualisation if requested - if (VISUALISATION) - target_include_directories(${NAME} PRIVATE "${VISUALISATION_ROOT}/include") - target_link_libraries(${NAME} flamegpu_visualiser) - CMAKE_SET_TARGET_FOLDER(flamegpu_visualiser "FLAMEGPU") - add_compile_definitions(VISUALISATION) - # set(SDL2_DIR ${VISUALISATION_BUILD}/sdl2) - # find_package(SDL2 REQUIRED) - - # Make the visualisers GLM accessible via include - if (USE_GLM) - if(glm_FOUND) - target_include_directories(${NAME} PUBLIC "${glm_INCLUDE_DIRS}") - add_compile_definitions(GLM_PATH="${glm_INCLUDE_DIRS}") - else() - message(WARNING "USE_GLM enabled, but glm_FOUND is False.") - endif() - add_compile_definitions(USE_GLM) - endif() - endif() - - # Pass the SEATBELTS macro, which when set to off/0 (for non debug builds) removes expensive operations. - if (SEATBELTS) - # If on, all build configs have seatbelts - add_compile_definitions(SEATBELTS=1) - else() - # Id off, debug builds have seatbelts, non debug builds do not. - add_compile_definitions($,SEATBELTS=1,SEATBELTS=0>) - endif() - - if (NOT RTC_DISK_CACHE) - add_compile_definitions(DISABLE_RTC_DISK_CACHE) - endif() - if (EXPORT_RTC_SOURCES) - add_compile_definitions(OUTPUT_RTC_DYNAMIC_FILES) - endif () - - # Enable RDC - set_property(TARGET ${NAME} PROPERTY CUDA_SEPARABLE_COMPILATION ON) - - # Link against dependency targets / directories. - - # Linux / not windows has -isystem for suppressing warnings from "system" libraries - ie exeternal dependencies such as thrust. - if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - # CUB (and thrust) cause many compiler warnings at high levels, including Wreorder. - # CUB:CUB does not use -isystem to prevent the automatic -I/include from being more important, and the CUDA disributed CUB being used. - # Instead, if possible we pass the include directory directly rather than using the imported target. - # And also pass {CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}/../include" as isystem so the include order is correct for isystem to work (a workaround for a workaround). The `../` is required to prevent cmake from removing the duplicate path. - - # Include CUB via isystem if possible (via _CUB_INCLUDE_DIR which may be subject to change), otherwise use it via target_link_libraries. - if(DEFINED _CUB_INCLUDE_DIR) - target_include_directories(${NAME} ${INCLUDE_SYSTEM_FLAG} PUBLIC "${_CUB_INCLUDE_DIR}") - else() - target_link_libraries(${NAME} CUB::CUB) - endif() - target_include_directories(${NAME} ${INCLUDE_SYSTEM_FLAG} PUBLIC "${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}/../include") - else() - # MSVC just includes cub via the CUB::CUB target as no isystem to worry about. - target_link_libraries(${NAME} CUB::CUB) - # Same for Thrust. - # Visual studio 2015 needs to suppress deprecation messages from CUB/Thrust. - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10) - target_compile_definitions(${NAME} PUBLIC "CUB_IGNORE_DEPRECATED_CPP_DIALECT") - target_compile_definitions(${NAME} PUBLIC "THRUST_IGNORE_DEPRECATED_CPP_DIALECT") - endif() - endif() - - # Compiler flags which we do not want to be set to all targets - # GNU specific flags. - # @todo - make this not just applied to the library, but also executables. - # @todo - currently disabled as tinyxml2 include is not marked as system (because it's inherrited via properties on the imported target). Might require https://gitlab.kitware.com/cmake/cmake/-/issues/18040 to be implemented to actually achieve this. - # if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - # target_compile_options(${NAME} PRIVATE -Wsuggest-override) - # set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler -Wsuggest-override") - # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-override") - # set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wsuggest-override") - # endif() - - # Thrust uses isystem if available - target_link_libraries(${NAME} Thrust::Thrust) - - # tinyxml2 static library - target_link_libraries(${NAME} tinyxml2) - - # If rapidjson was found, add it to the include dirs. - if(RapidJSON_FOUND) - target_include_directories(${NAME} ${INCLUDE_SYSTEM_FLAG} PRIVATE "${RapidJSON_INCLUDE_DIRS}") - endif() - - # Add extra includes (jitify, nvtx, nvrtc etc.) @todo improve this. - target_include_directories(${NAME} ${INCLUDE_SYSTEM_FLAG} PUBLIC ${FLAMEGPU_DEPENDENCY_INCLUDE_DIRECTORIES}) - - # Add the library headers as public so they are forwarded on. - target_include_directories(${NAME} PUBLIC "${FLAMEGPU_ROOT}/include") - # Add any private headers. - target_include_directories(${NAME} PRIVATE "${FLAMEGPU_ROOT}/src") - - # Add extra linker targets - target_link_libraries(${NAME} ${FLAMEGPU_DEPENDENCY_LINK_LIBRARIES}) - - # Flag the new linter target and the files to be linted. - new_linter_target(${NAME} "${SRC}") - - # Put within FLAMEGPU filter - CMAKE_SET_TARGET_FOLDER(${NAME} "FLAMEGPU") - # Put the tinyxml2 in the folder - CMAKE_SET_TARGET_FOLDER("tinyxml2" "FLAMEGPU/Dependencies") - - # Emit some warnings that should only be issued once and are related to this file (but not this target) - if(MSVC AND CMAKE_CUDA_COMPILER_VERSION VERSION_LESS_EQUAL "10.2") - message(AUTHOR_WARNING "MSVC and NVCC <= 10.2 may encounter compiler errors due to an NVCC bug exposed by Thrust. Cosider using a newer CUDA toolkit.") - endif() - if(MSVC AND CMAKE_CUDA_COMPILER_VERSION VERSION_LESS_EQUAL "11.0") - # https://github.com/FLAMEGPU/FLAMEGPU2/issues/483 - message(AUTHOR_WARNING "MSVC and NVCC <= 11.0 may encounter errors at link time with incremental rebuilds. Cosider using a newer CUDA toolkit.") - endif() -endfunction() - #----------------------------------------------------------------------- # a macro that only sets the FOLDER target property if it's # "appropriate" diff --git a/cmake/cuda_arch.cmake b/cmake/cuda_arch.cmake index fdbdbf496..482a1ac1b 100644 --- a/cmake/cuda_arch.cmake +++ b/cmake/cuda_arch.cmake @@ -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 "$<$:SHELL:-gencode arch=compute_${ARCH}$code=sm_${ARCH}>") + target_link_options(${SCG_TARGET} PRIVATE "$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 "$<$:SHELL:-gencode arch=compute_${LAST_ARCH}$code=compute_${LAST_ARCH}>") + target_link_options(${SCG_TARGET} PRIVATE "$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() diff --git a/cmake/cxxstd.cmake b/cmake/cxxstd.cmake index 5888233f6..19ca287a1 100644 --- a/cmake/cxxstd.cmake +++ b/cmake/cxxstd.cmake @@ -3,17 +3,10 @@ if(NOT FLAMEGPU_CXX_STD) # FLAME GPU is c++14, however due to MSVC 16.10 regressions we build as 17 if possible, else 14. # 14 Support is still required (CUDA 10.x, swig?). # Start by assuming both should be availble. + # No need to check CMake version, as our minimum (3.18) supports CUDA c++17 set(CXX17_SUPPORTED ON) - # CMake 3.18 adds CUDA CXX 17, 20 - # CMake 3.10 adds CUDA CXX 14 - if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.18) - # 17 OK - elseif(CMAKE_VERSION VERSION_GREATER_EQUAL 3.10) - # No need for deprecation warning here, already warning about CMAKE < 3.18 being deprecated elsewhere. - set(CXX17_SUPPORTED OFF) - else() - message(FATAL_ERROR "CMAKE ${CMAKE_VERSION} does not support -std=c++14") - endif() + + # Check the CU # CUDA 11.0 adds CXX 17 # CUDA 9.0 adds CXX 14 if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0.0) @@ -34,7 +27,7 @@ if(NOT FLAMEGPU_CXX_STD) if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29) # 17 required. if(NOT CXX17_SUPPORTED) - message(FATAL_ERROR "MSVC >= 19.29 requires CMake >= 3.18 and CUDA >= 11.0") + message(FATAL_ERROR "MSVC >= 19.29 requires CUDA >= 11.0") endif() elseif(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.11) # 17 available? diff --git a/cmake/Jitify.cmake b/cmake/dependencies/Jitify.cmake similarity index 81% rename from cmake/Jitify.cmake rename to cmake/dependencies/Jitify.cmake index 375a99131..30a665525 100644 --- a/cmake/Jitify.cmake +++ b/cmake/dependencies/Jitify.cmake @@ -19,7 +19,8 @@ FetchContent_GetProperties(jitify) if(NOT jitify_POPULATED) FetchContent_Populate(jitify) # Jitify is not a cmake project, so cannot use add_subdirectory, use custom find_package. - set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};${jitify_SOURCE_DIR}/..") - find_package(Jitify REQUIRED) - # Include path is ${Jitify_INCLUDE_DIRS} endif() + +set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};${jitify_SOURCE_DIR}/..") +# Always find the package, even if jitify is already populated. +find_package(Jitify REQUIRED) diff --git a/cmake/Thrust.cmake b/cmake/dependencies/Thrust.cmake similarity index 100% rename from cmake/Thrust.cmake rename to cmake/dependencies/Thrust.cmake diff --git a/cmake/Tinyxml2.cmake b/cmake/dependencies/Tinyxml2.cmake similarity index 66% rename from cmake/Tinyxml2.cmake rename to cmake/dependencies/Tinyxml2.cmake index 867e03f18..7382f8260 100644 --- a/cmake/Tinyxml2.cmake +++ b/cmake/dependencies/Tinyxml2.cmake @@ -11,23 +11,26 @@ cmake_policy(SET CMP0079 NEW) FetchContent_Declare( tinyxml2 GIT_REPOSITORY https://github.com/leethomason/tinyxml2.git - GIT_TAG 8.0.0 + GIT_TAG 9.0.0 GIT_SHALLOW 1 SOURCE_DIR ${FETCHCONTENT_BASE_DIR}/tinyxml2-src/tinyxml2 GIT_PROGRESS ON # UPDATE_DISCONNECTED ON ) +# @todo - try finding the pacakge first, assuming it sets system correctly when used. FetchContent_GetProperties(tinyxml2) if(NOT tinyxml2_POPULATED) FetchContent_Populate(tinyxml2) - # when adding via subdirectory tinyxml2 target doesn't seem to forward includes - # Which is super annoying. + # The Tinxyxml2 repository does not include tinyxml2.h in a subdirectory, so include "tinyxml2.h" would be used not "tinyxml2/tinyxml2.h" + # To avoid this, do not use add_subdirectory, instead create our own cmake target for tinyxml2. + # @todo - a possible alternative (from tinyxml2 9.0.0?) might be to run the install target of tinyxml2, and then use find package in config mode. Would require investigation. + # Disabled: # get_filename_component(FLAMEGPU_ROOT ${CMAKE_CURRENT_LIST_DIR}/../ REALPATH) # add_subdirectory(${tinyxml2_SOURCE_DIR} ${tinyxml2_BINARY_DIR}) - # Instead, build our own version. This is quite grim but better than the alternative? + # If the target does not already exist, add it. # @todo - make this far more robust. if(NOT TARGET tinyxml2) # @todo - make a dynamically generated CMakeLists.txt which can be add_subdirectory'd instead, so that the .vcxproj goes in a folder. Just adding a project doesn't work. @@ -48,11 +51,11 @@ if(NOT tinyxml2_POPULATED) # Pic is sensible for any library set_property(TARGET tinyxml2 PROPERTY POSITION_INDEPENDENT_CODE ON) - # Specify the interface headers library, to be forwarded. - # For our use case, this is up a folder so we can use tinyxml2/tinyxml2.h as the include. - # Find the resolved abs path to this. + # Specify the include directory, to be forwared to targets which link against the tinyxml2 target. + # Mark this as SYSTEM INTERFACE, so that it does not result in compiler warnings being generated for dependent projects. + # For our use case, this is up a folder so we can use tinyxml2/tinyxml2.h as the include, by resolving the relative path to get an abs path get_filename_component(tinyxml2_inc_dir ${tinyxml2_SOURCE_DIR}/../ REALPATH) - target_include_directories(tinyxml2 INTERFACE ${tinyxml2_inc_dir}) + target_include_directories(tinyxml2 SYSTEM INTERFACE ${tinyxml2_inc_dir}) # Add some compile time definitions target_compile_definitions(tinyxml2 INTERFACE $<$:TINYXML2_DEBUG>) @@ -64,7 +67,11 @@ if(NOT tinyxml2_POPULATED) endif(MSVC) # Suppress warnigns from this target. - include(${CMAKE_CURRENT_LIST_DIR}/warnings.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/../warnings.cmake) DisableCompilerWarnings(TARGET tinyxml2) + + # Create an alias target for tinyxml2 to namespace it / make it more like other modern cmake + add_library(Tinyxml2::tinyxml2 ALIAS tinyxml2) + endif() endif() diff --git a/cmake/doxygen.cmake b/cmake/dependencies/doxygen.cmake similarity index 100% rename from cmake/doxygen.cmake rename to cmake/dependencies/doxygen.cmake diff --git a/cmake/flamegpu2-visualiser.cmake b/cmake/dependencies/flamegpu2-visualiser.cmake similarity index 100% rename from cmake/flamegpu2-visualiser.cmake rename to cmake/dependencies/flamegpu2-visualiser.cmake diff --git a/cmake/glm.cmake b/cmake/dependencies/glm.cmake similarity index 100% rename from cmake/glm.cmake rename to cmake/dependencies/glm.cmake diff --git a/cmake/googletest.cmake b/cmake/dependencies/googletest.cmake similarity index 95% rename from cmake/googletest.cmake rename to cmake/dependencies/googletest.cmake index 9f8c24f6a..89e454fe8 100644 --- a/cmake/googletest.cmake +++ b/cmake/dependencies/googletest.cmake @@ -26,7 +26,7 @@ if(NOT googletest_POPULATED) add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL) CMAKE_SET_TARGET_FOLDER("gtest" "Tests/Dependencies") # Suppress warnigns from this target. - include(${CMAKE_CURRENT_LIST_DIR}/warnings.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/../warnings.cmake) if(TARGET gtest) DisableCompilerWarnings(TARGET gtest) endif() diff --git a/cmake/rapidjson.cmake b/cmake/dependencies/rapidjson.cmake similarity index 89% rename from cmake/rapidjson.cmake rename to cmake/dependencies/rapidjson.cmake index a19942a4b..579ec1b19 100644 --- a/cmake/rapidjson.cmake +++ b/cmake/dependencies/rapidjson.cmake @@ -27,4 +27,10 @@ if(NOT rapidjson_POPULATED) set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};${rapidjson_SOURCE_DIR}") find_package(RapidJSON REQUIRED) # Include path is ${RapidJSON_INCLUDE_DIRS} + + # Create a namespaced alias target + if(TARGET rapidjson) + add_library(RapidJSON::rapidjson ALIAS rapidjson) + endif() + endif() diff --git a/cmake/modules/FindJitify.cmake b/cmake/modules/FindJitify.cmake index effc7ffd1..2f3cc3952 100644 --- a/cmake/modules/FindJitify.cmake +++ b/cmake/modules/FindJitify.cmake @@ -37,5 +37,9 @@ find_package_handle_standard_args(Jitify VERSION_VAR Jitify_VERSION ) +# Create a header only (INTERFACE) target which can be linked against to upadte include directories. Mark as IMPORTED as there are no build steps. +add_library(Jitify::jitify INTERFACE IMPORTED) +target_include_directories(Jitify::jitify INTERFACE ${Jitify_INCLUDE_DIRS}) + # Set returned values as advanced? mark_as_advanced(Jitify_INCLUDE_DIRS Jitify_VERSION) diff --git a/cmake/modules/FindNVRTC.cmake b/cmake/modules/FindNVRTC.cmake deleted file mode 100644 index 1b8434989..000000000 --- a/cmake/modules/FindNVRTC.cmake +++ /dev/null @@ -1,56 +0,0 @@ -# CMake module to find NVRTC headers/library -# This is currently quite simple, could be expanded to support user-provided hinting? -# Usage: -# find_package( NVRTC ) -# if(NVRTC_FOUND) -# include_directories(${NVRTC_INCLUDE_DIRS}) -# target_link_libraries(target ${NVRTC_LIBRARIES}) -# endif() -# -# Variables: -# NVRTC_FOUND -# NVRTC_INCLUDE_DIRS -# NVRTC_LIBRARIES -# -# Manually specify NVRTC paths via -DNVRTC_ROOT=/path/to/cuda/install/location - -# CMake Native CUDA support doesn't provide the raw directory, only include -# Note that CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES and CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES are not set for visual studio generators for CMAKE < 3.17, so this relies on searching the users HINTS/PATH. - -# Search Path heirarchy order is _ROOT > NVRTC_INCLUDE_DIRS / NVRTC_LIBRARIES > cmake environment variables > HINTS > system environment variables > platform files for current system > PATHS - -# Attempt to find nvToolsExt.h containing directory -find_path(NVRTC_INCLUDE_DIRS - NAMES - nvrtc.h - HINTS - ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES} - PATHS - ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES} - PATH_SUFFIXES - include - ) - -# Find the directory containing the dynamic library -find_library(NVRTC_LIBRARIES - NAMES - libnvrtc.so - nvrtc - nvrtc.lib - HINTS - ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES} - PATHS - ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES} - PATH_SUFFIXES - lib - lib64 - lib/Win32 - lib/x64 -) - -# Apply standard cmake find package rules / variables. I.e. QUIET, NVRTC_FOUND etc. -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(NVRTC DEFAULT_MSG NVRTC_INCLUDE_DIRS NVRTC_LIBRARIES) - -# Set returned values as advanced? -mark_as_advanced(NVRTC_INCLUDE_DIRS NVRTC_LIBRARIES) diff --git a/cmake/modules/FindNVTX.cmake b/cmake/modules/FindNVTX.cmake index 94c0a1ec6..01b8a57ce 100644 --- a/cmake/modules/FindNVTX.cmake +++ b/cmake/modules/FindNVTX.cmake @@ -51,8 +51,16 @@ if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "10.0") REQUIRED_VARS NVTX_INCLUDE_DIRS VERSION_VAR NVTX_VERSION ) + + if(NVTX_FOUND) + # Create a header only (INTERFACE) target which can be linked against to inherit include directories. Mark this as imported, because there are no build steps requred. + add_library(NVTX::nvtx3 INTERFACE IMPORTED) + target_include_directories(NVTX::nvtx3 INTERFACE ${NVTX_INCLUDE_DIRS}) + set_property(TARGET NVTX::nvtx3 PROPERTY VERSION ${NVTX_VERSION}) + endif() endif() +# @todo - find both if possible, so both targets are avialable? # If not yet aware of NVTX, or we found V1/2 while looking for V3, make sure we find the actual V1/2 if(NOT NVTX_FOUND OR NVTX_VERSION VERSION_LESS 3) # Find the header file @@ -91,7 +99,21 @@ if(NOT NVTX_FOUND OR NVTX_VERSION VERSION_LESS 3) REQUIRED_VARS NVTX_INCLUDE_DIRS VERSION_VAR NVTX_VERSION ) + + if(NVTX_FOUND) + # Create an imported target which can be linked against to inherit include directories and the shared object(s). Mark this as imported, because there are no build steps requred. + add_library(NVTX::nvtx1 SHARED IMPORTED) + target_include_directories(NVTX::nvtx1 INTERFACE ${NVTX_INCLUDE_DIRS}) + target_include_directories(NVTX::nvtx1 INTERFACE ${NVTX_LIBRARIES}) + set_property(TARGET NVTX::nvtx1 PROPERTY VERSION ${NVTX_VERSION}) + endif() endif() +# Create an alias target which will alias nvtx3 if available, otherwise nvtx1 +if(TARGET NVTX::nvtx3) + add_library(NVTX::nvtx ALIAS NVTX::nvtx3) +elseif(TARGET NVTX::nvtx1) + add_library(NVTX::nvtx ALIAS NVTX::nvtx1) +endif() # Set returned values as advanced? mark_as_advanced(NVTX_INCLUDE_DIRS NVTX_LIBRARIES NVTX_VERSION) diff --git a/cmake/modules/Findglm.cmake b/cmake/modules/Findglm.cmake index cd4b90ddc..81407f83e 100644 --- a/cmake/modules/Findglm.cmake +++ b/cmake/modules/Findglm.cmake @@ -34,6 +34,10 @@ find_package_handle_standard_args(glm REQUIRED_VARS glm_INCLUDE_DIRS VERSION_VAR glm_VERSION ) - +if(NOT TARGET GLM::glm) + # Create a header only (INTERFACE) target which can be linked against to inherit include directories. Mark this as imported, because there are no build steps requred. + add_library(GLM::glm INTERFACE IMPORTED) + target_include_directories(GLM::glm INTERFACE ${glm_INCLUDE_DIRS}) +endif() # Set returned values as advanced? mark_as_advanced(glm_INCLUDE_DIRS glm_VERSION) diff --git a/cmake/version.cmake b/cmake/version.cmake index 6fa390212..e7a510ada 100644 --- a/cmake/version.cmake +++ b/cmake/version.cmake @@ -103,15 +103,10 @@ endif() # Local python version identifiers are: [+] # Optionally (default on) embed the cuda version in the local version number, to differentiate wheels based on python version. set(FLAMEGPU_VERSION_PYTHON_LOCAL "${FLAMEGPU_VERSION_PYTHON_PUBLIC}") -# Find and attach the `cudaXY` to the local python version number -# @todo - if FindCUDAToolkit is used, this could be massively simplified. -string(REPLACE "." ";" CUDA_VERSION_LIST ${CMAKE_CUDA_COMPILER_VERSION}) -list(GET CUDA_VERSION_LIST 0 CUDA_VERSION_MAJOR) -list(GET CUDA_VERSION_LIST 1 CUDA_VERSION_MINOR) -set(FLAMEGPU_VERSION_PYTHON_LOCAL_SUFFIX "cuda${CUDA_VERSION_MAJOR}${CUDA_VERSION_MINOR}") -unset(CUDA_VERSION_LIST) -unset(CUDA_VERSION_MAJOR) -unset(CUDA_VERSION_MINOR) +# Find and attach the `cudaXY` to the local python version number, if we know what it should be. +if(CUDAToolkit_FOUND) + set(FLAMEGPU_VERSION_PYTHON_LOCAL_SUFFIX "cuda${CUDAToolkit_VERSION_MAJOR}${CUDAToolkit_VERSION_MINOR}") +endif() if(NOT FLAMEGPU_VERSION_PYTHON_LOCAL_SUFFIX STREQUAL "") set(FLAMEGPU_VERSION_PYTHON_LOCAL "${FLAMEGPU_VERSION_PYTHON_LOCAL}+${FLAMEGPU_VERSION_PYTHON_LOCAL_SUFFIX}") endif() diff --git a/cmake/warnings.cmake b/cmake/warnings.cmake index b3714d0ad..d9aa5b42a 100644 --- a/cmake/warnings.cmake +++ b/cmake/warnings.cmake @@ -1,110 +1,197 @@ -# Function to suppress compiler warnings for a given target +# Function to disable all (as many as possible) compiler warnings for a given target function(DisableCompilerWarnings) # Parse the expected arguments, prefixing variables. cmake_parse_arguments( - DISABLE_COMPILER_WARNINGS + DCW "" "TARGET" "" ${ARGN} ) # Ensure that a target has been passed, and that it is a valid target. - if(NOT DISABLE_COMPILER_WARNINGS_TARGET) - message( FATAL_ERROR "DisableCompilerWarnings: 'TARGET' argument required." ) - elseif(NOT TARGET ${DISABLE_COMPILER_WARNINGS_TARGET} ) - message( FATAL_ERROR "DisableCompilerWarnings: TARGET '${DISABLE_COMPILER_WARNINGS_TARGET}' is not a valid target" ) + if(NOT DCW_TARGET) + message(FATAL_ERROR "DisableCompilerWarnings: 'TARGET' argument required.") + elseif(NOT TARGET ${DCW_TARGET}) + message(FATAL_ERROR "DisableCompilerWarnings: TARGET '${DCW_TARGET}' is not a valid target") endif() # By default, suppress all warnings, so that warnings are applied per-target. if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - target_compile_options(${DISABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:/W0>") + target_compile_options(${DCW_TARGET} PRIVATE "$<$:/W0>") else() - target_compile_options(${DISABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:-w>") + target_compile_options(${DCW_TARGET} PRIVATE "$<$:-w>") endif() # Always tell nvcc to disable warnings - target_compile_options(${DISABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:-w>") + target_compile_options(${DCW_TARGET} PRIVATE "$<$:-w>") endfunction() -# Define a function which applies warning flags to a given target. -# Also enables the treating of warnings as errors if required. -function(EnableCompilerWarnings) + +# Function to set a high level of compiler warnings for a target +# Function to disable all (as many as possible) compiler warnings for a given target +function(SetHighWarningLevel) # Parse the expected arguments, prefixing variables. cmake_parse_arguments( - ENABLE_COMPILER_WARNINGS + SHWL "" "TARGET" "" ${ARGN} ) # Ensure that a target has been passed, and that it is a valid target. - if(NOT ENABLE_COMPILER_WARNINGS_TARGET) - message( FATAL_ERROR "EnableCompilerWarnings: 'TARGET' argument required." ) - elseif(NOT TARGET ${ENABLE_COMPILER_WARNINGS_TARGET} ) - message( FATAL_ERROR "EnableCompilerWarnings: TARGET '${ENABLE_COMPILER_WARNINGS_TARGET}' is not a valid target" ) + if(NOT SHWL_TARGET) + message(FATAL_ERROR "SetHighWarningLevel: 'TARGET' argument required.") + elseif(NOT TARGET ${SHWL_TARGET}) + message(FATAL_ERROR "SetHighWarningLevel: TARGET '${SHWL_TARGET}' is not a valid target") endif() - # Host Compiler version specific high warnings + + # Per host-compiler settings for high warning levels and opt-in warnings. if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") # Only set W4 for MSVC, WAll is more like Wall, Wextra and Wpedantic - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:SHELL:-Xcompiler /W4>") - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:/W4>") - # Also suppress some unwanted W4 warnings + target_compile_options(${SHWL_TARGET} PRIVATE "$<$:SHELL:-Xcompiler /W4>") + target_compile_options(${SHWL_TARGET} PRIVATE "$<$:/W4>") + else() + # Assume using GCC/Clang which Wall is relatively sane for. + target_compile_options(${SHWL_TARGET} PRIVATE "$<$:SHELL:-Xcompiler -Wall$-Wsign-compare>") + target_compile_options(${SHWL_TARGET} PRIVATE "$<$:-Wall>") + target_compile_options(${SHWL_TARGET} PRIVATE "$<$:-Wsign-compare>") + # CUB 1.9.10 prevents Wreorder being usable on windows, so linux only. Cannot suppress via diag_suppress pragmas. + target_compile_options(${SHWL_TARGET} PRIVATE "$<$:SHELL:--Wreorder>") + # Add warnings which suggest the use of override + target_compile_options(${SHWL_TARGET} PRIVATE "$<$:SHELL:-Xcompiler -Wsuggest-override>") + target_compile_options(${SHWL_TARGET} PRIVATE "$<$:-Wsuggest-override>") + endif() + # Generic options regardless of platform/host compiler: + # Ensure NVCC outputs warning numbers + target_compile_options(${SHWL_TARGET} PRIVATE "$<$:SHELL:-Xcudafe --display_error_number>") +endfunction() + +# Function to apply warning suppressions to a given target, without changing the general warning level (This is so SWIG can have suppressions, with default warning levels) +function(SuppressSomeCompilerWarnings) + # Parse the expected arguments, prefixing variables. + cmake_parse_arguments( + SSCW + "" + "TARGET" + "" + ${ARGN} + ) + # Ensure that a target has been passed, and that it is a valid target. + if(NOT SSCW_TARGET) + message(FATAL_ERROR "SuppressSomeCompilerWarnings: 'TARGET' argument required.") + elseif(NOT TARGET ${SSCW_TARGET}) + message(FATAL_ERROR "SuppressSomeCompilerWarnings: TARGET '${SSCW_TARGET}' is not a valid target") + endif() + + # Per host-compiler/OS settings for suppressions + if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") # decorated name length exceeded, name was truncated - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:SHELL:-Xcompiler /wd4503>") - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:/wd4503>") + target_compile_options(${SSCW_TARGET} PRIVATE "$<$:SHELL:-Xcompiler /wd4503>") + target_compile_options(${SSCW_TARGET} PRIVATE "$<$:/wd4503>") # 'function' : unreferenced local function has been removed - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:SHELL:-Xcompiler /wd4505>") - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:/wd4505>") + target_compile_options(${SSCW_TARGET} PRIVATE "$<$:SHELL:-Xcompiler /wd4505>") + target_compile_options(${SSCW_TARGET} PRIVATE "$<$:/wd4505>") # unreferenced formal parameter warnings disabled - tests make use of it. - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:SHELL:-Xcompiler /wd4100>") - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:/wd4100>") + target_compile_options(${SSCW_TARGET} PRIVATE "$<$:SHELL:-Xcompiler /wd4100>") + target_compile_options(${SSCW_TARGET} PRIVATE "$<$:/wd4100>") # C4127: conditional expression is constant. Longer term true static assertions would be better. - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:SHELL:-Xcompiler /wd4127>") - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:/wd4127>") + target_compile_options(${SSCW_TARGET} PRIVATE "$<$:SHELL:-Xcompiler /wd4127>") + target_compile_options(${SSCW_TARGET} PRIVATE "$<$:/wd4127>") # Suppress some VS2015 specific warnings. if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10) - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:SHELL:-Xcompiler /wd4091>") - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:/wd4091>") + target_compile_options(${SSCW_TARGET} PRIVATE "$<$:SHELL:-Xcompiler /wd4091>") + target_compile_options(${SSCW_TARGET} PRIVATE "$<$:/wd4091>") endif() + # Suppress Fatbinc warnings on msvc at link time (CMake >= 3.18) + target_link_options(${SSCW_TARGET} PRIVATE "$") else() - # Assume using GCC/Clang which Wall is relatively sane for. - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:SHELL:-Xcompiler -Wall$-Wsign-compare>") - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:-Wall>") - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:-Wsign-compare>") - # CUB 1.9.10 prevents Wreorder being usable on windows. Cannot suppress via diag_suppress pragmas. - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:SHELL:--Wreorder>") + # Linux specific warning suppressions + endif() + # Generic OS/host compiler warning suppressions + # Ensure NVCC outputs warning numbers + target_compile_options(${SSCW_TARGET} PRIVATE "$<$:SHELL:-Xcudafe --display_error_number>") + # Suppress deprecated compute capability warnings. + target_compile_options(${SSCW_TARGET} PRIVATE "$<$:-Wno-deprecated-gpu-targets>") + target_link_options(${SSCW_TARGET} PRIVATE "$") + # Supress CUDA 11.3 specific warnings, which are host compiler agnostic. + if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.3.0) + # Suppress 117-D, declared_but_not_referenced + target_compile_options(${SSCW_TARGET} PRIVATE "$<$:SHELL:-Xcudafe --diag_suppress=declared_but_not_referenced>") endif() - # Promote warnings to errors if requested + # Suppress nodiscard warnings from the cuda frontend + target_compile_options(${SSCW_TARGET} PRIVATE "$<$:SHELL:-Xcudafe --diag_suppress=2809>") +endfunction() + +# Function to promote warnings to errors, controlled by the WARNINGS_AS_ERRORS CMake option. +function(EnableWarningsAsErrors) + # Parse the expected arguments, prefixing variables. + cmake_parse_arguments( + EWAS + "" + "TARGET" + "" + ${ARGN} + ) + # Ensure that a target has been passed, and that it is a valid target. + if(NOT EWAS_TARGET) + message(FATAL_ERROR "EnableWarningsAsErrors: 'TARGET' argument required.") + elseif(NOT TARGET ${EWAS_TARGET}) + message(FATAL_ERROR "EnableWarningsAsErrors: TARGET '${EWAS_TARGET}' is not a valid target") + endif() + + # Check the WARNINGS_AS_ERRORS cmake option to optionally enable this. if(WARNINGS_AS_ERRORS) # OS Specific flags if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:SHELL:-Xcompiler /WX>") - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:/WX>") + # Windows specific options + target_compile_options(${EWAS_TARGET} PRIVATE "$<$:SHELL:-Xcompiler /WX>") + target_compile_options(${EWAS_TARGET} PRIVATE "$<$:/WX>") + # Device link warnings as errors, CMake 3.18+ + target_link_options(${EWAS_TARGET} PRIVATE "$") else() - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:SHELL:-Xcompiler -Werror>") - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:-Werror>") + # Linux specific options + target_compile_options(${EWAS_TARGET} PRIVATE "$<$:SHELL:-Xcompiler -Werror>") + target_compile_options(${EWAS_TARGET} PRIVATE "$<$:-Werror>") + # Device link warnings as errors, CMake 3.18+ + target_link_options(${EWAS_TARGET} PRIVATE "$") + # Add cross-execution-space-call. This is blocked under msvc by a jitify related bug (untested > CUDA 10.1): https://github.com/NVIDIA/jitify/issues/62 + target_compile_options(${EWAS_TARGET} PRIVATE "$<$:SHELL:-Werror cross-execution-space-call>") + # Add reorder to Werror. This is blocked under msvc by cub/thrust and the lack of isystem on msvc. Appears unable to suppress the warning via diag_suppress pragmas. + target_compile_options(${EWAS_TARGET} PRIVATE "$<$:SHELL:-Werror reorder>") endif() + # Platform/host-compiler indifferent options: # Generic WError settings for nvcc - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:SHELL:-Xptxas=\"-Werror\" -Xnvlink=\"-Werror\">") + target_compile_options(${EWAS_TARGET} PRIVATE "$<$:SHELL:-Xptxas=\"-Werror\" -Xnvlink=\"-Werror\">") # If CUDA 10.2+, add all_warnings to the Werror option if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "10.2") - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:SHELL:-Werror all-warnings>") + target_compile_options(${EWAS_TARGET} PRIVATE "$<$:SHELL:-Werror all-warnings>") endif() - # If not msvc, add cross-execution-space-call. This is blocked under msvc by a jitify related bug (untested > CUDA 10.1): https://github.com/NVIDIA/jitify/issues/62 - if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:SHELL:-Werror cross-execution-space-call >") - endif() - # If not msvc, add reorder to Werror. This is blocked under msvc by cub/thrust and the lack of isystem on msvc. Appears unable to suppress the warning via diag_suppress pragmas. - if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:SHELL:-Werror reorder >") - endif() - endif() - # Ask the cuda frontend to include warnings numbers, so they can be targetted for suppression. - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:SHELL:-Xcudafe --display_error_number>") - # Suppress nodiscard warnings from the cuda frontend - if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:SHELL:-Xcudafe --diag_suppress=2809>") endif() - # Supress CUDA 11.3 specific warnings. - if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.3.0) - # Suppress 117-D, declared_but_not_referenced - target_compile_options(${ENABLE_COMPILER_WARNINGS_TARGET} PRIVATE "$<$:SHELL:-Xcudafe --diag_suppress=declared_but_not_referenced>") +endfunction() + + +# Define a function which sets our preffered warning options for a target: +# + A high warning level +# + With some warnings suppressed +# + Optionally promotes warnings to errors. +# Also enables the treating of warnings as errors if required. +function(EnableFLAMEGPUCompilerWarnings) + # Parse the expected arguments, prefixing variables. + cmake_parse_arguments( + EFCW + "" + "TARGET" + "" + ${ARGN} + ) + # Ensure that a target has been passed, and that it is a valid target. + if(NOT EFCW_TARGET) + message(FATAL_ERROR "EnableFLAMEGPUCompilerWarnings: 'TARGET' argument required.") + elseif(NOT TARGET ${EFCW_TARGET}) + message(FATAL_ERROR "EnableFLAMEGPUCompilerWarnings: TARGET '${EFCW_TARGET}' is not a valid target") endif() + + # Enable a high level of warnings + SetHighWarningLevel(TARGET ${EFCW_TARGET}) + # Suppress some warnings + SuppressSomeCompilerWarnings(TARGET ${EFCW_TARGET}) + # Optionally promote warnings to errors. + EnableWarningsAsErrors(TARGET ${EFCW_TARGET}) endfunction() \ No newline at end of file diff --git a/examples/boids_bruteforce/CMakeLists.txt b/examples/boids_bruteforce/CMakeLists.txt index 525b38c46..2981f3ecb 100644 --- a/examples/boids_bruteforce/CMakeLists.txt +++ b/examples/boids_bruteforce/CMakeLists.txt @@ -1,5 +1,5 @@ -# CMake 3.15+ for Thrust/Cub support -cmake_minimum_required(VERSION VERSION 3.15 FATAL_ERROR) +# Minimum CMake version 3.18 for CUDA --std=c++17 +cmake_minimum_required(VERSION VERSION 3.18 FATAL_ERROR) # Name the project and set languages project(boids_bruteforce CUDA CXX) diff --git a/examples/boids_bruteforce_dependency_graph/CMakeLists.txt b/examples/boids_bruteforce_dependency_graph/CMakeLists.txt index 63c2ea40f..6f3e8264e 100644 --- a/examples/boids_bruteforce_dependency_graph/CMakeLists.txt +++ b/examples/boids_bruteforce_dependency_graph/CMakeLists.txt @@ -1,5 +1,5 @@ -# CMake 3.15+ for Thrust/Cub support -cmake_minimum_required(VERSION VERSION 3.15 FATAL_ERROR) +# Minimum CMake version 3.18 for CUDA --std=c++17 +cmake_minimum_required(VERSION VERSION 3.18 FATAL_ERROR) # Name the project and set languages project(boids_bruteforce_dependency_graph CUDA CXX) diff --git a/examples/boids_rtc_bruteforce/CMakeLists.txt b/examples/boids_rtc_bruteforce/CMakeLists.txt index 1de5bc732..3048a4c73 100644 --- a/examples/boids_rtc_bruteforce/CMakeLists.txt +++ b/examples/boids_rtc_bruteforce/CMakeLists.txt @@ -1,5 +1,5 @@ -# CMake 3.15+ for Thrust/Cub support -cmake_minimum_required(VERSION VERSION 3.15 FATAL_ERROR) +# Minimum CMake version 3.18 for CUDA --std=c++17 +cmake_minimum_required(VERSION VERSION 3.18 FATAL_ERROR) # Name the project and set languages project(boids_rtc_bruteforce CUDA CXX) diff --git a/examples/boids_rtc_spatial3D/CMakeLists.txt b/examples/boids_rtc_spatial3D/CMakeLists.txt index f39e22bf3..b9d4ded81 100644 --- a/examples/boids_rtc_spatial3D/CMakeLists.txt +++ b/examples/boids_rtc_spatial3D/CMakeLists.txt @@ -1,5 +1,5 @@ -# CMake 3.15+ for Thrust/Cub support -cmake_minimum_required(VERSION VERSION 3.15 FATAL_ERROR) +# Minimum CMake version 3.18 for CUDA --std=c++17 +cmake_minimum_required(VERSION VERSION 3.18 FATAL_ERROR) # Name the project and set languages project(boids_rtc_spatial3D CUDA CXX) diff --git a/examples/boids_spatial3D/CMakeLists.txt b/examples/boids_spatial3D/CMakeLists.txt index dd1ccc008..665cfebd2 100644 --- a/examples/boids_spatial3D/CMakeLists.txt +++ b/examples/boids_spatial3D/CMakeLists.txt @@ -1,5 +1,5 @@ -# CMake 3.15+ for Thrust/Cub support -cmake_minimum_required(VERSION VERSION 3.15 FATAL_ERROR) +# Minimum CMake version 3.18 for CUDA --std=c++17 +cmake_minimum_required(VERSION VERSION 3.18 FATAL_ERROR) # Name the project and set languages project(boids_spatial3D CUDA CXX) diff --git a/examples/circles_bruteforce/CMakeLists.txt b/examples/circles_bruteforce/CMakeLists.txt index 5bb2aa729..fef1d5282 100644 --- a/examples/circles_bruteforce/CMakeLists.txt +++ b/examples/circles_bruteforce/CMakeLists.txt @@ -1,5 +1,5 @@ -# CMake 3.15+ for Thrust/Cub support -cmake_minimum_required(VERSION VERSION 3.15 FATAL_ERROR) +# Minimum CMake version 3.18 for CUDA --std=c++17 +cmake_minimum_required(VERSION VERSION 3.18 FATAL_ERROR) # Name the project and set languages project(circles_bruteforce CUDA CXX) diff --git a/examples/circles_spatial3D/CMakeLists.txt b/examples/circles_spatial3D/CMakeLists.txt index 29f68f395..73810fbbe 100644 --- a/examples/circles_spatial3D/CMakeLists.txt +++ b/examples/circles_spatial3D/CMakeLists.txt @@ -1,5 +1,5 @@ -# CMake 3.15+ for Thrust/Cub support -cmake_minimum_required(VERSION VERSION 3.15 FATAL_ERROR) +# Minimum CMake version 3.18 for CUDA --std=c++17 +cmake_minimum_required(VERSION VERSION 3.18 FATAL_ERROR) # Name the project and set languages project(circles_spatial3D CUDA CXX) diff --git a/examples/game_of_life/CMakeLists.txt b/examples/game_of_life/CMakeLists.txt index f01c91e5f..8518972d3 100644 --- a/examples/game_of_life/CMakeLists.txt +++ b/examples/game_of_life/CMakeLists.txt @@ -1,5 +1,5 @@ -# CMake 3.15+ for Thrust/Cub support -cmake_minimum_required(VERSION VERSION 3.15 FATAL_ERROR) +# Minimum CMake version 3.18 for CUDA --std=c++17 +cmake_minimum_required(VERSION VERSION 3.18 FATAL_ERROR) # Name the project and set languages project(game_of_life CUDA CXX) diff --git a/examples/host_functions/CMakeLists.txt b/examples/host_functions/CMakeLists.txt index 406786ce0..8d76a2389 100644 --- a/examples/host_functions/CMakeLists.txt +++ b/examples/host_functions/CMakeLists.txt @@ -1,5 +1,5 @@ -# CMake 3.15+ for Thrust/Cub support -cmake_minimum_required(VERSION VERSION 3.15 FATAL_ERROR) +# Minimum CMake version 3.18 for CUDA --std=c++17 +cmake_minimum_required(VERSION VERSION 3.18 FATAL_ERROR) # Name the project and set languages project(host_functions CUDA CXX) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 983e7cf6b..ee070f2df 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,34 +1,37 @@ -# CMake 3.15+ for Thrust/Cub support -cmake_minimum_required(VERSION VERSION 3.15 FATAL_ERROR) - -# Cmake 3.16 has issues with CUB and Thrust due to the order of the include path it generates. -if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.16 AND CMAKE_VERSION VERSION_LESS 3.17) - message(WARNING - " CMake 3.16 does not use the correct CUDA include paths on some platforms.\n" - " Please consider using a different version of CMake.") -endif() +# Minimum CMake version 3.18 for CUDA --std=c++17 +cmake_minimum_required(VERSION VERSION 3.18 FATAL_ERROR) # Set the location of the ROOT flame gpu project relative to this CMakeList.txt get_filename_component(FLAMEGPU_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/.. REALPATH) -# See what languages are supported +# Include versioning CMake logic, to set the project version +include(${FLAMEGPU_ROOT}/cmake/version.cmake) + +# Set the project with no languages iniitailly, in case of doxygen only builds. +project(flamegpu LANGUAGES NONE VERSION ${FLAMEGPU_VERSION}) + +# See what languages are supported. Must be called within a project. # This is primarily here incase someone targets src/CMakeFiles.txt directly include(CheckLanguage) +check_language(CXX) check_language(CUDA) if(CMAKE_CUDA_COMPILER STREQUAL NOTFOUND) - project(flamegpu NONE) #Not able to build code, so just make docs message("Suitable compilers for building code not found.\n" "Attempting generation of minimal documentation only project.") - include(${FLAMEGPU_ROOT}/cmake/doxygen.cmake) + include(${FLAMEGPU_ROOT}/cmake/dependencies/doxygen.cmake) if(${BUILD_API_DOCUMENTATION}) create_doxygen_target("${FLAMEGPU_ROOT}" "${CMAKE_CURRENT_BINARY_DIR}" "") endif() return() endif() -include(${FLAMEGPU_ROOT}/cmake/version.cmake) -# Name the project and set languages -project(flamegpu LANGUAGES CUDA CXX VERSION ${FLAMEGPU_VERSION}) +# Enable the required languages for compilation +enable_language(C) +enable_language(CXX) +enable_language(CUDA) + +# Ensure this is not an in-source build +include(${FLAMEGPU_ROOT}/cmake/OutOfSourceOnly.cmake) # Option to enable/disable runtime checks which may impact performance # This will primarily prevent device code from reporting errors @@ -43,10 +46,12 @@ mark_as_advanced(USE_GLM) # Include common rules. include(${FLAMEGPU_ROOT}/cmake/common.cmake) -include(${FLAMEGPU_ROOT}/cmake/doxygen.cmake) +# Include the doxygen cmake logic. +include(${FLAMEGPU_ROOT}/cmake/dependencies/doxygen.cmake) +# Include the visualiser cmake if requested if(VISUALISATION) - include(${FLAMEGPU_ROOT}/cmake/flamegpu2-visualiser.cmake) + include(${FLAMEGPU_ROOT}/cmake/dependencies/flamegpu2-visualiser.cmake) endif() # Output the full FLAMEGPU version @@ -74,13 +79,6 @@ else() endif() endif() -# Enable parallel compilation -# Only do this for lib, as examples already build target parallel -if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP") -endif() - # Specify source files for the static library # Can't do this automatically, as CMake wouldn't know when to regen (as CMakeLists.txt would be unchanged) # version.h is automatically generated so does not exist prior to configure time @@ -330,8 +328,155 @@ set(T_SRC "${SRC_EXTERNAL}") list(FILTER T_SRC EXCLUDE REGEX ".*\.(h|hpp|cuh)$") source_group(TREE ${FLAMEGPU_ROOT}/include PREFIX external FILES ${T_SRC}) + +# Create the library target and set various properties + +# @todo - correctly set PUBLIC/PRIVATE/INTERFACE for the flamegpu library target + # Define which source files are required for the target executable -add_flamegpu_library("${PROJECT_NAME}" "${ALL_SRC}" "${FLAMEGPU_ROOT}") +add_library(${PROJECT_NAME} STATIC ${ALL_SRC}) + +# Add the library headers as public so they are forwarded on. +target_include_directories(${PROJECT_NAME} PUBLIC "${FLAMEGPU_ROOT}/include") +# Add any private headers. +target_include_directories(${PROJECT_NAME} PRIVATE "${FLAMEGPU_ROOT}/src") + +# Set target level warnings. +EnableFLAMEGPUCompilerWarnings(TARGET "${PROJECT_NAME}") +# Apply common compiler settings +CommonCompilerSettings(TARGET "${PROJECT_NAME}") +# Set the cuda gencodes, potentially using the user-provided CUDA_ARCH +SetCUDAGencodes(TARGET "${PROJECT_NAME}") + +# enable "fpic" for linux to allow shared libraries to be build from the static library (required for swig) +set_property(TARGET ${PROJECT_NAME} PROPERTY POSITION_INDEPENDENT_CODE ON) + +# Activate visualisation if requested +if (VISUALISATION) + # @todo - these could/should be private, but must be PUBLIC for swig to build. Alternateively it could be PRIVATE but also set for swig. + target_link_libraries(${PROJECT_NAME} PUBLIC flamegpu_visualiser) + CMAKE_SET_TARGET_FOLDER(flamegpu_visualiser "FLAMEGPU") + target_compile_definitions(${PROJECT_NAME} PUBLIC VISUALISATION) + + # Make the visualisers GLM accessible via include + # @todo - make the vis cmake/glm create a target to use. + if (USE_GLM) + if(glm_FOUND) + target_include_directories(${PROJECT_NAME} PUBLIC "${glm_INCLUDE_DIRS}") + target_compile_definitions(${PROJECT_NAME} PUBLIC GLM_PATH="${glm_INCLUDE_DIRS}") + else() + message(WARNING "USE_GLM enabled, but glm_FOUND is False.") + endif() + target_compile_definitions(${PROJECT_NAME} PRIVATE USE_GLM) + endif() +endif() + +if (NOT RTC_DISK_CACHE) + # Only used in source files, so can be private + target_compile_definitions(${PROJECT_NAME} PRIVATE DISABLE_RTC_DISK_CACHE) +endif() +if (EXPORT_RTC_SOURCES) + # Only used in source files, so can be private + target_compile_definitions(${PROJECT_NAME} PRIVATE OUTPUT_RTC_DYNAMIC_FILES) +endif () + +# Enable RDC +set_property(TARGET ${PROJECT_NAME} PROPERTY CUDA_SEPARABLE_COMPILATION ON) + +# Link against dependency targets / directories. + +# SYSTEM includes prevent warnings from 3rd party includes where possible. This is implied by target_link_libraries if it is an imported target. +if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + # CUB (and thrust) cause many compiler warnings at high levels, including Wreorder. + # CUB:CUB does not use -isystem to prevent the automatic -I/include from being more important, and the CUDA disributed CUB being used. + # Instead, if possible we pass the include directory directly rather than using the imported target. + # And also pass {CUDAToolkit_INCLUDE_DIRS}/../include" as isystem so the include order is correct for isystem to work (a workaround for a workaround). The `../` is required to prevent cmake from removing the duplicate path. + + # Include CUB via isystem if possible (via _CUB_INCLUDE_DIR which may be subject to change), otherwise use it via target_link_libraries. + # If we used the system CUB, via find_package (CUDA 11.3+ package the config) then this convoluted approach could be avoided. + if(DEFINED _CUB_INCLUDE_DIR) + target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC "${_CUB_INCLUDE_DIR}") + else() + target_link_libraries(${PROJECT_NAME} PUBLIC CUB::CUB) + endif() + target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC "${CUDAToolkit_INCLUDE_DIRS}/../include") +else() + # MSVC just includes cub via the CUB::CUB target as no isystem to worry about. + target_link_libraries(${PROJECT_NAME} PUBLIC CUB::CUB) + # Same for Thrust. + # Visual studio 2015 needs to suppress deprecation messages from CUB/Thrust. + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10) + target_compile_definitions(${PROJECT_NAME} PUBLIC "CUB_IGNORE_DEPRECATED_CPP_DIALECT") + target_compile_definitions(${PROJECT_NAME} PUBLIC "THRUST_IGNORE_DEPRECATED_CPP_DIALECT") + endif() +endif() + +# Thrust uses isystem if available +target_link_libraries(${PROJECT_NAME} PUBLIC Thrust::Thrust) + +# tinyxml2 static library +target_link_libraries(${PROJECT_NAME} PRIVATE Tinyxml2::tinyxml2) + +# If rapidjson was found, add it to the include dirs. +target_link_libraries(${PROJECT_NAME} PRIVATE RapidJSON::rapidjson) + +target_link_libraries(${PROJECT_NAME} PUBLIC CUDA::nvrtc) + +target_link_libraries(${PROJECT_NAME} PUBLIC CUDA::cuda_driver) + +if(USE_NVTX AND TARGET NVTX::nvtx) + target_link_libraries(${PROJECT_NAME} PUBLIC NVTX::nvtx) + # Get the version to set a definition value + get_target_property(nvtxversion NVTX::nvtx VERSION) + target_compile_definitions(${PROJECT_NAME} PUBLIC "$<$:USE_NVTX=${nvtxversion}>") + unset(nvtxversion) +endif() + +target_link_libraries(${PROJECT_NAME} PUBLIC Jitify::jitify) +target_compile_definitions(${PROJECT_NAME} PUBLIC "$<$:JITIFY_PRINT_LOG>") + +# If gcc, need to add linker flag for std::experimental::filesystem pre c++17 +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + target_link_libraries(${PROJECT_NAME} PUBLIC stdc++fs) +endif() + +# Link against dl if available. This used to be implied from somewhere... +if(CMAKE_DL_LIBS) + target_link_libraries(${PROJECT_NAME} PUBLIC ${CMAKE_DL_LIBS}) +endif() + +# Make GLM accessible via include. PUBLIC so this is usable by downstream projects +if (USE_GLM) + if(TARGET GLM::glm) + target_link_libraries(${PROJECT_NAME} PUBLIC GLM::glm) + target_compile_definitions(${PROJECT_NAME} PUBLIC USE_GLM) + else() + message(WARNING "USE_GLM enabled, but glm was not found") + endif() +endif() + +# Ensure we link against pthread / windows equilvalent. This was previously implied +set(THREADS_PREFER_PTHREAD_FLAG ON) +find_package(Threads REQUIRED) +target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads) + +# Flag the new linter target and the files to be linted. +new_linter_target(${PROJECT_NAME} "${ALL_SRC}") + +# Put within FLAMEGPU filter +CMAKE_SET_TARGET_FOLDER(${PROJECT_NAME} "FLAMEGPU") +# Put the tinyxml2 in the folder +CMAKE_SET_TARGET_FOLDER("tinyxml2" "FLAMEGPU/Dependencies") + +# Emit some warnings that should only be issued once and are related to this file (but not this target) +# @todo - move these author warnigns elsewhere, so they will be emitted if not building FLAMEGPU iteself? Common but with some form of guard? +if(MSVC AND CMAKE_CUDA_COMPILER_VERSION VERSION_LESS_EQUAL "10.2") + message(AUTHOR_WARNING "MSVC and NVCC <= 10.2 may encounter compiler errors due to an NVCC bug exposed by Thrust. Cosider using a newer CUDA toolkit.") +endif() +if(MSVC AND CMAKE_CUDA_COMPILER_VERSION VERSION_LESS_EQUAL "11.0") + # https://github.com/FLAMEGPU/FLAMEGPU2/issues/483 + message(AUTHOR_WARNING "MSVC and NVCC <= 11.0 may encounter errors at link time with incremental rebuilds. Cosider using a newer CUDA toolkit.") +endif() # Also set as startup project (if top level project) set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" PROPERTY VS_STARTUP_PROJECT "${PROJECT_NAME}") diff --git a/swig/CMakeLists.txt b/swig/CMakeLists.txt index 86d34ee6f..e58297e85 100644 --- a/swig/CMakeLists.txt +++ b/swig/CMakeLists.txt @@ -1,5 +1,5 @@ -# CMake 3.15+ for Thrust/Cub support -cmake_minimum_required(VERSION VERSION 3.15 FATAL_ERROR) +# Minimum CMake version 3.18 for CUDA --std=c++17 +cmake_minimum_required(VERSION VERSION 3.18 FATAL_ERROR) include(FetchContent) @@ -19,13 +19,8 @@ endif() if(PYTHON3_EXACT_VERSION) set(PYTHON3_EXACT_VERSION_ARG ${PYTHON3_EXACT_VERSION} EXACT) endif() -# CMake > 3.18 can use Development.Module which shoudl be all that's required, and should work inside manylinux containers. -if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.18) - find_package(Python3 ${PYTHON3_EXACT_VERSION_ARG} REQUIRED COMPONENTS Interpreter Development.Module) -else() - # This will not work with Manylinux, but the curreny manylinux image already includes 3.21 - find_package(Python3 ${PYTHON3_EXACT_VERSION_ARG} REQUIRED COMPONENTS Interpreter Development) -endif() +# CMake > 3.18 can use Development.Module rather than development +find_package(Python3 ${PYTHON3_EXACT_VERSION_ARG} REQUIRED COMPONENTS Interpreter Development.Module) unset(PYTHON3_EXACT_VERSION_ARG) message(STATUS "Python found at " ${Python3_EXECUTABLE}) diff --git a/swig/python/CMakeLists.txt b/swig/python/CMakeLists.txt index ac1ba50f1..94e3632f1 100644 --- a/swig/python/CMakeLists.txt +++ b/swig/python/CMakeLists.txt @@ -1,10 +1,15 @@ -# Include common rules. -# Actually dont as the c Warning levels are too damn high -#include(../../cmake/common.cmake) -# Just include cuda_arch to suppress CMAKE 3.18 warnings on windows (where nvcc is used even when not neccesary) +# Minimum CMake version 3.18 for CUDA --std=c++17 +cmake_minimum_required(VERSION VERSION 3.18 FATAL_ERROR) + +# Get the root of the repository to find other CMake files etc. get_filename_component(FLAMEGPU_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../ REALPATH) -# Set CUDA gencode arguments +# Ensure that the cuda toolkit package is available +find_package(CUDAToolkit REQUIRED) + +# include CMake function to enable setting of warning suppressions +include(${FLAMEGPU_ROOT}/cmake/warnings.cmake) +# include CMake function to enable setting of gencode flags include(${FLAMEGPU_ROOT}/cmake/cuda_arch.cmake) # Set the C++ and CUDA standard to use include(${FLAMEGPU_ROOT}/cmake/cxxstd.cmake) @@ -77,23 +82,30 @@ set_property(TARGET ${PYTHON_MODULE_NAME} PROPERTY CUDA_SEPARABLE_COMPILATION ON # Build with the SWIG pre-processor macro enabled set_property(TARGET ${PYTHON_MODULE_NAME} APPEND PROPERTY SWIG_GENERATED_COMPILE_DEFINITIONS "SWIG") # Suppress warnings during compilation of SWIG generated PYTHON_wrap.cxx -set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --diag_suppress=\"declared_but_not_referenced\"") -# set bigobj property for windows compiler (needed due to the sheer size of the generated swig file: https://www.reddit.com/r/AbsoluteUnits/) +# @todo - Split setting warning level and suppressions to separate cmake functions, so swig can be built with suppressions but low warning level. + +# Set the gencode arguments for the target +SetCUDAGencodes(TARGET "${PYTHON_MODULE_NAME}") + +# Disable all compiler warnings, as we do not control the generated code +DisableCompilerWarnings(TARGET "${PYTHON_MODULE_NAME}") + +# Additionally suppress +SuppressSomeCompilerWarnings(TARGET "${PYTHON_MODULE_NAME}") + +# Set bigobj property for windows compiler, required by the very large generated swig file if(MSVC) - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler /bigobj") + target_compile_options(${PYTHON_MODULE_NAME} PRIVATE "$<$:SHELL:-Xcompiler /bigobj>") endif() + # set include directories for module build -target_include_directories(${PYTHON_MODULE_NAME} - PRIVATE - ${FLAMEGPU_ROOT}/include - ${Python3_INCLUDE_DIRS} - ) +target_include_directories(${PYTHON_MODULE_NAME} PRIVATE ${Python3_INCLUDE_DIRS}) # Handle user options +# This does not use common/CommonCompilerSettings as it appears to rely on swig specific properties (although this is untested.) if (VISUALISATION) set_property(TARGET ${PYTHON_MODULE_NAME} APPEND PROPERTY SWIG_COMPILE_DEFINITIONS VISUALISATION) set_property(TARGET ${PYTHON_MODULE_NAME} APPEND PROPERTY SWIG_GENERATED_COMPILE_DEFINITIONS VISUALISATION) - target_include_directories(${PYTHON_MODULE_NAME} PUBLIC "${VISUALISATION_ROOT}/include") endif() if (SEATBELTS) # Debug alwasy has seatbelts. @@ -117,16 +129,24 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") set_property(TARGET ${PYTHON_MODULE_NAME} APPEND PROPERTY SWIG_COMPILE_DEFINITIONS NOMINMAX) set_property(TARGET ${PYTHON_MODULE_NAME} APPEND PROPERTY SWIG_GENERATED_COMPILE_DEFINITIONS NOMINMAX) endif() - -# link with the static flamegpu and cuda libraries -target_link_libraries(${PYTHON_MODULE_NAME} PRIVATE flamegpu cuda) + +# Use the FindCUDATooklit package (CMake > 3.17) to find other parts of the cuda toolkit not provided by the CMake language support +find_package(CUDAToolkit REQUIRED) + +# link with the static flamegpu, inherriting links on nvrtc and the cuda driver api etc +target_link_libraries(${PYTHON_MODULE_NAME} PRIVATE flamegpu) + +# Requires the development module. +target_link_libraries(${PYTHON_MODULE_NAME} PRIVATE Python3::Module) + +# @todo - this might need re-enabling subject to CI passing? # Variable PYTHON_LIBRARIES can contains keyword `optimized` # which won't be interpreted inside a generator expression. # i.e. we can't use: $<$:${PYTHON_LIBRARIES}> # see: https://cmake.org/cmake/help/git-stage/command/target_link_libraries.html#command:target_link_libraries -if(MSVC) - target_link_libraries(${PYTHON_MODULE_NAME} PRIVATE ${Python3_LIBRARIES} flamegpu cuda) -endif() +# if(MSVC) +# target_link_libraries(${PYTHON_MODULE_NAME} PRIVATE ${Python3_LIBRARIES}) +# endif() ####################### ## Python Packaging ## @@ -143,22 +163,11 @@ if(WIN32) # @todo - See if there is a dynamic way to achieve this through target properties? set(FLAMEGPU_PYTHON_PACKAGE_DATA_OS_SPECIFIC "${FLAMEGPU_PYTHON_PACKAGE_DATA_OS_SPECIFIC}'glew32.dll', 'SDL2.dll', 'DevIL.dll'") endif() - - -# Get the cuda major and minor versions as required for setup.py. There is no easy cmake way to access this that is supported across multiple CMake versions.. -string(REPLACE "." ";" CMAKE_CUDA_COMPILER_VERSION_LIST ${CMAKE_CUDA_COMPILER_VERSION}) -list(GET CMAKE_CUDA_COMPILER_VERSION_LIST 0 CMAKE_CUDA_COMPILER_VERSION_MAJOR) -list(GET CMAKE_CUDA_COMPILER_VERSION_LIST 1 CMAKE_CUDA_COMPILER_VERSION_MINOR) - - # configure the python setup.py and __init__.py files for packaging and output to the final lib output folder configure_file( setup.py.in ${PYTHON_LIB_TEMP_DIRECTORY}/setup.py.in @ONLY) -unset(CMAKE_CUDA_COMPILER_VERSION_LIST) -unset(CMAKE_CUDA_COMPILER_VERSION_MAJOR) -unset(CMAKE_CUDA_COMPILER_VERSION_MINOR) unset(FLAMEGPU_PYTHON_PACKAGE_DATA_OS_SPECIFIC) file(GENERATE diff --git a/swig/python/setup.py.in b/swig/python/setup.py.in index b6e74ace1..30c0b218e 100644 --- a/swig/python/setup.py.in +++ b/swig/python/setup.py.in @@ -25,7 +25,7 @@ setup( include_package_data=True, classifiers=[ 'Development Status :: 3 - Alpha', - 'Environment :: GPU :: NVIDIA CUDA :: @CMAKE_CUDA_COMPILER_VERSION_MAJOR@.@CMAKE_CUDA_COMPILER_VERSION_MINOR@' + 'Environment :: GPU :: NVIDIA CUDA :: @CUDAToolkit_VERSION_MAJOR@.@CUDAToolkit_VERSION_MINOR@' 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: POSIX :: Linux', diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d944d5961..7685e1c8d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,5 +1,5 @@ -# CMake 3.15+ for Thrust/Cub support -cmake_minimum_required(VERSION VERSION 3.15 FATAL_ERROR) +# Minimum CMake version 3.18 for CUDA --std=c++17 +cmake_minimum_required(VERSION VERSION 3.18 FATAL_ERROR) # Only Do anything if BUILD_TESTS or BUILD_TESTS_DEV is set. if(NOT (BUILD_TESTS OR BUILD_TESTS_DEV)) @@ -92,7 +92,7 @@ SET(HELPERS_SRC get_filename_component(FLAMEGPU_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/.. REALPATH) # Include googletest as a dependency. -include(${FLAMEGPU_ROOT}/cmake/googletest.cmake) +include(${FLAMEGPU_ROOT}/cmake/dependencies/googletest.cmake) if(BUILD_TESTS) # Name the project and set languages @@ -112,17 +112,12 @@ if(BUILD_TESTS) # If called via add_subdirectory() SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../bin/${CMAKE_BUILD_TYPE}/) endif() - # Enable parallel compilation - if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP") - endif() # Add the executable and set required flags for the target add_flamegpu_executable("${PROJECT_NAME}" "${ALL_SRC}" "${FLAMEGPU_ROOT}" "${PROJECT_BINARY_DIR}" FALSE) # Add the tests directory to the include path, target_include_directories("${PROJECT_NAME}" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") # Add the targets we depend on (this does link and include) - target_link_libraries("${PROJECT_NAME}" gtest) + target_link_libraries("${PROJECT_NAME}" GTest::gtest) # target_link_libraries("${PROJECT_NAME}" gmock) # Currently unused # Put Within Tests filter CMAKE_SET_TARGET_FOLDER("${PROJECT_NAME}" "Tests") @@ -152,17 +147,12 @@ if(BUILD_TESTS_DEV) # If called via add_subdirectory() SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../bin/${CMAKE_BUILD_TYPE}/) endif() - # Enable parallel compilation - if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP") - endif() # Add the executable and set required flags for the target add_flamegpu_executable("${PROJECT_NAME}" "${ALL_SRC}" "${FLAMEGPU_ROOT}" "${PROJECT_BINARY_DIR}" FALSE) # Add the tests directory to the include path, target_include_directories("${PROJECT_NAME}" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") # Add the targets we depend on (this does link and include) - target_link_libraries("${PROJECT_NAME}" gtest) + target_link_libraries("${PROJECT_NAME}" GTest::gtest) # target_link_libraries("${PROJECT_NAME}" gmock) # Currently unused CMAKE_SET_TARGET_FOLDER("${PROJECT_NAME}" "Tests") # Set the default (visual studio) debugger configure_file