Explorar o código

Fix export of STATIC library PRIVATE non-target dependencies

In commit v3.5.0-rc1~43^2 (Fix export of STATIC library PRIVATE
dependencies with CMP0022 NEW, 2016-01-15) we taught
target_link_libraries to generate `$<LINK_ONLY:$<TARGET_NAME:dep>>` in
INTERFACE_LINK_LIBRARIES instead of `$<LINK_ONLY:dep>` so that `dep` can
be recognized as a target name and updated during export.  However, this
approach does not work when `dep` is just a plain library name and not a
target because `$<TARGET_NAME:...>` requires the name of a reachable
target.

Since we do not know during target_link_libraries whether the name will
correspond to a reachable target or not, we cannot inject the
`$<TARGET_NAME:...>` expression.  Revert this change and solve the
original problem instead by teaching the export logic to recognize and
update target names directly in `$<LINK_ONLY:...>` expressions.

Reported-by: Ben Boeckel <[email protected]>
Brad King %!s(int64=9) %!d(string=hai) anos
pai
achega
87f44b7525

+ 21 - 0
Source/cmExportFileGenerator.cxx

@@ -772,6 +772,27 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
     lastPos = endPos;
     }
 
+  pos = 0;
+  lastPos = pos;
+  while (errorString.empty() &&
+         (pos = input.find("$<LINK_ONLY:", lastPos)) != input.npos)
+    {
+    std::string::size_type nameStartPos = pos + sizeof("$<LINK_ONLY:") - 1;
+    std::string::size_type endPos = input.find(">", nameStartPos);
+    if (endPos == input.npos)
+      {
+      errorString = "$<LINK_ONLY:...> expression incomplete";
+      break;
+      }
+    std::string libName = input.substr(nameStartPos, endPos - nameStartPos);
+    if (cmGeneratorExpression::IsValidTargetName(libName) &&
+        this->AddTargetNamespace(libName, target, missingTargets))
+      {
+      input.replace(nameStartPos, endPos - nameStartPos, libName);
+      }
+    lastPos = nameStartPos + libName.size() + 1;
+    }
+
   this->ReplaceInstallPrefix(input);
 
   if (!errorString.empty())

+ 2 - 5
Source/cmTargetLinkLibrariesCommand.cxx

@@ -432,11 +432,8 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib,
         {
         std::string configLib = this->Target
                                      ->GetDebugGeneratorExpressions(lib, llt);
-        if (cmGeneratorExpression::IsValidTargetName(configLib))
-          {
-          configLib = "$<LINK_ONLY:$<TARGET_NAME:" + configLib + ">>";
-          }
-        else if (cmGeneratorExpression::Find(configLib) != std::string::npos)
+        if (cmGeneratorExpression::IsValidTargetName(lib)
+            || cmGeneratorExpression::Find(lib) != std::string::npos)
           {
           configLib = "$<LINK_ONLY:" + configLib + ">";
           }

+ 2 - 0
Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake

@@ -8,3 +8,5 @@ run_cmake(MixedSignature)
 run_cmake(Separate-PRIVATE-LINK_PRIVATE-uses)
 run_cmake(SubDirTarget)
 run_cmake(SharedDepNotTarget)
+run_cmake(StaticPrivateDepNotExported)
+run_cmake(StaticPrivateDepNotTarget)

+ 1 - 0
Tests/RunCMake/target_link_libraries/StaticPrivateDepNotExported-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/target_link_libraries/StaticPrivateDepNotExported-stderr.txt

@@ -0,0 +1 @@
+CMake Error: install\(EXPORT "Exp" ...\) includes target "foo" which requires target "not_exported" that is not in the export set.

+ 7 - 0
Tests/RunCMake/target_link_libraries/StaticPrivateDepNotExported.cmake

@@ -0,0 +1,7 @@
+cmake_policy(SET CMP0022 NEW)
+enable_language(C)
+add_library(foo STATIC empty.c)
+add_library(not_exported STATIC empty.c)
+target_link_libraries(foo PRIVATE not_exported)
+install(TARGETS foo EXPORT Exp DESTINATION lib)
+install(EXPORT Exp DESTINATION lib/cmake/Exp)

+ 6 - 0
Tests/RunCMake/target_link_libraries/StaticPrivateDepNotTarget.cmake

@@ -0,0 +1,6 @@
+cmake_policy(SET CMP0022 NEW)
+enable_language(C)
+add_library(foo STATIC empty.c)
+target_link_libraries(foo PRIVATE not_a_target)
+install(TARGETS foo EXPORT Exp DESTINATION lib)
+install(EXPORT Exp DESTINATION lib/cmake/Exp)