diff options
Diffstat (limited to 'Modules')
177 files changed, 5897 insertions, 1674 deletions
diff --git a/Modules/CMakeCUDACompiler.cmake.in b/Modules/CMakeCUDACompiler.cmake.in index 2f3e9a8..57d595a 100644 --- a/Modules/CMakeCUDACompiler.cmake.in +++ b/Modules/CMakeCUDACompiler.cmake.in @@ -50,8 +50,13 @@ endif() set(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "@CMAKE_CUDA_COMPILER_TOOLKIT_ROOT@") set(CMAKE_CUDA_COMPILER_TOOLKIT_LIBRARY_ROOT "@CMAKE_CUDA_COMPILER_TOOLKIT_LIBRARY_ROOT@") +set(CMAKE_CUDA_COMPILER_TOOLKIT_VERSION "@CMAKE_CUDA_COMPILER_TOOLKIT_VERSION@") set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "@CMAKE_CUDA_COMPILER_LIBRARY_ROOT@") +set(CMAKE_CUDA_ARCHITECTURES_ALL "@CMAKE_CUDA_ARCHITECTURES_ALL@") +set(CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR "@CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR@") +set(CMAKE_CUDA_ARCHITECTURES_NATIVE "@CMAKE_CUDA_ARCHITECTURES_NATIVE@") + set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "@CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES@") set(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "@CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES@") diff --git a/Modules/CMakeCUDACompilerABI.cu b/Modules/CMakeCUDACompilerABI.cu index 449a079..8463e86 100644 --- a/Modules/CMakeCUDACompilerABI.cu +++ b/Modules/CMakeCUDACompilerABI.cu @@ -2,6 +2,10 @@ # error "A C or C++ compiler has been selected for CUDA" #endif +#include <cstdio> + +#include <cuda_runtime.h> + #include "CMakeCompilerABI.h" int main(int argc, char* argv[]) @@ -13,6 +17,31 @@ int main(int argc, char* argv[]) #if defined(ABI_ID) require += info_abi[argc]; #endif - (void)argv; - return require; + static_cast<void>(argv); + + int count = 0; + if (cudaGetDeviceCount(&count) != cudaSuccess || count == 0) { + std::fprintf(stderr, "No CUDA devices found.\n"); + return -1; + } + + int found = 0; + const char* sep = ""; + for (int device = 0; device < count; ++device) { + cudaDeviceProp prop; + if (cudaGetDeviceProperties(&prop, device) == cudaSuccess) { + std::printf("%s%d%d", sep, prop.major, prop.minor); + sep = ";"; + found = 1; + } + } + + if (!found) { + std::fprintf(stderr, "No CUDA architecture detected from any devices.\n"); + // Convince the compiler that the non-zero return value depends + // on the info strings so they are not optimized out. + return require ? -1 : 1; + } + + return 0; } diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake index e9cfed6..dea721e 100644 --- a/Modules/CMakeCUDAInformation.cmake +++ b/Modules/CMakeCUDAInformation.cmake @@ -160,22 +160,9 @@ if(NOT DEFINED CMAKE_CUDA_ARCHIVE_FINISH) set(CMAKE_CUDA_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>") endif() -#Specify how to compile when ptx has been requested -if(NOT CMAKE_CUDA_COMPILE_PTX_COMPILATION) - set(CMAKE_CUDA_COMPILE_PTX_COMPILATION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} ${_CMAKE_CUDA_PTX_FLAG} <SOURCE> -o <OBJECT>") -endif() - -#Specify how to compile when separable compilation has been requested -if(NOT CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION) - set(CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} ${_CMAKE_CUDA_DEVICE_CODE} <SOURCE> -o <OBJECT>") -endif() - -#Specify how to compile when whole compilation has been requested -if(NOT CMAKE_CUDA_COMPILE_WHOLE_COMPILATION) - set(CMAKE_CUDA_COMPILE_WHOLE_COMPILATION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -c <SOURCE> -o <OBJECT>") +if(NOT CMAKE_CUDA_COMPILE_OBJECT) + set(CMAKE_CUDA_COMPILE_OBJECT + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} <CUDA_COMPILE_MODE> <SOURCE> -o <OBJECT>") endif() # compile a cu file into an executable @@ -211,7 +198,7 @@ endif() # Used when device linking is handled by CMake. if(NOT CMAKE_CUDA_DEVICE_LINK_COMPILE) - set(CMAKE_CUDA_DEVICE_LINK_COMPILE "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <FLAGS> -D__CUDA_INCLUDE_COMPILER_INTERNAL_HEADERS__ -D__NV_EXTRA_INITIALIZATION=\"\" -D__NV_EXTRA_FINALIZATION=\"\" -DREGISTERLINKBINARYFILE=\\\"<REGISTER_FILE>\\\" -DFATBINFILE=\\\"<FATBINARY>\\\" ${_CMAKE_COMPILE_AS_CUDA_FLAG} -c \"${CMAKE_CUDA_COMPILER_TOOLKIT_LIBRARY_ROOT}/bin/crt/link.stub\" -o <OBJECT>") + set(CMAKE_CUDA_DEVICE_LINK_COMPILE "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <FLAGS> <LINK_FLAGS> -D__CUDA_INCLUDE_COMPILER_INTERNAL_HEADERS__ -D__NV_EXTRA_INITIALIZATION=\"\" -D__NV_EXTRA_FINALIZATION=\"\" -DREGISTERLINKBINARYFILE=\\\"<REGISTER_FILE>\\\" -DFATBINFILE=\\\"<FATBINARY>\\\" ${_CMAKE_COMPILE_AS_CUDA_FLAG} -c \"${CMAKE_CUDA_COMPILER_TOOLKIT_LIBRARY_ROOT}/bin/crt/link.stub\" -o <OBJECT>") endif() unset(__IMPLICIT_DLINK_FLAGS) diff --git a/Modules/CMakeCompilerIdDetection.cmake b/Modules/CMakeCompilerIdDetection.cmake index e6b3ee3..f15974a 100644 --- a/Modules/CMakeCompilerIdDetection.cmake +++ b/Modules/CMakeCompilerIdDetection.cmake @@ -59,6 +59,7 @@ function(compiler_id_detection outvar lang) HP Compaq zOS + IBMClang XLClang XL VisualAge @@ -84,6 +85,7 @@ function(compiler_id_detection outvar lang) ) list(APPEND ordered_compilers Clang + LCC GNU MSVC ADSP diff --git a/Modules/CMakeDependentOption.cmake b/Modules/CMakeDependentOption.cmake index b7c478f..ac0e262 100644 --- a/Modules/CMakeDependentOption.cmake +++ b/Modules/CMakeDependentOption.cmake @@ -16,13 +16,18 @@ conditions are true. cmake_dependent_option(<option> "<help_text>" <value> <depends> <force>) - Makes ``<option>`` available to the user if ``<depends>`` is true. When - ``<option>`` is available, the given ``<help_text>`` and initial ``<value>`` - are used. If the ``<depends>`` condition is not true, ``<option>`` will not be - presented and will always have the value given by ``<force>``. Any value set by - the user is preserved for when the option is presented again. In case ``<depends>`` - is a :ref:`semicolon-separated list <CMake Language Lists>`, all elements must - be true in order to initialize ``<option>`` with ``<value>``. + Makes ``<option>`` available to the user if the + :ref:`semicolon-separated list <CMake Language Lists>` of conditions in + ``<depends>`` are all true. Otherwise, a local variable named ``<option>`` + is set to ``<force>``. + + When ``<option>`` is available, the given ``<help_text>`` and initial + ``<value>`` are used. Otherwise, any value set by the user is preserved for + when ``<depends>`` is satisfied in the future. + + Note that the ``<option>`` variable only has a value which satisfies the + ``<depends>`` condition within the scope of the caller because it is a local + variable. Example invocation: diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake index 15eab0f..f5298df 100644 --- a/Modules/CMakeDetermineCCompiler.cmake +++ b/Modules/CMakeDetermineCCompiler.cmake @@ -160,7 +160,7 @@ endif () # "arm-unknown-nto-qnx6" instead of the correct "arm-unknown-nto-qnx6.3.0-" if (NOT _CMAKE_TOOLCHAIN_PREFIX) - if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang|QCC") + if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang|QCC|LCC") get_filename_component(COMPILER_BASENAME "${CMAKE_C_COMPILER}" NAME) if (COMPILER_BASENAME MATCHES "^(.+-)?(clang|g?cc)(-cl)?(-[0-9]+(\\.[0-9]+)*)?(-[^.]+)?(\\.exe)?$") set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1}) diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake index d06315e..0ac06ac 100644 --- a/Modules/CMakeDetermineCUDACompiler.cmake +++ b/Modules/CMakeDetermineCUDACompiler.cmake @@ -18,16 +18,16 @@ else() if(NOT CMAKE_CUDA_COMPILER) set(CMAKE_CUDA_COMPILER_INIT NOTFOUND) - # prefer the environment variable CUDACXX - if(NOT $ENV{CUDACXX} STREQUAL "") - get_filename_component(CMAKE_CUDA_COMPILER_INIT $ENV{CUDACXX} PROGRAM PROGRAM_ARGS CMAKE_CUDA_FLAGS_ENV_INIT) - if(CMAKE_CUDA_FLAGS_ENV_INIT) - set(CMAKE_CUDA_COMPILER_ARG1 "${CMAKE_CUDA_FLAGS_ENV_INIT}" CACHE STRING "Arguments to CXX compiler") - endif() - if(NOT EXISTS ${CMAKE_CUDA_COMPILER_INIT}) - message(FATAL_ERROR "Could not find compiler set in environment variable CUDACXX:\n$ENV{CUDACXX}.\n${CMAKE_CUDA_COMPILER_INIT}") - endif() + # prefer the environment variable CUDACXX + if(NOT $ENV{CUDACXX} STREQUAL "") + get_filename_component(CMAKE_CUDA_COMPILER_INIT $ENV{CUDACXX} PROGRAM PROGRAM_ARGS CMAKE_CUDA_FLAGS_ENV_INIT) + if(CMAKE_CUDA_FLAGS_ENV_INIT) + set(CMAKE_CUDA_COMPILER_ARG1 "${CMAKE_CUDA_FLAGS_ENV_INIT}" CACHE STRING "Arguments to CUDA compiler") + endif() + if(NOT EXISTS ${CMAKE_CUDA_COMPILER_INIT}) + message(FATAL_ERROR "Could not find compiler set in environment variable CUDACXX:\n$ENV{CUDACXX}.\n${CMAKE_CUDA_COMPILER_INIT}") endif() + endif() # finally list compilers to try if(NOT CMAKE_CUDA_COMPILER_INIT) @@ -78,10 +78,11 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN) message(FATAL_ERROR "Clang with CUDA is not yet supported on Windows. See CMake issue #20776.") endif() - # Find the CUDA toolkit. We store the CMAKE_CUDA_COMPILER_TOOLKIT_ROOT and CMAKE_CUDA_COMPILER_LIBRARY_ROOT - # in CMakeCUDACompiler.cmake, so FindCUDAToolkit can avoid searching on future runs and the toolkit stays the same. + # Find the CUDA toolkit. We store the CMAKE_CUDA_COMPILER_TOOLKIT_ROOT, CMAKE_CUDA_COMPILER_TOOLKIT_VERSION and + # CMAKE_CUDA_COMPILER_LIBRARY_ROOT in CMakeCUDACompiler.cmake so FindCUDAToolkit can avoid searching on future + # runs and the toolkit is the same. # This is very similar to FindCUDAToolkit, but somewhat simplified since we can issue fatal errors - # if we fail to find things we need and we don't need to account for searching the libraries. + # if we fail and we don't need to account for searching the libraries. # For NVCC we can easily deduce the SDK binary directory from the compiler path. if(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") @@ -237,17 +238,29 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN) endif() endif() + # For regular nvcc we the toolkit version is the same as the compiler version and we can parse it from the vendor test output. + # For Clang we need to invoke nvcc to get version output. + if(NOT CMAKE_GENERATOR MATCHES "Visual Studio") + if(CMAKE_CUDA_COMPILER_ID STREQUAL "Clang") + execute_process(COMMAND ${_CUDA_NVCC_EXECUTABLE} "--version" OUTPUT_VARIABLE CMAKE_CUDA_COMPILER_ID_OUTPUT) + endif() + + if(CMAKE_CUDA_COMPILER_ID_OUTPUT MATCHES [=[V([0-9]+\.[0-9]+\.[0-9]+)]=]) + set(CMAKE_CUDA_COMPILER_TOOLKIT_VERSION "${CMAKE_MATCH_1}") + endif() + endif() + set(CMAKE_CUDA_COMPILER_ID_FLAGS_ALWAYS "-v") if(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") set(nvcc_test_flags "--keep --keep-dir tmp") if(CMAKE_CUDA_HOST_COMPILER) string(APPEND nvcc_test_flags " -ccbin=\"${CMAKE_CUDA_HOST_COMPILER}\"") - - # If the user has specified a host compiler we should fail instead of trying without. - # Succeeding detection without may result in confusing errors later on, see #21076. - set(CMAKE_CUDA_COMPILER_ID_REQUIRE_SUCCESS ON) endif() + # If we have extracted the vendor as NVIDIA we should require detection to + # work. If we don't, users will get confusing errors later about failure + # to detect a default value for CMAKE_CUDA_ARCHITECTURES + set(CMAKE_CUDA_COMPILER_ID_REQUIRE_SUCCESS ON) elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "Clang") set(clang_test_flags "--cuda-path=\"${CMAKE_CUDA_COMPILER_LIBRARY_ROOT}\"") if(CMAKE_CROSSCOMPILING) @@ -256,39 +269,35 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN) endif() endif() - # Append user-specified architectures. - if(CMAKE_CUDA_ARCHITECTURES) - foreach(arch ${CMAKE_CUDA_ARCHITECTURES}) - # Strip specifiers as PTX vs binary doesn't matter. - string(REGEX MATCH "[0-9]+" arch_name "${arch}") - string(APPEND clang_test_flags " --cuda-gpu-arch=sm_${arch_name}") - string(APPEND nvcc_test_flags " -gencode=arch=compute_${arch_name},code=sm_${arch_name}") - list(APPEND tested_architectures "${arch_name}") - endforeach() - - # If the user has specified architectures we'll want to fail during compiler detection if they don't work. - set(CMAKE_CUDA_COMPILER_ID_REQUIRE_SUCCESS ON) + # Rest of the code treats an empty value as equivalent to "use the defaults". + # Error out early to prevent confusing errors as a result of this. + # Note that this also catches invalid non-numerical values such as "a". + if(DEFINED CMAKE_CUDA_ARCHITECTURES) + if(CMAKE_CUDA_ARCHITECTURES STREQUAL "") + message(FATAL_ERROR "CMAKE_CUDA_ARCHITECTURES must be non-empty if set.") + elseif(CMAKE_CUDA_ARCHITECTURES AND NOT CMAKE_CUDA_ARCHITECTURES MATCHES "^([0-9]+(-real|-virtual)?(;[0-9]+(-real|-virtual)?|;)*|all|all-major|native)$") + message(FATAL_ERROR + "CMAKE_CUDA_ARCHITECTURES:\n" + " ${CMAKE_CUDA_ARCHITECTURES}\n" + "is not one of the following:\n" + " * a semicolon-separated list of integers, each optionally\n" + " followed by '-real' or '-virtual'\n" + " * a special value: all, all-major, native\n" + ) + endif() endif() if(CMAKE_CUDA_COMPILER_ID STREQUAL "Clang") - if(NOT CMAKE_CUDA_ARCHITECTURES) - # Clang doesn't automatically select an architecture supported by the SDK. - # Try in reverse order of deprecation with the most recent at front (i.e. the most likely to work for new setups). - foreach(arch "20" "30" "52") - list(APPEND CMAKE_CUDA_COMPILER_ID_TEST_FLAGS_FIRST "${clang_test_flags} --cuda-gpu-arch=sm_${arch}") - endforeach() - endif() - - # If the user specified CMAKE_CUDA_ARCHITECTURES this will include all the architecture flags. - # Otherwise this won't include any architecture flags and we'll fallback to Clang's defaults. - list(APPEND CMAKE_CUDA_COMPILER_ID_TEST_FLAGS_FIRST "${clang_test_flags}") + # Clang doesn't automatically select an architecture supported by the SDK. + # Try in reverse order of deprecation with the most recent at front (i.e. the most likely to work for new setups). + foreach(arch "52" "30" "20") + list(APPEND CMAKE_CUDA_COMPILER_ID_TEST_FLAGS_FIRST "${clang_test_flags} --cuda-gpu-arch=sm_${arch}") + endforeach() elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") list(APPEND CMAKE_CUDA_COMPILER_ID_TEST_FLAGS_FIRST "${nvcc_test_flags}") endif() # We perform compiler identification for a second time to extract implicit linking info and host compiler for NVCC. - # We also use it to verify that CMAKE_CUDA_ARCHITECTURES and additionally on Clang that CUDA toolkit path works. - # The latter could be done during compiler testing in the future to avoid doing this for Clang. # We need to unset the compiler ID otherwise CMAKE_DETERMINE_COMPILER_ID() doesn't work. set(CMAKE_CUDA_COMPILER_ID) set(CMAKE_CUDA_PLATFORM_ID) @@ -302,8 +311,13 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN) get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${CMAKE_CUDA_COMPILER}" DIRECTORY) get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}" DIRECTORY) set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}") + + # The compiler comes with the toolkit, so the versions are the same. + set(CMAKE_CUDA_COMPILER_TOOLKIT_VERSION ${CMAKE_CUDA_COMPILER_VERSION}) endif() + include(${CMAKE_ROOT}/Modules/CUDA/architectures.cmake) + _cmake_find_compiler_sysroot(CUDA) endif() @@ -337,18 +351,12 @@ if(${CMAKE_GENERATOR} MATCHES "Visual Studio") set(_SET_CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT "set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT \"${CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT}\")") elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "Clang") - if(NOT CMAKE_CUDA_ARCHITECTURES) - # Find the architecture that we successfully compiled using and set it as the default. - string(REGEX MATCH "-target-cpu sm_([0-9]+)" dont_care "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") - set(detected_architecture "${CMAKE_MATCH_1}") - else() - string(REGEX MATCHALL "-target-cpu sm_([0-9]+)" target_cpus "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") + string(REGEX MATCHALL "-target-cpu sm_([0-9]+)" target_cpus "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") - foreach(cpu ${target_cpus}) - string(REGEX MATCH "-target-cpu sm_([0-9]+)" dont_care "${cpu}") - list(APPEND architectures "${CMAKE_MATCH_1}") - endforeach() - endif() + foreach(cpu ${target_cpus}) + string(REGEX MATCH "-target-cpu sm_([0-9]+)" dont_care "${cpu}") + list(APPEND architectures_detected "${CMAKE_MATCH_1}") + endforeach() # Find target directory when crosscompiling. if(CMAKE_CROSSCOMPILING) @@ -574,46 +582,25 @@ if(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") "Failed to detect CUDA nvcc include information:\n${_nvcc_log}\n\n") endif() - # Parse default CUDA architecture. - cmake_policy(GET CMP0104 _CUDA_CMP0104) - if(NOT CMAKE_CUDA_ARCHITECTURES AND _CUDA_CMP0104 STREQUAL "NEW") - string(REGEX MATCH "arch[ =]compute_([0-9]+)" dont_care "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") - set(detected_architecture "${CMAKE_MATCH_1}") - elseif(CMAKE_CUDA_ARCHITECTURES) - string(REGEX MATCHALL "-arch compute_([0-9]+)" target_cpus "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") - - foreach(cpu ${target_cpus}) - string(REGEX MATCH "-arch compute_([0-9]+)" dont_care "${cpu}") - list(APPEND architectures "${CMAKE_MATCH_1}") - endforeach() - endif() + string(REGEX MATCHALL "-arch compute_([0-9]+)" target_cpus "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") + + foreach(cpu ${target_cpus}) + string(REGEX MATCH "-arch compute_([0-9]+)" dont_care "${cpu}") + list(APPEND architectures_detected "${CMAKE_MATCH_1}") + endforeach() endif() # If the user didn't set the architectures, then set them to a default. # If the user did, then make sure those architectures worked. -if(DEFINED detected_architecture AND "${CMAKE_CUDA_ARCHITECTURES}" STREQUAL "") - set(CMAKE_CUDA_ARCHITECTURES "${detected_architecture}" CACHE STRING "CUDA architectures") +if("${CMAKE_CUDA_ARCHITECTURES}" STREQUAL "") + cmake_policy(GET CMP0104 _CUDA_CMP0104) - if(NOT CMAKE_CUDA_ARCHITECTURES) - message(FATAL_ERROR "Failed to find a working CUDA architecture.") - endif() -elseif(architectures) - # Sort since order mustn't matter. - list(SORT architectures) - list(SORT tested_architectures) - - # We don't distinguish real/virtual architectures during testing. - # For "70-real;70-virtual" we detect "70" as working and tested_architectures is "70;70". - # Thus we need to remove duplicates before checking if they're equal. - list(REMOVE_DUPLICATES tested_architectures) - - if(NOT "${architectures}" STREQUAL "${tested_architectures}") - message(FATAL_ERROR - "The CMAKE_CUDA_ARCHITECTURES:\n" - " ${CMAKE_CUDA_ARCHITECTURES}\n" - "do not all work with this compiler. Try:\n" - " ${architectures}\n" - "instead.") + if(NOT CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA" OR _CUDA_CMP0104 STREQUAL "NEW") + set(CMAKE_CUDA_ARCHITECTURES "${architectures_detected}" CACHE STRING "CUDA architectures") + + if(NOT CMAKE_CUDA_ARCHITECTURES) + message(FATAL_ERROR "Failed to detect a default CUDA architecture.\n\nCompiler output:\n${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") + endif() endif() endif() @@ -630,5 +617,7 @@ unset(_CUDA_LIBRARY_DIR) unset(_CUDA_TARGET_DIR) unset(_CUDA_TARGET_NAME) +unset(architectures_detected) + set(CMAKE_CUDA_COMPILER_ENV_VAR "CUDACXX") set(CMAKE_CUDA_HOST_COMPILER_ENV_VAR "CUDAHOSTCXX") diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake index 72dc8d3..fd3d028 100644 --- a/Modules/CMakeDetermineCXXCompiler.cmake +++ b/Modules/CMakeDetermineCXXCompiler.cmake @@ -159,7 +159,7 @@ endif () if (NOT _CMAKE_TOOLCHAIN_PREFIX) - if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|Clang|QCC") + if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|Clang|QCC|LCC") get_filename_component(COMPILER_BASENAME "${CMAKE_CXX_COMPILER}" NAME) if (COMPILER_BASENAME MATCHES "^(.+-)?(clang\\+\\+|[gc]\\+\\+|clang-cl)(-[0-9]+(\\.[0-9]+)*)?(-[^.]+)?(\\.exe)?$") set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1}) diff --git a/Modules/CMakeDetermineCompiler.cmake b/Modules/CMakeDetermineCompiler.cmake index c967ab7..3156ca9 100644 --- a/Modules/CMakeDetermineCompiler.cmake +++ b/Modules/CMakeDetermineCompiler.cmake @@ -53,10 +53,9 @@ macro(_cmake_find_compiler lang) NO_DEFAULT_PATH DOC "${lang} compiler") endif() - if(CMAKE_HOST_WIN32 AND CMAKE_GENERATOR MATCHES "Ninja") - # On Windows command-line builds, the Makefile generators each imply - # a preferred compiler tool. The Ninja generator does not imply a - # compiler tool, so use the compiler that occurs first in PATH. + if(CMAKE_HOST_WIN32 AND CMAKE_GENERATOR MATCHES "Ninja|MSYS Makefiles|MinGW Makefiles") + # On Windows command-line builds, some generators imply a preferred compiler tool. + # These generators do not, so use the compiler that occurs first in PATH. find_program(CMAKE_${lang}_COMPILER NAMES ${CMAKE_${lang}_COMPILER_LIST} NAMES_PER_DIR @@ -119,9 +118,15 @@ macro(_cmake_find_compiler_path lang) # (e.g. via ctest) or set in CMAKE_TOOLCHAIN_FILE # if CMAKE_${lang}_COMPILER is a list, use the first item as # CMAKE_${lang}_COMPILER and the rest as CMAKE_${lang}_COMPILER_ARG1 - set(CMAKE_${lang}_COMPILER_ARG1 "${CMAKE_${lang}_COMPILER}") - list(POP_FRONT CMAKE_${lang}_COMPILER_ARG1 CMAKE_${lang}_COMPILER) - list(JOIN CMAKE_${lang}_COMPILER_ARG1 " " CMAKE_${lang}_COMPILER_ARG1) + # Otherwise, preserve any existing CMAKE_${lang}_COMPILER_ARG1 that might + # have been saved by CMakeDetermine${lang}Compiler in a previous run. + list(LENGTH CMAKE_${lang}_COMPILER _CMAKE_${lang}_COMPILER_LENGTH) + if(_CMAKE_${lang}_COMPILER_LENGTH GREATER 1) + set(CMAKE_${lang}_COMPILER_ARG1 "${CMAKE_${lang}_COMPILER}") + list(POP_FRONT CMAKE_${lang}_COMPILER_ARG1 CMAKE_${lang}_COMPILER) + list(JOIN CMAKE_${lang}_COMPILER_ARG1 " " CMAKE_${lang}_COMPILER_ARG1) + endif() + unset(_CMAKE_${lang}_COMPILER_LENGTH) # find the compiler in the PATH if necessary # if compiler (and arguments) comes from cache then synchronize cache with updated CMAKE_<LANG>_COMPILER @@ -148,7 +153,7 @@ macro(_cmake_find_compiler_path lang) endmacro() function(_cmake_find_compiler_sysroot lang) - if(CMAKE_${lang}_COMPILER_ID STREQUAL "GNU") + if(CMAKE_${lang}_COMPILER_ID STREQUAL "GNU" OR CMAKE_${lang}_COMPILER_ID STREQUAL "LCC") execute_process(COMMAND "${CMAKE_${lang}_COMPILER}" -print-sysroot OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE _cmake_sysroot_run_out diff --git a/Modules/CMakeDetermineCompilerABI.cmake b/Modules/CMakeDetermineCompilerABI.cmake index 8191d81..82a6d21 100644 --- a/Modules/CMakeDetermineCompilerABI.cmake +++ b/Modules/CMakeDetermineCompilerABI.cmake @@ -26,6 +26,14 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src) if(DEFINED CMAKE_${lang}_VERBOSE_COMPILE_FLAG) set(COMPILE_DEFINITIONS "${CMAKE_${lang}_VERBOSE_COMPILE_FLAG}") endif() + if(lang STREQUAL "CUDA") + if(CMAKE_CUDA_ARCHITECTURES STREQUAL "native") + # We are about to detect the native architectures, so we do + # not yet know them. Use all architectures during detection. + set(CMAKE_CUDA_ARCHITECTURES "all") + endif() + set(CMAKE_CUDA_RUNTIME_LIBRARY "Static") + endif() if(NOT "x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xMSVC") # Avoid adding our own platform standard libraries for compilers # from which we might detect implicit link libraries. diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 0840ff9..2b19736 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -150,7 +150,28 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) endif() endif() - if (COMPILER_QNXNTO AND CMAKE_${lang}_COMPILER_ID STREQUAL "GNU") + # For LCC Fortran we need to explicitly query the version. + if(lang STREQUAL "Fortran" + AND CMAKE_${lang}_COMPILER_ID STREQUAL "LCC") + execute_process( + COMMAND "${CMAKE_${lang}_COMPILER}" + --version + OUTPUT_VARIABLE output ERROR_VARIABLE output + RESULT_VARIABLE result + TIMEOUT 10 + ) + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Running the ${lang} compiler: \"${CMAKE_${lang}_COMPILER}\" --version\n" + "${output}\n" + ) + + if(output MATCHES [[\(GCC\) ([0-9]+\.[0-9]+(\.[0-9]+)?) compatible]]) + set(CMAKE_${lang}_SIMULATE_ID "GNU") + set(CMAKE_${lang}_SIMULATE_VERSION "${CMAKE_MATCH_1}") + endif() + endif() + + if (COMPILER_QNXNTO AND (CMAKE_${lang}_COMPILER_ID STREQUAL "GNU" OR CMAKE_${lang}_COMPILER_ID STREQUAL "LCC")) execute_process( COMMAND "${CMAKE_${lang}_COMPILER}" -V @@ -474,11 +495,7 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} if(CMAKE_VS_PLATFORM_NAME STREQUAL x64) set(cuda_target "<TargetMachinePlatform>64</TargetMachinePlatform>") endif() - foreach(arch ${CMAKE_CUDA_ARCHITECTURES}) - string(REGEX MATCH "[0-9]+" arch_name "${arch}") - string(APPEND cuda_codegen "compute_${arch_name},sm_${arch_name};") - endforeach() - set(id_ItemDefinitionGroup_entry "<CudaCompile>${cuda_target}<AdditionalOptions>%(AdditionalOptions)-v</AdditionalOptions><CodeGeneration>${cuda_codegen}</CodeGeneration></CudaCompile>") + set(id_ItemDefinitionGroup_entry "<CudaCompile>${cuda_target}<AdditionalOptions>%(AdditionalOptions)-v</AdditionalOptions></CudaCompile>") set(id_PostBuildEvent_Command [[echo CMAKE_CUDA_COMPILER=$(CudaToolkitBinDir)\nvcc.exe]]) if(CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR) # check for legacy cuda custom toolkit folder structure @@ -641,12 +658,8 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} elseif("${CMAKE_GENERATOR}" MATCHES "Green Hills MULTI") set(id_dir ${CMAKE_${lang}_COMPILER_ID_DIR}) set(id_src "${src}") - if (GHS_PRIMARY_TARGET) - set(ghs_primary_target "${GHS_PRIMARY_TARGET}") - else() - set(ghs_primary_target "${CMAKE_GENERATOR_PLATFORM}_${GHS_TARGET_PLATFORM}.tgt") - endif() - if ("${GHS_TARGET_PLATFORM}" MATCHES "integrity") + set(ghs_primary_target "${GHS_PRIMARY_TARGET}") + if ("${ghs_primary_target}" MATCHES "integrity") set(bsp_name "macro GHS_BSP=${GHS_BSP_NAME}") set(os_dir "macro GHS_OS=${GHS_OS_DIR}") endif() @@ -824,15 +837,24 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file) set(ARCHITECTURE_ID) set(SIMULATE_ID) set(SIMULATE_VERSION) + set(CMAKE_${lang}_COMPILER_ID_STRING_REGEX ".?I.?N.?F.?O.?:.?[A-Za-z0-9_]+\\[[^]]*\\]") foreach(encoding "" "ENCODING;UTF-16LE" "ENCODING;UTF-16BE") file(STRINGS "${file}" CMAKE_${lang}_COMPILER_ID_STRINGS LIMIT_COUNT 38 ${encoding} - REGEX ".?I.?N.?F.?O.?:.?[A-Za-z0-9_]+\\[[^]]*\\]") + REGEX "${CMAKE_${lang}_COMPILER_ID_STRING_REGEX}") if(NOT CMAKE_${lang}_COMPILER_ID_STRINGS STREQUAL "") break() endif() endforeach() + # Some ADSP processors result in characters being detected as separate strings + if(CMAKE_${lang}_COMPILER_ID_STRINGS STREQUAL "") + file(STRINGS "${file}" CMAKE_${lang}_COMPILER_ID_STRINGS LENGTH_MAXIMUM 1) + string(REGEX REPLACE ";" "" CMAKE_${lang}_COMPILER_ID_STRING "${CMAKE_${lang}_COMPILER_ID_STRINGS}") + string(REGEX MATCHALL "${CMAKE_${lang}_COMPILER_ID_STRING_REGEX}" + CMAKE_${lang}_COMPILER_ID_STRINGS "${CMAKE_${lang}_COMPILER_ID_STRING}") + endif() + # With the IAR Compiler, some strings are found twice, first time as incomplete # list like "?<Constant "INFO:compiler[IAR]">". Remove the incomplete copies. list(FILTER CMAKE_${lang}_COMPILER_ID_STRINGS EXCLUDE REGEX "\\?<Constant \\\"") diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake index 6a8984b..650c87a 100644 --- a/Modules/CMakeDetermineFortranCompiler.cmake +++ b/Modules/CMakeDetermineFortranCompiler.cmake @@ -52,6 +52,7 @@ else() # frt: Fujitsu F77 compiler # pathf90/pathf95/pathf2003: PathScale Fortran compiler # pgf77/pgf90/pgf95/pgfortran: Portland Group F77/F90/F95 compilers + # nvfortran: NVHPC Fotran compiler # flang: Flang Fortran compiler # xlf/xlf90/xlf95: IBM (AIX) F77/F90/F95 compilers # lf95: Lahey-Fujitsu F95 compiler @@ -70,29 +71,32 @@ else() # so if you paid for a compiler it is picked by default. if(CMAKE_HOST_WIN32) set(CMAKE_Fortran_COMPILER_LIST - ifort ifx pgf95 pgfortran lf95 fort + ifort ifx pgf95 pgfortran nvfortran lf95 fort flang gfortran gfortran-4 g95 f90 pgf90 pgf77 g77 f77 nag ) else() set(CMAKE_Fortran_COMPILER_LIST ftn - ifort ifc ifx efc pgf95 pgfortran lf95 xlf95 fort - flang gfortran gfortran-4 g95 f90 pgf90 + ifort ifc ifx efc pgf95 pgfortran nvfortran lf95 xlf95 fort + flang lfortran gfortran gfortran-4 g95 f90 pgf90 frt pgf77 xlf g77 f77 nag ) endif() # Vendor-specific compiler names. + set(_Fortran_COMPILER_NAMES_LCC lfortran gfortran) set(_Fortran_COMPILER_NAMES_GNU gfortran gfortran-4 g95 g77) set(_Fortran_COMPILER_NAMES_Intel ifort ifc efc ifx) set(_Fortran_COMPILER_NAMES_Absoft af95 af90 af77) set(_Fortran_COMPILER_NAMES_PGI pgf95 pgfortran pgf90 pgf77) set(_Fortran_COMPILER_NAMES_Flang flang) + set(_Fortran_COMPILER_NAMES_LLVMFlang flang) set(_Fortran_COMPILER_NAMES_PathScale pathf2003 pathf95 pathf90) set(_Fortran_COMPILER_NAMES_XL xlf) set(_Fortran_COMPILER_NAMES_VisualAge xlf95 xlf90 xlf) set(_Fortran_COMPILER_NAMES_NAG nagfor) + set(_Fortran_COMPILER_NAMES_NVHPC nvfortran) endif() _cmake_find_compiler(Fortran) diff --git a/Modules/CMakeDetermineSystem.cmake b/Modules/CMakeDetermineSystem.cmake index 8c7af06..2c2c2ac 100644 --- a/Modules/CMakeDetermineSystem.cmake +++ b/Modules/CMakeDetermineSystem.cmake @@ -128,7 +128,6 @@ if(CMAKE_TOOLCHAIN_FILE) set(CMAKE_TOOLCHAIN_FILE "${_INCLUDED_TOOLCHAIN_FILE}" CACHE FILEPATH "The CMake toolchain file" FORCE) else() message(FATAL_ERROR "Could not find toolchain file: ${CMAKE_TOOLCHAIN_FILE}") - set(CMAKE_TOOLCHAIN_FILE "NOTFOUND" CACHE FILEPATH "The CMake toolchain file" FORCE) endif() endif() diff --git a/Modules/CMakeExtraGeneratorDetermineCompilerMacrosAndIncludeDirs.cmake b/Modules/CMakeExtraGeneratorDetermineCompilerMacrosAndIncludeDirs.cmake index f90301b..5d7d430 100644 --- a/Modules/CMakeExtraGeneratorDetermineCompilerMacrosAndIncludeDirs.cmake +++ b/Modules/CMakeExtraGeneratorDetermineCompilerMacrosAndIncludeDirs.cmake @@ -88,7 +88,7 @@ set(ENV{LANG} C) # Now check for C, works for gcc and Intel compiler at least if (NOT CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS) - if (CMAKE_C_COMPILER_ID MATCHES GNU OR CMAKE_C_COMPILER_ID MATCHES "Intel" OR CMAKE_C_COMPILER_ID MATCHES Clang) + if (CMAKE_C_COMPILER_ID MATCHES GNU OR CMAKE_C_COMPILER_ID MATCHES "LCC" OR CMAKE_C_COMPILER_ID MATCHES "Intel" OR CMAKE_C_COMPILER_ID MATCHES Clang) _DETERMINE_GCC_SYSTEM_INCLUDE_DIRS(c _dirs _defines) set(CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS "${_dirs}" CACHE INTERNAL "C compiler system include directories") set(CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS "${_defines}" CACHE INTERNAL "C compiler system defined macros") @@ -99,7 +99,7 @@ endif () # And now the same for C++ if (NOT CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS) - if ("${CMAKE_CXX_COMPILER_ID}" MATCHES GNU OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES Clang) + if ("${CMAKE_CXX_COMPILER_ID}" MATCHES GNU OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "LCC" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES Clang) _DETERMINE_GCC_SYSTEM_INCLUDE_DIRS(c++ _dirs _defines) set(CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS "${_dirs}" CACHE INTERNAL "CXX compiler system include directories") set(CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS "${_defines}" CACHE INTERNAL "CXX compiler system defined macros") diff --git a/Modules/CMakeFindJavaCommon.cmake b/Modules/CMakeFindJavaCommon.cmake index 46b6280..c6e3348 100644 --- a/Modules/CMakeFindJavaCommon.cmake +++ b/Modules/CMakeFindJavaCommon.cmake @@ -19,7 +19,10 @@ else() set(_CMD_JAVA_HOME "") if(APPLE AND EXISTS /usr/libexec/java_home) execute_process(COMMAND /usr/libexec/java_home - OUTPUT_VARIABLE _CMD_JAVA_HOME OUTPUT_STRIP_TRAILING_WHITESPACE) + OUTPUT_VARIABLE _CMD_JAVA_HOME + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) endif() if(_CMD_JAVA_HOME AND IS_DIRECTORY "${_CMD_JAVA_HOME}") set(_JAVA_HOME "${_CMD_JAVA_HOME}") diff --git a/Modules/CMakeFortranCompilerId.F.in b/Modules/CMakeFortranCompilerId.F.in index d0e0e46..f5c2ab5 100644 --- a/Modules/CMakeFortranCompilerId.F.in +++ b/Modules/CMakeFortranCompilerId.F.in @@ -95,6 +95,13 @@ # endif #elif defined(__ABSOFT__) PRINT *, 'INFO:compiler[Absoft]' +#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__)) + PRINT *, 'INFO:compiler[LCC]' +# define COMPILER_VERSION_MAJOR DEC(1) +# define COMPILER_VERSION_MINOR DEC(__LCC__ - 100) +# if defined(__LCC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__) +# endif #elif defined(__GNUC__) PRINT *, 'INFO:compiler[GNU]' # define COMPILER_VERSION_MAJOR DEC(__GNUC__) @@ -147,6 +154,13 @@ # if defined(__FLANG_PATCHLEVEL__) # define COMPILER_VERSION_PATCH DEC(__FLANG_PATCHLEVEL__) # endif +#elif defined(__flang__) + PRINT *, 'INFO:compiler[LLVMFlang]' +# define COMPILER_VERSION_MAJOR DEC(__flang_major__) +# define COMPILER_VERSION_MINOR DEC(__flang_minor__) +# if defined(__flang_patchlevel__) +# define COMPILER_VERSION_PATCH DEC(__flang_patchlevel__) +# endif #elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) PRINT *, 'INFO:compiler[VisualAge]' #elif defined(__hpux) || defined(__hpux__) diff --git a/Modules/CMakeGenericSystem.cmake b/Modules/CMakeGenericSystem.cmake index 649b6f7..e2925dc 100644 --- a/Modules/CMakeGenericSystem.cmake +++ b/Modules/CMakeGenericSystem.cmake @@ -24,6 +24,12 @@ set(CMAKE_DL_LIBS "dl") set(CMAKE_FIND_LIBRARY_PREFIXES "lib") set(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".a") +# Define feature "DEFAULT" as supported. This special feature generates the +# default option to link a library +# This feature is intended to be used in LINK_LIBRARY_OVERRIDE and +# LINK_LIBRARY_OVERRIDE_<LIBRARY> target properties +set(CMAKE_LINK_LIBRARY_USING_DEFAULT_SUPPORTED TRUE) + set(CMAKE_AUTOGEN_ORIGIN_DEPENDS ON) set(CMAKE_AUTOMOC_COMPILER_PREDEFINES ON) if(NOT DEFINED CMAKE_AUTOMOC_PATH_PREFIX) @@ -41,11 +47,16 @@ set (CMAKE_SKIP_INSTALL_RPATH "NO" CACHE BOOL set(CMAKE_VERBOSE_MAKEFILE FALSE CACHE BOOL "If this value is on, makefiles will be generated without the .SILENT directive, and all commands will be echoed to the console during the make. This is useful for debugging only. With Visual Studio IDE projects all commands are done without /nologo.") +if(DEFINED ENV{CMAKE_COLOR_DIAGNOSTICS} AND NOT DEFINED CACHE{CMAKE_COLOR_DIAGNOSTICS}) + set(CMAKE_COLOR_DIAGNOSTICS $ENV{CMAKE_COLOR_DIAGNOSTICS} CACHE BOOL "Enable colored diagnostics throughout.") +endif() + if(CMAKE_GENERATOR MATCHES "Make") - set(CMAKE_COLOR_MAKEFILE ON CACHE BOOL - "Enable/Disable color output during build." - ) + if(NOT DEFINED CMAKE_COLOR_DIAGNOSTICS) + set(CMAKE_COLOR_MAKEFILE ON CACHE BOOL "Enable/Disable color output during build.") + endif() mark_as_advanced(CMAKE_COLOR_MAKEFILE) + if(DEFINED CMAKE_RULE_MESSAGES) set_property(GLOBAL PROPERTY RULE_MESSAGES ${CMAKE_RULE_MESSAGES}) endif() diff --git a/Modules/CMakePackageConfigHelpers.cmake b/Modules/CMakePackageConfigHelpers.cmake index 5813956..6f5702a 100644 --- a/Modules/CMakePackageConfigHelpers.cmake +++ b/Modules/CMakePackageConfigHelpers.cmake @@ -177,9 +177,9 @@ macro. packages with no binaries. .. versionadded:: 3.19 - ``COMPATIBILITY_MODE`` ``AnyNewerVersion``, ``SameMajorVersion`` and - ``SameMinorVersion`` handle the version range if any is specified - (see :command:`find_package` command for the details). + The version file generated by ``AnyNewerVersion``, ``SameMajorVersion`` and + ``SameMinorVersion`` arguments of ``COMPATIBILITY`` handle the version range + if any is specified (see :command:`find_package` command for the details). ``ExactVersion`` mode is incompatible with version ranges and will display an author warning if one is specified. diff --git a/Modules/CMakeParseImplicitLinkInfo.cmake b/Modules/CMakeParseImplicitLinkInfo.cmake index a61f71b..6bdefde 100644 --- a/Modules/CMakeParseImplicitLinkInfo.cmake +++ b/Modules/CMakeParseImplicitLinkInfo.cmake @@ -58,6 +58,10 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj endif() separate_arguments(args NATIVE_COMMAND "${line}") list(GET args 0 cmd) + if("${cmd}" MATCHES "->") + # LCC has '-> ' in-front of the linker + list(GET args 1 cmd) + endif() else() #check to see if the link line is comma-separated instead of space separated string(REGEX REPLACE "," " " line "${line}") diff --git a/Modules/CMakePlatformId.h.in b/Modules/CMakePlatformId.h.in index 59195f8..06f5ecd 100644 --- a/Modules/CMakePlatformId.h.in +++ b/Modules/CMakePlatformId.h.in @@ -105,6 +105,9 @@ # define PLATFORM_ID "Integrity" # endif +# elif defined(_ADI_COMPILER) +# define PLATFORM_ID "ADSP" + #else /* unknown platform */ # define PLATFORM_ID @@ -233,6 +236,12 @@ # define ARCHITECTURE_ID "" # endif +# elif defined(__ADSPSHARC__) +# define ARCHITECTURE_ID "SHARC" + +# elif defined(__ADSPBLACKFIN__) +# define ARCHITECTURE_ID "Blackfin" + #else # define ARCHITECTURE_ID #endif diff --git a/Modules/CMakePrintHelpers.cmake b/Modules/CMakePrintHelpers.cmake index 8c25a73..fb201dc 100644 --- a/Modules/CMakePrintHelpers.cmake +++ b/Modules/CMakePrintHelpers.cmake @@ -10,16 +10,19 @@ e.g. for debugging. :: - cmake_print_properties([TARGETS target1 .. targetN] - [SOURCES source1 .. sourceN] - [DIRECTORIES dir1 .. dirN] - [TESTS test1 .. testN] - [CACHE_ENTRIES entry1 .. entryN] - PROPERTIES prop1 .. propN ) + cmake_print_properties(<TARGETS [<target1> ...] | + SOURCES [<source1> ...] | + DIRECTORIES [<dir1> ...] | + TESTS [<test1> ...] | + CACHE_ENTRIES [<entry1> ...] > + PROPERTIES [<prop1> ...] ) This function prints the values of the properties of the given targets, source files, directories, tests or cache entries. Exactly one of the -scope keywords must be used. Example:: +scope keywords must be used. The scope keyword and its arguments must +come before the ``PROPERTIES`` keyword, in the arguments list. + +Example:: cmake_print_properties(TARGETS foo bar PROPERTIES LOCATION INTERFACE_INCLUDE_DIRECTORIES) @@ -56,17 +59,34 @@ endfunction() function(cmake_print_properties) set(options ) set(oneValueArgs ) - set(multiValueArgs TARGETS SOURCES TESTS DIRECTORIES CACHE_ENTRIES PROPERTIES ) + set(cpp_multiValueArgs PROPERTIES ) + set(cppmode_multiValueArgs TARGETS SOURCES TESTS DIRECTORIES CACHE_ENTRIES ) + + string(JOIN " " _mode_names ${cppmode_multiValueArgs}) + set(_missing_mode_message + "Mode keyword missing in cmake_print_properties() call, there must be exactly one of ${_mode_names}") - cmake_parse_arguments(CPP "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + cmake_parse_arguments( + CPP "${options}" "${oneValueArgs}" "${cpp_multiValueArgs}" ${ARGN}) - if(CPP_UNPARSED_ARGUMENTS) - message(FATAL_ERROR "Unknown keywords given to cmake_print_properties(): \"${CPP_UNPARSED_ARGUMENTS}\"") + if(NOT CPP_PROPERTIES) + message(FATAL_ERROR + "Required argument PROPERTIES missing in cmake_print_properties() call") return() endif() - if(NOT CPP_PROPERTIES) - message(FATAL_ERROR "Required argument PROPERTIES missing in cmake_print_properties() call") + if(NOT CPP_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "${_missing_mode_message}") + return() + endif() + + cmake_parse_arguments( + CPPMODE "${options}" "${oneValueArgs}" "${cppmode_multiValueArgs}" + ${CPP_UNPARSED_ARGUMENTS}) + + if(CPPMODE_UNPARSED_ARGUMENTS) + message(FATAL_ERROR + "Unknown keywords given to cmake_print_properties(): \"${CPPMODE_UNPARSED_ARGUMENTS}\"") return() endif() @@ -74,32 +94,32 @@ function(cmake_print_properties) set(items) set(keyword) - if(CPP_TARGETS) - set(items ${CPP_TARGETS}) + if(CPPMODE_TARGETS) + set(items ${CPPMODE_TARGETS}) set(mode ${mode} TARGETS) set(keyword TARGET) endif() - if(CPP_SOURCES) - set(items ${CPP_SOURCES}) + if(CPPMODE_SOURCES) + set(items ${CPPMODE_SOURCES}) set(mode ${mode} SOURCES) set(keyword SOURCE) endif() - if(CPP_TESTS) - set(items ${CPP_TESTS}) + if(CPPMODE_TESTS) + set(items ${CPPMODE_TESTS}) set(mode ${mode} TESTS) set(keyword TEST) endif() - if(CPP_DIRECTORIES) - set(items ${CPP_DIRECTORIES}) + if(CPPMODE_DIRECTORIES) + set(items ${CPPMODE_DIRECTORIES}) set(mode ${mode} DIRECTORIES) set(keyword DIRECTORY) endif() - if(CPP_CACHE_ENTRIES) - set(items ${CPP_CACHE_ENTRIES}) + if(CPPMODE_CACHE_ENTRIES) + set(items ${CPPMODE_CACHE_ENTRIES}) set(mode ${mode} CACHE_ENTRIES) # This is a workaround for the fact that passing `CACHE` as an argument to # set() causes a cache variable to be set. @@ -108,13 +128,14 @@ function(cmake_print_properties) endif() if(NOT mode) - message(FATAL_ERROR "Mode keyword missing in cmake_print_properties() call, must be one of TARGETS SOURCES TESTS DIRECTORIES CACHE_ENTRIES PROPERTIES") + message(FATAL_ERROR "${_missing_mode_message}") return() endif() list(LENGTH mode modeLength) if("${modeLength}" GREATER 1) - message(FATAL_ERROR "Multiple mode keyword used in cmake_print_properties() call, it must be exactly one of TARGETS SOURCES TESTS DIRECTORIES CACHE_ENTRIES PROPERTIES") + message(FATAL_ERROR + "Multiple mode keywords used in cmake_print_properties() call, there must be exactly one of ${_mode_names}.") return() endif() @@ -124,8 +145,8 @@ function(cmake_print_properties) set(itemExists TRUE) if(keyword STREQUAL "TARGET") if(NOT TARGET ${item}) - set(itemExists FALSE) - string(APPEND msg "\n No such TARGET \"${item}\" !\n\n") + set(itemExists FALSE) + string(APPEND msg "\n No such TARGET \"${item}\" !\n\n") endif() endif() diff --git a/Modules/CMakeSystemSpecificInformation.cmake b/Modules/CMakeSystemSpecificInformation.cmake index 0ded568..59f552a 100644 --- a/Modules/CMakeSystemSpecificInformation.cmake +++ b/Modules/CMakeSystemSpecificInformation.cmake @@ -17,6 +17,16 @@ set(CYGWIN ) set(MSYS ) set(WIN32 ) +function(_cmake_record_install_prefix ) + set(_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_VALUE "${CMAKE_INSTALL_PREFIX}" PARENT_SCOPE) + set(count 0) + foreach(value IN LISTS CMAKE_SYSTEM_PREFIX_PATH) + if(value STREQUAL CMAKE_INSTALL_PREFIX) + math(EXPR count "${count}+1") + endif() + endforeach() + set(_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_COUNT "${count}" PARENT_SCOPE) +endfunction() # include Generic system information include(CMakeGenericSystem) diff --git a/Modules/CMakeTestCUDACompiler.cmake b/Modules/CMakeTestCUDACompiler.cmake index 25a3653..853d655 100644 --- a/Modules/CMakeTestCUDACompiler.cmake +++ b/Modules/CMakeTestCUDACompiler.cmake @@ -21,6 +21,52 @@ if(CMAKE_CUDA_ABI_COMPILED) # The compiler worked so skip dedicated test below. set(CMAKE_CUDA_COMPILER_WORKS TRUE) message(STATUS "Check for working CUDA compiler: ${CMAKE_CUDA_COMPILER} - skipped") + + # Run the test binary to detect the native architectures. + execute_process(COMMAND "${CMAKE_PLATFORM_INFO_DIR}/CMakeDetermineCompilerABI_CUDA.bin" + RESULT_VARIABLE _CUDA_ARCHS_RESULT + OUTPUT_VARIABLE _CUDA_ARCHS_OUTPUT + ERROR_VARIABLE _CUDA_ARCHS_OUTPUT + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(_CUDA_ARCHS_RESULT EQUAL 0) + if("$ENV{CMAKE_CUDA_ARCHITECTURES_NATIVE_CLAMP}") + # Undocumented hook used by CMake's CI. + # Clamp native architecture to version range supported by this CUDA. + list(GET CMAKE_CUDA_ARCHITECTURES_ALL 0 _CUDA_ARCH_MIN) + list(GET CMAKE_CUDA_ARCHITECTURES_ALL -1 _CUDA_ARCH_MAX) + set(CMAKE_CUDA_ARCHITECTURES_NATIVE "") + foreach(_CUDA_ARCH IN LISTS _CUDA_ARCHS_OUTPUT) + if(_CUDA_ARCH LESS _CUDA_ARCH_MIN) + set(_CUDA_ARCH "${_CUDA_ARCH_MIN}") + endif() + if(_CUDA_ARCH GREATER _CUDA_ARCH_MAX) + set(_CUDA_ARCH "${_CUDA_ARCH_MAX}") + endif() + list(APPEND CMAKE_CUDA_ARCHITECTURES_NATIVE ${_CUDA_ARCH}) + endforeach() + unset(_CUDA_ARCH) + unset(_CUDA_ARCH_MIN) + unset(_CUDA_ARCH_MAX) + else() + set(CMAKE_CUDA_ARCHITECTURES_NATIVE "${_CUDA_ARCHS_OUTPUT}") + endif() + list(REMOVE_DUPLICATES CMAKE_CUDA_ARCHITECTURES_NATIVE) + list(TRANSFORM CMAKE_CUDA_ARCHITECTURES_NATIVE APPEND "-real") + else() + if(NOT _CUDA_ARCHS_RESULT MATCHES "[0-9]+") + set(_CUDA_ARCHS_STATUS " (${_CUDA_ARCHS_RESULT})") + else() + set(_CUDA_ARCHS_STATUS "") + endif() + string(REPLACE "\n" "\n " _CUDA_ARCHS_OUTPUT " ${_CUDA_ARCHS_OUTPUT}") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Detecting the CUDA native architecture(s) failed with " + "the following output:\n${_CUDA_ARCHS_OUTPUT}\n\n") + endif() + unset(_CUDA_ARCHS_EXE) + unset(_CUDA_ARCHS_RESULT) + unset(_CUDA_ARCHS_OUTPUT) endif() # This file is used by EnableLanguage in cmGlobalGenerator to diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake index 373a707..4934934 100644 --- a/Modules/CPack.cmake +++ b/Modules/CPack.cmake @@ -262,7 +262,7 @@ installers. The most commonly-used variables are: create Start Menu shortcuts. For example, setting this to the list ``ccmake;CMake`` will create a shortcut named "CMake" that will execute the installed executable ``ccmake``. Not all CPack generators use it (at least - NSIS, WIX and OSXX11 do). + NSIS, and WIX do). .. variable:: CPACK_STRIP_FILES @@ -304,14 +304,25 @@ installers. The most commonly-used variables are: By default ``CPACK_THREADS`` is set to ``1``. - Currently only ``xz`` compression *may* take advantage of multiple cores. - Other compression methods ignore this value and use only one thread. + The following compression methods may take advantage of multiple cores: + + ``xz`` + Supported if CMake is built with a ``liblzma`` that supports + parallel compression. + + .. versionadded:: 3.21 - .. versionadded:: 3.21 + Official CMake binaries available on ``cmake.org`` now ship + with a ``liblzma`` that supports parallel compression. + Older versions did not. - Official CMake binaries available on ``cmake.org`` now ship - with a ``liblzma`` that supports parallel compression. - Older versions did not. + ``zstd`` + .. versionadded:: 3.24 + + Supported if CMake is built with libarchive 3.6 or higher. + Official CMake binaries available on ``cmake.org`` support it. + + Other compression methods ignore this value and use only one thread. Variables for Source Package Generators ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -658,14 +669,10 @@ if(NOT CPACK_GENERATOR) if(APPLE) option(CPACK_BINARY_BUNDLE "Enable to build OSX bundles" OFF) option(CPACK_BINARY_DRAGNDROP "Enable to build OSX Drag And Drop package" OFF) - option(CPACK_BINARY_OSXX11 "Enable to build OSX X11 packages (deprecated)" OFF) - option(CPACK_BINARY_PACKAGEMAKER "Enable to build PackageMaker packages (deprecated)" OFF) option(CPACK_BINARY_PRODUCTBUILD "Enable to build productbuild packages" OFF) mark_as_advanced( CPACK_BINARY_BUNDLE CPACK_BINARY_DRAGNDROP - CPACK_BINARY_OSXX11 - CPACK_BINARY_PACKAGEMAKER CPACK_BINARY_PRODUCTBUILD ) else() @@ -717,8 +724,6 @@ if(NOT CPACK_GENERATOR) cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_IFW IFW) cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_NSIS NSIS) cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_NUGET NuGet) - cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_OSXX11 OSXX11) - cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_PACKAGEMAKER PackageMaker) cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_PRODUCTBUILD productbuild) cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_RPM RPM) cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_STGZ STGZ) @@ -808,6 +813,23 @@ _cpack_set_default(CPACK_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") _cpack_set_default(CPACK_NSIS_INSTALLER_ICON_CODE "") _cpack_set_default(CPACK_NSIS_INSTALLER_MUI_ICON_CODE "") +# DragNDrop specific variables +if(NOT DEFINED CPACK_DMG_SLA_USE_RESOURCE_FILE_LICENSE + AND CPACK_RESOURCE_FILE_LICENSE AND NOT CPACK_RESOURCE_FILE_LICENSE STREQUAL "${CMAKE_ROOT}/Templates/CPack.GenericLicense.txt") + cmake_policy(GET CMP0133 _CPack_CMP0133) + if(NOT "x${_CPack_CMP0133}x" STREQUAL "xNEWx") + if(NOT "x${_CPack_CMP0133}x" STREQUAL "xOLDx" AND CMAKE_POLICY_WARNING_CMP0133) + cmake_policy(GET_WARNING CMP0133 _CMP0133_warning) + message(AUTHOR_WARNING + "${_CMP0133_warning}\n" + "For compatibility, CMake will enable the SLA in the CPack DragNDrop Generator." + ) + endif() + _cpack_set_default(CPACK_DMG_SLA_USE_RESOURCE_FILE_LICENSE ON) + endif() + unset(_CPack_CMP0133) +endif() + # WiX specific variables _cpack_set_default(CPACK_WIX_SIZEOF_VOID_P "${CMAKE_SIZEOF_VOID_P}") diff --git a/Modules/CPackComponent.cmake b/Modules/CPackComponent.cmake index 1f8c38c..8ca9f28 100644 --- a/Modules/CPackComponent.cmake +++ b/Modules/CPackComponent.cmake @@ -327,32 +327,34 @@ OS X. if(NOT CPackComponent_CMake_INCLUDED) set(CPackComponent_CMake_INCLUDED 1) -# Macro that appends a SET command for the given variable name (var) -# to the macro named strvar, but only if the variable named "var" +# Function that appends a SET command for the given variable name (var) +# to the string named strvar, but only if the variable named "var" # has been defined. The string will eventually be appended to a CPack # configuration file. -macro(cpack_append_variable_set_command var strvar) +function(cpack_append_variable_set_command var strvar) if (DEFINED ${var}) string(APPEND ${strvar} "set(${var}") foreach(APPENDVAL ${${var}}) string(APPEND ${strvar} " ${APPENDVAL}") endforeach() string(APPEND ${strvar} ")\n") + set(${strvar} "${${strvar}}" PARENT_SCOPE) endif () -endmacro() +endfunction() -# Macro that appends a SET command for the given variable name (var) -# to the macro named strvar, but only if the variable named "var" +# Function that appends a SET command for the given variable name (var) +# to the string named strvar, but only if the variable named "var" # has been defined and is a string. The string will eventually be # appended to a CPack configuration file. -macro(cpack_append_string_variable_set_command var strvar) +function(cpack_append_string_variable_set_command var strvar) if (DEFINED ${var}) list(LENGTH ${var} CPACK_APP_VALUE_LEN) if(${CPACK_APP_VALUE_LEN} EQUAL 1) string(APPEND ${strvar} "set(${var} \"${${var}}\")\n") endif() + set(${strvar} "${${strvar}}" PARENT_SCOPE) endif () -endmacro() +endfunction() # Macro that appends a SET command for the given list variable name (var) # to the macro named strvar, but only if the variable named "var" diff --git a/Modules/CPackIFW.cmake b/Modules/CPackIFW.cmake index 85108db..003cf3f 100644 --- a/Modules/CPackIFW.cmake +++ b/Modules/CPackIFW.cmake @@ -439,6 +439,7 @@ set(_CPACK_IFW_PREFIXES "QtIFW-") set(_CPACK_IFW_VERSIONS + "4.3" "4.2" "4.1" "4.0" diff --git a/Modules/CUDA/architectures.cmake b/Modules/CUDA/architectures.cmake new file mode 100644 index 0000000..79c1252 --- /dev/null +++ b/Modules/CUDA/architectures.cmake @@ -0,0 +1,57 @@ +# See supported GPUs on Wikipedia +# https://en.wikipedia.org/wiki/CUDA#GPUs_supported + +# Initial set based on CUDA 7.0. +set(CMAKE_CUDA_ARCHITECTURES_ALL 20 21 30 35 37 50 52 53) +set(CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 20 30 35 50) + +if(CMAKE_CUDA_COMPILER_TOOLKIT_VERSION VERSION_GREATER_EQUAL 8.0) + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 60 61 62) + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 60) +endif() + +if(CMAKE_CUDA_COMPILER_TOOLKIT_VERSION VERSION_GREATER_EQUAL 9.0) + if(NOT CMAKE_CUDA_COMPILER_ID STREQUAL "Clang" OR CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0) + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 70 72) + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 70) + endif() + + list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL 20 21) + list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 20 21) +endif() + +if(CMAKE_CUDA_COMPILER_TOOLKIT_VERSION VERSION_GREATER_EQUAL 10.0 + AND (NOT CMAKE_CUDA_COMPILER_ID STREQUAL "Clang" OR CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0)) + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 75) +endif() + +if(CMAKE_CUDA_COMPILER_TOOLKIT_VERSION VERSION_GREATER_EQUAL 11.0) + if(NOT CMAKE_CUDA_COMPILER_ID STREQUAL "Clang" OR CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0) + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 80) + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 80) + endif() + + list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL 30) + list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR 30) +endif() + +if(CMAKE_CUDA_COMPILER_TOOLKIT_VERSION VERSION_GREATER_EQUAL 11.1 + AND (NOT CMAKE_CUDA_COMPILER_ID STREQUAL "Clang" OR CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0)) + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 86) +endif() + +if(CMAKE_CUDA_COMPILER_TOOLKIT_VERSION VERSION_GREATER_EQUAL 11.4 + AND (NOT CMAKE_CUDA_COMPILER_ID STREQUAL "Clang")) + list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL 87) +endif() + +# only generate jit code for the newest arch for all/all-major +list(POP_BACK CMAKE_CUDA_ARCHITECTURES_ALL _latest_arch) +list(TRANSFORM CMAKE_CUDA_ARCHITECTURES_ALL APPEND "-real") +list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL ${_latest_arch}) + +list(POP_BACK CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR _latest_arch) +list(TRANSFORM CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR APPEND "-real") +list(APPEND CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR ${_latest_arch}) + +unset(_latest_arch) diff --git a/Modules/CheckIPOSupported.cmake b/Modules/CheckIPOSupported.cmake index 0bc3c92..cca1be9 100644 --- a/Modules/CheckIPOSupported.cmake +++ b/Modules/CheckIPOSupported.cmake @@ -36,6 +36,11 @@ module will return error in this case. See policy :policy:`CMP0069` for details. .. versionadded:: 3.13 Add support for Visual Studio generators. +.. versionadded:: 3.24 + The check uses the caller's :variable:`CMAKE_<LANG>_FLAGS` + and :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` values. + See policy :policy:`CMP0138`. + Examples ^^^^^^^^ @@ -117,6 +122,16 @@ macro(_ipo_run_language_check language) ) endforeach() + if(ipo_CMP0138 STREQUAL "NEW") + set(CMAKE_TRY_COMPILE_CONFIGURATION Debug) + set(_CMAKE_LANG_FLAGS + "-DCMAKE_${language}_FLAGS:STRING=${CMAKE_${language}_FLAGS}" + "-DCMAKE_${language}_FLAGS_DEBUG:STRING=${CMAKE_${language}_FLAGS_DEBUG}" + ) + else() + set(_CMAKE_LANG_FLAGS "") + endif() + try_compile( _IPO_LANGUAGE_CHECK_RESULT "${bindir}" @@ -125,6 +140,7 @@ macro(_ipo_run_language_check language) CMAKE_FLAGS "-DCMAKE_VERBOSE_MAKEFILE=ON" "-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON" + ${_CMAKE_LANG_FLAGS} OUTPUT_VARIABLE output ) set(_IPO_LANGUAGE_CHECK_RESULT "${_IPO_LANGUAGE_CHECK_RESULT}") @@ -155,6 +171,11 @@ function(check_ipo_supported) message(FATAL_ERROR "Policy CMP0069 set to OLD") endif() + # Save policy setting for condition in _ipo_run_language_check. + cmake_policy(GET CMP0138 ipo_CMP0138 + PARENT_SCOPE # undocumented, do not use outside of CMake + ) + set(optional) set(one RESULT OUTPUT) set(multiple LANGUAGES) diff --git a/Modules/CheckLinkerFlag.cmake b/Modules/CheckLinkerFlag.cmake index e85e43e..8319216 100644 --- a/Modules/CheckLinkerFlag.cmake +++ b/Modules/CheckLinkerFlag.cmake @@ -38,53 +38,8 @@ effect or even a specific one is beyond the scope of this module. #]=======================================================================] include_guard(GLOBAL) - -include(CMakeCheckCompilerFlagCommonPatterns) - -cmake_policy(PUSH) -cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced -cmake_policy(SET CMP0057 NEW) # if() supports IN_LIST +include(Internal/CheckLinkerFlag) function(CHECK_LINKER_FLAG _lang _flag _var) - get_property (_supported_languages GLOBAL PROPERTY ENABLED_LANGUAGES) - if (NOT _lang IN_LIST _supported_languages) - message (SEND_ERROR "check_linker_flag: ${_lang}: unknown language.") - return() - endif() - - include (CheckSourceCompiles) - - set(CMAKE_REQUIRED_LINK_OPTIONS "${_flag}") - - # Normalize locale during test compilation. - set(_locale_vars LC_ALL LC_MESSAGES LANG) - foreach(v IN LISTS _locale_vars) - set(_locale_vars_saved_${v} "$ENV{${v}}") - set(ENV{${v}} C) - endforeach() - - if (_lang MATCHES "^(C|CXX)$") - set (_source "int main() { return 0; }") - elseif (_lang STREQUAL "Fortran") - set (_source " program test\n stop\n end program") - elseif (_lang MATCHES "CUDA") - set (_source "__host__ int main() { return 0; }") - elseif (_lang MATCHES "HIP") - set (_source "__host__ int main() { return 0; }") - elseif (_lang MATCHES "^(OBJC|OBJCXX)$") - set (_source "#ifndef __OBJC__\n# error \"Not an Objective-C++ compiler\"\n#endif\nint main(void) { return 0; }") - else() - message (SEND_ERROR "check_linker_flag: ${_lang}: unsupported language.") - return() - endif() - check_compiler_flag_common_patterns(_common_patterns) - - check_source_compiles(${_lang} "${_source}" ${_var} ${_common_patterns}) - - foreach(v IN LISTS _locale_vars) - set(ENV{${v}} ${_locale_vars_saved_${v}}) - endforeach() - set(${_var} "${${_var}}" PARENT_SCOPE) + cmake_check_linker_flag(${_lang} "${_flag}" ${_var}) endfunction() - -cmake_policy(POP) diff --git a/Modules/CheckPIESupported.cmake b/Modules/CheckPIESupported.cmake index fb87822..452348b 100644 --- a/Modules/CheckPIESupported.cmake +++ b/Modules/CheckPIESupported.cmake @@ -22,10 +22,19 @@ property for executables will be honored at link time. Options are: ``OUTPUT_VARIABLE <output>`` - Set ``<output>`` variable with details about any error. + Set ``<output>`` variable with details about any error. If the check is + bypassed because it uses cached results from a previous call, the output + will be empty even if errors were present in the previous call. + ``LANGUAGES <lang>...`` Check the linkers used for each of the specified languages. - Supported languages are ``C``, ``CXX``, and ``Fortran``. + If this option is not provided, the command checks all enabled languages. + + ``C``, ``CXX``, ``Fortran`` are supported. + + .. versionadded:: 3.23 + + ``OBJC``, ``OBJCXX``, ``CUDA``, and ``HIP`` are supported. It makes no sense to use this module when :policy:`CMP0083` is set to ``OLD``, so the command will return an error in this case. See policy :policy:`CMP0083` @@ -37,9 +46,9 @@ Variables For each language checked, two boolean cache variables are defined. ``CMAKE_<lang>_LINK_PIE_SUPPORTED`` - Set to ``YES`` if ``PIE`` is supported by the linker and ``NO`` otherwise. + Set to true if ``PIE`` is supported by the linker and false otherwise. ``CMAKE_<lang>_LINK_NO_PIE_SUPPORTED`` - Set to ``YES`` if ``NO_PIE`` is supported by the linker and ``NO`` otherwise. + Set to true if ``NO_PIE`` is supported by the linker and false otherwise. Examples ^^^^^^^^ @@ -62,7 +71,7 @@ Examples #]=======================================================================] -include (Internal/CMakeTryCompilerOrLinkerFlag) +include (Internal/CheckLinkerFlag) function (check_pie_supported) cmake_policy(GET CMP0083 cmp0083) @@ -86,7 +95,7 @@ function (check_pie_supported) if (CHECK_PIE_LANGUAGES) set (unsupported_languages "${CHECK_PIE_LANGUAGES}") - list (REMOVE_ITEM unsupported_languages "C" "CXX" "Fortran") + list (REMOVE_ITEM unsupported_languages "C" "CXX" "OBJC" "OBJCXX" "Fortran" "CUDA" "HIP") if(unsupported_languages) message(FATAL_ERROR "check_pie_supported: language(s) '${unsupported_languages}' not supported") endif() @@ -97,7 +106,7 @@ function (check_pie_supported) return() endif() - list (FILTER enabled_languages INCLUDE REGEX "^(C|CXX|Fortran)$") + list (FILTER enabled_languages INCLUDE REGEX "^(C|CXX|OBJC|OBJCXX|Fortran|CUDA|HIP)$") if (NOT enabled_languages) return() endif() @@ -105,30 +114,35 @@ function (check_pie_supported) set (CHECK_PIE_LANGUAGES ${enabled_languages}) endif() + set(CMAKE_REQUIRED_QUIET TRUE) set (outputs) foreach(lang IN LISTS CHECK_PIE_LANGUAGES) if(_CMAKE_${lang}_PIE_MAY_BE_SUPPORTED_BY_LINKER) - cmake_try_compiler_or_linker_flag(${lang} + if(NOT DEFINED CMAKE_${lang}_LINK_PIE_SUPPORTED) + cmake_check_linker_flag(${lang} "${CMAKE_${lang}_LINK_OPTIONS_PIE}" CMAKE_${lang}_LINK_PIE_SUPPORTED OUTPUT_VARIABLE output) - if (NOT CMAKE_${lang}_LINK_PIE_SUPPORTED) - string (APPEND outputs "PIE (${lang}): ${output}\n") + if (NOT CMAKE_${lang}_LINK_PIE_SUPPORTED) + string (APPEND outputs "PIE (${lang}): ${output}\n") + endif() endif() - cmake_try_compiler_or_linker_flag(${lang} + if(NOT DEFINED CMAKE_${lang}_LINK_NO_PIE_SUPPORTED) + cmake_check_linker_flag(${lang} "${CMAKE_${lang}_LINK_OPTIONS_NO_PIE}" CMAKE_${lang}_LINK_NO_PIE_SUPPORTED OUTPUT_VARIABLE output) - if (NOT CMAKE_${lang}_LINK_NO_PIE_SUPPORTED) - string (APPEND outputs "NO_PIE (${lang}): ${output}\n") + if (NOT CMAKE_${lang}_LINK_NO_PIE_SUPPORTED) + string (APPEND outputs "NO_PIE (${lang}): ${output}\n") + endif() endif() else() # no support at link time. Set cache variables to NO set(CMAKE_${lang}_LINK_PIE_SUPPORTED NO CACHE INTERNAL "PIE (${lang})") set(CMAKE_${lang}_LINK_NO_PIE_SUPPORTED NO CACHE INTERNAL "NO_PIE (${lang})") - string (APPEND outputs "PIE and NO_PIE are not supported by linker for ${lang}") + string (APPEND outputs "PIE and NO_PIE are not supported by linker for ${lang}\n") endif() endforeach() diff --git a/Modules/CheckSymbolExists.cmake b/Modules/CheckSymbolExists.cmake index 48ee3c4..a7139af 100644 --- a/Modules/CheckSymbolExists.cmake +++ b/Modules/CheckSymbolExists.cmake @@ -67,14 +67,29 @@ cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced macro(CHECK_SYMBOL_EXISTS SYMBOL FILES VARIABLE) if(CMAKE_C_COMPILER_LOADED) + __CHECK_SYMBOL_EXISTS_FILTER_FLAGS(C) __CHECK_SYMBOL_EXISTS_IMPL("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c" "${SYMBOL}" "${FILES}" "${VARIABLE}" ) + __CHECK_SYMBOL_EXISTS_RESTORE_FLAGS(C) elseif(CMAKE_CXX_COMPILER_LOADED) + __CHECK_SYMBOL_EXISTS_FILTER_FLAGS(CXX) __CHECK_SYMBOL_EXISTS_IMPL("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.cxx" "${SYMBOL}" "${FILES}" "${VARIABLE}" ) + __CHECK_SYMBOL_EXISTS_RESTORE_FLAGS(CXX) else() message(FATAL_ERROR "CHECK_SYMBOL_EXISTS needs either C or CXX language enabled") endif() endmacro() +macro(__CHECK_SYMBOL_EXISTS_FILTER_FLAGS LANG) + set(__CMAKE_${LANG}_FLAGS_SAVED "${CMAKE_${LANG}_FLAGS}") + string(REGEX REPLACE "(^| )-Werror([= ][^ ]*)?( |$)" " " CMAKE_${LANG}_FLAGS "${CMAKE_${LANG}_FLAGS}") + string(REGEX REPLACE "(^| )-pedantic-errors( |$)" " " CMAKE_${LANG}_FLAGS "${CMAKE_${LANG}_FLAGS}") +endmacro() + +macro(__CHECK_SYMBOL_EXISTS_RESTORE_FLAGS LANG) + set(CMAKE_${LANG}_FLAGS "${__CMAKE_${LANG}_FLAGS_SAVED}") + unset(__CMAKE_${LANG}_FLAGS_SAVED) +endmacro() + macro(__CHECK_SYMBOL_EXISTS_IMPL SOURCEFILE SYMBOL FILES VARIABLE) if(NOT DEFINED "${VARIABLE}" OR "x${${VARIABLE}}" STREQUAL "x${VARIABLE}") set(CMAKE_CONFIGURABLE_FILE_CONTENT "/* */\n") diff --git a/Modules/CheckTypeSize.cmake b/Modules/CheckTypeSize.cmake index 69f68f9..602170c 100644 --- a/Modules/CheckTypeSize.cmake +++ b/Modules/CheckTypeSize.cmake @@ -7,46 +7,53 @@ CheckTypeSize Check sizeof a type -.. command:: CHECK_TYPE_SIZE +.. command:: check_type_size .. code-block:: cmake - CHECK_TYPE_SIZE(TYPE VARIABLE [BUILTIN_TYPES_ONLY] - [LANGUAGE <language>]) + check_type_size(<type> <variable> [BUILTIN_TYPES_ONLY] + [LANGUAGE <language>]) - Check if the type exists and determine its size. On return, - ``HAVE_${VARIABLE}`` holds the existence of the type, and ``${VARIABLE}`` - holds one of the following: + Check if the type exists and determine its size. Results are reported + in the following variables: - :: + ``HAVE_<variable>`` + Holds a true or false value indicating whether the type exists. - <size> = type has non-zero size <size> - "0" = type has arch-dependent size (see below) - "" = type does not exist + ``<variable>`` + Holds one of the following values: - Both ``HAVE_${VARIABLE}`` and ``${VARIABLE}`` will be created as internal - cache variables. + ``<size>`` + Type has non-zero size ``<size>``. - Furthermore, the variable ``${VARIABLE}_CODE`` holds C preprocessor code - to define the macro ``${VARIABLE}`` to the size of the type, or leave - the macro undefined if the type does not exist. + ``0`` + Type has architecture-dependent size. This may occur when + :variable:`CMAKE_OSX_ARCHITECTURES` has multiple architectures. + In this case ``<variable>_CODE`` contains C preprocessor tests + mapping from each architecture macro to the corresponding type size. + The list of architecture macros is stored in ``<variable>_KEYS``, + and the value for each key is stored in ``<variable>-<key>``. - The variable ``${VARIABLE}`` may be ``0`` when - :variable:`CMAKE_OSX_ARCHITECTURES` has multiple architectures for building - OS X universal binaries. This indicates that the type size varies across - architectures. In this case ``${VARIABLE}_CODE`` contains C preprocessor - tests mapping from each architecture macro to the corresponding type size. - The list of architecture macros is stored in ``${VARIABLE}_KEYS``, and the - value for each key is stored in ``${VARIABLE}-${KEY}``. + "" (empty string) + Type does not exist. - If the ``BUILTIN_TYPES_ONLY`` option is not given, the macro checks for - headers ``<sys/types.h>``, ``<stdint.h>``, and ``<stddef.h>``, and saves - results in ``HAVE_SYS_TYPES_H``, ``HAVE_STDINT_H``, and ``HAVE_STDDEF_H``. - The type size check automatically includes the available headers, thus - supporting checks of types defined in the headers. + ``<variable>_CODE`` + Holds C preprocessor code to define the macro ``<variable>`` to the size + of the type, or to leave the macro undefined if the type does not exist. - If ``LANGUAGE`` is set, the specified compiler will be used to perform the - check. Acceptable values are ``C`` and ``CXX``. + The options are: + + ``BUILTIN_TYPES_ONLY`` + + Support only compiler-builtin types. If *not* given, the macro checks + for headers ``<sys/types.h>``, ``<stdint.h>``, and ``<stddef.h>``, and + saves results in ``HAVE_SYS_TYPES_H``, ``HAVE_STDINT_H``, and + ``HAVE_STDDEF_H``. The type size check automatically includes the + available headers, thus supporting checks of types defined in the headers. + + ``LANGUAGE <language>`` + Use the ``<language>`` compiler to perform the check. + Acceptable values are ``C`` and ``CXX``. Despite the name of the macro you may use it to check the size of more complex expressions, too. To check e.g. for the size of a struct diff --git a/Modules/Compiler/ADSP-C.cmake b/Modules/Compiler/ADSP-C.cmake new file mode 100644 index 0000000..cef3fb1 --- /dev/null +++ b/Modules/Compiler/ADSP-C.cmake @@ -0,0 +1,11 @@ +include(Compiler/CMakeCommonCompilerMacros) +include(Compiler/ADSP) + +__compiler_adsp(C) + +set(CMAKE_C90_STANDARD_COMPILE_OPTION -c89) +set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON) + +set(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT ON) + +__compiler_check_default_language_standard(C 8.0.0.0 99) diff --git a/Modules/Compiler/ADSP-CXX.cmake b/Modules/Compiler/ADSP-CXX.cmake new file mode 100644 index 0000000..b01cab1 --- /dev/null +++ b/Modules/Compiler/ADSP-CXX.cmake @@ -0,0 +1,16 @@ +include(Compiler/CMakeCommonCompilerMacros) +include(Compiler/ADSP) + +__compiler_adsp(CXX) + +set(CMAKE_CXX98_STANDARD_COMPILE_OPTION -c++) +set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION -g++) +set(CMAKE_CXX98_STANDARD__HAS_FULL_SUPPORT ON) + +if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.3.0.0) + set(CMAKE_CXX11_STANDARD_COMPILE_OPTION -c++11) + set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION -c++11 -g++) + set(CMAKE_CXX11_STANDARD__HAS_FULL_SUPPORT ON) +endif() + +__compiler_check_default_language_standard(CXX 8.0.0.0 98) diff --git a/Modules/Compiler/ADSP-DetermineCompiler.cmake b/Modules/Compiler/ADSP-DetermineCompiler.cmake index 0340f69..96c88f9 100644 --- a/Modules/Compiler/ADSP-DetermineCompiler.cmake +++ b/Modules/Compiler/ADSP-DetermineCompiler.cmake @@ -1,10 +1,11 @@ -set(_compiler_id_pp_test "defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__)") +set(_compiler_id_pp_test "defined(_ADI_COMPILER)") set(_compiler_id_version_compute " -#if defined(__VISUALDSPVERSION__) - /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ -# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_HEX@(__VISUALDSPVERSION__>>24) -# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_HEX@(__VISUALDSPVERSION__>>16 & 0xFF) -# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_HEX@(__VISUALDSPVERSION__>>8 & 0xFF) +#if defined(__VERSIONNUM__) + /* __VERSIONNUM__ = 0xVVRRPPTT */ +# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__VERSIONNUM__ >> 24 & 0xFF) +# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__VERSIONNUM__ >> 16 & 0xFF) +# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__VERSIONNUM__ >> 8 & 0xFF) +# define @PREFIX@COMPILER_VERSION_TWEAK @MACRO_DEC@(__VERSIONNUM__ & 0xFF) #endif") diff --git a/Modules/Compiler/ADSP.cmake b/Modules/Compiler/ADSP.cmake new file mode 100644 index 0000000..62566a0 --- /dev/null +++ b/Modules/Compiler/ADSP.cmake @@ -0,0 +1,26 @@ +include_guard() + +set(CMAKE_EXECUTABLE_SUFFIX ".dxe") + +macro(__compiler_adsp lang) + set(CMAKE_${lang}_OUTPUT_EXTENSION ".doj") + + set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-flags-link" " ") + set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",") + + set(_CMAKE_${lang}_ADSP_FLAGS "-proc=${CMAKE_ADSP_PROCESSOR}") + + set(CMAKE_${lang}_COMPILE_OBJECT + "<CMAKE_${lang}_COMPILER> ${_CMAKE_${lang}_ADSP_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>") + + set(CMAKE_${lang}_CREATE_STATIC_LIBRARY + "<CMAKE_${lang}_COMPILER> ${_CMAKE_${lang}_ADSP_FLAGS} -build-lib -o <TARGET> <CMAKE_${lang}_LINK_FLAGS> <OBJECTS>") + + set(CMAKE_${lang}_LINK_EXECUTABLE + "<CMAKE_${lang}_COMPILER> ${_CMAKE_${lang}_ADSP_FLAGS} <FLAGS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>") + + unset(_CMAKE_${lang}_ADSP_FLAGS) + + set(CMAKE_${lang}_CREATE_SHARED_LIBRARY) + set(CMAKE_${lang}_CREATE_MODULE_LIBRARY) +endmacro() diff --git a/Modules/Compiler/Clang-CUDA.cmake b/Modules/Compiler/Clang-CUDA.cmake index 0223081..219897e 100644 --- a/Modules/Compiler/Clang-CUDA.cmake +++ b/Modules/Compiler/Clang-CUDA.cmake @@ -18,8 +18,13 @@ __compiler_clang_cxx_standards(CUDA) set(CMAKE_CUDA_COMPILER_HAS_DEVICE_LINK_PHASE TRUE) set(_CMAKE_COMPILE_AS_CUDA_FLAG "-x cuda") +set(_CMAKE_CUDA_WHOLE_FLAG "-c") +set(_CMAKE_CUDA_RDC_FLAG "-fgpu-rdc") set(_CMAKE_CUDA_PTX_FLAG "--cuda-device-only -S") -set(_CMAKE_CUDA_DEVICE_CODE "-fgpu-rdc -c") + +# Device linking is just regular linking so these are the same. +set(CMAKE_CUDA_DEVICE_LINKER_WRAPPER_FLAG ${CMAKE_CUDA_LINKER_WRAPPER_FLAG}) +set(CMAKE_CUDA_DEVICE_LINKER_WRAPPER_FLAG_SEP ${CMAKE_CUDA_LINKER_WRAPPER_FLAG_SEP}) # RulePlaceholderExpander expands crosscompile variables like sysroot and target only for CMAKE_<LANG>_COMPILER. Override the default. set(CMAKE_CUDA_LINK_EXECUTABLE "<CMAKE_CUDA_COMPILER> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICIT_LINKS}") diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake index f885eb0..df115d3 100644 --- a/Modules/Compiler/Clang.cmake +++ b/Modules/Compiler/Clang.cmake @@ -114,6 +114,12 @@ else() endif() set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH -Xclang -include-pch -Xclang <PCH_FILE> -Xclang -include -Xclang <PCH_HEADER>) set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH -Xclang -emit-pch -Xclang -include -Xclang <PCH_HEADER> -x ${__pch_header_${lang}}) + + # '-fcolor-diagnostics' introduced since Clang 2.6 + if(CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 2.6) + set(CMAKE_${lang}_COMPILE_OPTIONS_COLOR_DIAGNOSTICS "-fcolor-diagnostics") + set(CMAKE_${lang}_COMPILE_OPTIONS_COLOR_DIAGNOSTICS_OFF "-fno-color-diagnostics") + endif() endmacro() endif() diff --git a/Modules/Compiler/Fujitsu.cmake b/Modules/Compiler/Fujitsu.cmake index 78495cb..55c2aa4 100644 --- a/Modules/Compiler/Fujitsu.cmake +++ b/Modules/Compiler/Fujitsu.cmake @@ -11,6 +11,7 @@ include(Compiler/CMakeCommonCompilerMacros) macro(__compiler_fujitsu lang) set(CMAKE_${lang}_VERBOSE_FLAG "-###") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-cwno") # Initial configuration flags string(APPEND CMAKE_${lang}_FLAGS_INIT " ") diff --git a/Modules/Compiler/GNU.cmake b/Modules/Compiler/GNU.cmake index 928e726..db1eab5 100644 --- a/Modules/Compiler/GNU.cmake +++ b/Modules/Compiler/GNU.cmake @@ -18,6 +18,7 @@ set(__pch_header_OBJCXX "objective-c++-header") macro(__compiler_gnu lang) # Feature flags. set(CMAKE_${lang}_VERBOSE_FLAG "-v") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror") set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC") set (_CMAKE_${lang}_PIE_MAY_BE_SUPPORTED_BY_LINKER NO) if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 3.4) @@ -71,7 +72,18 @@ macro(__compiler_gnu lang) # * https://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc/Option-Summary.html (yes) if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 4.5) set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) - set(__lto_flags -flto) + + set(__lto_flags "") + + # '-flto=auto' introduced since GCC 10.1: + # * https://gcc.gnu.org/onlinedocs/gcc-9.5.0/gcc/Optimize-Options.html#Optimize-Options (no) + # * https://gcc.gnu.org/onlinedocs/gcc-10.1.0/gcc/Optimize-Options.html#Optimize-Options (yes) + # Since GCC 12.1, the abundance of a parameter produces a warning if compiling multiple targets. + if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 10.1) + list(APPEND __lto_flags -flto=auto) + else() + list(APPEND __lto_flags -flto) + endif() if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 4.7) # '-ffat-lto-objects' introduced since GCC 4.7: @@ -119,4 +131,11 @@ macro(__compiler_gnu lang) set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH -include <PCH_HEADER>) set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH -x ${__pch_header_${lang}} -include <PCH_HEADER>) endif() + + # '-fdiagnostics-color=always' introduced since GCC 4.9 + # https://gcc.gnu.org/gcc-4.9/changes.html + if(CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 4.9) + set(CMAKE_${lang}_COMPILE_OPTIONS_COLOR_DIAGNOSTICS "-fdiagnostics-color=always") + set(CMAKE_${lang}_COMPILE_OPTIONS_COLOR_DIAGNOSTICS_OFF "-fno-diagnostics-color") + endif() endmacro() diff --git a/Modules/Compiler/IAR-CXX.cmake b/Modules/Compiler/IAR-CXX.cmake index 7df74ad..6c15735 100644 --- a/Modules/Compiler/IAR-CXX.cmake +++ b/Modules/Compiler/IAR-CXX.cmake @@ -19,12 +19,14 @@ if(NOT CMAKE_IAR_CXX_FLAG) cmake_policy(PUSH) cmake_policy(SET CMP0057 NEW) # if IN_LIST - if(${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT} IN_LIST "14;17" OR + set(_CMAKE_IAR_MODERNCXX_LIST 14 17) + if(${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT} IN_LIST _CMAKE_IAR_MODERNCXX_LIST OR ("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM" AND ${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT} EQUAL 98)) string(PREPEND CMAKE_CXX_FLAGS "--c++ ") else() string(PREPEND CMAKE_CXX_FLAGS "--eec++ ") endif() + unset(_CMAKE_IAR_MODERNCXX_LIST) cmake_policy(POP) endif() diff --git a/Modules/Compiler/IBMClang-ASM.cmake b/Modules/Compiler/IBMClang-ASM.cmake new file mode 100644 index 0000000..dffc085 --- /dev/null +++ b/Modules/Compiler/IBMClang-ASM.cmake @@ -0,0 +1,5 @@ +include(Compiler/IBMClang) + +set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;S;asm) + +__compiler_ibmclang(ASM) diff --git a/Modules/Compiler/IBMClang-C-DetermineCompiler.cmake b/Modules/Compiler/IBMClang-C-DetermineCompiler.cmake new file mode 100644 index 0000000..623c8af --- /dev/null +++ b/Modules/Compiler/IBMClang-C-DetermineCompiler.cmake @@ -0,0 +1,8 @@ +set(_compiler_id_pp_test "defined(__open_xl__) && defined(__clang__)") + +set(_compiler_id_version_compute " +# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__open_xl_version__) +# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__open_xl_release__) +# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__open_xl_modification__) +# define @PREFIX@COMPILER_VERSION_TWEAK @MACRO_DEC@(__open_xl_ptf_fix_level__) +") diff --git a/Modules/Compiler/IBMClang-C.cmake b/Modules/Compiler/IBMClang-C.cmake new file mode 100644 index 0000000..b69b1b8 --- /dev/null +++ b/Modules/Compiler/IBMClang-C.cmake @@ -0,0 +1,30 @@ +include(Compiler/IBMClang) +__compiler_ibmclang(C) + +set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c) + +if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) + AND CMAKE_GENERATOR MATCHES "Makefiles|WMake" + AND CMAKE_DEPFILE_FLAGS_C) + # dependencies are computed by the compiler itself + set(CMAKE_C_DEPFILE_FORMAT gcc) + set(CMAKE_C_DEPENDS_USE_COMPILER TRUE) +endif() + +set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON) +set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90") +set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90") + +set(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT ON) +set(CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99") +set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=gnu99") + +set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON) +set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c11") +set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11") + +if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 17.1.0) + set(CMAKE_C17_STANDARD_COMPILE_OPTION "-std=c17") + set(CMAKE_C17_EXTENSION_COMPILE_OPTION "-std=gnu17") +endif () +__compiler_check_default_language_standard(C 17.1.0 17) diff --git a/Modules/Compiler/IBMClang-CXX-DetermineCompiler.cmake b/Modules/Compiler/IBMClang-CXX-DetermineCompiler.cmake new file mode 100644 index 0000000..623c8af --- /dev/null +++ b/Modules/Compiler/IBMClang-CXX-DetermineCompiler.cmake @@ -0,0 +1,8 @@ +set(_compiler_id_pp_test "defined(__open_xl__) && defined(__clang__)") + +set(_compiler_id_version_compute " +# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__open_xl_version__) +# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__open_xl_release__) +# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__open_xl_modification__) +# define @PREFIX@COMPILER_VERSION_TWEAK @MACRO_DEC@(__open_xl_ptf_fix_level__) +") diff --git a/Modules/Compiler/IBMClang-CXX.cmake b/Modules/Compiler/IBMClang-CXX.cmake new file mode 100644 index 0000000..5431b17 --- /dev/null +++ b/Modules/Compiler/IBMClang-CXX.cmake @@ -0,0 +1,39 @@ +include(Compiler/IBMClang) +__compiler_ibmclang(CXX) + +if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU") + if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) + AND CMAKE_GENERATOR MATCHES "Makefiles|WMake" + AND CMAKE_DEPFILE_FLAGS_CXX) + # dependencies are computed by the compiler itself + set(CMAKE_CXX_DEPFILE_FORMAT gcc) + set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE) + endif() + + set(CMAKE_CXX_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c++) + set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") +endif() + +set(CMAKE_CXX98_STANDARD__HAS_FULL_SUPPORT ON) +set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-std=c++98") +set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98") + +set(CMAKE_CXX11_STANDARD__HAS_FULL_SUPPORT ON) +set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++11") +set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++11") + +set(CMAKE_CXX14_STANDARD__HAS_FULL_SUPPORT ON) +set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "-std=c++14") +set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-std=gnu++14") + +if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 17.1.0) + set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std=c++17") + set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++17") + set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-std=c++20") + set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std=gnu++20") +endif() + +__compiler_check_default_language_standard(CXX 17.1.0 17) + +set(CMAKE_CXX_COMPILE_OBJECT + "<CMAKE_CXX_COMPILER> -x c++ <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>") diff --git a/Modules/Compiler/IBMClang.cmake b/Modules/Compiler/IBMClang.cmake new file mode 100644 index 0000000..9ed7658 --- /dev/null +++ b/Modules/Compiler/IBMClang.cmake @@ -0,0 +1,79 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + + +# This module is shared by multiple languages; use include blocker. +if(__COMPILER_IBMClang) + return() +endif() +set(__COMPILER_IBMClang 1) + +include(Compiler/CMakeCommonCompilerMacros) + +set(__pch_header_C "c-header") +set(__pch_header_CXX "c++-header") +set(__pch_header_OBJC "objective-c-header") +set(__pch_header_OBJCXX "objective-c++-header") + +include(Compiler/GNU) + +macro(__compiler_ibmclang lang) + __compiler_gnu(${lang}) + + # Feature flags. + set(CMAKE_${lang}_VERBOSE_FLAG "-v") + set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC") + set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIC") + set(CMAKE_${lang}_RESPONSE_FILE_FLAG "@") + set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "@") + + set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ") + set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY "-fvisibility=") + + set(CMAKE_${lang}_COMPILE_OPTIONS_TARGET "--target=") + set(CMAKE_${lang}_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN "--gcc-toolchain=") + + set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Xlinker" " ") + set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP) + + if(CMAKE_${lang}_COMPILER_TARGET) + list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "--target=${CMAKE_${lang}_COMPILER_TARGET}") + endif() + + set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES) + set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) + + set(_CMAKE_LTO_THIN TRUE) + + if(_CMAKE_LTO_THIN) + set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto=thin") + else() + set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto") + endif() + + set(__ar "${CMAKE_${lang}_COMPILER_AR}") + set(__ranlib "${CMAKE_${lang}_COMPILER_RANLIB}") + + set(CMAKE_${lang}_ARCHIVE_CREATE_IPO + "\"${__ar}\" cr <TARGET> <LINK_FLAGS> <OBJECTS>" + ) + + set(CMAKE_${lang}_ARCHIVE_APPEND_IPO + "\"${__ar}\" r <TARGET> <LINK_FLAGS> <OBJECTS>" + ) + + set(CMAKE_${lang}_ARCHIVE_FINISH_IPO + "\"${__ranlib}\" <TARGET>" + ) + + list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "-dM" "-E" "-c" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp") + + set(CMAKE_PCH_EXTENSION .pch) + + set(CMAKE_PCH_PROLOGUE "#pragma clang system_header") + + set(CMAKE_${lang}_COMPILE_OPTIONS_INSTANTIATE_TEMPLATES_PCH -fpch-instantiate-templates) + + set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH -Xclang -include-pch -Xclang <PCH_FILE> -Xclang -include -Xclang <PCH_HEADER>) + set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH -Xclang -emit-pch -Xclang -include -Xclang <PCH_HEADER> -x ${__pch_header_${lang}}) +endmacro() diff --git a/Modules/Compiler/Intel.cmake b/Modules/Compiler/Intel.cmake index 9a760c8..20989d2 100644 --- a/Modules/Compiler/Intel.cmake +++ b/Modules/Compiler/Intel.cmake @@ -13,6 +13,7 @@ include(Compiler/CMakeCommonCompilerMacros) if(CMAKE_HOST_WIN32) # MSVC-like macro(__compiler_intel lang) + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror-all") endmacro() else() # GNU-like @@ -24,6 +25,7 @@ else() string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -Os") string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O3") string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -g") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror-all") set(CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}") if(CMAKE_${lang}_COMPILER_ARG1) diff --git a/Modules/Compiler/IntelLLVM.cmake b/Modules/Compiler/IntelLLVM.cmake index 14b7ad8..c344f32 100644 --- a/Modules/Compiler/IntelLLVM.cmake +++ b/Modules/Compiler/IntelLLVM.cmake @@ -20,6 +20,7 @@ if(CMAKE_HOST_WIN32) macro(__compiler_intel_llvm lang) if(NOT "x${lang}" STREQUAL "xFortran") set(CMAKE_${lang}_COMPILE_OPTIONS_INVALID_PCH -Winvalid-pch) + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-WX") endif() endmacro() else() @@ -38,6 +39,7 @@ else() set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE") set(CMAKE_${lang}_LINK_OPTIONS_PIE ${CMAKE_${lang}_COMPILE_OPTIONS_PIE} "-pie") set(CMAKE_${lang}_LINK_OPTIONS_NO_PIE "-no-pie") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror") set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC") set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared") diff --git a/Modules/Compiler/LCC-C-DetermineCompiler.cmake b/Modules/Compiler/LCC-C-DetermineCompiler.cmake new file mode 100644 index 0000000..2ce92fe --- /dev/null +++ b/Modules/Compiler/LCC-C-DetermineCompiler.cmake @@ -0,0 +1,19 @@ + +set(_compiler_id_pp_test "defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__))") + +set(_compiler_id_version_compute " +# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(1) +# if defined(__LCC__) +# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__LCC__- 100) +# endif +# if defined(__LCC_MINOR__) +# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__LCC_MINOR__) +# endif +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define @PREFIX@SIMULATE_ID \"GNU\" +# define @PREFIX@SIMULATE_VERSION_MAJOR @MACRO_DEC@(__GNUC__) +# define @PREFIX@SIMULATE_VERSION_MINOR @MACRO_DEC@(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define @PREFIX@SIMULATE_VERSION_PATCH @MACRO_DEC@(__GNUC_PATCHLEVEL__) +# endif +# endif") diff --git a/Modules/Compiler/LCC-C-FeatureTests.cmake b/Modules/Compiler/LCC-C-FeatureTests.cmake new file mode 100644 index 0000000..0ab5265 --- /dev/null +++ b/Modules/Compiler/LCC-C-FeatureTests.cmake @@ -0,0 +1,17 @@ + +set(_cmake_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304") + +# GNU 4.7 correctly sets __STDC_VERSION__ to 201112L, but GNU 4.6 sets it +# to 201000L. As the former is strictly greater than the latter, test only +# for the latter. If in the future CMake learns about a C feature which was +# introduced with GNU 4.7, that should test for the correct version, similar +# to the distinction between __cplusplus and __GXX_EXPERIMENTAL_CXX0X__ tests. +set(GNU46_C11 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201000L") +set(_cmake_feature_test_c_static_assert "${GNU46_C11}") +# Since 3.4 at least: +set(GNU34_C99 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L") +set(_cmake_feature_test_c_restrict "${GNU34_C99}") +set(_cmake_feature_test_c_variadic_macros "${GNU34_C99}") + +set(GNU_C90 "${_cmake_oldestSupported}") +set(_cmake_feature_test_c_function_prototypes "${GNU_C90}") diff --git a/Modules/Compiler/LCC-C.cmake b/Modules/Compiler/LCC-C.cmake new file mode 100644 index 0000000..3dd6e68 --- /dev/null +++ b/Modules/Compiler/LCC-C.cmake @@ -0,0 +1,29 @@ +include(Compiler/LCC) +__compiler_lcc(C) + + +if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) + AND CMAKE_GENERATOR MATCHES "Makefiles|WMake" + AND CMAKE_DEPFILE_FLAGS_C) + # dependencies are computed by the compiler itself + set(CMAKE_C_DEPFILE_FORMAT gcc) + set(CMAKE_C_DEPENDS_USE_COMPILER TRUE) +endif() + +set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c) + +set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90") +set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90") +set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON) +set(CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99") +set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=gnu99") +set(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT ON) +set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c11") +set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11") +set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON) +set(CMAKE_C17_STANDARD_COMPILE_OPTION "-std=c17") +set(CMAKE_C17_EXTENSION_COMPILE_OPTION "-std=gnu17") +set(CMAKE_C23_STANDARD_COMPILE_OPTION "-std=c2x") +set(CMAKE_C23_EXTENSION_COMPILE_OPTION "-std=gnu2x") + +__compiler_check_default_language_standard(C 1.23 90 1.20 11 1.26 17) diff --git a/Modules/Compiler/LCC-CXX-DetermineCompiler.cmake b/Modules/Compiler/LCC-CXX-DetermineCompiler.cmake new file mode 100644 index 0000000..2ce92fe --- /dev/null +++ b/Modules/Compiler/LCC-CXX-DetermineCompiler.cmake @@ -0,0 +1,19 @@ + +set(_compiler_id_pp_test "defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__))") + +set(_compiler_id_version_compute " +# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(1) +# if defined(__LCC__) +# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__LCC__- 100) +# endif +# if defined(__LCC_MINOR__) +# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__LCC_MINOR__) +# endif +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define @PREFIX@SIMULATE_ID \"GNU\" +# define @PREFIX@SIMULATE_VERSION_MAJOR @MACRO_DEC@(__GNUC__) +# define @PREFIX@SIMULATE_VERSION_MINOR @MACRO_DEC@(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define @PREFIX@SIMULATE_VERSION_PATCH @MACRO_DEC@(__GNUC_PATCHLEVEL__) +# endif +# endif") diff --git a/Modules/Compiler/LCC-CXX-FeatureTests.cmake b/Modules/Compiler/LCC-CXX-FeatureTests.cmake new file mode 100644 index 0000000..45c5470 --- /dev/null +++ b/Modules/Compiler/LCC-CXX-FeatureTests.cmake @@ -0,0 +1,109 @@ + +# Reference: http://gcc.gnu.org/projects/cxx0x.html +# http://gcc.gnu.org/projects/cxx1y.html + +set(_cmake_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404") + +set(GNU50_CXX14 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 500 && __cplusplus >= 201402L") +set(_cmake_feature_test_cxx_variable_templates "${GNU50_CXX14}") +set(_cmake_feature_test_cxx_relaxed_constexpr "${GNU50_CXX14}") +set(_cmake_feature_test_cxx_aggregate_default_initializers "${GNU50_CXX14}") + +# GNU 4.9 in c++14 mode sets __cplusplus to 201300L, so don't test for the +# correct value of it below. +# https://patchwork.ozlabs.org/patch/382470/ +set(GNU49_CXX14 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L") +set(_cmake_feature_test_cxx_contextual_conversions "${GNU49_CXX14}") +set(_cmake_feature_test_cxx_attribute_deprecated "${GNU49_CXX14}") +set(_cmake_feature_test_cxx_decltype_auto "${GNU49_CXX14}") +set(_cmake_feature_test_cxx_digit_separators "${GNU49_CXX14}") +set(_cmake_feature_test_cxx_generic_lambdas "${GNU49_CXX14}") +# GNU 4.3 supports binary literals as an extension, but may warn about +# use of extensions prior to GNU 4.9 +# http://stackoverflow.com/questions/16334024/difference-between-gcc-binary-literals-and-c14-ones +set(_cmake_feature_test_cxx_binary_literals "${GNU49_CXX14}") +# The features below are documented as available in GNU 4.8 (by implementing an +# earlier draft of the standard paper), but that version of the compiler +# does not set __cplusplus to a value greater than 201103L until GNU 4.9: +# http://gcc.gnu.org/onlinedocs/gcc-4.8.2/cpp/Standard-Predefined-Macros.html#Standard-Predefined-Macros +# http://gcc.gnu.org/onlinedocs/gcc-4.9.0/cpp/Standard-Predefined-Macros.html#Standard-Predefined-Macros +# So, CMake only reports availability for it with GNU 4.9 or later. +set(_cmake_feature_test_cxx_return_type_deduction "${GNU49_CXX14}") +set(_cmake_feature_test_cxx_lambda_init_captures "${GNU49_CXX14}") + +# Introduced in GCC 4.8.1 +set(GNU481_CXX11 "((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40801) && __cplusplus >= 201103L") +set(_cmake_feature_test_cxx_decltype_incomplete_return_types "${GNU481_CXX11}") +set(_cmake_feature_test_cxx_reference_qualified_functions "${GNU481_CXX11}") +set(GNU48_CXX11 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 408 && __cplusplus >= 201103L") +set(_cmake_feature_test_cxx_alignas "${GNU48_CXX11}") +# The alignof feature works with GNU 4.7 and -std=c++11, but it is documented +# as available with GNU 4.8, so treat that as true. +set(_cmake_feature_test_cxx_alignof "${GNU48_CXX11}") +set(_cmake_feature_test_cxx_attributes "${GNU48_CXX11}") +set(_cmake_feature_test_cxx_inheriting_constructors "${GNU48_CXX11}") +set(_cmake_feature_test_cxx_thread_local "${GNU48_CXX11}") +set(GNU47_CXX11 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L") +set(_cmake_feature_test_cxx_alias_templates "${GNU47_CXX11}") +set(_cmake_feature_test_cxx_delegating_constructors "${GNU47_CXX11}") +set(_cmake_feature_test_cxx_extended_friend_declarations "${GNU47_CXX11}") +set(_cmake_feature_test_cxx_final "${GNU47_CXX11}") +set(_cmake_feature_test_cxx_nonstatic_member_init "${GNU47_CXX11}") +set(_cmake_feature_test_cxx_override "${GNU47_CXX11}") +set(_cmake_feature_test_cxx_user_literals "${GNU47_CXX11}") +# NOTE: C++11 was ratified in September 2011. GNU 4.7 is the first minor +# release following that (March 2012), and the first minor release to +# support -std=c++11. Prior to that, support for C++11 features is technically +# experiemental and possibly incomplete (see for example the note below about +# cxx_variadic_template_template_parameters) +# GNU does not define __cplusplus correctly before version 4.7. +# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=1773 +# __GXX_EXPERIMENTAL_CXX0X__ is defined in prior versions, but may not be +# defined in the future. +set(GNU_CXX0X_DEFINED "(__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__))") +set(GNU46_CXX11 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && ${GNU_CXX0X_DEFINED}") +set(_cmake_feature_test_cxx_constexpr "${GNU46_CXX11}") +set(_cmake_feature_test_cxx_defaulted_move_initializers "${GNU46_CXX11}") +set(_cmake_feature_test_cxx_enum_forward_declarations "${GNU46_CXX11}") +set(_cmake_feature_test_cxx_noexcept "${GNU46_CXX11}") +set(_cmake_feature_test_cxx_nullptr "${GNU46_CXX11}") +set(_cmake_feature_test_cxx_range_for "${GNU46_CXX11}") +set(_cmake_feature_test_cxx_unrestricted_unions "${GNU46_CXX11}") +set(GNU45_CXX11 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 405 && ${GNU_CXX0X_DEFINED}") +set(_cmake_feature_test_cxx_explicit_conversions "${GNU45_CXX11}") +set(_cmake_feature_test_cxx_lambdas "${GNU45_CXX11}") +set(_cmake_feature_test_cxx_local_type_template_args "${GNU45_CXX11}") +set(_cmake_feature_test_cxx_raw_string_literals "${GNU45_CXX11}") +set(GNU44_CXX11 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && ${GNU_CXX0X_DEFINED}") +set(_cmake_feature_test_cxx_auto_type "${GNU44_CXX11}") +set(_cmake_feature_test_cxx_defaulted_functions "${GNU44_CXX11}") +set(_cmake_feature_test_cxx_deleted_functions "${GNU44_CXX11}") +set(_cmake_feature_test_cxx_generalized_initializers "${GNU44_CXX11}") +set(_cmake_feature_test_cxx_inline_namespaces "${GNU44_CXX11}") +set(_cmake_feature_test_cxx_sizeof_member "${GNU44_CXX11}") +set(_cmake_feature_test_cxx_strong_enums "${GNU44_CXX11}") +set(_cmake_feature_test_cxx_trailing_return_types "${GNU44_CXX11}") +set(_cmake_feature_test_cxx_unicode_literals "${GNU44_CXX11}") +set(_cmake_feature_test_cxx_uniform_initialization "${GNU44_CXX11}") +set(_cmake_feature_test_cxx_variadic_templates "${GNU44_CXX11}") +# TODO: If features are ever recorded for GNU 4.3, there should possibly +# be a new feature added like cxx_variadic_template_template_parameters, +# which is implemented by GNU 4.4, but not 4.3. cxx_variadic_templates is +# actually implemented by GNU 4.3, but variadic template template parameters +# 'completes' it, so that is the version we record as having the variadic +# templates capability in CMake. See +# http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2555.pdf +# TODO: Should be supported by GNU 4.3 +set(GNU43_CXX11 "${_cmake_oldestSupported} && ${GNU_CXX0X_DEFINED}") +set(_cmake_feature_test_cxx_decltype "${GNU43_CXX11}") +set(_cmake_feature_test_cxx_default_function_template_args "${GNU43_CXX11}") +set(_cmake_feature_test_cxx_long_long_type "${GNU43_CXX11}") +set(_cmake_feature_test_cxx_right_angle_brackets "${GNU43_CXX11}") +set(_cmake_feature_test_cxx_rvalue_references "${GNU43_CXX11}") +set(_cmake_feature_test_cxx_static_assert "${GNU43_CXX11}") +# TODO: Should be supported since GNU 3.4? +set(_cmake_feature_test_cxx_extern_templates "${_cmake_oldestSupported} && ${GNU_CXX0X_DEFINED}") +# TODO: Should be supported forever? +set(_cmake_feature_test_cxx_func_identifier "${_cmake_oldestSupported} && ${GNU_CXX0X_DEFINED}") +set(_cmake_feature_test_cxx_variadic_macros "${_cmake_oldestSupported} && ${GNU_CXX0X_DEFINED}") +set(_cmake_feature_test_cxx_template_template_parameters "${_cmake_oldestSupported} && __cplusplus") diff --git a/Modules/Compiler/LCC-CXX.cmake b/Modules/Compiler/LCC-CXX.cmake new file mode 100644 index 0000000..b3bdd3c --- /dev/null +++ b/Modules/Compiler/LCC-CXX.cmake @@ -0,0 +1,31 @@ +include(Compiler/LCC) +__compiler_lcc(CXX) + + +if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) + AND CMAKE_GENERATOR MATCHES "Makefiles|WMake" + AND CMAKE_DEPFILE_FLAGS_CXX) + # dependencies are computed by the compiler itself + set(CMAKE_CXX_DEPFILE_FORMAT gcc) + set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE) +endif() + +set(CMAKE_CXX_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c++) + +set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") + +set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-std=c++98") +set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98") +set(CMAKE_CXX98_STANDARD__HAS_FULL_SUPPORT ON) +set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++11") +set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++11") +set(CMAKE_CXX11_STANDARD__HAS_FULL_SUPPORT ON) +set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "-std=c++14") +set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-std=gnu++14") +set(CMAKE_CXX14_STANDARD__HAS_FULL_SUPPORT ON) +set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std=c++17") +set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++17") +set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-std=c++2a") +set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std=gnu++2a") + +__compiler_check_default_language_standard(CXX 1.19 98 1.20 11 1.21 14 1.24 17 1.26 20) diff --git a/Modules/Compiler/LCC-FindBinUtils.cmake b/Modules/Compiler/LCC-FindBinUtils.cmake new file mode 100644 index 0000000..4dcdd53 --- /dev/null +++ b/Modules/Compiler/LCC-FindBinUtils.cmake @@ -0,0 +1,37 @@ +if(NOT DEFINED _CMAKE_PROCESSING_LANGUAGE OR _CMAKE_PROCESSING_LANGUAGE STREQUAL "") + message(FATAL_ERROR "Internal error: _CMAKE_PROCESSING_LANGUAGE is not set") +endif() + +# Ubuntu 16.04: +# * /usr/bin/gcc-ar-5 +# * /usr/bin/gcc-ranlib-5 +string(REGEX MATCH "^([0-9]+)" __version_x + "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION}") + +string(REGEX MATCH "^([0-9]+\\.[0-9]+)" __version_x_y + "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION}") + +# Try to find tools in the same directory as GCC itself +get_filename_component(__gcc_hints "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" DIRECTORY) + +# http://manpages.ubuntu.com/manpages/wily/en/man1/gcc-ar.1.html +find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR NAMES + "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ar-${__version_x_y}" + "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ar-${__version_x}" + "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ar${_CMAKE_COMPILER_SUFFIX}" + HINTS ${__gcc_hints} + NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH + DOC "A wrapper around 'ar' adding the appropriate '--plugin' option for the GCC compiler" +) +mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR) + +# http://manpages.ubuntu.com/manpages/wily/en/man1/gcc-ranlib.1.html +find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB NAMES + "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ranlib-${__version_x_y}" + "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ranlib-${__version_x}" + "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ranlib${_CMAKE_COMPILER_SUFFIX}" + HINTS ${__gcc_hints} + NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH + DOC "A wrapper around 'ranlib' adding the appropriate '--plugin' option for the GCC compiler" +) +mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB) diff --git a/Modules/Compiler/LCC-Fortran.cmake b/Modules/Compiler/LCC-Fortran.cmake new file mode 100644 index 0000000..8091b29 --- /dev/null +++ b/Modules/Compiler/LCC-Fortran.cmake @@ -0,0 +1,26 @@ +include(Compiler/LCC) +__compiler_lcc(Fortran) + +set(CMAKE_Fortran_SUBMODULE_SEP "@") +set(CMAKE_Fortran_SUBMODULE_EXT ".smod") + +set(CMAKE_Fortran_PREPROCESS_SOURCE + "<CMAKE_Fortran_COMPILER> -cpp <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> -o <PREPROCESSED_SOURCE>") + +set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed-form") +set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree-form") + +set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-cpp") +set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nocpp") + +set(CMAKE_Fortran_POSTPROCESS_FLAG "-fpreprocessed") + +# No -DNDEBUG for Fortran. +string(APPEND CMAKE_Fortran_FLAGS_MINSIZEREL_INIT " -Os") +string(APPEND CMAKE_Fortran_FLAGS_RELEASE_INIT " -O3") + +# No -isystem for Fortran because it will not find .mod files. +unset(CMAKE_INCLUDE_SYSTEM_FLAG_Fortran) + +# Fortran-specific feature flags. +set(CMAKE_Fortran_MODDIR_FLAG -J) diff --git a/Modules/Compiler/LCC.cmake b/Modules/Compiler/LCC.cmake new file mode 100644 index 0000000..bdee9a6 --- /dev/null +++ b/Modules/Compiler/LCC.cmake @@ -0,0 +1,96 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + + +# This module is shared by multiple languages; use include blocker. +if(__COMPILER_LCC) + return() +endif() +set(__COMPILER_LCC 1) + +include(Compiler/CMakeCommonCompilerMacros) + +set(__pch_header_C "c-header") +set(__pch_header_CXX "c++-header") +set(__pch_header_OBJC "objective-c-header") +set(__pch_header_OBJCXX "objective-c++-header") + +macro(__compiler_lcc lang) + # Feature flags. + set(CMAKE_${lang}_VERBOSE_FLAG "-v") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror") + set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC") + set (_CMAKE_${lang}_PIE_MAY_BE_SUPPORTED_BY_LINKER NO) + set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE") + # Support of PIE at link stage depends on various elements : platform, compiler, linker + # so to activate it, module CheckPIESupported must be used. + set (_CMAKE_${lang}_PIE_MAY_BE_SUPPORTED_BY_LINKER YES) + set(CMAKE_${lang}_LINK_OPTIONS_PIE ${CMAKE_${lang}_COMPILE_OPTIONS_PIE} "-pie") + set(CMAKE_${lang}_LINK_OPTIONS_NO_PIE "-no-pie") + set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY "-fvisibility=") + set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC") + set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared") + set(CMAKE_${lang}_COMPILE_OPTIONS_SYSROOT "--sysroot=") + + set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,") + set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",") + + # Older versions of gcc (< 4.5) contain a bug causing them to report a missing + # header file as a warning if depfiles are enabled, causing check_header_file + # tests to always succeed. Work around this by disabling dependency tracking + # in try_compile mode. + get_property(_IN_TC GLOBAL PROPERTY IN_TRY_COMPILE) + if(CMAKE_${lang}_COMPILER_ID STREQUAL "LCC" AND _IN_TC AND NOT CMAKE_FORCE_DEPFILES) + else() + # distcc does not transform -o to -MT when invoking the preprocessor + # internally, as it ought to. Work around this bug by setting -MT here + # even though it isn't strictly necessary. + set(CMAKE_DEPFILE_FLAGS_${lang} "-MD -MT <DEP_TARGET> -MF <DEP_FILE>") + endif() + + # Initial configuration flags. + string(APPEND CMAKE_${lang}_FLAGS_INIT " ") + string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -g") + string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -Os -DNDEBUG") + string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O3 -DNDEBUG") + string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG") + set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>") + set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>") + set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ") + set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES) + set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO) + set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) + set(__lto_flags -flto) + list(APPEND __lto_flags -fno-fat-lto-objects) + set(CMAKE_${lang}_COMPILE_OPTIONS_IPO ${__lto_flags}) + + set(CMAKE_${lang}_ARCHIVE_CREATE_IPO + "\"${CMAKE_${lang}_COMPILER_AR}\" cr <TARGET> <LINK_FLAGS> <OBJECTS>" + ) + + set(CMAKE_${lang}_ARCHIVE_APPEND_IPO + "\"${CMAKE_${lang}_COMPILER_AR}\" r <TARGET> <LINK_FLAGS> <OBJECTS>" + ) + + set(CMAKE_${lang}_ARCHIVE_FINISH_IPO + "\"${CMAKE_${lang}_COMPILER_RANLIB}\" <TARGET>" + ) + + set(CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}") + if(CMAKE_${lang}_COMPILER_ARG1) + separate_arguments(_COMPILER_ARGS NATIVE_COMMAND "${CMAKE_${lang}_COMPILER_ARG1}") + list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND ${_COMPILER_ARGS}) + unset(_COMPILER_ARGS) + endif() + list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "-dM" "-E" "-c" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp") + + if(NOT "x${lang}" STREQUAL "xFortran") + set(CMAKE_PCH_EXTENSION .gch) + if (NOT CMAKE_GENERATOR MATCHES "Xcode") + set(CMAKE_PCH_PROLOGUE "#pragma GCC system_header") + endif() + set(CMAKE_${lang}_COMPILE_OPTIONS_INVALID_PCH -Winvalid-pch) + set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH -include <PCH_HEADER>) + set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH -x ${__pch_header_${lang}} -include <PCH_HEADER>) + endif() +endmacro() diff --git a/Modules/Compiler/LLVMFlang-Fortran.cmake b/Modules/Compiler/LLVMFlang-Fortran.cmake new file mode 100644 index 0000000..7e9ba5e --- /dev/null +++ b/Modules/Compiler/LLVMFlang-Fortran.cmake @@ -0,0 +1,13 @@ +set(CMAKE_Fortran_SUBMODULE_SEP "-") +set(CMAKE_Fortran_SUBMODULE_EXT ".mod") + +set(CMAKE_Fortran_PREPROCESS_SOURCE + "<CMAKE_Fortran_COMPILER> -cpp <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>") + +set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed-form") +set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree-form") + +set(CMAKE_Fortran_MODDIR_FLAG "-module-dir") + +set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-cpp") +set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nocpp") diff --git a/Modules/Compiler/MSVC-C.cmake b/Modules/Compiler/MSVC-C.cmake index df3691c..6bf6b4e 100644 --- a/Modules/Compiler/MSVC-C.cmake +++ b/Modules/Compiler/MSVC-C.cmake @@ -1,6 +1,9 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. +include(Compiler/MSVC) +__compiler_msvc(C) + include(Compiler/CMakeCommonCompilerMacros) if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.27) @@ -67,16 +70,3 @@ else() endif() set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TC) -set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl") -set(CMAKE_C_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") - -# /JMC "Just My Code" is only supported by MSVC 19.05 onward. -if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05) - set(CMAKE_C_COMPILE_OPTIONS_JMC "-JMC") -endif() - -# The `/external:I` flag was made non-experimental in 19.29.30036.3. -if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29.30036.3) - set(CMAKE_INCLUDE_SYSTEM_FLAG_C "-external:I") - set(_CMAKE_INCLUDE_SYSTEM_FLAG_C_WARNING "-external:W0 ") -endif () diff --git a/Modules/Compiler/MSVC-CXX.cmake b/Modules/Compiler/MSVC-CXX.cmake index 17cbc3c..75165fd 100644 --- a/Modules/Compiler/MSVC-CXX.cmake +++ b/Modules/Compiler/MSVC-CXX.cmake @@ -1,10 +1,10 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. -include(Compiler/CMakeCommonCompilerMacros) +include(Compiler/MSVC) +__compiler_msvc(CXX) -set(CMAKE_CXX_CLANG_TIDY_DRIVER_MODE "cl") -set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") +include(Compiler/CMakeCommonCompilerMacros) if ((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.0.24215.1 AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10) OR @@ -76,14 +76,3 @@ elseif (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0) _record_compiler_features(CXX "" CMAKE_CXX_COMPILE_FEATURES) endmacro() endif() - -# /JMC "Just My Code" is only supported by MSVC 19.05 onward. -if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05) - set(CMAKE_CXX_COMPILE_OPTIONS_JMC "-JMC") -endif() - -# The `/external:I` flag was made non-experimental in 19.29.30036.3. -if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29.30036.3) - set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "-external:I") - set(_CMAKE_INCLUDE_SYSTEM_FLAG_CXX_WARNING "-external:W0 ") -endif () diff --git a/Modules/Compiler/MSVC.cmake b/Modules/Compiler/MSVC.cmake new file mode 100644 index 0000000..154b657 --- /dev/null +++ b/Modules/Compiler/MSVC.cmake @@ -0,0 +1,25 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# This module is shared by multiple languages; use include blocker. +if(__COMPILER_MSVC) + return() +endif() +set(__COMPILER_MSVC 1) + +macro(__compiler_msvc lang) + set(CMAKE_${lang}_CLANG_TIDY_DRIVER_MODE "cl") + set(CMAKE_${lang}_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-WX") + + # /JMC "Just My Code" is only supported by MSVC 19.05 onward. + if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05) + set(CMAKE_${lang}_COMPILE_OPTIONS_JMC "-JMC") + endif() + + # The `/external:I` flag was made non-experimental in 19.29.30036.3. + if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29.30036.3) + set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-external:I") + set(_CMAKE_INCLUDE_SYSTEM_FLAG_${lang}_WARNING "-external:W0 ") + endif () +endmacro() diff --git a/Modules/Compiler/NVHPC.cmake b/Modules/Compiler/NVHPC.cmake index b51bb43..957dacd 100644 --- a/Modules/Compiler/NVHPC.cmake +++ b/Modules/Compiler/NVHPC.cmake @@ -13,4 +13,5 @@ include(Compiler/PGI) macro(__compiler_nvhpc lang) # Logic specific to NVHPC. set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror all-warnings") endmacro() diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake index c2fe42d..2e3ae2c 100644 --- a/Modules/Compiler/NVIDIA-CUDA.cmake +++ b/Modules/Compiler/NVIDIA-CUDA.cmake @@ -5,8 +5,9 @@ set(CMAKE_CUDA_VERBOSE_FLAG "-v") set(CMAKE_CUDA_VERBOSE_COMPILE_FLAG "-Xcompiler=-v") set(_CMAKE_COMPILE_AS_CUDA_FLAG "-x cu") +set(_CMAKE_CUDA_WHOLE_FLAG "-c") +set(_CMAKE_CUDA_RDC_FLAG "-rdc=true") set(_CMAKE_CUDA_PTX_FLAG "-ptx") -set(_CMAKE_CUDA_DEVICE_CODE "-dc") if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 10.2.89) # The -forward-unknown-to-host-compiler flag was only @@ -29,6 +30,11 @@ if(CMAKE_CUDA_HOST_COMPILER AND NOT CMAKE_GENERATOR MATCHES "Visual Studio") endif() if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 10.2.89) + # Starting in 10.2, nvcc supported treating all warnings as errors + set(CMAKE_CUDA_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror all-warnings") +endif() + +if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 10.2.89) # The -MD flag was only added to nvcc in 10.2 so # before that we had to invoke the compiler twice # to get header dependency information diff --git a/Modules/Compiler/SunPro-ASM.cmake b/Modules/Compiler/SunPro-ASM.cmake index 0d67400..fc0f2fa 100644 --- a/Modules/Compiler/SunPro-ASM.cmake +++ b/Modules/Compiler/SunPro-ASM.cmake @@ -1,3 +1,6 @@ +include(Compiler/SunPro) +__compiler_sunpro(ASM) + set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s ) set(CMAKE_ASM_VERBOSE_FLAG "-#") diff --git a/Modules/Compiler/SunPro-C.cmake b/Modules/Compiler/SunPro-C.cmake index c98656f..b06719d 100644 --- a/Modules/Compiler/SunPro-C.cmake +++ b/Modules/Compiler/SunPro-C.cmake @@ -2,6 +2,7 @@ # file Copyright.txt or https://cmake.org/licensing for details. include(Compiler/SunPro) +__compiler_sunpro(C) set(CMAKE_C_VERBOSE_FLAG "-#") @@ -33,8 +34,13 @@ foreach(type SHARED_LIBRARY SHARED_MODULE EXE) set(CMAKE_${type}_LINK_DYNAMIC_C_FLAGS "-Bdynamic") endforeach() -set(CMAKE_C_LINKER_WRAPPER_FLAG "-Qoption" "ld" " ") -set(CMAKE_C_LINKER_WRAPPER_FLAG_SEP ",") +if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "5.12") + set(CMAKE_C_LINKER_WRAPPER_FLAG "-Qoption" "ld" " ") + set(CMAKE_C_LINKER_WRAPPER_FLAG_SEP ",") +else() + set(CMAKE_C_LINKER_WRAPPER_FLAG "-Wl,") + set(CMAKE_C_LINKER_WRAPPER_FLAG_SEP ",") +endif() if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 5.13) set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c89") diff --git a/Modules/Compiler/SunPro-CXX.cmake b/Modules/Compiler/SunPro-CXX.cmake index aa8a9c5..f835f2d 100644 --- a/Modules/Compiler/SunPro-CXX.cmake +++ b/Modules/Compiler/SunPro-CXX.cmake @@ -2,6 +2,7 @@ # file Copyright.txt or https://cmake.org/licensing for details. include(Compiler/SunPro) +__compiler_sunpro(CXX) set(CMAKE_CXX_VERBOSE_FLAG "-v") diff --git a/Modules/Compiler/SunPro-Fortran.cmake b/Modules/Compiler/SunPro-Fortran.cmake index 0ba5015..d336980 100644 --- a/Modules/Compiler/SunPro-Fortran.cmake +++ b/Modules/Compiler/SunPro-Fortran.cmake @@ -1,3 +1,6 @@ +include(Compiler/SunPro) +__compiler_sunpro(Fortran) + set(CMAKE_Fortran_VERBOSE_FLAG "-v") set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-fixed") set(CMAKE_Fortran_FORMAT_FREE_FLAG "-free") diff --git a/Modules/Compiler/SunPro.cmake b/Modules/Compiler/SunPro.cmake index 52da39a..331cdfc 100644 --- a/Modules/Compiler/SunPro.cmake +++ b/Modules/Compiler/SunPro.cmake @@ -8,3 +8,7 @@ endif() set(__COMPILER_SUNPRO 1) include(Compiler/CMakeCommonCompilerMacros) + +macro(__compiler_sunpro lang) + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-errwarn=%all") +endmacro() diff --git a/Modules/Compiler/XL.cmake b/Modules/Compiler/XL.cmake index 8b9d4a9..844fcfd 100644 --- a/Modules/Compiler/XL.cmake +++ b/Modules/Compiler/XL.cmake @@ -15,6 +15,7 @@ macro(__compiler_xl lang) set(CMAKE_${lang}_VERBOSE_FLAG "-V") set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-qpic") set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-qpic") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-qhalt=i") set(CMAKE_${lang}_RESPONSE_FILE_FLAG "-qoptfile=") set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "-qoptfile=") diff --git a/Modules/Compiler/XLClang.cmake b/Modules/Compiler/XLClang.cmake index cdf0fdc..8c3e5e9 100644 --- a/Modules/Compiler/XLClang.cmake +++ b/Modules/Compiler/XLClang.cmake @@ -17,6 +17,7 @@ macro(__compiler_xlclang lang) set(CMAKE_${lang}_VERBOSE_FLAG "-V") set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC") set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIC") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror") set(CMAKE_${lang}_RESPONSE_FILE_FLAG "@") set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "@") endmacro() diff --git a/Modules/CompilerId/Xcode-3.pbxproj.in b/Modules/CompilerId/Xcode-3.pbxproj.in index 43e8cc8..543c6a9 100644 --- a/Modules/CompilerId/Xcode-3.pbxproj.in +++ b/Modules/CompilerId/Xcode-3.pbxproj.in @@ -83,6 +83,7 @@ buildSettings = { CODE_SIGNING_REQUIRED = NO; CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; + GENERATE_INFOPLIST_FILE = YES; SYMROOT = .; @id_archs@ @id_arch_active@ diff --git a/Modules/DartConfiguration.tcl.in b/Modules/DartConfiguration.tcl.in index e5b1e5d..afa36f7 100644 --- a/Modules/DartConfiguration.tcl.in +++ b/Modules/DartConfiguration.tcl.in @@ -21,6 +21,7 @@ LabelsForSubprojects: @CTEST_LABELS_FOR_SUBPROJECTS@ # Submission information SubmitURL: @SUBMIT_URL@ +SubmitInactivityTimeout: @CTEST_SUBMIT_INACTIVITY_TIMEOUT@ # Dashboard start time NightlyStartTime: @NIGHTLY_START_TIME@ diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 4004ea4..c7948cd 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -170,6 +170,19 @@ External Project Definition the default name is generally suitable and is not normally used outside of code internal to the ``ExternalProject`` module. + ``DOWNLOAD_EXTRACT_TIMESTAMP <bool>`` + .. versionadded:: 3.24 + + When specified with a true value, the timestamps of the extracted + files will match those in the archive. When false, the timestamps of + the extracted files will reflect the time at which the extraction + was performed. If the download URL changes, timestamps based off + those in the archive can result in dependent targets not being rebuilt + when they potentially should have been. Therefore, unless the file + timestamps are significant to the project in some way, use a false + value for this option. If ``DOWNLOAD_EXTRACT_TIMESTAMP`` is not given, + the default is false. See policy :policy:`CMP0135`. + ``DOWNLOAD_NO_EXTRACT <bool>`` .. versionadded:: 3.6 @@ -231,9 +244,9 @@ External Project Definition .. versionadded:: 3.11 Specify whether the ``.netrc`` file is to be used for operation. - If this option is not specified, the value of the :variable:`CMAKE_NETRC` - variable will be used instead (see :command:`file(DOWNLOAD)`) - Valid levels are: + If this option is not specified, the value of the + :variable:`CMAKE_NETRC` variable will be used instead + (see :command:`file(DOWNLOAD)`). Valid levels are: ``IGNORED`` The ``.netrc`` file is ignored. @@ -353,6 +366,10 @@ External Project Definition When ``GIT_REMOTE_UPDATE_STRATEGY`` is not present, this is the default strategy unless the default has been overridden with ``CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY`` (see below). + Note that if the branch specified in ``GIT_TAG`` is different to + the upstream branch currently being tracked, it is not safe to + perform a rebase. In that situation, ``REBASE`` will silently be + treated as ``CHECKOUT`` instead. ``REBASE_CHECKOUT`` Same as ``REBASE`` except if the rebase fails, an annotated tag will @@ -369,8 +386,9 @@ External Project Definition override the default strategy. This variable should not be set by a project, it is intended for the user to set. It is primarily intended for use in continuous integration scripts to ensure that when history - is rewritten on a remote branch, the build doesn't end up with unintended - changes or failed builds resulting from conflicts during rebase operations. + is rewritten on a remote branch, the build doesn't end up with + unintended changes or failed builds resulting from conflicts during + rebase operations. *Subversion* ``SVN_REPOSITORY <url>`` @@ -407,7 +425,7 @@ External Project Definition ``CVS_TAG <tag>`` Tag to checkout from the CVS repository. - **Update/Patch Step Options:** + **Update Step Options:** Whenever CMake is re-run, by default the external project's sources will be updated if the download method supports updates (e.g. a git repository would be checked if the ``GIT_TAG`` does not refer to a specific commit). @@ -442,6 +460,7 @@ External Project Definition This may cause a step target to be created automatically for the ``download`` step. See policy :policy:`CMP0114`. + **Patch Step Options:** ``PATCH_COMMAND <cmd>...`` Specifies a custom command to patch the sources after an update. By default, no patch command is defined. Note that it can be quite difficult @@ -509,7 +528,8 @@ External Project Definition :manual:`CMake Options <cmake(1)>`). .. versionadded:: 3.3 - Arguments may use :manual:`generator expressions <cmake-generator-expressions(7)>`. + Arguments may use + :manual:`generator expressions <cmake-generator-expressions(7)>`. ``CMAKE_CACHE_ARGS <arg>...`` This is an alternate way of specifying cache variables where command line @@ -520,7 +540,8 @@ External Project Definition using the :manual:`cmake -C <cmake(1)>` command line option. .. versionadded:: 3.3 - Arguments may use :manual:`generator expressions <cmake-generator-expressions(7)>`. + Arguments may use + :manual:`generator expressions <cmake-generator-expressions(7)>`. ``CMAKE_CACHE_DEFAULT_ARGS <arg>...`` .. versionadded:: 3.2 @@ -533,7 +554,7 @@ External Project Definition build directory or re-uses previous build contents. .. versionadded:: 3.15 - If the CMake generator is the ``Green Hills MULTI`` and not overridden then + If the CMake generator is the ``Green Hills MULTI`` and not overridden, the original project's settings for the GHS toolset and target system customization cache variables are propagated into the external project. @@ -750,6 +771,11 @@ External Project Definition ``USES_TERMINAL_UPDATE <bool>`` Give the update step access to the terminal. + ``USES_TERMINAL_PATCH <bool>`` + .. versionadded:: 3.23 + + Give the patch step access to the terminal. + ``USES_TERMINAL_CONFIGURE <bool>`` Give the configure step access to the terminal. @@ -801,11 +827,11 @@ External Project Definition **Miscellaneous Options:** ``LIST_SEPARATOR <sep>`` - For any of the various ``..._COMMAND`` options, replace ``;`` with - ``<sep>`` in the specified command lines. This can be useful where list - variables may be given in commands where they should end up as - space-separated arguments (``<sep>`` would be a single space character - string in this case). + For any of the various ``..._COMMAND`` options, and ``CMAKE_ARGS``, + replace ``;`` with ``<sep>`` in the specified command lines. + This can be useful where list variables may be given in commands where + they should end up as space-separated arguments (``<sep>`` would be a + single space character string in this case). ``COMMAND <cmd>...`` Any of the other ``..._COMMAND`` options can have additional commands @@ -994,9 +1020,9 @@ control needed to implement such step-level capabilities. .. versionadded:: 3.19 If :policy:`CMP0114` is set to ``NEW``, step targets are fully responsible - for holding the custom commands implementing their steps. The primary target - created by ``ExternalProject_Add`` depends on the step targets, and the - step targets depend on each other. The target-level dependencies match + for holding the custom commands implementing their steps. The primary + target created by ``ExternalProject_Add`` depends on the step targets, and + the step targets depend on each other. The target-level dependencies match the file-level dependencies used by the custom commands for each step. The targets for steps created with :command:`ExternalProject_Add_Step`'s ``INDEPENDENT`` option do not depend on the external targets specified @@ -1008,16 +1034,16 @@ control needed to implement such step-level capabilities. * A deprecated ``NO_DEPENDS`` option may be specified immediately after the ``<name>`` and before the first step. - If the ``NO_DEPENDS`` option is specified, the step target will not depend on - the dependencies of the external project (i.e. on any dependencies of the + If the ``NO_DEPENDS`` option is specified, the step target will not depend + on the dependencies of the external project (i.e. on any dependencies of the ``<name>`` custom target created by :command:`ExternalProject_Add`). This is - usually safe for the ``download``, ``update`` and ``patch`` steps, since they - do not typically require that the dependencies are updated and built. Using - ``NO_DEPENDS`` for any of the other pre-defined steps, however, may break - parallel builds. Only use ``NO_DEPENDS`` where it is certain that the named - steps genuinely do not have dependencies. For custom steps, consider whether - or not the custom commands require the dependencies to be configured, built - and installed. + usually safe for the ``download``, ``update`` and ``patch`` steps, since + they do not typically require that the dependencies are updated and built. + Using ``NO_DEPENDS`` for any of the other pre-defined steps, however, may + break parallel builds. Only use ``NO_DEPENDS`` where it is certain that the + named steps genuinely do not have dependencies. For custom steps, consider + whether or not the custom commands require the dependencies to be + configured, built and installed. * The ``INDEPENDENT_STEP_TARGETS`` option for :command:`ExternalProject_Add`, or the ``EP_INDEPENDENT_STEP_TARGETS`` directory property, tells the @@ -1167,7 +1193,13 @@ macro(_ep_get_hash_regex out_var) set(${out_var} "^(${${out_var}})=([0-9A-Fa-f]+)$") endmacro() -function(_ep_parse_arguments f keywords name ns args) +function(_ep_parse_arguments + f + keywords + name + ns + args +) # Transfer the arguments to this function into target properties for the # new custom target we just added so that we can set up all the build steps # correctly based on target properties. @@ -1183,7 +1215,8 @@ function(_ep_parse_arguments f keywords name ns args) set(is_value 1) if(arg MATCHES "^[A-Z][A-Z0-9_][A-Z0-9_]+$" AND - NOT (("x${arg}x" STREQUAL "x${key}x") AND ("x${key}x" STREQUAL "xCOMMANDx")) AND + NOT (("x${arg}x" STREQUAL "x${key}x") AND + ("x${key}x" STREQUAL "xCOMMANDx")) AND NOT arg MATCHES "^(TRUE|FALSE)$") if(arg IN_LIST keywords) set(is_value 0) @@ -1206,7 +1239,9 @@ function(_ep_parse_arguments f keywords name ns args) endif() else() # Missing Keyword - message(AUTHOR_WARNING "value '${arg}' with no previous keyword in ${f}") + message(AUTHOR_WARNING + "value '${arg}' with no previous keyword in ${f}" + ) endif() else() set(key "${arg}") @@ -1215,46 +1250,32 @@ function(_ep_parse_arguments f keywords name ns args) endfunction() -define_property(DIRECTORY PROPERTY "EP_BASE" INHERITED - BRIEF_DOCS "Base directory for External Project storage." - FULL_DOCS - "See documentation of the ExternalProject_Add() function in the " - "ExternalProject module." - ) - -define_property(DIRECTORY PROPERTY "EP_PREFIX" INHERITED - BRIEF_DOCS "Top prefix for External Project storage." - FULL_DOCS - "See documentation of the ExternalProject_Add() function in the " - "ExternalProject module." - ) - -define_property(DIRECTORY PROPERTY "EP_STEP_TARGETS" INHERITED - BRIEF_DOCS - "List of ExternalProject steps that automatically get corresponding targets" - FULL_DOCS - "These targets will be dependent on the main target dependencies. " - "See documentation of the ExternalProject_Add_StepTargets() function in the " - "ExternalProject module." - ) - -define_property(DIRECTORY PROPERTY "EP_INDEPENDENT_STEP_TARGETS" INHERITED - BRIEF_DOCS - "List of ExternalProject steps that automatically get corresponding targets" - FULL_DOCS - "These targets will not be dependent on the main target dependencies. " - "See documentation of the ExternalProject_Add_StepTargets() function in the " - "ExternalProject module." - ) - -define_property(DIRECTORY PROPERTY "EP_UPDATE_DISCONNECTED" INHERITED - BRIEF_DOCS "Never update automatically from the remote repo." - FULL_DOCS - "See documentation of the ExternalProject_Add() function in the " - "ExternalProject module." - ) +define_property(DIRECTORY PROPERTY "EP_BASE" INHERITED) +define_property(DIRECTORY PROPERTY "EP_PREFIX" INHERITED) +define_property(DIRECTORY PROPERTY "EP_STEP_TARGETS" INHERITED) +define_property(DIRECTORY PROPERTY "EP_INDEPENDENT_STEP_TARGETS" INHERITED) +define_property(DIRECTORY PROPERTY "EP_UPDATE_DISCONNECTED" INHERITED) + +function(_ep_write_gitclone_script + script_filename + source_dir + git_EXECUTABLE + git_repository + git_tag + git_remote_name + init_submodules + git_submodules_recurse + git_submodules + git_shallow + git_progress + git_config + src_name + work_dir + gitclone_infofile + gitclone_stampfile + tls_verify +) -function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git_repository git_tag git_remote_name init_submodules git_submodules_recurse git_submodules git_shallow git_progress git_config src_name work_dir gitclone_infofile gitclone_stampfile tls_verify) if(NOT GIT_VERSION_STRING VERSION_LESS 1.8.5) # Use `git checkout <tree-ish> --` to avoid ambiguity with a local path. set(git_checkout_explicit-- "--") @@ -1268,7 +1289,8 @@ function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git message(FATAL_ERROR "Tag for git checkout should not be empty.") endif() - if(GIT_VERSION_STRING VERSION_LESS 2.20 OR 2.21 VERSION_LESS_EQUAL GIT_VERSION_STRING) + if(GIT_VERSION_STRING VERSION_LESS 2.20 OR + 2.21 VERSION_LESS_EQUAL GIT_VERSION_STRING) set(git_clone_options "--no-checkout") else() set(git_clone_options) @@ -1296,138 +1318,55 @@ function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git # disable cert checking if explicitly told not to do it if(NOT "x${tls_verify}" STREQUAL "x" AND NOT tls_verify) set(git_options - -c http.sslVerify=false) + -c http.sslVerify=false + ) endif() string (REPLACE ";" " " git_options "${git_options}") - file(WRITE ${script_filename} -" -if(NOT \"${gitclone_infofile}\" IS_NEWER_THAN \"${gitclone_stampfile}\") - message(STATUS \"Avoiding repeated git clone, stamp file is up to date: '${gitclone_stampfile}'\") - return() -endif() - -execute_process( - COMMAND \${CMAKE_COMMAND} -E rm -rf \"${source_dir}\" - RESULT_VARIABLE error_code - ) -if(error_code) - message(FATAL_ERROR \"Failed to remove directory: '${source_dir}'\") -endif() - -# try the clone 3 times in case there is an odd git clone issue -set(error_code 1) -set(number_of_tries 0) -while(error_code AND number_of_tries LESS 3) - execute_process( - COMMAND \"${git_EXECUTABLE}\" ${git_options} clone ${git_clone_options} \"${git_repository}\" \"${src_name}\" - WORKING_DIRECTORY \"${work_dir}\" - RESULT_VARIABLE error_code - ) - math(EXPR number_of_tries \"\${number_of_tries} + 1\") -endwhile() -if(number_of_tries GREATER 1) - message(STATUS \"Had to git clone more than once: - \${number_of_tries} times.\") -endif() -if(error_code) - message(FATAL_ERROR \"Failed to clone repository: '${git_repository}'\") -endif() - -execute_process( - COMMAND \"${git_EXECUTABLE}\" ${git_options} checkout ${git_tag} ${git_checkout_explicit--} - WORKING_DIRECTORY \"${work_dir}/${src_name}\" - RESULT_VARIABLE error_code - ) -if(error_code) - message(FATAL_ERROR \"Failed to checkout tag: '${git_tag}'\") -endif() - -set(init_submodules ${init_submodules}) -if(init_submodules) - execute_process( - COMMAND \"${git_EXECUTABLE}\" ${git_options} submodule update ${git_submodules_recurse} --init ${git_submodules} - WORKING_DIRECTORY \"${work_dir}/${src_name}\" - RESULT_VARIABLE error_code - ) -endif() -if(error_code) - message(FATAL_ERROR \"Failed to update submodules in: '${work_dir}/${src_name}'\") -endif() - -# Complete success, update the script-last-run stamp file: -# -execute_process( - COMMAND \${CMAKE_COMMAND} -E copy - \"${gitclone_infofile}\" - \"${gitclone_stampfile}\" - RESULT_VARIABLE error_code + configure_file( + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/gitclone.cmake.in + ${script_filename} + @ONLY ) -if(error_code) - message(FATAL_ERROR \"Failed to copy script-last-run stamp file: '${gitclone_stampfile}'\") -endif() +endfunction() -" +function(_ep_write_hgclone_script + script_filename + source_dir + hg_EXECUTABLE + hg_repository + hg_tag + src_name + work_dir + hgclone_infofile + hgclone_stampfile ) -endfunction() - -function(_ep_write_hgclone_script script_filename source_dir hg_EXECUTABLE hg_repository hg_tag src_name work_dir hgclone_infofile hgclone_stampfile) if("${hg_tag}" STREQUAL "") message(FATAL_ERROR "Tag for hg checkout should not be empty.") endif() - file(WRITE ${script_filename} -" -if(NOT \"${hgclone_infofile}\" IS_NEWER_THAN \"${hgclone_stampfile}\") - message(STATUS \"Avoiding repeated hg clone, stamp file is up to date: '${hgclone_stampfile}'\") - return() -endif() - -execute_process( - COMMAND \${CMAKE_COMMAND} -E rm -rf \"${source_dir}\" - RESULT_VARIABLE error_code - ) -if(error_code) - message(FATAL_ERROR \"Failed to remove directory: '${source_dir}'\") -endif() -execute_process( - COMMAND \"${hg_EXECUTABLE}\" clone -U \"${hg_repository}\" \"${src_name}\" - WORKING_DIRECTORY \"${work_dir}\" - RESULT_VARIABLE error_code - ) -if(error_code) - message(FATAL_ERROR \"Failed to clone repository: '${hg_repository}'\") -endif() - -execute_process( - COMMAND \"${hg_EXECUTABLE}\" update ${hg_tag} - WORKING_DIRECTORY \"${work_dir}/${src_name}\" - RESULT_VARIABLE error_code + configure_file( + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/hgclone.cmake.in + ${script_filename} + @ONLY ) -if(error_code) - message(FATAL_ERROR \"Failed to checkout tag: '${hg_tag}'\") -endif() +endfunction() -# Complete success, update the script-last-run stamp file: -# -execute_process( - COMMAND \${CMAKE_COMMAND} -E copy - \"${hgclone_infofile}\" - \"${hgclone_stampfile}\" - RESULT_VARIABLE error_code - ) -if(error_code) - message(FATAL_ERROR \"Failed to copy script-last-run stamp file: '${hgclone_stampfile}'\") -endif() -" +function(_ep_write_gitupdate_script + script_filename + git_EXECUTABLE + git_tag + git_remote_name + init_submodules + git_submodules_recurse + git_submodules + git_repository + work_dir + git_update_strategy ) -endfunction() - - -function(_ep_write_gitupdate_script script_filename git_EXECUTABLE git_tag git_remote_name init_submodules git_submodules_recurse git_submodules git_repository work_dir git_update_strategy) if("${git_tag}" STREQUAL "") message(FATAL_ERROR "Tag for git checkout should not be empty.") endif() @@ -1441,13 +1380,27 @@ function(_ep_write_gitupdate_script script_filename git_EXECUTABLE git_tag git_r endif() configure_file( - "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject-gitupdate.cmake.in" + "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/gitupdate.cmake.in" "${script_filename}" @ONLY ) endfunction() -function(_ep_write_downloadfile_script script_filename REMOTE LOCAL timeout inactivity_timeout no_progress hash tls_verify tls_cainfo userpwd http_headers netrc netrc_file) +function(_ep_write_downloadfile_script + script_filename + REMOTE + LOCAL + timeout + inactivity_timeout + no_progress + hash + tls_verify + tls_cainfo + userpwd + http_headers + netrc + netrc_file +) if(timeout) set(TIMEOUT_ARGS TIMEOUT ${timeout}) set(TIMEOUT_MSG "${timeout} seconds") @@ -1463,7 +1416,6 @@ function(_ep_write_downloadfile_script script_filename REMOTE LOCAL timeout inac set(INACTIVITY_TIMEOUT_MSG "none") endif() - if(no_progress) set(SHOW_PROGRESS "") else() @@ -1531,9 +1483,8 @@ function(_ep_write_downloadfile_script script_filename REMOTE LOCAL timeout inac set(HTTP_HEADERS_ARGS "") if(NOT http_headers STREQUAL "") foreach(header ${http_headers}) - set( - HTTP_HEADERS_ARGS - "HTTPHEADER \"${header}\"\n ${HTTP_HEADERS_ARGS}" + string(PREPEND HTTP_HEADERS_ARGS + "HTTPHEADER \"${header}\"\n " ) endforeach() endif() @@ -1551,13 +1502,17 @@ function(_ep_write_downloadfile_script script_filename REMOTE LOCAL timeout inac # * USERPWD_ARGS # * HTTP_HEADERS_ARGS configure_file( - "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject-download.cmake.in" - "${script_filename}" - @ONLY + "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/download.cmake.in" + "${script_filename}" + @ONLY ) endfunction() -function(_ep_write_verifyfile_script script_filename LOCAL hash) +function(_ep_write_verifyfile_script + script_filename + LOCAL + hash +) _ep_get_hash_regex(_ep_hash_regex) if("${hash}" MATCHES "${_ep_hash_regex}") set(ALGO "${CMAKE_MATCH_1}") @@ -1572,17 +1527,23 @@ function(_ep_write_verifyfile_script script_filename LOCAL hash) # * EXPECT_VALUE # * LOCAL configure_file( - "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject-verify.cmake.in" - "${script_filename}" - @ONLY + "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/verify.cmake.in" + "${script_filename}" + @ONLY ) endfunction() -function(_ep_write_extractfile_script script_filename name filename directory) +function(_ep_write_extractfile_script + script_filename + name + filename + directory options +) set(args "") - if(filename MATCHES "(\\.|=)(7z|tar\\.bz2|tar\\.gz|tar\\.xz|tbz2|tgz|txz|zip)$") + if(filename MATCHES + "(\\.|=)(7z|tar\\.bz2|tar\\.gz|tar\\.xz|tbz2|tgz|txz|zip)$") set(args xfz) endif() @@ -1591,72 +1552,17 @@ function(_ep_write_extractfile_script script_filename name filename directory) endif() if(args STREQUAL "") - message(SEND_ERROR "error: do not know how to extract '${filename}' -- known types are .7z, .tar, .tar.bz2, .tar.gz, .tar.xz, .tbz2, .tgz, .txz and .zip") - return() + message(FATAL_ERROR + "Do not know how to extract '${filename}' -- known types are: " + ".7z, .tar, .tar.bz2, .tar.gz, .tar.xz, .tbz2, .tgz, .txz and .zip" + ) endif() - file(WRITE ${script_filename} -"# Make file names absolute: -# -get_filename_component(filename \"${filename}\" ABSOLUTE) -get_filename_component(directory \"${directory}\" ABSOLUTE) - -message(STATUS \"extracting... - src='\${filename}' - dst='\${directory}'\") - -if(NOT EXISTS \"\${filename}\") - message(FATAL_ERROR \"error: file to extract does not exist: '\${filename}'\") -endif() - -# Prepare a space for extracting: -# -set(i 1234) -while(EXISTS \"\${directory}/../ex-${name}\${i}\") - math(EXPR i \"\${i} + 1\") -endwhile() -set(ut_dir \"\${directory}/../ex-${name}\${i}\") -file(MAKE_DIRECTORY \"\${ut_dir}\") - -# Extract it: -# -message(STATUS \"extracting... [tar ${args}]\") -execute_process(COMMAND \${CMAKE_COMMAND} -E tar ${args} \${filename} - WORKING_DIRECTORY \${ut_dir} - RESULT_VARIABLE rv) - -if(NOT rv EQUAL 0) - message(STATUS \"extracting... [error clean up]\") - file(REMOVE_RECURSE \"\${ut_dir}\") - message(FATAL_ERROR \"error: extract of '\${filename}' failed\") -endif() - -# Analyze what came out of the tar file: -# -message(STATUS \"extracting... [analysis]\") -file(GLOB contents \"\${ut_dir}/*\") -list(REMOVE_ITEM contents \"\${ut_dir}/.DS_Store\") -list(LENGTH contents n) -if(NOT n EQUAL 1 OR NOT IS_DIRECTORY \"\${contents}\") - set(contents \"\${ut_dir}\") -endif() - -# Move \"the one\" directory to the final directory: -# -message(STATUS \"extracting... [rename]\") -file(REMOVE_RECURSE \${directory}) -get_filename_component(contents \${contents} ABSOLUTE) -file(RENAME \${contents} \${directory}) - -# Clean up: -# -message(STATUS \"extracting... [clean up]\") -file(REMOVE_RECURSE \"\${ut_dir}\") - -message(STATUS \"extracting... done\") -" -) - + configure_file( + "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/extractfile.cmake.in" + "${script_filename}" + @ONLY + ) endfunction() @@ -1672,6 +1578,7 @@ function(_ep_set_directories name) endif() endif() if(prefix) + file(TO_CMAKE_PATH "${prefix}" prefix) set(tmp_default "${prefix}/tmp") set(download_default "${prefix}/src") set(source_default "${prefix}/src/${name}") @@ -1679,6 +1586,7 @@ function(_ep_set_directories name) set(stamp_default "${prefix}/src/${name}-stamp") set(install_default "${prefix}") else() + file(TO_CMAKE_PATH "${base}" base) set(tmp_default "${base}/tmp/${name}") set(download_default "${base}/Download/${name}") set(source_default "${base}/Source/${name}") @@ -1691,7 +1599,8 @@ function(_ep_set_directories name) get_property(have_binary_dir TARGET ${name} PROPERTY _EP_BINARY_DIR SET) if(have_binary_dir) message(FATAL_ERROR - "External project ${name} has both BINARY_DIR and BUILD_IN_SOURCE!") + "External project ${name} has both BINARY_DIR and BUILD_IN_SOURCE!" + ) endif() endif() set(top "${CMAKE_CURRENT_BINARY_DIR}") @@ -1707,6 +1616,7 @@ function(_ep_set_directories name) if(NOT IS_ABSOLUTE "${${var}_dir}") get_filename_component(${var}_dir "${top}/${${var}_dir}" ABSOLUTE) endif() + file(TO_CMAKE_PATH "${${var}_dir}" ${var}_dir) set_property(TARGET ${name} PROPERTY _EP_${VAR}_DIR "${${var}_dir}") endforeach() @@ -1718,6 +1628,7 @@ function(_ep_set_directories name) if(NOT IS_ABSOLUTE "${log_dir}") get_filename_component(log_dir "${top}/${log_dir}" ABSOLUTE) endif() + file(TO_CMAKE_PATH "${log_dir}" log_dir) set_property(TARGET ${name} PROPERTY _EP_LOG_DIR "${log_dir}") get_property(source_subdir TARGET ${name} PROPERTY _EP_SOURCE_SUBDIR) @@ -1725,37 +1636,41 @@ function(_ep_set_directories name) set_property(TARGET ${name} PROPERTY _EP_SOURCE_SUBDIR "") elseif(IS_ABSOLUTE "${source_subdir}") message(FATAL_ERROR - "External project ${name} has non-relative SOURCE_SUBDIR!") + "External project ${name} has non-relative SOURCE_SUBDIR!" + ) else() # Prefix with a slash so that when appended to the source directory, it # behaves as expected. + file(TO_CMAKE_PATH "${source_subdir}" source_subdir) set_property(TARGET ${name} PROPERTY _EP_SOURCE_SUBDIR "/${source_subdir}") endif() if(build_in_source) get_property(source_dir TARGET ${name} PROPERTY _EP_SOURCE_DIR) if(source_subdir) - set_property(TARGET ${name} PROPERTY _EP_BINARY_DIR "${source_dir}/${source_subdir}") + set_property(TARGET ${name} PROPERTY + _EP_BINARY_DIR "${source_dir}/${source_subdir}" + ) else() - set_property(TARGET ${name} PROPERTY _EP_BINARY_DIR "${source_dir}") + set_property(TARGET ${name} PROPERTY + _EP_BINARY_DIR "${source_dir}" + ) endif() endif() - # Make the directories at CMake configure time *and* add a custom command - # to make them at build time. They need to exist at makefile generation - # time for Borland make and wmake so that CMake may generate makefiles - # with "cd C:\short\paths\with\no\spaces" commands in them. - # - # Additionally, the add_custom_command is still used in case somebody - # removes one of the necessary directories and tries to rebuild without - # re-running cmake. - foreach(var ${places}) - string(TOUPPER "${var}" VAR) - get_property(dir TARGET ${name} PROPERTY _EP_${VAR}_DIR) - file(MAKE_DIRECTORY "${dir}") - if(NOT EXISTS "${dir}") - message(FATAL_ERROR "dir '${dir}' does not exist after file(MAKE_DIRECTORY)") - endif() - endforeach() + # This script will be used both here and by the mkdir step. We create the + # directories now at configure time and ensure they exist again at build + # time (since somebody might remove one of the required directories and try + # to rebuild without re-running cmake). They need to exist now at makefile + # generation time for Borland make and wmake so that CMake may generate + # makefiles with "cd C:\short\paths\with\no\spaces" commands in them. + set(script_filename "${tmp_dir}/${name}-mkdirs.cmake") + configure_file( + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/mkdirs.cmake.in + ${script_filename} + @ONLY + ) + unset(cfgdir) # do not leak into mkdirs.cmake script + include(${script_filename}) endfunction() @@ -1766,7 +1681,16 @@ macro(_ep_replace_location_tags target_name) set(vars ${ARGN}) foreach(var ${vars}) if(${var}) - foreach(dir SOURCE_DIR SOURCE_SUBDIR BINARY_DIR INSTALL_DIR TMP_DIR DOWNLOAD_DIR DOWNLOADED_FILE LOG_DIR) + foreach(dir + SOURCE_DIR + SOURCE_SUBDIR + BINARY_DIR + INSTALL_DIR + TMP_DIR + DOWNLOAD_DIR + DOWNLOADED_FILE + LOG_DIR + ) get_property(val TARGET ${target_name} PROPERTY _EP_${dir}) string(REPLACE "<${dir}>" "${val}" ${var} "${${var}}") endforeach() @@ -1775,7 +1699,11 @@ macro(_ep_replace_location_tags target_name) endmacro() -function(_ep_command_line_to_initial_cache var args force) +function(_ep_command_line_to_initial_cache + var + args + force +) set(script_initial_cache "") set(regex "^([^:]+):([^=]+)=(.*)$") set(setArg "") @@ -1788,7 +1716,9 @@ function(_ep_command_line_to_initial_cache var args force) set(line "${CMAKE_MATCH_1}") if(NOT "${setArg}" STREQUAL "") # This is required to build up lists in variables, or complete an entry - string(APPEND setArg "${accumulator}\" CACHE ${type} \"Initial cache\" ${forceArg})") + string(APPEND setArg + "${accumulator}\" CACHE ${type} \"Initial cache\" ${forceArg})" + ) string(APPEND script_initial_cache "\n${setArg}") set(accumulator "") set(setArg "") @@ -1808,14 +1738,20 @@ function(_ep_command_line_to_initial_cache var args force) endforeach() # Catch the final line of the args if(NOT "${setArg}" STREQUAL "") - string(APPEND setArg "${accumulator}\" CACHE ${type} \"Initial cache\" ${forceArg})") + string(APPEND setArg + "${accumulator}\" CACHE ${type} \"Initial cache\" ${forceArg})" + ) string(APPEND script_initial_cache "\n${setArg}") endif() set(${var} ${script_initial_cache} PARENT_SCOPE) endfunction() -function(_ep_write_initial_cache target_name script_filename script_initial_cache) +function(_ep_write_initial_cache + target_name + script_filename + script_initial_cache +) # Write out values into an initial cache, that will be passed to CMake with -C # Replace location tags. _ep_replace_location_tags(${target_name} script_initial_cache) @@ -1843,7 +1779,10 @@ function(ExternalProject_Get_Property name) endfunction() -function(_ep_get_configure_command_id name cfg_cmd_id_var) +function(_ep_get_configure_command_id + name + cfg_cmd_id_var +) get_target_property(cmd ${name} _EP_CONFIGURE_COMMAND) if(cmd STREQUAL "") @@ -1869,7 +1808,11 @@ function(_ep_get_configure_command_id name cfg_cmd_id_var) endfunction() -function(_ep_get_build_command name step cmd_var) +function(_ep_get_build_command + name + step + cmd_var +) set(cmd "") set(args) _ep_get_configure_command_id(${name} cfg_cmd_id) @@ -1907,8 +1850,10 @@ function(_ep_get_build_command name step cmd_var) # BUILD_COMMAND to change the default command instead, but for # compatibility honor the value. set(config ${CMAKE_CFG_INTDIR}) - message(AUTHOR_WARNING "CMAKE_CFG_INTDIR should not be set by project code.\n" - "To get a non-default build command, use the BUILD_COMMAND option.") + message(AUTHOR_WARNING + "CMAKE_CFG_INTDIR should not be set by project code.\n" + "To get a non-default build command, use the BUILD_COMMAND option." + ) else() set(config $<CONFIG>) endif() @@ -1956,7 +1901,11 @@ function(_ep_get_build_command name step cmd_var) set(${cmd_var} "${cmd}" PARENT_SCOPE) endfunction() -function(_ep_write_log_script name step cmd_var) +function(_ep_write_log_script + name + step + cmd_var +) ExternalProject_Get_Property(${name} log_dir) ExternalProject_Get_Property(${name} stamp_dir) set(command "${${cmd_var}}") @@ -2023,15 +1972,29 @@ endif() endif() endforeach() string(APPEND code "set(command \"${cmd}\")${code_execute_process}") - file(GENERATE OUTPUT "${stamp_dir}/${name}-${step}-$<CONFIG>-impl.cmake" CONTENT "${code}") - set(command ${CMAKE_COMMAND} "-Dmake=\${make}" "-Dconfig=\${config}" -P ${stamp_dir}/${name}-${step}-$<CONFIG>-impl.cmake) + file(GENERATE + OUTPUT "${stamp_dir}/${name}-${step}-$<CONFIG>-impl.cmake" + CONTENT "${code}" + ) + set(command + ${CMAKE_COMMAND} + "-Dmake=\${make}" + "-Dconfig=\${config}" + -P ${stamp_dir}/${name}-${step}-$<CONFIG>-impl.cmake + ) endif() # Wrap the command in a script to log output to files. set(script ${stamp_dir}/${name}-${step}-$<CONFIG>.cmake) set(logbase ${log_dir}/${name}-${step}) - get_property(log_merged TARGET ${name} PROPERTY _EP_LOG_MERGED_STDOUTERR) - get_property(log_output_on_failure TARGET ${name} PROPERTY _EP_LOG_OUTPUT_ON_FAILURE) + get_property(log_merged + TARGET ${name} + PROPERTY _EP_LOG_MERGED_STDOUTERR + ) + get_property(log_output_on_failure + TARGET ${name} + PROPERTY _EP_LOG_OUTPUT_ON_FAILURE + ) if (log_merged) set(stdout_log "${logbase}.log") set(stderr_log "${logbase}.log") @@ -2052,7 +2015,7 @@ execute_process( RESULT_VARIABLE result OUTPUT_FILE \"\${stdout_log}\" ERROR_FILE \"\${stderr_log}\" - ) +) macro(read_up_to_max_size log_file output_var) file(SIZE \${log_file} determined_size) set(max_size 10240) @@ -2101,44 +2064,55 @@ endif() set(${cmd_var} "${command}" PARENT_SCOPE) endfunction() -# This module used to use "/${CMAKE_CFG_INTDIR}" directly and produced -# makefiles with "/./" in paths for custom command dependencies. Which -# resulted in problems with parallel make -j invocations. -# -# This function was added so that the suffix (search below for ${cfgdir}) is -# only set to "/${CMAKE_CFG_INTDIR}" when ${CMAKE_CFG_INTDIR} is not going to -# be "." (multi-configuration build systems like Visual Studio and Xcode...) -# -function(_ep_get_configuration_subdir_suffix suffix_var) +# On multi-config generators, provide a placeholder for a per-config subdir. +# On single-config generators, this is empty. +function(_ep_get_configuration_subdir_genex suffix_var) set(suffix "") get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(_isMultiConfig) - set(suffix "/${CMAKE_CFG_INTDIR}") + if(CMAKE_GENERATOR STREQUAL "Xcode") + # The Xcode generator does not support per-config sources, + # so use the underlying build system's placeholder instead. + set(suffix "/${CMAKE_CFG_INTDIR}") + else() + set(suffix "/$<CONFIG>") + endif() endif() set(${suffix_var} "${suffix}" PARENT_SCOPE) endfunction() -function(_ep_get_step_stampfile name step stampfile_var) +function(_ep_get_step_stampfile + name + step + stampfile_var +) ExternalProject_Get_Property(${name} stamp_dir) - _ep_get_configuration_subdir_suffix(cfgdir) + _ep_get_configuration_subdir_genex(cfgdir) set(stampfile "${stamp_dir}${cfgdir}/${name}-${step}") set(${stampfile_var} "${stampfile}" PARENT_SCOPE) endfunction() -function(_ep_get_complete_stampfile name stampfile_var) +function(_ep_get_complete_stampfile + name + stampfile_var +) set(cmf_dir ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles) - _ep_get_configuration_subdir_suffix(cfgdir) + _ep_get_configuration_subdir_genex(cfgdir) set(stampfile "${cmf_dir}${cfgdir}/${name}-complete") set(${stampfile_var} ${stampfile} PARENT_SCOPE) endfunction() -function(_ep_step_add_target name step no_deps) +function(_ep_step_add_target + name + step + no_deps +) if(TARGET ${name}-${step}) return() endif() @@ -2150,16 +2124,20 @@ function(_ep_step_add_target name step no_deps) # we need CMP0113 NEW behavior. cmake_policy(SET CMP0113 NEW) endif() - add_custom_target(${name}-${step} - DEPENDS ${stamp_file}) + add_custom_target(${name}-${step} DEPENDS ${stamp_file}) cmake_policy(POP) - set_property(TARGET ${name}-${step} PROPERTY _EP_IS_EXTERNAL_PROJECT_STEP 1) - set_property(TARGET ${name}-${step} PROPERTY LABELS ${name}) - set_property(TARGET ${name}-${step} PROPERTY FOLDER "ExternalProjectTargets/${name}") + set_target_properties(${name}-${step} PROPERTIES + _EP_IS_EXTERNAL_PROJECT_STEP 1 + LABELS "${name}" + FOLDER "ExternalProjectTargets/${name}" + ) if(cmp0114 STREQUAL "NEW") # Add target-level dependencies for the step. - get_property(exclude_from_main TARGET ${name} PROPERTY _EP_${step}_EXCLUDE_FROM_MAIN) + get_property(exclude_from_main + TARGET ${name} + PROPERTY _EP_${step}_EXCLUDE_FROM_MAIN + ) if(NOT exclude_from_main) add_dependencies(${name} ${name}-${step}) endif() @@ -2169,7 +2147,9 @@ function(_ep_step_add_target name step no_deps) get_property(independent TARGET ${name} PROPERTY _EP_${step}_INDEPENDENT) else() if(no_deps AND "${step}" MATCHES "^(configure|build|install|test)$") - message(AUTHOR_WARNING "Using NO_DEPENDS for \"${step}\" step might break parallel builds") + message(AUTHOR_WARNING + "Using NO_DEPENDS for \"${step}\" step might break parallel builds" + ) endif() set(independent ${no_deps}) endif() @@ -2184,12 +2164,25 @@ function(_ep_step_add_target name step no_deps) endfunction() -function(_ep_step_add_target_dependencies name step node) - get_property(dependees TARGET ${name} PROPERTY _EP_${node}_INTERNAL_DEPENDEES) +function(_ep_step_add_target_dependencies + name + step + node +) + get_property(dependees + TARGET ${name} + PROPERTY _EP_${node}_INTERNAL_DEPENDEES + ) list(REMOVE_DUPLICATES dependees) foreach(dependee IN LISTS dependees) - get_property(exclude_from_main TARGET ${name} PROPERTY _EP_${step}_EXCLUDE_FROM_MAIN) - get_property(dependee_dependers TARGET ${name} PROPERTY _EP_${dependee}_INTERNAL_DEPENDERS) + get_property(exclude_from_main + TARGET ${name} + PROPERTY _EP_${step}_EXCLUDE_FROM_MAIN + ) + get_property(dependee_dependers + TARGET ${name} + PROPERTY _EP_${dependee}_INTERNAL_DEPENDERS + ) if(exclude_from_main OR dependee_dependers MATCHES ";") # The step on which our step target depends itself has # dependents in multiple targes. It needs a step target too @@ -2206,8 +2199,15 @@ function(_ep_step_add_target_dependencies name step node) endfunction() -function(_ep_step_add_target_dependents name step node) - get_property(dependers TARGET ${name} PROPERTY _EP_${node}_INTERNAL_DEPENDERS) +function(_ep_step_add_target_dependents + name + step + node +) + get_property(dependers + TARGET ${name} + PROPERTY _EP_${node}_INTERNAL_DEPENDERS + ) list(REMOVE_DUPLICATES dependers) foreach(depender IN LISTS dependers) if(TARGET ${name}-${depender}) @@ -2234,7 +2234,7 @@ function(ExternalProject_Add_StepTargets name) "The 'NO_DEPENDS' option is no longer allowed. " "It has been superseded by the per-step 'INDEPENDENT' option. " "See policy CMP0114." - ) + ) endif() elseif(cmp0114 STREQUAL "") cmake_policy(GET_WARNING CMP0114 _cmp0114_warning) @@ -2242,11 +2242,11 @@ function(ExternalProject_Add_StepTargets name) "ExternalProject target '${name}' would depend on the targets for " "step(s) '${steps}' under policy CMP0114, but this is being left out " "for compatibility since the policy is not set." - ) + ) if(no_deps) - string(APPEND _cmp0114_warning - " Also, the NO_DEPENDS option is deprecated in favor of policy CMP0114." - ) + string(APPEND _cmp0114_warning " " + "Also, the NO_DEPENDS option is deprecated in favor of policy CMP0114." + ) endif() message(AUTHOR_WARNING "${_cmp0114_warning}") endif() @@ -2275,38 +2275,60 @@ function(ExternalProject_Add_Step name step) LOG USES_TERMINAL ) - _ep_parse_arguments(ExternalProject_Add_Step "${keywords}" - ${name} _EP_${step}_ "${ARGN}") + _ep_parse_arguments( + ExternalProject_Add_Step + "${keywords}" + ${name} + _EP_${step}_ + "${ARGN}" + ) - get_property(independent TARGET ${name} PROPERTY _EP_${step}_INDEPENDENT) + get_property(independent + TARGET ${name} + PROPERTY _EP_${step}_INDEPENDENT + ) if(independent STREQUAL "") set(independent FALSE) - set_property(TARGET ${name} PROPERTY _EP_${step}_INDEPENDENT "${independent}") + set_property(TARGET ${name} PROPERTY + _EP_${step}_INDEPENDENT "${independent}" + ) endif() - get_property(exclude_from_main TARGET ${name} PROPERTY _EP_${step}_EXCLUDE_FROM_MAIN) + get_property(exclude_from_main + TARGET ${name} + PROPERTY _EP_${step}_EXCLUDE_FROM_MAIN + ) if(NOT exclude_from_main) add_custom_command(APPEND OUTPUT ${complete_stamp_file} DEPENDS ${stamp_file} - ) + ) endif() # Steps depending on this step. get_property(dependers TARGET ${name} PROPERTY _EP_${step}_DEPENDERS) - set_property(TARGET ${name} APPEND PROPERTY _EP_${step}_INTERNAL_DEPENDERS ${dependers}) + set_property(TARGET ${name} APPEND PROPERTY + _EP_${step}_INTERNAL_DEPENDERS ${dependers} + ) foreach(depender IN LISTS dependers) - set_property(TARGET ${name} APPEND PROPERTY _EP_${depender}_INTERNAL_DEPENDEES ${step}) + set_property(TARGET ${name} APPEND PROPERTY + _EP_${depender}_INTERNAL_DEPENDEES ${step} + ) _ep_get_step_stampfile(${name} ${depender} depender_stamp_file) add_custom_command(APPEND OUTPUT ${depender_stamp_file} DEPENDS ${stamp_file} - ) + ) if(cmp0114 STREQUAL "NEW" AND NOT independent) - get_property(dep_independent TARGET ${name} PROPERTY _EP_${depender}_INDEPENDENT) + get_property(dep_independent + TARGET ${name} + PROPERTY _EP_${depender}_INDEPENDENT + ) if(dep_independent) - message(FATAL_ERROR "ExternalProject '${name}' step '${depender}' is marked INDEPENDENT " - "but depends on step '${step}' that is not marked INDEPENDENT.") + message(FATAL_ERROR + "ExternalProject '${name}' step '${depender}' is marked INDEPENDENT " + "but depends on step '${step}' that is not marked INDEPENDENT." + ) endif() endif() endforeach() @@ -2319,16 +2341,25 @@ function(ExternalProject_Add_Step name step) # Dependencies on steps. get_property(dependees TARGET ${name} PROPERTY _EP_${step}_DEPENDEES) - set_property(TARGET ${name} APPEND PROPERTY _EP_${step}_INTERNAL_DEPENDEES ${dependees}) + set_property(TARGET ${name} APPEND PROPERTY + _EP_${step}_INTERNAL_DEPENDEES ${dependees} + ) foreach(dependee IN LISTS dependees) - set_property(TARGET ${name} APPEND PROPERTY _EP_${dependee}_INTERNAL_DEPENDERS ${step}) + set_property(TARGET ${name} APPEND PROPERTY + _EP_${dependee}_INTERNAL_DEPENDERS ${step} + ) _ep_get_step_stampfile(${name} ${dependee} dependee_stamp_file) list(APPEND depends ${dependee_stamp_file}) if(cmp0114 STREQUAL "NEW" AND independent) - get_property(dep_independent TARGET ${name} PROPERTY _EP_${dependee}_INDEPENDENT) + get_property(dep_independent + TARGET ${name} + PROPERTY _EP_${dependee}_INDEPENDENT + ) if(NOT dep_independent) - message(FATAL_ERROR "ExternalProject '${name}' step '${step}' is marked INDEPENDENT " - "but depends on step '${dependee}' that is not marked INDEPENDENT.") + message(FATAL_ERROR + "ExternalProject '${name}' step '${step}' is marked INDEPENDENT " + "but depends on step '${dependee}' that is not marked INDEPENDENT." + ) endif() endif() endforeach() @@ -2340,25 +2371,47 @@ function(ExternalProject_Add_Step name step) else() set(comment "No ${step} step for '${name}'") endif() - get_property(work_dir TARGET ${name} PROPERTY _EP_${step}_WORKING_DIRECTORY) + get_property(work_dir + TARGET ${name} + PROPERTY _EP_${step}_WORKING_DIRECTORY + ) # Replace list separators. - get_property(sep TARGET ${name} PROPERTY _EP_LIST_SEPARATOR) + get_property(sep + TARGET ${name} + PROPERTY _EP_LIST_SEPARATOR + ) if(sep AND command) string(REPLACE "${sep}" "\\;" command "${command}") endif() # Replace location tags. - _ep_replace_location_tags(${name} comment command work_dir byproducts) + _ep_replace_location_tags( + ${name} + comment + command + work_dir + byproducts + ) # Custom comment? - get_property(comment_set TARGET ${name} PROPERTY _EP_${step}_COMMENT SET) + get_property(comment_set + TARGET ${name} + PROPERTY _EP_${step}_COMMENT + SET + ) if(comment_set) - get_property(comment TARGET ${name} PROPERTY _EP_${step}_COMMENT) + get_property(comment + TARGET ${name} + PROPERTY _EP_${step}_COMMENT + ) endif() # Uses terminal? - get_property(uses_terminal TARGET ${name} PROPERTY _EP_${step}_USES_TERMINAL) + get_property(uses_terminal + TARGET ${name} + PROPERTY _EP_${step}_USES_TERMINAL + ) if(uses_terminal) set(uses_terminal USES_TERMINAL) else() @@ -2366,18 +2419,30 @@ function(ExternalProject_Add_Step name step) endif() # Run every time? - get_property(always TARGET ${name} PROPERTY _EP_${step}_ALWAYS) + get_property(always + TARGET ${name} + PROPERTY _EP_${step}_ALWAYS + ) if(always) - set_property(SOURCE ${stamp_file} PROPERTY SYMBOLIC 1) set(touch) + # Mark stamp files for all configs as SYMBOLIC since we do not create them. # Remove any existing stamp in case the option changed in an existing tree. get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(_isMultiConfig) + _ep_get_configuration_subdir_genex(cfgdir) foreach(cfg ${CMAKE_CONFIGURATION_TYPES}) - string(REPLACE "/${CMAKE_CFG_INTDIR}" "/${cfg}" stamp_file_config "${stamp_file}") + string(REPLACE "${cfgdir}" "/${cfg}" + stamp_file_config "${stamp_file}" + ) + set_property(SOURCE ${stamp_file_config} PROPERTY SYMBOLIC 1) file(REMOVE ${stamp_file_config}) endforeach() + if(CMAKE_GENERATOR STREQUAL "Xcode") + # See Xcode case in _ep_get_configuration_subdir_genex. + set_property(SOURCE ${stamp_file} PROPERTY SYMBOLIC 1) + endif() else() + set_property(SOURCE ${stamp_file} PROPERTY SYMBOLIC 1) file(REMOVE ${stamp_file}) endif() else() @@ -2419,9 +2484,15 @@ function(ExternalProject_Add_Step name step) set_property(TARGET ${name} APPEND PROPERTY _EP_STEPS ${step}) # Add custom "step target"? - get_property(step_targets TARGET ${name} PROPERTY _EP_STEP_TARGETS) + get_property(step_targets + TARGET ${name} + PROPERTY _EP_STEP_TARGETS + ) if(NOT step_targets) - get_property(step_targets DIRECTORY PROPERTY EP_STEP_TARGETS) + get_property(step_targets + DIRECTORY + PROPERTY EP_STEP_TARGETS + ) endif() foreach(st ${step_targets}) if("${st}" STREQUAL "${step}") @@ -2430,31 +2501,43 @@ function(ExternalProject_Add_Step name step) endif() endforeach() - get_property(independent_step_targets TARGET ${name} PROPERTY _EP_INDEPENDENT_STEP_TARGETS) + get_property(independent_step_targets + TARGET ${name} PROPERTY + _EP_INDEPENDENT_STEP_TARGETS + ) if(NOT independent_step_targets) - get_property(independent_step_targets DIRECTORY PROPERTY EP_INDEPENDENT_STEP_TARGETS) + get_property(independent_step_targets + DIRECTORY + PROPERTY EP_INDEPENDENT_STEP_TARGETS + ) endif() if(cmp0114 STREQUAL "NEW") if(independent_step_targets) message(FATAL_ERROR - "ExternalProject '${name}' option 'INDEPENDENT_STEP_TARGETS' is set to\n" - " ${independent_step_targets}\n" + "ExternalProject '${name}' option 'INDEPENDENT_STEP_TARGETS' is set to" + "\n ${independent_step_targets}\n" "but the option is no longer allowed. " "It has been superseded by the per-step 'INDEPENDENT' option. " "See policy CMP0114." - ) + ) endif() else() if(independent_step_targets AND cmp0114 STREQUAL "") - get_property(warned TARGET ${name} PROPERTY _EP_CMP0114_WARNED_INDEPENDENT_STEP_TARGETS) + get_property(warned + TARGET ${name} + PROPERTY _EP_CMP0114_WARNED_INDEPENDENT_STEP_TARGETS + ) if(NOT warned) - set_property(TARGET ${name} PROPERTY _EP_CMP0114_WARNED_INDEPENDENT_STEP_TARGETS 1) + set_property(TARGET ${name} PROPERTY + _EP_CMP0114_WARNED_INDEPENDENT_STEP_TARGETS 1 + ) cmake_policy(GET_WARNING CMP0114 _cmp0114_warning) - string(APPEND _cmp0114_warning "\n" - "ExternalProject '${name}' option INDEPENDENT_STEP_TARGETS is set to\n" - " ${independent_step_targets}\n" + string(APPEND _cmp0114_warning + "\n" + "ExternalProject '${name}' option INDEPENDENT_STEP_TARGETS is set to" + "\n ${independent_step_targets}\n" "but the option is deprecated in favor of policy CMP0114." - ) + ) message(AUTHOR_WARNING "${_cmp0114_warning}") endif() endif() @@ -2473,33 +2556,51 @@ function(ExternalProject_Add_StepDependencies name step) # Sanity checks on "name" and "step". if(NOT TARGET ${name}) - message(FATAL_ERROR "Cannot find target \"${name}\". Perhaps it has not yet been created using ExternalProject_Add.") + message(FATAL_ERROR + "Cannot find target \"${name}\". Perhaps it has not yet been created " + "using ExternalProject_Add." + ) endif() get_property(type TARGET ${name} PROPERTY TYPE) if(NOT type STREQUAL "UTILITY") - message(FATAL_ERROR "Target \"${name}\" was not generated by ExternalProject_Add.") + message(FATAL_ERROR + "Target \"${name}\" was not generated by ExternalProject_Add." + ) endif() get_property(is_ep TARGET ${name} PROPERTY _EP_IS_EXTERNAL_PROJECT) if(NOT is_ep) - message(FATAL_ERROR "Target \"${name}\" was not generated by ExternalProject_Add.") + message(FATAL_ERROR + "Target \"${name}\" was not generated by ExternalProject_Add." + ) endif() get_property(steps TARGET ${name} PROPERTY _EP_STEPS) list(FIND steps ${step} is_step) if(is_step LESS 0) - message(FATAL_ERROR "External project \"${name}\" does not have a step \"${step}\".") + message(FATAL_ERROR + "External project \"${name}\" does not have a step \"${step}\"." + ) endif() if(TARGET ${name}-${step}) get_property(type TARGET ${name}-${step} PROPERTY TYPE) if(NOT type STREQUAL "UTILITY") - message(FATAL_ERROR "Target \"${name}-${step}\" was not generated by ExternalProject_Add_StepTargets.") + message(FATAL_ERROR + "Target \"${name}-${step}\" was not generated by " + "ExternalProject_Add_StepTargets." + ) endif() - get_property(is_ep_step TARGET ${name}-${step} PROPERTY _EP_IS_EXTERNAL_PROJECT_STEP) + get_property(is_ep_step + TARGET ${name}-${step} + PROPERTY _EP_IS_EXTERNAL_PROJECT_STEP + ) if(NOT is_ep_step) - message(FATAL_ERROR "Target \"${name}-${step}\" was not generated by ExternalProject_Add_StepTargets.") + message(FATAL_ERROR + "Target \"${name}-${step}\" was not generated by " + "ExternalProject_Add_StepTargets." + ) endif() endif() @@ -2509,7 +2610,8 @@ function(ExternalProject_Add_StepDependencies name step) foreach(dep ${dependencies}) add_custom_command(APPEND OUTPUT ${stamp_file} - DEPENDS ${dep}) + DEPENDS ${dep} + ) if(TARGET ${name}-${step}) foreach(dep ${dependencies}) add_dependencies(${name}-${step} ${dep}) @@ -2521,22 +2623,15 @@ endfunction() function(_ep_add_mkdir_command name) - ExternalProject_Get_Property(${name} - source_dir binary_dir install_dir stamp_dir download_dir tmp_dir log_dir) - - _ep_get_configuration_subdir_suffix(cfgdir) + ExternalProject_Get_Property(${name} tmp_dir) + set(script_filename "${tmp_dir}/${name}-mkdirs.cmake") + _ep_get_configuration_subdir_genex(cfgdir) ExternalProject_Add_Step(${name} mkdir INDEPENDENT TRUE COMMENT "Creating directories for '${name}'" - COMMAND ${CMAKE_COMMAND} -E make_directory ${source_dir} - COMMAND ${CMAKE_COMMAND} -E make_directory ${binary_dir} - COMMAND ${CMAKE_COMMAND} -E make_directory ${install_dir} - COMMAND ${CMAKE_COMMAND} -E make_directory ${tmp_dir} - COMMAND ${CMAKE_COMMAND} -E make_directory ${stamp_dir}${cfgdir} - COMMAND ${CMAKE_COMMAND} -E make_directory ${download_dir} - COMMAND ${CMAKE_COMMAND} -E make_directory ${log_dir} - ) + COMMAND ${CMAKE_COMMAND} -Dcfgdir=${cfgdir} -P ${script_filename} + ) endfunction() @@ -2550,14 +2645,21 @@ function(_ep_is_dir_empty dir empty_var) endfunction() function(_ep_get_git_submodules_recurse git_submodules_recurse) - # Checks for GIT_SUBMODULES_RECURSE property - # Default is ON, which sets git_submodules_recurse output variable to "--recursive" - # Otherwise, the output variable is set to an empty value "" - get_property(git_submodules_recurse_set TARGET ${name} PROPERTY _EP_GIT_SUBMODULES_RECURSE SET) + # Checks for GIT_SUBMODULES_RECURSE property. Default is ON, which sets + # git_submodules_recurse output variable to "--recursive". Otherwise, the + # output variable is set to an empty value "". + get_property(git_submodules_recurse_set + TARGET ${name} + PROPERTY _EP_GIT_SUBMODULES_RECURSE + SET + ) if(NOT git_submodules_recurse_set) set(recurseFlag "--recursive") else() - get_property(git_submodules_recurse_value TARGET ${name} PROPERTY _EP_GIT_SUBMODULES_RECURSE) + get_property(git_submodules_recurse_value + TARGET ${name} + PROPERTY _EP_GIT_SUBMODULES_RECURSE + ) if(git_submodules_recurse_value) set(recurseFlag "--recursive") else() @@ -2568,13 +2670,21 @@ function(_ep_get_git_submodules_recurse git_submodules_recurse) # The git submodule update '--recursive' flag requires git >= v1.6.5 if(recurseFlag AND GIT_VERSION_STRING VERSION_LESS 1.6.5) - message(FATAL_ERROR "error: git version 1.6.5 or later required for --recursive flag with 'git submodule ...': GIT_VERSION_STRING='${GIT_VERSION_STRING}'") + message(FATAL_ERROR + "git version 1.6.5 or later required for --recursive flag with " + "'git submodule ...': GIT_VERSION_STRING='${GIT_VERSION_STRING}'" + ) endif() endfunction() function(_ep_add_download_command name) - ExternalProject_Get_Property(${name} source_dir stamp_dir download_dir tmp_dir) + ExternalProject_Get_Property(${name} + source_dir + stamp_dir + download_dir + tmp_dir + ) get_property(cmd_set TARGET ${name} PROPERTY _EP_DOWNLOAD_COMMAND SET) get_property(cmd TARGET ${name} PROPERTY _EP_DOWNLOAD_COMMAND) @@ -2591,10 +2701,13 @@ function(_ep_add_download_command name) set(depends) set(comment) set(work_dir) + set(extra_repo_info) if(cmd_set) set(work_dir ${download_dir}) + set(method custom) elseif(cvs_repository) + set(method cvs) find_package(CVS QUIET) if(NOT CVS_EXECUTABLE) message(FATAL_ERROR "error: could not find cvs for checkout of ${name}") @@ -2606,22 +2719,20 @@ function(_ep_add_download_command name) endif() get_property(cvs_tag TARGET ${name} PROPERTY _EP_CVS_TAG) - - set(repository ${cvs_repository}) - set(module ${cvs_module}) - set(tag ${cvs_tag}) - configure_file( - "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in" - "${stamp_dir}/${name}-cvsinfo.txt" - @ONLY - ) - get_filename_component(src_name "${source_dir}" NAME) get_filename_component(work_dir "${source_dir}" PATH) set(comment "Performing download step (CVS checkout) for '${name}'") - set(cmd ${CVS_EXECUTABLE} -d ${cvs_repository} -q co ${cvs_tag} -d ${src_name} ${cvs_module}) - list(APPEND depends ${stamp_dir}/${name}-cvsinfo.txt) + set(cmd + ${CVS_EXECUTABLE} + -d ${cvs_repository} + -q + co ${cvs_tag} + -d ${src_name} + ${cvs_module} + ) + elseif(svn_repository) + set(method svn) find_package(Subversion QUIET) if(NOT Subversion_SVN_EXECUTABLE) message(FATAL_ERROR "error: could not find svn for checkout of ${name}") @@ -2631,15 +2742,15 @@ function(_ep_add_download_command name) get_property(svn_username TARGET ${name} PROPERTY _EP_SVN_USERNAME) get_property(svn_password TARGET ${name} PROPERTY _EP_SVN_PASSWORD) get_property(svn_trust_cert TARGET ${name} PROPERTY _EP_SVN_TRUST_CERT) - - set(repository "${svn_repository} user=${svn_username} password=${svn_password}") - set(module) - set(tag ${svn_revision}) - configure_file( - "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in" - "${stamp_dir}/${name}-svninfo.txt" - @ONLY - ) + get_property(uses_terminal + TARGET ${name} + PROPERTY _EP_USES_TERMINAL_DOWNLOAD + ) + if(uses_terminal) + set(svn_interactive_args "") + else() + set(svn_interactive_args "--non-interactive") + endif() get_filename_component(src_name "${source_dir}" NAME) get_filename_component(work_dir "${source_dir}" PATH) @@ -2654,10 +2765,19 @@ function(_ep_add_download_command name) if(svn_trust_cert) set(svn_trust_cert_args --trust-server-cert) endif() - set(cmd ${Subversion_SVN_EXECUTABLE} co ${svn_repository} ${svn_revision} - --non-interactive ${svn_trust_cert_args} ${svn_user_pw_args} ${src_name}) - list(APPEND depends ${stamp_dir}/${name}-svninfo.txt) + set(cmd + ${Subversion_SVN_EXECUTABLE} + co + ${svn_repository} + ${svn_revision} + ${svn_interactive_args} + ${svn_trust_cert_args} + ${svn_user_pw_args} + ${src_name} + ) + elseif(git_repository) + set(method git) # FetchContent gives us these directly, so don't try to recompute them if(NOT GIT_EXECUTABLE OR NOT GIT_VERSION_STRING) unset(CMAKE_MODULE_PATH) # Use CMake builtin find module @@ -2675,7 +2795,10 @@ function(_ep_add_download_command name) endif() set(git_init_submodules TRUE) - get_property(git_submodules_set TARGET ${name} PROPERTY _EP_GIT_SUBMODULES SET) + get_property(git_submodules_set + TARGET ${name} + PROPERTY _EP_GIT_SUBMODULES SET + ) if(git_submodules_set) get_property(git_submodules TARGET ${name} PROPERTY _EP_GIT_SUBMODULES) if(git_submodules STREQUAL "" AND _EP_CMP0097 STREQUAL "NEW") @@ -2702,21 +2825,21 @@ function(_ep_add_download_command name) list(PREPEND git_config advice.detachedHead=false) endif() - # For the download step, and the git clone operation, only the repository - # should be recorded in a configured RepositoryInfo file. If the repo - # changes, the clone script should be run again. But if only the tag - # changes, avoid running the clone script again. Let the 'always' running - # update step checkout the new tag. + # The command doesn't expose any details, so we need to record additional + # information in the RepositoryInfo.txt file. For the download step, only + # the things specifically affecting the clone operation should be recorded. + # If the repo changes, the clone script should be run again. + # But if only the tag changes, avoid running the clone script again. + # Let the 'always' running update step checkout the new tag. # - set(repository ${git_repository}) - set(module) - set(tag ${git_remote_name}) - configure_file( - "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in" - "${stamp_dir}/${name}-gitinfo.txt" - @ONLY - ) - + set(extra_repo_info +"repository=${git_repository} +remote=${git_remote_name} +init_submodules=${git_init_submodules} +recurse_submodules=${git_submodules_recurse} +submodules=${git_submodules} +CMP0097=${_EP_CMP0097} +") get_filename_component(src_name "${source_dir}" NAME) get_filename_component(work_dir "${source_dir}" PATH) @@ -2724,14 +2847,30 @@ function(_ep_add_download_command name) # create a cmake script to invoke as download command. # The script will delete the source directory and then call git clone. # - _ep_write_gitclone_script(${tmp_dir}/${name}-gitclone.cmake ${source_dir} - ${GIT_EXECUTABLE} ${git_repository} ${git_tag} ${git_remote_name} ${git_init_submodules} "${git_submodules_recurse}" "${git_submodules}" "${git_shallow}" "${git_progress}" "${git_config}" ${src_name} ${work_dir} - ${stamp_dir}/${name}-gitinfo.txt ${stamp_dir}/${name}-gitclone-lastrun.txt "${tls_verify}" - ) + _ep_write_gitclone_script( + ${tmp_dir}/${name}-gitclone.cmake + ${source_dir} + ${GIT_EXECUTABLE} + ${git_repository} + ${git_tag} + ${git_remote_name} + ${git_init_submodules} + "${git_submodules_recurse}" + "${git_submodules}" + "${git_shallow}" + "${git_progress}" + "${git_config}" + ${src_name} + ${work_dir} + ${stamp_dir}/${name}-gitinfo.txt + ${stamp_dir}/${name}-gitclone-lastrun.txt + "${tls_verify}" + ) set(comment "Performing download step (git clone) for '${name}'") set(cmd ${CMAKE_COMMAND} -P ${tmp_dir}/${name}-gitclone.cmake) - list(APPEND depends ${stamp_dir}/${name}-gitinfo.txt) + elseif(hg_repository) + set(method hg) find_package(Hg QUIET) if(NOT HG_EXECUTABLE) message(FATAL_ERROR "error: could not find hg for clone of ${name}") @@ -2742,21 +2881,14 @@ function(_ep_add_download_command name) set(hg_tag "tip") endif() - # For the download step, and the hg clone operation, only the repository - # should be recorded in a configured RepositoryInfo file. If the repo - # changes, the clone script should be run again. But if only the tag - # changes, avoid running the clone script again. Let the 'always' running - # update step checkout the new tag. + # The command doesn't expose any details, so we need to record additional + # information in the RepositoryInfo.txt file. For the download step, only + # the things specifically affecting the clone operation should be recorded. + # If the repo changes, the clone script should be run again. + # But if only the tag changes, avoid running the clone script again. + # Let the 'always' running update step checkout the new tag. # - set(repository ${hg_repository}) - set(module) - set(tag) - configure_file( - "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in" - "${stamp_dir}/${name}-hginfo.txt" - @ONLY - ) - + set(extra_repo_info "repository=${hg_repository}") get_filename_component(src_name "${source_dir}" NAME) get_filename_component(work_dir "${source_dir}" PATH) @@ -2764,46 +2896,59 @@ function(_ep_add_download_command name) # create a cmake script to invoke as download command. # The script will delete the source directory and then call hg clone. # - _ep_write_hgclone_script(${tmp_dir}/${name}-hgclone.cmake ${source_dir} - ${HG_EXECUTABLE} ${hg_repository} ${hg_tag} ${src_name} ${work_dir} - ${stamp_dir}/${name}-hginfo.txt ${stamp_dir}/${name}-hgclone-lastrun.txt - ) + _ep_write_hgclone_script( + ${tmp_dir}/${name}-hgclone.cmake + ${source_dir} + ${HG_EXECUTABLE} + ${hg_repository} + ${hg_tag} + ${src_name} + ${work_dir} + ${stamp_dir}/${name}-hginfo.txt + ${stamp_dir}/${name}-hgclone-lastrun.txt + ) set(comment "Performing download step (hg clone) for '${name}'") set(cmd ${CMAKE_COMMAND} -P ${tmp_dir}/${name}-hgclone.cmake) - list(APPEND depends ${stamp_dir}/${name}-hginfo.txt) + elseif(url) + set(method url) get_filename_component(work_dir "${source_dir}" PATH) get_property(hash TARGET ${name} PROPERTY _EP_URL_HASH) _ep_get_hash_regex(_ep_hash_regex) if(hash AND NOT "${hash}" MATCHES "${_ep_hash_regex}") _ep_get_hash_algos(_ep_hash_algos) list(JOIN _ep_hash_algos "|" _ep_hash_algos) - message(FATAL_ERROR "URL_HASH is set to\n ${hash}\n" - "but must be ALGO=value where ALGO is\n ${_ep_hash_algos}\n" - "and value is a hex string.") + message(FATAL_ERROR + "URL_HASH is set to\n" + " ${hash}\n" + "but must be ALGO=value where ALGO is\n" + " ${_ep_hash_algos}\n" + "and value is a hex string." + ) endif() get_property(md5 TARGET ${name} PROPERTY _EP_URL_MD5) if(md5 AND NOT "MD5=${md5}" MATCHES "${_ep_hash_regex}") - message(FATAL_ERROR "URL_MD5 is set to\n ${md5}\nbut must be a hex string.") + message(FATAL_ERROR + "URL_MD5 is set to\n" + " ${md5}\n" + "but must be a hex string." + ) endif() if(md5 AND NOT hash) set(hash "MD5=${md5}") endif() - set(repository "external project URL") - set(module "${url}") - set(tag "${hash}") - configure_file( - "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in" - "${stamp_dir}/${name}-urlinfo.txt" - @ONLY - ) - list(APPEND depends ${stamp_dir}/${name}-urlinfo.txt) + set(extra_repo_info +"url(s)=${url} +hash=${hash} +") list(LENGTH url url_list_length) if(NOT "${url_list_length}" STREQUAL "1") foreach(entry ${url}) if(NOT "${entry}" MATCHES "^[a-z]+://") - message(FATAL_ERROR "At least one entry of URL is a path (invalid in a list)") + message(FATAL_ERROR + "At least one entry of URL is a path (invalid in a list)" + ) endif() endforeach() if("x${fname}" STREQUAL "x") @@ -2814,16 +2959,23 @@ function(_ep_add_download_command name) if(IS_DIRECTORY "${url}") get_filename_component(abs_dir "${url}" ABSOLUTE) set(comment "Performing download step (DIR copy) for '${name}'") - set(cmd ${CMAKE_COMMAND} -E rm -rf ${source_dir} - COMMAND ${CMAKE_COMMAND} -E copy_directory ${abs_dir} ${source_dir}) + set(cmd + ${CMAKE_COMMAND} -E rm -rf ${source_dir} + COMMAND ${CMAKE_COMMAND} -E copy_directory ${abs_dir} ${source_dir} + ) else() - get_property(no_extract TARGET "${name}" PROPERTY _EP_DOWNLOAD_NO_EXTRACT) + get_property(no_extract + TARGET "${name}" + PROPERTY _EP_DOWNLOAD_NO_EXTRACT + ) + string(APPEND extra_repo_info "no_extract=${no_extract}\n") if("${url}" MATCHES "^[a-z]+://") # TODO: Should download and extraction be different steps? if("x${fname}" STREQUAL "x") set(fname "${url}") endif() - if("${fname}" MATCHES [[([^/\?#]+(\.|=)(7z|tar|tar\.bz2|tar\.gz|tar\.xz|tbz2|tgz|txz|zip))([/?#].*)?$]]) + set(ext_regex [[7z|tar|tar\.bz2|tar\.gz|tar\.xz|tbz2|tgz|txz|zip]]) + if("${fname}" MATCHES "([^/\\?#]+(\\.|=)(${ext_regex}))([/?#].*)?$") set(fname "${CMAKE_MATCH_1}") elseif(no_extract) get_filename_component(fname "${fname}" NAME) @@ -2838,8 +2990,14 @@ function(_ep_add_download_command name) string(REPLACE ";" "-" fname "${fname}") set(file ${download_dir}/${fname}) get_property(timeout TARGET ${name} PROPERTY _EP_TIMEOUT) - get_property(inactivity_timeout TARGET ${name} PROPERTY _EP_INACTIVITY_TIMEOUT) - get_property(no_progress TARGET ${name} PROPERTY _EP_DOWNLOAD_NO_PROGRESS) + get_property(inactivity_timeout + TARGET ${name} + PROPERTY _EP_INACTIVITY_TIMEOUT + ) + get_property(no_progress + TARGET ${name} + PROPERTY _EP_DOWNLOAD_NO_PROGRESS + ) get_property(tls_verify TARGET ${name} PROPERTY _EP_TLS_VERIFY) get_property(tls_cainfo TARGET ${name} PROPERTY _EP_TLS_CAINFO) get_property(netrc TARGET ${name} PROPERTY _EP_NETRC) @@ -2848,16 +3006,38 @@ function(_ep_add_download_command name) get_property(http_password TARGET ${name} PROPERTY _EP_HTTP_PASSWORD) get_property(http_headers TARGET ${name} PROPERTY _EP_HTTP_HEADER) set(download_script "${stamp_dir}/download-${name}.cmake") - _ep_write_downloadfile_script("${download_script}" "${url}" "${file}" "${timeout}" "${inactivity_timeout}" "${no_progress}" "${hash}" "${tls_verify}" "${tls_cainfo}" "${http_username}:${http_password}" "${http_headers}" "${netrc}" "${netrc_file}") - set(cmd ${CMAKE_COMMAND} -P "${download_script}" - COMMAND) + _ep_write_downloadfile_script( + "${download_script}" + "${url}" + "${file}" + "${timeout}" + "${inactivity_timeout}" + "${no_progress}" + "${hash}" + "${tls_verify}" + "${tls_cainfo}" + "${http_username}:${http_password}" + "${http_headers}" + "${netrc}" + "${netrc_file}" + ) + set(cmd + ${CMAKE_COMMAND} -P "${download_script}" + COMMAND + ) if (no_extract) set(steps "download and verify") else () set(steps "download, verify and extract") endif () set(comment "Performing download step (${steps}) for '${name}'") - file(WRITE "${stamp_dir}/verify-${name}.cmake" "") # already verified by 'download_script' + # already verified by 'download_script' + file(WRITE "${stamp_dir}/verify-${name}.cmake" "") + + # Rather than adding everything to the RepositoryInfo.txt file, it is + # more robust to just depend on the download script. That way, we will + # re-download if any aspect of the download changes. + list(APPEND depends "${download_script}") else() set(file "${url}") if (no_extract) @@ -2866,20 +3046,69 @@ function(_ep_add_download_command name) set(steps "verify and extract") endif () set(comment "Performing download step (${steps}) for '${name}'") - _ep_write_verifyfile_script("${stamp_dir}/verify-${name}.cmake" "${file}" "${hash}") + _ep_write_verifyfile_script( + "${stamp_dir}/verify-${name}.cmake" + "${file}" + "${hash}" + ) endif() list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/verify-${name}.cmake) - if (NOT no_extract) - _ep_write_extractfile_script("${stamp_dir}/extract-${name}.cmake" "${name}" "${file}" "${source_dir}") - list(APPEND cmd COMMAND ${CMAKE_COMMAND} -P ${stamp_dir}/extract-${name}.cmake) - else () + get_target_property(extract_timestamp ${name} + _EP_DOWNLOAD_EXTRACT_TIMESTAMP + ) + if(no_extract) + if(NOT extract_timestamp STREQUAL "extract_timestamp-NOTFOUND") + message(FATAL_ERROR + "Cannot specify DOWNLOAD_EXTRACT_TIMESTAMP when using " + "DOWNLOAD_NO_EXTRACT TRUE" + ) + endif() set_property(TARGET ${name} PROPERTY _EP_DOWNLOADED_FILE ${file}) + else() + if(extract_timestamp STREQUAL "extract_timestamp-NOTFOUND") + # Default depends on policy CMP0135 + if(_EP_CMP0135 STREQUAL "") + message(AUTHOR_WARNING + "The DOWNLOAD_EXTRACT_TIMESTAMP option was not given and policy " + "CMP0135 is not set. The policy's OLD behavior will be used. " + "When using a URL download, the timestamps of extracted files " + "should preferably be that of the time of extraction, otherwise " + "code that depends on the extracted contents might not be " + "rebuilt if the URL changes. The OLD behavior preserves the " + "timestamps from the archive instead, but this is usually not " + "what you want. Update your project to the NEW behavior or " + "specify the DOWNLOAD_EXTRACT_TIMESTAMP option with a value of " + "true to avoid this robustness issue." + ) + set(extract_timestamp TRUE) + elseif(_EP_CMP0135 STREQUAL "NEW") + set(extract_timestamp FALSE) + else() + set(extract_timestamp TRUE) + endif() + endif() + if(extract_timestamp) + set(options "") + else() + set(options "--touch") + endif() + _ep_write_extractfile_script( + "${stamp_dir}/extract-${name}.cmake" + "${name}" + "${file}" + "${source_dir}" + "${options}" + ) + list(APPEND cmd + COMMAND ${CMAKE_COMMAND} -P ${stamp_dir}/extract-${name}.cmake + ) endif () endif() else() + set(method source_dir) _ep_is_dir_empty("${source_dir}" empty) if(${empty}) - message(SEND_ERROR + message(FATAL_ERROR "No download info given for '${name}' and its source directory:\n" " ${source_dir}\n" "is not an existing non-empty directory. Please specify one of:\n" @@ -2890,19 +3119,35 @@ function(_ep_add_download_command name) " * SVN_REPOSITORY\n" " * HG_REPOSITORY\n" " * CVS_REPOSITORY and CVS_MODULE" - ) + ) endif() endif() - get_property(log TARGET ${name} PROPERTY _EP_LOG_DOWNLOAD) + # We use configure_file() to write the repo_info_file so that the file's + # timestamp is not updated if we don't change the contents + + set(repo_info_file ${stamp_dir}/${name}-${method}info.txt) + list(APPEND depends ${repo_info_file}) + configure_file( + "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/RepositoryInfo.txt.in" + "${repo_info_file}" + @ONLY + ) + + get_property(log + TARGET ${name} + PROPERTY _EP_LOG_DOWNLOAD + ) if(log) set(log LOG 1) else() set(log "") endif() - get_property(uses_terminal TARGET ${name} PROPERTY - _EP_USES_TERMINAL_DOWNLOAD) + get_property(uses_terminal + TARGET ${name} + PROPERTY _EP_USES_TERMINAL_DOWNLOAD + ) if(uses_terminal) set(uses_terminal USES_TERMINAL 1) else() @@ -2923,16 +3168,26 @@ function(_ep_add_download_command name) DEPENDEES mkdir ${log} ${uses_terminal} - )" + )" ) endfunction() function(_ep_get_update_disconnected var name) - get_property(update_disconnected_set TARGET ${name} PROPERTY _EP_UPDATE_DISCONNECTED SET) + get_property(update_disconnected_set + TARGET ${name} + PROPERTY _EP_UPDATE_DISCONNECTED + SET + ) if(update_disconnected_set) - get_property(update_disconnected TARGET ${name} PROPERTY _EP_UPDATE_DISCONNECTED) + get_property(update_disconnected + TARGET ${name} + PROPERTY _EP_UPDATE_DISCONNECTED + ) else() - get_property(update_disconnected DIRECTORY PROPERTY EP_UPDATE_DISCONNECTED) + get_property(update_disconnected + DIRECTORY + PROPERTY EP_UPDATE_DISCONNECTED + ) endif() set(${var} "${update_disconnected}" PARENT_SCOPE) endfunction() @@ -2977,6 +3232,12 @@ function(_ep_add_update_command name) get_property(svn_username TARGET ${name} PROPERTY _EP_SVN_USERNAME) get_property(svn_password TARGET ${name} PROPERTY _EP_SVN_PASSWORD) get_property(svn_trust_cert TARGET ${name} PROPERTY _EP_SVN_TRUST_CERT) + get_property(uses_terminal TARGET ${name} PROPERTY _EP_USES_TERMINAL_UPDATE) + if(uses_terminal) + set(svn_interactive_args "") + else() + set(svn_interactive_args "--non-interactive") + endif() set(svn_user_pw_args "") if(DEFINED svn_username) set(svn_user_pw_args ${svn_user_pw_args} "--username=${svn_username}") @@ -2987,8 +3248,14 @@ function(_ep_add_update_command name) if(svn_trust_cert) set(svn_trust_cert_args --trust-server-cert) endif() - set(cmd ${Subversion_SVN_EXECUTABLE} up ${svn_revision} - --non-interactive ${svn_trust_cert_args} ${svn_user_pw_args}) + set(cmd + ${Subversion_SVN_EXECUTABLE} + up + ${svn_revision} + ${svn_interactive_args} + ${svn_trust_cert_args} + ${svn_user_pw_args} + ) set(always 1) elseif(git_repository) # FetchContent gives us these directly, so don't try to recompute them @@ -3001,25 +3268,43 @@ function(_ep_add_update_command name) endif() set(work_dir ${source_dir}) set(comment "Performing update step for '${name}'") - get_property(git_tag TARGET ${name} PROPERTY _EP_GIT_TAG) + + get_property(git_tag + TARGET ${name} + PROPERTY _EP_GIT_TAG + ) if(NOT git_tag) set(git_tag "master") endif() - get_property(git_remote_name TARGET ${name} PROPERTY _EP_GIT_REMOTE_NAME) + + get_property(git_remote_name + TARGET ${name} + PROPERTY _EP_GIT_REMOTE_NAME + ) if(NOT git_remote_name) set(git_remote_name "origin") endif() set(git_init_submodules TRUE) - get_property(git_submodules_set TARGET ${name} PROPERTY _EP_GIT_SUBMODULES SET) + get_property(git_submodules_set + TARGET ${name} + PROPERTY _EP_GIT_SUBMODULES + SET + ) if(git_submodules_set) - get_property(git_submodules TARGET ${name} PROPERTY _EP_GIT_SUBMODULES) + get_property(git_submodules + TARGET ${name} + PROPERTY _EP_GIT_SUBMODULES + ) if(git_submodules STREQUAL "" AND _EP_CMP0097 STREQUAL "NEW") set(git_init_submodules FALSE) endif() endif() - get_property(git_update_strategy TARGET ${name} PROPERTY _EP_GIT_REMOTE_UPDATE_STRATEGY) + get_property(git_update_strategy + TARGET ${name} + PROPERTY _EP_GIT_REMOTE_UPDATE_STRATEGY + ) if(NOT git_update_strategy) set(git_update_strategy "${CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY}") endif() @@ -3028,14 +3313,26 @@ function(_ep_add_update_command name) endif() set(strategies CHECKOUT REBASE REBASE_CHECKOUT) if(NOT git_update_strategy IN_LIST strategies) - message(FATAL_ERROR "'${git_update_strategy}' is not one of the supported strategies: ${strategies}") + message(FATAL_ERROR + "'${git_update_strategy}' is not one of the supported strategies: " + "${strategies}" + ) endif() _ep_get_git_submodules_recurse(git_submodules_recurse) - _ep_write_gitupdate_script(${tmp_dir}/${name}-gitupdate.cmake - ${GIT_EXECUTABLE} ${git_tag} ${git_remote_name} ${git_init_submodules} "${git_submodules_recurse}" "${git_submodules}" ${git_repository} ${work_dir} ${git_update_strategy} - ) + _ep_write_gitupdate_script( + "${tmp_dir}/${name}-gitupdate.cmake" + "${GIT_EXECUTABLE}" + "${git_tag}" + "${git_remote_name}" + "${git_init_submodules}" + "${git_submodules_recurse}" + "${git_submodules}" + "${git_repository}" + "${work_dir}" + "${git_update_strategy}" + ) set(cmd ${CMAKE_COMMAND} -P ${tmp_dir}/${name}-gitupdate.cmake) set(always 1) elseif(hg_repository) @@ -3044,32 +3341,48 @@ function(_ep_add_update_command name) endif() set(work_dir ${source_dir}) set(comment "Performing update step (hg pull) for '${name}'") - get_property(hg_tag TARGET ${name} PROPERTY _EP_HG_TAG) + + get_property(hg_tag + TARGET ${name} + PROPERTY _EP_HG_TAG + ) if(NOT hg_tag) set(hg_tag "tip") endif() + if("${HG_VERSION_STRING}" STREQUAL "2.1") - message(WARNING "Mercurial 2.1 does not distinguish an empty pull from a failed pull: - http://mercurial.selenic.com/wiki/UpgradeNotes#A2.1.1:_revert_pull_return_code_change.2C_compile_issue_on_OS_X + set(notesAnchor + "#A2.1.1:_revert_pull_return_code_change.2C_compile_issue_on_OS_X" + ) + message(WARNING +"Mercurial 2.1 does not distinguish an empty pull from a failed pull: + http://mercurial.selenic.com/wiki/UpgradeNotes${notesAnchor} http://thread.gmane.org/gmane.comp.version-control.mercurial.devel/47656 Update to Mercurial >= 2.1.1. ") endif() - set(cmd ${HG_EXECUTABLE} pull + + set(cmd + ${HG_EXECUTABLE} pull COMMAND ${HG_EXECUTABLE} update ${hg_tag} - ) + ) set(always 1) endif() - get_property(log TARGET ${name} PROPERTY _EP_LOG_UPDATE) + get_property(log + TARGET ${name} + PROPERTY _EP_LOG_UPDATE + ) if(log) set(log LOG 1) else() set(log "") endif() - get_property(uses_terminal TARGET ${name} PROPERTY - _EP_USES_TERMINAL_UPDATE) + get_property(uses_terminal + TARGET ${name} + PROPERTY _EP_USES_TERMINAL_UPDATE + ) if(uses_terminal) set(uses_terminal USES_TERMINAL 1) else() @@ -3091,7 +3404,7 @@ Update to Mercurial >= 2.1.1. DEPENDEES download ${log} ${uses_terminal} - )" + )" ) endfunction() @@ -3109,13 +3422,26 @@ function(_ep_add_patch_command name) set(work_dir ${source_dir}) endif() - get_property(log TARGET ${name} PROPERTY _EP_LOG_PATCH) + get_property(log + TARGET ${name} + PROPERTY _EP_LOG_PATCH + ) if(log) set(log LOG 1) else() set(log "") endif() + get_property(uses_terminal + TARGET ${name} + PROPERTY _EP_USES_TERMINAL_PATCH + ) + if(uses_terminal) + set(uses_terminal USES_TERMINAL 1) + else() + set(uses_terminal "") + endif() + _ep_get_update_disconnected(update_disconnected ${name}) if(update_disconnected) set(patch_dep download) @@ -3134,18 +3460,28 @@ function(_ep_add_patch_command name) WORKING_DIRECTORY \${work_dir} DEPENDEES \${patch_dep} ${log} - )" + ${uses_terminal} + )" ) endfunction() function(_ep_get_file_deps var name) set(file_deps) - get_property(deps TARGET ${name} PROPERTY _EP_DEPENDS) + get_property(deps + TARGET ${name} + PROPERTY _EP_DEPENDS + ) foreach(dep IN LISTS deps) - get_property(dep_type TARGET ${dep} PROPERTY TYPE) + get_property(dep_type + TARGET ${dep} + PROPERTY TYPE + ) if(dep_type STREQUAL "UTILITY") - get_property(is_ep TARGET ${dep} PROPERTY _EP_IS_EXTERNAL_PROJECT) + get_property(is_ep + TARGET ${dep} + PROPERTY _EP_IS_EXTERNAL_PROJECT + ) if(is_ep) _ep_get_step_stampfile(${dep} "done" done_stamp_file) list(APPEND file_deps ${done_stamp_file}) @@ -3157,9 +3493,16 @@ function(_ep_get_file_deps var name) endfunction() function(_ep_extract_configure_command var name) - get_property(cmd_set TARGET ${name} PROPERTY _EP_CONFIGURE_COMMAND SET) + get_property(cmd_set + TARGET ${name} + PROPERTY _EP_CONFIGURE_COMMAND + SET + ) if(cmd_set) - get_property(cmd TARGET ${name} PROPERTY _EP_CONFIGURE_COMMAND) + get_property(cmd + TARGET ${name} + PROPERTY _EP_CONFIGURE_COMMAND + ) else() get_target_property(cmake_command ${name} _EP_CMAKE_COMMAND) if(cmake_command) @@ -3168,13 +3511,22 @@ function(_ep_extract_configure_command var name) set(cmd "${CMAKE_COMMAND}") endif() - get_property(cmake_args TARGET ${name} PROPERTY _EP_CMAKE_ARGS) + get_property(cmake_args + TARGET ${name} + PROPERTY _EP_CMAKE_ARGS + ) list(APPEND cmd ${cmake_args}) # If there are any CMAKE_CACHE_ARGS or CMAKE_CACHE_DEFAULT_ARGS, # write an initial cache and use it - get_property(cmake_cache_args TARGET ${name} PROPERTY _EP_CMAKE_CACHE_ARGS) - get_property(cmake_cache_default_args TARGET ${name} PROPERTY _EP_CMAKE_CACHE_DEFAULT_ARGS) + get_property(cmake_cache_args + TARGET ${name} + PROPERTY _EP_CMAKE_CACHE_ARGS + ) + get_property(cmake_cache_default_args + TARGET ${name} + PROPERTY _EP_CMAKE_CACHE_DEFAULT_ARGS + ) set(has_cmake_cache_args 0) if(NOT "${cmake_cache_args}" STREQUAL "") @@ -3186,10 +3538,18 @@ function(_ep_extract_configure_command var name) set(has_cmake_cache_default_args 1) endif() - get_target_property(cmake_generator ${name} _EP_CMAKE_GENERATOR) - get_target_property(cmake_generator_instance ${name} _EP_CMAKE_GENERATOR_INSTANCE) - get_target_property(cmake_generator_platform ${name} _EP_CMAKE_GENERATOR_PLATFORM) - get_target_property(cmake_generator_toolset ${name} _EP_CMAKE_GENERATOR_TOOLSET) + get_target_property(cmake_generator ${name} + _EP_CMAKE_GENERATOR + ) + get_target_property(cmake_generator_instance ${name} + _EP_CMAKE_GENERATOR_INSTANCE + ) + get_target_property(cmake_generator_platform ${name} + _EP_CMAKE_GENERATOR_PLATFORM + ) + get_target_property(cmake_generator_toolset ${name} + _EP_CMAKE_GENERATOR_TOOLSET + ) if(cmake_generator) list(APPEND cmd "-G${cmake_generator}") if(cmake_generator_platform) @@ -3199,7 +3559,9 @@ function(_ep_extract_configure_command var name) list(APPEND cmd "-T${cmake_generator_toolset}") endif() if(cmake_generator_instance) - list(APPEND cmd "-DCMAKE_GENERATOR_INSTANCE:INTERNAL=${cmake_generator_instance}") + list(APPEND cmd + "-DCMAKE_GENERATOR_INSTANCE:INTERNAL=${cmake_generator_instance}" + ) endif() else() if(CMAKE_EXTRA_GENERATOR) @@ -3208,49 +3570,72 @@ function(_ep_extract_configure_command var name) list(APPEND cmd "-G${CMAKE_GENERATOR}") if("${CMAKE_GENERATOR}" MATCHES "Green Hills MULTI") set(has_cmake_cache_default_args 1) - set(cmake_cache_default_args ${cmake_cache_default_args} + list(APPEND cmake_cache_default_args "-DGHS_TARGET_PLATFORM:STRING=${GHS_TARGET_PLATFORM}" "-DGHS_PRIMARY_TARGET:STRING=${GHS_PRIMARY_TARGET}" "-DGHS_TOOLSET_ROOT:STRING=${GHS_TOOLSET_ROOT}" "-DGHS_OS_ROOT:STRING=${GHS_OS_ROOT}" "-DGHS_OS_DIR:STRING=${GHS_OS_DIR}" - "-DGHS_BSP_NAME:STRING=${GHS_BSP_NAME}") + "-DGHS_BSP_NAME:STRING=${GHS_BSP_NAME}" + ) endif() endif() if(cmake_generator_platform) - message(FATAL_ERROR "Option CMAKE_GENERATOR_PLATFORM not allowed without CMAKE_GENERATOR.") + message(FATAL_ERROR + "Option CMAKE_GENERATOR_PLATFORM not allowed without " + "CMAKE_GENERATOR." + ) endif() if(CMAKE_GENERATOR_PLATFORM) list(APPEND cmd "-A${CMAKE_GENERATOR_PLATFORM}") endif() if(cmake_generator_toolset) - message(FATAL_ERROR "Option CMAKE_GENERATOR_TOOLSET not allowed without CMAKE_GENERATOR.") + message(FATAL_ERROR + "Option CMAKE_GENERATOR_TOOLSET not allowed without CMAKE_GENERATOR." + ) endif() if(CMAKE_GENERATOR_TOOLSET) list(APPEND cmd "-T${CMAKE_GENERATOR_TOOLSET}") endif() if(cmake_generator_instance) - message(FATAL_ERROR "Option CMAKE_GENERATOR_INSTANCE not allowed without CMAKE_GENERATOR.") + message(FATAL_ERROR + "Option CMAKE_GENERATOR_INSTANCE not allowed without CMAKE_GENERATOR." + ) endif() if(CMAKE_GENERATOR_INSTANCE) - list(APPEND cmd "-DCMAKE_GENERATOR_INSTANCE:INTERNAL=${CMAKE_GENERATOR_INSTANCE}") + list(APPEND cmd + "-DCMAKE_GENERATOR_INSTANCE:INTERNAL=${CMAKE_GENERATOR_INSTANCE}" + ) endif() endif() if(has_cmake_cache_args OR has_cmake_cache_default_args) set(_ep_cache_args_script "<TMP_DIR>/${name}-cache-$<CONFIG>.cmake") if(has_cmake_cache_args) - _ep_command_line_to_initial_cache(script_initial_cache_force "${cmake_cache_args}" 1) + _ep_command_line_to_initial_cache( + script_initial_cache_force + "${cmake_cache_args}" + 1 + ) endif() if(has_cmake_cache_default_args) - _ep_command_line_to_initial_cache(script_initial_cache_default "${cmake_cache_default_args}" 0) + _ep_command_line_to_initial_cache( + script_initial_cache_default + "${cmake_cache_default_args}" + 0 + ) endif() - _ep_write_initial_cache(${name} "${_ep_cache_args_script}" "${script_initial_cache_force}${script_initial_cache_default}") + _ep_write_initial_cache( + ${name} + "${_ep_cache_args_script}" + "${script_initial_cache_force}${script_initial_cache_default}" + ) list(APPEND cmd "-C${_ep_cache_args_script}") _ep_replace_location_tags(${name} _ep_cache_args_script) set(_ep_cache_args_script "${_ep_cache_args_script}" - PARENT_SCOPE) + PARENT_SCOPE + ) endif() list(APPEND cmd "<SOURCE_DIR><SOURCE_SUBDIR>") @@ -3264,8 +3649,10 @@ function(_ep_add_configure_command name) ExternalProject_Get_Property(${name} binary_dir tmp_dir) set(file_deps) - get_property(configure_handled_by_build TARGET ${name} - PROPERTY _EP_CONFIGURE_HANDLED_BY_BUILD) + get_property(configure_handled_by_build + TARGET ${name} + PROPERTY _EP_CONFIGURE_HANDLED_BY_BUILD + ) if(NOT configure_handled_by_build) # Depend on other external projects (file-level) _ep_get_file_deps(file_deps ${name}) @@ -3277,22 +3664,28 @@ function(_ep_add_configure_command name) # used, cmake args or cmake generator) then re-run the configure step. # Fixes issue https://gitlab.kitware.com/cmake/cmake/-/issues/10258 # - if(NOT EXISTS ${tmp_dir}/${name}-cfgcmd.txt.in) - file(WRITE ${tmp_dir}/${name}-cfgcmd.txt.in "cmd='\@cmd\@'\n") - endif() - configure_file(${tmp_dir}/${name}-cfgcmd.txt.in ${tmp_dir}/${name}-cfgcmd.txt) + configure_file( + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/cfgcmd.txt.in + ${tmp_dir}/${name}-cfgcmd.txt + @ONLY + ) list(APPEND file_deps ${tmp_dir}/${name}-cfgcmd.txt) list(APPEND file_deps ${_ep_cache_args_script}) - get_property(log TARGET ${name} PROPERTY _EP_LOG_CONFIGURE) + get_property(log + TARGET ${name} + PROPERTY _EP_LOG_CONFIGURE + ) if(log) set(log LOG 1) else() set(log "") endif() - get_property(uses_terminal TARGET ${name} PROPERTY - _EP_USES_TERMINAL_CONFIGURE) + get_property(uses_terminal + TARGET ${name} + PROPERTY _EP_USES_TERMINAL_CONFIGURE + ) if(uses_terminal) set(uses_terminal USES_TERMINAL 1) else() @@ -3312,7 +3705,7 @@ function(_ep_add_configure_command name) DEPENDS \${file_deps} ${log} ${uses_terminal} - )" + )" ) endfunction() @@ -3321,43 +3714,63 @@ function(_ep_add_build_command name) ExternalProject_Get_Property(${name} binary_dir) set(file_deps) - get_property(configure_handled_by_build TARGET ${name} - PROPERTY _EP_CONFIGURE_HANDLED_BY_BUILD) + get_property(configure_handled_by_build + TARGET ${name} + PROPERTY _EP_CONFIGURE_HANDLED_BY_BUILD + ) if(configure_handled_by_build) # Depend on other external projects (file-level) _ep_get_file_deps(file_deps ${name}) endif() - get_property(cmd_set TARGET ${name} PROPERTY _EP_BUILD_COMMAND SET) + get_property(cmd_set + TARGET ${name} + PROPERTY _EP_BUILD_COMMAND + SET + ) if(cmd_set) - get_property(cmd TARGET ${name} PROPERTY _EP_BUILD_COMMAND) + get_property(cmd + TARGET ${name} + PROPERTY _EP_BUILD_COMMAND + ) else() _ep_get_build_command(${name} BUILD cmd) endif() - get_property(log TARGET ${name} PROPERTY _EP_LOG_BUILD) + get_property(log + TARGET ${name} + PROPERTY _EP_LOG_BUILD + ) if(log) set(log LOG 1) else() set(log "") endif() - get_property(uses_terminal TARGET ${name} PROPERTY - _EP_USES_TERMINAL_BUILD) + get_property(uses_terminal + TARGET ${name} + PROPERTY _EP_USES_TERMINAL_BUILD + ) if(uses_terminal) set(uses_terminal USES_TERMINAL 1) else() set(uses_terminal "") endif() - get_property(build_always TARGET ${name} PROPERTY _EP_BUILD_ALWAYS) + get_property(build_always + TARGET ${name} + PROPERTY _EP_BUILD_ALWAYS + ) if(build_always) set(always 1) else() set(always 0) endif() - get_property(build_byproducts TARGET ${name} PROPERTY _EP_BUILD_BYPRODUCTS) + get_property(build_byproducts + TARGET ${name} + PROPERTY _EP_BUILD_BYPRODUCTS + ) set(__cmdQuoted) foreach(__item IN LISTS cmd) @@ -3374,7 +3787,7 @@ function(_ep_add_build_command name) ALWAYS \${always} ${log} ${uses_terminal} - )" + )" ) endfunction() @@ -3382,22 +3795,34 @@ endfunction() function(_ep_add_install_command name) ExternalProject_Get_Property(${name} binary_dir) - get_property(cmd_set TARGET ${name} PROPERTY _EP_INSTALL_COMMAND SET) + get_property(cmd_set + TARGET ${name} + PROPERTY _EP_INSTALL_COMMAND + SET + ) if(cmd_set) - get_property(cmd TARGET ${name} PROPERTY _EP_INSTALL_COMMAND) + get_property(cmd + TARGET ${name} + PROPERTY _EP_INSTALL_COMMAND + ) else() _ep_get_build_command(${name} INSTALL cmd) endif() - get_property(log TARGET ${name} PROPERTY _EP_LOG_INSTALL) + get_property(log + TARGET ${name} + PROPERTY _EP_LOG_INSTALL + ) if(log) set(log LOG 1) else() set(log "") endif() - get_property(uses_terminal TARGET ${name} PROPERTY - _EP_USES_TERMINAL_INSTALL) + get_property(uses_terminal + TARGET ${name} + PROPERTY _EP_USES_TERMINAL_INSTALL + ) if(uses_terminal) set(uses_terminal USES_TERMINAL 1) else() @@ -3416,7 +3841,7 @@ function(_ep_add_install_command name) DEPENDEES build ${log} ${uses_terminal} - )" + )" ) endfunction() @@ -3434,7 +3859,10 @@ function(_ep_add_test_command name) # if(cmd_set OR before OR after OR exclude) if(cmd_set) - get_property(cmd TARGET ${name} PROPERTY _EP_TEST_COMMAND) + get_property(cmd + TARGET ${name} + PROPERTY _EP_TEST_COMMAND + ) else() _ep_get_build_command(${name} TEST cmd) endif() @@ -3457,15 +3885,20 @@ function(_ep_add_test_command name) set(exclude_args "") endif() - get_property(log TARGET ${name} PROPERTY _EP_LOG_TEST) + get_property(log + TARGET ${name} + PROPERTY _EP_LOG_TEST + ) if(log) set(log LOG 1) else() set(log "") endif() - get_property(uses_terminal TARGET ${name} PROPERTY - _EP_USES_TERMINAL_TEST) + get_property(uses_terminal + TARGET ${name} + PROPERTY _EP_USES_TERMINAL_TEST + ) if(uses_terminal) set(uses_terminal USES_TERMINAL 1) else() @@ -3486,7 +3919,7 @@ function(_ep_add_test_command name) ${exclude_args} ${log} ${uses_terminal} - )" + )" ) endif() endfunction() @@ -3495,11 +3928,12 @@ endfunction() function(ExternalProject_Add name) cmake_policy(GET CMP0097 _EP_CMP0097 PARENT_SCOPE # undocumented, do not use outside of CMake - ) + ) cmake_policy(GET CMP0114 cmp0114 PARENT_SCOPE # undocumented, do not use outside of CMake - ) - if(CMAKE_XCODE_BUILD_SYSTEM VERSION_GREATER_EQUAL 12 AND NOT cmp0114 STREQUAL "NEW") + ) + if(CMAKE_XCODE_BUILD_SYSTEM VERSION_GREATER_EQUAL 12 AND + NOT cmp0114 STREQUAL "NEW") message(AUTHOR_WARNING "Policy CMP0114 is not set to NEW. " "In order to support the Xcode \"new build system\", " @@ -3508,11 +3942,14 @@ function(ExternalProject_Add name) "Since CMake is generating for the Xcode \"new build system\", " "ExternalProject_Add will use policy CMP0114's NEW behavior anyway, " "but the generated build system may not match what the project intends." - ) + ) set(cmp0114 "NEW") endif() + cmake_policy(GET CMP0135 _EP_CMP0135 + PARENT_SCOPE # undocumented, do not use outside of CMake + ) - _ep_get_configuration_subdir_suffix(cfgdir) + _ep_get_configuration_subdir_genex(cfgdir) # Add a custom target for the external project. set(cmf_dir ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles) @@ -3529,11 +3966,12 @@ function(ExternalProject_Add name) # argument was passed, we explicitly set it for the target. add_custom_target(${name} ALL DEPENDS ${complete_stamp_file}) cmake_policy(POP) - set_property(TARGET ${name} PROPERTY _EP_IS_EXTERNAL_PROJECT 1) - set_property(TARGET ${name} PROPERTY LABELS ${name}) - set_property(TARGET ${name} PROPERTY FOLDER "ExternalProjectTargets/${name}") - - set_property(TARGET ${name} PROPERTY _EP_CMP0114 "${cmp0114}") + set_target_properties(${name} PROPERTIES + _EP_IS_EXTERNAL_PROJECT 1 + LABELS ${name} + FOLDER "ExternalProjectTargets/${name}" + _EP_CMP0114 "${cmp0114}" + ) set(keywords # @@ -3556,6 +3994,7 @@ function(ExternalProject_Add name) URL_HASH URL_MD5 DOWNLOAD_NAME + DOWNLOAD_EXTRACT_TIMESTAMP DOWNLOAD_NO_EXTRACT DOWNLOAD_NO_PROGRESS TIMEOUT @@ -3648,6 +4087,7 @@ function(ExternalProject_Add name) # USES_TERMINAL_DOWNLOAD USES_TERMINAL_UPDATE + USES_TERMINAL_PATCH USES_TERMINAL_CONFIGURE USES_TERMINAL_BUILD USES_TERMINAL_INSTALL @@ -3664,13 +4104,22 @@ function(ExternalProject_Add name) # LIST_SEPARATOR ) - _ep_parse_arguments(ExternalProject_Add "${keywords}" ${name} _EP_ "${ARGN}") + _ep_parse_arguments( + ExternalProject_Add + "${keywords}" + ${name} + _EP_ + "${ARGN}" + ) _ep_set_directories(${name}) _ep_get_step_stampfile(${name} "done" done_stamp_file) _ep_get_step_stampfile(${name} "install" install_stamp_file) # Set the EXCLUDE_FROM_ALL target property if required. - get_property(exclude_from_all TARGET ${name} PROPERTY _EP_EXCLUDE_FROM_ALL) + get_property(exclude_from_all + TARGET ${name} + PROPERTY _EP_EXCLUDE_FROM_ALL + ) if(exclude_from_all) set_property(TARGET ${name} PROPERTY EXCLUDE_FROM_ALL TRUE) endif() @@ -3697,11 +4146,13 @@ function(ExternalProject_Add name) COMMAND ${CMAKE_COMMAND} -E touch ${done_stamp_file} DEPENDS ${install_stamp_file} VERBATIM - ) - + ) # Depend on other external projects (target-level). - get_property(deps TARGET ${name} PROPERTY _EP_DEPENDS) + get_property(deps + TARGET ${name} + PROPERTY _EP_DEPENDS + ) foreach(arg IN LISTS deps) add_dependencies(${name} ${arg}) endforeach() diff --git a/Modules/ExternalProject/RepositoryInfo.txt.in b/Modules/ExternalProject/RepositoryInfo.txt.in new file mode 100644 index 0000000..b81850f --- /dev/null +++ b/Modules/ExternalProject/RepositoryInfo.txt.in @@ -0,0 +1,9 @@ +# This is a generated file and its contents are an internal implementation detail. +# The download step will be re-executed if anything in this file changes. +# No other meaning or use of this file is supported. + +method=@method@ +command=@cmd@ +source_dir=@source_dir@ +work_dir=@work_dir@ +@extra_repo_info@ diff --git a/Modules/ExternalProject/cfgcmd.txt.in b/Modules/ExternalProject/cfgcmd.txt.in new file mode 100644 index 0000000..b3f09ef --- /dev/null +++ b/Modules/ExternalProject/cfgcmd.txt.in @@ -0,0 +1 @@ +cmd='@cmd@' diff --git a/Modules/ExternalProject-download.cmake.in b/Modules/ExternalProject/download.cmake.in index ff8c659..ff8c659 100644 --- a/Modules/ExternalProject-download.cmake.in +++ b/Modules/ExternalProject/download.cmake.in diff --git a/Modules/ExternalProject/extractfile.cmake.in b/Modules/ExternalProject/extractfile.cmake.in new file mode 100644 index 0000000..984565b --- /dev/null +++ b/Modules/ExternalProject/extractfile.cmake.in @@ -0,0 +1,65 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.5) + +# Make file names absolute: +# +get_filename_component(filename "@filename@" ABSOLUTE) +get_filename_component(directory "@directory@" ABSOLUTE) + +message(STATUS "extracting... + src='${filename}' + dst='${directory}'" +) + +if(NOT EXISTS "${filename}") + message(FATAL_ERROR "File to extract does not exist: '${filename}'") +endif() + +# Prepare a space for extracting: +# +set(i 1234) +while(EXISTS "${directory}/../ex-@name@${i}") + math(EXPR i "${i} + 1") +endwhile() +set(ut_dir "${directory}/../ex-@name@${i}") +file(MAKE_DIRECTORY "${ut_dir}") + +# Extract it: +# +message(STATUS "extracting... [tar @args@]") +execute_process(COMMAND ${CMAKE_COMMAND} -E tar @args@ ${filename} @options@ + WORKING_DIRECTORY ${ut_dir} + RESULT_VARIABLE rv +) + +if(NOT rv EQUAL 0) + message(STATUS "extracting... [error clean up]") + file(REMOVE_RECURSE "${ut_dir}") + message(FATAL_ERROR "Extract of '${filename}' failed") +endif() + +# Analyze what came out of the tar file: +# +message(STATUS "extracting... [analysis]") +file(GLOB contents "${ut_dir}/*") +list(REMOVE_ITEM contents "${ut_dir}/.DS_Store") +list(LENGTH contents n) +if(NOT n EQUAL 1 OR NOT IS_DIRECTORY "${contents}") + set(contents "${ut_dir}") +endif() + +# Move "the one" directory to the final directory: +# +message(STATUS "extracting... [rename]") +file(REMOVE_RECURSE ${directory}) +get_filename_component(contents ${contents} ABSOLUTE) +file(RENAME ${contents} ${directory}) + +# Clean up: +# +message(STATUS "extracting... [clean up]") +file(REMOVE_RECURSE "${ut_dir}") + +message(STATUS "extracting... done") diff --git a/Modules/ExternalProject/gitclone.cmake.in b/Modules/ExternalProject/gitclone.cmake.in new file mode 100644 index 0000000..3312171 --- /dev/null +++ b/Modules/ExternalProject/gitclone.cmake.in @@ -0,0 +1,73 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.5) + +if(EXISTS "@gitclone_stampfile@" AND EXISTS "@gitclone_infofile@" AND + "@gitclone_stampfile@" IS_NEWER_THAN "@gitclone_infofile@") + message(STATUS + "Avoiding repeated git clone, stamp file is up to date: " + "'@gitclone_stampfile@'" + ) + return() +endif() + +execute_process( + COMMAND ${CMAKE_COMMAND} -E rm -rf "@source_dir@" + RESULT_VARIABLE error_code +) +if(error_code) + message(FATAL_ERROR "Failed to remove directory: '@source_dir@'") +endif() + +# try the clone 3 times in case there is an odd git clone issue +set(error_code 1) +set(number_of_tries 0) +while(error_code AND number_of_tries LESS 3) + execute_process( + COMMAND "@git_EXECUTABLE@" @git_options@ + clone @git_clone_options@ "@git_repository@" "@src_name@" + WORKING_DIRECTORY "@work_dir@" + RESULT_VARIABLE error_code + ) + math(EXPR number_of_tries "${number_of_tries} + 1") +endwhile() +if(number_of_tries GREATER 1) + message(STATUS "Had to git clone more than once: ${number_of_tries} times.") +endif() +if(error_code) + message(FATAL_ERROR "Failed to clone repository: '@git_repository@'") +endif() + +execute_process( + COMMAND "@git_EXECUTABLE@" @git_options@ + checkout "@git_tag@" @git_checkout_explicit--@ + WORKING_DIRECTORY "@work_dir@/@src_name@" + RESULT_VARIABLE error_code +) +if(error_code) + message(FATAL_ERROR "Failed to checkout tag: '@git_tag@'") +endif() + +set(init_submodules @init_submodules@) +if(init_submodules) + execute_process( + COMMAND "@git_EXECUTABLE@" @git_options@ + submodule update @git_submodules_recurse@ --init @git_submodules@ + WORKING_DIRECTORY "@work_dir@/@src_name@" + RESULT_VARIABLE error_code + ) +endif() +if(error_code) + message(FATAL_ERROR "Failed to update submodules in: '@work_dir@/@src_name@'") +endif() + +# Complete success, update the script-last-run stamp file: +# +execute_process( + COMMAND ${CMAKE_COMMAND} -E copy "@gitclone_infofile@" "@gitclone_stampfile@" + RESULT_VARIABLE error_code +) +if(error_code) + message(FATAL_ERROR "Failed to copy script-last-run stamp file: '@gitclone_stampfile@'") +endif() diff --git a/Modules/ExternalProject-gitupdate.cmake.in b/Modules/ExternalProject/gitupdate.cmake.in index 0de2372..7896f62 100644 --- a/Modules/ExternalProject-gitupdate.cmake.in +++ b/Modules/ExternalProject/gitupdate.cmake.in @@ -128,7 +128,7 @@ if(git_update_strategy MATCHES "^REBASE(_CHECKOUT)?$") else() execute_process( - COMMAND "@git_EXECUTABLE@" for-each-ref "--format='%(upstream:short)'" "${current_branch}" + COMMAND "@git_EXECUTABLE@" for-each-ref "--format=%(upstream:short)" "${current_branch}" WORKING_DIRECTORY "@work_dir@" OUTPUT_VARIABLE upstream_branch OUTPUT_STRIP_TRAILING_WHITESPACE diff --git a/Modules/ExternalProject/hgclone.cmake.in b/Modules/ExternalProject/hgclone.cmake.in new file mode 100644 index 0000000..e2b55ba --- /dev/null +++ b/Modules/ExternalProject/hgclone.cmake.in @@ -0,0 +1,49 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.5) + +if(EXISTS "@hgclone_stampfile@" AND EXISTS "@hgclone_infofile@" AND + "@hgclone_stampfile@" IS_NEWER_THAN "@hgclone_infofile@") + message(STATUS + "Avoiding repeated hg clone, stamp file is up to date: " + "'@hgclone_stampfile@'" + ) + return() +endif() + +execute_process( + COMMAND ${CMAKE_COMMAND} -E rm -rf "@source_dir@" + RESULT_VARIABLE error_code +) +if(error_code) + message(FATAL_ERROR "Failed to remove directory: '@source_dir@'") +endif() + +execute_process( + COMMAND "@hg_EXECUTABLE@" clone -U "@hg_repository@" "@src_name@" + WORKING_DIRECTORY "@work_dir@" + RESULT_VARIABLE error_code +) +if(error_code) + message(FATAL_ERROR "Failed to clone repository: '@hg_repository@'") +endif() + +execute_process( + COMMAND "@hg_EXECUTABLE@" update @hg_tag@ + WORKING_DIRECTORY "@work_dir@/@src_name@" + RESULT_VARIABLE error_code +) +if(error_code) + message(FATAL_ERROR "Failed to checkout tag: '@hg_tag@'") +endif() + +# Complete success, update the script-last-run stamp file: +# +execute_process( + COMMAND ${CMAKE_COMMAND} -E copy "@hgclone_infofile@" "@hgclone_stampfile@" + RESULT_VARIABLE error_code +) +if(error_code) + message(FATAL_ERROR "Failed to copy script-last-run stamp file: '@hgclone_stampfile@'") +endif() diff --git a/Modules/ExternalProject/mkdirs.cmake.in b/Modules/ExternalProject/mkdirs.cmake.in new file mode 100644 index 0000000..bb835cf --- /dev/null +++ b/Modules/ExternalProject/mkdirs.cmake.in @@ -0,0 +1,22 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.5) + +file(MAKE_DIRECTORY + "@source_dir@" + "@binary_dir@" + "@install_dir@" + "@tmp_dir@" + "@stamp_dir@" + "@download_dir@" + "@log_dir@" +) + +set(configSubDirs @CMAKE_CONFIGURATION_TYPES@) +foreach(subDir IN LISTS configSubDirs) + file(MAKE_DIRECTORY "@stamp_dir@/${subDir}") +endforeach() +if(cfgdir) + file(MAKE_DIRECTORY "@stamp_dir@${cfgdir}") # cfgdir has leading slash +endif() diff --git a/Modules/ExternalProject-verify.cmake.in b/Modules/ExternalProject/verify.cmake.in index c06da4e..c06da4e 100644 --- a/Modules/ExternalProject-verify.cmake.in +++ b/Modules/ExternalProject/verify.cmake.in diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index be75689..df40c85 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -11,6 +11,12 @@ FetchContent .. contents:: +.. note:: The :guide:`Using Dependencies Guide` provides a high-level + introduction to this general topic. It provides a broader overview of + where the ``FetchContent`` module fits into the bigger picture, + including its relationship to the :command:`find_package` command. + The guide is recommended pre-reading before moving on to the details below. + Overview ^^^^^^^^ @@ -43,7 +49,7 @@ dependencies and then ensuring they are populated with a separate call: URL_HASH MD5=5588a7b18261c20068beabfb4f530b87 ) - FetchContent_MakeAvailable(googletest secret_sauce) + FetchContent_MakeAvailable(googletest myCompanyIcons) The :command:`FetchContent_MakeAvailable` command ensures the named dependencies have been populated, either by an earlier call or by populating @@ -102,7 +108,12 @@ Commands .. code-block:: cmake - FetchContent_Declare(<name> <contentOptions>...) + FetchContent_Declare( + <name> + <contentOptions>... + [OVERRIDE_FIND_PACKAGE | + FIND_PACKAGE_ARGS args...] + ) The ``FetchContent_Declare()`` function records the options that describe how to populate the specified content. If such details have already @@ -169,6 +180,55 @@ Commands they do for :command:`ExternalProject_Add`. Previously, these variables were ignored by the ``FetchContent`` module. + .. versionadded:: 3.24 + + ``FIND_PACKAGE_ARGS`` + This option is for scenarios where the + :command:`FetchContent_MakeAvailable` command may first try a call to + :command:`find_package` to satisfy the dependency for ``<name>``. + By default, such a call would be simply ``find_package(<name>)``, but + ``FIND_PACKAGE_ARGS`` can be used to provide additional arguments to be + appended after the ``<name>``. ``FIND_PACKAGE_ARGS`` can also be given + with nothing after it, which indicates that :command:`find_package` can + still be called if :variable:`FETCHCONTENT_TRY_FIND_PACKAGE_MODE` is + set to ``OPT_IN`` or is not set. + + Everything after the ``FIND_PACKAGE_ARGS`` keyword is appended to the + :command:`find_package` call, so all other ``<contentOptions>`` must + come before the ``FIND_PACKAGE_ARGS`` keyword. If the + :variable:`CMAKE_FIND_PACKAGE_TARGETS_GLOBAL` variable is set to true + at the time ``FetchContent_Declare()`` is called, a ``GLOBAL`` keyword + will be appended to the :command:`find_package` arguments if it was + not already specified. It will also be appended if + ``FIND_PACKAGE_ARGS`` was not given, but + :variable:`FETCHCONTENT_TRY_FIND_PACKAGE_MODE` was set to ``ALWAYS``. + + ``OVERRIDE_FIND_PACKAGE`` cannot be used when ``FIND_PACKAGE_ARGS`` is + given. + + :ref:`dependency_providers` discusses another way that + :command:`FetchContent_MakeAvailable` calls can be redirected. + ``FIND_PACKAGE_ARGS`` is intended for project control, whereas + dependency providers allow users to override project behavior. + + ``OVERRIDE_FIND_PACKAGE`` + When a ``FetchContent_Declare(<name> ...)`` call includes this option, + subsequent calls to ``find_package(<name> ...)`` will ensure that + ``FetchContent_MakeAvailable(<name>)`` has been called, then use the + config package files in the :variable:`CMAKE_FIND_PACKAGE_REDIRECTS_DIR` + directory (which are usually created by ``FetchContent_MakeAvailable()``). + This effectively makes :command:`FetchContent_MakeAvailable` override + :command:`find_package` for the named dependency, allowing the former to + satisfy the package requirements of the latter. ``FIND_PACKAGE_ARGS`` + cannot be used when ``OVERRIDE_FIND_PACKAGE`` is given. + + If a :ref:`dependency provider <dependency_providers>` has been set + and the project calls :command:`find_package` for the ``<name>`` + dependency, ``OVERRIDE_FIND_PACKAGE`` will not prevent the provider + from seeing that call. Dependency providers always have the opportunity + to intercept any direct call to :command:`find_package`, except if that + call contains the ``BYPASS_PROVIDER`` option. + .. command:: FetchContent_MakeAvailable .. versionadded:: 3.14 @@ -177,9 +237,45 @@ Commands FetchContent_MakeAvailable(<name1> [<name2>...]) - This command ensures that each of the named dependencies are populated and - potentially added to the build by the time it returns. It iterates over - the list, and for each dependency, the following logic is applied: + This command ensures that each of the named dependencies are made available + to the project by the time it returns. There must have been a call to + :command:`FetchContent_Declare` for each dependency, and the first such call + will control how that dependency will be made available, as described below. + + If ``<lowercaseName>_SOURCE_DIR`` is not set: + + * .. versionadded:: 3.24 + + If a :ref:`dependency provider <dependency_providers>` is set, call the + provider's command with ``FETCHCONTENT_MAKEAVAILABLE_SERIAL`` as the + first argument, followed by the arguments of the first call to + :command:`FetchContent_Declare` for ``<name>``. If ``SOURCE_DIR`` or + ``BINARY_DIR`` were not part of the original declared arguments, they + will be added with their default values. + If :variable:`FETCHCONTENT_TRY_FIND_PACKAGE_MODE` was set to ``NEVER`` + when the details were declared, any ``FIND_PACKAGE_ARGS`` will be + omitted. The ``OVERRIDE_FIND_PACKAGE`` keyword is also always omitted. + If the provider fulfilled the request, ``FetchContent_MakeAvailable()`` + will consider that dependency handled, skip the remaining steps below + and move on to the next dependency in the list. + + * .. versionadded:: 3.24 + + If permitted, :command:`find_package(<name> [<args>...]) <find_package>` + will be called, where ``<args>...`` may be provided by the + ``FIND_PACKAGE_ARGS`` option in :command:`FetchContent_Declare`. + The value of the :variable:`FETCHCONTENT_TRY_FIND_PACKAGE_MODE` variable + at the time :command:`FetchContent_Declare` was called determines whether + ``FetchContent_MakeAvailable()`` can call :command:`find_package`. + If the :variable:`CMAKE_FIND_PACKAGE_TARGETS_GLOBAL` variable is set to + true when ``FetchContent_MakeAvailable()`` is called, it still affects + any imported targets created when that in turn calls + :command:`find_package`, even if that variable was false when the + corresponding details were declared. + + If the dependency was not satisfied by a provider or a + :command:`find_package` call, ``FetchContent_MakeAvailable()`` then uses + the following logic to make the dependency available: * If the dependency has already been populated earlier in this run, set the ``<lowercaseName>_POPULATED``, ``<lowercaseName>_SOURCE_DIR`` and @@ -194,6 +290,37 @@ Commands the declared details and use content provided at the specified location instead. + * .. versionadded:: 3.24 + + Ensure the :variable:`CMAKE_FIND_PACKAGE_REDIRECTS_DIR` directory + contains a ``<lowercaseName>-config.cmake`` and a + ``<lowercaseName>-config-version.cmake`` file (or equivalently + ``<name>Config.cmake`` and ``<name>ConfigVersion.cmake``). + The directory that the :variable:`CMAKE_FIND_PACKAGE_REDIRECTS_DIR` + variable points to is cleared at the start of every CMake run. + If no config file exists when :command:`FetchContent_Populate` returns, + a minimal one will be written which :command:`includes <include>` any + ``<lowercaseName>-extra.cmake`` or ``<name>Extra.cmake`` file with the + ``OPTIONAL`` flag (so the files can be missing and won't generate a + warning). Similarly, if no config version file exists, a very simple + one will be written which sets ``PACKAGE_VERSION_COMPATIBLE`` to true. + CMake cannot automatically determine an arbitrary dependency's version, + so it cannot set ``PACKAGE_VERSION`` or ``PACKAGE_VERSION_EXACT``. + When a dependency is pulled in via :command:`add_subdirectory` in the + next step, it may choose to overwrite the generated config version file + in :variable:`CMAKE_FIND_PACKAGE_REDIRECTS_DIR` with one that also sets + ``PACKAGE_VERSION``, and if appropriate, ``PACKAGE_VERSION_EXACT``. + The dependency may also write a ``<lowercaseName>-extra.cmake`` or + ``<name>Extra.cmake`` file to perform custom processing or define any + variables that their normal (installed) package config file would + otherwise usually define (many projects don't do any custom processing + or set any variables and therefore have no need to do this). + If required, the main project can write these files instead if the + dependency project doesn't do so. This allows the main project to + add missing details from older dependencies that haven't or can't be + updated to support this functionality. + See `Integrating With find_package()`_ for examples. + * If the top directory of the populated content contains a ``CMakeLists.txt`` file, call :command:`add_subdirectory` to add it to the main build. It is not an error for there to be no ``CMakeLists.txt`` file, which @@ -389,7 +516,7 @@ Commands When using saved content details, a call to :command:`FetchContent_MakeAvailable` or :command:`FetchContent_Populate` records information in global properties which can be queried at any time. - This information includes the source and binary directories associated with + This information may include the source and binary directories associated with the content and also whether or not the content population has been processed during the current configure run. @@ -409,6 +536,8 @@ Commands set the same variables as a call to :command:`FetchContent_MakeAvailable(name) <FetchContent_MakeAvailable>` or :command:`FetchContent_Populate(name) <FetchContent_Populate>`. + Note that the ``SOURCE_DIR`` and ``BINARY_DIR`` values can be empty if the + call is fulfilled by a :ref:`dependency provider <dependency_providers>`. This command is rarely needed when using :command:`FetchContent_MakeAvailable`. It is more commonly used as part of @@ -432,13 +561,42 @@ Commands add_subdirectory(${depname_SOURCE_DIR} ${depname_BINARY_DIR}) endif() +.. command:: FetchContent_SetPopulated + + .. versionadded:: 3.24 + + .. note:: + This command should only be called by + :ref:`dependency providers <dependency_providers>`. Calling it in any + other context is unsupported and future CMake versions may halt with a + fatal error in such cases. + + .. code-block:: cmake + + FetchContent_SetPopulated( + <name> + [SOURCE_DIR <srcDir>] + [BINARY_DIR <binDir>] + ) + + If a provider command fulfills a ``FETCHCONTENT_MAKEAVAILABLE_SERIAL`` + request, it must call this function before returning. The ``SOURCE_DIR`` + and ``BINARY_DIR`` arguments can be used to specify the values that + :command:`FetchContent_GetProperties` should return for its corresponding + arguments. Only provide ``SOURCE_DIR`` and ``BINARY_DIR`` if they have + the same meaning as if they had been populated by the built-in + :command:`FetchContent_MakeAvailable` implementation. + + Variables ^^^^^^^^^ A number of cache variables can influence the behavior where details from a :command:`FetchContent_Declare` call are used to populate content. -The variables are all intended for the developer to customize behavior and -should not normally be set by the project. + +.. note:: + All of these variables are intended for the developer to customize behavior. + They should not normally be set by the project. .. variable:: FETCHCONTENT_BASE_DIR @@ -481,8 +639,53 @@ should not normally be set by the project. This can speed up the configure stage, but not as much as :variable:`FETCHCONTENT_FULLY_DISCONNECTED`. It is ``OFF`` by default. -In addition to the above cache variables, the following cache variables are -also defined for each content name: +.. variable:: FETCHCONTENT_TRY_FIND_PACKAGE_MODE + + .. versionadded:: 3.24 + + This variable modifies the details that :command:`FetchContent_Declare` + records for a given dependency. While it ultimately controls the behavior + of :command:`FetchContent_MakeAvailable`, it is the variable's value when + :command:`FetchContent_Declare` is called that gets used. It makes no + difference what the variable is set to when + :command:`FetchContent_MakeAvailable` is called. Since the variable should + only be set by the user and not by projects directly, it will typically have + the same value throughout anyway, so this distinction is not usually + noticeable. + + ``FETCHCONTENT_TRY_FIND_PACKAGE_MODE`` ultimately controls whether + :command:`FetchContent_MakeAvailable` is allowed to call + :command:`find_package` to satisfy a dependency. The variable can be set + to one of the following values: + + ``OPT_IN`` + :command:`FetchContent_MakeAvailable` will only call + :command:`find_package` if the :command:`FetchContent_Declare` call + included a ``FIND_PACKAGE_ARGS`` keyword. This is also the default + behavior if ``FETCHCONTENT_TRY_FIND_PACKAGE_MODE`` is not set. + + ``ALWAYS`` + :command:`find_package` can be called by + :command:`FetchContent_MakeAvailable` regardless of whether the + :command:`FetchContent_Declare` call included a ``FIND_PACKAGE_ARGS`` + keyword or not. If no ``FIND_PACKAGE_ARGS`` keyword was given, the + behavior will be as though ``FIND_PACKAGE_ARGS`` had been provided, + with no additional arguments after it. + + ``NEVER`` + :command:`FetchContent_MakeAvailable` will not call + :command:`find_package`. Any ``FIND_PACKAGE_ARGS`` given to the + :command:`FetchContent_Declare` call will be ignored. + + As a special case, if the :variable:`FETCHCONTENT_SOURCE_DIR_<uppercaseName>` + variable has a non-empty value for a dependency, it is assumed that the + user is overriding all other methods of making that dependency available. + ``FETCHCONTENT_TRY_FIND_PACKAGE_MODE`` will have no effect on that + dependency and :command:`FetchContent_MakeAvailable` will not try to call + :command:`find_package` for it. + +In addition to the above, the following variables are also defined for each +content name: .. variable:: FETCHCONTENT_SOURCE_DIR_<uppercaseName> @@ -511,6 +714,9 @@ also defined for each content name: Examples ^^^^^^^^ +Typical Case +"""""""""""" + This first fairly straightforward example ensures that some popular testing frameworks are available to the main build: @@ -532,6 +738,135 @@ frameworks are available to the main build: # Catch2 will be available to the rest of the build FetchContent_MakeAvailable(googletest Catch2) +.. _FetchContent-find_package-integration-examples: + +Integrating With find_package() +""""""""""""""""""""""""""""""" + +For the previous example, if the user wanted to try to find ``googletest`` +and ``Catch2`` via :command:`find_package` first before trying to download +and build them from source, they could set the +:variable:`FETCHCONTENT_TRY_FIND_PACKAGE_MODE` variable to ``ALWAYS``. +This would also affect any other calls to :command:`FetchContent_Declare` +throughout the project, which might not be acceptable. The behavior can be +enabled for just these two dependencies instead by adding ``FIND_PACKAGE_ARGS`` +to the declared details and leaving +:variable:`FETCHCONTENT_TRY_FIND_PACKAGE_MODE` unset, or set to ``OPT_IN``: + +.. code-block:: cmake + + include(FetchContent) + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0 + FIND_PACKAGE_ARGS NAMES gtest + ) + FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG de6fe184a9ac1a06895cdd1c9b437f0a0bdf14ad # v2.13.4 + FIND_PACKAGE_ARGS + ) + + # This will try calling find_package() first for both dependencies + FetchContent_MakeAvailable(googletest Catch2) + +For ``Catch2``, no additional arguments to :command:`find_package` are needed, +so no additional arguments are provided after the ``FIND_PACKAGE_ARGS`` +keyword. For ``googletest``, its package is more commonly called ``gtest``, +so arguments are added to support it being found by that name. + +If the user wanted to disable :command:`FetchContent_MakeAvailable` from +calling :command:`find_package` for any dependency, even if it provided +``FIND_PACKAGE_ARGS`` in its declared details, they could set +:variable:`FETCHCONTENT_TRY_FIND_PACKAGE_MODE` to ``NEVER``. + +If the project wanted to indicate that these two dependencies should be +downloaded and built from source and that :command:`find_package` calls +should be redirected to use the built dependencies, the +``OVERRIDE_FIND_PACKAGE`` option should be used when declaring the content +details: + +.. code-block:: cmake + + include(FetchContent) + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0 + OVERRIDE_FIND_PACKAGE + ) + FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG de6fe184a9ac1a06895cdd1c9b437f0a0bdf14ad # v2.13.4 + OVERRIDE_FIND_PACKAGE + ) + + # The following will automatically forward through to FetchContent_MakeAvailable() + find_package(googletest) + find_package(Catch2) + +CMake provides a FindGTest module which defines some variables that older +projects may use instead of linking to the imported targets. To support +those cases, we can provide an extras file. In keeping with the +"first to define, wins" philosophy of ``FetchContent``, we only write out +that file if something else hasn't already done so. + +.. code-block:: cmake + + FetchContent_MakeAvailable(googletest) + + if(NOT EXISTS ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/googletest-extras.cmake AND + NOT EXISTS ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/googletestExtras.cmake) + file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/googletest-extras.cmake + [=[ + if("${GTEST_LIBRARIES}" STREQUAL "" AND TARGET GTest::gtest) + set(GTEST_LIBRARIES GTest::gtest) + endif() + if("${GTEST_MAIN_LIBRARIES}" STREQUAL "" AND TARGET GTest::gtest_main) + set(GTEST_MAIN_LIBRARIES GTest::gtest_main) + endif() + if("${GTEST_BOTH_LIBRARIES}" STREQUAL "") + set(GTEST_BOTH_LIBRARIES ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES}) + endif() + ]=]) + endif() + +Projects will also likely be using ``find_package(GTest)`` rather than +``find_package(googletest)``, but it is possible to make use of the +:variable:`CMAKE_FIND_PACKAGE_REDIRECTS_DIR` area to pull in the latter as +a dependency of the former. This is likely to be sufficient to satisfy +a typical ``find_package(GTest)`` call. + +.. code-block:: cmake + + FetchContent_MakeAvailable(googletest) + + if(NOT EXISTS ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/gtest-config.cmake AND + NOT EXISTS ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/GTestConfig.cmake) + file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/gtest-config.cmake + [=[ + include(CMakeFindDependencyMacro) + find_dependency(googletest) + ]=]) + endif() + + if(NOT EXISTS ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/gtest-config-version.cmake AND + NOT EXISTS ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/GTestConfigVersion.cmake) + file(WRITE ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/gtest-config-version.cmake + [=[ + include(${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/googletest-config-version.cmake OPTIONAL) + if(NOT PACKAGE_VERSION_COMPATIBLE) + include(${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/googletestConfigVersion.cmake OPTIONAL) + endif() + ]=]) + endif() + +Overriding Where To Find CMakeLists.txt +""""""""""""""""""""""""""""""""""""""" + If the sub-project's ``CMakeLists.txt`` file is not at the top level of its source tree, the ``SOURCE_SUBDIR`` option can be used to tell ``FetchContent`` where to find it. The following example shows how to use that option and @@ -550,6 +885,9 @@ it into the main build: set(protobuf_BUILD_TESTS OFF) FetchContent_MakeAvailable(protobuf) +Complex Dependency Hierarchies +"""""""""""""""""""""""""""""" + In more complex project hierarchies, the dependency relationships can be more complicated. Consider a hierarchy where ``projA`` is the top level project and it depends directly on projects ``projB`` and ``projC``. Both ``projB`` and @@ -647,6 +985,8 @@ A few key points should be noted in the above: child projects. This saves repeating the same thing at each level of the project hierarchy unnecessarily. +Populating Content Without Adding It To The Build +""""""""""""""""""""""""""""""""""""""""""""""""" Projects don't always need to add the populated content to the build. Sometimes the project just wants to make the downloaded content available at @@ -682,7 +1022,10 @@ named toolchain file relative to the build directory. Because the tarball has already been downloaded and unpacked by then, the toolchain file will be in place, even the very first time that ``cmake`` is run in the build directory. -Lastly, the following example demonstrates how one might download and unpack a +Populating Content In CMake Script Mode +""""""""""""""""""""""""""""""""""""""" + +This last example demonstrates how one might download and unpack a firmware tarball using CMake's :manual:`script mode <cmake(1)>`. The call to :command:`FetchContent_Populate` specifies all the content details and the unpacked firmware will be placed in a ``firmware`` directory below the @@ -722,19 +1065,89 @@ current working directory. function(__FetchContent_declareDetails contentName) string(TOLOWER ${contentName} contentNameLower) - set(propertyName "_FetchContent_${contentNameLower}_savedDetails") - get_property(alreadyDefined GLOBAL PROPERTY ${propertyName} DEFINED) - if(NOT alreadyDefined) - define_property(GLOBAL PROPERTY ${propertyName} - BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" - FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + set(savedDetailsPropertyName "_FetchContent_${contentNameLower}_savedDetails") + get_property(alreadyDefined GLOBAL PROPERTY ${savedDetailsPropertyName} DEFINED) + if(alreadyDefined) + return() + endif() + + if("${FETCHCONTENT_TRY_FIND_PACKAGE_MODE}" STREQUAL "ALWAYS") + set(__tryFindPackage TRUE) + set(__tryFindPackageAllowed TRUE) + elseif("${FETCHCONTENT_TRY_FIND_PACKAGE_MODE}" STREQUAL "NEVER") + set(__tryFindPackage FALSE) + set(__tryFindPackageAllowed FALSE) + elseif("${FETCHCONTENT_TRY_FIND_PACKAGE_MODE}" STREQUAL "OPT_IN" OR + NOT DEFINED FETCHCONTENT_TRY_FIND_PACKAGE_MODE) + set(__tryFindPackage FALSE) + set(__tryFindPackageAllowed TRUE) + else() + message(FATAL_ERROR + "Unsupported value for FETCHCONTENT_TRY_FIND_PACKAGE_MODE: " + "${FETCHCONTENT_TRY_FIND_PACKAGE_MODE}" ) - set(__cmdArgs) - foreach(__item IN LISTS ARGN) - string(APPEND __cmdArgs " [==[${__item}]==]") - endforeach() + endif() + + set(__cmdArgs) + set(__findPackageArgs) + set(__sawQuietKeyword NO) + set(__sawGlobalKeyword NO) + foreach(__item IN LISTS ARGN) + if(DEFINED __findPackageArgs) + # All remaining args are for find_package() + string(APPEND __findPackageArgs " [==[${__item}]==]") + if(__item STREQUAL "QUIET") + set(__sawQuietKeyword YES) + elseif(__item STREQUAL "GLOBAL") + set(__sawGlobalKeyword YES) + endif() + continue() + endif() + + # Still processing non-find_package() args + if(__item STREQUAL "FIND_PACKAGE_ARGS") + if(__tryFindPackageAllowed) + set(__tryFindPackage TRUE) + endif() + # All arguments after this keyword are for find_package(). Define the + # variable but with an empty value initially. This allows us to check + # at the start of the loop whether to store remaining items in this + # variable or not. Note that there could be no more args, which is still + # a valid case because we automatically provide ${contentName} as the + # package name and there may not need to be any further arguments. + set(__findPackageArgs "") + continue() # Don't store this item + elseif(__item STREQUAL "OVERRIDE_FIND_PACKAGE") + set(__tryFindPackageAllowed FALSE) + # Define a separate dedicated property for find_package() to check + # in its implementation. This will be a placeholder until FetchContent + # actually does the population. After that, we will have created a + # stand-in config file that find_package() will pick up instead. + set(propertyName "_FetchContent_${contentNameLower}_override_find_package") + define_property(GLOBAL PROPERTY ${propertyName}) + set_property(GLOBAL PROPERTY ${propertyName} TRUE) + endif() + + string(APPEND __cmdArgs " [==[${__item}]==]") + endforeach() + + define_property(GLOBAL PROPERTY ${savedDetailsPropertyName}) + cmake_language(EVAL CODE + "set_property(GLOBAL PROPERTY ${savedDetailsPropertyName} ${__cmdArgs})" + ) + + if(__tryFindPackage AND __tryFindPackageAllowed) + set(propertyName "_FetchContent_${contentNameLower}_find_package_args") + define_property(GLOBAL PROPERTY ${propertyName}) + if(NOT __sawQuietKeyword) + list(INSERT __findPackageArgs 0 QUIET) + endif() + if(CMAKE_FIND_PACKAGE_TARGETS_GLOBAL AND NOT __sawGlobalKeyword) + list(APPEND __findPackageArgs GLOBAL) + endif() cmake_language(EVAL CODE - "set_property(GLOBAL PROPERTY ${propertyName} ${__cmdArgs})") + "set_property(GLOBAL PROPERTY ${propertyName} ${__findPackageArgs})" + ) endif() endfunction() @@ -763,15 +1176,43 @@ endfunction() # SOURCE_DIR and BUILD_DIR. function(FetchContent_Declare contentName) + # Always check this even if we won't save these details. + # This helps projects catch errors earlier. + # Avoid using if(... IN_LIST ...) so we don't have to alter policy settings + list(FIND ARGN OVERRIDE_FIND_PACKAGE index_OVERRIDE_FIND_PACKAGE) + list(FIND ARGN FIND_PACKAGE_ARGS index_FIND_PACKAGE_ARGS) + if(index_OVERRIDE_FIND_PACKAGE GREATER_EQUAL 0 AND + index_FIND_PACKAGE_ARGS GREATER_EQUAL 0) + message(FATAL_ERROR + "Cannot specify both OVERRIDE_FIND_PACKAGE and FIND_PACKAGE_ARGS " + "when declaring details for ${contentName}" + ) + endif() + set(options "") - set(oneValueArgs SVN_REPOSITORY) + set(oneValueArgs + SVN_REPOSITORY + DOWNLOAD_NO_EXTRACT + DOWNLOAD_EXTRACT_TIMESTAMP + URL + BINARY_DIR + SOURCE_DIR + ) set(multiValueArgs "") cmake_parse_arguments(PARSE_ARGV 1 ARG "${options}" "${oneValueArgs}" "${multiValueArgs}") - unset(srcDirSuffix) - unset(svnRepoArgs) + string(TOLOWER ${contentName} contentNameLower) + + if(NOT ARG_BINARY_DIR) + set(ARG_BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build") + endif() + + if(NOT ARG_SOURCE_DIR) + set(ARG_SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src") + endif() + if(ARG_SVN_REPOSITORY) # Add a hash of the svn repository URL to the source dir. This works # around the problem where if the URL changes, the download would @@ -781,25 +1222,55 @@ function(FetchContent_Declare contentName) # problem on windows due to path length limits). string(SHA1 urlSHA ${ARG_SVN_REPOSITORY}) string(SUBSTRING ${urlSHA} 0 7 urlSHA) - set(srcDirSuffix "-${urlSHA}") - set(svnRepoArgs SVN_REPOSITORY ${ARG_SVN_REPOSITORY}) + string(APPEND ARG_SOURCE_DIR "-${urlSHA}") endif() - string(TOLOWER ${contentName} contentNameLower) + # The ExternalProject_Add() call in the sub-build won't see the CMP0135 + # policy setting of our caller. Work out if that policy will be needed and + # explicitly set the relevant option if not already provided. The condition + # here is essentially an abbreviated version of the logic in + # ExternalProject's _ep_add_download_command() function. + if(ARG_URL AND + NOT IS_DIRECTORY "${ARG_URL}" AND + NOT ARG_DOWNLOAD_NO_EXTRACT AND + NOT DEFINED ARG_DOWNLOAD_EXTRACT_TIMESTAMP) + cmake_policy(GET CMP0135 _FETCHCONTENT_CMP0135 + PARENT_SCOPE # undocumented, do not use outside of CMake + ) + if(_FETCHCONTENT_CMP0135 STREQUAL "") + message(AUTHOR_WARNING + "The DOWNLOAD_EXTRACT_TIMESTAMP option was not given and policy " + "CMP0135 is not set. The policy's OLD behavior will be used. " + "When using a URL download, the timestamps of extracted files " + "should preferably be that of the time of extraction, otherwise " + "code that depends on the extracted contents might not be " + "rebuilt if the URL changes. The OLD behavior preserves the " + "timestamps from the archive instead, but this is usually not " + "what you want. Update your project to the NEW behavior or " + "specify the DOWNLOAD_EXTRACT_TIMESTAMP option with a value of " + "true to avoid this robustness issue." + ) + set(ARG_DOWNLOAD_EXTRACT_TIMESTAMP TRUE) + elseif(_FETCHCONTENT_CMP0135 STREQUAL "NEW") + set(ARG_DOWNLOAD_EXTRACT_TIMESTAMP FALSE) + else() + set(ARG_DOWNLOAD_EXTRACT_TIMESTAMP TRUE) + endif() + endif() + + # Add back in the keyword args we pulled out and potentially tweaked/added + foreach(key IN LISTS oneValueArgs) + if(DEFINED ARG_${key}) + list(PREPEND ARG_UNPARSED_ARGUMENTS ${key} "${ARG_${key}}") + endif() + endforeach() set(__argsQuoted) foreach(__item IN LISTS ARG_UNPARSED_ARGUMENTS) string(APPEND __argsQuoted " [==[${__item}]==]") endforeach() - cmake_language(EVAL CODE " - __FetchContent_declareDetails( - ${contentNameLower} - SOURCE_DIR \"${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src${srcDirSuffix}\" - BINARY_DIR \"${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build\" - \${svnRepoArgs} - # List these last so they can override things we set above - ${__argsQuoted} - )" + cmake_language(EVAL CODE + "__FetchContent_declareDetails(${contentNameLower} ${__argsQuoted})" ) endfunction() @@ -810,35 +1281,43 @@ endfunction() # The setter also records the source and binary dirs used. #======================================================================= -# Internal use, projects must not call this directly. It is -# intended for use by the FetchContent_Populate() function to -# record when FetchContent_Populate() is called for a particular -# content name. -function(__FetchContent_setPopulated contentName sourceDir binaryDir) +# Semi-internal use. Projects must not call this directly. Dependency +# providers must call it if they satisfy a request made with the +# FETCHCONTENT_MAKEAVAILABLE_SERIAL method (that is the only permitted +# place to call it outside of the FetchContent module). +function(FetchContent_SetPopulated contentName) + + cmake_parse_arguments(PARSE_ARGV 1 arg + "" + "SOURCE_DIR;BINARY_DIR" + "" + ) + if(NOT "${arg_UNPARSED_ARGUMENTS}" STREQUAL "") + message(FATAL_ERROR "Unsupported arguments: ${arg_UNPARSED_ARGUMENTS}") + endif() string(TOLOWER ${contentName} contentNameLower) set(prefix "_FetchContent_${contentNameLower}") set(propertyName "${prefix}_sourceDir") - define_property(GLOBAL PROPERTY ${propertyName} - BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" - FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" - ) - set_property(GLOBAL PROPERTY ${propertyName} ${sourceDir}) + define_property(GLOBAL PROPERTY ${propertyName}) + if("${arg_SOURCE_DIR}" STREQUAL "") + # Don't discard a previously provided SOURCE_DIR + get_property(arg_SOURCE_DIR GLOBAL PROPERTY ${propertyName}) + endif() + set_property(GLOBAL PROPERTY ${propertyName} "${arg_SOURCE_DIR}") set(propertyName "${prefix}_binaryDir") - define_property(GLOBAL PROPERTY ${propertyName} - BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" - FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" - ) - set_property(GLOBAL PROPERTY ${propertyName} ${binaryDir}) + define_property(GLOBAL PROPERTY ${propertyName}) + if("${arg_BINARY_DIR}" STREQUAL "") + # Don't discard a previously provided BINARY_DIR + get_property(arg_BINARY_DIR GLOBAL PROPERTY ${propertyName}) + endif() + set_property(GLOBAL PROPERTY ${propertyName} "${arg_BINARY_DIR}") set(propertyName "${prefix}_populated") - define_property(GLOBAL PROPERTY ${propertyName} - BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" - FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" - ) - set_property(GLOBAL PROPERTY ${propertyName} True) + define_property(GLOBAL PROPERTY ${propertyName}) + set_property(GLOBAL PROPERTY ${propertyName} TRUE) endfunction() @@ -920,13 +1399,14 @@ function(__FetchContent_directPopulate contentName) BUILD_COMMAND INSTALL_COMMAND TEST_COMMAND - # We force both of these to be ON since we are always executing serially + # We force these to be ON since we are always executing serially # and we want all steps to have access to the terminal in case they # need input from the command line (e.g. ask for a private key password) # or they want to provide timely progress. We silently absorb and # discard these if they are set by the caller. USES_TERMINAL_DOWNLOAD USES_TERMINAL_UPDATE + USES_TERMINAL_PATCH ) set(multiValueArgs "") @@ -1015,6 +1495,14 @@ ExternalProject_Add_Step(${contentName}-populate copyfile list(APPEND subCMakeOpts "-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}") endif() + # Override the sub-build's configuration types for multi-config generators. + # This ensures we are not affected by any custom setting from the project + # and can always request a known configuration further below. + get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + if(is_multi_config) + list(APPEND subCMakeOpts "-DCMAKE_CONFIGURATION_TYPES:STRING=Debug") + endif() + else() # Likely we've been invoked via CMake's script mode where no # generator is set (and hence CMAKE_MAKE_PROGRAM could not be @@ -1059,7 +1547,8 @@ set_property(GLOBAL PROPERTY _CMAKE_FindGit_GIT_EXECUTABLE_VERSION # If we've already previously done these steps, they will not cause # anything to be updated, so extra rebuilds of the project won't occur. # Make sure to pass through CMAKE_MAKE_PROGRAM in case the main project - # has this set to something not findable on the PATH. + # has this set to something not findable on the PATH. We also ensured above + # that the Debug config will be defined for multi-config generators. configure_file("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/FetchContent/CMakeLists.cmake.in" "${ARG_SUBBUILD_DIR}/CMakeLists.txt") execute_process( @@ -1075,7 +1564,7 @@ set_property(GLOBAL PROPERTY _CMAKE_FindGit_GIT_EXECUTABLE_VERSION message(FATAL_ERROR "CMake step for ${contentName} failed: ${result}") endif() execute_process( - COMMAND ${CMAKE_COMMAND} --build . + COMMAND ${CMAKE_COMMAND} --build . --config Debug RESULT_VARIABLE result ${outputOptions} WORKING_DIRECTORY "${ARG_SUBBUILD_DIR}" @@ -1133,7 +1622,16 @@ function(FetchContent_Populate contentName) # populated this content before in case the caller forgot to check. FetchContent_GetProperties(${contentName}) if(${contentNameLower}_POPULATED) - message(FATAL_ERROR "Content ${contentName} already populated in ${${contentNameLower}_SOURCE_DIR}") + if("${${contentNameLower}_SOURCE_DIR}" STREQUAL "") + message(FATAL_ERROR + "Content ${contentName} already populated by find_package() or a " + "dependency provider" + ) + else() + message(FATAL_ERROR + "Content ${contentName} already populated in ${${contentNameLower}_SOURCE_DIR}" + ) + endif() endif() __FetchContent_getSavedDetails(${contentName} contentDetails) @@ -1211,7 +1709,9 @@ function(FetchContent_Populate contentName) set(__detailsQuoted) foreach(__item IN LISTS contentDetails) - string(APPEND __detailsQuoted " [==[${__item}]==]") + if(NOT __item STREQUAL "OVERRIDE_FIND_PACKAGE") + string(APPEND __detailsQuoted " [==[${__item}]==]") + endif() endforeach() cmake_language(EVAL CODE " __FetchContent_directPopulate( @@ -1229,10 +1729,10 @@ function(FetchContent_Populate contentName) ) endif() - __FetchContent_setPopulated( + FetchContent_SetPopulated( ${contentName} - ${${contentNameLower}_SOURCE_DIR} - ${${contentNameLower}_BINARY_DIR} + SOURCE_DIR "${${contentNameLower}_SOURCE_DIR}" + BINARY_DIR "${${contentNameLower}_BINARY_DIR}" ) # Pass variables back to the caller. The variables passed back here @@ -1244,6 +1744,55 @@ function(FetchContent_Populate contentName) endfunction() +function(__FetchContent_setupFindPackageRedirection contentName) + + __FetchContent_getSavedDetails(${contentName} contentDetails) + + string(TOLOWER ${contentName} contentNameLower) + get_property(wantFindPackage GLOBAL PROPERTY + _FetchContent_${contentNameLower}_find_package_args + DEFINED + ) + + # Avoid using if(... IN_LIST ...) so we don't have to alter policy settings + list(FIND contentDetails OVERRIDE_FIND_PACKAGE indexResult) + if(NOT wantFindPackage AND indexResult EQUAL -1) + # No find_package() redirection allowed + return() + endif() + + # We write out dep-config.cmake and dep-config-version.cmake file name + # forms here because they are forced to lowercase. FetchContent + # dependency names are case-insensitive, but find_package() config files + # are only case-insensitive for the -config and -config-version forms, + # not the Config and ConfigVersion forms. + set(inFileDir ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/FetchContent) + set(configFilePrefix1 "${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/${contentName}Config") + set(configFilePrefix2 "${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/${contentNameLower}-config") + if(NOT EXISTS "${configFilePrefix1}.cmake" AND + NOT EXISTS "${configFilePrefix2}.cmake") + configure_file(${inFileDir}/package-config.cmake.in + "${configFilePrefix2}.cmake" @ONLY + ) + endif() + if(NOT EXISTS "${configFilePrefix1}Version.cmake" AND + NOT EXISTS "${configFilePrefix2}-version.cmake") + configure_file(${inFileDir}/package-config-version.cmake.in + "${configFilePrefix2}-version.cmake" @ONLY + ) + endif() + + # Now that we've created the redirected package config files, prevent + # find_package() from delegating to FetchContent and let it find these + # config files through its normal processing. + set(propertyName "${prefix}_override_find_package") + set(GLOBAL PROPERTY ${propertyName} FALSE) + set(${contentName}_DIR "${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}" + CACHE INTERNAL "Redirected by FetchContent" + ) + +endfunction() + # Arguments are assumed to be the names of dependencies that have been # declared previously and should be populated. It is not an error if # any of them have already been populated (they will just be skipped in @@ -1252,11 +1801,127 @@ endfunction() # calls will be available to the caller. macro(FetchContent_MakeAvailable) + get_property(__cmake_providerCommand GLOBAL PROPERTY + __FETCHCONTENT_MAKEAVAILABLE_SERIAL_PROVIDER + ) foreach(__cmake_contentName IN ITEMS ${ARGV}) string(TOLOWER ${__cmake_contentName} __cmake_contentNameLower) + + # If user specified FETCHCONTENT_SOURCE_DIR_... for this dependency, that + # overrides everything else and we shouldn't try to use find_package() or + # a dependency provider. + string(TOUPPER ${__cmake_contentName} __cmake_contentNameUpper) + if("${FETCHCONTENT_SOURCE_DIR_${__cmake_contentNameUpper}}" STREQUAL "") + # Dependency provider gets first opportunity, but prevent infinite + # recursion if we are called again for the same thing + if(NOT "${__cmake_providerCommand}" STREQUAL "" AND + NOT DEFINED __cmake_fcProvider_${__cmake_contentNameLower}) + message(VERBOSE + "Trying FETCHCONTENT_MAKEAVAILABLE_SERIAL dependency provider for " + "${__cmake_contentName}" + ) + # It's still valid if there are no saved details. The project may have + # been written to assume a dependency provider is always set and will + # provide dependencies without having any declared details for them. + __FetchContent_getSavedDetails(${__cmake_contentName} __cmake_contentDetails) + set(__cmake_providerArgs + "FETCHCONTENT_MAKEAVAILABLE_SERIAL" + "${__cmake_contentName}" + ) + # Empty arguments must be preserved because of things like + # GIT_SUBMODULES (see CMP0097) + foreach(__cmake_item IN LISTS __cmake_contentDetails) + string(APPEND __cmake_providerArgs " [==[${__cmake_item}]==]") + endforeach() + + # This property might be defined but empty. As long as it is defined, + # find_package() can be called. + get_property(__cmake_addfpargs GLOBAL PROPERTY + _FetchContent_${contentNameLower}_find_package_args + DEFINED + ) + if(__cmake_addfpargs) + get_property(__cmake_fpargs GLOBAL PROPERTY + _FetchContent_${contentNameLower}_find_package_args + ) + string(APPEND __cmake_providerArgs " FIND_PACKAGE_ARGS") + foreach(__cmake_item IN LISTS __cmake_fpargs) + string(APPEND __cmake_providerArgs " [==[${__cmake_item}]==]") + endforeach() + endif() + + # Calling the provider could lead to FetchContent_MakeAvailable() being + # called for a nested dependency. That nested call may occur in the + # current variable scope. We have to save and restore the variables we + # need preserved. + list(APPEND __cmake_fcCurrentVarsStack + ${__cmake_contentName} + ${__cmake_contentNameLower} + ) + + set(__cmake_fcProvider_${__cmake_contentNameLower} YES) + cmake_language(EVAL CODE "${__cmake_providerCommand}(${__cmake_providerArgs})") + unset(__cmake_fcProvider_${__cmake_contentNameLower}) + + list(POP_BACK __cmake_fcCurrentVarsStack + __cmake_contentNameLower + __cmake_contentName + ) + + unset(__cmake_providerArgs) + unset(__cmake_addfpargs) + unset(__cmake_fpargs) + unset(__cmake_item) + unset(__cmake_contentDetails) + + FetchContent_GetProperties(${__cmake_contentName}) + if(${__cmake_contentNameLower}_POPULATED) + continue() + endif() + endif() + + # Check if we've been asked to try find_package() first, even if we + # have already populated this dependency. If we previously tried to + # use find_package() for this and it succeeded, those things might + # no longer be in scope, so we have to do it again. + get_property(__cmake_haveFpArgs GLOBAL PROPERTY + _FetchContent_${__cmake_contentNameLower}_find_package_args DEFINED + ) + if(__cmake_haveFpArgs) + unset(__cmake_haveFpArgs) + message(VERBOSE "Trying find_package(${__cmake_contentName} ...) before FetchContent") + get_property(__cmake_fpArgs GLOBAL PROPERTY + _FetchContent_${__cmake_contentNameLower}_find_package_args + ) + + # This call could lead to FetchContent_MakeAvailable() being called for + # a nested dependency and it may occur in the current variable scope. + # We have to save/restore the variables we need to preserve. + list(APPEND __cmake_fcCurrentNameStack + ${__cmake_contentName} + ${__cmake_contentNameLower} + ) + find_package(${__cmake_contentName} ${__cmake_fpArgs}) + list(POP_BACK __cmake_fcCurrentNameStack + __cmake_contentNameLower + __cmake_contentName + ) + unset(__cmake_fpArgs) + + if(${__cmake_contentName}_FOUND) + FetchContent_SetPopulated(${__cmake_contentName}) + FetchContent_GetProperties(${__cmake_contentName}) + continue() + endif() + endif() + else() + unset(__cmake_haveFpArgs) + endif() + FetchContent_GetProperties(${__cmake_contentName}) if(NOT ${__cmake_contentNameLower}_POPULATED) FetchContent_Populate(${__cmake_contentName}) + __FetchContent_setupFindPackageRedirection(${__cmake_contentName}) # Only try to call add_subdirectory() if the populated content # can be treated that way. Protecting the call with the check @@ -1282,13 +1947,15 @@ macro(FetchContent_MakeAvailable) endif() unset(__cmake_srcdir) + unset(__cmake_contentDetails) + unset(__cmake_arg_SOURCE_SUBDIR) endif() endforeach() # clear local variables to prevent leaking into the caller's scope unset(__cmake_contentName) unset(__cmake_contentNameLower) - unset(__cmake_contentDetails) - unset(__cmake_arg_SOURCE_SUBDIR) + unset(__cmake_contentNameUpper) + unset(__cmake_providerCommand) endmacro() diff --git a/Modules/FetchContent/CMakeLists.cmake.in b/Modules/FetchContent/CMakeLists.cmake.in index 5ebb12f..d94b0f4 100644 --- a/Modules/FetchContent/CMakeLists.cmake.in +++ b/Modules/FetchContent/CMakeLists.cmake.in @@ -22,6 +22,7 @@ ExternalProject_Add(${contentName}-populate TEST_COMMAND "" USES_TERMINAL_DOWNLOAD YES USES_TERMINAL_UPDATE YES + USES_TERMINAL_PATCH YES ) @__FETCHCONTENT_COPY_FILE@ diff --git a/Modules/FetchContent/package-config-version.cmake.in b/Modules/FetchContent/package-config-version.cmake.in new file mode 100644 index 0000000..7f19094 --- /dev/null +++ b/Modules/FetchContent/package-config-version.cmake.in @@ -0,0 +1,5 @@ +# Automatically generated by CMake's FetchContent module. +# Do not edit this file, it will be regenerated every time CMake runs. + +# Version not available, assuming it is compatible +set(PACKAGE_VERSION_COMPATIBLE TRUE) diff --git a/Modules/FetchContent/package-config.cmake.in b/Modules/FetchContent/package-config.cmake.in new file mode 100644 index 0000000..c3b64c9 --- /dev/null +++ b/Modules/FetchContent/package-config.cmake.in @@ -0,0 +1,11 @@ +# Automatically generated by CMake's FetchContent module. +# Do not edit this file, it will be regenerated every time CMake runs. + +# Projects or the dependencies themselves can provide the following files. +# The files should define any additional commands or variables that the +# dependency would normally provide but which won't be available globally +# if the dependency is brought into the build via FetchContent instead. +# For dependencies that only provide imported targets and no commands, +# these typically won't be needed. +include("${CMAKE_CURRENT_LIST_DIR}/@contentNameLower@-extra.cmake" OPTIONAL) +include("${CMAKE_CURRENT_LIST_DIR}/@contentName@Extra.cmake" OPTIONAL) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 308138f..7a381af 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -273,8 +273,8 @@ endif() include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) if(BLA_PREFER_PKGCONFIG) - find_package(PkgConfig) - pkg_check_modules(PKGC_BLAS blas) + find_package(PkgConfig QUIET) + pkg_check_modules(PKGC_BLAS QUIET blas) if(PKGC_BLAS_FOUND) set(BLAS_FOUND ${PKGC_BLAS_FOUND}) set(BLAS_LIBRARIES "${PKGC_BLAS_LINK_LIBRARIES}") @@ -437,7 +437,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") set(BLAS_mkl_END_GROUP "") endif() # Switch to GNU Fortran support layer if needed (but not on Apple, where MKL does not provide it) - if(CMAKE_Fortran_COMPILER_LOADED AND CMAKE_Fortran_COMPILER_ID STREQUAL "GNU" AND NOT APPLE) + if(CMAKE_Fortran_COMPILER_LOADED AND (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "LCC") AND NOT APPLE) set(BLAS_mkl_INTFACE "gf") set(BLAS_mkl_THREADING "gnu") set(BLAS_mkl_OMP "gomp") @@ -756,10 +756,10 @@ if(BLA_VENDOR STREQUAL "OpenBLAS" OR BLA_VENDOR STREQUAL "All") set(_threadlibs "${CMAKE_THREAD_LIBS_INIT}") if(BLA_STATIC) if (CMAKE_C_COMPILER_LOADED) - find_package(OpenMP COMPONENTS C) + find_package(OpenMP QUIET COMPONENTS C) list(PREPEND _threadlibs "${OpenMP_C_LIBRARIES}") elseif(CMAKE_CXX_COMPILER_LOADED) - find_package(OpenMP COMPONENTS CXX) + find_package(OpenMP QUIET COMPONENTS CXX) list(PREPEND _threadlibs "${OpenMP_CXX_LIBRARIES}") endif() endif() diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake index c3142d6..0f407c8 100644 --- a/Modules/FindBoost.cmake +++ b/Modules/FindBoost.cmake @@ -917,14 +917,14 @@ function(_Boost_GUESS_COMPILER_PREFIX _ret) if(NOT Boost_VERSION_STRING VERSION_LESS 1.69.0) # From GCC 5 and clang 4, versioning changes and minor becomes patch. # For those compilers, patch is exclude from compiler tag in Boost 1.69+ library naming. - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND _boost_COMPILER_VERSION_MAJOR VERSION_GREATER 4) + if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND _boost_COMPILER_VERSION_MAJOR VERSION_GREATER 4) OR CMAKE_CXX_COMPILER_ID STREQUAL "LCC") set(_boost_COMPILER_VERSION "${_boost_COMPILER_VERSION_MAJOR}") elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND _boost_COMPILER_VERSION_MAJOR VERSION_GREATER 3) set(_boost_COMPILER_VERSION "${_boost_COMPILER_VERSION_MAJOR}") endif() endif() - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "LCC") if(Boost_VERSION_STRING VERSION_LESS 1.34) set(_boost_COMPILER "-gcc") # no GCC version encoding prior to 1.34 else() @@ -1380,7 +1380,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret) set(_Boost_TIMER_DEPENDENCIES chrono) set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono atomic) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.79.0 AND NOT Boost_NO_WARN_NEW_VERSIONS) + if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.80.0 AND NOT Boost_NO_WARN_NEW_VERSIONS) message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets") endif() endif() @@ -1653,6 +1653,7 @@ else() # _Boost_COMPONENT_HEADERS. See the instructions at the top of # _Boost_COMPONENT_DEPENDENCIES. set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS} + "1.79.0" "1.79" "1.78.0" "1.78" "1.77.0" "1.77" "1.76.0" "1.76" "1.75.0" "1.75" "1.74.0" "1.74" "1.73.0" "1.73" "1.72.0" "1.72" "1.71.0" "1.71" "1.70.0" "1.70" "1.69.0" "1.69" "1.68.0" "1.68" "1.67.0" "1.67" "1.66.0" "1.66" "1.65.1" "1.65.0" "1.65" diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake index dd795f4..af5f798 100644 --- a/Modules/FindCUDA.cmake +++ b/Modules/FindCUDA.cmake @@ -926,8 +926,8 @@ mark_as_advanced(CUDA_NVCC_EXECUTABLE) if(CUDA_NVCC_EXECUTABLE AND NOT CUDA_VERSION) # Compute the version. execute_process (COMMAND ${CUDA_NVCC_EXECUTABLE} "--version" OUTPUT_VARIABLE NVCC_OUT) - string(REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\1" CUDA_VERSION_MAJOR ${NVCC_OUT}) - string(REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\2" CUDA_VERSION_MINOR ${NVCC_OUT}) + string(REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\1" CUDA_VERSION_MAJOR "${NVCC_OUT}") + string(REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\2" CUDA_VERSION_MINOR "${NVCC_OUT}") set(CUDA_VERSION "${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR}" CACHE STRING "Version of CUDA as computed from nvcc.") mark_as_advanced(CUDA_VERSION) else() diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake index d22a676..538e132 100644 --- a/Modules/FindCUDAToolkit.cmake +++ b/Modules/FindCUDAToolkit.cmake @@ -143,13 +143,11 @@ CUDA Driver Library """""""""""""""""""" The CUDA Driver library (cuda) are used by applications that use calls -such as `cuMemAlloc`, and `cuMemFree`. This is generally used by advanced - +such as `cuMemAlloc`, and `cuMemFree`. Targets Created: - ``CUDA::cuda_driver`` -- ``CUDA::cuda_driver`` .. _`cuda_toolkit_cuBLAS`: @@ -177,6 +175,7 @@ Targets Created: - ``CUDA::cufft`` - ``CUDA::cufftw`` - ``CUDA::cufft_static`` +- ``CUDA::cufft_static_nocallback`` starting in CUDA 9.2, requires CMake 3.23+ - ``CUDA::cufftw_static`` cuRAND @@ -500,12 +499,17 @@ if(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT) set(CUDAToolkit_LIBRARY_ROOT "${CMAKE_CUDA_COMPILER_LIBRARY_ROOT}") set(CUDAToolkit_BIN_DIR "${CUDAToolkit_ROOT_DIR}/bin") set(CUDAToolkit_NVCC_EXECUTABLE "${CUDAToolkit_BIN_DIR}/nvcc${CMAKE_EXECUTABLE_SUFFIX}") -else() + set(CUDAToolkit_VERSION "${CMAKE_CUDA_COMPILER_TOOLKIT_VERSION}") + if(CUDAToolkit_VERSION MATCHES [=[([0-9]+)\.([0-9]+)\.([0-9]+)]=]) + set(CUDAToolkit_VERSION_MAJOR "${CMAKE_MATCH_1}") + set(CUDAToolkit_VERSION_MINOR "${CMAKE_MATCH_2}") + set(CUDAToolkit_VERSION_PATCH "${CMAKE_MATCH_3}") + endif() +else() function(_CUDAToolkit_find_root_dir ) cmake_parse_arguments(arg "" "" "SEARCH_PATHS;FIND_FLAGS" ${ARGN}) - if(NOT CUDAToolkit_BIN_DIR) if(NOT CUDAToolkit_SENTINEL_FILE) find_program(CUDAToolkit_NVCC_EXECUTABLE @@ -688,6 +692,40 @@ else() get_filename_component(CUDAToolkit_LIBRARY_ROOT "${_CUDAToolkit_version_file}" DIRECTORY ABSOLUTE) endif() unset(_CUDAToolkit_version_file) + + if(CUDAToolkit_NVCC_EXECUTABLE AND + CMAKE_CUDA_COMPILER_VERSION AND + CUDAToolkit_NVCC_EXECUTABLE STREQUAL CMAKE_CUDA_COMPILER) + # Need to set these based off the already computed CMAKE_CUDA_COMPILER_VERSION value + # This if statement will always match, but is used to provide variables for MATCH 1,2,3... + if(CMAKE_CUDA_COMPILER_VERSION MATCHES [=[([0-9]+)\.([0-9]+)\.([0-9]+)]=]) + set(CUDAToolkit_VERSION_MAJOR "${CMAKE_MATCH_1}") + set(CUDAToolkit_VERSION_MINOR "${CMAKE_MATCH_2}") + set(CUDAToolkit_VERSION_PATCH "${CMAKE_MATCH_3}") + set(CUDAToolkit_VERSION "${CMAKE_CUDA_COMPILER_VERSION}") + endif() + elseif(CUDAToolkit_NVCC_EXECUTABLE) + # Compute the version by invoking nvcc + execute_process(COMMAND ${CUDAToolkit_NVCC_EXECUTABLE} "--version" OUTPUT_VARIABLE NVCC_OUT) + if(NVCC_OUT MATCHES [=[ V([0-9]+)\.([0-9]+)\.([0-9]+)]=]) + set(CUDAToolkit_VERSION_MAJOR "${CMAKE_MATCH_1}") + set(CUDAToolkit_VERSION_MINOR "${CMAKE_MATCH_2}") + set(CUDAToolkit_VERSION_PATCH "${CMAKE_MATCH_3}") + set(CUDAToolkit_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}") + endif() + unset(NVCC_OUT) + else() + _CUDAToolkit_find_version_file(version_file) + if(version_file) + file(READ "${version_file}" VERSION_INFO) + if(VERSION_INFO MATCHES [=[CUDA Version ([0-9]+)\.([0-9]+)\.([0-9]+)]=]) + set(CUDAToolkit_VERSION_MAJOR "${CMAKE_MATCH_1}") + set(CUDAToolkit_VERSION_MINOR "${CMAKE_MATCH_2}") + set(CUDAToolkit_VERSION_PATCH "${CMAKE_MATCH_3}") + set(CUDAToolkit_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}") + endif() + endif() + endif() endif() # Find target directory when crosscompiling. @@ -755,40 +793,6 @@ if(NOT EXISTS "${CUDAToolkit_INCLUDE_DIR}/cublas_v2.h") endif() endif() -if(CUDAToolkit_NVCC_EXECUTABLE AND - CMAKE_CUDA_COMPILER_VERSION AND - CUDAToolkit_NVCC_EXECUTABLE STREQUAL CMAKE_CUDA_COMPILER) - # Need to set these based off the already computed CMAKE_CUDA_COMPILER_VERSION value - # This if statement will always match, but is used to provide variables for MATCH 1,2,3... - if(CMAKE_CUDA_COMPILER_VERSION MATCHES [=[([0-9]+)\.([0-9]+)\.([0-9]+)]=]) - set(CUDAToolkit_VERSION_MAJOR "${CMAKE_MATCH_1}") - set(CUDAToolkit_VERSION_MINOR "${CMAKE_MATCH_2}") - set(CUDAToolkit_VERSION_PATCH "${CMAKE_MATCH_3}") - set(CUDAToolkit_VERSION "${CMAKE_CUDA_COMPILER_VERSION}") - endif() -elseif(CUDAToolkit_NVCC_EXECUTABLE) - # Compute the version by invoking nvcc - execute_process(COMMAND ${CUDAToolkit_NVCC_EXECUTABLE} "--version" OUTPUT_VARIABLE NVCC_OUT) - if(NVCC_OUT MATCHES [=[ V([0-9]+)\.([0-9]+)\.([0-9]+)]=]) - set(CUDAToolkit_VERSION_MAJOR "${CMAKE_MATCH_1}") - set(CUDAToolkit_VERSION_MINOR "${CMAKE_MATCH_2}") - set(CUDAToolkit_VERSION_PATCH "${CMAKE_MATCH_3}") - set(CUDAToolkit_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}") - endif() - unset(NVCC_OUT) -else() - _CUDAToolkit_find_version_file(version_file) - if(version_file) - file(READ "${version_file}" VERSION_INFO) - if(VERSION_INFO MATCHES [=[CUDA Version ([0-9]+)\.([0-9]+)\.([0-9]+)]=]) - set(CUDAToolkit_VERSION_MAJOR "${CMAKE_MATCH_1}") - set(CUDAToolkit_VERSION_MINOR "${CMAKE_MATCH_2}") - set(CUDAToolkit_VERSION_PATCH "${CMAKE_MATCH_3}") - set(CUDAToolkit_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}") - endif() - endif() -endif() - # Find the CUDA Runtime Library libcudart find_library(CUDA_CUDART NAMES cudart @@ -839,7 +843,7 @@ endif() if(CUDAToolkit_FOUND) function(_CUDAToolkit_find_and_add_import_lib lib_name) - cmake_parse_arguments(arg "" "" "ALT;DEPS;EXTRA_PATH_SUFFIXES" ${ARGN}) + cmake_parse_arguments(arg "" "" "ALT;DEPS;EXTRA_PATH_SUFFIXES;EXTRA_INCLUDE_DIRS" ${ARGN}) set(search_names ${lib_name} ${arg_ALT}) @@ -879,6 +883,9 @@ if(CUDAToolkit_FOUND) target_link_libraries(CUDA::${lib_name} INTERFACE CUDA::${dep}) endif() endforeach() + if(arg_EXTRA_INCLUDE_DIRS) + target_include_directories(CUDA::${lib_name} SYSTEM INTERFACE "${arg_EXTRA_INCLUDE_DIRS}") + endif() endif() endfunction() @@ -925,14 +932,41 @@ if(CUDAToolkit_FOUND) _CUDAToolkit_find_and_add_import_lib(${cuda_lib}_static DEPS culibos) endforeach() + if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 11.0.0) + # cublas depends on cublasLt + # https://docs.nvidia.com/cuda/archive/11.0/cublas/index.html#static-library + _CUDAToolkit_find_and_add_import_lib(cublas DEPS cublasLt) + _CUDAToolkit_find_and_add_import_lib(cublas_static DEPS cublasLt_static) + endif() + # cuFFTW depends on cuFFT _CUDAToolkit_find_and_add_import_lib(cufftw DEPS cufft) - _CUDAToolkit_find_and_add_import_lib(cufftw DEPS cufft_static) + _CUDAToolkit_find_and_add_import_lib(cufftw_static DEPS cufft_static) + if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 9.2) + _CUDAToolkit_find_and_add_import_lib(cufft_static_nocallback DEPS culibos) + endif() # cuSOLVER depends on cuBLAS, and cuSPARSE _CUDAToolkit_find_and_add_import_lib(cusolver DEPS cublas cusparse) _CUDAToolkit_find_and_add_import_lib(cusolver_static DEPS cublas_static cusparse_static culibos) + + if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 10.1.2) + # cusolver depends on liblapack_static.a starting with CUDA 10.1 update 2, + # https://docs.nvidia.com/cuda/archive/11.5.0/cusolver/index.html#static-link-lapack + _CUDAToolkit_find_and_add_import_lib(cusolver_lapack_static ALT lapack_static) # implementation detail static lib + _CUDAToolkit_find_and_add_import_lib(cusolver_static DEPS cusolver_lapack_static) + endif() + + if(CUDAToolkit_VERSION VERSION_GREATER 11.2.1) + # cusolver depends on libcusolver_metis and cublasLt + # https://docs.nvidia.com/cuda/archive/11.2.2/cusolver/index.html#link-dependency + _CUDAToolkit_find_and_add_import_lib(cusolver DEPS cublasLt) + + _CUDAToolkit_find_and_add_import_lib(cusolver_metis_static ALT metis_static) # implementation detail static lib + _CUDAToolkit_find_and_add_import_lib(cusolver_static DEPS cusolver_metis_static cublasLt_static) + endif() + # nvGRAPH depends on cuRAND, and cuSOLVER. _CUDAToolkit_find_and_add_import_lib(nvgraph DEPS curand cusolver) _CUDAToolkit_find_and_add_import_lib(nvgraph_static DEPS curand_static cusolver_static) @@ -943,12 +977,22 @@ if(CUDAToolkit_FOUND) _CUDAToolkit_find_and_add_import_lib(${cuda_lib}_static DEPS nppc_static) endforeach() - _CUDAToolkit_find_and_add_import_lib(cupti - EXTRA_PATH_SUFFIXES ../extras/CUPTI/lib64/ - ../extras/CUPTI/lib/) - _CUDAToolkit_find_and_add_import_lib(cupti_static - EXTRA_PATH_SUFFIXES ../extras/CUPTI/lib64/ - ../extras/CUPTI/lib/) + find_path(CUDAToolkit_CUPTI_INCLUDE_DIR cupti.h PATHS + "${CUDAToolkit_ROOT_DIR}/extras/CUPTI/include" + "${CUDAToolkit_INCLUDE_DIR}/../extras/CUPTI/include" + "${CUDATookit_INCLUDE_DIR}" + NO_DEFAULT_PATH) + + if(CUDAToolkit_CUPTI_INCLUDE_DIR) + _CUDAToolkit_find_and_add_import_lib(cupti + EXTRA_PATH_SUFFIXES ../extras/CUPTI/lib64/ + ../extras/CUPTI/lib/ + EXTRA_INCLUDE_DIRS "${CUDAToolkit_CUPTI_INCLUDE_DIR}") + _CUDAToolkit_find_and_add_import_lib(cupti_static + EXTRA_PATH_SUFFIXES ../extras/CUPTI/lib64/ + ../extras/CUPTI/lib/ + EXTRA_INCLUDE_DIRS "${CUDAToolkit_CUPTI_INCLUDE_DIR}") + endif() _CUDAToolkit_find_and_add_import_lib(nvrtc DEPS cuda_driver) diff --git a/Modules/FindEnvModules.cmake b/Modules/FindEnvModules.cmake index a4ac0b4..dab97ac 100644 --- a/Modules/FindEnvModules.cmake +++ b/Modules/FindEnvModules.cmake @@ -259,7 +259,7 @@ function(env_module_swap out_mod in_mod) ) if(MOD_ARGS_OUTPUT_VARIABLE) - set(${MOD_ARGS_OUTPUT_VARIABLE} "${err_var}" PARENT_SCOPE) + set(${MOD_ARGS_OUTPUT_VARIABLE} "${tmp_out}" PARENT_SCOPE) endif() if(MOD_ARGS_RESULT_VARIABLE) set(${MOD_ARGS_RESULT_VARIABLE} ${tmp_ret} PARENT_SCOPE) diff --git a/Modules/FindGLUT.cmake b/Modules/FindGLUT.cmake index 9c80ad7..320ddad 100644 --- a/Modules/FindGLUT.cmake +++ b/Modules/FindGLUT.cmake @@ -20,24 +20,48 @@ This module defines the :prop_tgt:`IMPORTED` targets: Result Variables ^^^^^^^^^^^^^^^^ -This module sets the following variables: +This module defines the following variables: -:: +``GLUT_FOUND`` + True if ``glut`` was found. - GLUT_INCLUDE_DIR, where to find GL/glut.h, etc. - GLUT_LIBRARIES, the libraries to link against - GLUT_FOUND, If false, do not try to use GLUT. +``GLUT_INCLUDE_DIRS`` + .. versionadded:: 3.23 -Also defined, but not for general use are: + Where to find GL/glut.h, etc. -:: +``GLUT_LIBRARIES`` + List of libraries for using ``glut``. - GLUT_glut_LIBRARY = the full path to the glut library. - GLUT_Xmu_LIBRARY = the full path to the Xmu library. - GLUT_Xi_LIBRARY = the full path to the Xi Library. +Cache Variables +^^^^^^^^^^^^^^^ -.. versionadded:: 3.13 - Debug and Release variants are found separately. +This module may set the following variables depending on platform. +These variables may optionally be set to help this module find the +correct files, but clients should not use these as results: + +``GLUT_INCLUDE_DIR`` + The full path to the directory containing ``GL/glut.h``, + not including ``GL/``. + +``GLUT_glut_LIBRARY`` + The full path to the glut library. + +``GLUT_Xmu_LIBRARY`` + The full path to the Xmu library. + +``GLUT_Xi_LIBRARY`` + The full path to the Xi Library. + +Obsolete Variables +^^^^^^^^^^^^^^^^^^ + +The following variables may also be provided, for backwards compatibility: + +``GLUT_INCLUDE_DIR`` + This is one of above `Cache Variables`_, but prior to CMake 3.23 was + also a result variable. Prefer to use ``GLUT_INCLUDE_DIRS`` instead + in CMake 3.23 and above. #]=======================================================================] include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) @@ -70,11 +94,29 @@ function(_add_glut_target_simple) IMPORTED_LOCATION "${GLUT_glut_LIBRARY}") endfunction() -find_package(PkgConfig) +find_package(PkgConfig QUIET) if(PKG_CONFIG_FOUND) - pkg_check_modules(GLUT glut) + # Tell pkg-config not to strip any -I flags to make sure GLUT_INCLUDE_DIRS + # will be defined. + if(DEFINED ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS}) + set(_pkgconfig_allow_system_cflags_old "$ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS}") + else() + unset(_pkgconfig_allow_system_cflags_old) + endif() + set(ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS} 1) + pkg_check_modules(GLUT QUIET glut) + if(DEFINED _pkgconfig_allow_system_cflags_old) + set(ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS} "${_pkgconfig_allow_system_cflags_old}") + unset(_pkgconfig_allow_system_cflags_old) + else() + unset(ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS}) + endif() + if(NOT GLUT_FOUND) + pkg_check_modules(GLUT QUIET freeglut) + endif() if(GLUT_FOUND) - # In the non-pkg-config code path we only provide GLUT_INCLUDE_DIR. + # GLUT_INCLUDE_DIRS is now the official result variable, but + # older versions of CMake only provided GLUT_INCLUDE_DIR. set(GLUT_INCLUDE_DIR "${GLUT_INCLUDE_DIRS}") _add_glut_target_simple() FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLUT REQUIRED_VARS GLUT_FOUND) @@ -85,7 +127,8 @@ endif() if(WIN32) find_path( GLUT_INCLUDE_DIR NAMES GL/glut.h PATHS ${GLUT_ROOT_PATH}/include ) - find_library( GLUT_glut_LIBRARY_RELEASE NAMES glut glut32 freeglut + mark_as_advanced(GLUT_INCLUDE_DIR) + find_library( GLUT_glut_LIBRARY_RELEASE NAMES freeglut glut glut32 PATHS ${OPENGL_LIBRARY_DIR} ${GLUT_ROOT_PATH}/Release @@ -99,6 +142,7 @@ if(WIN32) select_library_configurations(GLUT_glut) elseif(APPLE) find_path(GLUT_INCLUDE_DIR glut.h ${OPENGL_LIBRARY_DIR}) + mark_as_advanced(GLUT_INCLUDE_DIR) find_library(GLUT_glut_LIBRARY GLUT DOC "GLUT library for OSX") find_library(GLUT_cocoa_LIBRARY Cocoa DOC "Cocoa framework for OSX") mark_as_advanced(GLUT_glut_LIBRARY GLUT_cocoa_LIBRARY) @@ -155,16 +199,17 @@ else() /opt/graphics/OpenGL/contrib/libglut ${_GLUT_INC_DIR} ) + mark_as_advanced(GLUT_INCLUDE_DIR) find_library( GLUT_glut_LIBRARY glut /usr/openwin/lib ${_GLUT_glut_LIB_DIR} ) + mark_as_advanced(GLUT_glut_LIBRARY) unset(_GLUT_INC_DIR) unset(_GLUT_glut_LIB_DIR) endif() -mark_as_advanced(GLUT_glut_LIBRARY) FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLUT REQUIRED_VARS GLUT_glut_LIBRARY GLUT_INCLUDE_DIR) @@ -174,6 +219,9 @@ if (GLUT_FOUND) set( GLUT_LIBRARIES ${GLUT_glut_LIBRARY} ) + set(GLUT_INCLUDE_DIRS + ${GLUT_INCLUDE_DIR} + ) foreach(v GLUT_Xmu_LIBRARY GLUT_Xi_LIBRARY GLUT_cocoa_LIBRARY) if(${v}) list(APPEND GLUT_LIBRARIES ${${v}}) @@ -183,7 +231,7 @@ if (GLUT_FOUND) if(NOT TARGET GLUT::GLUT) add_library(GLUT::GLUT UNKNOWN IMPORTED) set_target_properties(GLUT::GLUT PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${GLUT_INCLUDE_DIR}") + INTERFACE_INCLUDE_DIRECTORIES "${GLUT_INCLUDE_DIRS}") if(GLUT_glut_LIBRARY MATCHES "/([^/]+)\\.framework$") set(_glut_glut "${GLUT_glut_LIBRARY}/${CMAKE_MATCH_1}") if(EXISTS "${_glut_glut}.tbd") @@ -227,10 +275,4 @@ if (GLUT_FOUND) PROPERTY INTERFACE_LINK_LIBRARIES GLUT::Cocoa) endif() endif() - - #The following deprecated settings are for backwards compatibility with CMake1.4 - set (GLUT_LIBRARY ${GLUT_LIBRARIES}) - set (GLUT_INCLUDE_PATH ${GLUT_INCLUDE_DIR}) endif() - -mark_as_advanced(GLUT_INCLUDE_DIR) diff --git a/Modules/FindGSL.cmake b/Modules/FindGSL.cmake index 485735a..1943847 100644 --- a/Modules/FindGSL.cmake +++ b/Modules/FindGSL.cmake @@ -77,7 +77,7 @@ endif() # *NIX systems. See :module:`findpkgconfig` # This will return ``GSL_INCLUDEDIR`` and ``GSL_LIBDIR`` used below. if( GSL_USE_PKGCONFIG ) - find_package(PkgConfig) + find_package(PkgConfig QUIET) pkg_check_modules( GSL QUIET gsl ) if( EXISTS "${GSL_INCLUDEDIR}" ) diff --git a/Modules/FindGTest.cmake b/Modules/FindGTest.cmake index 8e22f79..60bb401 100644 --- a/Modules/FindGTest.cmake +++ b/Modules/FindGTest.cmake @@ -22,6 +22,14 @@ Imported targets ``GTest::gtest_main`` The Google Test ``gtest_main`` library, if found +.. versionadded:: 3.23 + +``GTest::gmock`` + The Google Mock ``gmock`` library, if found; adds Thread::Thread + automatically +``GTest::gmock_main`` + The Google Mock ``gmock_main`` library, if found + .. deprecated:: 3.20 For backwards compatibility, this module defines additionally the following deprecated :prop_tgt:`IMPORTED` targets (available since 3.5): @@ -32,7 +40,6 @@ Imported targets ``GTest::Main`` The Google Test ``gtest_main`` library, if found - Result variables ^^^^^^^^^^^^^^^^ @@ -245,15 +252,29 @@ if(MSVC AND GTEST_MSVC_SEARCH STREQUAL "MD") __gtest_find_library(GTEST_LIBRARY_DEBUG gtest-mdd gtestd) __gtest_find_library(GTEST_MAIN_LIBRARY gtest_main-md gtest_main) __gtest_find_library(GTEST_MAIN_LIBRARY_DEBUG gtest_main-mdd gtest_maind) + __gtest_find_library(GMOCK_LIBRARY gmock-md gmock) + __gtest_find_library(GMOCK_LIBRARY_DEBUG gmock-mdd gmockd) + __gtest_find_library(GMOCK_MAIN_LIBRARY gmock_main-md gmock_main) + __gtest_find_library(GMOCK_MAIN_LIBRARY_DEBUG gmock_main-mdd gmock_maind) else() __gtest_find_library(GTEST_LIBRARY gtest) __gtest_find_library(GTEST_LIBRARY_DEBUG gtestd) __gtest_find_library(GTEST_MAIN_LIBRARY gtest_main) __gtest_find_library(GTEST_MAIN_LIBRARY_DEBUG gtest_maind) + __gtest_find_library(GMOCK_LIBRARY gmock) + __gtest_find_library(GMOCK_LIBRARY_DEBUG gmockd) + __gtest_find_library(GMOCK_MAIN_LIBRARY gmock_main) + __gtest_find_library(GMOCK_MAIN_LIBRARY_DEBUG gmock_maind) endif() FIND_PACKAGE_HANDLE_STANDARD_ARGS(GTest DEFAULT_MSG GTEST_LIBRARY GTEST_INCLUDE_DIR GTEST_MAIN_LIBRARY) +if(GMOCK_LIBRARY AND GMOCK_MAIN_LIBRARY) + set(GMock_FOUND True) +else() + set(GMock_FOUND False) +endif() + if(GTest_FOUND) set(GTEST_INCLUDE_DIRS ${GTEST_INCLUDE_DIR}) __gtest_append_debugs(GTEST_LIBRARIES GTEST_LIBRARY) @@ -292,3 +313,36 @@ if(GTest_FOUND) __gtest_define_backwards_compatible_library_targets() endif() + +if(GMock_FOUND) + if(NOT TARGET GTest::gmock) + __gtest_determine_library_type(GMOCK_LIBRARY) + add_library(GTest::gmock ${GMOCK_LIBRARY_TYPE} IMPORTED) + set(_gmock_link_libraries "GTest::gtest") + if(TARGET Threads::Threads) + list(APPEND _gmock_link_libraries Threads::Threads) + endif() + set_target_properties(GTest::gmock PROPERTIES + INTERFACE_LINK_LIBRARIES "${_gmock_link_libraries}") + if(GMOCK_LIBRARY_TYPE STREQUAL "SHARED") + set_target_properties(GTest::gmock PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "GMOCK_LINKED_AS_SHARED_LIBRARY=1") + endif() + if(GTEST_INCLUDE_DIRS) + set_target_properties(GTest::gmock PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${GTEST_INCLUDE_DIRS}") + endif() + __gtest_import_library(GTest::gmock GMOCK_LIBRARY "") + __gtest_import_library(GTest::gmock GMOCK_LIBRARY "RELEASE") + __gtest_import_library(GTest::gmock GMOCK_LIBRARY "DEBUG") + endif() + if(NOT TARGET GTest::gmock_main) + __gtest_determine_library_type(GMOCK_MAIN_LIBRARY) + add_library(GTest::gmock_main ${GMOCK_MAIN_LIBRARY_TYPE} IMPORTED) + set_target_properties(GTest::gmock_main PROPERTIES + INTERFACE_LINK_LIBRARIES "GTest::gmock") + __gtest_import_library(GTest::gmock_main GMOCK_MAIN_LIBRARY "") + __gtest_import_library(GTest::gmock_main GMOCK_MAIN_LIBRARY "RELEASE") + __gtest_import_library(GTest::gmock_main GMOCK_MAIN_LIBRARY "DEBUG") + endif() +endif() diff --git a/Modules/FindGit.cmake b/Modules/FindGit.cmake index 99850b4..08a386a 100644 --- a/Modules/FindGit.cmake +++ b/Modules/FindGit.cmake @@ -31,16 +31,16 @@ Example usage: endif() #]=======================================================================] -# Look for 'git' or 'eg' (easy git) +# Look for 'git' # -set(git_names git eg) +set(git_names git) # Prefer .cmd variants on Windows unless running in a Makefile # in the MSYS shell. # if(CMAKE_HOST_WIN32) if(NOT CMAKE_GENERATOR MATCHES "MSYS") - set(git_names git.cmd git eg.cmd eg) + set(git_names git.cmd git) # GitHub search path for Windows file(GLOB github_path "$ENV{LOCALAPPDATA}/Github/PortableGit*/cmd" diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index 6cadadb..40ed9a9 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -242,7 +242,7 @@ function(_HDF5_test_regular_compiler_C success version is_parallel) COPY_FILE ${scratch_directory}/compiler_has_h5_c ) endif() - if(${success}) + if(${success} AND EXISTS ${scratch_directory}/compiler_has_h5_c) file(STRINGS ${scratch_directory}/compiler_has_h5_c INFO_STRINGS REGEX "^INFO:" ) @@ -290,7 +290,7 @@ function(_HDF5_test_regular_compiler_CXX success version is_parallel) COPY_FILE ${scratch_directory}/compiler_has_h5_cxx ) endif() - if(${success}) + if(${success} AND EXISTS ${scratch_directory}/compiler_has_h5_cxx) file(STRINGS ${scratch_directory}/compiler_has_h5_cxx INFO_STRINGS REGEX "^INFO:" ) @@ -319,8 +319,6 @@ function(_HDF5_test_regular_compiler_Fortran success is_parallel) file(WRITE ${test_file} "program hdf5_hello\n" " use hdf5\n" - " use h5lt\n" - " use h5ds\n" " integer error\n" " call h5open_f(error)\n" " call h5close_f(error)\n" @@ -881,7 +879,7 @@ if( NOT HDF5_FOUND ) # Add library-based search paths for Fortran modules. if (NOT _hdf5_main_library STREQUAL "") # gfortran module directory - if (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") + if (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "LCC") get_filename_component(_hdf5_library_dir "${_hdf5_main_library}" DIRECTORY) list(APPEND _hdf5_inc_extra_paths "${_hdf5_library_dir}") unset(_hdf5_library_dir) @@ -1052,8 +1050,12 @@ if (HDF5_FOUND) else() if (DEFINED "HDF5_${hdf5_target_name}_LIBRARY") set(_hdf5_location "${HDF5_${hdf5_target_name}_LIBRARY}") + set(_hdf5_location_release "${HDF5_${hdf5_target_name}_LIBRARY_RELEASE}") + set(_hdf5_location_debug "${HDF5_${hdf5_target_name}_LIBRARY_DEBUG}") elseif (DEFINED "HDF5_${hdf5_lang}_LIBRARY") set(_hdf5_location "${HDF5_${hdf5_lang}_LIBRARY}") + set(_hdf5_location_release "${HDF5_${hdf5_lang}_LIBRARY_RELEASE}") + set(_hdf5_location_debug "${HDF5_${hdf5_lang}_LIBRARY_DEBUG}") elseif (DEFINED "HDF5_${hdf5_lang}_LIBRARY_${hdf5_target_name}") set(_hdf5_location "${HDF5_${hdf5_lang}_LIBRARY_${hdf5_target_name}}") else () @@ -1068,10 +1070,24 @@ if (HDF5_FOUND) set(HDF5_${hdf5_lang}_INCLUDE_DIRS ${HDF5_INCLUDE_DIRS}) endif () set_target_properties("hdf5::${hdf5_target_name}" PROPERTIES - IMPORTED_LOCATION "${_hdf5_location}" - IMPORTED_IMPLIB "${_hdf5_location}" INTERFACE_INCLUDE_DIRECTORIES "${HDF5_${hdf5_lang}_INCLUDE_DIRS}" INTERFACE_COMPILE_DEFINITIONS "${_hdf5_definitions}") + if (_hdf5_location_release) + set_property(TARGET "hdf5::${hdf5_target_name}" APPEND PROPERTY + IMPORTED_CONFIGURATIONS RELEASE) + set_property(TARGET "hdf5::${hdf5_target_name}" PROPERTY + IMPORTED_LOCATION_RELEASE "${_hdf5_location_release}") + endif() + if (_hdf5_location_debug) + set_property(TARGET "hdf5::${hdf5_target_name}" APPEND PROPERTY + IMPORTED_CONFIGURATIONS DEBUG) + set_property(TARGET "hdf5::${hdf5_target_name}" PROPERTY + IMPORTED_LOCATION_DEBUG "${_hdf5_location_debug}") + endif() + if (NOT _hdf5_location_release AND NOT _hdf5_location_debug) + set_property(TARGET "hdf5::${hdf5_target_name}" PROPERTY + IMPORTED_LOCATION "${_hdf5_location}") + endif() if (_hdf5_libtype STREQUAL "SHARED") set_property(TARGET "hdf5::${hdf5_target_name}" APPEND PROPERTY @@ -1084,6 +1100,8 @@ if (HDF5_FOUND) unset(_hdf5_definitions) unset(_hdf5_libtype) unset(_hdf5_location) + unset(_hdf5_location_release) + unset(_hdf5_location_debug) endif () endif () @@ -1113,8 +1131,12 @@ if (HDF5_FOUND) else() if (DEFINED "HDF5_${hdf5_target_name}_LIBRARY") set(_hdf5_location "${HDF5_${hdf5_target_name}_LIBRARY}") + set(_hdf5_location_release "${HDF5_${hdf5_target_name}_LIBRARY_RELEASE}") + set(_hdf5_location_debug "${HDF5_${hdf5_target_name}_LIBRARY_DEBUG}") elseif (DEFINED "HDF5_${hdf5_lang}_HL_LIBRARY") set(_hdf5_location "${HDF5_${hdf5_lang}_HL_LIBRARY}") + set(_hdf5_location_release "${HDF5_${hdf5_lang}_HL_LIBRARY_RELEASE}") + set(_hdf5_location_debug "${HDF5_${hdf5_lang}_HL_LIBRARY_DEBUG}") elseif (DEFINED "HDF5_${hdf5_lang}_LIBRARY_${hdf5_target_name}") set(_hdf5_location "${HDF5_${hdf5_lang}_LIBRARY_${hdf5_target_name}}") elseif (hdf5_alt_target_name AND DEFINED "HDF5_${hdf5_lang}_LIBRARY_${hdf5_alt_target_name}") @@ -1128,10 +1150,24 @@ if (HDF5_FOUND) add_library("hdf5::${hdf5_target_name}" UNKNOWN IMPORTED) string(REPLACE "-D" "" _hdf5_definitions "${HDF5_${hdf5_lang}_HL_DEFINITIONS}") set_target_properties("hdf5::${hdf5_target_name}" PROPERTIES - IMPORTED_LOCATION "${_hdf5_location}" - IMPORTED_IMPLIB "${_hdf5_location}" INTERFACE_INCLUDE_DIRECTORIES "${HDF5_${hdf5_lang}_HL_INCLUDE_DIRS}" INTERFACE_COMPILE_DEFINITIONS "${_hdf5_definitions}") + if (_hdf5_location_release) + set_property(TARGET "hdf5::${hdf5_target_name}" APPEND PROPERTY + IMPORTED_CONFIGURATIONS RELEASE) + set_property(TARGET "hdf5::${hdf5_target_name}" PROPERTY + IMPORTED_LOCATION_RELEASE "${_hdf5_location_release}") + endif() + if (_hdf5_location_debug) + set_property(TARGET "hdf5::${hdf5_target_name}" APPEND PROPERTY + IMPORTED_CONFIGURATIONS DEBUG) + set_property(TARGET "hdf5::${hdf5_target_name}" PROPERTY + IMPORTED_LOCATION_DEBUG "${_hdf5_location_debug}") + endif() + if (NOT _hdf5_location_release AND NOT _hdf5_location_debug) + set_property(TARGET "hdf5::${hdf5_target_name}" PROPERTY + IMPORTED_LOCATION "${_hdf5_location}") + endif() if (_hdf5_libtype STREQUAL "SHARED") set_property(TARGET "hdf5::${hdf5_target_name}" APPEND PROPERTY diff --git a/Modules/FindICU.cmake b/Modules/FindICU.cmake index 1bae825..91dcba5 100644 --- a/Modules/FindICU.cmake +++ b/Modules/FindICU.cmake @@ -262,9 +262,9 @@ function(_ICU_FIND) set("${component_found_compat}" "${${component_found_compat}}" PARENT_SCOPE) if(component_found OR component_found_compat) if (ICU_FIND_REQUIRED_${component}) - list(APPEND ICU_LIBS_FOUND "${component} (required)") + list(APPEND ICU_LIBS_FOUND "${component} (required): ${${component_cache}}") else() - list(APPEND ICU_LIBS_FOUND "${component} (optional)") + list(APPEND ICU_LIBS_FOUND "${component} (optional): ${${component_cache}}") endif() else() if (ICU_FIND_REQUIRED_${component}) diff --git a/Modules/FindJNI.cmake b/Modules/FindJNI.cmake index e4f60b3..e93b91e 100644 --- a/Modules/FindJNI.cmake +++ b/Modules/FindJNI.cmake @@ -5,28 +5,79 @@ FindJNI ------- -Find Java Native Interface (JNI) libraries. +Find Java Native Interface (JNI) headers and libraries. -JNI enables Java code running in a Java Virtual Machine (JVM) to call -and be called by native applications and libraries written in other -languages such as C, C++. +JNI enables Java code running in a Java Virtual Machine (JVM) or Dalvik Virtual +Machine (DVM) on Android to call and be called by native applications and +libraries written in other languages such as C and C++. This module finds if Java is installed and determines where the include files and libraries are. It also determines what the name of the library is. The caller may set variable ``JAVA_HOME`` to specify a Java installation prefix explicitly. +.. versionadded:: 3.24 + + Added imported targets, components ``AWT``, ``JVM``, and Android NDK support. + If no components are specified, the module defaults to an empty components + list while targeting Android, and all available components otherwise. + + When using Android NDK, the corresponding package version is reported and a + specific release can be requested. At Android API level 31 and above, the + additional ``NativeHelper`` component can be requested. ``NativeHelper`` is + also exposed as an implicit dependency of the ``JVM`` component (only if this + does not cause a conflict) which provides a uniform access to JVM functions. + +Imported Targets +^^^^^^^^^^^^^^^^ + +.. versionadded:: 3.24 + +``JNI::JNI`` + Main JNI target, defined only if ``jni.h`` was found. + +``JNI::AWT`` + Java AWT Native Interface (JAWT) library, defined only if component ``AWT`` was + found. + +``JNI::JVM`` + Java Virtual Machine (JVM) library, defined only if component ``JVM`` was found. + +``JNI::NativeHelper`` + When targeting Android API level 31 and above, the import target will provide + access to ``libnativehelper.so`` that exposes JVM functions such as + ``JNI_CreateJavaVM``. + Result Variables ^^^^^^^^^^^^^^^^ This module sets the following result variables: ``JNI_INCLUDE_DIRS`` - the include dirs to use + The include directories to use. ``JNI_LIBRARIES`` - the libraries to use (JAWT and JVM) + The libraries to use (JAWT and JVM). ``JNI_FOUND`` - TRUE if JNI headers and libraries were found. + ``TRUE`` if JNI headers and libraries were found. +``JNI_<component>_FOUND`` + .. versionadded:: 3.24 + + ``TRUE`` if ``<component>`` was found. +``JNI_VERSION`` + Full Android NDK package version (including suffixes such as ``-beta3`` and + ``-rc1``) or undefined otherwise. +``JNI_VERSION_MAJOR`` + .. versionadded:: 3.24 + + Android NDK major version or undefined otherwise. +``JNI_VERSION_MINOR`` + .. versionadded:: 3.24 + + Android NDK minor version or undefined otherwise. +``JNI_VERSION_PATCH`` + .. versionadded:: 3.24 + + Android NDK patch version or undefined otherwise. Cache Variables ^^^^^^^^^^^^^^^ @@ -34,17 +85,55 @@ Cache Variables The following cache variables are also available to set or use: ``JAVA_AWT_LIBRARY`` - the path to the Java AWT Native Interface (JAWT) library + The path to the Java AWT Native Interface (JAWT) library. ``JAVA_JVM_LIBRARY`` - the path to the Java Virtual Machine (JVM) library + The path to the Java Virtual Machine (JVM) library. ``JAVA_INCLUDE_PATH`` - the include path to jni.h + The include path to ``jni.h``. ``JAVA_INCLUDE_PATH2`` - the include path to jni_md.h and jniport.h + The include path to machine-dependant headers ``jni_md.h`` and ``jniport.h``. + The variable is defined only if ``jni.h`` depends on one of these headers. In + contrast, Android NDK ``jni.h`` can be typically used standalone. ``JAVA_AWT_INCLUDE_PATH`` - the include path to jawt.h + The include path to ``jawt.h``. #]=======================================================================] +cmake_policy(PUSH) +cmake_policy(SET CMP0057 NEW) + +include(CheckSourceCompiles) +include(CMakePushCheckState) +include(FindPackageHandleStandardArgs) + +if(NOT JNI_FIND_COMPONENTS) + if(ANDROID) + if(CMAKE_ANDROID_API LESS 31) + # There are no components for Android NDK + set(JNI_FIND_COMPONENTS) + else() + set(JNI_FIND_COMPONENTS NativeHelper) + set(JNI_FIND_REQUIRED_NativeHelper TRUE) + endif() + else(ANDROID) + set(JNI_FIND_COMPONENTS AWT JVM) + # For compatibility purposes, if no components are specified both are + # considered required. + set(JNI_FIND_REQUIRED_AWT TRUE) + set(JNI_FIND_REQUIRED_JVM TRUE) + endif() +else() + # On Android, if JVM was requested we need to find NativeHelper as well which + # is an implicit dependency of JVM allowing to provide uniform access to basic + # JVM/DVM functionality. + if(ANDROID AND CMAKE_ANDROID_API GREATER_EQUAL 31 AND JVM IN_LIST JNI_FIND_COMPONENTS) + if(NOT NativeHelper IN_LIST JNI_FIND_COMPONENTS) + list(APPEND JNI_FIND_COMPONENTS NativeHelper) + # NativeHelper is required only if JVM was requested as such. + set(JNI_FIND_REQUIRED_NativeHelper ${JNI_FIND_REQUIRED_JVM}) + endif() + endif() +endif() + # Expand {libarch} occurrences to java_libarch subdirectory(-ies) and set ${_var} macro(java_append_library_directories _var) # Determine java arch-specific library subdir @@ -145,46 +234,41 @@ endif() if (WIN32) set (_JNI_HINTS) - execute_process(COMMAND REG QUERY HKLM\\SOFTWARE\\JavaSoft\\JDK - RESULT_VARIABLE _JNI_RESULT - OUTPUT_VARIABLE _JNI_VERSIONS - ERROR_QUIET) - if (NOT _JNI_RESULT) - string (REGEX MATCHALL "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\JDK\\\\[0-9.]+" _JNI_VERSIONS "${_JNI_VERSIONS}") - if (_JNI_VERSIONS) - # sort versions. Most recent first - ## handle version 9 apart from other versions to get correct ordering - set (_JNI_V9 ${_JNI_VERSIONS}) - list (FILTER _JNI_VERSIONS EXCLUDE REGEX "JDK\\\\9") - list (SORT _JNI_VERSIONS) - list (REVERSE _JNI_VERSIONS) - list (FILTER _JNI_V9 INCLUDE REGEX "JDK\\\\9") - list (SORT _JNI_V9) - list (REVERSE _JNI_V9) - list (APPEND _JNI_VERSIONS ${_JNI_V9}) - foreach (_JNI_HINT IN LISTS _JNI_VERSIONS) - list(APPEND _JNI_HINTS "[${_JNI_HINT};JavaHome]") - endforeach() + macro (_JNI_GET_INSTALLED_VERSIONS _KIND) + execute_process(COMMAND REG QUERY "HKLM\\SOFTWARE\\JavaSoft\\${_KIND}" + RESULT_VARIABLE _JAVA_RESULT + OUTPUT_VARIABLE _JAVA_VERSIONS + ERROR_QUIET) + if (NOT _JAVA_RESULT) + string (REGEX MATCHALL "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\${_KIND}\\\\[0-9._]+" _JNI_VERSIONS "${_JAVA_VERSIONS}") + string (REGEX REPLACE "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\${_KIND}\\\\([0-9._]+)" "\\1" _JNI_VERSIONS "${_JNI_VERSIONS}") + if (_JNI_VERSIONS) + # sort versions. Most recent first + list (SORT _JNI_VERSIONS COMPARE NATURAL ORDER DESCENDING) + foreach (_JNI_VERSION IN LISTS _JNI_VERSIONS) + string(REPLACE "_" "." _JNI_CMAKE_VERSION "${_JNI_VERSION}") + if (JNI_FIND_VERSION_EXACT + AND NOT _JNI_CMAKE_VERSION MATCHES "^${JNI_FIND_VERSION}") + continue() + endif() + if (DEFINED JNI_FIND_VERSION AND _JNI_CMAKE_VERSION VERSION_LESS JNI_FIND_VERSION) + break() + endif() + list(APPEND _JNI_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\${_KIND}\\${_JNI_VERSION};JavaHome]") + endforeach() + endif() endif() - endif() + endmacro() + + # for version 9 and upper + _JNI_GET_INSTALLED_VERSIONS("JDK") + + # for versions older than 9 + _JNI_GET_INSTALLED_VERSIONS("Java Development Kit") foreach (_JNI_HINT IN LISTS _JNI_HINTS) list(APPEND JAVA_AWT_LIBRARY_DIRECTORIES "${_JNI_HINT}/lib") endforeach() - - get_filename_component(java_install_version - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit;CurrentVersion]" NAME) - - list(APPEND JAVA_AWT_LIBRARY_DIRECTORIES - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.9;JavaHome]/lib" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.8;JavaHome]/lib" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.7;JavaHome]/lib" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.6;JavaHome]/lib" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.5;JavaHome]/lib" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.4;JavaHome]/lib" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.3;JavaHome]/lib" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\${java_install_version};JavaHome]/lib" - ) endif() set(_JNI_JAVA_DIRECTORIES_BASE @@ -268,16 +352,6 @@ if (WIN32) foreach (_JNI_HINT IN LISTS _JNI_HINTS) list(APPEND JAVA_AWT_INCLUDE_DIRECTORIES "${_JNI_HINT}/include") endforeach() - list(APPEND JAVA_AWT_INCLUDE_DIRECTORIES - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.9;JavaHome]/include" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.8;JavaHome]/include" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.7;JavaHome]/include" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.6;JavaHome]/include" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.5;JavaHome]/include" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.4;JavaHome]/include" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.3;JavaHome]/include" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\${java_install_version};JavaHome]/include" - ) endif() JAVA_APPEND_LIBRARY_DIRECTORIES(JAVA_AWT_INCLUDE_DIRECTORIES @@ -328,10 +402,19 @@ set(_JNI_NORMAL_JAWT ) foreach(search ${_JNI_SEARCHES}) - find_library(JAVA_JVM_LIBRARY ${_JNI_${search}_JVM}) - find_library(JAVA_AWT_LIBRARY ${_JNI_${search}_JAWT}) - if(JAVA_JVM_LIBRARY) - break() + if(JVM IN_LIST JNI_FIND_COMPONENTS) + find_library(JAVA_JVM_LIBRARY ${_JNI_${search}_JVM} + DOC "Java Virtual Machine library" + ) + endif(JVM IN_LIST JNI_FIND_COMPONENTS) + + if(AWT IN_LIST JNI_FIND_COMPONENTS) + find_library(JAVA_AWT_LIBRARY ${_JNI_${search}_JAWT} + DOC "Java AWT Native Interface library" + ) + if(JAVA_JVM_LIBRARY) + break() + endif() endif() endforeach() unset(_JNI_SEARCHES) @@ -350,11 +433,46 @@ endif() # add in the include path find_path(JAVA_INCLUDE_PATH jni.h ${JAVA_AWT_INCLUDE_DIRECTORIES} + DOC "JNI include directory" ) +if(JAVA_INCLUDE_PATH) + if(CMAKE_C_COMPILER_LOADED) + set(_JNI_CHECK_LANG C) + elseif(CMAKE_CXX_COMPILER_LOADED) + set(_JNI_CHECK_LANG CXX) + else() + set(_JNI_CHECK_LANG FALSE) + endif() + + # Skip the check if neither C nor CXX is loaded. + if(_JNI_CHECK_LANG) + cmake_push_check_state(RESET) + # The result of the following check is not relevant for the user as + # JAVA_INCLUDE_PATH2 will be added to REQUIRED_VARS if necessary. + set(CMAKE_REQUIRED_QUIET ON) + set(CMAKE_REQUIRED_INCLUDES ${JAVA_INCLUDE_PATH}) + + # Determine whether jni.h requires jni_md.h and add JAVA_INCLUDE_PATH2 + # correspondingly to REQUIRED_VARS + check_source_compiles(${_JNI_CHECK_LANG} +" +#include <jni.h> +int main(void) { return 0; } +" + JNI_INCLUDE_PATH2_OPTIONAL) + + cmake_pop_check_state() + else() + # If the above check is skipped assume jni_md.h is not needed. + set(JNI_INCLUDE_PATH2_OPTIONAL TRUE) + endif() + + unset(_JNI_CHECK_LANG) +endif() + find_path(JAVA_INCLUDE_PATH2 NAMES jni_md.h jniport.h - PATHS - ${JAVA_INCLUDE_PATH} + PATHS ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH}/darwin ${JAVA_INCLUDE_PATH}/win32 ${JAVA_INCLUDE_PATH}/linux @@ -364,11 +482,50 @@ find_path(JAVA_INCLUDE_PATH2 NAMES jni_md.h jniport.h ${JAVA_INCLUDE_PATH}/hp-ux ${JAVA_INCLUDE_PATH}/alpha ${JAVA_INCLUDE_PATH}/aix + DOC "jni_md.h jniport.h include directory" ) -find_path(JAVA_AWT_INCLUDE_PATH jawt.h - ${JAVA_INCLUDE_PATH} -) +if(AWT IN_LIST JNI_FIND_COMPONENTS) + find_path(JAVA_AWT_INCLUDE_PATH jawt.h + ${JAVA_INCLUDE_PATH} + DOC "Java AWT Native Interface include directory" + ) +endif() + +if(ANDROID) + # Some functions in jni.h (e.g., JNI_GetCreatedJavaVMs) are exported by + # libnativehelper.so, however, only when targeting Android API level >= 31. + find_library(JAVA_NativeHelper_LIBRARY NAMES nativehelper + DOC "Android nativehelper library" + ) +endif() + +# Set found components +if(JAVA_AWT_INCLUDE_PATH AND JAVA_AWT_LIBRARY) + set(JNI_AWT_FOUND TRUE) +else() + set(JNI_AWT_FOUND FALSE) +endif() + +# JVM is available even on Android referencing the nativehelper library +if(JAVA_JVM_LIBRARY) + set(JNI_JVM_FOUND TRUE) +else(JAVA_JVM_LIBRARY) + set(JNI_JVM_FOUND FALSE) +endif() + +if(JAVA_NativeHelper_LIBRARY) + # Alias JAVA_JVM_LIBRARY to JAVA_NativeHelper_LIBRARY + if(NOT JAVA_JVM_LIBRARY) + set(JAVA_JVM_LIBRARY "${JAVA_NativeHelper_LIBRARY}" CACHE FILEPATH + "Alias to nativehelper library" FORCE) + # Make JVM component available + set(JNI_JVM_FOUND TRUE) + endif() + set(JNI_NativeHelper_FOUND TRUE) +else() + set(JNI_NativeHelper_FOUND FALSE) +endif() # Restore CMAKE_FIND_FRAMEWORK if(DEFINED _JNI_CMAKE_FIND_FRAMEWORK) @@ -378,12 +535,35 @@ else() unset(CMAKE_FIND_FRAMEWORK) endif() -include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(JNI DEFAULT_MSG JAVA_AWT_LIBRARY - JAVA_JVM_LIBRARY - JAVA_INCLUDE_PATH - JAVA_INCLUDE_PATH2 - JAVA_AWT_INCLUDE_PATH) +if(ANDROID) + # Extract NDK version from source.properties in the NDK root + set(JAVA_SOURCE_PROPERTIES_FILE ${CMAKE_ANDROID_NDK}/source.properties) + + if(EXISTS ${JAVA_SOURCE_PROPERTIES_FILE}) + file(READ ${JAVA_SOURCE_PROPERTIES_FILE} NDK_VERSION_CONTENTS) + string (REGEX REPLACE + ".*Pkg\\.Revision = (([0-9]+)\\.([0-9]+)\\.([0-9]+)([^\n]+)?).*" "\\1" + JNI_VERSION "${NDK_VERSION_CONTENTS}") + set(JNI_VERSION_MAJOR ${CMAKE_MATCH_1}) + set(JNI_VERSION_MINOR ${CMAKE_MATCH_2}) + set(JNI_VERSION_PATCH ${CMAKE_MATCH_3}) + set(JNI_VERSION_COMPONENTS 3) + + set(JNI_FPHSA_ARGS VERSION_VAR JNI_VERSION HANDLE_VERSION_RANGE) + endif() +endif() + +set(JNI_REQUIRED_VARS JAVA_INCLUDE_PATH) + +if(NOT JNI_INCLUDE_PATH2_OPTIONAL) + list(APPEND JNI_REQUIRED_VARS JAVA_INCLUDE_PATH2) +endif() + +find_package_handle_standard_args(JNI + REQUIRED_VARS ${JNI_REQUIRED_VARS} + ${JNI_FPHSA_ARGS} + HANDLE_COMPONENTS +) mark_as_advanced( JAVA_AWT_LIBRARY @@ -393,13 +573,93 @@ mark_as_advanced( JAVA_INCLUDE_PATH2 ) -set(JNI_LIBRARIES - ${JAVA_AWT_LIBRARY} - ${JAVA_JVM_LIBRARY} -) +set(JNI_LIBRARIES) -set(JNI_INCLUDE_DIRS - ${JAVA_INCLUDE_PATH} - ${JAVA_INCLUDE_PATH2} - ${JAVA_AWT_INCLUDE_PATH} -) +foreach(component IN LISTS JNI_FIND_COMPONENTS) + if(JNI_${component}_FOUND) + list(APPEND JNI_LIBRARIES ${JAVA_${component}_LIBRARY}) + endif() +endforeach() + +set(JNI_INCLUDE_DIRS ${JAVA_INCLUDE_PATH}) + +if(NOT JNI_INCLUDE_PATH2_OPTIONAL) + list(APPEND JNI_INCLUDE_DIRS ${JAVA_INCLUDE_PATH2}) +endif() + +if(JNI_FIND_REQUIRED_AWT) + list(APPEND JNI_INCLUDE_DIRS ${JAVA_AWT_INCLUDE_PATH}) +endif() + +if(JNI_FOUND) + if(NOT TARGET JNI::JNI) + add_library(JNI::JNI IMPORTED INTERFACE) + endif() + + set_property(TARGET JNI::JNI PROPERTY INTERFACE_INCLUDE_DIRECTORIES + ${JAVA_INCLUDE_PATH}) + + if(JNI_NativeHelper_FOUND) + if(NOT TARGET JNI::NativeHelper) + add_library(JNI::NativeHelper IMPORTED UNKNOWN) + endif() + + set_property(TARGET JNI::NativeHelper PROPERTY INTERFACE_LINK_LIBRARIES + JNI::JNI) + set_property(TARGET JNI::NativeHelper PROPERTY IMPORTED_LOCATION + ${JAVA_NativeHelper_LIBRARY}) + endif() + + if(NOT JNI_INCLUDE_PATH2_OPTIONAL AND JAVA_INCLUDE_PATH2) + set_property(TARGET JNI::JNI APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES + ${JAVA_INCLUDE_PATH2}) + endif() + + if(JNI_AWT_FOUND) + if(NOT TARGET JNI::AWT) + add_library(JNI::AWT IMPORTED UNKNOWN) + endif(NOT TARGET JNI::AWT) + + set_property(TARGET JNI::AWT PROPERTY INTERFACE_INCLUDE_DIRECTORIES + ${JAVA_AWT_INCLUDE_PATH}) + set_property(TARGET JNI::AWT PROPERTY IMPORTED_LOCATION + ${JAVA_AWT_LIBRARY}) + set_property(TARGET JNI::AWT PROPERTY INTERFACE_LINK_LIBRARIES JNI::JNI) + endif() + + if(JNI_JVM_FOUND OR JNI_NativeHelper_FOUND) + # If Android nativehelper is available but not the JVM library, we still + # define the JNI::JVM target but only declare JNI::NativeHelper as an + # interface link library of the former. This provides a uniform access to + # fundamental JVM functionality regardless of whether JVM or DVM is used. At + # the same time, this allows the user to detect whenever exclusively + # nativehelper functionality is available. + if(NOT TARGET JNI::JVM) + if(JAVA_JVM_LIBRARY AND NOT JAVA_JVM_LIBRARY STREQUAL JAVA_NativeHelper_LIBRARY) + # JAVA_JVM_LIBRARY is not an alias of JAVA_NativeHelper_LIBRARY + add_library(JNI::JVM IMPORTED UNKNOWN) + else() + add_library(JNI::JVM IMPORTED INTERFACE) + endif() + endif(NOT TARGET JNI::JVM) + + set_property(TARGET JNI::JVM PROPERTY INTERFACE_LINK_LIBRARIES JNI::JNI) + get_property(_JNI_JVM_TYPE TARGET JNI::JVM PROPERTY TYPE) + + if(NOT _JNI_JVM_TYPE STREQUAL "INTERFACE_LIBRARY") + set_property(TARGET JNI::JVM PROPERTY IMPORTED_LOCATION + ${JAVA_JVM_LIBRARY}) + else() + # We declare JNI::NativeHelper a dependency of JNI::JVM only if the latter + # was not initially found. If the solely theoretical situation occurs + # where both libraries are available, we want to avoid any potential + # errors that can occur due to duplicate symbols. + set_property(TARGET JNI::JVM APPEND PROPERTY INTERFACE_LINK_LIBRARIES + JNI::NativeHelper) + endif() + + unset(_JNI_JVM_TYPE) + endif() +endif() + +cmake_policy(POP) diff --git a/Modules/FindJava.cmake b/Modules/FindJava.cmake index 4f0e0fe..e8fb120 100644 --- a/Modules/FindJava.cmake +++ b/Modules/FindJava.cmake @@ -90,50 +90,35 @@ if(_JAVA_HOME) endif() if (WIN32) macro (_JAVA_GET_INSTALLED_VERSIONS _KIND) - execute_process(COMMAND REG QUERY HKLM\\SOFTWARE\\JavaSoft\\${_KIND} + execute_process(COMMAND REG QUERY "HKLM\\SOFTWARE\\JavaSoft\\${_KIND}" RESULT_VARIABLE _JAVA_RESULT OUTPUT_VARIABLE _JAVA_VERSIONS ERROR_QUIET) if (NOT _JAVA_RESULT) - string (REGEX MATCHALL "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\${_KIND}\\\\[0-9.]+" _JAVA_VERSIONS "${_JAVA_VERSIONS}") + string (REGEX MATCHALL "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\${_KIND}\\\\[0-9._]+" _JAVA_VERSIONS "${_JAVA_VERSIONS}") + string (REGEX REPLACE "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\${_KIND}\\\\([0-9._]+)" "\\1" _JAVA_VERSIONS "${_JAVA_VERSIONS}") if (_JAVA_VERSIONS) # sort versions. Most recent first - ## handle version 9 apart from other versions to get correct ordering - set (_JAVA_V9 ${_JAVA_VERSIONS}) - list (FILTER _JAVA_VERSIONS EXCLUDE REGEX "${_KIND}\\\\9") - list (SORT _JAVA_VERSIONS) - list (REVERSE _JAVA_VERSIONS) - list (FILTER _JAVA_V9 INCLUDE REGEX "${_KIND}\\\\9") - list (SORT _JAVA_V9) - list (REVERSE _JAVA_V9) - list (APPEND _JAVA_VERSIONS ${_JAVA_V9}) - foreach (_JAVA_HINT IN LISTS _JAVA_VERSIONS) - list(APPEND _JAVA_HINTS "[${_JAVA_HINT};JavaHome]/bin") + list (SORT _JAVA_VERSIONS COMPARE NATURAL ORDER DESCENDING) + foreach (_JAVA_VERSION IN LISTS _JAVA_VERSIONS) + string(REPLACE "_" "." _JAVA_CMAKE_VERSION "${_JAVA_VERSION}") + if (Java_FIND_VERSION_EXACT + AND NOT _JAVA_CMAKE_VERSION MATCHES "^${Java_FIND_VERSION}") + continue() + endif() + list(APPEND _JAVA_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\${_KIND}\\${_JAVA_VERSION};JavaHome]/bin") endforeach() endif() endif() endmacro() - # search for installed versions for version 9 and upper + # for version 9 and upper _JAVA_GET_INSTALLED_VERSIONS("JDK") _JAVA_GET_INSTALLED_VERSIONS("JRE") - list(APPEND _JAVA_HINTS - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.9;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.8;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.7;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.6;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.5;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.4;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.3;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.9;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.8;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.7;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.6;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.5;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.4;JavaHome]/bin" - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.3;JavaHome]/bin" - ) + # for versions older than 9 + _JAVA_GET_INSTALLED_VERSIONS("Java Development Kit") + _JAVA_GET_INSTALLED_VERSIONS("Java Runtime Environment") endif() # Hard-coded guesses should still go in PATHS. This ensures that the user @@ -159,23 +144,25 @@ find_program(Java_JAVA_EXECUTABLE if(Java_JAVA_EXECUTABLE) execute_process(COMMAND "${Java_JAVA_EXECUTABLE}" -version - RESULT_VARIABLE res - OUTPUT_VARIABLE var - ERROR_VARIABLE var # sun-java output to stderr + RESULT_VARIABLE _java_res + OUTPUT_VARIABLE _java_var + ERROR_VARIABLE _java_var # sun-java output to stderr OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE) - if( res ) - if(var MATCHES "Unable to locate a Java Runtime to invoke|No Java runtime present, requesting install") - set(Java_JAVA_EXECUTABLE Java_JAVA_EXECUTABLE-NOTFOUND) - elseif(${Java_FIND_REQUIRED}) - message( FATAL_ERROR "Error executing java -version" ) - else() - message( STATUS "Warning, could not run java -version") + if(_java_res) + if(NOT Java_FIND_QUIETLY) + message(STATUS "Java version check failed: " + "${Java_JAVA_EXECUTABLE} -version returned an error: \"${_java_var}\"") + endif() + if(_java_var MATCHES "Unable to locate a Java Runtime|No Java runtime present, requesting install") + # macOS distributes a java stub that provides an error message + set(Java_JAVA_EXECUTABLE "Java_JAVA_EXECUTABLE-NOTFOUND" CACHE PATH + "Path to the Java executable" FORCE) endif() else() # Extract version components (up to 4 levels) from "java -version" output. set(_java_version_regex [[(([0-9]+)(\.([0-9]+)(\.([0-9]+)(_([0-9]+))?)?)?.*)]]) - if(var MATCHES "java version \"${_java_version_regex}\"") + if(_java_var MATCHES "java version \"${_java_version_regex}\"") # Sun, GCJ, older OpenJDK set(Java_VERSION_STRING "${CMAKE_MATCH_1}") set(Java_VERSION_MAJOR "${CMAKE_MATCH_2}") @@ -190,7 +177,7 @@ if(Java_JAVA_EXECUTABLE) set(Java_VERSION_PATCH 0) endif() set(Java_VERSION_TWEAK "${CMAKE_MATCH_8}") - elseif(var MATCHES "openjdk version \"${_java_version_regex}\"") + elseif(_java_var MATCHES "openjdk version \"${_java_version_regex}\"") # OpenJDK set(Java_VERSION_STRING "${CMAKE_MATCH_1}") set(Java_VERSION_MAJOR "${CMAKE_MATCH_2}") @@ -205,14 +192,14 @@ if(Java_JAVA_EXECUTABLE) set(Java_VERSION_PATCH 0) endif() set(Java_VERSION_TWEAK "${CMAKE_MATCH_8}") - elseif(var MATCHES "openjdk version \"([0-9]+)-[A-Za-z]+\"") + elseif(_java_var MATCHES "openjdk version \"([0-9]+)-[A-Za-z]+\"") # OpenJDK 9 early access builds or locally built set(Java_VERSION_STRING "1.${CMAKE_MATCH_1}.0") set(Java_VERSION_MAJOR "1") set(Java_VERSION_MINOR "${CMAKE_MATCH_1}") set(Java_VERSION_PATCH "0") set(Java_VERSION_TWEAK "") - elseif(var MATCHES "java full version \"kaffe-${_java_version_regex}\"") + elseif(_java_var MATCHES "java full version \"kaffe-${_java_version_regex}\"") # Kaffe style set(Java_VERSION_STRING "${CMAKE_MATCH_1}") set(Java_VERSION_MAJOR "${CMAKE_MATCH_2}") @@ -221,7 +208,7 @@ if(Java_JAVA_EXECUTABLE) set(Java_VERSION_TWEAK "${CMAKE_MATCH_8}") else() if(NOT Java_FIND_QUIETLY) - string(REPLACE "\n" "\n " ver_msg "\n${var}") + string(REPLACE "\n" "\n " ver_msg "\n${_java_var}") message(WARNING "Java version not recognized:${ver_msg}\nPlease report.") endif() set(Java_VERSION_STRING "") @@ -230,18 +217,21 @@ if(Java_JAVA_EXECUTABLE) set(Java_VERSION_PATCH "") set(Java_VERSION_TWEAK "") endif() + unset(_java_version_regex) + unset(_java_var) set(Java_VERSION "${Java_VERSION_MAJOR}") if(NOT "x${Java_VERSION}" STREQUAL "x") - foreach(c MINOR PATCH TWEAK) - if(NOT "x${Java_VERSION_${c}}" STREQUAL "x") - string(APPEND Java_VERSION ".${Java_VERSION_${c}}") + foreach(_java_c MINOR PATCH TWEAK) + if(NOT "x${Java_VERSION_${_java_c}}" STREQUAL "x") + string(APPEND Java_VERSION ".${Java_VERSION_${_java_c}}") else() break() endif() endforeach() + unset(_java_c) endif() endif() - + unset(_java_res) endif() @@ -330,19 +320,20 @@ if(Java_FIND_COMPONENTS) set(Java_${component}_FOUND TRUE) endforeach() endif() + unset(_JAVA_REQUIRED_VARS) else() # Check for Development if(Java_VERSION VERSION_LESS "10") find_package_handle_standard_args(Java REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVAC_EXECUTABLE Java_JAVAH_EXECUTABLE Java_JAVADOC_EXECUTABLE - VERSION_VAR Java_VERSION_STRING + VERSION_VAR Java_VERSION ) else() find_package_handle_standard_args(Java REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVAC_EXECUTABLE Java_JAVADOC_EXECUTABLE - VERSION_VAR Java_VERSION_STRING + VERSION_VAR Java_VERSION ) endif() endif() @@ -356,7 +347,7 @@ mark_as_advanced( Java_JAVADOC_EXECUTABLE Java_IDLJ_EXECUTABLE Java_JARSIGNER_EXECUTABLE - ) +) # LEGACY set(JAVA_RUNTIME ${Java_JAVA_EXECUTABLE}) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index 91086a3..b08b359 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -278,8 +278,8 @@ endif() # Search with pkg-config if specified if(BLA_PREFER_PKGCONFIG) - find_package(PkgConfig) - pkg_check_modules(PKGC_LAPACK lapack) + find_package(PkgConfig QUIET) + pkg_check_modules(PKGC_LAPACK QUIET lapack) if(PKGC_LAPACK_FOUND) set(LAPACK_FOUND TRUE) set(LAPACK_LIBRARIES "${PKGC_LAPACK_LINK_LIBRARIES}") diff --git a/Modules/FindLTTngUST.cmake b/Modules/FindLTTngUST.cmake index f478e4d..a70a418 100644 --- a/Modules/FindLTTngUST.cmake +++ b/Modules/FindLTTngUST.cmake @@ -63,11 +63,11 @@ if(LTTNGUST_INCLUDE_DIRS AND LTTNGUST_LIBRARIES) REGEX "^[\t ]*#define[\t ]+LTTNG_UST_MINOR_VERSION[\t ]+[0-9]+[\t ]*$") file(STRINGS "${lttngust_version_file}" lttngust_version_patch_string REGEX "^[\t ]*#define[\t ]+LTTNG_UST_PATCHLEVEL_VERSION[\t ]+[0-9]+[\t ]*$") - string(REGEX REPLACE ".*([0-9]+).*" "\\1" + string(REGEX REPLACE ".*[\t ]+([0-9]+).*" "\\1" lttngust_v_major "${lttngust_version_major_string}") - string(REGEX REPLACE ".*([0-9]+).*" "\\1" + string(REGEX REPLACE ".*[\t ]+([0-9]+).*" "\\1" lttngust_v_minor "${lttngust_version_minor_string}") - string(REGEX REPLACE ".*([0-9]+).*" "\\1" + string(REGEX REPLACE ".*[\t ]+([0-9]+).*" "\\1" lttngust_v_patch "${lttngust_version_patch_string}") set(LTTNGUST_VERSION_STRING "${lttngust_v_major}.${lttngust_v_minor}.${lttngust_v_patch}") diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index c974d33..bca0c10 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -775,7 +775,8 @@ function (_MPI_interrogate_compiler LANG) MPI_LIBNAMES "${MPI_LINK_CMDLINE}") foreach(_MPI_LIB_NAME IN LISTS MPI_LIBNAMES) - string(REGEX REPLACE "^ ?${CMAKE_LINK_LIBRARY_FLAG}" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") + # also match flags starting with "-l:" here + string(REGEX REPLACE "^ ?${CMAKE_LINK_LIBRARY_FLAG}(:lib|:)?" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") string(REPLACE "\"" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") list(APPEND MPI_LIB_NAMES_WORK "${_MPI_LIB_NAME}") endforeach() @@ -788,7 +789,7 @@ function (_MPI_interrogate_compiler LANG) set(_MPI_LIB_SUFFIX_REGEX "${CMAKE_STATIC_LIBRARY_SUFFIX}") if(DEFINED CMAKE_IMPORT_LIBRARY_SUFFIX) if(NOT ("${CMAKE_IMPORT_LIBRARY_SUFFIX}" STREQUAL "${CMAKE_STATIC_LIBRARY_SUFFIX}")) - string(APPEND _MPI_SUFFIX_REGEX "|${CMAKE_IMPORT_LIBRARY_SUFFIX}") + string(APPEND _MPI_LIB_SUFFIX_REGEX "|${CMAKE_IMPORT_LIBRARY_SUFFIX}") endif() else() string(APPEND _MPI_LIB_SUFFIX_REGEX "|${CMAKE_SHARED_LIBRARY_SUFFIX}") @@ -798,12 +799,16 @@ function (_MPI_interrogate_compiler LANG) string(REGEX MATCHALL "${_MPI_LIB_NAME_REGEX}" MPI_LIBNAMES "${MPI_LINK_CMDLINE}") foreach(_MPI_LIB_NAME IN LISTS MPI_LIBNAMES) - string(REGEX REPLACE "^ +\"?|\"? +$" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") - get_filename_component(_MPI_LIB_PATH "${_MPI_LIB_NAME}" DIRECTORY) - if(NOT "${_MPI_LIB_PATH}" STREQUAL "") - list(APPEND MPI_LIB_FULLPATHS_WORK "${_MPI_LIB_NAME}") - else() - list(APPEND MPI_LIB_NAMES_WORK "${_MPI_LIB_NAME}") + # Do not match "-l:" flags + string(REGEX MATCH "^ ?${CMAKE_LINK_LIBRARY_FLAG}:" _MPI_LIB_NAME_TEST "${_MPI_LIB_NAME}") + if(_MPI_LIB_NAME_TEST STREQUAL "") + string(REGEX REPLACE "^ +\"?|\"? +$" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") + get_filename_component(_MPI_LIB_PATH "${_MPI_LIB_NAME}" DIRECTORY) + if(NOT "${_MPI_LIB_PATH}" STREQUAL "") + list(APPEND MPI_LIB_FULLPATHS_WORK "${_MPI_LIB_NAME}") + else() + list(APPEND MPI_LIB_NAMES_WORK "${_MPI_LIB_NAME}") + endif() endif() endforeach() @@ -1452,21 +1457,21 @@ foreach(LANG IN ITEMS C CXX Fortran) if(CMAKE_${LANG}_COMPILER_LOADED) if(NOT MPI_FIND_COMPONENTS) set(_MPI_FIND_${LANG} TRUE) - elseif( ${LANG} IN_LIST MPI_FIND_COMPONENTS) + elseif( LANG IN_LIST MPI_FIND_COMPONENTS) set(_MPI_FIND_${LANG} TRUE) - elseif( ${LANG} STREQUAL CXX AND NOT MPI_CXX_SKIP_MPICXX AND MPICXX IN_LIST MPI_FIND_COMPONENTS ) + elseif( "${LANG}" STREQUAL "CXX" AND NOT MPI_CXX_SKIP_MPICXX AND MPICXX IN_LIST MPI_FIND_COMPONENTS ) set(_MPI_FIND_${LANG} TRUE) else() set(_MPI_FIND_${LANG} FALSE) endif() else() set(_MPI_FIND_${LANG} FALSE) - if(${LANG} IN_LIST MPI_FIND_COMPONENTS) + if(LANG IN_LIST MPI_FIND_COMPONENTS) string(APPEND _MPI_FAIL_REASON "MPI component '${LANG}' was requested, but language ${LANG} is not enabled. ") endif() endif() if(_MPI_FIND_${LANG}) - if( ${LANG} STREQUAL CXX AND NOT MPICXX IN_LIST MPI_FIND_COMPONENTS ) + if( "${LANG}" STREQUAL "CXX" AND NOT MPICXX IN_LIST MPI_FIND_COMPONENTS ) option(MPI_CXX_SKIP_MPICXX "If true, the MPI-2 C++ bindings are disabled using definitions." FALSE) mark_as_advanced(MPI_CXX_SKIP_MPICXX) endif() diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake index 3c7efbc..48ef5eb 100644 --- a/Modules/FindMatlab.cmake +++ b/Modules/FindMatlab.cmake @@ -288,6 +288,7 @@ if(NOT MATLAB_ADDITIONAL_VERSIONS) endif() set(MATLAB_VERSIONS_MAPPING + "R2022a=9.12" "R2021b=9.11" "R2021a=9.10" "R2020b=9.9" @@ -768,6 +769,10 @@ function(matlab_get_version_from_matlab_run matlab_binary_program matlab_list_ve set(devnull INPUT_FILE NUL) endif() + # we first try to run a simple program using the -r option, and then we use the + # -batch option that is supported and recommended since R2019a + set(_matlab_get_version_failed_with_r_option FALSE) + # timeout set to 120 seconds, in case it does not start # note as said before OUTPUT_VARIABLE cannot be used in a platform # independent manner however, not setting it would flush the output of Matlab @@ -785,21 +790,57 @@ function(matlab_get_version_from_matlab_run matlab_binary_program matlab_list_ve if(_matlab_result_version_call MATCHES "timeout") if(MATLAB_FIND_DEBUG) message(WARNING "[MATLAB] Unable to determine the version of Matlab." - " Matlab call timed out after 120 seconds.") + " Matlab call with -r option timed out after 120 seconds.") endif() - return() + set(_matlab_get_version_failed_with_r_option TRUE) endif() - if(${_matlab_result_version_call}) + if(NOT ${_matlab_get_version_failed_with_r_option} AND ${_matlab_result_version_call}) if(MATLAB_FIND_DEBUG) - message(WARNING "[MATLAB] Unable to determine the version of Matlab. Matlab call returned with error ${_matlab_result_version_call}.") + message(WARNING "[MATLAB] Unable to determine the version of Matlab. Matlab call with -r option returned with error ${_matlab_result_version_call}.") endif() - return() - elseif(NOT EXISTS "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp") + set(_matlab_get_version_failed_with_r_option TRUE) + elseif(NOT ${_matlab_get_version_failed_with_r_option} AND NOT EXISTS "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp") if(MATLAB_FIND_DEBUG) message(WARNING "[MATLAB] Unable to determine the version of Matlab. The log file does not exist.") endif() - return() + set(_matlab_get_version_failed_with_r_option TRUE) + endif() + + if(_matlab_get_version_failed_with_r_option) + execute_process( + COMMAND "${matlab_binary_program}" -nosplash -nojvm ${_matlab_additional_commands} -logfile "matlabVersionLog.cmaketmp" -nodesktop -nodisplay -batch "version, exit" + OUTPUT_VARIABLE _matlab_version_from_cmd_dummy_batch + RESULT_VARIABLE _matlab_result_version_call_batch + ERROR_VARIABLE _matlab_result_version_call_error_batch + TIMEOUT 120 + WORKING_DIRECTORY "${_matlab_temporary_folder}" + ${devnull} + ) + + if(_matlab_result_version_call_batch MATCHES "timeout") + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Unable to determine the version of Matlab." + " Matlab call with -batch option timed out after 120 seconds.") + endif() + return() + endif() + + if(${_matlab_result_version_call_batch}) + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Command executed \"${matlab_binary_program}\" -nosplash -nojvm ${_matlab_additional_commands} -logfile \"matlabVersionLog.cmaketmp\" -nodesktop -nodisplay -batch \"version, exit\"") + message(WARNING "_matlab_version_from_cmd_dummy_batch (OUTPUT_VARIABLE): ${_matlab_version_from_cmd_dummy_batch}") + message(WARNING "_matlab_result_version_call_batch (RESULT_VARIABLE): ${_matlab_result_version_call_batch}") + message(WARNING "_matlab_result_version_call_error_batch (ERROR_VARIABLE): ${_matlab_result_version_call_error_batch}") + message(WARNING "[MATLAB] Unable to determine the version of Matlab. Matlab call with -batch option returned with error ${_matlab_result_version_call_batch}.") + endif() + return() + elseif(NOT ${_matlab_get_version_failed_with_r_option} AND NOT EXISTS "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp") + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Unable to determine the version of Matlab. The log file does not exist.") + endif() + return() + endif() endif() # if successful, read back the log @@ -927,6 +968,16 @@ function(matlab_add_unit_test) message(FATAL_ERROR "[MATLAB] The Matlab test name cannot be empty") endif() + # The option to run a batch program with MATLAB changes depending on the MATLAB version + # For MATLAB before R2019a (9.6), the only supported option is -r, afterwords the suggested option + # is -batch as -r is deprecated + set(maut_BATCH_OPTION "-r") + if(NOT (Matlab_VERSION_STRING STREQUAL "")) + if(Matlab_VERSION_STRING VERSION_GREATER_EQUAL "9.6") + set(maut_BATCH_OPTION "-batch") + endif() + endif() + add_test(NAME ${${prefix}_NAME} COMMAND ${CMAKE_COMMAND} "-Dtest_name=${${prefix}_NAME}" @@ -940,6 +991,7 @@ function(matlab_add_unit_test) "-Dunittest_file_to_run=${${prefix}_UNITTEST_FILE}" "-Dcustom_Matlab_test_command=${${prefix}_CUSTOM_TEST_COMMAND}" "-Dcmd_to_run_before_test=${${prefix}_UNITTEST_PRECOMMAND}" + "-Dmaut_BATCH_OPTION=${maut_BATCH_OPTION}" -P ${_FindMatlab_SELF_DIR}/MatlabTestsRedirect.cmake ${${prefix}_TEST_ARGS} ${${prefix}_UNPARSED_ARGUMENTS} @@ -968,6 +1020,7 @@ endfunction() [LINK_TO target1 target2 ...] [R2017b | R2018a] [EXCLUDE_FROM_ALL] + [NO_IMPLICIT_LINK_TO_MATLAB_LIBRARIES] [...] ) @@ -977,7 +1030,8 @@ endfunction() list of source files. ``LINK_TO`` a list of additional link dependencies. The target links to ``libmex`` - and ``libmx`` by default. + and ``libmx`` by default, unless the + ``NO_IMPLICIT_LINK_TO_MATLAB_LIBRARIES`` option is passed. ``OUTPUT_NAME`` if given, overrides the default name. The default name is the name of the target without any prefix and @@ -1013,6 +1067,12 @@ endfunction() This option has the same meaning as for :prop_tgt:`EXCLUDE_FROM_ALL` and is forwarded to :command:`add_library` or :command:`add_executable` commands. + ``NO_IMPLICIT_LINK_TO_MATLAB_LIBRARIES`` + .. versionadded:: 3.24 + + This option permits to disable the automatic linking of MATLAB + libraries, so that only the libraries that are actually required can be + linked via the ``LINK_TO`` option. The documentation file is not processed and should be in the following format: @@ -1039,7 +1099,7 @@ function(matlab_add_mex) endif() - set(options EXECUTABLE MODULE SHARED R2017b R2018a EXCLUDE_FROM_ALL) + set(options EXECUTABLE MODULE SHARED R2017b R2018a EXCLUDE_FROM_ALL NO_IMPLICIT_LINK_TO_MATLAB_LIBRARIES) set(oneValueArgs NAME DOCUMENTATION OUTPUT_NAME) set(multiValueArgs LINK_TO SRC) @@ -1111,16 +1171,19 @@ function(matlab_add_mex) target_include_directories(${${prefix}_NAME} PRIVATE ${Matlab_INCLUDE_DIRS}) - if(Matlab_HAS_CPP_API) - if(Matlab_ENGINE_LIBRARY) - target_link_libraries(${${prefix}_NAME} ${Matlab_ENGINE_LIBRARY}) - endif() - if(Matlab_DATAARRAY_LIBRARY) - target_link_libraries(${${prefix}_NAME} ${Matlab_DATAARRAY_LIBRARY}) + if(NOT ${prefix}_NO_IMPLICIT_LINK_TO_MATLAB_LIBRARIES) + if(Matlab_HAS_CPP_API) + if(Matlab_ENGINE_LIBRARY) + target_link_libraries(${${prefix}_NAME} ${Matlab_ENGINE_LIBRARY}) + endif() + if(Matlab_DATAARRAY_LIBRARY) + target_link_libraries(${${prefix}_NAME} ${Matlab_DATAARRAY_LIBRARY}) + endif() endif() - endif() - target_link_libraries(${${prefix}_NAME} ${Matlab_MEX_LIBRARY} ${Matlab_MX_LIBRARY} ${${prefix}_LINK_TO}) + target_link_libraries(${${prefix}_NAME} ${Matlab_MEX_LIBRARY} ${Matlab_MX_LIBRARY}) + endif() + target_link_libraries(${${prefix}_NAME} ${${prefix}_LINK_TO}) set_target_properties(${${prefix}_NAME} PROPERTIES PREFIX "" diff --git a/Modules/FindOpenCL.cmake b/Modules/FindOpenCL.cmake index 1b4662b..5c7aa22 100644 --- a/Modules/FindOpenCL.cmake +++ b/Modules/FindOpenCL.cmake @@ -45,7 +45,7 @@ function(_FIND_OPENCL_VERSION) set(CMAKE_REQUIRED_QUIET ${OpenCL_FIND_QUIETLY}) CMAKE_PUSH_CHECK_STATE() - foreach(VERSION "2_2" "2_1" "2_0" "1_2" "1_1" "1_0") + foreach(VERSION "3_0" "2_2" "2_1" "2_0" "1_2" "1_1" "1_0") set(CMAKE_REQUIRED_INCLUDES "${OpenCL_INCLUDE_DIR}") if(APPLE) diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake index 929a809..ecfb7f9 100644 --- a/Modules/FindOpenMP.cmake +++ b/Modules/FindOpenMP.cmake @@ -102,6 +102,7 @@ function(_OPENMP_FLAG_CANDIDATES LANG) unset(OpenMP_FLAG_CANDIDATES) set(OMP_FLAG_GNU "-fopenmp") + set(OMP_FLAG_LCC "-fopenmp") set(OMP_FLAG_Clang "-fopenmp=libomp" "-fopenmp=libiomp5" "-fopenmp" "-Xclang -fopenmp") set(OMP_FLAG_AppleClang "-Xclang -fopenmp") set(OMP_FLAG_HP "+Oopenmp") diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake index 8474e05..9278566 100644 --- a/Modules/FindOpenSSL.cmake +++ b/Modules/FindOpenSSL.cmake @@ -124,7 +124,11 @@ function(_OpenSSL_target_add_dependencies target) set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS} ) endif() if(WIN32 AND OPENSSL_USE_STATIC_LIBS) - set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ws2_32 ) + if(WINCE) + set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ws2 ) + else() + set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ws2_32 ) + endif() set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES crypt32 ) endif() endfunction() @@ -144,6 +148,19 @@ if(OPENSSL_USE_STATIC_LIBS) endif() endif() +if(CMAKE_SYSTEM_NAME STREQUAL "QNX" AND + CMAKE_SYSTEM_VERSION VERSION_GREATER_EQUAL "7.0" AND CMAKE_SYSTEM_VERSION VERSION_LESS "7.1" AND + OpenSSL_FIND_VERSION VERSION_GREATER_EQUAL "1.1" AND OpenSSL_FIND_VERSION VERSION_LESS "1.2") + # QNX 7.0.x provides openssl 1.0.2 and 1.1.1 in parallel: + # * openssl 1.0.2: libcrypto.so.2 and libssl.so.2, headers under usr/include/openssl + # * openssl 1.1.1: libcrypto1_1.so.2.1 and libssl1_1.so.2.1, header under usr/include/openssl1_1 + # See http://www.qnx.com/developers/articles/rel_6726_0.html + set(_OPENSSL_FIND_PATH_SUFFIX "openssl1_1") + set(_OPENSSL_NAME_POSTFIX "1_1") +else() + set(_OPENSSL_FIND_PATH_SUFFIX "include") +endif() + if (WIN32) # http://www.slproweb.com/products/Win32OpenSSL.html set(_OPENSSL_ROOT_HINTS @@ -196,7 +213,7 @@ find_path(OPENSSL_INCLUDE_DIR ${_OPENSSL_INCLUDEDIR} ${_OPENSSL_INCLUDE_DIRS} PATH_SUFFIXES - include + ${_OPENSSL_FIND_PATH_SUFFIX} ) if(WIN32 AND NOT CYGWIN) @@ -426,7 +443,7 @@ else() find_library(OPENSSL_SSL_LIBRARY NAMES - ssl + ssl${_OPENSSL_NAME_POSTFIX} ssleay32 ssleay32MD NAMES_PER_DIR @@ -435,19 +452,19 @@ else() ${_OPENSSL_LIBDIR} ${_OPENSSL_LIBRARY_DIRS} PATH_SUFFIXES - lib + lib lib64 ) find_library(OPENSSL_CRYPTO_LIBRARY NAMES - crypto + crypto${_OPENSSL_NAME_POSTFIX} NAMES_PER_DIR ${_OPENSSL_ROOT_HINTS_AND_PATHS} HINTS ${_OPENSSL_LIBDIR} ${_OPENSSL_LIBRARY_DIRS} PATH_SUFFIXES - lib + lib lib64 ) mark_as_advanced(OPENSSL_CRYPTO_LIBRARY OPENSSL_SSL_LIBRARY) @@ -538,6 +555,14 @@ if(OPENSSL_INCLUDE_DIR AND EXISTS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h") set(OPENSSL_VERSION "${OPENSSL_VERSION_STR}") + # Setting OPENSSL_VERSION_MAJOR OPENSSL_VERSION_MINOR and OPENSSL_VERSION_FIX + string(REGEX MATCHALL "([0-9])+" OPENSSL_VERSION_NUMBER "${OPENSSL_VERSION}") + list(POP_FRONT OPENSSL_VERSION_NUMBER + OPENSSL_VERSION_MAJOR + OPENSSL_VERSION_MINOR + OPENSSL_VERSION_FIX) + + unset(OPENSSL_VERSION_NUMBER) unset(OPENSSL_VERSION_STR) endif () endif () @@ -650,7 +675,7 @@ if(OPENSSL_FOUND) _OpenSSL_target_add_dependencies(OpenSSL::SSL) endif() - if("${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_FIX}" VERSION_GREATER_EQUAL "0.9.8") + if("${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MINOR}.${OPENSSL_VERSION_FIX}" VERSION_GREATER_EQUAL "0.9.8") if(MSVC) if(EXISTS "${OPENSSL_INCLUDE_DIR}") set(_OPENSSL_applink_paths PATHS ${OPENSSL_INCLUDE_DIR}) @@ -677,3 +702,6 @@ endif() if(OPENSSL_USE_STATIC_LIBS) set(CMAKE_FIND_LIBRARY_SUFFIXES ${_openssl_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) endif() + +unset(_OPENSSL_FIND_PATH_SUFFIX) +unset(_OPENSSL_NAME_POSTFIX) diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake index ab8af3e..02f7fb4 100644 --- a/Modules/FindPkgConfig.cmake +++ b/Modules/FindPkgConfig.cmake @@ -143,7 +143,9 @@ macro(_pkgconfig_invoke _pkglist _prefix _varname _regexp) string(REGEX REPLACE "${_regexp}" " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}") endif() - separate_arguments(_pkgconfig_invoke_result) + # pkg-config can represent "spaces within an argument" by backslash-escaping the space. + # UNIX_COMMAND mode treats backslash-escaped spaces as "not a space that delimits arguments". + separate_arguments(_pkgconfig_invoke_result UNIX_COMMAND "${_pkgconfig_invoke_result}") #message(STATUS " ${_varname} ... ${_pkgconfig_invoke_result}") set(_pkgconfig_${_varname} ${_pkgconfig_invoke_result}) diff --git a/Modules/FindPostgreSQL.cmake b/Modules/FindPostgreSQL.cmake index 147071a..2233aa0 100644 --- a/Modules/FindPostgreSQL.cmake +++ b/Modules/FindPostgreSQL.cmake @@ -53,7 +53,7 @@ is set regardless of the presence of the ``Server`` component in find_package ca # In Windows the default installation of PostgreSQL uses that as part of the path. # E.g C:\Program Files\PostgreSQL\8.4. # Currently, the following version numbers are known to this module: -# "11" "10" "9.6" "9.5" "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0" +# "14" "13" "12" "11" "10" "9.6" "9.5" "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0" # # To use this variable just do something like this: # set(PostgreSQL_ADDITIONAL_VERSIONS "9.2" "8.4.4") @@ -102,7 +102,7 @@ set(PostgreSQL_ROOT_DIR_MESSAGE "Set the PostgreSQL_ROOT system variable to wher set(PostgreSQL_KNOWN_VERSIONS ${PostgreSQL_ADDITIONAL_VERSIONS} - "13" "12" "11" "10" "9.6" "9.5" "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0") + "14" "13" "12" "11" "10" "9.6" "9.5" "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0") # Define additional search paths for root directories. set( PostgreSQL_ROOT_DIRECTORIES diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake index afe9743..c4fae6b 100644 --- a/Modules/FindPython/Support.cmake +++ b/Modules/FindPython/Support.cmake @@ -22,7 +22,7 @@ if (NOT DEFINED _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) message (FATAL_ERROR "FindPython: INTERNAL ERROR") endif() if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL "3") - set(_${_PYTHON_PREFIX}_VERSIONS 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) + set(_${_PYTHON_PREFIX}_VERSIONS 3.12 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) elseif (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL "2") set(_${_PYTHON_PREFIX}_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0) else() @@ -415,7 +415,6 @@ function (_PYTHON_GET_NAMES _PYTHON_PGN_NAMES) if (_PGN_WIN32) foreach (version IN LISTS _PGN_VERSION) string (REPLACE "." "" version_no_dots ${version}) - set (name "python${version_no_dots}") if (_PGN_DEBUG) string (APPEND name "_d") @@ -423,6 +422,13 @@ function (_PYTHON_GET_NAMES _PYTHON_PGN_NAMES) list (APPEND names "${name}") endforeach() endif() + + if (_PGN_POSIX) + foreach(version IN LISTS _PGN_VERSION) + list (APPEND names "pypy${version}-c") + endforeach() + endif() + list (APPEND names ${_${_PYTHON_PREFIX}_PYPY_LIB_NAMES}) endif() endif() @@ -588,6 +594,11 @@ function (_PYTHON_GET_VERSION) set (${_PGV_PREFIX}VERSION_MINOR "${CMAKE_MATCH_2}" PARENT_SCOPE) set (${_PGV_PREFIX}VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}" PARENT_SCOPE) set (${_PGV_PREFIX}ABI "${CMAKE_MATCH_3}" PARENT_SCOPE) + elseif (library_name MATCHES "pypy([23])\\.([0-9]+)-c") + set (${_PGV_PREFIX}VERSION_MAJOR "${CMAKE_MATCH_1}" PARENT_SCOPE) + set (${_PGV_PREFIX}VERSION_MINOR "${CMAKE_MATCH_2}" PARENT_SCOPE) + set (${_PGV_PREFIX}VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}" PARENT_SCOPE) + set (${_PGV_PREFIX}ABI "" PARENT_SCOPE) elseif (library_name MATCHES "pypy(3)?-c") set (version "${CMAKE_MATCH_1}") # try to pick-up a more precise version from the path @@ -663,7 +674,7 @@ endfunction() function (_PYTHON_GET_LAUNCHER _PYTHON_PGL_NAME) cmake_parse_arguments (PARSE_ARGV 1 _PGL "INTERPRETER;COMPILER" "" "") - unset ({_PYTHON_PGL_NAME} PARENT_SCOPE) + unset (${_PYTHON_PGL_NAME} PARENT_SCOPE) if ((_PGL_INTERPRETER AND NOT _${_PYTHON_PREFIX}_EXECUTABLE) OR (_PGL_COMPILER AND NOT _${_PYTHON_PREFIX}_COMPILER)) @@ -1237,9 +1248,18 @@ endif() # Python and Anaconda distributions: define which architectures can be used if (CMAKE_SIZEOF_VOID_P) - # In this case, search only for 64bit or 32bit math (EXPR _${_PYTHON_PREFIX}_ARCH "${CMAKE_SIZEOF_VOID_P} * 8") - set (_${_PYTHON_PREFIX}_ARCH2 ${_${_PYTHON_PREFIX}_ARCH}) + if ("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS + OR "Development.Embed" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) + # In this case, search only for 64bit or 32bit + set (_${_PYTHON_PREFIX}_ARCH2 ${_${_PYTHON_PREFIX}_ARCH}) + else() + if (_${_PYTHON_PREFIX}_ARCH EQUAL "32") + set (_${_PYTHON_PREFIX}_ARCH2 64) + else() + set (_${_PYTHON_PREFIX}_ARCH2 32) + endif() + endif() else() # architecture unknown, search for both 64bit and 32bit set (_${_PYTHON_PREFIX}_ARCH 64) @@ -2841,7 +2861,8 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() unset (_${_PYTHON_PREFIX}_INCLUDE_HINTS) - if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE) + if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS + AND _${_PYTHON_PREFIX}_LIBRARY_RELEASE) # Use the library's install prefix as a hint if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "^(.+/Frameworks/Python.framework/Versions/[0-9.]+)") list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${CMAKE_MATCH_1}") @@ -2925,7 +2946,8 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS if (_${_PYTHON_PREFIX}_INCLUDE_DIR) # retrieve version from header file _python_get_version (INCLUDE PREFIX _${_PYTHON_PREFIX}_INC_) - if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE) + if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS + AND _${_PYTHON_PREFIX}_LIBRARY_RELEASE) if ("${_${_PYTHON_PREFIX}_INC_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_INC_VERSION_MINOR}" VERSION_EQUAL _${_PYTHON_PREFIX}_VERSION) # update versioning diff --git a/Modules/FindPythonInterp.cmake b/Modules/FindPythonInterp.cmake index 4fc40c8..7ad3587 100644 --- a/Modules/FindPythonInterp.cmake +++ b/Modules/FindPythonInterp.cmake @@ -54,7 +54,7 @@ unset(_Python_NAMES) set(_PYTHON1_VERSIONS 1.6 1.5) set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0) -set(_PYTHON3_VERSIONS 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) +set(_PYTHON3_VERSIONS 3.12 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) if(PythonInterp_FIND_VERSION) if(PythonInterp_FIND_VERSION_COUNT GREATER 1) diff --git a/Modules/FindPythonLibs.cmake b/Modules/FindPythonLibs.cmake index c0caf34..43a84dd 100644 --- a/Modules/FindPythonLibs.cmake +++ b/Modules/FindPythonLibs.cmake @@ -79,7 +79,7 @@ set(CMAKE_FIND_FRAMEWORK LAST) set(_PYTHON1_VERSIONS 1.6 1.5) set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0) -set(_PYTHON3_VERSIONS 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) +set(_PYTHON3_VERSIONS 3.12 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) if(PythonLibs_FIND_VERSION) if(PythonLibs_FIND_VERSION_COUNT GREATER 1) diff --git a/Modules/FindRuby.cmake b/Modules/FindRuby.cmake index 759f57c..a80758d 100644 --- a/Modules/FindRuby.cmake +++ b/Modules/FindRuby.cmake @@ -8,7 +8,7 @@ FindRuby Find Ruby This module finds if Ruby is installed and determines where the -include files and libraries are. Ruby 1.8 through 2.7 are +include files and libraries are. Ruby 1.8 through 3.1 are supported. The minimum required version of Ruby can be specified using the @@ -139,13 +139,13 @@ set(Ruby_FIND_VERSION_SHORT_NODOT "${Ruby_FIND_VERSION_MAJOR}${Ruby_FIND_VERSION # Set name of possible executables, ignoring the minor # Eg: -# 2.1.1 => from ruby27 to ruby21 included -# 2.1 => from ruby27 to ruby21 included -# 2 => from ruby26 to ruby20 included -# empty => from ruby27 to ruby18 included +# 2.1.1 => from ruby31 to ruby21 included +# 2.1 => from ruby31 to ruby21 included +# 2 => from ruby31 to ruby20 included +# empty => from ruby31 to ruby18 included if(NOT Ruby_FIND_VERSION_EXACT) - foreach(_ruby_version RANGE 27 18 -1) + foreach(_ruby_version RANGE 31 18 -1) string(SUBSTRING "${_ruby_version}" 0 1 _ruby_major_version) string(SUBSTRING "${_ruby_version}" 1 1 _ruby_minor_version) @@ -266,9 +266,20 @@ while(1) _RUBY_VALIDATE_INTERPRETER (${Ruby_FIND_VERSION}) if (Ruby_EXECUTABLE) break() + else() + # Remove first entry from names list. + LIST(REMOVE_AT _Ruby_POSSIBLE_EXECUTABLE_NAMES 0) + + # If the list is now empty, abort. + if (NOT _Ruby_POSSIBLE_EXECUTABLE_NAMES) + break() + else() + # Otherwise, continue with the remaining list. Make sure that we clear + # the cached variable. + unset(Ruby_EXECUTABLE CACHE) + endif() endif() - break() endwhile() if(Ruby_EXECUTABLE AND NOT Ruby_VERSION_MAJOR) @@ -398,6 +409,16 @@ if(Ruby_EXECUTABLE AND NOT Ruby_VERSION_MAJOR) set(Ruby_VERSION_MAJOR 2) set(Ruby_VERSION_MINOR 7) endif() + # check whether we found 3.0.x + if(${Ruby_EXECUTABLE} MATCHES "ruby3\\.?0") + set(Ruby_VERSION_MAJOR 3) + set(Ruby_VERSION_MINOR 0) + endif() + # check whether we found 3.1.x + if(${Ruby_EXECUTABLE} MATCHES "ruby3\\.?1") + set(Ruby_VERSION_MAJOR 3) + set(Ruby_VERSION_MINOR 1) + endif() endif() if(Ruby_VERSION_MAJOR) diff --git a/Modules/FindThreads.cmake b/Modules/FindThreads.cmake index e4d6cf3..a2304c2 100644 --- a/Modules/FindThreads.cmake +++ b/Modules/FindThreads.cmake @@ -91,12 +91,27 @@ int main(void) # Internal helper macro. # Do NOT even think about using it outside of this file! -macro(_check_threads_lib LIBNAME FUNCNAME VARNAME) +macro(_threads_check_libc) + if(NOT Threads_FOUND) + if(CMAKE_C_COMPILER_LOADED) + CHECK_C_SOURCE_COMPILES("${PTHREAD_C_CXX_TEST_SOURCE}" CMAKE_HAVE_LIBC_PTHREAD) + elseif(CMAKE_CXX_COMPILER_LOADED) + CHECK_CXX_SOURCE_COMPILES("${PTHREAD_C_CXX_TEST_SOURCE}" CMAKE_HAVE_LIBC_PTHREAD) + endif() + if(CMAKE_HAVE_LIBC_PTHREAD) + set(CMAKE_THREAD_LIBS_INIT "") + set(Threads_FOUND TRUE) + endif() + endif () +endmacro() + +# Internal helper macro. +# Do NOT even think about using it outside of this file! +macro(_threads_check_lib LIBNAME FUNCNAME VARNAME) if(NOT Threads_FOUND) CHECK_LIBRARY_EXISTS(${LIBNAME} ${FUNCNAME} "" ${VARNAME}) if(${VARNAME}) set(CMAKE_THREAD_LIBS_INIT "-l${LIBNAME}") - set(CMAKE_HAVE_THREADS_LIBRARY 1) set(Threads_FOUND TRUE) endif() endif () @@ -104,7 +119,7 @@ endmacro() # Internal helper macro. # Do NOT even think about using it outside of this file! -macro(_check_pthreads_flag) +macro(_threads_check_flag_pthread) if(NOT Threads_FOUND) # If we did not find -lpthreads, -lpthread, or -lthread, look for -pthread if(NOT DEFINED THREADS_HAVE_PTHREAD_ARG) @@ -141,54 +156,27 @@ macro(_check_pthreads_flag) endif() endmacro() -# Do we have pthreads? -if(CMAKE_C_COMPILER_LOADED) - CHECK_INCLUDE_FILE("pthread.h" CMAKE_HAVE_PTHREAD_H) -else() - CHECK_INCLUDE_FILE_CXX("pthread.h" CMAKE_HAVE_PTHREAD_H) +# Check if pthread functions are in normal C library. +# We list some pthread functions in PTHREAD_C_CXX_TEST_SOURCE test code. +# If the pthread functions already exist in C library, we could just use +# them instead of linking to the additional pthread library. +_threads_check_libc() + +# Check for -pthread first if enabled. This is the recommended +# way, but not backwards compatible as one must also pass -pthread +# as compiler flag then. +if (THREADS_PREFER_PTHREAD_FLAG) + _threads_check_flag_pthread() +endif () + +if(CMAKE_SYSTEM MATCHES "GHS-MULTI") + _threads_check_lib(posix pthread_create CMAKE_HAVE_PTHREADS_CREATE) endif() +_threads_check_lib(pthreads pthread_create CMAKE_HAVE_PTHREADS_CREATE) +_threads_check_lib(pthread pthread_create CMAKE_HAVE_PTHREAD_CREATE) -if(CMAKE_HAVE_PTHREAD_H) - # - # We have pthread.h - # Let's check for the library now. - # - set(CMAKE_HAVE_THREADS_LIBRARY) - if(NOT THREADS_HAVE_PTHREAD_ARG) - # Check if pthread functions are in normal C library. - # We list some pthread functions in PTHREAD_C_CXX_TEST_SOURCE test code. - # If the pthread functions already exist in C library, we could just use - # them instead of linking to the additional pthread library. - if(CMAKE_C_COMPILER_LOADED) - CHECK_C_SOURCE_COMPILES("${PTHREAD_C_CXX_TEST_SOURCE}" CMAKE_HAVE_LIBC_PTHREAD) - elseif(CMAKE_CXX_COMPILER_LOADED) - CHECK_CXX_SOURCE_COMPILES("${PTHREAD_C_CXX_TEST_SOURCE}" CMAKE_HAVE_LIBC_PTHREAD) - endif() - if(CMAKE_HAVE_LIBC_PTHREAD) - set(CMAKE_THREAD_LIBS_INIT "") - set(CMAKE_HAVE_THREADS_LIBRARY 1) - set(Threads_FOUND TRUE) - else() - # Check for -pthread first if enabled. This is the recommended - # way, but not backwards compatible as one must also pass -pthread - # as compiler flag then. - if (THREADS_PREFER_PTHREAD_FLAG) - _check_pthreads_flag() - endif () - - if(CMAKE_SYSTEM MATCHES "GHS-MULTI") - _check_threads_lib(posix pthread_create CMAKE_HAVE_PTHREADS_CREATE) - endif() - _check_threads_lib(pthreads pthread_create CMAKE_HAVE_PTHREADS_CREATE) - _check_threads_lib(pthread pthread_create CMAKE_HAVE_PTHREAD_CREATE) - if(CMAKE_SYSTEM_NAME MATCHES "SunOS") - # On sun also check for -lthread - _check_threads_lib(thread thr_create CMAKE_HAVE_THR_CREATE) - endif() - endif() - endif() - - _check_pthreads_flag() +if (NOT THREADS_PREFER_PTHREAD_FLAG) + _threads_check_flag_pthread() endif() if(CMAKE_THREAD_LIBS_INIT OR CMAKE_HAVE_LIBC_PTHREAD) diff --git a/Modules/FindVulkan.cmake b/Modules/FindVulkan.cmake index 4f48e13..8b322ed 100644 --- a/Modules/FindVulkan.cmake +++ b/Modules/FindVulkan.cmake @@ -10,6 +10,16 @@ FindVulkan Find Vulkan, which is a low-overhead, cross-platform 3D graphics and computing API. +Optional COMPONENTS +^^^^^^^^^^^^^^^^^^^ + +.. versionadded:: 3.24 + +This module respects several optional COMPONENTS: ``glslc``, +``glslangValidator``, ``glslang``, ``shaderc_combined`` and ``SPIRV-Tools``. +On macOS, an additional component ``MoltenVK`` is available. +There are corresponding import targets for each of these flags. + IMPORTED Targets ^^^^^^^^^^^^^^^^ @@ -36,21 +46,96 @@ This module defines :prop_tgt:`IMPORTED` targets if Vulkan has been found: The glslangValidator tool, if found. It is used to compile GLSL and HLSL shaders into SPIR-V. +``Vulkan::glslang`` + .. versionadded:: 3.24 + + Defined if SDK has the Khronos-reference front-end shader parser and SPIR-V + generator library (glslang). + +``Vulkan::shaderc_combined`` + .. versionadded:: 3.24 + + Defined if SDK has the Google static library for Vulkan shader compilation + (shaderc_combined). + +``Vulkan::SPIRV-Tools`` + .. versionadded:: 3.24 + + Defined if SDK has the Khronos library to process SPIR-V modules + (SPIRV-Tools). + +``Vulkan::MoltenVK`` + .. versionadded:: 3.24 + + Defined if SDK has the Khronos library which implement a subset of Vulkan API + over Apple Metal graphics framework. (MoltenVK). + Result Variables ^^^^^^^^^^^^^^^^ -This module defines the following variables:: +This module defines the following variables: + +``Vulkan_FOUND`` + set to true if Vulkan was found +``Vulkan_INCLUDE_DIRS`` + include directories for Vulkan +``Vulkan_LIBRARIES`` + link against this library to use Vulkan +``Vulkan_VERSION`` + .. versionadded:: 3.23 + + value from ``vulkan/vulkan_core.h`` +``Vulkan_glslc_FOUND`` + .. versionadded:: 3.24 + + True, if the SDK has the glslc executable. +``Vulkan_glslangValidator_FOUND`` + .. versionadded:: 3.24 + + True, if the SDK has the glslangValidator executable. +``Vulkan_glslang_FOUND`` + .. versionadded:: 3.24 + + True, if the SDK has the glslang library. +``Vulkan_shaderc_combined_FOUND`` + .. versionadded:: 3.24 + + True, if the SDK has the shaderc_combined library. +``Vulkan_SPIRV-Tools_FOUND`` + .. versionadded:: 3.24 + + True, if the SDK has the SPIRV-Tools library. +``Vulkan_MoltenVK_FOUND`` + .. versionadded:: 3.24 + + True, if the SDK has the MoltenVK library. - Vulkan_FOUND - "True" if Vulkan was found - Vulkan_INCLUDE_DIRS - include directories for Vulkan - Vulkan_LIBRARIES - link against this library to use Vulkan +The module will also defines these cache variables: -The module will also define three cache variables:: +``Vulkan_INCLUDE_DIR`` + the Vulkan include directory +``Vulkan_LIBRARY`` + the path to the Vulkan library +``Vulkan_GLSLC_EXECUTABLE`` + the path to the GLSL SPIR-V compiler +``Vulkan_GLSLANG_VALIDATOR_EXECUTABLE`` + the path to the glslangValidator tool +``Vulkan_glslang_LIBRARY`` + .. versionadded:: 3.24 - Vulkan_INCLUDE_DIR - the Vulkan include directory - Vulkan_LIBRARY - the path to the Vulkan library - Vulkan_GLSLC_EXECUTABLE - the path to the GLSL SPIR-V compiler - Vulkan_GLSLANG_VALIDATOR_EXECUTABLE - the path to the glslangValidator tool + Path to the glslang library. +``Vulkan_shaderc_combined_LIBRARY`` + .. versionadded:: 3.24 + + Path to the shaderc_combined library. +``Vulkan_SPIRV-Tools_LIBRARY`` + .. versionadded:: 3.24 + + Path to the SPIRV-Tools library. +``Vulkan_MoltenVK_LIBRARY`` + .. versionadded:: 3.24 + + Path to the MoltenVK library. Hints ^^^^^ @@ -65,73 +150,350 @@ environment. #]=======================================================================] -if(WIN32) - find_path(Vulkan_INCLUDE_DIR - NAMES vulkan/vulkan.h - HINTS - "$ENV{VULKAN_SDK}/Include" - ) +cmake_policy(PUSH) +cmake_policy(SET CMP0057 NEW) + +# For backward compatibility as `FindVulkan` in previous CMake versions allow to retrieve `glslc` +# and `glslangValidator` without requesting the corresponding component. +if(NOT glslc IN_LIST Vulkan_FIND_COMPONENTS) + list(APPEND Vulkan_FIND_COMPONENTS glslc) +endif() +if(NOT glslangValidator IN_LIST Vulkan_FIND_COMPONENTS) + list(APPEND Vulkan_FIND_COMPONENTS glslangValidator) +endif() +if(WIN32) + set(_Vulkan_library_name vulkan-1) + set(_Vulkan_hint_include_search_paths + "$ENV{VULKAN_SDK}/Include" + ) if(CMAKE_SIZEOF_VOID_P EQUAL 8) - find_library(Vulkan_LIBRARY - NAMES vulkan-1 - HINTS - "$ENV{VULKAN_SDK}/Lib" - "$ENV{VULKAN_SDK}/Bin" - ) - find_program(Vulkan_GLSLC_EXECUTABLE - NAMES glslc - HINTS - "$ENV{VULKAN_SDK}/Bin" - ) - find_program(Vulkan_GLSLANG_VALIDATOR_EXECUTABLE - NAMES glslangValidator - HINTS - "$ENV{VULKAN_SDK}/Bin" - ) - elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) - find_library(Vulkan_LIBRARY - NAMES vulkan-1 - HINTS - "$ENV{VULKAN_SDK}/Lib32" - "$ENV{VULKAN_SDK}/Bin32" + set(_Vulkan_hint_executable_search_paths + "$ENV{VULKAN_SDK}/Bin" + ) + set(_Vulkan_hint_library_search_paths + "$ENV{VULKAN_SDK}/Lib" + "$ENV{VULKAN_SDK}/Bin" + ) + else() + set(_Vulkan_hint_executable_search_paths + "$ENV{VULKAN_SDK}/Bin32" + ) + set(_Vulkan_hint_library_search_paths + "$ENV{VULKAN_SDK}/Lib32" + "$ENV{VULKAN_SDK}/Bin32" + ) + endif() +else() + set(_Vulkan_library_name vulkan) + set(_Vulkan_hint_include_search_paths + "$ENV{VULKAN_SDK}/include" + ) + set(_Vulkan_hint_executable_search_paths + "$ENV{VULKAN_SDK}/bin" + ) + set(_Vulkan_hint_library_search_paths + "$ENV{VULKAN_SDK}/lib" + ) +endif() +if(APPLE AND DEFINED ENV{VULKAN_SDK}) + cmake_path(SET _MoltenVK_path NORMALIZE "$ENV{VULKAN_SDK}/../MoltenVK") + if(EXISTS "${_MoltenVK_path}") + list(APPEND _Vulkan_hint_include_search_paths + "${_MoltenVK_path}/include" + ) + if(CMAKE_SYSTEM_NAME STREQUAL "iOS") + list(APPEND _Vulkan_hint_library_search_paths + "${_MoltenVK_path}/dylib/iOS" ) - find_program(Vulkan_GLSLC_EXECUTABLE - NAMES glslc - HINTS - "$ENV{VULKAN_SDK}/Bin32" + elseif(CMAKE_SYSTEM_NAME STREQUAL "tvOS") + list(APPEND _Vulkan_hint_library_search_paths + "${_MoltenVK_path}/dylib/tvOS" ) - find_program(Vulkan_GLSLANG_VALIDATOR_EXECUTABLE - NAMES glslangValidator - HINTS - "$ENV{VULKAN_SDK}/Bin32" + else() + list(APPEND _Vulkan_hint_library_search_paths + "${_MoltenVK_path}/dylib/macOS" ) + endif() endif() -else() - find_path(Vulkan_INCLUDE_DIR - NAMES vulkan/vulkan.h - HINTS "$ENV{VULKAN_SDK}/include") - find_library(Vulkan_LIBRARY - NAMES vulkan - HINTS "$ENV{VULKAN_SDK}/lib") + unset(_MoltenVK_path) +endif() + +find_path(Vulkan_INCLUDE_DIR + NAMES vulkan/vulkan.h + HINTS + ${_Vulkan_hint_include_search_paths} + ) +mark_as_advanced(Vulkan_INCLUDE_DIR) + +find_library(Vulkan_LIBRARY + NAMES ${_Vulkan_library_name} + HINTS + ${_Vulkan_hint_library_search_paths} + ) +mark_as_advanced(Vulkan_LIBRARY) + +if(glslc IN_LIST Vulkan_FIND_COMPONENTS) find_program(Vulkan_GLSLC_EXECUTABLE NAMES glslc - HINTS "$ENV{VULKAN_SDK}/bin") + HINTS + ${_Vulkan_hint_executable_search_paths} + ) + mark_as_advanced(Vulkan_GLSLC_EXECUTABLE) +endif() +if(glslangValidator IN_LIST Vulkan_FIND_COMPONENTS) find_program(Vulkan_GLSLANG_VALIDATOR_EXECUTABLE NAMES glslangValidator - HINTS "$ENV{VULKAN_SDK}/bin") + HINTS + ${_Vulkan_hint_executable_search_paths} + ) + mark_as_advanced(Vulkan_GLSLANG_VALIDATOR_EXECUTABLE) +endif() +if(glslang IN_LIST Vulkan_FIND_COMPONENTS) + find_library(Vulkan_glslang-spirv_LIBRARY + NAMES SPIRV + HINTS + ${_Vulkan_hint_library_search_paths} + ) + mark_as_advanced(Vulkan_glslang-spirv_LIBRARY) + + find_library(Vulkan_glslang-spirv_DEBUG_LIBRARY + NAMES SPIRVd + HINTS + ${_Vulkan_hint_library_search_paths} + ) + mark_as_advanced(Vulkan_glslang-spirv_DEBUG_LIBRARY) + + find_library(Vulkan_glslang-oglcompiler_LIBRARY + NAMES OGLCompiler + HINTS + ${_Vulkan_hint_library_search_paths} + ) + mark_as_advanced(Vulkan_glslang-oglcompiler_LIBRARY) + + find_library(Vulkan_glslang-oglcompiler_DEBUG_LIBRARY + NAMES OGLCompilerd + HINTS + ${_Vulkan_hint_library_search_paths} + ) + mark_as_advanced(Vulkan_glslang-oglcompiler_DEBUG_LIBRARY) + + find_library(Vulkan_glslang-osdependent_LIBRARY + NAMES OSDependent + HINTS + ${_Vulkan_hint_library_search_paths} + ) + mark_as_advanced(Vulkan_glslang-osdependent_LIBRARY) + + find_library(Vulkan_glslang-osdependent_DEBUG_LIBRARY + NAMES OSDependentd + HINTS + ${_Vulkan_hint_library_search_paths} + ) + mark_as_advanced(Vulkan_glslang-osdependent_DEBUG_LIBRARY) + + find_library(Vulkan_glslang-machineindependent_LIBRARY + NAMES MachineIndependent + HINTS + ${_Vulkan_hint_library_search_paths} + ) + mark_as_advanced(Vulkan_glslang-machineindependent_LIBRARY) + + find_library(Vulkan_glslang-machineindependent_DEBUG_LIBRARY + NAMES MachineIndependentd + HINTS + ${_Vulkan_hint_library_search_paths} + ) + mark_as_advanced(Vulkan_glslang-machineindependent_DEBUG_LIBRARY) + + find_library(Vulkan_glslang-genericcodegen_LIBRARY + NAMES GenericCodeGen + HINTS + ${_Vulkan_hint_library_search_paths} + ) + mark_as_advanced(Vulkan_glslang-genericcodegen_LIBRARY) + + find_library(Vulkan_glslang-genericcodegen_DEBUG_LIBRARY + NAMES GenericCodeGend + HINTS + ${_Vulkan_hint_library_search_paths} + ) + mark_as_advanced(Vulkan_glslang-genericcodegen_DEBUG_LIBRARY) + + find_library(Vulkan_glslang_LIBRARY + NAMES glslang + HINTS + ${_Vulkan_hint_library_search_paths} + ) + mark_as_advanced(Vulkan_glslang_LIBRARY) + + find_library(Vulkan_glslang_DEBUG_LIBRARY + NAMES glslangd + HINTS + ${_Vulkan_hint_library_search_paths} + ) + mark_as_advanced(Vulkan_glslang_DEBUG_LIBRARY) +endif() +if(shaderc_combined IN_LIST Vulkan_FIND_COMPONENTS) + find_library(Vulkan_shaderc_combined_LIBRARY + NAMES shaderc_combined + HINTS + ${_Vulkan_hint_library_search_paths}) + mark_as_advanced(Vulkan_shaderc_combined_LIBRARY) + + find_library(Vulkan_shaderc_combined_DEBUG_LIBRARY + NAMES shaderc_combinedd + HINTS + ${_Vulkan_hint_library_search_paths}) + mark_as_advanced(Vulkan_shaderc_combined_DEBUG_LIBRARY) +endif() +if(SPIRV-Tools IN_LIST Vulkan_FIND_COMPONENTS) + find_library(Vulkan_SPIRV-Tools_LIBRARY + NAMES SPIRV-Tools + HINTS + ${_Vulkan_hint_library_search_paths}) + mark_as_advanced(Vulkan_SPIRV-Tools_LIBRARY) + + find_library(Vulkan_SPIRV-Tools_DEBUG_LIBRARY + NAMES SPIRV-Toolsd + HINTS + ${_Vulkan_hint_library_search_paths}) + mark_as_advanced(Vulkan_SPIRV-Tools_DEBUG_LIBRARY) +endif() +if(MoltenVK IN_LIST Vulkan_FIND_COMPONENTS) + find_library(Vulkan_MoltenVK_LIBRARY + NAMES MoltenVK + HINTS + ${_Vulkan_hint_library_search_paths}) + mark_as_advanced(Vulkan_MoltenVK_LIBRARY) + + find_path(Vulkan_MoltenVK_INCLUDE_DIR + NAMES MoltenVK/mvk_vulkan.h + HINTS + ${_Vulkan_hint_include_search_paths} + ) + mark_as_advanced(Vulkan_MoltenVK_INCLUDE_DIR) +endif() + +if(Vulkan_GLSLC_EXECUTABLE) + set(Vulkan_glslc_FOUND TRUE) +else() + set(Vulkan_glslc_FOUND FALSE) +endif() + +if(Vulkan_GLSLANG_VALIDATOR_EXECUTABLE) + set(Vulkan_glslangValidator_FOUND TRUE) +else() + set(Vulkan_glslangValidator_FOUND FALSE) +endif() + +function(_Vulkan_set_library_component_found component) + cmake_parse_arguments(PARSE_ARGV 1 _ARG + "NO_WARNING" + "" + "DEPENDENT_COMPONENTS") + + set(all_dependent_component_found TRUE) + foreach(dependent_component IN LISTS _ARG_DEPENDENT_COMPONENTS) + if(NOT Vulkan_${dependent_component}_FOUND) + set(all_dependent_component_found FALSE) + break() + endif() + endforeach() + + if(all_dependent_component_found AND (Vulkan_${component}_LIBRARY OR Vulkan_${component}_DEBUG_LIBRARY)) + set(Vulkan_${component}_FOUND TRUE PARENT_SCOPE) + + # For Windows Vulkan SDK, third party tools binaries are provided with different MSVC ABI: + # - Release binaries uses a runtime library + # - Debug binaries uses a debug runtime library + # This lead to incompatibilities in linking for some configuration types due to CMake-default or project-configured selected MSVC ABI. + if(WIN32 AND NOT _ARG_NO_WARNING) + if(NOT Vulkan_${component}_LIBRARY) + message(WARNING +"Library ${component} for Release configuration is missing, imported target Vulkan::${component} may not be able to link when targeting this build configuration due to incompatible MSVC ABI.") + endif() + if(NOT Vulkan_${component}_DEBUG_LIBRARY) + message(WARNING +"Library ${component} for Debug configuration is missing, imported target Vulkan::${component} may not be able to link when targeting this build configuration due to incompatible MSVC ABI. Consider re-installing the Vulkan SDK and request debug libraries to fix this warning.") + endif() + endif() + else() + set(Vulkan_${component}_FOUND FALSE PARENT_SCOPE) + endif() +endfunction() + +_Vulkan_set_library_component_found(glslang-spirv NO_WARNING) +_Vulkan_set_library_component_found(glslang-oglcompiler NO_WARNING) +_Vulkan_set_library_component_found(glslang-osdependent NO_WARNING) +_Vulkan_set_library_component_found(glslang-machineindependent NO_WARNING) +_Vulkan_set_library_component_found(glslang-genericcodegen NO_WARNING) +_Vulkan_set_library_component_found(glslang + DEPENDENT_COMPONENTS + glslang-spirv + glslang-oglcompiler + glslang-osdependent + glslang-machineindependent + glslang-genericcodegen) +_Vulkan_set_library_component_found(shaderc_combined) +_Vulkan_set_library_component_found(SPIRV-Tools) + +if(Vulkan_MoltenVK_INCLUDE_DIR AND Vulkan_MoltenVK_LIBRARY) + set(Vulkan_MoltenVK_FOUND TRUE) +else() + set(Vulkan_MoltenVK_FOUND FALSE) endif() set(Vulkan_LIBRARIES ${Vulkan_LIBRARY}) set(Vulkan_INCLUDE_DIRS ${Vulkan_INCLUDE_DIR}) +# detect version e.g 1.2.189 +set(Vulkan_VERSION "") +if(Vulkan_INCLUDE_DIR) + set(VULKAN_CORE_H ${Vulkan_INCLUDE_DIR}/vulkan/vulkan_core.h) + if(EXISTS ${VULKAN_CORE_H}) + file(STRINGS ${VULKAN_CORE_H} VulkanHeaderVersionLine REGEX "^#define VK_HEADER_VERSION ") + string(REGEX MATCHALL "[0-9]+" VulkanHeaderVersion "${VulkanHeaderVersionLine}") + file(STRINGS ${VULKAN_CORE_H} VulkanHeaderVersionLine2 REGEX "^#define VK_HEADER_VERSION_COMPLETE ") + string(REGEX MATCHALL "[0-9]+" VulkanHeaderVersion2 "${VulkanHeaderVersionLine2}") + list(LENGTH VulkanHeaderVersion2 _len) + # versions >= 1.2.175 have an additional numbers in front of e.g. '0, 1, 2' instead of '1, 2' + if(_len EQUAL 3) + list(REMOVE_AT VulkanHeaderVersion2 0) + endif() + list(APPEND VulkanHeaderVersion2 ${VulkanHeaderVersion}) + list(JOIN VulkanHeaderVersion2 "." Vulkan_VERSION) + endif() +endif() + +if(Vulkan_MoltenVK_FOUND) + set(Vulkan_MoltenVK_VERSION "") + if(Vulkan_MoltenVK_INCLUDE_DIR) + set(VK_MVK_MOLTENVK_H ${Vulkan_MoltenVK_INCLUDE_DIR}/MoltenVK/vk_mvk_moltenvk.h) + if(EXISTS ${VK_MVK_MOLTENVK_H}) + file(STRINGS ${VK_MVK_MOLTENVK_H} _Vulkan_MoltenVK_VERSION_MAJOR REGEX "^#define MVK_VERSION_MAJOR ") + string(REGEX MATCHALL "[0-9]+" _Vulkan_MoltenVK_VERSION_MAJOR "${_Vulkan_MoltenVK_VERSION_MAJOR}") + file(STRINGS ${VK_MVK_MOLTENVK_H} _Vulkan_MoltenVK_VERSION_MINOR REGEX "^#define MVK_VERSION_MINOR ") + string(REGEX MATCHALL "[0-9]+" _Vulkan_MoltenVK_VERSION_MINOR "${_Vulkan_MoltenVK_VERSION_MINOR}") + file(STRINGS ${VK_MVK_MOLTENVK_H} _Vulkan_MoltenVK_VERSION_PATCH REGEX "^#define MVK_VERSION_PATCH ") + string(REGEX MATCHALL "[0-9]+" _Vulkan_MoltenVK_VERSION_PATCH "${_Vulkan_MoltenVK_VERSION_PATCH}") + set(Vulkan_MoltenVK_VERSION "${_Vulkan_MoltenVK_VERSION_MAJOR}.${_Vulkan_MoltenVK_VERSION_MINOR}.${_Vulkan_MoltenVK_VERSION_PATCH}") + unset(_Vulkan_MoltenVK_VERSION_MAJOR) + unset(_Vulkan_MoltenVK_VERSION_MINOR) + unset(_Vulkan_MoltenVK_VERSION_PATCH) + endif() + endif() +endif() + include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) find_package_handle_standard_args(Vulkan - DEFAULT_MSG - Vulkan_LIBRARY Vulkan_INCLUDE_DIR) - -mark_as_advanced(Vulkan_INCLUDE_DIR Vulkan_LIBRARY Vulkan_GLSLC_EXECUTABLE - Vulkan_GLSLANG_VALIDATOR_EXECUTABLE) + REQUIRED_VARS + Vulkan_LIBRARY + Vulkan_INCLUDE_DIR + VERSION_VAR + Vulkan_VERSION + HANDLE_COMPONENTS +) if(Vulkan_FOUND AND NOT TARGET Vulkan::Vulkan) add_library(Vulkan::Vulkan UNKNOWN IMPORTED) @@ -155,3 +517,228 @@ if(Vulkan_FOUND AND Vulkan_GLSLANG_VALIDATOR_EXECUTABLE AND NOT TARGET Vulkan::g add_executable(Vulkan::glslangValidator IMPORTED) set_property(TARGET Vulkan::glslangValidator PROPERTY IMPORTED_LOCATION "${Vulkan_GLSLANG_VALIDATOR_EXECUTABLE}") endif() + +if(Vulkan_FOUND) + if((Vulkan_glslang-spirv_LIBRARY OR Vulkan_glslang-spirv_DEBUG_LIBRARY) AND NOT TARGET Vulkan::glslang-spirv) + add_library(Vulkan::glslang-spirv STATIC IMPORTED) + set_property(TARGET Vulkan::glslang-spirv + PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_INCLUDE_DIRS}") + if(Vulkan_glslang-spirv_LIBRARY) + set_property(TARGET Vulkan::glslang-spirv APPEND + PROPERTY + IMPORTED_CONFIGURATIONS Release) + set_property(TARGET Vulkan::glslang-spirv + PROPERTY + IMPORTED_LOCATION_RELEASE "${Vulkan_glslang-spirv_LIBRARY}") + endif() + if(Vulkan_glslang-spirv_DEBUG_LIBRARY) + set_property(TARGET Vulkan::glslang-spirv APPEND + PROPERTY + IMPORTED_CONFIGURATIONS Debug) + set_property(TARGET Vulkan::glslang-spirv + PROPERTY + IMPORTED_LOCATION_DEBUG "${Vulkan_glslang-spirv_DEBUG_LIBRARY}") + endif() + endif() + + if((Vulkan_glslang-oglcompiler_LIBRARY OR Vulkan_glslang-oglcompiler_DEBUG_LIBRARY) AND NOT TARGET Vulkan::glslang-oglcompiler) + add_library(Vulkan::glslang-oglcompiler STATIC IMPORTED) + set_property(TARGET Vulkan::glslang-oglcompiler + PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_INCLUDE_DIRS}") + if(Vulkan_glslang-oglcompiler_LIBRARY) + set_property(TARGET Vulkan::glslang-oglcompiler APPEND + PROPERTY + IMPORTED_CONFIGURATIONS Release) + set_property(TARGET Vulkan::glslang-oglcompiler + PROPERTY + IMPORTED_LOCATION_RELEASE "${Vulkan_glslang-oglcompiler_LIBRARY}") + endif() + if(Vulkan_glslang-oglcompiler_DEBUG_LIBRARY) + set_property(TARGET Vulkan::glslang-oglcompiler APPEND + PROPERTY + IMPORTED_CONFIGURATIONS Debug) + set_property(TARGET Vulkan::glslang-oglcompiler + PROPERTY + IMPORTED_LOCATION_DEBUG "${Vulkan_glslang-oglcompiler_DEBUG_LIBRARY}") + endif() + endif() + + if((Vulkan_glslang-osdependent_LIBRARY OR Vulkan_glslang-osdependent_DEBUG_LIBRARY) AND NOT TARGET Vulkan::glslang-osdependent) + add_library(Vulkan::glslang-osdependent STATIC IMPORTED) + set_property(TARGET Vulkan::glslang-osdependent + PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_INCLUDE_DIRS}") + if(Vulkan_glslang-osdependent_LIBRARY) + set_property(TARGET Vulkan::glslang-osdependent APPEND + PROPERTY + IMPORTED_CONFIGURATIONS Release) + set_property(TARGET Vulkan::glslang-osdependent + PROPERTY + IMPORTED_LOCATION_RELEASE "${Vulkan_glslang-osdependent_LIBRARY}") + endif() + if(Vulkan_glslang-osdependent_DEBUG_LIBRARY) + set_property(TARGET Vulkan::glslang-osdependent APPEND + PROPERTY + IMPORTED_CONFIGURATIONS Debug) + set_property(TARGET Vulkan::glslang-osdependent + PROPERTY + IMPORTED_LOCATION_DEBUG "${Vulkan_glslang-osdependent_DEBUG_LIBRARY}") + endif() + endif() + + if((Vulkan_glslang-machineindependent_LIBRARY OR Vulkan_glslang-machineindependent_DEBUG_LIBRARY) AND NOT TARGET Vulkan::glslang-machineindependent) + add_library(Vulkan::glslang-machineindependent STATIC IMPORTED) + set_property(TARGET Vulkan::glslang-machineindependent + PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_INCLUDE_DIRS}") + if(Vulkan_glslang-machineindependent_LIBRARY) + set_property(TARGET Vulkan::glslang-machineindependent APPEND + PROPERTY + IMPORTED_CONFIGURATIONS Release) + set_property(TARGET Vulkan::glslang-machineindependent + PROPERTY + IMPORTED_LOCATION_RELEASE "${Vulkan_glslang-machineindependent_LIBRARY}") + endif() + if(Vulkan_glslang-machineindependent_DEBUG_LIBRARY) + set_property(TARGET Vulkan::glslang-machineindependent APPEND + PROPERTY + IMPORTED_CONFIGURATIONS Debug) + set_property(TARGET Vulkan::glslang-machineindependent + PROPERTY + IMPORTED_LOCATION_DEBUG "${Vulkan_glslang-machineindependent_DEBUG_LIBRARY}") + endif() + endif() + + if((Vulkan_glslang-genericcodegen_LIBRARY OR Vulkan_glslang-genericcodegen_DEBUG_LIBRARY) AND NOT TARGET Vulkan::glslang-genericcodegen) + add_library(Vulkan::glslang-genericcodegen STATIC IMPORTED) + set_property(TARGET Vulkan::glslang-genericcodegen + PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_INCLUDE_DIRS}") + if(Vulkan_glslang-genericcodegen_LIBRARY) + set_property(TARGET Vulkan::glslang-genericcodegen APPEND + PROPERTY + IMPORTED_CONFIGURATIONS Release) + set_property(TARGET Vulkan::glslang-genericcodegen + PROPERTY + IMPORTED_LOCATION_RELEASE "${Vulkan_glslang-genericcodegen_LIBRARY}") + endif() + if(Vulkan_glslang-genericcodegen_DEBUG_LIBRARY) + set_property(TARGET Vulkan::glslang-genericcodegen APPEND + PROPERTY + IMPORTED_CONFIGURATIONS Debug) + set_property(TARGET Vulkan::glslang-genericcodegen + PROPERTY + IMPORTED_LOCATION_DEBUG "${Vulkan_glslang-genericcodegen_DEBUG_LIBRARY}") + endif() + endif() + + if((Vulkan_glslang_LIBRARY OR Vulkan_glslang_DEBUG_LIBRARY) + AND TARGET Vulkan::glslang-spirv + AND TARGET Vulkan::glslang-oglcompiler + AND TARGET Vulkan::glslang-osdependent + AND TARGET Vulkan::glslang-machineindependent + AND TARGET Vulkan::glslang-genericcodegen + AND NOT TARGET Vulkan::glslang) + add_library(Vulkan::glslang STATIC IMPORTED) + set_property(TARGET Vulkan::glslang + PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_INCLUDE_DIRS}") + if(Vulkan_glslang_LIBRARY) + set_property(TARGET Vulkan::glslang APPEND + PROPERTY + IMPORTED_CONFIGURATIONS Release) + set_property(TARGET Vulkan::glslang + PROPERTY + IMPORTED_LOCATION_RELEASE "${Vulkan_glslang_LIBRARY}") + endif() + if(Vulkan_glslang_DEBUG_LIBRARY) + set_property(TARGET Vulkan::glslang APPEND + PROPERTY + IMPORTED_CONFIGURATIONS Debug) + set_property(TARGET Vulkan::glslang + PROPERTY + IMPORTED_LOCATION_DEBUG "${Vulkan_glslang_DEBUG_LIBRARY}") + endif() + target_link_libraries(Vulkan::glslang + INTERFACE + Vulkan::glslang-spirv + Vulkan::glslang-oglcompiler + Vulkan::glslang-osdependent + Vulkan::glslang-machineindependent + Vulkan::glslang-genericcodegen + ) + endif() + + if((Vulkan_shaderc_combined_LIBRARY OR Vulkan_shaderc_combined_DEBUG_LIBRARY) AND NOT TARGET Vulkan::shaderc_combined) + add_library(Vulkan::shaderc_combined STATIC IMPORTED) + set_property(TARGET Vulkan::shaderc_combined + PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_INCLUDE_DIRS}") + if(Vulkan_shaderc_combined_LIBRARY) + set_property(TARGET Vulkan::shaderc_combined APPEND + PROPERTY + IMPORTED_CONFIGURATIONS Release) + set_property(TARGET Vulkan::shaderc_combined + PROPERTY + IMPORTED_LOCATION_RELEASE "${Vulkan_shaderc_combined_LIBRARY}") + endif() + if(Vulkan_shaderc_combined_DEBUG_LIBRARY) + set_property(TARGET Vulkan::shaderc_combined APPEND + PROPERTY + IMPORTED_CONFIGURATIONS Debug) + set_property(TARGET Vulkan::shaderc_combined + PROPERTY + IMPORTED_LOCATION_DEBUG "${Vulkan_shaderc_combined_DEBUG_LIBRARY}") + endif() + + if(UNIX) + find_package(Threads REQUIRED) + target_link_libraries(Vulkan::shaderc_combined + INTERFACE + Threads::Threads) + endif() + endif() + + if((Vulkan_SPIRV-Tools_LIBRARY OR Vulkan_SPIRV-Tools_DEBUG_LIBRARY) AND NOT TARGET Vulkan::SPIRV-Tools) + add_library(Vulkan::SPIRV-Tools STATIC IMPORTED) + set_property(TARGET Vulkan::SPIRV-Tools + PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_INCLUDE_DIRS}") + if(Vulkan_SPIRV-Tools_LIBRARY) + set_property(TARGET Vulkan::SPIRV-Tools APPEND + PROPERTY + IMPORTED_CONFIGURATIONS Release) + set_property(TARGET Vulkan::SPIRV-Tools + PROPERTY + IMPORTED_LOCATION_RELEASE "${Vulkan_SPIRV-Tools_LIBRARY}") + endif() + if(Vulkan_SPIRV-Tools_DEBUG_LIBRARY) + set_property(TARGET Vulkan::SPIRV-Tools APPEND + PROPERTY + IMPORTED_CONFIGURATIONS Debug) + set_property(TARGET Vulkan::SPIRV-Tools + PROPERTY + IMPORTED_LOCATION_DEBUG "${Vulkan_SPIRV-Tools_DEBUG_LIBRARY}") + endif() + endif() +endif() + +if(Vulkan_MoltenVK_FOUND) + if(Vulkan_MoltenVK_LIBRARY AND NOT TARGET Vulkan::MoltenVK) + add_library(Vulkan::MoltenVK SHARED IMPORTED) + set_target_properties(Vulkan::MoltenVK + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_MoltenVK_INCLUDE_DIR}" + IMPORTED_LOCATION "${Vulkan_MoltenVK_LIBRARY}" + ) + endif() +endif() + +unset(_Vulkan_library_name) +unset(_Vulkan_hint_include_search_paths) +unset(_Vulkan_hint_executable_search_paths) +unset(_Vulkan_hint_library_search_paths) + +cmake_policy(POP) diff --git a/Modules/FindX11.cmake b/Modules/FindX11.cmake index fd5ee53..8e5a5f1 100644 --- a/Modules/FindX11.cmake +++ b/Modules/FindX11.cmake @@ -31,8 +31,11 @@ and also the following more fine grained variables and targets: X11_xcb_INCLUDE_PATH, X11_xcb_LIB, X11_xcb_FOUND, X11::xcb X11_X11_xcb_INCLUDE_PATH, X11_X11_xcb_LIB, X11_X11_xcb_FOUND, X11::X11_xcb X11_xcb_icccm_INCLUDE_PATH, X11_xcb_icccm_LIB, X11_xcb_icccm_FOUND, X11::xcb_icccm + X11_xcb_randr_INCLUDE_PATH, X11_xcb_randr_LIB, X11_xcb_randr_FOUND, X11::xcb_randr X11_xcb_util_INCLUDE_PATH, X11_xcb_util_LIB, X11_xcb_util_FOUND, X11::xcb_util X11_xcb_xfixes_INCLUDE_PATH, X11_xcb_xfixes_LIB, X11_xcb_xfixes_FOUND, X11::xcb_xfixes + X11_xcb_xtest_INCLUDE_PATH, X11_xcb_xtest_LIB, X11_xcb_xtest_FOUND, X11::xcb_xtest + X11_xcb_keysyms_INCLUDE_PATH, X11_xcb_keysyms_LIB,X11_xcb_keysyms_FOUND,X11::xcb_keysyms X11_xcb_xkb_INCLUDE_PATH, X11_xcb_xkb_LIB, X11_xcb_xkb_FOUND, X11::xcb_xkb X11_Xcomposite_INCLUDE_PATH, X11_Xcomposite_LIB, X11_Xcomposite_FOUND, X11::Xcomposite X11_Xcursor_INCLUDE_PATH, X11_Xcursor_LIB, X11_Xcursor_FOUND, X11::Xcursor @@ -82,6 +85,9 @@ and also the following more fine grained variables and targets: .. versionadded:: 3.19 Added the ``Xaw``, ``xcb_util``, and ``xcb_xfixes`` libraries. +.. versionadded:: 3.24 + Added the ``xcb_randr``, ``xcb_xtext``, and ``xcb_keysyms`` libraries. + #]=======================================================================] if (UNIX) @@ -127,8 +133,11 @@ if (UNIX) find_path(X11_xcb_INCLUDE_PATH xcb/xcb.h ${X11_INC_SEARCH_PATH}) find_path(X11_X11_xcb_INCLUDE_PATH X11/Xlib-xcb.h ${X11_INC_SEARCH_PATH}) find_path(X11_xcb_icccm_INCLUDE_PATH xcb/xcb_icccm.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_randr_INCLUDE_PATH xcb/randr.h ${X11_INC_SEARCH_PATH}) find_path(X11_xcb_util_INCLUDE_PATH xcb/xcb_aux.h ${X11_INC_SEARCH_PATH}) find_path(X11_xcb_xfixes_INCLUDE_PATH xcb/xfixes.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_xtest_INCLUDE_PATH xcb/xtest.h ${X11_INC_SEARCH_PATH}) + find_path(X11_xcb_keysyms_INCLUDE_PATH xcb/xcb_keysyms.h ${X11_INC_SEARCH_PATH}) find_path(X11_Xcomposite_INCLUDE_PATH X11/extensions/Xcomposite.h ${X11_INC_SEARCH_PATH}) find_path(X11_Xcursor_INCLUDE_PATH X11/Xcursor/Xcursor.h ${X11_INC_SEARCH_PATH}) find_path(X11_Xdamage_INCLUDE_PATH X11/extensions/Xdamage.h ${X11_INC_SEARCH_PATH}) @@ -180,8 +189,11 @@ if (UNIX) find_library(X11_xcb_LIB xcb ${X11_LIB_SEARCH_PATH}) find_library(X11_X11_xcb_LIB X11-xcb ${X11_LIB_SEARCH_PATH}) find_library(X11_xcb_icccm_LIB xcb-icccm ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_randr_LIB xcb-randr ${X11_LIB_SEARCH_PATH}) find_library(X11_xcb_util_LIB xcb-util ${X11_LIB_SEARCH_PATH}) find_library(X11_xcb_xfixes_LIB xcb-xfixes ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_xtest_LIB xcb-xtest ${X11_LIB_SEARCH_PATH}) + find_library(X11_xcb_keysyms_LIB xcb-keysyms ${X11_LIB_SEARCH_PATH}) find_library(X11_xcb_xkb_LIB xcb-xkb ${X11_LIB_SEARCH_PATH}) find_library(X11_Xcomposite_LIB Xcomposite ${X11_LIB_SEARCH_PATH}) find_library(X11_Xcursor_LIB Xcursor ${X11_LIB_SEARCH_PATH}) @@ -281,6 +293,10 @@ if (UNIX) set(X11_xcb_icccm_FOUND TRUE) endif () + if (X11_xcb_randr_LIB AND X11_xcb_randr_INCLUDE_PATH) + set(X11_xcb_randr_FOUND TRUE) + endif () + if (X11_xcb_util_LIB AND X11_xcb_util_INCLUDE_PATH) set(X11_xcb_util_FOUND TRUE) endif () @@ -289,6 +305,14 @@ if (UNIX) set(X11_xcb_xfixes_FOUND TRUE) endif () + if (X11_xcb_xtest_LIB) + set(X11_xcb_xtest_FOUND TRUE) + endif () + + if (X11_xcb_keysyms_LIB) + set(X11_xcb_keysyms_FOUND TRUE) + endif () + if (X11_xcb_xkb_LIB) set(X11_xcb_xkb_FOUND TRUE) endif () @@ -600,6 +624,13 @@ if (UNIX) INTERFACE_LINK_LIBRARIES "X11::xcb") endif () + if (X11_xcb_randr_FOUND AND NOT TARGET X11::xcb_randr) + add_library(X11::xcb_randr UNKNOWN IMPORTED) + set_target_properties(X11::xcb_randr PROPERTIES + IMPORTED_LOCATION "${X11_xcb_randr_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + if (X11_xcb_util_FOUND AND NOT TARGET X11::xcb_util) add_library(X11::xcb_util UNKNOWN IMPORTED) set_target_properties(X11::xcb_util PROPERTIES @@ -614,6 +645,20 @@ if (UNIX) INTERFACE_LINK_LIBRARIES "X11::xcb") endif () + if (X11_xcb_xtest_FOUND AND NOT TARGET X11::xcb_xtest) + add_library(X11::xcb_xtest UNKNOWN IMPORTED) + set_target_properties(X11::xcb_xtest PROPERTIES + IMPORTED_LOCATION "${X11_xcb_xtest_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + + if (X11_xcb_keysyms_FOUND AND NOT TARGET X11::xcb_keysyms) + add_library(X11::xcb_keysyms UNKNOWN IMPORTED) + set_target_properties(X11::xcb_keysyms PROPERTIES + IMPORTED_LOCATION "${X11_xcb_keysyms_LIB}" + INTERFACE_LINK_LIBRARIES "X11::xcb") + endif () + if (X11_xcb_xkb_FOUND AND NOT TARGET X11::xcb_xkb) add_library(X11::xcb_xkb UNKNOWN IMPORTED) set_target_properties(X11::xcb_xkb PROPERTIES @@ -830,10 +875,16 @@ if (UNIX) X11_xcb_INCLUDE_PATH X11_xcb_icccm_LIB X11_xcb_icccm_INCLUDE_PATH + X11_xcb_randr_LIB + X11_xcb_randr_INCLUDE_PATH X11_xcb_util_LIB X11_xcb_util_INCLUDE_PATH X11_xcb_xfixes_LIB X11_xcb_xfixes_INCLUDE_PATH + X11_xcb_xtest_LIB + X11_xcb_xtest_INCLUDE_PATH + X11_xcb_keysyms_LIB + X11_xcb_keysyms_INCLUDE_PATH X11_xcb_xkb_LIB X11_X11_xcb_LIB X11_X11_xcb_INCLUDE_PATH diff --git a/Modules/FindXercesC.cmake b/Modules/FindXercesC.cmake index af1b0b4..d39bbf6 100644 --- a/Modules/FindXercesC.cmake +++ b/Modules/FindXercesC.cmake @@ -91,11 +91,13 @@ if(NOT XercesC_LIBRARY) NAMES "xerces-c" "xerces-c_${XercesC_VERSION_MAJOR}" "xerces-c-${XercesC_VERSION_MAJOR}.${XercesC_VERSION_MINOR}" + NAMES_PER_DIR DOC "Xerces-C++ libraries (release)") find_library(XercesC_LIBRARY_DEBUG NAMES "xerces-cd" "xerces-c_${XercesC_VERSION_MAJOR}D" "xerces-c_${XercesC_VERSION_MAJOR}_${XercesC_VERSION_MINOR}D" + NAMES_PER_DIR DOC "Xerces-C++ libraries (debug)") include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) select_library_configurations(XercesC) diff --git a/Modules/FindZLIB.cmake b/Modules/FindZLIB.cmake index 5778b03..f50116f 100644 --- a/Modules/FindZLIB.cmake +++ b/Modules/FindZLIB.cmake @@ -53,6 +53,11 @@ Hints A user may set ``ZLIB_ROOT`` to a zlib installation root to tell this module where to look. + +.. versionadded:: 3.24 + Set ``ZLIB_USE_STATIC_LIBS`` to ``ON`` to look for static libraries. + Default is ``OFF``. + #]=======================================================================] set(_ZLIB_SEARCHES) @@ -72,8 +77,13 @@ set(_ZLIB_SEARCH_NORMAL unset(_ZLIB_x86) list(APPEND _ZLIB_SEARCHES _ZLIB_SEARCH_NORMAL) -set(ZLIB_NAMES z zlib zdll zlib1 zlibstatic) -set(ZLIB_NAMES_DEBUG zd zlibd zdlld zlibd1 zlib1d zlibstaticd) +if(ZLIB_USE_STATIC_LIBS) + set(ZLIB_NAMES zlibstatic zlibstat zlib z) + set(ZLIB_NAMES_DEBUG zlibstaticd zlibstatd zlibd zd) +else() + set(ZLIB_NAMES z zlib zdll zlib1 zlibstatic zlibwapi zlibvc zlibstat) + set(ZLIB_NAMES_DEBUG zd zlibd zdlld zlibd1 zlib1d zlibstaticd zlibwapid zlibvcd zlibstatd) +endif() # Try each search configuration. foreach(search ${_ZLIB_SEARCHES}) @@ -82,11 +92,31 @@ endforeach() # Allow ZLIB_LIBRARY to be set manually, as the location of the zlib library if(NOT ZLIB_LIBRARY) + set(_zlib_ORIG_CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES}) + set(_zlib_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + # Prefix/suffix of the win32/Makefile.gcc build + if(WIN32) + list(APPEND CMAKE_FIND_LIBRARY_PREFIXES "" "lib") + list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES ".dll.a") + endif() + # Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES + if(ZLIB_USE_STATIC_LIBS) + if(WIN32) + set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) + else() + set(CMAKE_FIND_LIBRARY_SUFFIXES .a) + endif() + endif() + foreach(search ${_ZLIB_SEARCHES}) find_library(ZLIB_LIBRARY_RELEASE NAMES ${ZLIB_NAMES} NAMES_PER_DIR ${${search}} PATH_SUFFIXES lib) find_library(ZLIB_LIBRARY_DEBUG NAMES ${ZLIB_NAMES_DEBUG} NAMES_PER_DIR ${${search}} PATH_SUFFIXES lib) endforeach() + # Restore the original find library ordering + set(CMAKE_FIND_LIBRARY_SUFFIXES ${_zlib_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) + set(CMAKE_FIND_LIBRARY_PREFIXES ${_zlib_ORIG_CMAKE_FIND_LIBRARY_PREFIXES}) + include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) select_library_configurations(ZLIB) endif() diff --git a/Modules/FindwxWidgets.cmake b/Modules/FindwxWidgets.cmake index 63af9b6..9e7937e 100644 --- a/Modules/FindwxWidgets.cmake +++ b/Modules/FindwxWidgets.cmake @@ -29,9 +29,9 @@ select a configuration): :: wxWidgets_ROOT_DIR - Base wxWidgets directory - (e.g., C:/wxWidgets-2.6.3). + (e.g., C:/wxWidgets-3.2.0). wxWidgets_LIB_DIR - Path to wxWidgets libraries - (e.g., C:/wxWidgets-2.6.3/lib/vc_lib). + (e.g., C:/wxWidgets-3.2.0/lib/vc_x64_lib). wxWidgets_CONFIGURATION - Configuration to use (e.g., msw, mswd, mswu, mswunivud, etc.) wxWidgets_EXCLUDE_COMMON_LIBRARIES @@ -215,10 +215,36 @@ else() set(wxWidgets_USE_FILE UsewxWidgets) endif() +# Known wxWidgets versions. +set(wx_versions 3.3 3.2 3.1 3.0 2.9 2.8 2.7 2.6 2.5) + +macro(wx_extract_version) + unset(_wx_filename) + find_file(_wx_filename wx/version.h PATHS ${wxWidgets_INCLUDE_DIRS} NO_DEFAULT_PATH) + dbg_msg("_wx_filename: ${_wx_filename}") + + if(NOT _wx_filename) + message(FATAL_ERROR "wxWidgets wx/version.h file not found in ${wxWidgets_INCLUDE_DIRS}.") + endif() + + file(READ "${_wx_filename}" _wx_version_h) + unset(_wx_filename CACHE) + + string(REGEX REPLACE "^(.*\n)?#define +wxMAJOR_VERSION +([0-9]+).*" + "\\2" wxWidgets_VERSION_MAJOR "${_wx_version_h}" ) + string(REGEX REPLACE "^(.*\n)?#define +wxMINOR_VERSION +([0-9]+).*" + "\\2" wxWidgets_VERSION_MINOR "${_wx_version_h}" ) + string(REGEX REPLACE "^(.*\n)?#define +wxRELEASE_NUMBER +([0-9]+).*" + "\\2" wxWidgets_VERSION_PATCH "${_wx_version_h}" ) + set(wxWidgets_VERSION_STRING + "${wxWidgets_VERSION_MAJOR}.${wxWidgets_VERSION_MINOR}.${wxWidgets_VERSION_PATCH}" ) + dbg_msg("wxWidgets_VERSION_STRING: ${wxWidgets_VERSION_STRING}") +endmacro() + #===================================================================== # Determine whether unix or win32 paths should be used #===================================================================== -if(WIN32 AND NOT CYGWIN AND NOT MSYS AND NOT CMAKE_CROSSCOMPILING) +if(WIN32 AND NOT CYGWIN AND NOT MSYS AND NOT MINGW AND NOT CMAKE_CROSSCOMPILING) set(wxWidgets_FIND_STYLE "win32") else() set(wxWidgets_FIND_STYLE "unix") @@ -269,10 +295,11 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32") # # Find libraries associated to a configuration. # - macro(WX_FIND_LIBS _PF _UNV _UCD _DBG) + macro(WX_FIND_LIBS _PF _UNV _UCD _DBG _VER) DBG_MSG_V("m_unv = ${_UNV}") DBG_MSG_V("m_ucd = ${_UCD}") DBG_MSG_V("m_dbg = ${_DBG}") + DBG_MSG_V("m_ver = ${_VER}") # FIXME: What if both regex libs are available. regex should be # found outside the loop and only wx${LIB}${_UCD}${_DBG}. @@ -290,28 +317,14 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32") # Find wxWidgets multilib base libraries. find_library(WX_base${_DBG} - NAMES - wxbase31${_UCD}${_DBG} - wxbase30${_UCD}${_DBG} - wxbase29${_UCD}${_DBG} - wxbase28${_UCD}${_DBG} - wxbase27${_UCD}${_DBG} - wxbase26${_UCD}${_DBG} - wxbase25${_UCD}${_DBG} + NAMES wxbase${_VER}${_UCD}${_DBG} PATHS ${WX_LIB_DIR} NO_DEFAULT_PATH ) mark_as_advanced(WX_base${_DBG}) foreach(LIB net odbc xml) find_library(WX_${LIB}${_DBG} - NAMES - wxbase31${_UCD}${_DBG}_${LIB} - wxbase30${_UCD}${_DBG}_${LIB} - wxbase29${_UCD}${_DBG}_${LIB} - wxbase28${_UCD}${_DBG}_${LIB} - wxbase27${_UCD}${_DBG}_${LIB} - wxbase26${_UCD}${_DBG}_${LIB} - wxbase25${_UCD}${_DBG}_${LIB} + NAMES wxbase${_VER}${_UCD}${_DBG}_${LIB} PATHS ${WX_LIB_DIR} NO_DEFAULT_PATH ) @@ -320,14 +333,7 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32") # Find wxWidgets monolithic library. find_library(WX_mono${_DBG} - NAMES - wx${_PF}${_UNV}31${_UCD}${_DBG} - wx${_PF}${_UNV}30${_UCD}${_DBG} - wx${_PF}${_UNV}29${_UCD}${_DBG} - wx${_PF}${_UNV}28${_UCD}${_DBG} - wx${_PF}${_UNV}27${_UCD}${_DBG} - wx${_PF}${_UNV}26${_UCD}${_DBG} - wx${_PF}${_UNV}25${_UCD}${_DBG} + NAMES wx${_PF}${_UNV}${_VER}${_UCD}${_DBG} PATHS ${WX_LIB_DIR} NO_DEFAULT_PATH ) @@ -337,14 +343,7 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32") foreach(LIB core adv aui html media xrc dbgrid gl qa richtext stc ribbon propgrid webview) find_library(WX_${LIB}${_DBG} - NAMES - wx${_PF}${_UNV}31${_UCD}${_DBG}_${LIB} - wx${_PF}${_UNV}30${_UCD}${_DBG}_${LIB} - wx${_PF}${_UNV}29${_UCD}${_DBG}_${LIB} - wx${_PF}${_UNV}28${_UCD}${_DBG}_${LIB} - wx${_PF}${_UNV}27${_UCD}${_DBG}_${LIB} - wx${_PF}${_UNV}26${_UCD}${_DBG}_${LIB} - wx${_PF}${_UNV}25${_UCD}${_DBG}_${LIB} + NAMES wx${_PF}${_UNV}${_VER}${_UCD}${_DBG}_${LIB} PATHS ${WX_LIB_DIR} NO_DEFAULT_PATH ) @@ -447,6 +446,13 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32") # WIN32: Start actual work. #------------------------------------------------------------------- + set(wx_paths "wxWidgets") + foreach(version ${wx_versions}) + foreach(patch RANGE 15 0 -1) + list(APPEND wx_paths "wxWidgets-${version}.${patch}") + endforeach() + endforeach() + # Look for an installation tree. find_path(wxWidgets_ROOT_DIR NAMES include/wx/wx.h @@ -458,41 +464,7 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32") D:/ ENV ProgramFiles PATH_SUFFIXES - wxWidgets-3.1.0 - wxWidgets-3.0.2 - wxWidgets-3.0.1 - wxWidgets-3.0.0 - wxWidgets-2.9.5 - wxWidgets-2.9.4 - wxWidgets-2.9.3 - wxWidgets-2.9.2 - wxWidgets-2.9.1 - wxWidgets-2.9.0 - wxWidgets-2.8.9 - wxWidgets-2.8.8 - wxWidgets-2.8.7 - wxWidgets-2.8.6 - wxWidgets-2.8.5 - wxWidgets-2.8.4 - wxWidgets-2.8.3 - wxWidgets-2.8.2 - wxWidgets-2.8.1 - wxWidgets-2.8.0 - wxWidgets-2.7.4 - wxWidgets-2.7.3 - wxWidgets-2.7.2 - wxWidgets-2.7.1 - wxWidgets-2.7.0 - wxWidgets-2.7.0-1 - wxWidgets-2.6.4 - wxWidgets-2.6.3 - wxWidgets-2.6.2 - wxWidgets-2.6.1 - wxWidgets-2.5.4 - wxWidgets-2.5.3 - wxWidgets-2.5.2 - wxWidgets-2.5.1 - wxWidgets + ${wx_paths} DOC "wxWidgets base/installation directory" ) @@ -655,10 +627,14 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32") set(wxWidgets_FOUND FALSE) endif() + # Get version number. + wx_extract_version() + set(VER "${wxWidgets_VERSION_MAJOR}${wxWidgets_VERSION_MINOR}") + # Find wxWidgets libraries. - WX_FIND_LIBS("${PF}" "${UNV}" "${UCD}" "${DBG}") + WX_FIND_LIBS("${PF}" "${UNV}" "${UCD}" "${DBG}" "${VER}") if(WX_USE_REL_AND_DBG) - WX_FIND_LIBS("${PF}" "${UNV}" "${UCD}" "d") + WX_FIND_LIBS("${PF}" "${UNV}" "${UCD}" "d" "${VER}") endif() # Settings for requested libs (i.e., include dir, libraries, etc.). @@ -773,12 +749,14 @@ else() # Look for wx-config -- this can be set in the environment, # or try versioned and toolchain-versioned variants of the -config # executable as well. + set(wx_config_names "wx-config") + foreach(version ${wx_versions}) + list(APPEND wx_config_names "wx-config-${version}" "wxgtk3u-${version}-config" "wxgtk2u-${version}-config") + endforeach() find_program(wxWidgets_CONFIG_EXECUTABLE NAMES $ENV{WX_CONFIG} - wx-config - wx-config-3.1 wx-config-3.0 wx-config-2.9 wx-config-2.8 - wxgtk3u-3.1-config wxgtk3u-3.0-config wxgtk2u-2.8-config + ${wx_config_names} DOC "Location of wxWidgets library configuration provider binary (wx-config)." ONLY_CMAKE_FIND_ROOT_PATH ) @@ -981,26 +959,7 @@ unset(_wx_lib_missing) # Check if a specific version was requested by find_package(). if(wxWidgets_FOUND) - unset(_wx_filename) - find_file(_wx_filename wx/version.h PATHS ${wxWidgets_INCLUDE_DIRS} NO_DEFAULT_PATH) - dbg_msg("_wx_filename: ${_wx_filename}") - - if(NOT _wx_filename) - message(FATAL_ERROR "wxWidgets wx/version.h file not found in ${wxWidgets_INCLUDE_DIRS}.") - endif() - - file(READ "${_wx_filename}" _wx_version_h) - unset(_wx_filename CACHE) - - string(REGEX REPLACE "^(.*\n)?#define +wxMAJOR_VERSION +([0-9]+).*" - "\\2" wxWidgets_VERSION_MAJOR "${_wx_version_h}" ) - string(REGEX REPLACE "^(.*\n)?#define +wxMINOR_VERSION +([0-9]+).*" - "\\2" wxWidgets_VERSION_MINOR "${_wx_version_h}" ) - string(REGEX REPLACE "^(.*\n)?#define +wxRELEASE_NUMBER +([0-9]+).*" - "\\2" wxWidgets_VERSION_PATCH "${_wx_version_h}" ) - set(wxWidgets_VERSION_STRING - "${wxWidgets_VERSION_MAJOR}.${wxWidgets_VERSION_MINOR}.${wxWidgets_VERSION_PATCH}" ) - dbg_msg("wxWidgets_VERSION_STRING: ${wxWidgets_VERSION_STRING}") + wx_extract_version() endif() # Debug output: diff --git a/Modules/FortranCInterface.cmake b/Modules/FortranCInterface.cmake index 733c723..53df01a 100644 --- a/Modules/FortranCInterface.cmake +++ b/Modules/FortranCInterface.cmake @@ -343,6 +343,14 @@ function(FortranCInterface_VERIFY) set(_desc "Verifying Fortran/${lang} Compiler Compatibility") message(CHECK_START "${_desc}") + # Perform verification with only one architecture. + # FIXME: Add try_compile whole-project option to forward architectures. + if(CMAKE_OSX_ARCHITECTURES MATCHES "^([^;]+)(;|$)") + set(_FortranCInterface_OSX_ARCH "-DCMAKE_OSX_ARCHITECTURES=${CMAKE_MATCH_1}") + else() + set(_FortranCInterface_OSX_ARCH "") + endif() + cmake_policy(GET CMP0056 _FortranCInterface_CMP0056) if(_FortranCInterface_CMP0056 STREQUAL "NEW") set(_FortranCInterface_EXE_LINKER_FLAGS "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS}") @@ -365,6 +373,7 @@ function(FortranCInterface_VERIFY) "-DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE}" "-DCMAKE_CXX_FLAGS_RELEASE:STRING=${CMAKE_CXX_FLAGS_RELEASE}" "-DCMAKE_Fortran_FLAGS_RELEASE:STRING=${CMAKE_Fortran_FLAGS_RELEASE}" + ${_FortranCInterface_OSX_ARCH} ${_FortranCInterface_EXE_LINKER_FLAGS} OUTPUT_VARIABLE _output) file(WRITE "${FortranCInterface_BINARY_DIR}/Verify${lang}/output.txt" "${_output}") diff --git a/Modules/FortranCInterface/Detect.cmake b/Modules/FortranCInterface/Detect.cmake index 4d3cb00..72e5544 100644 --- a/Modules/FortranCInterface/Detect.cmake +++ b/Modules/FortranCInterface/Detect.cmake @@ -28,6 +28,14 @@ unset(FortranCInterface_VERIFIED_CXX CACHE) set(_result) +# Perform detection with only one architecture so that +# the info strings are not repeated. +if(CMAKE_OSX_ARCHITECTURES MATCHES "^([^;]+)(;|$)") + set(_FortranCInterface_OSX_ARCH "-DCMAKE_OSX_ARCHITECTURES=${CMAKE_MATCH_1}") +else() + set(_FortranCInterface_OSX_ARCH "") +endif() + cmake_policy(GET CMP0056 _FortranCInterface_CMP0056) if(_FortranCInterface_CMP0056 STREQUAL "NEW") set(_FortranCInterface_EXE_LINKER_FLAGS "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS}") @@ -48,11 +56,13 @@ try_compile(FortranCInterface_COMPILED "-DCMAKE_Fortran_FLAGS:STRING=${CMAKE_Fortran_FLAGS}" "-DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE}" "-DCMAKE_Fortran_FLAGS_RELEASE:STRING=${CMAKE_Fortran_FLAGS_RELEASE}" + ${_FortranCInterface_OSX_ARCH} ${_FortranCInterface_EXE_LINKER_FLAGS} OUTPUT_VARIABLE FortranCInterface_OUTPUT) set(FortranCInterface_COMPILED ${FortranCInterface_COMPILED}) unset(FortranCInterface_COMPILED CACHE) unset(_FortranCInterface_EXE_LINKER_FLAGS) +unset(_FortranCInterface_OSX_ARCH) # Locate the sample project executable. set(FortranCInterface_EXE) diff --git a/Modules/GNUInstallDirs.cmake b/Modules/GNUInstallDirs.cmake index 01bd637..9796854 100644 --- a/Modules/GNUInstallDirs.cmake +++ b/Modules/GNUInstallDirs.cmake @@ -52,8 +52,10 @@ where ``<dir>`` is one of: .. versionadded:: 3.9 run-time variable data (``LOCALSTATEDIR/run``) ``LIBDIR`` - object code libraries (``lib`` or ``lib64`` - or ``lib/<multiarch-tuple>`` on Debian) + object code libraries (``lib`` or ``lib64``) + + On Debian, this may be ``lib/<multiarch-tuple>`` when + :variable:`CMAKE_INSTALL_PREFIX` is ``/usr``. ``INCLUDEDIR`` C header files (``include``) ``OLDINCLUDEDIR`` @@ -110,6 +112,8 @@ The following values of :variable:`CMAKE_INSTALL_PREFIX` are special: For example, the ``SYSCONFDIR`` value ``etc`` becomes ``/etc/opt/...``. This is defined by the `Filesystem Hierarchy Standard`_. + This behavior does not apply to paths under ``/opt/homebrew/...``. + .. _`Filesystem Hierarchy Standard`: https://refspecs.linuxfoundation.org/FHS_3.0/fhs/index.html Macros @@ -328,7 +332,7 @@ else() "Info documentation (DATAROOTDIR/info)") endif() -if(CMAKE_SYSTEM_NAME MATCHES "^(([^k].*)?BSD|DragonFly)$") +if(CMAKE_SYSTEM_NAME MATCHES "^(([^k].*)?BSD|DragonFly)$" AND NOT CMAKE_SYSTEM_NAME MATCHES "^(FreeBSD)$") _GNUInstallDirs_cache_path_fallback(CMAKE_INSTALL_MANDIR "man" "Man documentation (man)") else() @@ -398,7 +402,7 @@ macro(GNUInstallDirs_get_absolute_install_dir absvar var) else() set(${absvar} "${CMAKE_INSTALL_PREFIX}/${${var}}") endif() - elseif("${CMAKE_INSTALL_PREFIX}" MATCHES "^/opt/.*") + elseif("${CMAKE_INSTALL_PREFIX}" MATCHES "^/opt/" AND NOT "${CMAKE_INSTALL_PREFIX}" MATCHES "^/opt/homebrew/") if("${GGAID_dir}" STREQUAL "SYSCONFDIR" OR "${GGAID_dir}" STREQUAL "LOCALSTATEDIR" OR "${GGAID_dir}" STREQUAL "RUNSTATEDIR") set(${absvar} "/${${var}}${CMAKE_INSTALL_PREFIX}") else() diff --git a/Modules/GenerateExportHeader.cmake b/Modules/GenerateExportHeader.cmake index a9a9c59..7461a3e 100644 --- a/Modules/GenerateExportHeader.cmake +++ b/Modules/GenerateExportHeader.cmake @@ -231,7 +231,7 @@ macro(_test_compiler_hidden_visibility) AND NOT _INTEL_TOO_OLD AND NOT WIN32 AND NOT CYGWIN - AND NOT CMAKE_CXX_COMPILER_ID MATCHES XL + AND NOT CMAKE_CXX_COMPILER_ID MATCHES "^(IBMClang|XLClang|XL)$" AND NOT CMAKE_CXX_COMPILER_ID MATCHES "^(PGI|NVHPC)$" AND NOT CMAKE_CXX_COMPILER_ID MATCHES Watcom) if (CMAKE_CXX_COMPILER_LOADED) diff --git a/Modules/GetPrerequisites.cmake b/Modules/GetPrerequisites.cmake index 53584c6..0ba35b6 100644 --- a/Modules/GetPrerequisites.cmake +++ b/Modules/GetPrerequisites.cmake @@ -755,11 +755,13 @@ function(get_prerequisites target prerequisites_var exclude_system recurse exepa # objdump generates copious output so we create a grep filter to pre-filter results if(WIN32) find_program(gp_grep_cmd findstr) + set(gp_grep_cmd_arg "") else() find_program(gp_grep_cmd grep) + set(gp_grep_cmd_arg "-a") endif() if(gp_grep_cmd) - set(gp_cmd_maybe_filter COMMAND ${gp_grep_cmd} "-a" "^[[:blank:]]*DLL Name: ") + set(gp_cmd_maybe_filter COMMAND ${gp_grep_cmd} "${gp_grep_cmd_arg}" "^[[:blank:]]*DLL Name: ") endif() else() message(STATUS "warning: gp_tool='${gp_tool}' is an unknown tool...") diff --git a/Modules/GoogleTestAddTests.cmake b/Modules/GoogleTestAddTests.cmake index 6b3bf34..2bd0cc9 100644 --- a/Modules/GoogleTestAddTests.cmake +++ b/Modules/GoogleTestAddTests.cmake @@ -9,7 +9,7 @@ set(flush_tests_MODE WRITE) # Flushes script to ${_CTEST_FILE} macro(flush_script) file(${flush_tests_MODE} "${_CTEST_FILE}" "${script}") - set(flush_tests_MODE APPEND) + set(flush_tests_MODE APPEND PARENT_SCOPE) set(script "") endmacro() @@ -20,24 +20,48 @@ macro(flush_tests_buffer) set(tests_buffer "") endmacro() -macro(add_command NAME) - set(_args "") - foreach(_arg ${ARGN}) - if(_arg MATCHES "[^-./:a-zA-Z0-9_]") - string(APPEND _args " [==[${_arg}]==]") +function(add_command NAME TEST_NAME) + set(args "") + foreach(arg ${ARGN}) + if(arg MATCHES "[^-./:a-zA-Z0-9_]") + string(APPEND args " [==[${arg}]==]") else() - string(APPEND _args " ${_arg}") + string(APPEND args " ${arg}") endif() endforeach() - string(APPEND script "${NAME}(${_args})\n") - string(LENGTH "${script}" _script_len) - if(${_script_len} GREATER "50000") + string(APPEND script "${NAME}(${TEST_NAME} ${args})\n") + string(LENGTH "${script}" script_len) + if(${script_len} GREATER "50000") flush_script() endif() - # Unsets macro local variables to prevent leakage outside of this macro. - unset(_args) - unset(_script_len) -endmacro() + set(script "${script}" PARENT_SCOPE) +endfunction() + +function(generate_testname_guards OUTPUT OPEN_GUARD_VAR CLOSE_GUARD_VAR) + set(open_guard "[=[") + set(close_guard "]=]") + set(counter 1) + while("${OUTPUT}" MATCHES "${close_guard}") + math(EXPR counter "${counter} + 1") + string(REPEAT "=" ${counter} equals) + set(open_guard "[${equals}[") + set(close_guard "]${equals}]") + endwhile() + set(${OPEN_GUARD_VAR} "${open_guard}" PARENT_SCOPE) + set(${CLOSE_GUARD_VAR} "${close_guard}" PARENT_SCOPE) +endfunction() + +function(escape_square_brackets OUTPUT BRACKET PLACEHOLDER PLACEHOLDER_VAR OUTPUT_VAR) + if("${OUTPUT}" MATCHES "\\${BRACKET}") + set(placeholder "${PLACEHOLDER}") + while("${OUTPUT}" MATCHES "${placeholder}") + set(placeholder "${placeholder}_") + endwhile() + string(REPLACE "${BRACKET}" "${placeholder}" OUTPUT "${OUTPUT}") + set(${PLACEHOLDER_VAR} "${placeholder}" PARENT_SCOPE) + set(${OUTPUT_VAR} "${OUTPUT}" PARENT_SCOPE) + endif() +endfunction() function(gtest_discover_tests_impl) @@ -80,15 +104,23 @@ function(gtest_discover_tests_impl) ) if(NOT ${result} EQUAL 0) string(REPLACE "\n" "\n " output "${output}") + if(_TEST_EXECUTOR) + set(path "${_TEST_EXECUTOR} ${_TEST_EXECUTABLE}") + else() + set(path "${_TEST_EXECUTABLE}") + endif() message(FATAL_ERROR "Error running test executable.\n" - " Path: '${_TEST_EXECUTABLE}'\n" + " Path: '${path}'\n" " Result: ${result}\n" " Output:\n" " ${output}\n" ) endif() + generate_testname_guards("${output}" open_guard close_guard) + escape_square_brackets("${output}" "[" "__osb" open_sb output) + escape_square_brackets("${output}" "]" "__csb" close_sb output) # Preserve semicolon in test-parameters string(REPLACE [[;]] [[\;]] output "${output}") string(REPLACE "\n" ";" output "${output}") @@ -100,41 +132,48 @@ function(gtest_discover_tests_impl) # Do we have a module name or a test name? if(NOT line MATCHES "^ ") # Module; remove trailing '.' to get just the name... - string(REGEX REPLACE "\\.( *#.*)?" "" suite "${line}") - if(line MATCHES "#" AND NOT _NO_PRETTY_TYPES) - string(REGEX REPLACE "/[0-9]\\.+ +#.*= +" "/" pretty_suite "${line}") + string(REGEX REPLACE "\\.( *#.*)?$" "" suite "${line}") + if(line MATCHES "#") + string(REGEX REPLACE "/.*" "" pretty_suite "${line}") + if(NOT _NO_PRETTY_TYPES) + string(REGEX REPLACE ".*/[0-9]+[ .#]+TypeParam = (.*)" "\\1" type_parameter "${line}") + else() + string(REGEX REPLACE ".*/([0-9]+)[ .#]+TypeParam = .*" "\\1" type_parameter "${line}") + endif() + set(test_name_template "@prefix@@pretty_suite@.@pretty_test@<@type_parameter@>@suffix@") else() set(pretty_suite "${suite}") + set(test_name_template "@prefix@@pretty_suite@.@pretty_test@@suffix@") endif() string(REGEX REPLACE "^DISABLED_" "" pretty_suite "${pretty_suite}") else() - # Test name; strip spaces and comments to get just the name... - string(REGEX REPLACE " +" "" test "${line}") + string(STRIP "${line}" test) if(test MATCHES "#" AND NOT _NO_PRETTY_VALUES) - string(REGEX REPLACE "/[0-9]+#GetParam..=" "/" pretty_test "${test}") + string(REGEX REPLACE "/[0-9]+[ #]+GetParam\\(\\) = " "/" pretty_test "${test}") else() - string(REGEX REPLACE "#.*" "" pretty_test "${test}") + string(REGEX REPLACE " +#.*" "" pretty_test "${test}") endif() string(REGEX REPLACE "^DISABLED_" "" pretty_test "${pretty_test}") - string(REGEX REPLACE "#.*" "" test "${test}") + string(REGEX REPLACE " +#.*" "" test "${test}") if(NOT "${_TEST_XML_OUTPUT_DIR}" STREQUAL "") set(TEST_XML_OUTPUT_PARAM "--gtest_output=xml:${_TEST_XML_OUTPUT_DIR}/${prefix}${suite}.${test}${suffix}.xml") else() unset(TEST_XML_OUTPUT_PARAM) endif() - # sanitize test name for further processing downstream - set(testname "${prefix}${pretty_suite}.${pretty_test}${suffix}") - # escape \ - string(REPLACE [[\]] [[\\]] testname "${testname}") - # escape ; - string(REPLACE [[;]] [[\;]] testname "${testname}") - # escape $ - string(REPLACE [[$]] [[\$]] testname "${testname}") + string(CONFIGURE "${test_name_template}" testname) + # unescape [] + if(open_sb) + string(REPLACE "${open_sb}" "[" testname "${testname}") + endif() + if(close_sb) + string(REPLACE "${close_sb}" "]" testname "${testname}") + endif() + set(guarded_testname "${open_guard}${testname}${close_guard}") - # ...and add to script + # add to script add_command(add_test - "${testname}" + "${guarded_testname}" ${_TEST_EXECUTOR} "${_TEST_EXECUTABLE}" "--gtest_filter=${suite}.${test}" @@ -144,21 +183,28 @@ function(gtest_discover_tests_impl) ) if(suite MATCHES "^DISABLED_" OR test MATCHES "^DISABLED_") add_command(set_tests_properties - "${testname}" + "${guarded_testname}" PROPERTIES DISABLED TRUE ) endif() + add_command(set_tests_properties - "${testname}" + "${guarded_testname}" PROPERTIES WORKING_DIRECTORY "${_TEST_WORKING_DIR}" - SKIP_REGULAR_EXPRESSION "\\\\[ SKIPPED \\\\]" + SKIP_REGULAR_EXPRESSION "\\[ SKIPPED \\]" ${properties} ) - list(APPEND tests_buffer "${testname}") - list(LENGTH tests_buffer tests_buffer_length) - if(${tests_buffer_length} GREATER "250") - flush_tests_buffer() + + # possibly unbalanced square brackets render lists invalid so skip such tests in ${_TEST_LIST} + if(NOT "${testname}" MATCHES [=[(\[|\])]=]) + # escape ; + string(REPLACE [[;]] [[\\;]] testname "${testname}") + list(APPEND tests_buffer "${testname}") + list(LENGTH tests_buffer tests_buffer_length) + if(${tests_buffer_length} GREATER "250") + flush_tests_buffer() + endif() endif() endif() endif() @@ -168,7 +214,7 @@ function(gtest_discover_tests_impl) # Create a list of all discovered tests, which users may use to e.g. set # properties on the tests flush_tests_buffer() - add_command(set ${_TEST_LIST} ${tests}) + add_command(set "" ${_TEST_LIST} "${tests}") # Write CTest script flush_script() diff --git a/Modules/Internal/CPack/CPack.OSXScriptLauncher.in b/Modules/Internal/CPack/CPack.OSXScriptLauncher.in Binary files differdeleted file mode 100644 index c715860..0000000 --- a/Modules/Internal/CPack/CPack.OSXScriptLauncher.in +++ /dev/null diff --git a/Modules/Internal/CPack/CPack.OSXScriptLauncher.rsrc.in b/Modules/Internal/CPack/CPack.OSXScriptLauncher.rsrc.in Binary files differdeleted file mode 100644 index 5f5f17a..0000000 --- a/Modules/Internal/CPack/CPack.OSXScriptLauncher.rsrc.in +++ /dev/null diff --git a/Modules/Internal/CPack/CPack.distribution.dist.in b/Modules/Internal/CPack/CPack.distribution.dist.in index f20e66c..291b24d 100644 --- a/Modules/Internal/CPack/CPack.distribution.dist.in +++ b/Modules/Internal/CPack/CPack.distribution.dist.in @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <installer-gui-script minSpecVersion="1.0"> - <title>@CPACK_PACKAGE_NAME@</title> - <welcome file="@CPACK_RESOURCE_FILE_WELCOME_NOPATH@"/> - <readme file="@CPACK_RESOURCE_FILE_README_NOPATH@"/> - <license file="@CPACK_RESOURCE_FILE_LICENSE_NOPATH@"/> - <options allow-external-scripts="no" customize="allow" rootVolumeOnly="false"></options> - @CPACK_PACKAGEMAKER_CHOICES@ + <title>@CPACK_PACKAGE_NAME@</title> + <welcome file="@CPACK_RESOURCE_FILE_WELCOME_NOPATH@"/> + <readme file="@CPACK_RESOURCE_FILE_README_NOPATH@"/> + <license file="@CPACK_RESOURCE_FILE_LICENSE_NOPATH@"/> +@CPACK_APPLE_PKG_INSTALLER_CONTENT@ </installer-gui-script> diff --git a/Modules/Internal/CPack/CPackDeb.cmake b/Modules/Internal/CPack/CPackDeb.cmake index c115f00..958a6db 100644 --- a/Modules/Internal/CPack/CPackDeb.cmake +++ b/Modules/Internal/CPack/CPackDeb.cmake @@ -332,6 +332,14 @@ function(cpack_deb_prepare_package_vars) RESULT_VARIABLE SHLIBDEPS_RESULT ERROR_VARIABLE SHLIBDEPS_ERROR OUTPUT_STRIP_TRAILING_WHITESPACE ) + + # E2K OSL 6.0.1 and prior has broken dpkg-shlibdeps. CPack will deal with that (mocking SHLIBDEPS_OUTPUT), but inform user of this. + if("${SHLIBDEPS_ERROR}" MATCHES "unknown gcc system type e2k.*, falling back to default") + message(WARNING "CPackDeb: broken dpkg-shlibdeps on E2K detected, will fall back to minimal dependencies.\n" + "You should expect that dependencies list in the package will be incomplete.") + set(SHLIBDEPS_OUTPUT "shlibs:Depends=libc6, lcc-libs") + endif() + if(CPACK_DEBIAN_PACKAGE_DEBUG) # dpkg-shlibdeps will throw some warnings if some input files are not binary message( "CPackDeb Debug: dpkg-shlibdeps warnings \n${SHLIBDEPS_ERROR}") diff --git a/Modules/Internal/CPack/CPackFreeBSD.cmake b/Modules/Internal/CPack/CPackFreeBSD.cmake index ae40532..c35089c 100644 --- a/Modules/Internal/CPack/CPackFreeBSD.cmake +++ b/Modules/Internal/CPack/CPackFreeBSD.cmake @@ -34,7 +34,7 @@ function(_cpack_freebsd_fallback_var OUTPUT_VAR_NAME) endif() endforeach() if(NOT VALUE) - message(WARNING "Variable ${OUTPUT_VAR_NAME} could not be given a fallback value from any variable ${FALLBACK_VAR_NAMES}.") + message(WARNING "Variable ${OUTPUT_VAR_NAME} could not be given a fallback value from (any of) ${FALLBACK_VAR_NAMES}.") endif() endfunction() diff --git a/Modules/Internal/CPack/CPackNuGet.cmake b/Modules/Internal/CPack/CPackNuGet.cmake index fb363f4..056d025 100644 --- a/Modules/Internal/CPack/CPackNuGet.cmake +++ b/Modules/Internal/CPack/CPackNuGet.cmake @@ -332,7 +332,9 @@ endfunction() function(_cpack_nuget_make_files_tag) set(_files) foreach(_comp IN LISTS ARGN) - string(APPEND _files " <file src=\"${_comp}/**\" target=\".\" />\n") + cmake_path(APPEND _comp "**") + cmake_path(NATIVE_PATH _comp _comp) + string(APPEND _files " <file src=\"${_comp}\" target=\".\" />\n") endforeach() set(_CPACK_NUGET_FILES_TAG "<files>\n${_files} </files>" PARENT_SCOPE) endfunction() diff --git a/Modules/Internal/CPack/CPackRPM.cmake b/Modules/Internal/CPack/CPackRPM.cmake index c72bf6d..cd631b8 100644 --- a/Modules/Internal/CPack/CPackRPM.cmake +++ b/Modules/Internal/CPack/CPackRPM.cmake @@ -790,7 +790,7 @@ function(cpack_rpm_variable_fallback OUTPUT_VAR_NAME) set(FALLBACK_VAR_NAMES ${ARGN}) foreach(variable_name IN LISTS FALLBACK_VAR_NAMES) - if(${variable_name}) + if(DEFINED ${variable_name}) set(${OUTPUT_VAR_NAME} "${${variable_name}}" PARENT_SCOPE) break() endif() diff --git a/Modules/Internal/CPack/NSIS.template.in b/Modules/Internal/CPack/NSIS.template.in index f16eaf6..42a44d9 100644 --- a/Modules/Internal/CPack/NSIS.template.in +++ b/Modules/Internal/CPack/NSIS.template.in @@ -48,7 +48,7 @@ ;--- Component support macros: --- ; The code for the add/remove functionality is from: -; http://nsis.sourceforge.net/Add/Remove_Functionality +; https://nsis.sourceforge.io/Add/Remove_Functionality ; It has been modified slightly and extended to provide ; inter-component dependencies. Var AR_SecFlags @@ -383,7 +383,7 @@ Function un.RemoveFromPath FunctionEnd ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Uninstall sutff +; Uninstall stuff ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ########################################### @@ -487,15 +487,15 @@ Done: Exch $R1 FunctionEnd -Function ConditionalAddToRegisty +Function ConditionalAddToRegistry Pop $0 Pop $1 - StrCmp "$0" "" ConditionalAddToRegisty_EmptyString + StrCmp "$0" "" ConditionalAddToRegistry_EmptyString WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" \ "$1" "$0" ;MessageBox MB_OK "Set Registry: '$1' to '$0'" DetailPrint "Set install registry entry: '$1' to '$0'" - ConditionalAddToRegisty_EmptyString: + ConditionalAddToRegistry_EmptyString: FunctionEnd ;-------------------------------- @@ -531,7 +531,6 @@ FunctionEnd @CPACK_NSIS_INSTALLER_ICON_CODE@ @CPACK_NSIS_INSTALLER_MUI_WELCOMEFINISH_CODE@ @CPACK_NSIS_INSTALLER_MUI_UNWELCOMEFINISH_CODE@ -@CPACK_NSIS_INSTALLER_MUI_COMPONENTS_DESC@ @CPACK_NSIS_INSTALLER_MUI_FINISHPAGE_RUN_CODE@ ;-------------------------------- @@ -648,7 +647,7 @@ FunctionEnd ;-------------------------------- ; Component sections @CPACK_NSIS_COMPONENT_SECTIONS@ - +@CPACK_NSIS_INSTALLER_MUI_COMPONENTS_DESC@ ;-------------------------------- ;Installer Sections @@ -666,44 +665,44 @@ Section "-Core installation" WriteUninstaller "$INSTDIR\@CPACK_NSIS_UNINSTALL_NAME@.exe" Push "DisplayName" Push "@CPACK_NSIS_DISPLAY_NAME@" - Call ConditionalAddToRegisty + Call ConditionalAddToRegistry Push "DisplayVersion" Push "@CPACK_PACKAGE_VERSION@" - Call ConditionalAddToRegisty + Call ConditionalAddToRegistry Push "Publisher" Push "@CPACK_PACKAGE_VENDOR@" - Call ConditionalAddToRegisty + Call ConditionalAddToRegistry Push "UninstallString" Push "$\"$INSTDIR\@CPACK_NSIS_UNINSTALL_NAME@.exe$\"" - Call ConditionalAddToRegisty + Call ConditionalAddToRegistry Push "NoRepair" Push "1" - Call ConditionalAddToRegisty + Call ConditionalAddToRegistry !ifdef CPACK_NSIS_ADD_REMOVE ;Create add/remove functionality Push "ModifyPath" Push "$INSTDIR\AddRemove.exe" - Call ConditionalAddToRegisty + Call ConditionalAddToRegistry !else Push "NoModify" Push "1" - Call ConditionalAddToRegisty + Call ConditionalAddToRegistry !endif ; Optional registration Push "DisplayIcon" Push "$INSTDIR\@CPACK_NSIS_INSTALLED_ICON_NAME@" - Call ConditionalAddToRegisty + Call ConditionalAddToRegistry Push "HelpLink" Push "@CPACK_NSIS_HELP_LINK@" - Call ConditionalAddToRegisty + Call ConditionalAddToRegistry Push "URLInfoAbout" Push "@CPACK_NSIS_URL_INFO_ABOUT@" - Call ConditionalAddToRegisty + Call ConditionalAddToRegistry Push "Contact" Push "@CPACK_NSIS_CONTACT@" - Call ConditionalAddToRegisty + Call ConditionalAddToRegistry !insertmacro MUI_INSTALLOPTIONS_READ $INSTALL_DESKTOP "NSIS.InstallOptions.ini" "Field 5" "State" !insertmacro MUI_STARTMENU_WRITE_BEGIN Application @@ -721,19 +720,19 @@ Section "-Core installation" ; Write special uninstall registry entries Push "StartMenu" Push "$STARTMENU_FOLDER" - Call ConditionalAddToRegisty + Call ConditionalAddToRegistry Push "DoNotAddToPath" Push "$DO_NOT_ADD_TO_PATH" - Call ConditionalAddToRegisty + Call ConditionalAddToRegistry Push "AddToPathAllUsers" Push "$ADD_TO_PATH_ALL_USERS" - Call ConditionalAddToRegisty + Call ConditionalAddToRegistry Push "AddToPathCurrentUser" Push "$ADD_TO_PATH_CURRENT_USER" - Call ConditionalAddToRegisty + Call ConditionalAddToRegistry Push "InstallToDesktop" Push "$INSTALL_DESKTOP" - Call ConditionalAddToRegisty + Call ConditionalAddToRegistry !insertmacro MUI_STARTMENU_WRITE_END @@ -881,7 +880,7 @@ Section "Uninstall" StrCmp "$MUI_TEMP" "$SMPROGRAMS" startMenuDeleteLoopDone startMenuDeleteLoop startMenuDeleteLoopDone: - ; If the user changed the shortcut, then untinstall may not work. This should + ; If the user changed the shortcut, then uninstall may not work. This should ; try to fix it. StrCpy $MUI_TEMP "$START_MENU" Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" diff --git a/Modules/Internal/CheckCompilerFlag.cmake b/Modules/Internal/CheckCompilerFlag.cmake index f6a4cc9..910f426 100644 --- a/Modules/Internal/CheckCompilerFlag.cmake +++ b/Modules/Internal/CheckCompilerFlag.cmake @@ -2,82 +2,30 @@ # file Copyright.txt or https://cmake.org/licensing for details. include_guard(GLOBAL) +include(Internal/CheckFlagCommonConfig) include(Internal/CheckSourceCompiles) include(CMakeCheckCompilerFlagCommonPatterns) -cmake_policy(PUSH) -cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced -cmake_policy(SET CMP0057 NEW) # if() supports IN_LIST - function(CMAKE_CHECK_COMPILER_FLAG _lang _flag _var) + # Parse extra arguments + cmake_parse_arguments(PARSE_ARGV 3 CHECK_COMPILER_FLAG "" "OUTPUT_VARIABLE" "") - if(_lang STREQUAL "C") - set(_lang_src "int main(void) { return 0; }") - set(_lang_fail_regex FAIL_REGEX "command[ -]line option .* is valid for .* but not for C" - FAIL_REGEX "-Werror=.* argument .* is not valid for C") - elseif(_lang STREQUAL "CXX") - set(_lang_src "int main() { return 0; }") - set(_lang_fail_regex FAIL_REGEX "command[ -]line option .* is valid for .* but not for C\\+\\+" - FAIL_REGEX "-Werror=.* argument .* is not valid for C\\+\\+") - elseif(_lang STREQUAL "CUDA") - set(_lang_src "__host__ int main() { return 0; }") - set(_lang_fail_regex FAIL_REGEX "command[ -]line option .* is valid for .* but not for C\\+\\+" # Host GNU - FAIL_REGEX "argument unused during compilation: .*") # Clang - elseif(_lang STREQUAL "Fortran") - set(_lang_src " program test\n stop\n end program") - set(_lang_fail_regex FAIL_REGEX "command[ -]line option .* is valid for .* but not for Fortran") - elseif(_lang STREQUAL "HIP") - set(_lang_src "__host__ int main() { return 0; }") - set(_lang_fail_regex FAIL_REGEX "argument unused during compilation: .*") # Clang - elseif(_lang STREQUAL "OBJC") - set(_lang_src [=[ -#ifndef __OBJC__ -# error "Not an Objective-C compiler" -#endif -int main(void) { return 0; }]=]) - set(_lang_fail_regex FAIL_REGEX "command[ -]line option .* is valid for .* but not for Objective-C" # GNU - FAIL_REGEX "argument unused during compilation: .*") # Clang - elseif(_lang STREQUAL "OBJCXX") - set(_lang_src [=[ -#ifndef __OBJC__ -# error "Not an Objective-C++ compiler" -#endif -int main(void) { return 0; }]=]) - set(_lang_fail_regex FAIL_REGEX "command[ -]line option .* is valid for .* but not for Objective-C\\+\\+" # GNU - FAIL_REGEX "argument unused during compilation: .*") # Clang - elseif(_lang STREQUAL "ISPC") - set(_lang_src "float func(uniform int32, float a) { return a / 2.25; }") - else() - message (SEND_ERROR "check_compiler_flag: ${_lang}: unknown language.") - return() - endif() - - get_property (_supported_languages GLOBAL PROPERTY ENABLED_LANGUAGES) - if (NOT _lang IN_LIST _supported_languages) - message (SEND_ERROR "check_compiler_flag: ${_lang}: needs to be enabled before use.") - return() - endif() + cmake_check_flag_common_init("check_compiler_flag" ${_lang} _lang_src _lang_fail_regex) set(CMAKE_REQUIRED_DEFINITIONS ${_flag}) - # Normalize locale during test compilation. - set(_locale_vars LC_ALL LC_MESSAGES LANG) - foreach(v IN LISTS _locale_vars) - set(_locale_vars_saved_${v} "$ENV{${v}}") - set(ENV{${v}} C) - endforeach() - check_compiler_flag_common_patterns(_common_patterns) cmake_check_source_compiles(${_lang} "${_lang_src}" ${_var} ${_lang_fail_regex} ${_common_patterns} + OUTPUT_VARIABLE _output ) - foreach(v IN LISTS _locale_vars) - set(ENV{${v}} ${_locale_vars_saved_${v}}) - endforeach() -endfunction () + if (CHECK_COMPILER_FLAG_OUTPUT_VARIABLE) + set(${CHECK_COMPILER_FLAG_OUTPUT_VARIABLE} "${_output}" PARENT_SCOPE) + endif() -cmake_policy(POP) + cmake_check_flag_common_finish() +endfunction() diff --git a/Modules/Internal/CheckFlagCommonConfig.cmake b/Modules/Internal/CheckFlagCommonConfig.cmake new file mode 100644 index 0000000..c011c24 --- /dev/null +++ b/Modules/Internal/CheckFlagCommonConfig.cmake @@ -0,0 +1,75 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + + +# Do NOT include this module directly into any of your code. It is meant as +# a library for Check*CompilerFlag.cmake and Check*LinkerFlag.cma modules. +# It's content may change in any way between releases. + +include_guard(GLOBAL) +cmake_policy(PUSH) +cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced +cmake_policy(SET CMP0057 NEW) # if() supports IN_LIST + +macro(CMAKE_CHECK_FLAG_COMMON_INIT _FUNC _LANG _SRC _PATTERNS) + if("${_LANG}" STREQUAL "C") + set(${_SRC} "int main(void) { return 0; }") + set(${_PATTERNS} FAIL_REGEX "command[ -]line option .* is valid for .* but not for C" + FAIL_REGEX "-Werror=.* argument .* is not valid for C") + elseif("${_LANG}" STREQUAL "CXX") + set(${_SRC} "int main() { return 0; }") + set(${_PATTERNS} FAIL_REGEX "command[ -]line option .* is valid for .* but not for C\\+\\+" + FAIL_REGEX "-Werror=.* argument .* is not valid for C\\+\\+") + elseif("${_LANG}" STREQUAL "CUDA") + set(${_SRC} "__host__ int main() { return 0; }") + set(${_PATTERNS} FAIL_REGEX "command[ -]line option .* is valid for .* but not for C\\+\\+" # Host GNU + FAIL_REGEX "argument unused during compilation: .*") # Clang + elseif("${_LANG}" STREQUAL "Fortran") + set(${_SRC} " program test\n stop\n end program") + set(${_PATTERNS} FAIL_REGEX "command[ -]line option .* is valid for .* but not for Fortran") + elseif("${_LANG}" STREQUAL "HIP") + set(${_SRC} "__host__ int main() { return 0; }") + set(${_PATTERNS} FAIL_REGEX "argument unused during compilation: .*") # Clang + elseif("${_LANG}" STREQUAL "OBJC") + set(${_SRC} [=[ + #ifndef __OBJC__ + # error "Not an Objective-C compiler" + #endif + int main(void) { return 0; }]=]) + set(${_PATTERNS} FAIL_REGEX "command[ -]line option .* is valid for .* but not for Objective-C" # GNU + FAIL_REGEX "argument unused during compilation: .*") # Clang + elseif("${_LANG}" STREQUAL "OBJCXX") + set(${_SRC} [=[ + #ifndef __OBJC__ + # error "Not an Objective-C++ compiler" + #endif + int main(void) { return 0; }]=]) + set(${_PATTERNS} FAIL_REGEX "command[ -]line option .* is valid for .* but not for Objective-C\\+\\+" # GNU + FAIL_REGEX "argument unused during compilation: .*") # Clang + elseif("${_LANG}" STREQUAL "ISPC") + set(${_SRC} "float func(uniform int32, float a) { return a / 2.25; }") + else() + message (SEND_ERROR "${_FUNC}: ${_LANG}: unknown language.") + return() + endif() + + get_property (_supported_languages GLOBAL PROPERTY ENABLED_LANGUAGES) + if (NOT "${_LANG}" IN_LIST _supported_languages) + message (SEND_ERROR "${_FUNC}: ${_LANG}: needs to be enabled before use.") + return() + endif() + # Normalize locale during test compilation. + set(_CFCC_locale_vars LC_ALL LC_MESSAGES LANG) + foreach(v IN LISTS _CFCC_locale_vars) + set(_CMAKE_CHECK_FLAG_COMMON_CONFIG_locale_vars_saved_${v} "$ENV{${v}}") + set(ENV{${v}} C) + endforeach() +endmacro() + +macro(CMAKE_CHECK_FLAG_COMMON_FINISH) + foreach(v IN LISTS _CFCC_locale_vars) + set(ENV{${v}} ${_CMAKE_CHECK_FLAG_COMMON_CONFIG_locale_vars_saved_${v}}) + endforeach() +endmacro() + +cmake_policy(POP) diff --git a/Modules/Internal/CheckLinkerFlag.cmake b/Modules/Internal/CheckLinkerFlag.cmake new file mode 100644 index 0000000..7613105 --- /dev/null +++ b/Modules/Internal/CheckLinkerFlag.cmake @@ -0,0 +1,52 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +include_guard(GLOBAL) +include(Internal/CheckFlagCommonConfig) +include(Internal/CheckSourceCompiles) +include(CMakeCheckCompilerFlagCommonPatterns) + +cmake_policy(PUSH) +cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced + +function(CMAKE_CHECK_LINKER_FLAG _lang _flag _var) + # link step supports less languages than the compiler + # so do a first check about the requested language + if (_lang STREQUAL "ISPC") + message (SEND_ERROR "check_linker_flag: ${_lang}: unsupported language.") + return() + endif() + + # Parse extra arguments + cmake_parse_arguments(PARSE_ARGV 3 CHECK_LINKER_FLAG "" "OUTPUT_VARIABLE" "") + + cmake_check_flag_common_init("check_linker_flag" ${_lang} _lang_src _lang_fail_regex) + + set(CMAKE_REQUIRED_LINK_OPTIONS "${_flag}") + + check_compiler_flag_common_patterns(_common_patterns) + + # Match linker warnings if the exact flag is ignored. + foreach(flag IN LISTS _flag) + string(REGEX REPLACE "([][+.*?()^$])" [[\\\1]] _flag_regex "${flag}") + list(APPEND _common_patterns + FAIL_REGEX "warning: .*${_flag_regex}.* ignored" + ) + endforeach() + + cmake_check_source_compiles(${_lang} + "${_lang_src}" + ${_var} + ${_lang_fail_regex} + ${_common_patterns} + OUTPUT_VARIABLE _output + ) + + if (CHECK_LINKER_FLAG_OUTPUT_VARIABLE) + set(${CHECK_LINKER_FLAG_OUTPUT_VARIABLE} "${_output}" PARENT_SCOPE) + endif() + + cmake_check_flag_common_finish() +endfunction() + +cmake_policy(POP) diff --git a/Modules/Internal/CheckSourceCompiles.cmake b/Modules/Internal/CheckSourceCompiles.cmake index 8c3a418..27aa3e0 100644 --- a/Modules/Internal/CheckSourceCompiles.cmake +++ b/Modules/Internal/CheckSourceCompiles.cmake @@ -49,13 +49,16 @@ function(CMAKE_CHECK_SOURCE_COMPILES _lang _source _var) set(_SRC_EXT) set(_key) foreach(arg ${ARGN}) - if("${arg}" MATCHES "^(FAIL_REGEX|SRC_EXT)$") + if("${arg}" MATCHES "^(FAIL_REGEX|SRC_EXT|OUTPUT_VARIABLE)$") set(_key "${arg}") elseif(_key STREQUAL "FAIL_REGEX") list(APPEND _FAIL_REGEX "${arg}") elseif(_key STREQUAL "SRC_EXT") set(_SRC_EXT "${arg}") set(_key "") + elseif(_key STREQUAL "OUTPUT_VARIABLE") + set(_OUTPUT_VARIABLE "${arg}") + set(_key "") else() message(FATAL_ERROR "Unknown argument:\n ${arg}\n") endif() @@ -105,6 +108,10 @@ function(CMAKE_CHECK_SOURCE_COMPILES _lang _source _var) endif() endforeach() + if (_OUTPUT_VARIABLE) + set(${_OUTPUT_VARIABLE} "${OUTPUT}" PARENT_SCOPE) + endif() + if(${_var}) set(${_var} 1 CACHE INTERNAL "Test ${_var}") if(NOT CMAKE_REQUIRED_QUIET) diff --git a/Modules/Internal/HeaderpadWorkaround.cmake b/Modules/Internal/HeaderpadWorkaround.cmake new file mode 100644 index 0000000..9a7f9f5 --- /dev/null +++ b/Modules/Internal/HeaderpadWorkaround.cmake @@ -0,0 +1,69 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + + +# Do NOT include this module directly into any of your code. It is used by +# the try_compile() implementation to work around a specific issue with +# conflicting flags when building for Apple platforms. +if(NOT APPLE) + return() +endif() + +cmake_policy(PUSH) +cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced + +function(__cmake_internal_workaround_headerpad_flag_conflict _LANG) + + # Until we can avoid hard-coding -Wl,-headerpad_max_install_names in the + # linker flags, we need to remove it here for cases where we know it will + # conflict with other flags, generate a warning and be ignored. + set(regex "(^| )(-fembed-bitcode(-marker|=(all|bitcode|marker))?|-bundle_bitcode)($| )") + set(remove_headerpad NO) + + # Check arbitrary flags that the user or project has set. These compiler + # flags get added to the linker command line. + if("${CMAKE_${_LANG}_FLAGS}" MATCHES "${regex}") + set(remove_headerpad YES) + endif() + if(NOT remove_headerpad) + get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + if(is_multi_config) + # Only one of these config-specific variables will be set by try_compile() + # and the rest will be unset, but we can't easily tell which one is set. + # No harm to just add them all here, empty ones won't add flags to check. + foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES) + if("${CMAKE_${_LANG}_FLAGS_${config}}" MATCHES "${regex}") + set(remove_headerpad YES) + break() + endif() + endforeach() + else() + if("${CMAKE_${_LANG}_FLAGS_${CMAKE_BUILD_TYPE}}" MATCHES "${regex}") + set(remove_headerpad YES) + endif() + endif() + endif() + + # The try_compile() command passes compiler flags to check in a way that + # results in them being added to add_definitions(). Those don't end up on + # the linker command line, so we don't need to check them here. + + if(remove_headerpad) + foreach(flag IN ITEMS + CMAKE_${_LANG}_LINK_FLAGS + CMAKE_SHARED_LIBRARY_CREATE_${_LANG}_FLAGS + CMAKE_SHARED_MODULE_CREATE_${_LANG}_FLAGS) + string(REPLACE "-Wl,-headerpad_max_install_names" "" ${flag} "${${flag}}") + set(${flag} "${${flag}}" PARENT_SCOPE) + endforeach() + endif() +endfunction() + +get_property(__enabled_languages GLOBAL PROPERTY ENABLED_LANGUAGES) +foreach(__lang IN LISTS __enabled_languages) + __cmake_internal_workaround_headerpad_flag_conflict(${__lang}) +endforeach() +unset(__lang) +unset(__enabled_languages) + +cmake_policy(POP) diff --git a/Modules/MatlabTestsRedirect.cmake b/Modules/MatlabTestsRedirect.cmake index fc36fc3..d651cdd 100644 --- a/Modules/MatlabTestsRedirect.cmake +++ b/Modules/MatlabTestsRedirect.cmake @@ -15,6 +15,7 @@ # -Dcustom_Matlab_test_command="" # -Dcmd_to_run_before_test="" # -Dunittest_file_to_run +# -Dmaut_BATCH_OPTION="-batch" # -P FindMatlab_TestsRedirect.cmake set(Matlab_UNIT_TESTS_CMD -nosplash -nodesktop -nodisplay ${Matlab_ADDITIONAL_STARTUP_OPTIONS}) @@ -84,7 +85,7 @@ execute_process( # Do not use a full path to log file. Depend on the fact that the log file # is always going to go in the working_directory. This is because matlab # on unix is a shell script that does not handle spaces in the logfile path. - COMMAND "${Matlab_PROGRAM}" ${Matlab_UNIT_TESTS_CMD} -logfile "${log_file_name}" -r "${Matlab_SCRIPT_TO_RUN}" + COMMAND "${Matlab_PROGRAM}" ${Matlab_UNIT_TESTS_CMD} -logfile "${log_file_name}" "${maut_BATCH_OPTION}" "${Matlab_SCRIPT_TO_RUN}" RESULT_VARIABLE res ${test_timeout} OUTPUT_QUIET # we do not want the output twice diff --git a/Modules/Platform/ADSP-C.cmake b/Modules/Platform/ADSP-C.cmake new file mode 100644 index 0000000..c85e746 --- /dev/null +++ b/Modules/Platform/ADSP-C.cmake @@ -0,0 +1,2 @@ +include(Platform/ADSP-Common) +__platform_adsp(C) diff --git a/Modules/Platform/ADSP-CXX.cmake b/Modules/Platform/ADSP-CXX.cmake new file mode 100644 index 0000000..d827c80 --- /dev/null +++ b/Modules/Platform/ADSP-CXX.cmake @@ -0,0 +1,2 @@ +include(Platform/ADSP-Common) +__platform_adsp(CXX) diff --git a/Modules/Platform/ADSP-Common.cmake b/Modules/Platform/ADSP-Common.cmake new file mode 100644 index 0000000..2ba90b2 --- /dev/null +++ b/Modules/Platform/ADSP-Common.cmake @@ -0,0 +1,36 @@ +include_guard() + +macro(__platform_adsp_init) + if(NOT CMAKE_ADSP_PLATFORM_INITIALIZED) + if(NOT CMAKE_SYSTEM_PROCESSOR) + message(FATAL_ERROR "ADSP: CMAKE_SYSTEM_PROCESSOR is required but not set") + endif() + + set(CMAKE_ADSP_PROCESSOR "ADSP-${CMAKE_SYSTEM_PROCESSOR}") + string(TOUPPER "${CMAKE_ADSP_PROCESSOR}" CMAKE_ADSP_PROCESSOR) + + set(CMAKE_ADSP_COMPILER_NAME cc21k.exe) + if(CMAKE_ADSP_PROCESSOR MATCHES "^ADSP-BF") + set(CMAKE_ADSP_COMPILER_NAME ccblkfn.exe) + endif() + + set(CMAKE_ADSP_PLATFORM_INITIALIZED TRUE) + endif() +endmacro() + +macro(__platform_adsp lang) + __platform_adsp_init() + set(CMAKE_${lang}_COMPILER "${CMAKE_ADSP_ROOT}/${CMAKE_ADSP_COMPILER_NAME}") + + execute_process( + COMMAND "${CMAKE_${lang}_COMPILER}" "-proc=${CMAKE_ADSP_PROCESSOR}" "-version" + OUTPUT_QUIET ERROR_QUIET + RESULT_VARIABLE _adsp_is_valid_proc + ) + if(NOT _adsp_is_valid_proc EQUAL 0) + message(FATAL_ERROR + "ADSP: unsupported processor '${CMAKE_ADSP_PROCESSOR}' for CMAKE_${lang}_COMPILER:\n" + " ${CMAKE_${lang}_COMPILER}" + ) + endif() +endmacro() diff --git a/Modules/Platform/ADSP-Determine.cmake b/Modules/Platform/ADSP-Determine.cmake new file mode 100644 index 0000000..6ccf1ea --- /dev/null +++ b/Modules/Platform/ADSP-Determine.cmake @@ -0,0 +1,26 @@ +if(IS_DIRECTORY "$ENV{ADSP_ROOT}") + file(TO_CMAKE_PATH "$ENV{ADSP_ROOT}" CMAKE_ADSP_ROOT) +endif() + +macro(_find_adsp_root path_pattern) + set(CMAKE_ADSP_ROOT "") + set(_adsp_root_version "0") + file(GLOB _adsp_root_paths "${path_pattern}") + foreach(_current_adsp_root_path IN LISTS _adsp_root_paths) + string(REGEX MATCH "([0-9\\.]+)/?$" _current_adsp_root_version "${_current_adsp_root_path}") + if(_current_adsp_root_version VERSION_GREATER _adsp_root_version) + set(CMAKE_ADSP_ROOT "${_current_adsp_root_path}") + set(_adsp_root_version "${_current_adsp_root_version}") + endif() + endforeach() +endmacro() + +if(NOT CMAKE_ADSP_ROOT) + _find_adsp_root("C:/Analog Devices/CrossCore Embedded Studio *") +endif() +if(NOT CMAKE_ADSP_ROOT) + _find_adsp_root("C:/Program Files (x86)/Analog Devices/VisualDSP *") +endif() +if(NOT IS_DIRECTORY "${CMAKE_ADSP_ROOT}") + message(FATAL_ERROR "ADSP: could not find CCES/VDSP++ install directory ${CMAKE_ADSP_ROOT}") +endif() diff --git a/Modules/Platform/ADSP.cmake b/Modules/Platform/ADSP.cmake new file mode 100644 index 0000000..15e9dd2 --- /dev/null +++ b/Modules/Platform/ADSP.cmake @@ -0,0 +1,4 @@ +include(Platform/ADSP-Common) +__platform_adsp_init() + +set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE) diff --git a/Modules/Platform/AIX-IBMClang-C.cmake b/Modules/Platform/AIX-IBMClang-C.cmake new file mode 100644 index 0000000..db21f29 --- /dev/null +++ b/Modules/Platform/AIX-IBMClang-C.cmake @@ -0,0 +1,2 @@ +include(Platform/AIX-IBMClang) +__aix_compiler_ibmclang(C) diff --git a/Modules/Platform/AIX-IBMClang-CXX.cmake b/Modules/Platform/AIX-IBMClang-CXX.cmake new file mode 100644 index 0000000..bf580ec --- /dev/null +++ b/Modules/Platform/AIX-IBMClang-CXX.cmake @@ -0,0 +1,3 @@ +include(Platform/AIX-IBMClang) +__aix_compiler_ibmclang(CXX) +unset(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN) diff --git a/Modules/Platform/AIX-IBMClang.cmake b/Modules/Platform/AIX-IBMClang.cmake new file mode 100644 index 0000000..4e5205e --- /dev/null +++ b/Modules/Platform/AIX-IBMClang.cmake @@ -0,0 +1,16 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + + +# This module is shared by multiple languages; use include blocker. +if(__AIX_COMPILER_IBMCLANG) + return() +endif() +set(__AIX_COMPILER_IBMCLANG 1) + +include(Platform/AIX-GNU) + +macro(__aix_compiler_ibmclang lang) + __aix_compiler_gnu(${lang}) + unset(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY) +endmacro() diff --git a/Modules/Platform/CYGWIN-GNU.cmake b/Modules/Platform/CYGWIN-GNU.cmake index b81bd4d..ef64012 100644 --- a/Modules/Platform/CYGWIN-GNU.cmake +++ b/Modules/Platform/CYGWIN-GNU.cmake @@ -14,6 +14,34 @@ string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " -Wl,--enable-auto-import") set(CMAKE_GNULD_IMAGE_VERSION "-Wl,--major-image-version,<TARGET_VERSION_MAJOR>,--minor-image-version,<TARGET_VERSION_MINOR>") set(CMAKE_GENERATOR_RC windres) + + +# Features for LINK_LIBRARY generator expression +## check linker capabilities +if(NOT DEFINED _CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + execute_process(COMMAND "${CMAKE_LINKER}" --help + OUTPUT_VARIABLE __linker_help + ERROR_VARIABLE __linker_help) + if(__linker_help MATCHES "--push-state" AND __linker_help MATCHES "--pop-state") + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED TRUE CACHE INTERNAL "linker supports push/pop state") + else() + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED FALSE CACHE INTERNAL "linker supports push/pop state") + endif() + unset(__linker_help) +endif() +## WHOLE_ARCHIVE: Force loading all members of an archive +if(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--push-state,--whole-archive" + "<LINK_ITEM>" + "LINKER:--pop-state") +else() + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--whole-archive" + "<LINK_ITEM>" + "LINKER:--no-whole-archive") +endif() +set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE) + + macro(__cygwin_compiler_gnu lang) # Binary link rules. set(CMAKE_${lang}_CREATE_SHARED_MODULE diff --git a/Modules/Platform/CrayLinuxEnvironment.cmake b/Modules/Platform/CrayLinuxEnvironment.cmake index f2aaf3f..b982b3f 100644 --- a/Modules/Platform/CrayLinuxEnvironment.cmake +++ b/Modules/Platform/CrayLinuxEnvironment.cmake @@ -68,6 +68,7 @@ if (NOT CMAKE_FIND_NO_INSTALL_PREFIX) ) endif() endif() +_cmake_record_install_prefix() list(APPEND CMAKE_SYSTEM_INCLUDE_PATH $ENV{SYSROOT_DIR}/usr/include/X11 diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake index 839dc81..ac2478b 100644 --- a/Modules/Platform/Darwin.cmake +++ b/Modules/Platform/Darwin.cmake @@ -108,6 +108,33 @@ foreach(lang C CXX Fortran OBJC OBJCXX) set(CMAKE_${lang}_FRAMEWORK_SEARCH_FLAG -F) endforeach() +# Defines LINK_LIBRARY features for frameworks +set(CMAKE_LINK_LIBRARY_USING_FRAMEWORK "LINKER:-framework,<LIBRARY>") +set(CMAKE_LINK_LIBRARY_USING_FRAMEWORK_SUPPORTED TRUE) + +set(CMAKE_LINK_LIBRARY_USING_NEEDED_FRAMEWORK "LINKER:-needed_framework,<LIBRARY>") +set(CMAKE_LINK_LIBRARY_USING_NEEDED_FRAMEWORK_SUPPORTED TRUE) + +set(CMAKE_LINK_LIBRARY_USING_REEXPORT_FRAMEWORK "LINKER:-reexport_framework,<LIBRARY>") +set(CMAKE_LINK_LIBRARY_USING_REEXPORT_FRAMEWORK_SUPPORTED TRUE) + +set(CMAKE_LINK_LIBRARY_USING_WEAK_FRAMEWORK "LINKER:-weak_framework,<LIBRARY>") +set(CMAKE_LINK_LIBRARY_USING_WEAK_FRAMEWORK_SUPPORTED TRUE) + +# Defines LINK_LIBRARY features for libraries +set(CMAKE_LINK_LIBRARY_USING_NEEDED_LIBRARY "PATH{LINKER:-needed_library <LIBRARY>}NAME{LINKER:-needed-l<LIBRARY>}") +set(CMAKE_LINK_LIBRARY_USING_NEEDED_LIBRARY_SUPPORTED TRUE) + +set(CMAKE_LINK_LIBRARY_USING_REEXPORT_LIBRARY "PATH{LINKER:-reexport_library <LIBRARY>}NAME{LINKER:-reexport-l<LIBRARY>}") +set(CMAKE_LINK_LIBRARY_USING_REEXPORT_LIBRARY_SUPPORTED TRUE) + +set(CMAKE_LINK_LIBRARY_USING_WEAK_LIBRARY "PATH{LINKER:-weak_library <LIBRARY>}NAME{LINKER:-weak-l<LIBRARY>}") +set(CMAKE_LINK_LIBRARY_USING_WEAK_LIBRARY_SUPPORTED TRUE) + +# Defines LINK_LIBRARY feature to Force loading of all members of an archive +set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:-force_load <LIB_ITEM>") +set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE) + # default to searching for frameworks first if(NOT DEFINED CMAKE_FIND_FRAMEWORK) set(CMAKE_FIND_FRAMEWORK FIRST) diff --git a/Modules/Platform/FreeBSD.cmake b/Modules/Platform/FreeBSD.cmake index 4a4c00d..bd5a786 100644 --- a/Modules/Platform/FreeBSD.cmake +++ b/Modules/Platform/FreeBSD.cmake @@ -26,4 +26,38 @@ foreach(type SHARED_LIBRARY SHARED_MODULE EXE) set(CMAKE_${type}_LINK_DYNAMIC_C_FLAGS "-Wl,-Bdynamic") endforeach() + +# Features for LINK_LIBRARY generator expression +## check linker capabilities +if(NOT DEFINED _CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + execute_process(COMMAND "${CMAKE_LINKER}" --help + OUTPUT_VARIABLE __linker_help + ERROR_VARIABLE __linker_help) + if(__linker_help MATCHES "--push-state" AND __linker_help MATCHES "--pop-state") + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED TRUE CACHE INTERNAL "linker supports push/pop state") + else() + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED FALSE CACHE INTERNAL "linker supports push/pop state") + endif() + unset(__linker_help) +endif() +## WHOLE_ARCHIVE: Force loading all members of an archive +if(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--push-state,--whole-archive" + "<LINK_ITEM>" + "LINKER:--pop-state") +else() + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--whole-archive" + "<LINK_ITEM>" + "LINKER:--no-whole-archive") +endif() +set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE) + + +# Features for LINK_GROUP generator expression +## RESCAN: request the linker to rescan static libraries until there is +## no pending undefined symbols +set(CMAKE_LINK_GROUP_USING_RESCAN "LINKER:--start-group" "LINKER:--end-group") +set(CMAKE_LINK_GROUP_USING_RESCAN_SUPPORTED TRUE) + + include(Platform/UnixPaths) diff --git a/Modules/Platform/GHS-MULTI-Determine.cmake b/Modules/Platform/GHS-MULTI-Determine.cmake index 349d906..67464f7 100644 --- a/Modules/Platform/GHS-MULTI-Determine.cmake +++ b/Modules/Platform/GHS-MULTI-Determine.cmake @@ -1,26 +1,77 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. -#Setup Green Hills MULTI specific compilation information +# Setup variables used for Green Hills MULTI generator +# -- Allow users to override these values. + +if(CMAKE_GENERATOR MATCHES "Green Hills MULTI") + + # Set the project primaryTarget value + # If not set then primaryTarget will be determined by the generator + if((NOT DEFINED GHS_PRIMARY_TARGET) OR (DEFINED CACHE{GHS_PRIMARY_TARGET})) + set(GHS_PRIMARY_TARGET "IGNORE" CACHE STRING "GHS MULTI primaryTarget") + mark_as_advanced(GHS_PRIMARY_TARGET) + endif() + + # Setup MULTI toolset selection variables + if((NOT DEFINED GHS_TOOLSET_ROOT) OR (DEFINED CACHE{GHS_TOOLSET_ROOT})) + if(CMAKE_HOST_UNIX) + set(_ts_root "/usr/ghs") + else() + set(_ts_root "C:/ghs") + endif() + set(GHS_TOOLSET_ROOT "${_ts_root}" CACHE PATH "GHS platform toolset root directory") + mark_as_advanced(GHS_TOOLSET_ROOT) + unset(_ts_root) + endif() + + # Setup MULTI project variables + if((NOT DEFINED GHS_CUSTOMIZATION) OR (DEFINED CACHE{GHS_CUSTOMIZATION})) + set(GHS_CUSTOMIZATION "" CACHE FILEPATH "optional GHS customization") + mark_as_advanced(GHS_CUSTOMIZATION) + endif() + + if((NOT DEFINED GHS_GPJ_MACROS) OR (DEFINED CACHE{GHS_GPJ_MACROS})) + set(GHS_GPJ_MACROS "" CACHE STRING "optional GHS macros generated in the .gpjs for legacy reasons") + mark_as_advanced(GHS_GPJ_MACROS) + endif() -if(CMAKE_HOST_UNIX) - set(GHS_OS_ROOT "/usr/ghs" CACHE PATH "GHS platform OS search root directory") -else() - set(GHS_OS_ROOT "C:/ghs" CACHE PATH "GHS platform OS search root directory") endif() -mark_as_advanced(GHS_OS_ROOT) -set(GHS_OS_DIR "NOTFOUND" CACHE PATH "GHS platform OS directory") -mark_as_advanced(GHS_OS_DIR) +# If project primaryTarget not set then set target platform name. +# -- May be used by the generator when determining the primaryTarget. +if(NOT GHS_PRIMARY_TARGET) + if((NOT DEFINED GHS_TARGET_PLATFORM) OR (DEFINED CACHE{GHS_TARGET_PLATFORM})) + set(GHS_TARGET_PLATFORM "integrity" CACHE STRING "GHS MULTI target platform") + mark_as_advanced(GHS_TARGET_PLATFORM) + endif() +endif() -set(GHS_OS_DIR_OPTION "-os_dir " CACHE STRING "GHS compiler OS option") -mark_as_advanced(GHS_OS_DIR_OPTION) +# Settings for OS selection +if((NOT DEFINED GHS_OS_ROOT) OR (DEFINED CACHE{GHS_OS_ROOT})) + if(CMAKE_HOST_UNIX) + set(_os_root "/usr/ghs") + else() + set(_os_root "C:/ghs") + endif() + set(GHS_OS_ROOT "${_os_root}" CACHE PATH "GHS platform OS search root directory") + unset(_os_root) + mark_as_advanced(GHS_OS_ROOT) +endif() -#set GHS_OS_DIR if not set by user -if(NOT GHS_OS_DIR) +# Search for GHS_OS_DIR if not set by user and is known to be required +if(GHS_PRIMARY_TARGET MATCHES "integrity" OR GHS_TARGET_PLATFORM MATCHES "integrity") + # Needed - Use a value that will make it apparent RTOS selection failed + set(_ghs_os_dir "GHS_OS_DIR-NOT-SPECIFIED") +else() + # Not needed for this target + set(_ghs_os_dir "IGNORE") +endif() + +if(_ghs_os_dir AND NOT DEFINED GHS_OS_DIR) if(EXISTS ${GHS_OS_ROOT}) - #get all directories in root directory + # Get all directories in root directory FILE(GLOB GHS_CANDIDATE_OS_DIRS LIST_DIRECTORIES true RELATIVE ${GHS_OS_ROOT} ${GHS_OS_ROOT}/*) FILE(GLOB GHS_CANDIDATE_OS_FILES @@ -29,28 +80,50 @@ if(NOT GHS_OS_DIR) list(REMOVE_ITEM GHS_CANDIDATE_OS_DIRS ${GHS_CANDIDATE_OS_FILES}) endif () - #filter based on platform name - if(GHS_TARGET_PLATFORM MATCHES "integrity") + # Filter based on platform name + if(GHS_PRIMARY_TARGET MATCHES "integrity" OR GHS_TARGET_PLATFORM MATCHES "integrity") list(FILTER GHS_CANDIDATE_OS_DIRS INCLUDE REGEX "int[0-9][0-9][0-9][0-9a-z]") - else() #fall-back for standalone - unset(GHS_CANDIDATE_OS_DIRS) - set(GHS_OS_DIR "IGNORE") endif() + # Select latest? of matching candidates if(GHS_CANDIDATE_OS_DIRS) list(SORT GHS_CANDIDATE_OS_DIRS) - list(GET GHS_CANDIDATE_OS_DIRS -1 GHS_OS_DIR) - string(CONCAT GHS_OS_DIR ${GHS_OS_ROOT} "/" ${GHS_OS_DIR}) + list(GET GHS_CANDIDATE_OS_DIRS -1 _ghs_os_dir) + string(CONCAT _ghs_os_dir ${GHS_OS_ROOT} "/" ${_ghs_os_dir}) endif() - - #update cache with new value - set(GHS_OS_DIR "${GHS_OS_DIR}" CACHE PATH "GHS platform OS directory" FORCE) endif() endif() -set(GHS_BSP_NAME "IGNORE" CACHE STRING "BSP name") +#Used for targets requiring RTOS +if((NOT DEFINED GHS_OS_DIR) OR (DEFINED CACHE{GHS_OS_DIR})) + set(GHS_OS_DIR "${_ghs_os_dir}" CACHE PATH "GHS platform OS directory") + mark_as_advanced(GHS_OS_DIR) +endif() +unset(_ghs_os_dir) + +if((NOT DEFINED GHS_OS_DIR_OPTION) OR (DEFINED CACHE{GHS_OS_DIR_OPTION})) + set(GHS_OS_DIR_OPTION "-os_dir " CACHE STRING "GHS compiler OS option") + mark_as_advanced(GHS_OS_DIR_OPTION) +endif() + +# Select GHS_BSP_NAME if not set by user and is known to be required +if(GHS_PRIMARY_TARGET MATCHES "integrity" OR GHS_TARGET_PLATFORM MATCHES "integrity") + set(_ghs_bsp_name "GHS_BSP_NAME-NOT-SPECIFIED") +else() + set(_ghs_bsp_name "IGNORE") +endif() -set(GHS_CUSTOMIZATION "" CACHE FILEPATH "optional GHS customization") -mark_as_advanced(GHS_CUSTOMIZATION) -set(GHS_GPJ_MACROS "" CACHE STRING "optional GHS macros generated in the .gpjs for legacy reasons") -mark_as_advanced(GHS_GPJ_MACROS) +if(_ghs_bsp_name AND NOT DEFINED GHS_BSP_NAME) + # First try taking architecture from `-A` option + if(CMAKE_GENERATOR_PLATFORM) + set(_ghs_bsp_name "sim${CMAKE_GENERATOR_PLATFORM}") + else() + set(_ghs_bsp_name "simarm") + endif() +endif() + +if((NOT DEFINED GHS_BSP_NAME) OR (DEFINED CACHE{GHS_BSP_NAME})) + set(GHS_BSP_NAME "${_ghs_bsp_name}" CACHE STRING "BSP name") + mark_as_advanced(GHS_BSP_NAME) +endif() +unset(_ghs_bsp_name) diff --git a/Modules/Platform/GHS-MULTI.cmake b/Modules/Platform/GHS-MULTI.cmake index 60a15c4..5b28f29 100644 --- a/Modules/Platform/GHS-MULTI.cmake +++ b/Modules/Platform/GHS-MULTI.cmake @@ -13,5 +13,3 @@ set(GHSMULTI 1) set(CMAKE_FIND_LIBRARY_PREFIXES "") set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") - -include(Platform/WindowsPaths) diff --git a/Modules/Platform/Generic-ELF.cmake b/Modules/Platform/Generic-ELF.cmake new file mode 100644 index 0000000..943cb6b --- /dev/null +++ b/Modules/Platform/Generic-ELF.cmake @@ -0,0 +1,7 @@ +# This is a platform definition file for platforms without +# an operating system using the ELF executable format. +# It is used when CMAKE_SYSTEM_NAME is set to "Generic-ELF" + +include(Platform/Generic) + +set(CMAKE_EXECUTABLE_SUFFIX .elf) diff --git a/Modules/Platform/Linux-LCC-C.cmake b/Modules/Platform/Linux-LCC-C.cmake new file mode 100644 index 0000000..b204c55 --- /dev/null +++ b/Modules/Platform/Linux-LCC-C.cmake @@ -0,0 +1,2 @@ +include(Platform/Linux-LCC) +__linux_compiler_lcc(C) diff --git a/Modules/Platform/Linux-LCC-CXX.cmake b/Modules/Platform/Linux-LCC-CXX.cmake new file mode 100644 index 0000000..cf2fa35 --- /dev/null +++ b/Modules/Platform/Linux-LCC-CXX.cmake @@ -0,0 +1,2 @@ +include(Platform/Linux-LCC) +__linux_compiler_lcc(CXX) diff --git a/Modules/Platform/Linux-LCC-Fortran.cmake b/Modules/Platform/Linux-LCC-Fortran.cmake new file mode 100644 index 0000000..bf2a1c2 --- /dev/null +++ b/Modules/Platform/Linux-LCC-Fortran.cmake @@ -0,0 +1,7 @@ +include(Platform/Linux-LCC) +__linux_compiler_lcc(Fortran) +if (CMAKE_Fortran_COMPILER_VERSION VERSION_LESS "1.26.03") + set(CMAKE_SHARED_LIBRARY_LINK_Fortran_FLAGS "-llfortran") +else() + set(CMAKE_SHARED_LIBRARY_LINK_Fortran_FLAGS "-lgfortran") +endif() diff --git a/Modules/Platform/Linux-LCC.cmake b/Modules/Platform/Linux-LCC.cmake new file mode 100644 index 0000000..a375461 --- /dev/null +++ b/Modules/Platform/Linux-LCC.cmake @@ -0,0 +1,15 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + + +# This module is shared by multiple languages; use include blocker. +if(__LINUX_COMPILER_LCC) + return() +endif() +set(__LINUX_COMPILER_LCC 1) + +macro(__linux_compiler_lcc lang) + # We pass this for historical reasons. Projects may have + # executables that use dlopen but do not set ENABLE_EXPORTS. + set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-rdynamic") +endmacro() diff --git a/Modules/Platform/Linux-OpenWatcom-C.cmake b/Modules/Platform/Linux-OpenWatcom-C.cmake index 383349a..7236c74 100644 --- a/Modules/Platform/Linux-OpenWatcom-C.cmake +++ b/Modules/Platform/Linux-OpenWatcom-C.cmake @@ -1 +1,2 @@ include(Platform/Linux-OpenWatcom) +__linux_open_watcom(C) diff --git a/Modules/Platform/Linux-OpenWatcom-CXX.cmake b/Modules/Platform/Linux-OpenWatcom-CXX.cmake index 383349a..a5f386b 100644 --- a/Modules/Platform/Linux-OpenWatcom-CXX.cmake +++ b/Modules/Platform/Linux-OpenWatcom-CXX.cmake @@ -1 +1,2 @@ include(Platform/Linux-OpenWatcom) +__linux_open_watcom(CXX) diff --git a/Modules/Platform/Linux-OpenWatcom.cmake b/Modules/Platform/Linux-OpenWatcom.cmake index 5b4e995..678d373 100644 --- a/Modules/Platform/Linux-OpenWatcom.cmake +++ b/Modules/Platform/Linux-OpenWatcom.cmake @@ -10,6 +10,14 @@ string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " system linux opt noextension") string(APPEND CMAKE_MODULE_LINKER_FLAGS_INIT " system linux") string(APPEND CMAKE_SHARED_LINKER_FLAGS_INIT " system linux") +cmake_policy(GET CMP0136 __LINUX_WATCOM_CMP0136) +if(__LINUX_WATCOM_CMP0136 STREQUAL "NEW") + set(CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT "SingleThreaded") +else() + set(CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT "") +endif() +unset(__LINUX_WATCOM_CMP0136) + # single/multi-threaded /-bm # default is setup for single-threaded libraries string(APPEND CMAKE_C_FLAGS_INIT " -bt=linux") @@ -23,3 +31,8 @@ if(CMAKE_CROSSCOMPILING) set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES $ENV{WATCOM}/lh) endif() endif() + +macro(__linux_open_watcom lang) + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_SingleThreaded "") + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_MultiThreaded -bm) +endmacro() diff --git a/Modules/Platform/Linux.cmake b/Modules/Platform/Linux.cmake index b5d5464..a7e58ab 100644 --- a/Modules/Platform/Linux.cmake +++ b/Modules/Platform/Linux.cmake @@ -19,6 +19,39 @@ foreach(type SHARED_LIBRARY SHARED_MODULE EXE) set(CMAKE_${type}_LINK_DYNAMIC_C_FLAGS "-Wl,-Bdynamic") endforeach() + +# Features for LINK_LIBRARY generator expression +## check linker capabilities +if(NOT DEFINED _CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + execute_process(COMMAND "${CMAKE_LINKER}" --help + OUTPUT_VARIABLE __linker_help + ERROR_VARIABLE __linker_help) + if(__linker_help MATCHES "--push-state" AND __linker_help MATCHES "--pop-state") + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED TRUE CACHE INTERNAL "linker supports push/pop state") + else() + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED FALSE CACHE INTERNAL "linker supports push/pop state") + endif() + unset(__linker_help) +endif() +## WHOLE_ARCHIVE: Force loading all members of an archive +if(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--push-state,--whole-archive" + "<LINK_ITEM>" + "LINKER:--pop-state") +else() + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--whole-archive" + "<LINK_ITEM>" + "LINKER:--no-whole-archive") +endif() +set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE) + +# Features for LINK_GROUP generator expression +## RESCAN: request the linker to rescan static libraries until there is +## no pending undefined symbols +set(CMAKE_LINK_GROUP_USING_RESCAN "LINKER:--start-group" "LINKER:--end-group") +set(CMAKE_LINK_GROUP_USING_RESCAN_SUPPORTED TRUE) + + # Debian policy requires that shared libraries be installed without # executable permission. Fedora policy requires that shared libraries # be installed with the executable permission. Since the native tools diff --git a/Modules/Platform/NetBSD.cmake b/Modules/Platform/NetBSD.cmake index d99cb4a..ab85923 100644 --- a/Modules/Platform/NetBSD.cmake +++ b/Modules/Platform/NetBSD.cmake @@ -12,4 +12,38 @@ set(CMAKE_SHARED_LIBRARY_RPATH_LINK_C_FLAG "-Wl,-rpath-link,") set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-Wl,-soname,") set(CMAKE_EXE_EXPORTS_C_FLAG "-Wl,--export-dynamic") + +# Features for LINK_LIBRARY generator expression +## check linker capabilities +if(NOT DEFINED _CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + execute_process(COMMAND "${CMAKE_LINKER}" --help + OUTPUT_VARIABLE __linker_help + ERROR_VARIABLE __linker_help) + if(__linker_help MATCHES "--push-state" AND __linker_help MATCHES "--pop-state") + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED TRUE CACHE INTERNAL "linker supports push/pop state") + else() + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED FALSE CACHE INTERNAL "linker supports push/pop state") + endif() + unset(__linker_help) +endif() +## WHOLE_ARCHIVE: Force loading all members of an archive +if(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--push-state,--whole-archive" + "<LINK_ITEM>" + "LINKER:--pop-state") +else() + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--whole-archive" + "<LINK_ITEM>" + "LINKER:--no-whole-archive") +endif() +set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE) + + +# Features for LINK_GROUP generator expression +## RESCAN: request the linker to rescan static libraries until there is +## no pending undefined symbols +set(CMAKE_LINK_GROUP_USING_RESCAN "LINKER:--start-group" "LINKER:--end-group") +set(CMAKE_LINK_GROUP_USING_RESCAN_SUPPORTED TRUE) + + include(Platform/UnixPaths) diff --git a/Modules/Platform/OS2-OpenWatcom-C.cmake b/Modules/Platform/OS2-OpenWatcom-C.cmake index 21a4d9e..a6a6b78 100644 --- a/Modules/Platform/OS2-OpenWatcom-C.cmake +++ b/Modules/Platform/OS2-OpenWatcom-C.cmake @@ -1 +1,2 @@ include(Platform/OS2-OpenWatcom) +__os2_open_watcom(C) diff --git a/Modules/Platform/OS2-OpenWatcom-CXX.cmake b/Modules/Platform/OS2-OpenWatcom-CXX.cmake index 21a4d9e..846bb29 100644 --- a/Modules/Platform/OS2-OpenWatcom-CXX.cmake +++ b/Modules/Platform/OS2-OpenWatcom-CXX.cmake @@ -1 +1,2 @@ include(Platform/OS2-OpenWatcom) +__os2_open_watcom(CXX) diff --git a/Modules/Platform/OS2-OpenWatcom.cmake b/Modules/Platform/OS2-OpenWatcom.cmake index 998fb9f..720b953 100644 --- a/Modules/Platform/OS2-OpenWatcom.cmake +++ b/Modules/Platform/OS2-OpenWatcom.cmake @@ -16,6 +16,14 @@ endif() set(CMAKE_C_COMPILE_OPTIONS_DLL "-bd") # Note: This variable is a ';' separated list set(CMAKE_SHARED_LIBRARY_C_FLAGS "-bd") # ... while this is a space separated string. +cmake_policy(GET CMP0136 __OS2_WATCOM_CMP0136) +if(__OS2_WATCOM_CMP0136 STREQUAL "NEW") + set(CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT "SingleThreaded") +else() + set(CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT "") +endif() +unset(__OS2_WATCOM_CMP0136) + string(APPEND CMAKE_C_FLAGS_INIT " -bt=os2") string(APPEND CMAKE_CXX_FLAGS_INIT " -bt=os2 -xs") @@ -33,3 +41,10 @@ if(NOT CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES) set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES $ENV{WATCOM}/h $ENV{WATCOM}/h/os2) endif() endif() + +macro(__os2_open_watcom lang) + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_SingleThreaded "") + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_SingleThreadedDLL -br) + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_MultiThreaded -bm) + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_MultiThreadedDLL -bm -br) +endmacro() diff --git a/Modules/Platform/SunOS.cmake b/Modules/Platform/SunOS.cmake index 78eccf7..b8a302c 100644 --- a/Modules/Platform/SunOS.cmake +++ b/Modules/Platform/SunOS.cmake @@ -7,6 +7,30 @@ if(CMAKE_SYSTEM MATCHES "SunOS-4") set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP ":") endif() + +# Features for LINK_LIBRARY generator expression +## WHOLE_ARCHIVE: Force loading all members of an archive +if (CMAKE_SYSTEM_VERSION VERSION_GREATER "5.10") + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--whole-archive" + "<LINK_ITEM>" + "LINKER:--no-whole-archive") +else() + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:-z,allextract" + "<LINK_ITEM>" + "LINKER:-z,defaultextract") +endif() +set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE) + + +# Features for LINK_GROUP generator expression +if (CMAKE_SYSTEM_VERSION VERSION_GREATER "5.9") + ## RESCAN: request the linker to rescan static libraries until there is + ## no pending undefined symbols + set(CMAKE_LINK_GROUP_USING_RESCAN "LINKER:-z,rescan-start" "LINKER:-z,rescan-end") + set(CMAKE_LINK_GROUP_USING_RESCAN_SUPPORTED TRUE) +endif() + + include(Platform/UnixPaths) list(APPEND CMAKE_SYSTEM_PREFIX_PATH diff --git a/Modules/Platform/UnixPaths.cmake b/Modules/Platform/UnixPaths.cmake index b9381c3..8a0ad23 100644 --- a/Modules/Platform/UnixPaths.cmake +++ b/Modules/Platform/UnixPaths.cmake @@ -44,6 +44,7 @@ if (NOT CMAKE_FIND_NO_INSTALL_PREFIX) ) endif() endif() +_cmake_record_install_prefix() # Non "standard" but common install prefixes list(APPEND CMAKE_SYSTEM_PREFIX_PATH diff --git a/Modules/Platform/Windows-Clang-ASM.cmake b/Modules/Platform/Windows-Clang-ASM.cmake index 345d77d..c22e3b0 100644 --- a/Modules/Platform/Windows-Clang-ASM.cmake +++ b/Modules/Platform/Windows-Clang-ASM.cmake @@ -1,2 +1,7 @@ include(Platform/Windows-Clang) __windows_compiler_clang(ASM) + +set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded "") +set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL "") +set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug "") +set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL "") diff --git a/Modules/Platform/Windows-Clang.cmake b/Modules/Platform/Windows-Clang.cmake index 1c32018..3941311 100644 --- a/Modules/Platform/Windows-Clang.cmake +++ b/Modules/Platform/Windows-Clang.cmake @@ -39,6 +39,7 @@ macro(__windows_compiler_clang_gnu lang) set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP) set(CMAKE_${lang}_LINKER_MANIFEST_FLAG " -Xlinker /MANIFESTINPUT:") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror") if("${CMAKE_${lang}_SIMULATE_VERSION}" MATCHES "^([0-9]+)\\.([0-9]+)") math(EXPR MSVC_VERSION "${CMAKE_MATCH_1}*100 + ${CMAKE_MATCH_2}") @@ -56,7 +57,12 @@ macro(__windows_compiler_clang_gnu lang) set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_LIBRARIES 1) set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_INCLUDES 1) - set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto") + if(CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 3.9) + set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto=thin") + else() + set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto") + endif() + set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES) set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) set(CMAKE_${lang}_ARCHIVE_CREATE_IPO "<CMAKE_AR> qc <TARGET> <LINK_FLAGS> <OBJECTS>") @@ -96,6 +102,7 @@ macro(__windows_compiler_clang_gnu lang) string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG -Xclang -gcodeview ${__ADDED_FLAGS}") endif() set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ") + set(CMAKE_${lang}_LINKER_SUPPORTS_PDB ON) set(CMAKE_PCH_EXTENSION .pch) set(CMAKE_PCH_PROLOGUE "#pragma clang system_header") @@ -107,6 +114,13 @@ macro(__windows_compiler_clang_gnu lang) string(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE_LOWER) set(CMAKE_${lang}_STANDARD_LIBRARIES_INIT "-lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -loldnames") + # Features for LINK_LIBRARY generator expression + if(MSVC_VERSION GREATER "1900") + ## WHOLE_ARCHIVE: Force loading all members of an archive + set(CMAKE_${lang}_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:/WHOLEARCHIVE:<LIBRARY>") + set(CMAKE_${lang}_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE) + endif() + enable_language(RC) endmacro() @@ -176,7 +190,8 @@ if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC" macro(__windows_compiler_clang_base lang) set(_COMPILE_${lang} "${_COMPILE_${lang}_MSVC}") __windows_compiler_msvc(${lang}) - set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-imsvc ") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-WX") + set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-imsvc") endmacro() else() cmake_policy(GET CMP0091 __WINDOWS_CLANG_CMP0091) diff --git a/Modules/Platform/Windows-GNU.cmake b/Modules/Platform/Windows-GNU.cmake index 51dc146..b464169 100644 --- a/Modules/Platform/Windows-GNU.cmake +++ b/Modules/Platform/Windows-GNU.cmake @@ -44,6 +44,39 @@ if("${_help}" MATCHES "GNU ld .* 2\\.1[1-6]") set(__WINDOWS_GNU_LD_RESPONSE 0) endif() + +# Features for LINK_LIBRARY generator expression +## check linker capabilities +if(NOT DEFINED _CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + execute_process(COMMAND "${CMAKE_LINKER}" --help + OUTPUT_VARIABLE __linker_help + ERROR_VARIABLE __linker_help) + if(__linker_help MATCHES "--push-state" AND __linker_help MATCHES "--pop-state") + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED TRUE CACHE INTERNAL "linker supports push/pop state") + else() + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED FALSE CACHE INTERNAL "linker supports push/pop state") + endif() + unset(__linker_help) +endif() +## WHOLE_ARCHIVE: Force loading all members of an archive +if(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--push-state,--whole-archive" + "<LINK_ITEM>" + "LINKER:--pop-state") +else() + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--whole-archive" + "<LINK_ITEM>" + "LINKER:--no-whole-archive") +endif() +set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE) + +# Features for LINK_GROUP generator expression +## RESCAN: request the linker to rescan static libraries until there is +## no pending undefined symbols +set(CMAKE_LINK_GROUP_USING_RESCAN "LINKER:--start-group" "LINKER:--end-group") +set(CMAKE_LINK_GROUP_USING_RESCAN_SUPPORTED TRUE) + + macro(__windows_compiler_gnu lang) # Create archiving rules to support large object file lists for static libraries. diff --git a/Modules/Platform/Windows-IntelLLVM.cmake b/Modules/Platform/Windows-IntelLLVM.cmake index 8231e78..f24dcdb 100644 --- a/Modules/Platform/Windows-IntelLLVM.cmake +++ b/Modules/Platform/Windows-IntelLLVM.cmake @@ -12,6 +12,19 @@ include(Platform/Windows-MSVC) macro(__windows_compiler_intel lang) __windows_compiler_msvc(${lang}) + # For DPCPP other offload cases, some link flags need to go to the compiler + # driver and others need to go to the linker. Pass the compiler linking flags + # in CMAKE_${lang}_LINK_FLAGS and linker flags in LINK_FLAGS + set(CMAKE_${lang}_LINK_EXECUTABLE + "${_CMAKE_VS_LINK_EXE}<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} /link /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}") + set(CMAKE_${lang}_CREATE_SHARED_LIBRARY + "${_CMAKE_VS_LINK_DLL}<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} -LD -link /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}") + if (NOT "${lang}" STREQUAL "Fortran" OR CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 2022.1) + # The Fortran driver does not support -fuse-ld=llvm-lib before compiler version 2022.1 + set(CMAKE_${lang}_CREATE_STATIC_LIBRARY + "<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} -fuse-ld=llvm-lib -o <TARGET> -link <LINK_FLAGS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}") + endif() + set(CMAKE_DEPFILE_FLAGS_${lang} "-QMD -QMT <DEP_TARGET> -QMF <DEP_FILE>") set(CMAKE_${lang}_DEPFILE_FORMAT gcc) endmacro() diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index 7d602c3..e74ec9e 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -226,7 +226,7 @@ elseif(WINDOWS_PHONE OR WINDOWS_STORE) else() set(_PLATFORM_DEFINES "/DWIN32") if((_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM64EC") OR (_MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM64EC")) - set(_PLATFORM_DEFINES "${_PLATFORM_DEFINES} /D_AMD64_ /DAMD64 /D_ARM64EC_ /DARM64EC /D_ARM64EC_WORKAROUND_") + set(_PLATFORM_DEFINES "${_PLATFORM_DEFINES} /D_AMD64_ /DAMD64 /D_ARM64EC_ /DARM64EC") endif() if(_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM" OR _MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM") set(CMAKE_C_STANDARD_LIBRARIES_INIT "kernel32.lib user32.lib") @@ -246,6 +246,10 @@ else() set(CMAKE_C_STANDARD_LIBRARIES_INIT "kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib") endif() + if((_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM64EC") OR (_MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM64EC")) + string(APPEND CMAKE_C_STANDARD_LIBRARIES_INIT " softintrin.lib") + endif() + if(MSVC_VERSION LESS 1310) set(_FLAGS_C " /Zm1000${_FLAGS_C}") set(_FLAGS_CXX " /Zm1000${_FLAGS_CXX}") @@ -327,6 +331,15 @@ else() endif() unset(__WINDOWS_MSVC_CMP0091) + +# Features for LINK_LIBRARY generator expression +if(MSVC_VERSION GREATER "1900") + ## WHOLE_ARCHIVE: Force loading all members of an archive + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "/WHOLEARCHIVE:<LIBRARY>") + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE) +endif() + + macro(__windows_compiler_msvc lang) if(NOT MSVC_VERSION LESS 1400) # for 2005 make sure the manifest is put in the dll with mt @@ -478,7 +491,7 @@ macro(__windows_compiler_msvc_enable_rc flags) endif() enable_language(RC) - if(NOT DEFINED CMAKE_NINJA_CMCLDEPS_RC) + if(NOT DEFINED CMAKE_NINJA_CMCLDEPS_RC AND CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") set(CMAKE_NINJA_CMCLDEPS_RC 1) endif() endmacro() diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake index b83932e..6c1699b 100644 --- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake +++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake @@ -1,11 +1,7 @@ include(Platform/Windows-MSVC) -set(CMAKE_CUDA_COMPILE_PTX_COMPILATION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -ptx <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") -set(CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -dc <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") -set(CMAKE_CUDA_COMPILE_WHOLE_COMPILATION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -c <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") +set(CMAKE_CUDA_COMPILE_OBJECT + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} <CUDA_COMPILE_MODE> <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") set(__IMPLICIT_LINKS) foreach(dir ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES}) diff --git a/Modules/Platform/Windows-OpenWatcom.cmake b/Modules/Platform/Windows-OpenWatcom.cmake index 19bcb97..657a923 100644 --- a/Modules/Platform/Windows-OpenWatcom.cmake +++ b/Modules/Platform/Windows-OpenWatcom.cmake @@ -14,11 +14,20 @@ set(CMAKE_SHARED_LIBRARY_C_FLAGS "-bd") # ... while this is a space separated st set(CMAKE_RC_COMPILER "rc" ) -# single/multi-threaded /-bm -# static/DLL run-time libraries /-br -# default is setup for multi-threaded + DLL run-time libraries -string(APPEND CMAKE_C_FLAGS_INIT " -bt=nt -dWIN32 -br -bm") -string(APPEND CMAKE_CXX_FLAGS_INIT " -bt=nt -xs -dWIN32 -br -bm") +cmake_policy(GET CMP0136 __WINDOWS_WATCOM_CMP0136) +if(__WINDOWS_WATCOM_CMP0136 STREQUAL "NEW") + set(CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT "MultiThreadedDLL") + set(_br_bm "") +else() + set(CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT "") + set(_br_bm "-br -bm") +endif() + +string(APPEND CMAKE_C_FLAGS_INIT " -bt=nt -dWIN32 ${_br_bm}") +string(APPEND CMAKE_CXX_FLAGS_INIT " -bt=nt -xs -dWIN32 ${_br_bm}") + +unset(__WINDOWS_WATCOM_CMP0136) +unset(_br_bm) if(CMAKE_CROSSCOMPILING) if(NOT CMAKE_C_STANDARD_INCLUDE_DIRECTORIES) @@ -32,4 +41,9 @@ endif() macro(__windows_open_watcom lang) set(CMAKE_${lang}_CREATE_WIN32_EXE "system nt_win") set(CMAKE_${lang}_CREATE_CONSOLE_EXE "system nt") + + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_SingleThreaded "") + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_SingleThreadedDLL -br) + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_MultiThreaded -bm) + set(CMAKE_${lang}_COMPILE_OPTIONS_WATCOM_RUNTIME_LIBRARY_MultiThreadedDLL -bm -br) endmacro() diff --git a/Modules/Platform/WindowsPaths.cmake b/Modules/Platform/WindowsPaths.cmake index b9e2f17..de93338 100644 --- a/Modules/Platform/WindowsPaths.cmake +++ b/Modules/Platform/WindowsPaths.cmake @@ -67,6 +67,7 @@ if (NOT CMAKE_FIND_NO_INSTALL_PREFIX) ) endif() endif() +_cmake_record_install_prefix() if(CMAKE_CROSSCOMPILING AND NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows") # MinGW (useful when cross compiling from linux with CMAKE_FIND_ROOT_PATH set) diff --git a/Modules/RepositoryInfo.txt.in b/Modules/RepositoryInfo.txt.in deleted file mode 100644 index df8e322..0000000 --- a/Modules/RepositoryInfo.txt.in +++ /dev/null @@ -1,3 +0,0 @@ -repository='@repository@' -module='@module@' -tag='@tag@' |