Просмотр исходного кода

try_compile: Propagating top level includes into whole-project calls

Fixes: #24151
Craig Scott 1 год назад
Родитель
Сommit
4cb5bb014d

+ 5 - 0
Help/command/cmake_language.rst

@@ -271,6 +271,11 @@ Dependency Providers
   :command:`project`.  Calling ``cmake_language(SET_DEPENDENCY_PROVIDER)``
   outside of that context will result in an error.
 
+  .. versionadded:: 3.30
+    The :prop_gbl:`PROPAGATE_TOP_LEVEL_INCLUDES_TO_TRY_COMPILE` global
+    property can be set if the dependency provider also wants to be enabled
+    in whole-project calls to :command:`try_compile`.
+
   .. note::
     The choice of dependency provider should always be under the user's control.
     As a convenience, a project may choose to provide a file that users can

+ 11 - 0
Help/command/try_compile.rst

@@ -47,6 +47,11 @@ below for the meaning of other options.
   :ref:`configure-log try_compile event <try_compile configure-log event>`
   if the ``NO_LOG`` option is not specified.
 
+.. versionadded:: 3.30
+  If the :prop_gbl:`PROPAGATE_TOP_LEVEL_INCLUDES_TO_TRY_COMPILE` global
+  property is set to true, :variable:`CMAKE_PROJECT_TOP_LEVEL_INCLUDES` is
+  propagated into the project's build configuration.
+
 This command supports an alternate signature for CMake older than 3.25.
 The signature above is recommended for clarity.
 
@@ -388,6 +393,12 @@ configuration:
   :variable:`CMAKE_MSVC_DEBUG_INFORMATION_FORMAT` to specify the MSVC debug
   information format.
 
+.. versionadded:: 3.30
+  If the :prop_gbl:`PROPAGATE_TOP_LEVEL_INCLUDES_TO_TRY_COMPILE` global
+  property is set to true, :variable:`CMAKE_PROJECT_TOP_LEVEL_INCLUDES` is
+  propagated into the test project's build configuration when using the
+  :ref:`whole-project signature <Try Compiling Whole Projects>`.
+
 See Also
 ^^^^^^^^
 

+ 1 - 0
Help/manual/cmake-properties.7.rst

@@ -44,6 +44,7 @@ Properties of Global Scope
    /prop_gbl/PACKAGES_FOUND
    /prop_gbl/PACKAGES_NOT_FOUND
    /prop_gbl/PREDEFINED_TARGETS_FOLDER
+   /prop_gbl/PROPAGATE_TOP_LEVEL_INCLUDES_TO_TRY_COMPILE
    /prop_gbl/REPORT_UNDEFINED_PROPERTIES
    /prop_gbl/RULE_LAUNCH_COMPILE
    /prop_gbl/RULE_LAUNCH_CUSTOM

+ 19 - 0
Help/prop_gbl/PROPAGATE_TOP_LEVEL_INCLUDES_TO_TRY_COMPILE.rst

@@ -0,0 +1,19 @@
+PROPAGATE_TOP_LEVEL_INCLUDES_TO_TRY_COMPILE
+-------------------------------------------
+
+.. versionadded:: 3.30
+
+When this global property is set to true, the
+:variable:`CMAKE_PROJECT_TOP_LEVEL_INCLUDES` variable is propagated into
+:command:`try_compile` calls that use the
+:ref:`whole-project signature <Try Compiling Whole Projects>`.
+Calls to the :ref:`source file signature <Try Compiling Source Files>` are not
+affected by this property.
+``PROPAGATE_TOP_LEVEL_INCLUDES_TO_TRY_COMPILE`` is unset by default.
+
+For :ref:`dependency providers <dependency_providers_overview>` that want to
+be enabled in whole-project :command:`try_compile` calls, set this global
+property to true just before or after registering the provider.
+Note that all files listed in :variable:`CMAKE_PROJECT_TOP_LEVEL_INCLUDES`
+will need to be able to handle being included in such :command:`try_compile`
+calls, and it is the user's responsibility to ensure this.

+ 9 - 0
Help/release/dev/dep-provider-try_compile.rst

@@ -0,0 +1,9 @@
+dep-provider-try_compile
+------------------------
+
+* The :prop_gbl:`PROPAGATE_TOP_LEVEL_INCLUDES_TO_TRY_COMPILE` global property
+  can be used to propagate :variable:`CMAKE_PROJECT_TOP_LEVEL_INCLUDES` into
+  :command:`try_compile` calls that use the
+  :ref:`whole-project signature <Try Compiling Whole Projects>`.
+  This is primarily intended as a way for dependency providers to be enabled
+  in such :command:`try_compile` calls.

+ 7 - 4
Help/variable/CMAKE_PROJECT_TOP_LEVEL_INCLUDES.rst

@@ -25,7 +25,10 @@ details (use :variable:`CMAKE_TOOLCHAIN_FILE` for that).
 
 By default, this variable is empty.  It is intended to be set by the user.
 
-See also the :variable:`CMAKE_PROJECT_INCLUDE`,
-:variable:`CMAKE_PROJECT_INCLUDE_BEFORE`,
-:variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE`, and
-:variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE` variables.
+See also:
+
+* :variable:`CMAKE_PROJECT_INCLUDE`
+* :variable:`CMAKE_PROJECT_INCLUDE_BEFORE`
+* :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE`
+* :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE`
+* :prop_gbl:`PROPAGATE_TOP_LEVEL_INCLUDES_TO_TRY_COMPILE`

+ 11 - 0
Source/cmCoreTryCompile.cxx

@@ -1240,6 +1240,17 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode(
     }
   }
 
+  if (!this->SrcFileSignature &&
+      this->Makefile->GetState()->GetGlobalPropertyAsBool(
+        "PROPAGATE_TOP_LEVEL_INCLUDES_TO_TRY_COMPILE")) {
+    const std::string var = "CMAKE_PROJECT_TOP_LEVEL_INCLUDES";
+    if (cmValue val = this->Makefile->GetDefinition(var)) {
+      std::string flag = cmStrCat("-D", var, "=\'", *val, '\'');
+      arguments.CMakeFlags.emplace_back(std::move(flag));
+      cmakeVariables.emplace(var, *val);
+    }
+  }
+
   if (this->Makefile->GetState()->UseGhsMultiIDE()) {
     // Forward the GHS variables to the inner project cache.
     for (std::string const& var : ghs_platform_vars) {

+ 1 - 0
Tests/RunCMake/try_compile/RunCMakeTest.cmake

@@ -16,6 +16,7 @@ run_cmake_with_options(Inspect
 include("${RunCMake_BINARY_DIR}/Inspect-build/info.cmake")
 
 run_cmake(ConfigureLog)
+run_cmake(TopIncludes)
 run_cmake(NoArgs)
 run_cmake(OneArg)
 run_cmake(TwoArgs)

+ 85 - 0
Tests/RunCMake/try_compile/TopIncludes-config.txt

@@ -0,0 +1,85 @@
+^
+---
+events:(
+  -
+    kind: "message-v1"
+    backtrace:(
+      - "[^"]+")+
+    message: \|(
++      [^
+]*)*)+
+  -
+    kind: "try_compile-v1"
+    backtrace:
+      - "[^"]*/Modules/CMakeDetermineCompilerABI.cmake:[0-9]+ \(try_compile\)"
+      - "[^"]*/Modules/CMakeTestCCompiler.cmake:[0-9]+ \(CMAKE_DETERMINE_COMPILER_ABI\)"
+      - "TopIncludes.cmake:[0-9]+ \(enable_language\)"
+      - "CMakeLists.txt:[0-9]+ \(include\)"
+    checks:
+      - "Detecting C compiler ABI info"
+    directories:
+      source: "[^"]*/Tests/RunCMake/try_compile/TopIncludes-build/CMakeFiles/CMakeScratch/TryCompile-[^/"]+"
+      binary: "[^"]*/Tests/RunCMake/try_compile/TopIncludes-build/CMakeFiles/CMakeScratch/TryCompile-[^/"]+"
+    cmakeVariables:(
+      CMAKE_[^
+]*)+
+    buildResult:
+      variable: "CMAKE_C_ABI_COMPILED"
+      cached: true
+      stdout: \|.*
+      exitCode: 0(
+  -
+    kind: "message-v1"
+    backtrace:(
+      - "[^"]+")+
+    message: \|(
++      [^
+]*)*)*
+  -
+    kind: "try_compile-v1"
+    backtrace:
+      - "TopIncludes.cmake:[0-9]+ \(try_compile\)"
+      - "CMakeLists.txt:[0-9]+ \(include\)"
+    description: "Project without property set\."
+    directories:
+      source: "[^"]*/Tests/RunCMake/try_compile/proj"
+      binary: "[^"]*/Tests/RunCMake/try_compile/TopIncludes-build/CMakeFiles/CMakeScratch/TryCompile-[^/"]+"
+    buildResult:
+      variable: "result"
+      cached: true
+      stdout: \|.*
+      exitCode: 0
+  -
+    kind: "try_compile-v1"
+    backtrace:
+      - "TopIncludes.cmake:[0-9]+ \(try_compile\)"
+      - "CMakeLists.txt:[0-9]+ \(include\)"
+    description: "Project with property set\."
+    directories:
+      source: "[^"]*/Tests/RunCMake/try_compile/proj"
+      binary: "[^"]*/Tests/RunCMake/try_compile/TopIncludes-build/CMakeFiles/CMakeScratch/TryCompile-[^/"]+"
+    cmakeVariables:
+      CMAKE_PROJECT_TOP_LEVEL_INCLUDES: "[^"]*/Tests/RunCMake/try_compile/include_pass1.cmake;[^"]*/Tests/RunCMake/try_compile/include_pass2.cmake"
+    buildResult:
+      variable: "result"
+      cached: true
+      stdout: \|.*
+      exitCode: 0
+  -
+    kind: "try_compile-v1"
+    backtrace:
+      - "TopIncludes.cmake:[0-9]+ \(try_compile\)"
+      - "CMakeLists.txt:[0-9]+ \(include\)"
+    description: "Source file with property set\."
+    directories:
+      source: "[^"]*/Tests/RunCMake/try_compile/TopIncludes-build/CMakeFiles/CMakeScratch/TryCompile-[^/"]+"
+      binary: "[^"]*/Tests/RunCMake/try_compile/TopIncludes-build/CMakeFiles/CMakeScratch/TryCompile-[^/"]+"
+    cmakeVariables:(
+      CMAKE_[^
+]*)+
+    buildResult:
+      variable: "result"
+      cached: true
+      stdout: \|.*
+      exitCode: 0
+\.\.\.$

+ 34 - 0
Tests/RunCMake/try_compile/TopIncludes.cmake

@@ -0,0 +1,34 @@
+enable_language(C)
+
+# Normally CMAKE_PROJECT_TOP_LEVEL_INCLUDES must be set before the first
+# project() call. We don't care about the variable's usual effects here, we
+# only care whether the variable is propagated to try_compile() project calls.
+set(CMAKE_PROJECT_TOP_LEVEL_INCLUDES
+  ${CMAKE_CURRENT_LIST_DIR}/include_error.cmake
+)
+
+try_compile(result
+  PROJECT TestProject
+  SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/proj
+  LOG_DESCRIPTION "Project without property set."
+)
+
+set_property(GLOBAL PROPERTY PROPAGATE_TOP_LEVEL_INCLUDES_TO_TRY_COMPILE YES)
+set(CMAKE_PROJECT_TOP_LEVEL_INCLUDES
+  ${CMAKE_CURRENT_LIST_DIR}/include_pass1.cmake
+  ${CMAKE_CURRENT_LIST_DIR}/include_pass2.cmake
+)
+try_compile(result
+  PROJECT TestProject
+  SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/proj
+  LOG_DESCRIPTION "Project with property set."
+)
+
+# Confirm the property only affects whole project signature
+set(CMAKE_PROJECT_TOP_LEVEL_INCLUDES
+  ${CMAKE_CURRENT_LIST_DIR}/include_error.cmake
+)
+try_compile(result
+  SOURCES ${CMAKE_CURRENT_LIST_DIR}/src.c
+  LOG_DESCRIPTION "Source file with property set."
+)

+ 1 - 0
Tests/RunCMake/try_compile/include_error.cmake

@@ -0,0 +1 @@
+message(FATAL_ERROR "Unexpectedly read top level include file")

+ 1 - 0
Tests/RunCMake/try_compile/include_pass1.cmake

@@ -0,0 +1 @@
+message(STATUS "Top level include file was read - pass 1")

+ 1 - 0
Tests/RunCMake/try_compile/include_pass2.cmake

@@ -0,0 +1 @@
+message(STATUS "Top level include file was read - pass 2")

+ 1 - 1
Tests/RunCMake/try_compile/proj/CMakeLists.txt

@@ -1,2 +1,2 @@
-cmake_minimum_required(VERSION 3.3)
+cmake_minimum_required(VERSION 3.5)
 project(TestProject NONE)