Переглянути джерело

Merge topic 'link-shared-depend-cycle-issue-12647' into check_symbol_exists

Rolf Eike Beer 14 роки тому
батько
коміт
6856b4d19d

+ 19 - 3
Source/cmComputeLinkDepends.cxx

@@ -358,7 +358,7 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
       this->AddLinkEntries(depender_index, iface->Libraries);
 
       // Handle dependent shared libraries.
-      this->QueueSharedDependencies(depender_index, iface->SharedDeps);
+      this->FollowSharedDeps(depender_index, iface);
 
       // Support for CMP0003.
       for(std::vector<std::string>::const_iterator
@@ -376,6 +376,23 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
     }
 }
 
+//----------------------------------------------------------------------------
+void
+cmComputeLinkDepends
+::FollowSharedDeps(int depender_index, cmTarget::LinkInterface const* iface,
+                   bool follow_interface)
+{
+  // Follow dependencies if we have not followed them already.
+  if(this->SharedDepFollowed.insert(depender_index).second)
+    {
+    if(follow_interface)
+      {
+      this->QueueSharedDependencies(depender_index, iface->Libraries);
+      }
+    this->QueueSharedDependencies(depender_index, iface->SharedDeps);
+    }
+}
+
 //----------------------------------------------------------------------------
 void
 cmComputeLinkDepends
@@ -430,8 +447,7 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
        entry.Target->GetLinkInterface(this->Config))
       {
       // Follow public and private dependencies transitively.
-      this->QueueSharedDependencies(index, iface->Libraries);
-      this->QueueSharedDependencies(index, iface->SharedDeps);
+      this->FollowSharedDeps(index, iface, true);
       }
     }
 }

+ 4 - 0
Source/cmComputeLinkDepends.h

@@ -105,6 +105,10 @@ private:
     int DependerIndex;
   };
   std::queue<SharedDepEntry> SharedDepQueue;
+  std::set<int> SharedDepFollowed;
+  void FollowSharedDeps(int depender_index,
+                        cmTarget::LinkInterface const* iface,
+                        bool follow_interface = false);
   void QueueSharedDependencies(int depender_index,
                                std::vector<std::string> const& deps);
   void HandleSharedDependency(SharedDepEntry const& dep);

+ 3 - 0
Tests/CMakeOnly/CMakeLists.txt

@@ -8,6 +8,9 @@ macro(add_CMakeOnly_test test)
     )
 endmacro()
 
+add_CMakeOnly_test(LinkInterfaceLoop)
+set_property(TEST CMakeOnly.LinkInterfaceLoop PROPERTY TIMEOUT 90)
+
 add_CMakeOnly_test(CheckSymbolExists)
 
 add_CMakeOnly_test(CheckCXXSymbolExists)

+ 27 - 0
Tests/CMakeOnly/LinkInterfaceLoop/CMakeLists.txt

@@ -0,0 +1,27 @@
+cmake_minimum_required (VERSION 2.8)
+project(LinkInterfaceLoop C)
+
+# Add a shared library that incorrectly names itself as a
+# dependency, thus forming a cycle.
+add_library(A SHARED IMPORTED)
+set_target_properties(A PROPERTIES
+  IMPORTED_LINK_DEPENDENT_LIBRARIES A
+  IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/dirA/A"
+  )
+
+# Add a shared library that incorrectly names itself in
+# its link interface, thus forming a cycle.
+add_library(B SHARED IMPORTED)
+set_target_properties(B PROPERTIES
+  IMPORTED_LINK_INTERFACE_LIBRARIES B
+  IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/dirB/B"
+  )
+
+# Add a shared library with an empty link interface
+# that depends on two shared libraries.
+add_library(C SHARED lib.c)
+set_property(TARGET C PROPERTY LINK_INTERFACE_LIBRARIES "")
+target_link_libraries(C B A)
+
+add_executable(main main.c)
+target_link_libraries(main C)

+ 1 - 0
Tests/CMakeOnly/LinkInterfaceLoop/lib.c

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

+ 1 - 0
Tests/CMakeOnly/LinkInterfaceLoop/main.c

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