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

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)``
   :command:`project`.  Calling ``cmake_language(SET_DEPENDENCY_PROVIDER)``
   outside of that context will result in an error.
   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::
   .. note::
     The choice of dependency provider should always be under the user's control.
     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
     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>`
   :ref:`configure-log try_compile event <try_compile configure-log event>`
   if the ``NO_LOG`` option is not specified.
   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.
 This command supports an alternate signature for CMake older than 3.25.
 The signature above is recommended for clarity.
 The signature above is recommended for clarity.
 
 
@@ -388,6 +393,12 @@ configuration:
   :variable:`CMAKE_MSVC_DEBUG_INFORMATION_FORMAT` to specify the MSVC debug
   :variable:`CMAKE_MSVC_DEBUG_INFORMATION_FORMAT` to specify the MSVC debug
   information format.
   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
 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_FOUND
    /prop_gbl/PACKAGES_NOT_FOUND
    /prop_gbl/PACKAGES_NOT_FOUND
    /prop_gbl/PREDEFINED_TARGETS_FOLDER
    /prop_gbl/PREDEFINED_TARGETS_FOLDER
+   /prop_gbl/PROPAGATE_TOP_LEVEL_INCLUDES_TO_TRY_COMPILE
    /prop_gbl/REPORT_UNDEFINED_PROPERTIES
    /prop_gbl/REPORT_UNDEFINED_PROPERTIES
    /prop_gbl/RULE_LAUNCH_COMPILE
    /prop_gbl/RULE_LAUNCH_COMPILE
    /prop_gbl/RULE_LAUNCH_CUSTOM
    /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.
 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()) {
   if (this->Makefile->GetState()->UseGhsMultiIDE()) {
     // Forward the GHS variables to the inner project cache.
     // Forward the GHS variables to the inner project cache.
     for (std::string const& var : ghs_platform_vars) {
     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")
 include("${RunCMake_BINARY_DIR}/Inspect-build/info.cmake")
 
 
 run_cmake(ConfigureLog)
 run_cmake(ConfigureLog)
+run_cmake(TopIncludes)
 run_cmake(NoArgs)
 run_cmake(NoArgs)
 run_cmake(OneArg)
 run_cmake(OneArg)
 run_cmake(TwoArgs)
 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)
 project(TestProject NONE)