Merge topic 'CheckIPOSupported-honor-flags' into release-3.24

ec08bc1752 CheckIPOSupported: Compile check using flags of calling project

Acked-by: Kitware Robot <kwrobot@kitware.com>
Tested-by: buildbot <buildbot@kitware.com>
Merge-request: !7343
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index d99afe3..43eb200 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -59,7 +59,7 @@
    :maxdepth: 1
 
    CMP0139: The if() command supports path comparisons using PATH_EQUAL operator. </policy/CMP0139>
-   CMP0138: Placeholder for reverted policy. </policy/CMP0138>
+   CMP0138: CheckIPOSupported uses flags from calling project. </policy/CMP0138>
    CMP0137: try_compile() passes platform variables in project mode. </policy/CMP0137>
    CMP0136: Watcom runtime library flags are selected by an abstraction. </policy/CMP0136>
    CMP0135: ExternalProject ignores timestamps in archives by default for the URL download method. </policy/CMP0135>
diff --git a/Help/policy/CMP0138.rst b/Help/policy/CMP0138.rst
index c7f0e2d..a86849d 100644
--- a/Help/policy/CMP0138.rst
+++ b/Help/policy/CMP0138.rst
@@ -3,7 +3,25 @@
 
 .. versionadded:: 3.24
 
-Placeholder for reverted policy.
+:module:`CheckIPOSupported` uses flags from calling project.
+
+The :module:`CheckIPOSupported` module :command:`check_ipo_supported`
+command compiles a test project to determine whether the toolchain
+supports :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION`.  CMake 3.23 and
+below run the check with the default values of the
+:variable:`CMAKE_<LANG>_FLAGS` and :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>`
+variables for the current environment and toolchain settings.
+However, some projects may modify these flag variables to add
+flags that affect availability of the toolchain's IPO features.
+CMake 3.24 and above prefer to honor the calling project's values
+for these variables.  This policy provides compatibility for projects
+that have not been updated to expect this behavior.
+
+The ``OLD`` behavior for this policy is to ignore the calling
+project's values of :variable:`CMAKE_<LANG>_FLAGS` and
+:variable:`CMAKE_<LANG>_FLAGS_<CONFIG>`.  The ``NEW`` behavior
+for this policy is to use the values of those variables as
+compiler flags in the test project.
 
 This policy was introduced in CMake version 3.24. Use the
 :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
diff --git a/Help/release/3.24.rst b/Help/release/3.24.rst
index f347acb..4bde23f 100644
--- a/Help/release/3.24.rst
+++ b/Help/release/3.24.rst
@@ -323,6 +323,11 @@
   etc. when enabling the corresponding language during the first CMake run in
   a build directory.  See policy :policy:`CMP0132`.
 
+* The :module:`CheckIPOSupported` module :command:`check_ipo_supported`
+  command now uses the caller's :variable:`CMAKE_<LANG>_FLAGS`
+  and :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` values.
+  See policy :policy:`CMP0138`.
+
 * The :generator:`MSYS Makefiles` and :generator:`MinGW Makefiles`
   generators, when a compiler is not explicitly specified, now select
   the first compiler (of any name) found in directories listed by the
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 @@
 .. 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 @@
     )
   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 @@
       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 @@
     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/Source/cmPolicies.h b/Source/cmPolicies.h
index 72a169a..cb7402c 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -415,7 +415,8 @@
   SELECT(POLICY, CMP0137,                                                     \
          "try_compile() passes platform variables in project mode", 3, 24, 0, \
          cmPolicies::WARN)                                                    \
-  SELECT(POLICY, CMP0138, "Placeholder for reverted policy.", 3, 24, 0,       \
+  SELECT(POLICY, CMP0138,                                                     \
+         "CheckIPOSupported uses flags from calling project.", 3, 24, 0,      \
          cmPolicies::WARN)                                                    \
   SELECT(                                                                     \
     POLICY, CMP0139,                                                          \
diff --git a/Tests/RunCMake/CheckIPOSupported/CMP0138-Common.cmake b/Tests/RunCMake/CheckIPOSupported/CMP0138-Common.cmake
new file mode 100644
index 0000000..508e6c3
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/CMP0138-Common.cmake
@@ -0,0 +1,9 @@
+enable_language(C)
+string(APPEND CMAKE_C_FLAGS " -DFOO")
+string(APPEND CMAKE_C_FLAGS_DEBUG " -DBAR")
+check_ipo_supported(RESULT ipo_supported)
+file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/_CMakeLTOTest-C/bin/CMakeCache.txt"
+  cached_flags REGEX "^CMAKE_C_FLAGS(_DEBUG)?:")
+foreach(line IN LISTS cached_flags)
+  message(STATUS "${line}")
+endforeach()
diff --git a/Tests/RunCMake/CheckIPOSupported/CMP0138-NEW-stdout.txt b/Tests/RunCMake/CheckIPOSupported/CMP0138-NEW-stdout.txt
new file mode 100644
index 0000000..aa150a8
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/CMP0138-NEW-stdout.txt
@@ -0,0 +1,5 @@
+-- CMAKE_C_FLAGS:STRING=[^
+]*-DFOO
+-- CMAKE_C_FLAGS_DEBUG:STRING=[^
+]*-DBAR
+--
diff --git a/Tests/RunCMake/CheckIPOSupported/CMP0138-NEW.cmake b/Tests/RunCMake/CheckIPOSupported/CMP0138-NEW.cmake
new file mode 100644
index 0000000..6611504
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/CMP0138-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0138 NEW)
+include(CMP0138-Common.cmake)
diff --git a/Tests/RunCMake/CheckIPOSupported/CMP0138-OLD-stdout.txt b/Tests/RunCMake/CheckIPOSupported/CMP0138-OLD-stdout.txt
new file mode 100644
index 0000000..c80b208
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/CMP0138-OLD-stdout.txt
@@ -0,0 +1,3 @@
+-- CMAKE_C_FLAGS:STRING=([^-]|-[^D]|-D[^F]|-DF[^O]|-DFO[^O])*
+-- CMAKE_C_FLAGS_DEBUG:STRING=([^-]|-[^D]|-D[^B]|-DB[^A]|-DBA[^R])*
+--
diff --git a/Tests/RunCMake/CheckIPOSupported/CMP0138-OLD.cmake b/Tests/RunCMake/CheckIPOSupported/CMP0138-OLD.cmake
new file mode 100644
index 0000000..b16ac9f
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/CMP0138-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0138 OLD)
+include(CMP0138-Common.cmake)
diff --git a/Tests/RunCMake/CheckIPOSupported/CMP0138-WARN-stdout.txt b/Tests/RunCMake/CheckIPOSupported/CMP0138-WARN-stdout.txt
new file mode 100644
index 0000000..c80b208
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/CMP0138-WARN-stdout.txt
@@ -0,0 +1,3 @@
+-- CMAKE_C_FLAGS:STRING=([^-]|-[^D]|-D[^F]|-DF[^O]|-DFO[^O])*
+-- CMAKE_C_FLAGS_DEBUG:STRING=([^-]|-[^D]|-D[^B]|-DB[^A]|-DBA[^R])*
+--
diff --git a/Tests/RunCMake/CheckIPOSupported/CMP0138-WARN.cmake b/Tests/RunCMake/CheckIPOSupported/CMP0138-WARN.cmake
new file mode 100644
index 0000000..01118ee
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/CMP0138-WARN.cmake
@@ -0,0 +1,2 @@
+# (leave CMP0138 unset)
+include(CMP0138-Common.cmake)
diff --git a/Tests/RunCMake/CheckIPOSupported/Inspect.cmake b/Tests/RunCMake/CheckIPOSupported/Inspect.cmake
new file mode 100644
index 0000000..07e4258
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/Inspect.cmake
@@ -0,0 +1,5 @@
+enable_language(C)
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/info.cmake" "
+set(_CMAKE_C_IPO_SUPPORTED_BY_CMAKE \"${_CMAKE_C_IPO_SUPPORTED_BY_CMAKE}\")
+set(_CMAKE_C_IPO_MAY_BE_SUPPORTED_BY_COMPILER \"${_CMAKE_C_IPO_MAY_BE_SUPPORTED_BY_COMPILER}\")
+")
diff --git a/Tests/RunCMake/CheckIPOSupported/RunCMakeTest.cmake b/Tests/RunCMake/CheckIPOSupported/RunCMakeTest.cmake
index b7d524c..2fb159e 100644
--- a/Tests/RunCMake/CheckIPOSupported/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CheckIPOSupported/RunCMakeTest.cmake
@@ -1,5 +1,8 @@
 include(RunCMake)
 
+run_cmake(Inspect)
+include("${RunCMake_BINARY_DIR}/Inspect-build/info.cmake")
+
 run_cmake(unparsed-arguments)
 run_cmake(user-lang-unknown)
 run_cmake(default-lang-none)
@@ -8,6 +11,14 @@
 run_cmake(save-to-result)
 run_cmake(cmp0069-is-old)
 
+if(_CMAKE_C_IPO_SUPPORTED_BY_CMAKE
+    AND _CMAKE_C_IPO_MAY_BE_SUPPORTED_BY_COMPILER
+    AND NOT RunCMake_GENERATOR MATCHES "^Visual Studio 9 ")
+  run_cmake(CMP0138-WARN)
+  run_cmake(CMP0138-OLD)
+  run_cmake(CMP0138-NEW)
+endif()
+
 if(RunCMake_GENERATOR MATCHES "^Visual Studio 9 ")
   run_cmake(not-supported-by-generator)
 endif()