summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2019-10-01 17:31:41 (GMT)
committerBrad King <brad.king@kitware.com>2019-10-01 18:34:03 (GMT)
commit4891f0f9662d6e2b355717aa1f7250f3462229bb (patch)
tree6052be050944f9f7ac133a397d5d159e09556361
parent62d65286e71c58c88646f2f851edf7669fd40a41 (diff)
downloadCMake-4891f0f9662d6e2b355717aa1f7250f3462229bb.zip
CMake-4891f0f9662d6e2b355717aa1f7250f3462229bb.tar.gz
CMake-4891f0f9662d6e2b355717aa1f7250f3462229bb.tar.bz2
Ninja: Ensure shared library version symlinks are created for dependents
When linking to a shared library target that has version symlinks, add an order-only dependency on the build statement that creates the links. This ensures that the links exist for use at runtime. Fixes: #19774
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx21
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjLHSShared.c17
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjLHSShared.cmake12
3 files changed, 48 insertions, 2 deletions
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index bd5abd1..38ccaa3 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -13,6 +13,7 @@
#include <cm/memory>
#include "cmAlgorithms.h"
+#include "cmComputeLinkInformation.h"
#include "cmCustomCommand.h" // IWYU pragma: keep
#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
@@ -1049,6 +1050,26 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
// Gather order-only dependencies.
this->GetLocalGenerator()->AppendTargetDepends(gt, linkBuild.OrderOnlyDeps);
+ // Add order-only dependencies on versioning symlinks of shared libs we link.
+ if (!this->GeneratorTarget->IsDLLPlatform()) {
+ if (cmComputeLinkInformation* cli =
+ this->GeneratorTarget->GetLinkInformation(this->GetConfigName())) {
+ for (auto const& item : cli->GetItems()) {
+ if (item.Target &&
+ item.Target->GetType() == cmStateEnums::SHARED_LIBRARY &&
+ !item.Target->IsFrameworkOnApple()) {
+ std::string const& lib = this->ConvertToNinjaPath(
+ item.Target->GetFullPath(this->GetConfigName()));
+ if (std::find(linkBuild.ImplicitDeps.begin(),
+ linkBuild.ImplicitDeps.end(),
+ lib) == linkBuild.ImplicitDeps.end()) {
+ linkBuild.OrderOnlyDeps.emplace_back(lib);
+ }
+ }
+ }
+ }
+ }
+
// Ninja should restat after linking if and only if there are byproducts.
vars["RESTAT"] = byproducts.empty() ? "" : "1";
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjLHSShared.c b/Tests/RunCMake/ObjectLibrary/LinkObjLHSShared.c
new file mode 100644
index 0000000..088da30
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjLHSShared.c
@@ -0,0 +1,17 @@
+#ifndef REQUIRED
+# error "REQUIRED not defined"
+#endif
+
+#if defined(_WIN32)
+# define IMPORT __declspec(dllimport)
+#else
+# define IMPORT
+#endif
+
+IMPORT int a(void);
+extern int required(void);
+
+int main(void)
+{
+ return required() + a();
+}
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjLHSShared.cmake b/Tests/RunCMake/ObjectLibrary/LinkObjLHSShared.cmake
index 4aa7bba..0a76932 100644
--- a/Tests/RunCMake/ObjectLibrary/LinkObjLHSShared.cmake
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjLHSShared.cmake
@@ -1,7 +1,15 @@
project(LinkObjLHSShared C)
+# Create a versioned shared library that does not build as part of "all".
add_library(OtherLib SHARED a.c)
-target_compile_definitions(OtherLib INTERFACE REQUIRED)
+target_compile_definitions(OtherLib INTERFACE REQUIRED PRIVATE COMPILE_FOR_SHARED_LIB)
+set_target_properties(OtherLib PROPERTIES SOVERSION 0 VERSION 0.0.0 EXCLUDE_FROM_ALL ON)
add_library(AnObjLib OBJECT requires.c)
-target_link_libraries(AnObjLib OtherLib)
+target_link_libraries(AnObjLib PUBLIC OtherLib)
+
+add_executable(LinkObjLHSShared LinkObjLHSShared.c)
+target_link_libraries(LinkObjLHSShared AnObjLib)
+
+# Verify that our dependency on OtherLib generated its versioning symlinks.
+add_custom_command(TARGET LinkObjLHSShared POST_BUILD COMMAND LinkObjLHSShared)