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
This commit is contained in:
Brad King
2019-10-01 13:31:41 -04:00
parent 62d65286e7
commit 4891f0f966
3 changed files with 48 additions and 2 deletions

View File

@@ -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";

View File

@@ -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();
}

View File

@@ -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)