From 27093bcede2bc2458cd20bbafbfb761387c77df8 Mon Sep 17 00:00:00 2001 From: Matthias Maier Date: Mon, 22 May 2023 16:28:33 -0500 Subject: [PATCH] CMake: multiple fixes for check_compiler_setup() - use custom build type for test project to avoid auto populated compiler flags - remove dysfunctional caching mechanism - properly escape compile and link options - expand interface targets --- .../check_compiler_setup/CMakeLists.txt | 11 +-- cmake/macros/macro_check_compiler_setup.cmake | 83 ++++++++++++------- 2 files changed, 59 insertions(+), 35 deletions(-) diff --git a/cmake/macros/check_compiler_setup/CMakeLists.txt b/cmake/macros/check_compiler_setup/CMakeLists.txt index 3b9e5a2ea4..543f86cadc 100644 --- a/cmake/macros/check_compiler_setup/CMakeLists.txt +++ b/cmake/macros/check_compiler_setup/CMakeLists.txt @@ -1,13 +1,10 @@ +# use a "Custom" build type to avoid auto populated compiler flags +set(CMAKE_BUILD_TYPE "Custom") cmake_minimum_required(VERSION 3.13.4) project(CheckCompilerSetup) add_executable(CheckCompilerSetupExec dummy.cpp) -# Make sure some CUDA warning flags don't get deduplicated -string (REPLACE ";" " " TEST_COMPILE_FLAGS "${TEST_COMPILE_FLAGS}") -string(REGEX REPLACE "(-Xcudafe --diag_suppress=[^ ]+)" "\"SHELL:\\1\"" TEST_COMPILE_FLAGS "${TEST_COMPILE_FLAGS}") -separate_arguments(TEST_COMPILE_FLAGS UNIX_COMMAND "${TEST_COMPILE_FLAGS}") - -target_compile_options(CheckCompilerSetupExec PRIVATE ${TEST_COMPILE_FLAGS}) -set_property(TARGET CheckCompilerSetupExec PROPERTY LINK_FLAGS "${TEST_LINK_OPTIONS}") +target_compile_options(CheckCompilerSetupExec PRIVATE ${TEST_COMPILE_OPTIONS}) +target_link_options(CheckCompilerSetupExec PRIVATE ${TEST_LINK_OPTIONS}) target_link_libraries(CheckCompilerSetupExec ${TEST_LINK_LIBRARIES}) diff --git a/cmake/macros/macro_check_compiler_setup.cmake b/cmake/macros/macro_check_compiler_setup.cmake index c86045624f..bf4c983acf 100644 --- a/cmake/macros/macro_check_compiler_setup.cmake +++ b/cmake/macros/macro_check_compiler_setup.cmake @@ -25,49 +25,76 @@ # ${_var} is set to true, otherwise it is set to false. # -macro(check_compiler_setup _compiler_flags_unstr _linker_flags_unstr _var) +macro(check_compiler_setup _compiler_flags _linker_flags _var) + message(STATUS "Performing Test ${_var}") + # - # Strip leading and trailing whitespace to make CMake 2.8.8 happy + # We used to do some fancy caching here, but for now simply rerun this + # check every time and do not bother with an elaborate caching strategy. + # We simply keep the build directory for the check around and rely on the + # build system to skip unnecessary recompilation. # - string(STRIP "${_compiler_flags_unstr}" _compiler_flags) - string(STRIP "${_linker_flags_unstr}" _linker_flags) - - separate_arguments(_compiler_flags) # - # Rerun this test if flags have changed: + # Prepare compile and link options: # - if(NOT "${_compiler_flags}" STREQUAL "${CACHED_${_var}_compiler_flags}" - OR NOT "${_linker_flags}" STREQUAL "${CACHED_${_var}_linker_flags}" - OR NOT "${ARGN}" STREQUAL "${CACHED_${_var}_ARGN}") - unset(${_var} CACHE) - endif() - set(CACHED_${_var}_compiler_flags "${_compiler_flags}" - CACHE INTERNAL "" FORCE - ) - set(CACHED_${_var}_linker_flags "${_linker_flags}" - CACHE INTERNAL "" FORCE - ) - set(CACHED_${_var}_ARGN "${ARGN}" CACHE INTERNAL "" FORCE) + separate_arguments(_compile_options UNIX_COMMAND "${_compiler_flags}") + shell_escape_option_groups(_compile_options) + separate_arguments(_link_options UNIX_COMMAND "${_linker_flags}") + shell_escape_option_groups(_link_options) - message(STATUS "Testing ${_var}") + # + # Ideally, we would like to simply list our internal interface_* targets, + # which might recursively list imported targets... But unfortunately, + # CMake as of version 3.25 does not support this operation. + # + # Rermak: What we try to accomplish here is somewhat fundamentally + # incompatible with how CMake envisions import targets to function. + # Namely, the final link line is only constructed after the "configure + # phase" during the "generator phase". + # + # As a workaround, at least for now, let us make the assumption that we + # only ever encounter an interface_* target and that imported targets + # have been expanded. + # + + set(_libraries) + foreach(_entry ${ARGN}) + if(TARGET ${_entry}) + get_target_property(_value ${_entry} INTERFACE_LINK_LIBRARIES) + if(NOT "${_value}" MATCHES "-NOTFOUND") + list(APPEND _libraries ${_value}) + endif() + get_target_property(_values ${_entry} INTERFACE_COMPILE_OPTIONS) + if(NOT "${_values}" MATCHES "-NOTFOUND") + list(APPEND _compile_options ${_values}) + endif() + get_target_property(_values ${_entry} INTERFACE_LINK_OPTIONS) + if(NOT "${_values}" MATCHES "-NOTFOUND") + list(APPEND _link_options ${_values}) + endif() + else() + list(APPEND _libraries ${_entry}) + endif() + endforeach() try_compile( ${_var} - ${CMAKE_CURRENT_BINARY_DIR}/check_compiler_setup/CheckCompilerSetup${_var} + ${CMAKE_CURRENT_BINARY_DIR}/check_compiler_setup/${_var} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/macros/check_compiler_setup CheckCompilerSetup${_var} - CMAKE_FLAGS "-DTEST_COMPILE_FLAGS=${_compiler_flags}" - "-DTEST_LINK_OPTIONS=${_linker_flags}" - "-DTEST_LINK_LIBRARIES=${ARGN}" + CMAKE_FLAGS "-DTEST_COMPILE_OPTIONS=${_compile_options}" + "-DTEST_LINK_OPTIONS=${_link_options}" + "-DTEST_LINK_LIBRARIES=${_libraries}" "-DCMAKE_VERBOSE_MAKEFILE=ON" - OUTPUT_VARIABLE _output) + OUTPUT_VARIABLE _output + ) if(${_var}) - set(${_var} TRUE CACHE INTERNAL "") - file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/check_compiler_setup/CheckCompilerSetup${var}) + message(STATUS "Performing Test ${_var} - Success") else() - message(STATUS "Compiler setup check for ${_var} failed with:\n${_output}") + message(STATUS "Performing Test ${_var} - Failed") + message(STATUS "Compiler output:\n\n${_output}") endif() endmacro() -- 2.39.5