From b4b3c3d815ebf12458dd7bc8e80cde9a151594e2 Mon Sep 17 00:00:00 2001 From: Peter Heywood Date: Tue, 22 Nov 2022 16:36:40 +0000 Subject: [PATCH] Refactor CMake: prefixing, use CMAKE_CUDA_ARCHITECTURES, general improvments + Prefixes CMake option and cache variables with FLAMEGPU_VISUALISER + Prefix CMake macros and functions with flamegpu_visualiser_ and use lower snake case + Remove unneeded reference to SEATBELTS from CMake + Mark many CMake variables as advanced to simplify the CMake GUI + Fix cmake_minimimum_requires statemeents and add a policy_max of 3.25 + This requied a fix for a CMake 3.21 policy + Use more-modern CMake C++/CUDA standard setting + Modernise/simplify GLM CMake and use PUBLIC/PRIVATE target_link_libraries + Provide list of DLLs via flamegpu_visualiser_get_runtime_depenencies to simplify code in FLAMEGPU/FLAMEGPU2 --- .github/workflows/Lint.yml | 2 +- .github/workflows/Manylinux2014.yml | 4 +- .github/workflows/Ubuntu.yml | 4 +- .github/workflows/Windows.yml | 4 +- CMakeLists.txt | 11 +- README.md | 8 +- cmake/CUDAArchitectures.cmake | 299 ++++++++++++++++++ cmake/CUDAArchitecturesProjectInclude.cmake | 9 + cmake/CheckCompilerFunctionality.cmake | 147 +++++++++ .../CheckStdChrono.cu | 7 + .../CheckStdFilesystem.cu | 4 + .../CheckVectorTuplePushBack.cu | 11 + cmake/CommonCompilerSettings.cmake | 16 +- cmake/OutOfSourceOnly.cmake | 6 +- cmake/SetTargetFolder.cmake | 17 + cmake/cpplint.cmake | 153 +++++---- cmake/cuda_arch.cmake | 134 -------- cmake/cxxstd.cmake | 52 --- cmake/dependencies/devil.cmake | 14 +- cmake/dependencies/freetype.cmake | 15 +- cmake/dependencies/glew.cmake | 10 +- cmake/dependencies/glm.cmake | 61 ++-- cmake/dependencies/imgui-CMakeLists.txt.in | 10 +- cmake/dependencies/imgui.cmake | 7 + cmake/dependencies/sdl2.cmake | 26 +- cmake/modules/Findglm.cmake | 39 --- cmake/warnings.cmake | 49 +-- src/CMakeLists.txt | 138 +++++--- 28 files changed, 835 insertions(+), 422 deletions(-) create mode 100644 cmake/CUDAArchitectures.cmake create mode 100644 cmake/CUDAArchitecturesProjectInclude.cmake create mode 100644 cmake/CheckCompilerFunctionality.cmake create mode 100644 cmake/CheckCompilerFunctionality/CheckStdChrono.cu create mode 100644 cmake/CheckCompilerFunctionality/CheckStdFilesystem.cu create mode 100644 cmake/CheckCompilerFunctionality/CheckVectorTuplePushBack.cu create mode 100644 cmake/SetTargetFolder.cmake delete mode 100644 cmake/cuda_arch.cmake delete mode 100644 cmake/cxxstd.cmake delete mode 100644 cmake/modules/Findglm.cmake diff --git a/.github/workflows/Lint.yml b/.github/workflows/Lint.yml index 5b87f59..c6fd74c 100644 --- a/.github/workflows/Lint.yml +++ b/.github/workflows/Lint.yml @@ -49,7 +49,7 @@ jobs: - name: Configure cmake run: > cmake . -B "${{ env.BUILD_DIR }}" - -DALLOW_LINT_ONLY=ON + -DFLAMEGPU_ALLOW_LINT_ONLY=ON - name: Lint working-directory: ${{ env.BUILD_DIR }} diff --git a/.github/workflows/Manylinux2014.yml b/.github/workflows/Manylinux2014.yml index 10b77c6..e89304f 100644 --- a/.github/workflows/Manylinux2014.yml +++ b/.github/workflows/Manylinux2014.yml @@ -117,8 +117,8 @@ jobs: -DCMAKE_BUILD_TYPE="${{ env.CONFIG }}" -Werror=dev -DCMAKE_WARN_DEPRECATED="OFF" - -DWARNINGS_AS_ERRORS="OFF" - -DCUDA_ARCH="${{ env.CUDA_ARCH }}" + -DFLAMEGPU_WARNINGS_AS_ERRORS="OFF" + -DCMAKE_CUDA_ARCHITECTURES="${{ env.CUDA_ARCH }}" -DGLEW_USE_STATIC_LIBS="${{ env.USE_STATIC_GLEW }}" -DOpenGL_GL_PREFERENCE:STRING=LEGACY diff --git a/.github/workflows/Ubuntu.yml b/.github/workflows/Ubuntu.yml index b967bb4..a641305 100644 --- a/.github/workflows/Ubuntu.yml +++ b/.github/workflows/Ubuntu.yml @@ -87,8 +87,8 @@ jobs: -DCMAKE_BUILD_TYPE="${{ env.CONFIG }}" -Werror=dev -DCMAKE_WARN_DEPRECATED="OFF" - -DWARNINGS_AS_ERRORS="ON" - -DCUDA_ARCH="${{ env.CUDA_ARCH }}" + -DFLAMEGPU_WARNINGS_AS_ERRORS="ON" + -DCMAKE_CUDA_ARCHITECTURES="${{ env.CUDA_ARCH }}" - name: Build working-directory: ${{ env.BUILD_DIR }} diff --git a/.github/workflows/Windows.yml b/.github/workflows/Windows.yml index 9647912..4f5db1b 100644 --- a/.github/workflows/Windows.yml +++ b/.github/workflows/Windows.yml @@ -69,8 +69,8 @@ jobs: -G "${{ env.HOSTCXX }}" -A x64 -Werror=dev -DCMAKE_WARN_DEPRECATED="OFF" - -DWARNINGS_AS_ERRORS="ON" - -DCUDA_ARCH="${{ env.CUDA_ARCH }}" + -DFLAMEGPU_WARNINGS_AS_ERRORS="ON" + -DCMAKE_CUDA_ARCHITECTURES="${{ env.CUDA_ARCH }}" - name: Build working-directory: ${{ env.BUILD_DIR }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a67d57..43371d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # Parity with main FGPU2 CMake -cmake_minimum_required(VERSION VERSION 3.18 FATAL_ERROR) +cmake_minimum_required(VERSION 3.18...3.25 FATAL_ERROR) project(FLAMEGPU2_VISUALISER LANGUAGES NONE) @@ -13,18 +13,15 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/OutOfSourceOnly.cmake) # Define some CMake Options which apply to all (sub) projects # Option to promote compilation warnings to error, useful for strict CI -option(WARNINGS_AS_ERRORS "Promote compilation warnings to errors" OFF) +option(FLAMEGPU_WARNINGS_AS_ERRORS "Promote compilation warnings to errors" OFF) # Option to group CMake generated projects into folders in supported IDEs option(CMAKE_USE_FOLDERS "Enable folder grouping of projects in IDEs." ON) mark_as_advanced(CMAKE_USE_FOLDERS) # Add a new cmake option, to allow lint_only configurations. -option(ALLOW_LINT_ONLY "Allow the project to be configured for lint-only builds" OFF) -mark_as_advanced(ALLOW_LINT_ONLY) - -# Control target CUDA_ARCH to compile for -SET(CUDA_ARCH "${CUDA_ARCH}" CACHE STRING "List of CUDA Architectures to target. E.g. 61;70" FORCE) +option(FLAMEGPU_ALLOW_LINT_ONLY "Allow the project to be configured for lint-only builds" OFF) +mark_as_advanced(FLAMEGPU_ALLOW_LINT_ONLY) # Add the src subdirectory cmake project. add_subdirectory(src "${PROJECT_BINARY_DIR}/FLAMEGPU_visualiser") diff --git a/README.md b/README.md index 169eb67..dd075ca 100644 --- a/README.md +++ b/README.md @@ -35,8 +35,8 @@ To build the visualiser under linux in Release mode using the command line: # Create a build directory mkdir -p build cd build -# Configure CMake, i.e. for Release builds for Pascal and newer GPUs -cmake .. -DCUDA_ARCH=61 -DCMAKE_BUILD_TYPE=Release +# Configure CMake, i.e. for Release builds for consumer Pascal and newer GPUs +cmake .. -DCMAKE_CUDA_ARCHITECTURES=61 -DCMAKE_BUILD_TYPE=Release # Build all targets using 8 threads. cmake --build . --target all -j 8 # Or directly via make @@ -65,10 +65,10 @@ cmake --open . The project can be configured to allow linting without the need for CUDA or OpenGL to be available (i.e. CI). -To do this, set the `ALLOW_LINT_ONLY` CMake option to `ON`. I.e.: +To do this, set the `FLAMEGPU_ALLOW_LINT_ONLY` CMake option to `ON`. I.e.: ```bash -cmake .. -DALLOW_LINT_ONLY=ON +cmake .. -DFLAMEGPU_ALLOW_LINT_ONLY=ON cmake --build . --target lint_flamegpu_visualiser ``` diff --git a/cmake/CUDAArchitectures.cmake b/cmake/CUDAArchitectures.cmake new file mode 100644 index 0000000..5e596b6 --- /dev/null +++ b/cmake/CUDAArchitectures.cmake @@ -0,0 +1,299 @@ +#[[[ +# Handle CMAKE_CUDA_ARCHITECTURES gracefully, allowing library CMakeLists.txt to provide a sane default if not user-specified +# +# CMAKE_CUDA_ARCHITECTURES is a CMake >= 3.18 feature which controls code generation options for CUDA device code. +# The initial value can be set using teh CUDAARCHS environment variable, or the CMake Cache varaibel CMAKE_CUDA_ARCHITECTURES. +# This allows users to provide their chosen value. +# When the CUDA language is enabled, by a project() or enable_language() command, if the cache variable is empty then CMake will set the cache variable to the default used by the compiler. I.e. 52 for CUDA 11.x. +# However, it is then impossible to detect if the user provided this value, or if CMake did, preventing a library from setting a default, without executing CMake prior to the first project command, which is unusual. +# +#]] +include_guard(GLOBAL) + +#[[[ +# Initialise the CMAKE_CUDA_ARCHITECTURES from the environment, CACHE or a sane programatic default +# +# Call this method prior to the first (or all) project commands, to store the initial state of CMAKE_CUDA_ARCHITECTURES/CUDAARCHS for later post processing. +# Optionally specify a project to inject a call to flamegpu_visualiser_set_cuda_architectures in to, to post-process the stored value or set a library-provided default. +# +# :keyword PROJECT: Optional project name to inject CMAKE_CUDA_ARCHITECTURES setting into. Otherwise call flamegpu_visualiser_set_cuda_architectures manually after the project command or enable_lanague(CUDA). +# :type PROJECT: string +# :keyword NO_VALIDATE_ARCHITECTURES: Do not validate the passed arguments against nvcc --help output +# :type NO_VALIDATE_ARCHITECTURES: boolean +#]] +function(flamegpu_visualiser_init_cuda_architectures) + # Handle argument parsing + cmake_parse_arguments(CICA + "NO_VALIDATE_ARCHITECTURES" + "PROJECT" + "" + ${ARGN} + ) + # Detect if there are user provided architectures or not, form the cache or environment + set(flamegpu_visualiser_ARCH_FROM_ENV_OR_CACHE FALSE) + if(DEFINED CMAKE_CUDA_ARCHITECTURES OR DEFINED ENV{CUDAARCHS}) + set(flamegpu_visualiser_ARCH_FROM_ENV_OR_CACHE TRUE) + endif() + # promote the stored value to parent(file) scope for later use. This might need to become internal cache, but hopefully not. + set(flamegpu_visualiser_ARCH_FROM_ENV_OR_CACHE ${flamegpu_visualiser_ARCH_FROM_ENV_OR_CACHE} PARENT_SCOPE) + # If the user does not want architecture validation to occur, set a parent scoped variable to be checked later. + if(CICA_NO_VALIDATE_ARCHITECTURES) + # If a project was also specified, append to a list and promote to the parent scope + if(CICA_PROJECT) + list(APPEND flamegpu_visualiser_NO_VALIDATE_ARCHITECTURES_PROJECTS ${CICA_PROJECT}) + set(flamegpu_visualiser_NO_VALIDATE_ARCHITECTURES_PROJECTS ${flamegpu_visualiser_NO_VALIDATE_ARCHITECTURES_PROJECTS} PARENT_SCOPE) + else() + # Otherwise just set a parent scoped variable + set(flamegpu_visualiser_NO_VALIDATE_ARCHITECTURES ${CICA_NO_VALIDATE_ARCHITECTURES} PARENT_SCOPE) + endif() + endif() + # If a project name was provided, inject code into the PROJECT command. Users must call flamegpu_visualiser_set_cuda_architectures otherwise + if(CICA_PROJECT) + set(CMAKE_PROJECT_${CICA_PROJECT}_INCLUDE "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/CUDAArchitecturesProjectInclude.cmake" PARENT_SCOPE) + endif() +endfunction() + +#[[[ +# Set the CMAKE_CUDA_ARCHITECTURES value to the environment/cache provided value, or generate the CUDA version appropraite default. +# +# Set teh CMAKE_CUDA_ARCHITECTURES cache variable to a user priovided or a library-arpropriate default. +# If the CUDAARCHS environment variable, or CMAKE_CUDA_ARCHITECTURES cache variable did not specify a value before the CUDA lanagugea was enabled, +# build an appropraite default option, based on the CMake and NVCC verison. +# Effectively all-major (-real for all major achitectures, and PTX for the most reent.) +# +# If the user provided a value, it will be validated against nvcc --help unless NO_VALIDATE_ARCHITECTURES is set, or was set in a previous call to flamegpu_visualiser_init_cuda_architectures without a PROJECT. +# +# CUDA must be enabled as a language prior to this method being called. +# +# :keyword NO_VALIDATE_ARCHITECTURES: Do not validate the passed arguments against nvcc --help output +# :type NO_VALIDATE_ARCHITECTURES: boolean +#]] +function(flamegpu_visualiser_set_cuda_architectures) + # Handle argument parsing + cmake_parse_arguments(CSCA + "NO_VALIDATE_ARCHITECTURES" + "" + "" + ${ARGN} + ) + # This function requires that the CUDA language is enabled on the current project. + if(NOT CMAKE_CUDA_COMPILER_LOADED) + # If in the inkected project code, give a different error message + if(DEFINED flamegpu_visualiser_IN_PROJECT_INCLUDE AND flamegpu_visualiser_IN_PROJECT_INCLUDE) + message(FATAL_ERROR + " ${CMAKE_CURRENT_FUNCTION} requires the CUDA lanaguage to be enabled\n" + " Please either:\n" + " * use project( LANGUAGES CUDA)\n" + " * call flamegpu_visualiser_init_cuda_architectures() without the PROJECT argument, and explcitly call ${CMAKE_CURRENT_FUNCTION}() after enable_language(CUDA).") + else() + # not in project injection, so only suggest enabled + message(FATAL_ERROR + " ${CMAKE_CURRENT_FUNCTION} requires the CUDA language to be enabled.\n" + " Please call enable_language(CUDA) prior to ${CMAKE_CURRENT_FUNCTION}()") + endif() + + endif() + # Query NVCC for the acceptable SM values, this is used in multiple places + if(NOT DEFINED SUPPORTED_CUDA_ARCHITECTURES_NVCC) + 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_ARCHITECTURES_NVCC "${NVCC_HELP_STR}" ) + # Strip just the numeric component + string(REGEX REPLACE "'(sm|compute)_([0-9]+)'" "\\2" SUPPORTED_CUDA_ARCHITECTURES_NVCC "${SUPPORTED_CUDA_ARCHITECTURES_NVCC}" ) + # Remove dupes and sort to build the correct list of supported CUDA_ARCH. + list(REMOVE_DUPLICATES SUPPORTED_CUDA_ARCHITECTURES_NVCC) + list(REMOVE_ITEM SUPPORTED_CUDA_ARCHITECTURES_NVCC "") + list(SORT SUPPORTED_CUDA_ARCHITECTURES_NVCC) + # 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? + set(SUPPORTED_CUDA_ARCHITECTURES_NVCC ${SUPPORTED_CUDA_ARCHITECTURES_NVCC} PARENT_SCOPE) + endif() + list(LENGTH SUPPORTED_CUDA_ARCHITECTURES_NVCC SUPPORTED_CUDA_ARCHITECTURES_NVCC_COUNT) + # If we already have a cuda architectures value, validate it as CMake doesn't on its own. Unless the caller asked us not to. + if(flamegpu_visualiser_ARCH_FROM_ENV_OR_CACHE AND NOT CMAKE_CUDA_ARCHITECTURES STREQUAL "" + AND NOT CSCA_NO_VALIDATE_ARCHITECTURES + AND NOT flamegpu_visualiser_NO_VALIDATE_ARCHITECTURES + AND (DEFINED PROJECT_NAME AND NOT ${PROJECT_NAME} IN_LIST flamegpu_visualiser_NO_VALIDATE_ARCHITECTURES_PROJECTS)) + # Get the number or architectures specified + list(LENGTH CMAKE_CUDA_ARCHITECTURES arch_count) + # Prep a bool to track if a single special value is being used or not + set(using_keyword_arch FALSE) + # native requires CMake >= 3.24, and must be the only option. + if("native" IN_LIST CMAKE_CUDA_ARCHITECTURES) + # Error if CMake is too old + if(CMAKE_VERSION VERSION_LESS 3.24) + message(FATAL_ERROR + " CMAKE_CUDA_ARCHITECTURES value `native` requires CMake >= 3.24.\n" + " CMAKE_CUDA_ARCHITECTURES=\"${CMAKE_CUDA_ARCHITECTURES}\"") + endif() + # Error if there are multiple architectures specified. + if(arch_count GREATER 1) + message(FATAL_ERROR + " CMAKE_CUDA_ARCHITECTURES value `native` must be the only value specified.\n" + " CMAKE_CUDA_ARCHITECTURES=\"${CMAKE_CUDA_ARCHITECTURES}\"") + endif() + set(using_keyword_arch TRUE) + endif() + # all requires 3.23, and must be the sole value. + if("all" IN_LIST CMAKE_CUDA_ARCHITECTURES) + # Error if CMake is too old + if(CMAKE_VERSION VERSION_LESS 3.23) + message(FATAL_ERROR + " CMAKE_CUDA_ARCHITECTURES value `all` requires CMake >= 3.23.\n" + " CMAKE_CUDA_ARCHITECTURES=\"${CMAKE_CUDA_ARCHITECTURES}\"") + endif() + # Error if there are multiple architectures specified. + if(arch_count GREATER 1) + message(FATAL_ERROR + " CMAKE_CUDA_ARCHITECTURES value `all` must be the only value specified.\n" + " CMAKE_CUDA_ARCHITECTURES=\"${CMAKE_CUDA_ARCHITECTURES}\"") + endif() + set(using_keyword_arch TRUE) + endif() + # all-major requires 3.23, and must be the sole value. + if("all-major" IN_LIST CMAKE_CUDA_ARCHITECTURES) + # Error if CMake is too old + if(CMAKE_VERSION VERSION_LESS 3.23) + message(FATAL_ERROR + " CMAKE_CUDA_ARCHITECTURES value `all-major` requires CMake >= 3.23.\n" + " CMAKE_CUDA_ARCHITECTURES=\"${CMAKE_CUDA_ARCHITECTURES}\"") + endif() + # Error if there are multiple architectures specified. + if(arch_count GREATER 1) + message(FATAL_ERROR + " CMAKE_CUDA_ARCHITECTURES value `all-major` must be the only value specified.\n" + " CMAKE_CUDA_ARCHITECTURES=\"${CMAKE_CUDA_ARCHITECTURES}\"") + endif() + set(using_keyword_arch TRUE) + endif() + # Cmake 3.18+ expects a list of 1 or more , -real or -virtual. + # CMake isn't aware of the exact SMS supported by the CUDA version afiak, but we have already queired nvcc for this (once and only once) + # If nvcc parsing worked and a single keyword option is not being used, attempt the validation: + if(SUPPORTED_CUDA_ARCHITECTURES_NVCC_COUNT GREATER 0 AND NOT using_keyword_arch) + # Transform a copy of the list of supported architectures, to hopefully just contain numbers + set(archs ${CMAKE_CUDA_ARCHITECTURES}) + list(TRANSFORM archs REPLACE "(\-real|\-virtual)" "") + # If any of the specified architectures are not in the nvcc reported list, error. + foreach(ARCH IN LISTS archs) + if(NOT ARCH IN_LIST SUPPORTED_CUDA_ARCHITECTURES_NVCC) + message(FATAL_ERROR + " CMAKE_CUDA_ARCHITECTURES value `${ARCH}` is not supported by nvcc ${CMAKE_CUDA_COMPILER_VERSION}.\n" + " Supported architectures based on nvcc --help: \n" + " ${SUPPORTED_CUDA_ARCHITECTURES_NVCC}\n") + endif() + endforeach() + unset(archs) + endif() + else() + # Otherwise, set a mulit-arch default for good compatibility and performacne + # If we're using CMake >= 3.23, we can just use all-major, though we then have to find the minimum a different way? + if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.23") + set(CMAKE_CUDA_ARCHITECTURES "all-major") + else() + # For CMake < 3.23, we have to make our own all-major equivalent. + # If we have nvcc help outut, we can generate this from all the elements that end with a 0 (and the first element if it does not.) + if(SUPPORTED_CUDA_ARCHITECTURES_NVCC_COUNT GREATER 0) + # If the lowest support arch is not major, add it to the default + list(GET SUPPORTED_CUDA_ARCHITECTURES_NVCC 0 lowest_supported) + if(NOT lowest_supported MATCHES "0$") + list(APPEND default_archs ${lowest_supported}) + endif() + unset(lowest_supported) + # For each architecture, if it is major add it to the default list + foreach(ARCH IN LISTS SUPPORTED_CUDA_ARCHITECTURES_NVCC) + if(ARCH MATCHES "0$") + list(APPEND default_archs ${ARCH}) + endif() + endforeach() + else() + # If nvcc help output parsing failed, just use an informed guess option from CUDA 11.8 + set(default_archs "35;50;60;70;80") + if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.8) + list(APPEND default_archs "90") + endif() + message(AUTHOR_WARNING + " ${CMAKE_CURRENT_FUNCTION} failed to parse NVCC --help output for default architecture generation\n" + " Using ${default_archs} based on CUDA 11.0 to 11.8." + ) + endif() + # We actually want real for each arch, then virtual for the final, but only for library-provided values, to only embed one arch worth of ptx. + # So grab the last element of the list + list(GET default_archs -1 final) + # append -real to each element, to not embed ptx for that arch too + list(TRANSFORM default_archs APPEND "-real") + # add the -virtual version of the final element + list(APPEND default_archs "${final}-virtual") + # Set the value + set(CMAKE_CUDA_ARCHITECTURES ${default_archs}) + #unset local vars + unset(default_archs) + endif() + endif() + # Promote the value to the parent's scope, where it is needed on the first invokation (might be fine with cache, but just incase) + set(CMAKE_CUDA_ARCHITECTURES "${CMAKE_CUDA_ARCHITECTURES}" PARENT_SCOPE) + # Promote the value to the cache for reconfigure persistence, as the enable_language sets it on the cache + set(CMAKE_CUDA_ARCHITECTURES "${CMAKE_CUDA_ARCHITECTURES}" CACHE STRING "CUDA architectures" FORCE) +endfunction() + +#[[[ +# Get the minimum CUDA Architecture from the current CMAKE_CUDA_ARCHITECTURES value if possible +# +# Gets the minimum CUDA architectuyre from teh current value of CMAKE_CUDA_ARCHITECTURES if possible, storing the result in the pass-by-reference return value +# Supports CMAKE_CUDA_ARCHITECTURE values including integers, -real post-fixed integers, -virtual post-fixed integers, all-major and all. +# Does not support native, instead returning -1. +# all or all-major are supported by querying nvcc --help to detect the minimum built for. +# +# CUDA must be enabled as a language prior to this method being called, and CMAKE_CUDA_ARCHITECTURES must be defined and non-empty +# +# :param minimum_architecture: the minimum architecture set in CMAKE_CUDA_ARCHITECTURES +# :type NO_VALIDATE_ARCHITECTURES: integer +#]] +function(flamegpu_visualiser_get_minimum_cuda_architecture minimum_architecture) + if(DEFINED CMAKE_CUDA_ARCHITECTURES) + # Cannot deal with native gracefully + if("native" IN_LIST CMAKE_CUDA_ARCHITECTURES) + # If it's native, we would need to exeucte some CUDA code to detect this. For now set -1. + set(flamegpu_visualiser_minimum_cuda_architecture -1) + # if all/all-major is specified, detect via nvcc --help. It must be the only option (CMake doens't validate this and generates bad gencodes otherwise) + elseif("all-major" IN_LIST CMAKE_CUDA_ARCHITECTURES OR "all" IN_LIST CMAKE_CUDA_ARCHITECTURES) + # Query NVCC for the acceptable SM values. + if(NOT DEFINED SUPPORTED_CUDA_ARCHITECTURES_NVCC) + 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_ARCHITECTURES_NVCC "${NVCC_HELP_STR}" ) + # Strip just the numeric component + string(REGEX REPLACE "'(sm|compute)_([0-9]+)'" "\\2" SUPPORTED_CUDA_ARCHITECTURES_NVCC "${SUPPORTED_CUDA_ARCHITECTURES_NVCC}" ) + # Remove dupes and sort to build the correct list of supported CUDA_ARCH. + list(REMOVE_DUPLICATES SUPPORTED_CUDA_ARCHITECTURES_NVCC) + list(REMOVE_ITEM SUPPORTED_CUDA_ARCHITECTURES_NVCC "") + list(SORT SUPPORTED_CUDA_ARCHITECTURES_NVCC) + # 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? + set(SUPPORTED_CUDA_ARCHITECTURES_NVCC ${SUPPORTED_CUDA_ARCHITECTURES_NVCC} PARENT_SCOPE) + endif() + list(LENGTH SUPPORTED_CUDA_ARCHITECTURES_NVCC SUPPORTED_CUDA_ARCHITECTURES_NVCC_COUNT) + if(SUPPORTED_CUDA_ARCHITECTURES_NVCC_COUNT GREATER 0) + # For both all and all-major, the lowest arch should be the lowest supported. This is true for CUDA <= 11.8 atleast. + list(GET SUPPORTED_CUDA_ARCHITECTURES_NVCC 0 lowest) + set(flamegpu_visualiser_minimum_cuda_architecture ${lowest}) + else() + # If nvcc didn't give anything useful, set -1. + set(flamegpu_visualiser_minimum_cuda_architecture -1) + endif() + else() + # Otherwise it should just be a list of one or more /-real/ + # Copy the list + set(archs ${CMAKE_CUDA_ARCHITECTURES}) + # Replace occurances of -real and -virtual + list(TRANSFORM archs REPLACE "(\-real|\-virtual)" "") + # Sort the list numerically (natural option + list(SORT archs COMPARE NATURAL ORDER ASCENDING) + # Get the first element + list(GET archs 0 lowest) + # Set the value for later returning + set(flamegpu_visualiser_minimum_cuda_architecture ${lowest}) + endif() + # Set the return value as required, effectively pass by reference. + set(${minimum_architecture} ${flamegpu_visualiser_minimum_cuda_architecture} PARENT_SCOPE) + else() + message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: CMAKE_CUDA_ARCHITECTURES is not set or is empty") + endif() +endfunction() diff --git a/cmake/CUDAArchitecturesProjectInclude.cmake b/cmake/CUDAArchitecturesProjectInclude.cmake new file mode 100644 index 0000000..c0d6611 --- /dev/null +++ b/cmake/CUDAArchitecturesProjectInclude.cmake @@ -0,0 +1,9 @@ +# CMake file to be injected into a project via CMAKE_PROJECT_INCLUDE +# If CUDA is enabled, call a CMake function which gracefully sets a library-useful + +# Set a locally scoped cmake variable, to alter the error message within. +set(flamegpu_visualiser_IN_PROJECT_INCLUDE ON) +# Call the appropraite command to set CMAKE_CUDA_ARCHITECTURES to the user-provided value, the exising value, or a sane libray-provided defualt +flamegpu_visualiser_set_cuda_architectures() +# Unset the variable used to alter behaviour in set_cuda_architectures +unset(flamegpu_visualiser_IN_PROJECT_INCLUDE) \ No newline at end of file diff --git a/cmake/CheckCompilerFunctionality.cmake b/cmake/CheckCompilerFunctionality.cmake new file mode 100644 index 0000000..4f038fc --- /dev/null +++ b/cmake/CheckCompilerFunctionality.cmake @@ -0,0 +1,147 @@ +include_guard(GLOBAL) + +# Define a cmake function which checks that CUDA and the host compiler are functional. +# Failure only results in CMake warnings not Errors, so that documentation only builds will function. +function(flamegpu_visualiser_check_compiler_functionality) + # If the result variable is already defined, this has already been called once, so don't check agian. + if(DEFINED FLAMEGPU_VISUALISER_CheckCompilerFunctionality_RESULT) + return() + endif() + + # Ensure that required languages are avialable. + # Enabling the languages must however be perfomed in file scope, so do this in the root cmake after docs only checks have been found. + include(CheckLanguage) + check_language(CXX) + if(NOT CMAKE_CXX_COMPILER) + message(WARNING "CXX Language Support Not Found") + set(FLAMEGPU_VISUALISER_CheckCompilerFunctionality_RESULT "NO" PARENT_SCOPE) + return() + endif() + enable_language(CXX) + check_language(CUDA) + if(NOT CMAKE_CUDA_COMPILER) + message(WARNING "CUDA Language Support Not Found") + set(FLAMEGPU_VISUALISER_CheckCompilerFunctionality_RESULT "NO" PARENT_SCOPE) + return() + endif() + enable_language(CUDA) + + # We need c++17 std::filesytem, but not all compilers which claim to implement c++17 provide filesystem (GCC 7) + if(NOT DEFINED CUDA_STD_FILESYSTEM) + # Disable CMAKE_CUDA_ARCHTIECTURES if not already controlled. This is scoped to the function so safe to control. + if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES OR "${CMAKE_CUDA_ARCHITECTURES}" STREQUAL "") + set(CMAKE_CUDA_ARCHITECTURES "OFF") + endif() + try_compile( + CUDA_STD_FILESYSTEM + "${CMAKE_CURRENT_BINARY_DIR}/try_compile" + "${CMAKE_CURRENT_LIST_DIR}/CheckCompilerFunctionality/CheckStdFilesystem.cu" + CXX_STANDARD 17 + CUDA_STANDARD 17 + CXX_STANDARD_REQUIRED "ON" + ) + endif() + # If an error occured while building the snippet, report a warning + if(NOT CUDA_STD_FILESYSTEM) + # If the GCC versions is known to be bad, give an appropriate error + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.1) + message(WARNING + "${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION} does not provide even in --std=c++17 mode.\n" + " Please use GCC >= 8.1.\n" + " \n") + else() + # If the gcc version is not a known problem, emit a generic error. + message(WARNING + " error with ${CMAKE_CUDA_COMPILER_ID} ${CMAKE_CUDA_COMPILER_VERSION} and ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}.") + endif() + # Set the result variable to a false-like value + set(FLAMEGPU_VISUALISER_CheckCompilerFunctionality_RESULT "NO" PARENT_SCOPE) + return() + endif() + + # Original releases of GCC 10.3.0 and 11.1.0 included a bug preventing the use of in . + # This was patched in subsequent versions, and backported in the release branches, but the broken version is still distributed in some cases (i.e. Ubuntu 20.04, but not 21.04). + # See https://github.com/FLAMEGPU/FLAMEGPU2/issues/575, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100102 + if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + # Try to compile the test case file for inclusion of chrono. + if(NOT DEFINED GCC_CUDA_STDCHRONO) + # Disable CMAKE_CUDA_ARCHTIECTURES if not already controlled. This is scoped to the function so safe to control. + if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES OR "${CMAKE_CUDA_ARCHITECTURES}" STREQUAL "") + set(CMAKE_CUDA_ARCHITECTURES "OFF") + endif() + try_compile( + GCC_CUDA_STDCHRONO + "${CMAKE_CURRENT_BINARY_DIR}/try_compile" + "${CMAKE_CURRENT_LIST_DIR}/CheckCompilerFunctionality/CheckStdChrono.cu" + CXX_STANDARD 17 + CUDA_STANDARD 17 + CXX_STANDARD_REQUIRED "ON" + ) + endif() + # If an error occured while building the snippet, report a warning + if(NOT GCC_CUDA_STDCHRONO) + # If the GCC versions is known to be bad, give an appropriate error + if(CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 10.3.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 11.1.0) + message(WARNING + "GCC ${CMAKE_CXX_COMPILER_VERSION} is incompatible with CUDA due to a bug in the implementation.\n" + " Please use an alternative GCC, or a patched version of GCC ${CMAKE_CXX_COMPILER_VERSION}.\n" + " \n" + " See the following for more information:\n" + " https://github.com/FLAMEGPU/FLAMEGPU2/issues/575\n" + " https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100102\n") + else() + # If the gcc version is not a known problem, emit a generic error. + message(WARNING + " not usable with ${CMAKE_CUDA_COMPILER_ID} ${CMAKE_CUDA_COMPILER_VERSION} and ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}.") + endif() + # Set the result variable to a false-like value + set(FLAMEGPU_VISUALISER_CheckCompilerFunctionality_RESULT "NO" PARENT_SCOPE) + return() + endif() + endif() + + # GCC 9 + CUDA 11.0 + std=c++17 errors when attempting to compile std::vector>::push_back. + # This is the only known bad combination, but let's check more often just in case. + # We no longer use this (intentionally) so if the error occurs emit a warning but not error? + # See https://github.com/FLAMEGPU/FLAMEGPU2/issues/575, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100102 + if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + # Try to compile the test case file for inclusion of chrono. + if(NOT DEFINED GCC_CUDA_VECTOR_TUPLE_PUSHBACK) + # Disable CMAKE_CUDA_ARCHTIECTURES if not already controlled. This is scoped to the function so safe to control. + if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES OR "${CMAKE_CUDA_ARCHITECTURES}" STREQUAL "") + set(CMAKE_CUDA_ARCHITECTURES "OFF") + endif() + try_compile( + GCC_CUDA_VECTOR_TUPLE_PUSHBACK + "${CMAKE_CURRENT_BINARY_DIR}/try_compile" + "${CMAKE_CURRENT_LIST_DIR}/CheckCompilerFunctionality/CheckVectorTuplePushBack.cu" + CXX_STANDARD 17 + CUDA_STANDARD 17 + CXX_STANDARD_REQUIRED "ON" + ) + endif() + # If an error occured while building MWE emit a dev warning. + if(NOT GCC_CUDA_VECTOR_TUPLE_PUSHBACK) + # If the GCC versions is known to be bad, give an appropriate error + message(AUTHOR_WARNING + "std::vector>::push_back cannot be compiled with ${CMAKE_CUDA_COMPILER_ID} ${CMAKE_CUDA_COMPILER_VERSION} and ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION} with --std=c++17.\n" + "Consider using a different ${CMAKE_CUDA_COMPILER_ID} and ${CMAKE_CXX_COMPILER_ID} combination as errors may be encountered.\n" + "See https://github.com/FLAMEGPU/FLAMEGPU2/issues/650") + # Not erroring, so don't change the output value, just emit the above developer warning + + # The compilation error is somewhat tempremental, so always emit a warning for the known bad combination + elseif(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "11.0" AND CMAKE_CUDA_COMPILER_VERSION VERSION_LESS "11.1" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "9" AND CMAKE_CXX_COMILER_VERSION VERSION_LESS "10") + message(AUTHOR_WARNING + "CUDA 11.0 with g++ 9 in c++17 mode may encounter compiler segmentation faults with 'std::vector>::push_back'.\n" + "Consider using CUDA 11.1+ or gcc 8 to avoid potential issues.\n" + "See https://github.com/FLAMEGPU/FLAMEGPU2/issues/650") + endif() + endif() + + # If we made it this far, set the result variable to be truthy + set(FLAMEGPU_VISUALISER_CheckCompilerFunctionality_RESULT "YES" PARENT_SCOPE) +endfunction() + + +# Call the function imediately, so the file only needs to be included. +flamegpu_visualiser_check_compiler_functionality() diff --git a/cmake/CheckCompilerFunctionality/CheckStdChrono.cu b/cmake/CheckCompilerFunctionality/CheckStdChrono.cu new file mode 100644 index 0000000..0627684 --- /dev/null +++ b/cmake/CheckCompilerFunctionality/CheckStdChrono.cu @@ -0,0 +1,7 @@ +// Including chrono is enough to trigger the compilation error being tested for. See: +// https://github.com/FLAMEGPU/FLAMEGPU2/issues/575 +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100102 +#include + +// CMake try_compile performs a link step, so main is required +int main() { return 0; } \ No newline at end of file diff --git a/cmake/CheckCompilerFunctionality/CheckStdFilesystem.cu b/cmake/CheckCompilerFunctionality/CheckStdFilesystem.cu new file mode 100644 index 0000000..11f1199 --- /dev/null +++ b/cmake/CheckCompilerFunctionality/CheckStdFilesystem.cu @@ -0,0 +1,4 @@ +// We require std::filesytem, but just requireing std=c++17 does not enforce this for all compilers, so check it works. (I.e. GCC < 8 is a problem.) +// CMake doesn't appear to have knowledge of this feature. +#include +int main() { return 0; } \ No newline at end of file diff --git a/cmake/CheckCompilerFunctionality/CheckVectorTuplePushBack.cu b/cmake/CheckCompilerFunctionality/CheckVectorTuplePushBack.cu new file mode 100644 index 0000000..91f81fd --- /dev/null +++ b/cmake/CheckCompilerFunctionality/CheckVectorTuplePushBack.cu @@ -0,0 +1,11 @@ +// GCC 9 + CUDA 11.0 + --std=c++17 errors during complation of std::vector>::push_back. +// Test this for the configured CUDA, incase it is OK on the given system +// See https://github.com/FLAMEGPU/FLAMEGPU2/issues/650 for more information +#include +#include + +int main (int argc, char * argv[]) { + std::vector> v; + std::tuple t = {1.f}; + v.push_back(t); // segmentation fault +} diff --git a/cmake/CommonCompilerSettings.cmake b/cmake/CommonCompilerSettings.cmake index 3a62d6d..d376039 100644 --- a/cmake/CommonCompilerSettings.cmake +++ b/cmake/CommonCompilerSettings.cmake @@ -1,7 +1,8 @@ +include_guard(GLOBAL) # 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) +function(flamegpu_visualiser_common_compiler_settings) # Parse the expected arguments, prefixing variables. cmake_parse_arguments( CCS @@ -13,9 +14,9 @@ function(CommonCompilerSettings) # 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") + message( FATAL_ERROR "flamegpu_visualiser_common_compiler_settings: 'TARGET' argument required") elseif(NOT TARGET ${CCS_TARGET} ) - message( FATAL_ERROR "function(CommonCompilerSettings): TARGET '${CCS_TARGET}' is not a valid target") + message( FATAL_ERROR "flamegpu_visualiser_common_compiler_settings: TARGET '${CCS_TARGET}' is not a valid target") endif() # Add device debugging symbols to device builds of CUDA objects @@ -34,15 +35,6 @@ function(CommonCompilerSettings) 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+) diff --git a/cmake/OutOfSourceOnly.cmake b/cmake/OutOfSourceOnly.cmake index 2041e45..9a93a1a 100644 --- a/cmake/OutOfSourceOnly.cmake +++ b/cmake/OutOfSourceOnly.cmake @@ -1,5 +1,7 @@ +include_guard(GLOBAL) + # Define a cmake function which emits a fatal error if the source directory and binary directory are the same. -function(EnforceOutOfSourceBuilds) +function(flamegpu_visualiser_enforce_out_of_source_builds) # 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) @@ -15,5 +17,5 @@ function(EnforceOutOfSourceBuilds) endfunction() # Call the function imediately, so the file only needs to be included. -EnforceOutOfSourceBuilds() +flamegpu_visualiser_enforce_out_of_source_builds() diff --git a/cmake/SetTargetFolder.cmake b/cmake/SetTargetFolder.cmake new file mode 100644 index 0000000..2f86fd0 --- /dev/null +++ b/cmake/SetTargetFolder.cmake @@ -0,0 +1,17 @@ +include_guard(GLOBAL) + +#----------------------------------------------------------------------- +# a macro that only sets the FOLDER target property if it's +# "appropriate" +# Borrowed from cmake's own CMakeLists.txt +#----------------------------------------------------------------------- +macro(flamegpu_visualiser_set_target_folder tgt folder) + if(CMAKE_USE_FOLDERS) + set_property(GLOBAL PROPERTY USE_FOLDERS ON) + if(TARGET ${tgt}) # AND MSVC # AND MSVC stops all lint from being set with folder + set_property(TARGET "${tgt}" PROPERTY FOLDER "${folder}") + endif() + else() + set_property(GLOBAL PROPERTY USE_FOLDERS OFF) + endif() +endmacro() \ No newline at end of file diff --git a/cmake/cpplint.cmake b/cmake/cpplint.cmake index 12e8632..6727486 100644 --- a/cmake/cpplint.cmake +++ b/cmake/cpplint.cmake @@ -1,75 +1,98 @@ -find_file(CPPLINT NAMES cpplint cpplint.exe) -if(CPPLINT) - # Create the all_lint meta target if it does not exist - if(NOT TARGET all_lint) +# Only include this once +include_guard(GLOBAL) + +include(${CMAKE_CURRENT_LIST_DIR}/SetTargetFolder.cmake) + +# Find CPPLINT, storing in a variable CPPLINT_EXECUTABLE +find_file(CPPLINT_EXECUTABLE NAMES cpplint cpplint.exe) +# find_file sets a cache var, so mark as advanced to hide from the GUI by default +mark_as_advanced(CPPLINT_EXECUTABLE) + +# If CPPLINT_EXECUTABLE was not found, emit a warning. This should only be once due to the include guard. +if(NOT CPPLINT_EXECUTABLE) + # Only raises a STATUS not a WARNING/AUTHOR_WARNING for CI's benefit + message(STATUS + " cpplint: NOT FOUND!\n" + " Lint projects will not be generated.\n" + " Please install cpplint as described on https://pypi.python.org/pypi/cpplint.\n" + " In most cases command 'pip install cpplint' should be sufficient.") +endif() + +# Decalre a function to create the all_lint target, if cpplint was found. + +# Create an all_lint target if cpplint is available +function(flamegpu_visualiser_create_all_lint_target) + if(CPPLINT_EXECUTABLE AND NOT TARGET all_lint) + # Add a custom target to lint all child projects. Dependencies are specified in child projects. add_custom_target(all_lint) + # Don't trigger this target on ALL_BUILD or Visual Studio 'Rebuild Solution' set_target_properties(all_lint PROPERTIES EXCLUDE_FROM_ALL TRUE) + # set_target_properties(all_lint PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD TRUE) + # Put all_lint within Lint filter + flamegpu_visualiser_set_target_folder(all_lint "Lint") endif() +endfunction() + +# Define a function to add a lint target. +function(flamegpu_visualiser_new_linter_target NAME SRC) + # if cpplint has not been found, do nothing + if(NOT CPPLINT_EXECUTABLE) + return() + endif() + # Create the all_lint meta target if it does not exist + flamegpu_visualiser_create_all_lint_target() # Define a cmake function for adding a new lint target. - function(new_linter_target NAME SRC) - cmake_parse_arguments( - NEW_LINTER_TARGET - "" - "" - "EXCLUDE_FILTERS" - ${ARGN}) - # Don't lint external files - list(FILTER SRC EXCLUDE REGEX "^${FLAMEGPU_ROOT}/externals/.*") - # Don't lint user provided list of regular expressions. - foreach(EXCLUDE_FILTER ${NEW_LINTER_TARGET_EXCLUDE_FILTERS}) - list(FILTER SRC EXCLUDE REGEX "${EXCLUDE_FILTER}") - endforeach() + cmake_parse_arguments( + NEW_LINTER_TARGET + "" + "" + "EXCLUDE_FILTERS" + ${ARGN}) + # Don't lint external files + list(FILTER SRC EXCLUDE REGEX "^${FLAMEGPU_ROOT}/externals/.*") + # Don't lint user provided list of regular expressions. + foreach(EXCLUDE_FILTER ${NEW_LINTER_TARGET_EXCLUDE_FILTERS}) + list(FILTER SRC EXCLUDE REGEX "${EXCLUDE_FILTER}") + endforeach() - # Only lint accepted file type extensions h++, hxx, cuh, cu, c, c++, cxx, cc, hpp, h, cpp, hh - list(FILTER SRC INCLUDE REGEX ".*\\.(h\\+\\+|hxx|cuh|cu|c|c\\+\\+|cxx|cc|hpp|h|cpp|hh)$") + # Only lint accepted file type extensions h++, hxx, cuh, cu, c, c++, cxx, cc, hpp, h, cpp, hh + list(FILTER SRC INCLUDE REGEX ".*\\.(h\\+\\+|hxx|cuh|cu|c|c\\+\\+|cxx|cc|hpp|h|cpp|hh)$") - # Build a list of arguments to pass to CPPLINT - LIST(APPEND CPPLINT_ARGS "") + # Build a list of arguments to pass to CPPLINT + LIST(APPEND CPPLINT_ARGS "") - # Specify output format for msvc highlighting - if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - LIST(APPEND CPPLINT_ARGS "--output" "vs7") - endif() - # Set the --repository argument if included as a sub project. - if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) - # Use find the repository root via git, to pass to cpplint. - execute_process(COMMAND git rev-parse --show-toplevel - WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" - RESULT_VARIABLE git_repo_found - OUTPUT_VARIABLE abs_repo_root - OUTPUT_STRIP_TRAILING_WHITESPACE) - if(git_repo_found EQUAL 0) - LIST(APPEND CPPLINT_ARGS "--repository=${abs_repo_root}") - endif() + # Specify output format for msvc highlighting + if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + LIST(APPEND CPPLINT_ARGS "--output" "vs7") + endif() + # Set the --repository argument if included as a sub project. + if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + # Use find the repository root via git, to pass to cpplint. + execute_process(COMMAND git rev-parse --show-toplevel + WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" + RESULT_VARIABLE git_repo_found + OUTPUT_VARIABLE abs_repo_root + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(git_repo_found EQUAL 0) + LIST(APPEND CPPLINT_ARGS "--repository=${abs_repo_root}") endif() - # Add the lint_ target - add_custom_target( - "lint_${PROJECT_NAME}" - COMMAND ${CPPLINT} ${CPPLINT_ARGS} - ${SRC} - ) + endif() + # Add the lint_ target + add_custom_target( + "lint_${PROJECT_NAME}" + COMMAND ${CPPLINT_EXECUTABLE} ${CPPLINT_ARGS} + ${SRC} + ) - # Don't trigger this target on ALL_BUILD or Visual Studio 'Rebuild Solution' - set_target_properties("lint_${NAME}" PROPERTIES EXCLUDE_FROM_ALL TRUE) - # Add the custom target as a dependency of the global lint target - if(TARGET all_lint) - add_dependencies(all_lint lint_${NAME}) - endif() - # Put within Lint filter - if (CMAKE_USE_FOLDERS) - set_property(GLOBAL PROPERTY USE_FOLDERS ON) - set_property(TARGET "lint_${PROJECT_NAME}" PROPERTY FOLDER "Lint") - endif () - endfunction() -else() - # Don't create this message multiple times - if(NOT COMMAND add_flamegpu_executable) - message( - " cpplint: NOT FOUND!\n" - " Lint projects will not be generated.\n" - " Please install cpplint as described on https://pypi.python.org/pypi/cpplint.\n" - " In most cases command 'pip install --user cpplint' should be sufficient.") - function(new_linter_target NAME SRC) - endfunction() + # Don't trigger this target on ALL_BUILD or Visual Studio 'Rebuild Solution' + set_target_properties("lint_${NAME}" PROPERTIES EXCLUDE_FROM_ALL TRUE) + # Add the custom target as a dependency of the global lint target + if(TARGET all_lint) + add_dependencies(all_lint lint_${NAME}) endif() -endif() \ No newline at end of file + # Put within Lint filter + if (CMAKE_USE_FOLDERS) + set_property(GLOBAL PROPERTY USE_FOLDERS ON) + set_property(TARGET "lint_${PROJECT_NAME}" PROPERTY FOLDER "Lint") + endif () +endfunction() diff --git a/cmake/cuda_arch.cmake b/cmake/cuda_arch.cmake deleted file mode 100644 index 482a1ac..0000000 --- a/cmake/cuda_arch.cmake +++ /dev/null @@ -1,134 +0,0 @@ -# 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() - - # 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(SUPPORTED_CUDA_ARCH ${SUPPORTED_CUDA_ARCH} PARENT_SCOPE) - endif() - endif() - - - # 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() - - 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() - - - # 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}") - 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 deleted file mode 100644 index b9d5af2..0000000 --- a/cmake/cxxstd.cmake +++ /dev/null @@ -1,52 +0,0 @@ -# Select the CXX standard to use, FLAME GPU 2 is c++17 only -if(NOT FLAMEGPU_CXX_STD) - # No need to check CMake version, as our minimum (3.18) supports CUDA c++17 - - # Check the CUDA version, CUDA 11.0 adds CXX 17 support - if(CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 11.0.0) - # Fatal Error. - message(FATAL_ERROR "CUDA ${CMAKE_CUDA_COMPILER_VERSION} does not support -std=c++17") - endif() - - # Check MSVC version, VS 2017 version 15.3 added /std:c++17 - 1911 - # Inside source code, __STDC_VERSION__ can be used on msvc, which will have a value such as 201710L for c++17 - if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.11) - message(FATAL_ERROR "MSVC ${CMAKE_CXX_COMPILER_VERSION} does not support -std=c++17 (>= 19.11 required)") - endif() - endif() - - # GCC 8 required for - if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.1) - message(FATAL_ERROR "GCC >= 8.1 required for -std=c++17 ") - endif() - - # Set a cmake variable so this is only calcualted once, and can be applied afterwards. - set(FLAMEGPU_CXX_STD 17) - - # Emit a developer warning if using CUDA 11.0 and GCC 9 in c++17 mode re std::vector>::push_back - # @todo - promote this to a try compile, and issue the (author) warning if the erorr is encountered? - if( CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "11.0" - AND CMAKE_CUDA_COMPILER_VERSION VERSION_LESS "11.1" - AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU" - AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "9" - AND CMAKE_CXX_COMILER_VERSION VERSION_LESS "10" - AND (FLAMEGPU_CXX_STD EQUAL 17 OR CMAKE_CUDA_STANDARD EQUAL 17)) - # https://github.com/FLAMEGPU/FLAMEGPU2/issues/650 - message(AUTHOR_WARNING - "CUDA 11.0 with g++ 9 in c++17 mode may encounter compiler segmentation faults with 'std::vector>::push_back'.\n" - "Consider using CUDA 11.1+ or gcc 8 to avoid potential issues.\n" - "See https://github.com/FLAMEGPU/FLAMEGPU2/issues/650 for more information.") - endif() -endif() - -# @future - set this on a per target basis using set_target_properties? -set(CMAKE_CXX_EXTENSIONS OFF) -if(NOT DEFINED CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD ${FLAMEGPU_CXX_STD}) - set(CMAKE_CXX_STANDARD_REQUIRED true) -endif() -if(NOT DEFINED CMAKE_CUDA_STANDARD) - set(CMAKE_CUDA_STANDARD ${FLAMEGPU_CXX_STD}) - set(CMAKE_CUDA_STANDARD_REQUIRED True) -endif() \ No newline at end of file diff --git a/cmake/dependencies/devil.cmake b/cmake/dependencies/devil.cmake index 2ee14de..5b98f1e 100644 --- a/cmake/dependencies/devil.cmake +++ b/cmake/dependencies/devil.cmake @@ -36,4 +36,16 @@ elseif(WIN32) NO_CMAKE_PACKAGE_REGISTRY NO_CMAKE_SYSTEM_PATH) endif() -endif() \ No newline at end of file +endif() + +# Mark some CACHE vars advanced for a cleaner GUI +mark_as_advanced(FETCHCONTENT_QUIET) +mark_as_advanced(FETCHCONTENT_BASE_DIR) +mark_as_advanced(FETCHCONTENT_FULLY_DISCONNECTED) +mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED) +mark_as_advanced(FETCHCONTENT_SOURCE_DIR_DEVIL) +mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED_DEVIL) +mark_as_advanced(IL_INCLUDE_DIR) +mark_as_advanced(IL_LIBRARIES) +mark_as_advanced(ILU_LIBRARIES) +mark_as_advanced(ILUT_LIBRARIES) \ No newline at end of file diff --git a/cmake/dependencies/freetype.cmake b/cmake/dependencies/freetype.cmake index 6482a33..7623de4 100644 --- a/cmake/dependencies/freetype.cmake +++ b/cmake/dependencies/freetype.cmake @@ -42,6 +42,19 @@ elseif(WIN32) # Freetype with MSVC on windows emits warnings at /W1 (default). Use a cmake function defined elsewhere to suppress all warnings on the freetype target include(${CMAKE_CURRENT_LIST_DIR}/../warnings.cmake) if(TARGET freetype) - DisableCompilerWarnings(TARGET freetype) + flamegpu_visualiser_disable_compiler_warnings(TARGET freetype) endif() + + mark_as_advanced(FETCHCONTENT_QUIET) + mark_as_advanced(FETCHCONTENT_BASE_DIR) + mark_as_advanced(FETCHCONTENT_FULLY_DISCONNECTED) + mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED) + mark_as_advanced(FETCHCONTENT_SOURCE_DIR_FREETYPE) + mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED_FREETYPE) + mark_as_advanced(CMAKE_DISABLE_FIND_PACKAGE_ZLIB) + mark_as_advanced(CMAKE_DISABLE_FIND_PACKAGE_HarfBuzz) + mark_as_advanced(CMAKE_DISABLE_FIND_PACKAGE_BZip2) + mark_as_advanced(CMAKE_DISABLE_FIND_PACKAGE_PNG) + mark_as_advanced(FT_WITH_HARFBUZZ) + mark_as_advanced(SKIP_INSTALL_ALL) endif() \ No newline at end of file diff --git a/cmake/dependencies/glew.cmake b/cmake/dependencies/glew.cmake index 77980c4..d62ea36 100644 --- a/cmake/dependencies/glew.cmake +++ b/cmake/dependencies/glew.cmake @@ -37,4 +37,12 @@ elseif(WIN32) NO_CMAKE_PACKAGE_REGISTRY NO_CMAKE_SYSTEM_PATH) endif() -endif() \ No newline at end of file +endif() + +mark_as_advanced(FETCHCONTENT_QUIET) +mark_as_advanced(FETCHCONTENT_BASE_DIR) +mark_as_advanced(FETCHCONTENT_FULLY_DISCONNECTED) +mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED) +mark_as_advanced(FETCHCONTENT_SOURCE_DIR_GLEW) +mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED_GLEW) +mark_as_advanced(GLEW_DIR) \ No newline at end of file diff --git a/cmake/dependencies/glm.cmake b/cmake/dependencies/glm.cmake index 70951f7..d328c95 100644 --- a/cmake/dependencies/glm.cmake +++ b/cmake/dependencies/glm.cmake @@ -1,26 +1,49 @@ ####### # glm # ####### -if(NOT glm_FOUND) - set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/../modules/ ${CMAKE_MODULE_PATH}) - include(FetchContent) - # As the URL method is used for download, set the policy if available - if(POLICY CMP0135) - cmake_policy(SET CMP0135 NEW) - endif() +# As the URL method is used for download, set the policy if available +if(POLICY CMP0135) + cmake_policy(SET CMP0135 NEW) +endif() + +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/modules/ ${CMAKE_MODULE_PATH}) +include(FetchContent) - # Head of master at point BugFix for NVRTC support was merged - FetchContent_Declare( - glm - URL "https://github.com/g-truc/glm/archive/66062497b104ca7c297321bd0e970869b1e6ece5.zip" - ) - FetchContent_GetProperties(glm) - if(NOT glm_POPULATED) - FetchContent_Populate(glm) +# Head of master at point BugFix for NVRTC support was merged +FetchContent_Declare( + glm + URL "https://github.com/g-truc/glm/archive/66062497b104ca7c297321bd0e970869b1e6ece5.zip" +) +FetchContent_GetProperties(glm) +if(NOT glm_POPULATED) + FetchContent_Populate(glm) + if (NOT TARGET glm::glm) # glm CMake wants to generate the find file in a system location, so handle it manually - set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};${glm_SOURCE_DIR}") - find_package(glm REQUIRED) - # Include path is ${glm_INCLUDE_DIRS} + # Find the path, just incase + find_path(glm_INCLUDE_DIRS + NAMES + glm/glm.hpp + PATHS + ${glm_SOURCE_DIR} + NO_CACHE + ) + if(glm_INCLUDE_DIRS) + # Define an imported interface target + add_library(glm::glm INTERFACE IMPORTED) + # Specify the location of the headers (but actually the parent dir, so include can be used.) + target_include_directories(glm::glm INTERFACE "${glm_INCLUDE_DIRS}") + else() + message(FATAL_ERROR "Error during creation og `glm::glm` target. Could not find glm/glm.hpp") + endif() + unset(glm_INCLUDE_DIRS) endif() -endif() \ No newline at end of file +endif() + +# Mark some CACHE vars advanced for a cleaner GUI +mark_as_advanced(FETCHCONTENT_QUIET) +mark_as_advanced(FETCHCONTENT_BASE_DIR) +mark_as_advanced(FETCHCONTENT_FULLY_DISCONNECTED) +mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED) +mark_as_advanced(FETCHCONTENT_SOURCE_DIR_GLM) +mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED_GLM) \ No newline at end of file diff --git a/cmake/dependencies/imgui-CMakeLists.txt.in b/cmake/dependencies/imgui-CMakeLists.txt.in index 64f5a68..0a5fc2e 100644 --- a/cmake/dependencies/imgui-CMakeLists.txt.in +++ b/cmake/dependencies/imgui-CMakeLists.txt.in @@ -1,3 +1,5 @@ +cmake_minimum_required(VERSION 3.18...3.25 FATAL_ERROR) + project(imgui LANGUAGES CXX) if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) # If top level project @@ -32,11 +34,11 @@ add_library(imgui STATIC ${imgui_sources}) # Specify the include directory, to be forwared to targets which link against the imgui 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 imgui/imgui.h as the include, by resolving the relative path to get an abs path -get_filename_component(imgui_inc_dir ${imgui_SOURCE_DIR} REALPATH) -target_include_directories("${PROJECT_NAME}" SYSTEM INTERFACE ${imgui_SOURCE_DIR}/imgui ${imgui_SOURCE_DIR}) +get_filename_component(imgui_inc_dir ${PROJECT_SOURCE_DIR} REALPATH) +target_include_directories("${PROJECT_NAME}" SYSTEM INTERFACE ${PROJECT_SOURCE_DIR}/imgui ${PROJECT_SOURCE_DIR}) # Because we're using a nested dir rather than root, specify include path -target_include_directories("${PROJECT_NAME}" PUBLIC ${imgui_SOURCE_DIR}/imgui) +target_include_directories("${PROJECT_NAME}" PUBLIC ${PROJECT_SOURCE_DIR}/imgui) # Also depends on SDL for backend target_include_directories("${PROJECT_NAME}" SYSTEM PRIVATE ${SDL2_INCLUDE_DIRS}) @@ -51,7 +53,7 @@ set_property(TARGET imgui PROPERTY POSITION_INDEPENDENT_CODE ON) # Suppress warnigns from this target. (Not currently required) #include(${CMAKE_CURRENT_LIST_DIR}/../warnings.cmake) -#DisableCompilerWarnings(TARGET imgui) +#flamegpu_visualiser_disable_compiler_warnings(TARGET imgui) # Create an alias target for imgui to namespace it / make it more like other modern cmake add_library(ImGui::ImGui ALIAS imgui) \ No newline at end of file diff --git a/cmake/dependencies/imgui.cmake b/cmake/dependencies/imgui.cmake index 77352da..636731f 100644 --- a/cmake/dependencies/imgui.cmake +++ b/cmake/dependencies/imgui.cmake @@ -37,3 +37,10 @@ if(NOT imgui_POPULATED) add_subdirectory(${imgui_SOURCE_DIR}/.. ${imgui_BINARY_DIR}) endif() endif() + +mark_as_advanced(FETCHCONTENT_QUIET) +mark_as_advanced(FETCHCONTENT_BASE_DIR) +mark_as_advanced(FETCHCONTENT_FULLY_DISCONNECTED) +mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED) +mark_as_advanced(FETCHCONTENT_SOURCE_DIR_IMGUI) +mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED_IMGUI) \ No newline at end of file diff --git a/cmake/dependencies/sdl2.cmake b/cmake/dependencies/sdl2.cmake index 29e2a2e..1002ea1 100644 --- a/cmake/dependencies/sdl2.cmake +++ b/cmake/dependencies/sdl2.cmake @@ -6,7 +6,21 @@ if(UNIX) if (NOT SDL2_FOUND) message(FATAL_ERROR "sdl2 is required for building, install it via your package manager.\n" "e.g. sudo apt install libsdl2-dev") - endif () + else() + # If no imported targets are provided, make one, using variables from the older find_package(SDL2). + # Tested on ubuntu 20.04 / libsdl2-dev 2.0.10+dfsg1-3 + if (NOT TARGET SDL2::SDL2) + # If we have a ${libdir} from the above find_package sdl2, use that. + if(${libdir}) + set(SDL2_LIBDIR ${libdir}) + endif() + add_library(SDL2::SDL2 SHARED IMPORTED) + set_target_properties(SDL2::SDL2 PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INCLUDE_DIRS}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${SDL2_LIBDIR}/${CMAKE_SHARED_LIBRARY_PREFIX}SDL2${CMAKE_SHARED_LIBRARY_SUFFIX}") + endif() + endif() elseif(WIN32) # On windows, always download manually. There are issues with find_package and multi-config generators where a release library will be found, but no debug library, which can break things. # Declare source properties @@ -34,4 +48,12 @@ elseif(WIN32) NO_CMAKE_PACKAGE_REGISTRY NO_CMAKE_SYSTEM_PATH) endif() -endif() \ No newline at end of file +endif() + +mark_as_advanced(FETCHCONTENT_QUIET) +mark_as_advanced(FETCHCONTENT_BASE_DIR) +mark_as_advanced(FETCHCONTENT_FULLY_DISCONNECTED) +mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED) +mark_as_advanced(FETCHCONTENT_SOURCE_DIR_SDL2) +mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED_SDL2) +mark_as_advanced(SDL2_DIR) diff --git a/cmake/modules/Findglm.cmake b/cmake/modules/Findglm.cmake deleted file mode 100644 index cd4b90d..0000000 --- a/cmake/modules/Findglm.cmake +++ /dev/null @@ -1,39 +0,0 @@ -# CMake module to find glm headers/library -# -# Very basic. -# -# Usage: -# find_package( glm ) -# if(glm_FOUND) -# include_directories(${glm_INCLUDE_DIRS}) -# endif() -# -# Variables: -# glm_FOUND -# glm_INCLUDE_DIRS -# glm_VERSION -# -# Manually specify glm paths via -Dglm_ROOT=/path/to/glm - -include(FindPackageHandleStandardArgs) - -# Find the main Jitify header -find_path(glm_INCLUDE_DIRS - NAMES - glm/glm.hpp -) - -# if found, get the version number. -if(glm_INCLUDE_DIRS) - # glm nolonger has official releases, so there isn't a way to detect a version - set(glm_VERSION "VERSION_UNKNOWN") -endif() -# Apply standard cmake find package rules / variables. I.e. QUIET, glm_FOUND etc. -# Outside the if, so REQUIRED works. -find_package_handle_standard_args(glm - REQUIRED_VARS glm_INCLUDE_DIRS - VERSION_VAR glm_VERSION -) - -# Set returned values as advanced? -mark_as_advanced(glm_INCLUDE_DIRS glm_VERSION) diff --git a/cmake/warnings.cmake b/cmake/warnings.cmake index cc90a2d..b7893dc 100644 --- a/cmake/warnings.cmake +++ b/cmake/warnings.cmake @@ -1,6 +1,7 @@ +include_guard(GLOBAL) # Function to disable all (as many as possible) compiler warnings for a given target -if(NOT COMMAND DisableCompilerWarnings) - function(DisableCompilerWarnings) +if(NOT COMMAND flamegpu_visualiser_disable_compiler_warnings) + function(flamegpu_visualiser_disable_compiler_warnings) # Parse the expected arguments, prefixing variables. cmake_parse_arguments( DCW @@ -11,9 +12,9 @@ if(NOT COMMAND DisableCompilerWarnings) ) # Ensure that a target has been passed, and that it is a valid target. if(NOT DCW_TARGET) - message(FATAL_ERROR "DisableCompilerWarnings: 'TARGET' argument required.") + message(FATAL_ERROR "flamegpu_visualiser_disable_compiler_warnings: 'TARGET' argument required.") elseif(NOT TARGET ${DCW_TARGET}) - message(FATAL_ERROR "DisableCompilerWarnings: TARGET '${DCW_TARGET}' is not a valid target") + message(FATAL_ERROR "flamegpu_visualiser_disable_compiler_warnings: 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") @@ -28,8 +29,8 @@ endif() # 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 -if(NOT COMMAND SetHighWarningLevel) - function(SetHighWarningLevel) +if(NOT COMMAND flamegpu_visualiser_set_high_warning_level) + function(flamegpu_visualiser_set_high_warning_level) # Parse the expected arguments, prefixing variables. cmake_parse_arguments( SHWL @@ -40,9 +41,9 @@ if(NOT COMMAND SetHighWarningLevel) ) # Ensure that a target has been passed, and that it is a valid target. if(NOT SHWL_TARGET) - message(FATAL_ERROR "SetHighWarningLevel: 'TARGET' argument required.") + message(FATAL_ERROR "flamegpu_visualiser_set_high_warning_level: 'TARGET' argument required.") elseif(NOT TARGET ${SHWL_TARGET}) - message(FATAL_ERROR "SetHighWarningLevel: TARGET '${SHWL_TARGET}' is not a valid target") + message(FATAL_ERROR "flamegpu_visualiser_set_high_warning_level: TARGET '${SHWL_TARGET}' is not a valid target") endif() # Per host-compiler settings for high warning levels and opt-in warnings. @@ -69,8 +70,8 @@ if(NOT COMMAND SetHighWarningLevel) endif() # 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) -if(NOT COMMAND SuppressSomeCompilerWarnings) - function(SuppressSomeCompilerWarnings) +if(NOT COMMAND flamegpu_visualiser_suppress_some_compiler_warnings) + function(flamegpu_visualiser_suppress_some_compiler_warnings) # Parse the expected arguments, prefixing variables. cmake_parse_arguments( SSCW @@ -81,9 +82,9 @@ if(NOT COMMAND SuppressSomeCompilerWarnings) ) # 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.") + message(FATAL_ERROR "flamegpu_visualiser_suppress_some_compiler_warnings: 'TARGET' argument required.") elseif(NOT TARGET ${SSCW_TARGET}) - message(FATAL_ERROR "SuppressSomeCompilerWarnings: TARGET '${SSCW_TARGET}' is not a valid target") + message(FATAL_ERROR "flamegpu_visualiser_suppress_some_compiler_warnings: TARGET '${SSCW_TARGET}' is not a valid target") endif() # Per host-compiler/OS settings for suppressions @@ -132,8 +133,8 @@ if(NOT COMMAND SuppressSomeCompilerWarnings) endif() # Function to promote warnings to errors, controlled by the WARNINGS_AS_ERRORS CMake option. -if(NOT COMMAND EnableWarningsAsErrors) - function(EnableWarningsAsErrors) +if(NOT COMMAND flamegpu_visualiser_enable_warnings_as_errors) + function(flamegpu_visualiser_enable_warnings_as_errors) # Parse the expected arguments, prefixing variables. cmake_parse_arguments( EWAS @@ -144,13 +145,13 @@ if(NOT COMMAND EnableWarningsAsErrors) ) # 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.") + message(FATAL_ERROR "flamegpu_visualiser_enable_warnings_as_errors: 'TARGET' argument required.") elseif(NOT TARGET ${EWAS_TARGET}) - message(FATAL_ERROR "EnableWarningsAsErrors: TARGET '${EWAS_TARGET}' is not a valid target") + message(FATAL_ERROR "flamegpu_visualiser_enable_warnings_as_errors: TARGET '${EWAS_TARGET}' is not a valid target") endif() # Check the WARNINGS_AS_ERRORS cmake option to optionally enable this. - if(WARNINGS_AS_ERRORS) + if(FLAMEGPU_WARNINGS_AS_ERRORS) # OS Specific flags if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") # Windows specific options @@ -183,8 +184,8 @@ endif() # + With some warnings suppressed # + Optionally promotes warnings to errors. # Also enables the treating of warnings as errors if required. -if(NOT COMMAND EnableFLAMEGPUCompilerWarnings) - function(EnableFLAMEGPUCompilerWarnings) +if(NOT COMMAND flamegpu_visuaiser_enable_compiler_warnings) + function(flamegpu_visuaiser_enable_compiler_warnings) # Parse the expected arguments, prefixing variables. cmake_parse_arguments( EFCW @@ -195,16 +196,16 @@ if(NOT COMMAND EnableFLAMEGPUCompilerWarnings) ) # 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.") + message(FATAL_ERROR "flamegpu_visuaiser_enable_compiler_warnings: 'TARGET' argument required.") elseif(NOT TARGET ${EFCW_TARGET}) - message(FATAL_ERROR "EnableFLAMEGPUCompilerWarnings: TARGET '${EFCW_TARGET}' is not a valid target") + message(FATAL_ERROR "flamegpu_visuaiser_enable_compiler_warnings: TARGET '${EFCW_TARGET}' is not a valid target") endif() # Enable a high level of warnings - SetHighWarningLevel(TARGET ${EFCW_TARGET}) + flamegpu_visualiser_set_high_warning_level(TARGET ${EFCW_TARGET}) # Suppress some warnings - SuppressSomeCompilerWarnings(TARGET ${EFCW_TARGET}) + flamegpu_visualiser_suppress_some_compiler_warnings(TARGET ${EFCW_TARGET}) # Optionally promote warnings to errors. - EnableWarningsAsErrors(TARGET ${EFCW_TARGET}) + flamegpu_visualiser_enable_warnings_as_errors(TARGET ${EFCW_TARGET}) endfunction() endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9e3da5c..54697ac 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,5 @@ # Parity with main FGPU2 CMake -cmake_minimum_required(VERSION VERSION 3.18 FATAL_ERROR) +cmake_minimum_required(VERSION 3.18...3.25 FATAL_ERROR) # Find git which is a hard dependency find_package(Git) @@ -7,8 +7,12 @@ if (NOT GIT_FOUND) message(FATAL_ERROR "git is required for building") endif () +# Record the user-provided CMAKE_CUDA_ARCHITECTURES if provided, to be applied later +include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/CUDAArchitectures.cmake) +flamegpu_visualiser_init_cuda_architectures() + # Set the project name, but do not specify languages immediately so we can have lint only builds. -project(flamegpu_visualiser) +project(flamegpu_visualiser LANGUAGES NONE) # handle cpplint. include(${CMAKE_CURRENT_LIST_DIR}/../cmake/cpplint.cmake) @@ -23,6 +27,9 @@ if(CMAKE_CUDA_COMPILER) enable_language(C) enable_language(CXX) enable_language(CUDA) + # Apply CMAKE_CUDA_ARCHITECTUES if the language was enabled + flamegpu_visualiser_set_cuda_architectures() + message(STATUS "Using CUDA_ARCHITECTURES ${CMAKE_CUDA_ARCHITECTURES}") endif() # Openg GL is required, unless doing a lint only build. @@ -40,9 +47,12 @@ if (UNIX AND OPENGL_FOUND) endif() endif() +# Ensure found compilers are actually good enough / don't trigger known issues. +include(${CMAKE_CURRENT_LIST_DIR}/../cmake/CheckCompilerFunctionality.cmake) + # If CUDA was not found, or opengl was not found we cannot build, but can lint, otherwise tehre should be a fatal error set(LINT_ONLY_BUILD "OFF") -if(ALLOW_LINT_ONLY AND CPPLINT AND (NOT OPENGL_FOUND OR NOT CMAKE_CUDA_COMPILER)) +if(FLAMEGPU_ALLOW_LINT_ONLY AND CPPLINT_EXECUTABLE AND (NOT OPENGL_FOUND OR NOT CMAKE_CUDA_COMPILER OR FLAMEGPU_VISUALISER_CheckCompilerFunctionality_RESULT)) set(LINT_ONLY_BUILD "ON") endif() @@ -160,16 +170,14 @@ SET(VISUALISER_ALL ) # Add the lint target. -if(CPPLINT) - new_linter_target("${PROJECT_NAME}" "${VISUALISER_ALL}") -endif() +flamegpu_visualiser_new_linter_target("${PROJECT_NAME}" "${VISUALISER_ALL}") -if(LINT_ONLY_BUILD) - # All should include all_lint if lint only build. - set_target_properties(all_lint PROPERTIES EXCLUDE_FROM_ALL FALSE) - if (NOT CPPLINT) +if(LINT_ONLY_BUILD AND CPPLINT_EXECUTABLE) + if (NOT CPPLINT_EXECUTABLE) message(FATAL_ERROR "Cpplint is required for lint-only builds.") endif() + # All should include all_lint if lint only build. + set_target_properties(all_lint PROPERTIES EXCLUDE_FROM_ALL FALSE) message(STATUS "Lint-only build configuraiton due to missing dependencies") if (NOT OPENGL_FOUND) message(STATUS "OpenGL is required for building") @@ -212,23 +220,24 @@ set(CMAKE_THREAD_PREFER_PTHREAD TRUE) set(THREADS_PREFER_PTHREAD_FLAG TRUE) find_package(Threads REQUIRED) -# CUDA_ARCH is used to control the compute capabilities to build for, via cmake/cuda_arch.cmake. -# @todo - use the same value as the parent project if imported. -include(${CMAKE_CURRENT_LIST_DIR}/../cmake/cuda_arch.cmake) -# Select the C++ standard to use -include(${CMAKE_CURRENT_LIST_DIR}/../cmake/cxxstd.cmake) # Import function to set compiler settings for the target include(${CMAKE_CURRENT_LIST_DIR}/../cmake/CommonCompilerSettings.cmake) # Define output add_library("${PROJECT_NAME}" STATIC ${VISUALISER_ALL}) +# Require C++17 as a public target property for C++ and CUDA, with no extensions, and the standard is required +target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17) +target_compile_features(${PROJECT_NAME} PUBLIC cuda_std_17) +set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_EXTENSIONS OFF) +set_property(TARGET ${PROJECT_NAME} PROPERTY CUDA_EXTENSIONS OFF) +set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) +set_property(TARGET ${PROJECT_NAME} PROPERTY CUDA_STANDARD_REQUIRED ON) + # Set target level warnings. -EnableFLAMEGPUCompilerWarnings(TARGET "${PROJECT_NAME}") +flamegpu_visuaiser_enable_compiler_warnings(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}") +flamegpu_visualiser_common_compiler_settings(TARGET "${PROJECT_NAME}") # Prevent fscanf warnings for msvc. if (WIN32) @@ -244,18 +253,8 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") target_compile_options("${PROJECT_NAME}" PRIVATE "$<$:/experimental:external>") endif() -# Set up include dirs -target_include_directories("${PROJECT_NAME}" SYSTEM PRIVATE ${glm_INCLUDE_DIRS}) -target_include_directories("${PROJECT_NAME}" SYSTEM PRIVATE ${SDL2_INCLUDE_DIRS}) -target_include_directories("${PROJECT_NAME}" SYSTEM PRIVATE ${GLEW_INCLUDE_DIRS}) -target_include_directories("${PROJECT_NAME}" SYSTEM PRIVATE ${IMGUI_INCLUDE_DIRS}) -if (FREETYPE_FOUND) # Only use this if we aren't building it ourselves - target_include_directories("${PROJECT_NAME}" SYSTEM PRIVATE ${FREETYPE_INCLUDE_DIRS}) -endif () +# Specify include directories which are not implicit from link interfaces target_include_directories("${PROJECT_NAME}" SYSTEM PRIVATE ${IL_INCLUDE_DIR}) -if(Fontconfig_FOUND) - target_include_directories("${PROJECT_NAME}" SYSTEM PRIVATE ${Fontconfig_INCLUDE_DIRS}) -endif() target_include_directories("${PROJECT_NAME}" SYSTEM PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../external") # The main include directory should be public. target_include_directories("${PROJECT_NAME}" PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../include") @@ -268,34 +267,57 @@ set_property(TARGET "${PROJECT_NAME}" PROPERTY POSITION_INDEPENDENT_CODE ON) # Add the targets we depend on (this does link and include) # This propagates to any project that uses this as a dependency if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - target_link_libraries("${PROJECT_NAME}" "legacy_stdio_definitions") # This won't be required if we rebuild freetype with newer than vs2013 + target_link_libraries("${PROJECT_NAME}" PRIVATE "legacy_stdio_definitions") # This won't be required if we rebuild freetype with newer than vs2013 endif() # If gcc < 9, needs to link against stdc++fs if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0) - target_link_libraries("${PROJECT_NAME}" stdc++fs) + target_link_libraries("${PROJECT_NAME}" PRIVATE stdc++fs) endif() -# Strip trailiing whitespace from SDL2_Libraries for Ubuntu1604 / libsdl2-dev 2.0.4 -string(STRIP "${SDL2_LIBRARIES}" SDL2_LIBRARIES) -target_link_libraries("${PROJECT_NAME}" "${SDL2_LIBRARIES}") -# Link against GLEW, via GLEW::GLEW which is an alias for GLEW::glew or GLEW::glew_s based on availability. +target_link_libraries("${PROJECT_NAME}" PRIVATE glm::glm) +# Use GLEW::GLEW if available, otherwise fallback to the variables only (i.e. custom windows fetching) if(TARGET GLEW::GLEW) - target_link_libraries("${PROJECT_NAME}" GLEW::GLEW) -else() - # Fallback to the variable for our partial windows CMake config file. We should add an imported target alias to this. - target_link_libraries("${PROJECT_NAME}" "${GLEW_LIBRARIES}") + target_link_libraries("${PROJECT_NAME}" PRIVATE GLEW::GLEW) +elseif(GLEW_INCLUDE_DIRS) + target_include_directories("${PROJECT_NAME}" SYSTEM PRIVATE ${GLEW_INCLUDE_DIRS}) + target_link_libraries("${PROJECT_NAME}" PRIVATE "${GLEW_LIBRARIES}") +endif() +# Use SDL2::SDL2 if available, otherwise fallback to the variables only (i.e. custom windows fetching) +if(TARGET SDL2::SDL2) + target_link_libraries("${PROJECT_NAME}" PRIVATE SDL2::SDL2) +elseif(SDL2_INCLUDE_DIRS) + target_include_directories("${PROJECT_NAME}" SYSTEM PRIVATE ${SDL2_INCLUDE_DIRS}) + # Ubuntu 16.04 workaround + string(STRIP "${SDL2_LIBRARIES}" SDL2_LIBRARIES) + target_link_libraries("${PROJECT_NAME}" PRIVATE "${SDL2_LIBRARIES}") +endif() +# Use DevIL::IL if available, otherwise fallback to the variables only (i.e. custom windows fetching) +if(TARGET DevIL::IL) + target_link_libraries("${PROJECT_NAME}" PRIVATE DevIL::IL) +elseif(IL_INCLUDE_DIR) + target_include_directories("${PROJECT_NAME}" SYSTEM PRIVATE ${IL_INCLUDE_DIR}) + target_link_libraries("${PROJECT_NAME}" PRIVATE "${IL_LIBRARIES}") endif() -target_link_libraries("${PROJECT_NAME}" freetype) -target_link_libraries("${PROJECT_NAME}" "${IL_LIBRARIES}") -target_link_libraries("${PROJECT_NAME}" ImGui::ImGui) -target_link_libraries("${PROJECT_NAME}" OpenGL::GL) -target_link_libraries("${PROJECT_NAME}" Threads::Threads) +# imgui must be public as the headers are visible in flamegpu/FLAMEGPU2 +target_link_libraries("${PROJECT_NAME}" PUBLIC ImGui::ImGui) +# GL required +target_link_libraries("${PROJECT_NAME}" PRIVATE OpenGL::GL) +# std::threads support +target_link_libraries("${PROJECT_NAME}" PRIVATE Threads::Threads) +# Link against freetype, via Freetype::Freetype if imported, or just freetype otherwise +if(TARGET Freetype::Freetype) + target_link_libraries("${PROJECT_NAME}" PRIVATE Freetype::Freetype) +elseif(TARGET freetype) + target_link_libraries("${PROJECT_NAME}" PRIVATE freetype) +endif() +# Fontconfig is only required under linux, so not always linked against if(TARGET Fontconfig::Fontconfig) - target_link_libraries("${PROJECT_NAME}" Fontconfig::Fontconfig) + target_link_libraries("${PROJECT_NAME}" PRIVATE Fontconfig::Fontconfig) endif() +# dwrite.lib required on windows if(WIN32) - target_link_libraries("${PROJECT_NAME}" "dwrite.lib") + target_link_libraries("${PROJECT_NAME}" PRIVATE "dwrite.lib") endif() # Enable parallel compilation on MSVC @@ -338,7 +360,27 @@ cmrc_add_resource_library(resources ${RESOURCES_ALL} WHENCE ${CMAKE_CURRENT_SOUR set_property(TARGET "resources" PROPERTY POSITION_INDEPENDENT_CODE ON) # Link resources and the visualiser static lib -target_link_libraries("${PROJECT_NAME}" resources) +target_link_libraries("${PROJECT_NAME}" PUBLIC resources) + +# Define a function to list the runtime libraries for the visualiser static lib, for downstream targets to copy to any required locations (i.e. pyflamegpu). This reduces the amount of overlap. +if (NOT COMMAND flamegpu_visualiser_get_runtime_depenencies) + function(flamegpu_visualiser_get_runtime_depenencies runtime_dependencies) + # windows only, and only with non-target dependencies. Fancier CMake based dependency stuff might be possible, but might require newer cmake or an install phase + if(WIN32) + if(SDL2_RUNTIME_LIBRARIES) + LIST(APPEND runtime_libs ${SDL2_RUNTIME_LIBRARIES}) + endif() + if(GLEW_RUNTIME_LIBRARIES) + LIST(APPEND runtime_libs ${GLEW_RUNTIME_LIBRARIES}) + endif() + if(IL_RUNTIME_LIBRARIES) + LIST(APPEND runtime_libs ${IL_RUNTIME_LIBRARIES}) + endif() + endif() + # Return the value to the calling scope + set(${runtime_dependencies} "${runtime_libs}" PARENT_SCOPE) + endfunction() +endif() if (CMAKE_USE_FOLDERS) # Setup Visual Studio (and eclipse) filters