Browse Source

Restore support for TARGET_OBJECTS in link interfaces with unity builds

This was broken by commit df08c37a42 (cmGlobalGenerator: Add unity/pch
sources after computing compile features, 2024-02-02, v3.28.3~1^2~1^2),
and 3.28.2's commit 76b5383123 (cmGlobalGenerator: add unity sources
after computing target compile features, 2024-01-01, v3.28.2~17^2~1).

The problem is very similar to that fixed by commit 4e8f24e977 (PCH:
Clear link interface cache when adding PCH object to it, 2022-01-24,
v3.23.0-rc1~44^2~9).  Generalize that fix.

Fixes: #25696
Brad King 1 year ago
parent
commit
5b8e9e068f

+ 4 - 1
Source/cmGeneratorTarget.h

@@ -721,7 +721,10 @@ public:
    */
   void ClearSourcesCache();
 
-  // Do not use.  This is only for a specific call site with a FIXME comment.
+  /**
+   * Clears cached evaluations of INTERFACE_LINK_LIBRARIES.
+   * They will be recomputed on demand.
+   */
   void ClearLinkInterfaceCache();
 
   void AddSource(const std::string& src, bool before = false);

+ 4 - 0
Source/cmGlobalGenerator.cxx

@@ -1897,9 +1897,13 @@ bool cmGlobalGenerator::AddAutomaticSources()
   // Clear the source list and classification cache (KindedSources) of all
   // targets so that it will be recomputed correctly by the generators later
   // now that the above transformations are done for all targets.
+  // Also clear the link interface cache to support $<TARGET_OBJECTS:objlib>
+  // in INTERFACE_LINK_LIBRARIES because the list of object files may have
+  // been changed by conversion to a unity build or addition of a PCH source.
   for (const auto& lg : this->LocalGenerators) {
     for (const auto& gt : lg->GetGeneratorTargets()) {
       gt->ClearSourcesCache();
+      gt->ClearLinkInterfaceCache();
     }
   }
   return true;

+ 0 - 5
Source/cmLocalGenerator.cxx

@@ -2831,15 +2831,10 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
                   cm::nullopt, true);
               } else if (reuseTarget->GetType() ==
                          cmStateEnums::OBJECT_LIBRARY) {
-                // FIXME: This can propagate more than one level, unlike
-                // the rest of the object files in an object library.
-                // Find another way to do this.
                 target->Target->AppendProperty(
                   "INTERFACE_LINK_LIBRARIES",
                   cmStrCat("$<$<CONFIG:", config,
                            ">:$<LINK_ONLY:", pchSourceObj, ">>"));
-                // We updated the link interface, so ensure it is recomputed.
-                target->ClearLinkInterfaceCache();
               }
             }
           } else {

+ 8 - 0
Tests/RunCMake/TargetObjects/RunCMakeTest.cmake

@@ -6,3 +6,11 @@ run_cmake(NotObjlibTarget)
 if(RunCMake_GENERATOR STREQUAL "Xcode" AND "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]")
   run_cmake(XcodeVariableNoGenexExpansion)
 endif()
+
+function(run_cmake_and_build case)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-build)
+  run_cmake(${case})
+  set(RunCMake_TEST_NO_CLEAN 1)
+  run_cmake_command(${case}-build ${CMAKE_COMMAND} --build .)
+endfunction()
+run_cmake_and_build(Unity)

+ 13 - 0
Tests/RunCMake/TargetObjects/Unity.cmake

@@ -0,0 +1,13 @@
+enable_language(C)
+
+# Test transforming the set of object files provided by an object library.
+set(CMAKE_UNITY_BUILD 1)
+
+add_library(UnityObj1 OBJECT UnityObj1.c)
+add_library(UnityObj2 OBJECT UnityObj2.c)
+
+add_library(UnityObj2Iface INTERFACE)
+target_link_libraries(UnityObj2Iface INTERFACE $<TARGET_OBJECTS:UnityObj2>)
+
+add_executable(UnityMain UnityMain.c)
+target_link_libraries(UnityMain PRIVATE UnityObj1 UnityObj2Iface)

+ 7 - 0
Tests/RunCMake/TargetObjects/UnityMain.c

@@ -0,0 +1,7 @@
+extern int UnityObj1(void);
+extern int UnityObj2(void);
+
+int main(void)
+{
+  return UnityObj1() + UnityObj2();
+}

+ 4 - 0
Tests/RunCMake/TargetObjects/UnityObj1.c

@@ -0,0 +1,4 @@
+int UnityObj1(void)
+{
+  return 0;
+}

+ 4 - 0
Tests/RunCMake/TargetObjects/UnityObj2.c

@@ -0,0 +1,4 @@
+int UnityObj2(void)
+{
+  return 0;
+}