summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2022-03-22 09:31:36 -0400
committerBrad King <brad.king@kitware.com>2022-03-22 11:57:48 -0400
commit73337cb383a704664a47fd3fec84c8feaa303995 (patch)
tree99d8447ed9418486e670ccf6b7f69365bda2615c /Source
parentc173b1009a12981c91bf9094c58b9b68a3806737 (diff)
downloadcmake-73337cb383a704664a47fd3fec84c8feaa303995.tar.gz
LINK_LIBRARIES: Evaluate separately for linking and usage requirements
We evaluate `LINK_LIBRARIES` and `INTERFACE_LINK_LIBRARIES` for two purposes: * Constructing the link line. * Collecting usage requirements. We evaluate `INTERFACE_LINK_LIBRARIES` separately for each purpose in order to support the `$<LINK_ONLY:...>` generator expression used to express private link dependencies of a static library. Previously we only evaluated `LINK_LIBRARIES` for linking, and used that result for collecting usage requirements too. Therefore `$<LINK_ONLY:...>` does not work in `LINK_LIBRARIES`. With the introduction of `INTERFACE_LINK_LIBRARIES_DIRECT`, evaluation of `LINK_LIBRARIES` now needs to distinguish these two cases in order to honor link dependencies encountered through `$<LINK_ONLY:...>` without also exposing other usage requirements through private dependencies of a static library. Revise internal infrastructure to distinguish the two cases when evaluating `LINK_LIBRARIES`. Make the information available in code paths for `INTERFACE_LINK_LIBRARIES_DIRECT` and `LINK_ONLY`. Defer actually using the information to later commits. Issue: #22496
Diffstat (limited to 'Source')
-rw-r--r--Source/cmComputeLinkDepends.cxx4
-rw-r--r--Source/cmComputeTargetDepends.cxx4
-rw-r--r--Source/cmExportBuildAndroidMKGenerator.cxx3
-rw-r--r--Source/cmGeneratorExpressionNode.cxx3
-rw-r--r--Source/cmGeneratorTarget.cxx83
-rw-r--r--Source/cmGeneratorTarget.h17
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx5
-rw-r--r--Source/cmLinkItemGraphVisitor.cxx4
-rw-r--r--Source/cmLinkLineDeviceComputer.cxx3
-rw-r--r--Source/cmQtAutoGenInitializer.cxx6
10 files changed, 89 insertions, 43 deletions
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index a4dc01b070..8cbdcaab45 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -677,8 +677,8 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
void cmComputeLinkDepends::AddDirectLinkEntries()
{
// Add direct link dependencies in this configuration.
- cmLinkImplementation const* impl =
- this->Target->GetLinkImplementation(this->Config);
+ cmLinkImplementation const* impl = this->Target->GetLinkImplementation(
+ this->Config, cmGeneratorTarget::LinkInterfaceFor::Link);
this->AddLinkEntries(-1, impl->Libraries);
this->AddLinkObjects(impl->Objects);
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx
index ef89c8b5c6..3ff16a4acb 100644
--- a/Source/cmComputeTargetDepends.cxx
+++ b/Source/cmComputeTargetDepends.cxx
@@ -218,8 +218,8 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
emitted.insert(cmLinkItem(depender, false, cmListFileBacktrace()));
emitted.insert(cmLinkItem(depender, true, cmListFileBacktrace()));
- if (cmLinkImplementation const* impl =
- depender->GetLinkImplementation(it)) {
+ if (cmLinkImplementation const* impl = depender->GetLinkImplementation(
+ it, cmGeneratorTarget::LinkInterfaceFor::Link)) {
for (cmLinkImplItem const& lib : impl->Libraries) {
// Don't emit the same library twice for this target.
if (emitted.insert(lib).second) {
diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx
index bcd8c6447c..14419256b1 100644
--- a/Source/cmExportBuildAndroidMKGenerator.cxx
+++ b/Source/cmExportBuildAndroidMKGenerator.cxx
@@ -168,7 +168,8 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
// Tell the NDK build system if prebuilt static libraries use C++.
if (target->GetType() == cmStateEnums::STATIC_LIBRARY) {
- cmLinkImplementation const* li = target->GetLinkImplementation(config);
+ cmLinkImplementation const* li = target->GetLinkImplementation(
+ config, cmGeneratorTarget::LinkInterfaceFor::Link);
if (cm::contains(li->Languages, "CXX")) {
os << "LOCAL_HAS_CPP := true\n";
}
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index db043ecb63..3d1cfbf4e8 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -1415,7 +1415,8 @@ static std::string getLinkedTargetsContent(
{
std::string result;
if (cmLinkImplementationLibraries const* impl =
- target->GetLinkImplementationLibraries(context->Config)) {
+ target->GetLinkImplementationLibraries(
+ context->Config, cmGeneratorTarget::LinkInterfaceFor::Usage)) {
for (cmLinkImplItem const& lib : impl->Libraries) {
if (lib.Target) {
// Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index ab3ed126b4..17a521ab5e 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -752,6 +752,7 @@ void cmGeneratorTarget::ClearSourcesCache()
this->Objects.clear();
this->VisitedConfigsForObjects.clear();
this->LinkImplMap.clear();
+ this->LinkImplUsageRequirementsOnlyMap.clear();
}
void cmGeneratorTarget::ClearLinkInterfaceCache()
@@ -1302,7 +1303,8 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(
&dagChecker, result, excludeImported, language);
}
- cmLinkImplementation const* impl = this->GetLinkImplementation(config);
+ cmLinkImplementation const* impl =
+ this->GetLinkImplementation(config, LinkInterfaceFor::Usage);
if (impl != nullptr) {
auto runtimeEntries = impl->LanguageRuntimeLibraries.find(language);
if (runtimeEntries != impl->LanguageRuntimeLibraries.end()) {
@@ -1519,7 +1521,8 @@ void AddLangSpecificImplicitIncludeDirectories(
const std::string& config, const std::string& propertyName,
IncludeDirectoryFallBack mode, EvaluatedTargetPropertyEntries& entries)
{
- if (const auto* libraries = target->GetLinkImplementationLibraries(config)) {
+ if (const auto* libraries = target->GetLinkImplementationLibraries(
+ config, LinkInterfaceFor::Usage)) {
cmGeneratorExpressionDAGChecker dag{ target->GetBacktrace(), target,
propertyName, nullptr, nullptr };
@@ -1609,7 +1612,7 @@ void AddInterfaceEntries(
{
if (searchRuntime == IncludeRuntimeInterface::Yes) {
if (cmLinkImplementation const* impl =
- headTarget->GetLinkImplementation(config)) {
+ headTarget->GetLinkImplementation(config, interfaceFor)) {
entries.HadContextSensitiveCondition =
impl->HadContextSensitiveCondition;
@@ -1623,7 +1626,7 @@ void AddInterfaceEntries(
}
} else {
if (cmLinkImplementationLibraries const* impl =
- headTarget->GetLinkImplementationLibraries(config)) {
+ headTarget->GetLinkImplementationLibraries(config, interfaceFor)) {
entries.HadContextSensitiveCondition =
impl->HadContextSensitiveCondition;
addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries,
@@ -1638,7 +1641,8 @@ void AddObjectEntries(cmGeneratorTarget const* headTarget,
EvaluatedTargetPropertyEntries& entries)
{
if (cmLinkImplementationLibraries const* impl =
- headTarget->GetLinkImplementationLibraries(config)) {
+ headTarget->GetLinkImplementationLibraries(config,
+ LinkInterfaceFor::Usage)) {
entries.HadContextSensitiveCondition = impl->HadContextSensitiveCondition;
for (cmLinkImplItem const& lib : impl->Libraries) {
if (lib.Target &&
@@ -2821,7 +2825,7 @@ bool cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
// Get languages built in this target.
std::unordered_set<std::string> languages;
cmLinkImplementation const* impl =
- this->GetLinkImplementation(config, secondPass);
+ this->GetLinkImplementation(config, LinkInterfaceFor::Link, secondPass);
assert(impl);
languages.insert(impl->Languages.cbegin(), impl->Languages.cend());
@@ -3089,7 +3093,7 @@ cmGeneratorTarget::GetLinkImplementationClosure(
std::set<cmGeneratorTarget const*> emitted;
cmLinkImplementationLibraries const* impl =
- this->GetLinkImplementationLibraries(config);
+ this->GetLinkImplementationLibraries(config, LinkInterfaceFor::Usage);
assert(impl);
for (cmLinkImplItem const& lib : impl->Libraries) {
@@ -3831,7 +3835,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories(
if (this->Makefile->IsOn("APPLE")) {
if (cmLinkImplementationLibraries const* impl =
- this->GetLinkImplementationLibraries(config)) {
+ this->GetLinkImplementationLibraries(config,
+ LinkInterfaceFor::Usage)) {
for (cmLinkImplItem const& lib : impl->Libraries) {
std::string libDir = cmSystemTools::CollapseFullPath(
lib.AsStr(), this->Makefile->GetHomeOutputDirectory());
@@ -6845,8 +6850,8 @@ void cmGeneratorTarget::ComputeLinkInterface(
emitted.insert(lib);
}
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
- cmLinkImplementation const* impl =
- this->GetLinkImplementation(config, secondPass);
+ cmLinkImplementation const* impl = this->GetLinkImplementation(
+ config, LinkInterfaceFor::Link, secondPass);
for (cmLinkImplItem const& lib : impl->Libraries) {
if (emitted.insert(lib).second) {
if (lib.Target) {
@@ -6868,15 +6873,16 @@ void cmGeneratorTarget::ComputeLinkInterface(
this->GetPolicyStatusCMP0022() == cmPolicies::OLD) {
// The link implementation is the default link interface.
cmLinkImplementationLibraries const* impl =
- this->GetLinkImplementationLibrariesInternal(config, headTarget);
+ this->GetLinkImplementationLibrariesInternal(config, headTarget,
+ LinkInterfaceFor::Link);
iface.ImplementationIsInterface = true;
iface.WrongConfigLibraries = impl->WrongConfigLibraries;
}
if (this->LinkLanguagePropagatesToDependents()) {
// Targets using this archive need its language runtime libraries.
- if (cmLinkImplementation const* impl =
- this->GetLinkImplementation(config, secondPass)) {
+ if (cmLinkImplementation const* impl = this->GetLinkImplementation(
+ config, LinkInterfaceFor::Link, secondPass)) {
iface.Languages = impl->Languages;
}
}
@@ -7307,7 +7313,8 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
// The link implementation is the default link interface.
if (cmLinkImplementationLibraries const* impl =
- this->GetLinkImplementationLibrariesInternal(config, headTarget)) {
+ this->GetLinkImplementationLibrariesInternal(config, headTarget,
+ interfaceFor)) {
iface.Libraries.insert(iface.Libraries.end(), impl->Libraries.begin(),
impl->Libraries.end());
if (this->GetPolicyStatusCMP0022() == cmPolicies::WARN &&
@@ -7686,27 +7693,30 @@ cmGeneratorTarget::GetHeadToLinkInterfaceUsageRequirementsMap(
}
const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
- const std::string& config) const
+ const std::string& config, LinkInterfaceFor implFor) const
{
- return this->GetLinkImplementation(config, false);
+ return this->GetLinkImplementation(config, implFor, false);
}
const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
- const std::string& config, bool secondPass) const
+ const std::string& config, LinkInterfaceFor implFor, bool secondPass) const
{
// There is no link implementation for targets that cannot compile sources.
if (!this->CanCompileSources()) {
return nullptr;
}
- cmOptionalLinkImplementation& impl =
- this->LinkImplMap[cmSystemTools::UpperCase(config)][this];
+ HeadToLinkImplementationMap& hm =
+ (implFor == LinkInterfaceFor::Usage
+ ? this->GetHeadToLinkImplementationUsageRequirementsMap(config)
+ : this->GetHeadToLinkImplementationMap(config));
+ cmOptionalLinkImplementation& impl = hm[this];
if (secondPass) {
impl = cmOptionalLinkImplementation();
}
if (!impl.LibrariesDone) {
impl.LibrariesDone = true;
- this->ComputeLinkImplementationLibraries(config, impl, this);
+ this->ComputeLinkImplementationLibraries(config, impl, this, implFor);
}
if (!impl.LanguagesDone) {
impl.LanguagesDone = true;
@@ -7716,6 +7726,21 @@ const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
return &impl;
}
+cmGeneratorTarget::HeadToLinkImplementationMap&
+cmGeneratorTarget::GetHeadToLinkImplementationMap(
+ std::string const& config) const
+{
+ return this->LinkImplMap[cmSystemTools::UpperCase(config)];
+}
+
+cmGeneratorTarget::HeadToLinkImplementationMap&
+cmGeneratorTarget::GetHeadToLinkImplementationUsageRequirementsMap(
+ std::string const& config) const
+{
+ return this
+ ->LinkImplUsageRequirementsOnlyMap[cmSystemTools::UpperCase(config)];
+}
+
bool cmGeneratorTarget::GetConfigCommonSourceFilesForXcode(
std::vector<cmSourceFile*>& files) const
{
@@ -7956,7 +7981,7 @@ bool cmGeneratorTarget::HaveBuildTreeRPATH(const std::string& config) const
return true;
}
if (cmLinkImplementationLibraries const* impl =
- this->GetLinkImplementationLibraries(config)) {
+ this->GetLinkImplementationLibraries(config, LinkInterfaceFor::Link)) {
return !impl->Libraries.empty();
}
return false;
@@ -7964,14 +7989,15 @@ bool cmGeneratorTarget::HaveBuildTreeRPATH(const std::string& config) const
cmLinkImplementationLibraries const*
cmGeneratorTarget::GetLinkImplementationLibraries(
- const std::string& config) const
+ const std::string& config, LinkInterfaceFor implFor) const
{
- return this->GetLinkImplementationLibrariesInternal(config, this);
+ return this->GetLinkImplementationLibrariesInternal(config, this, implFor);
}
cmLinkImplementationLibraries const*
cmGeneratorTarget::GetLinkImplementationLibrariesInternal(
- const std::string& config, cmGeneratorTarget const* head) const
+ const std::string& config, cmGeneratorTarget const* head,
+ LinkInterfaceFor implFor) const
{
// There is no link implementation for targets that cannot compile sources.
if (!this->CanCompileSources()) {
@@ -7980,7 +8006,9 @@ cmGeneratorTarget::GetLinkImplementationLibrariesInternal(
// Populate the link implementation libraries for this configuration.
HeadToLinkImplementationMap& hm =
- this->LinkImplMap[cmSystemTools::UpperCase(config)];
+ (implFor == LinkInterfaceFor::Usage
+ ? this->GetHeadToLinkImplementationUsageRequirementsMap(config)
+ : this->GetHeadToLinkImplementationMap(config));
// If the link implementation does not depend on the head target
// then re-use the one from the head we computed first.
@@ -7991,7 +8019,7 @@ cmGeneratorTarget::GetLinkImplementationLibrariesInternal(
cmOptionalLinkImplementation& impl = hm[head];
if (!impl.LibrariesDone) {
impl.LibrariesDone = true;
- this->ComputeLinkImplementationLibraries(config, impl, head);
+ this->ComputeLinkImplementationLibraries(config, impl, head, implFor);
}
return &impl;
}
@@ -8110,8 +8138,9 @@ void ComputeLinkImplTransitive(cmGeneratorTarget const* self,
void cmGeneratorTarget::ComputeLinkImplementationLibraries(
const std::string& config, cmOptionalLinkImplementation& impl,
- cmGeneratorTarget const* head) const
+ cmGeneratorTarget const* head, LinkInterfaceFor implFor) const
{
+ static_cast<void>(implFor);
cmLocalGenerator const* lg = this->LocalGenerator;
cmMakefile const* mf = lg->GetMakefile();
cmBTStringRange entryRange = this->Target->GetLinkImplementationEntries();
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 3e30913641..96e48a4b0a 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -399,17 +399,18 @@ public:
LinkClosure const* GetLinkClosure(const std::string& config) const;
cmLinkImplementation const* GetLinkImplementation(
- const std::string& config) const;
+ const std::string& config, LinkInterfaceFor implFor) const;
void ComputeLinkImplementationLanguages(
const std::string& config, cmOptionalLinkImplementation& impl) const;
cmLinkImplementationLibraries const* GetLinkImplementationLibraries(
- const std::string& config) const;
+ const std::string& config, LinkInterfaceFor implFor) const;
void ComputeLinkImplementationLibraries(const std::string& config,
cmOptionalLinkImplementation& impl,
- const cmGeneratorTarget* head) const;
+ const cmGeneratorTarget* head,
+ LinkInterfaceFor implFor) const;
struct TargetOrString
{
@@ -984,6 +985,7 @@ private:
const cmGeneratorTarget* head,
bool secondPass) const;
cmLinkImplementation const* GetLinkImplementation(const std::string& config,
+ LinkInterfaceFor implFor,
bool secondPass) const;
enum class LinkItemRole
@@ -1108,9 +1110,16 @@ private:
};
using LinkImplMapType = std::map<std::string, HeadToLinkImplementationMap>;
mutable LinkImplMapType LinkImplMap;
+ mutable LinkImplMapType LinkImplUsageRequirementsOnlyMap;
+
+ HeadToLinkImplementationMap& GetHeadToLinkImplementationMap(
+ std::string const& config) const;
+ HeadToLinkImplementationMap& GetHeadToLinkImplementationUsageRequirementsMap(
+ std::string const& config) const;
cmLinkImplementationLibraries const* GetLinkImplementationLibrariesInternal(
- const std::string& config, const cmGeneratorTarget* head) const;
+ const std::string& config, const cmGeneratorTarget* head,
+ LinkInterfaceFor implFor) const;
bool ComputeOutputDir(const std::string& config,
cmStateEnums::ArtifactType artifact,
std::string& out) const;
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 1e6624e5b5..f01b36ce6a 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -1627,7 +1627,10 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt)
// If the language is compiled as a source trust Xcode to link with it.
for (auto const& Language :
- gtgt->GetLinkImplementation("NOCONFIG")->Languages) {
+ gtgt
+ ->GetLinkImplementation("NOCONFIG",
+ cmGeneratorTarget::LinkInterfaceFor::Link)
+ ->Languages) {
if (Language == llang) {
return;
}
diff --git a/Source/cmLinkItemGraphVisitor.cxx b/Source/cmLinkItemGraphVisitor.cxx
index d87d183b6c..0ad846b7ea 100644
--- a/Source/cmLinkItemGraphVisitor.cxx
+++ b/Source/cmLinkItemGraphVisitor.cxx
@@ -98,8 +98,8 @@ void cmLinkItemGraphVisitor::GetDependencies(cmGeneratorTarget const& target,
std::string const& config,
DependencyMap& dependencies)
{
- const auto* implementationLibraries =
- target.GetLinkImplementationLibraries(config);
+ const auto* implementationLibraries = target.GetLinkImplementationLibraries(
+ config, cmGeneratorTarget::LinkInterfaceFor::Link);
if (implementationLibraries != nullptr) {
for (auto const& lib : implementationLibraries->Libraries) {
auto const& name = lib.AsStr();
diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx
index 71f9f80d84..43f1b8e6db 100644
--- a/Source/cmLinkLineDeviceComputer.cxx
+++ b/Source/cmLinkLineDeviceComputer.cxx
@@ -136,7 +136,8 @@ void cmLinkLineDeviceComputer::ComputeLinkLibraries(
linkLib.Value += " ";
const cmLinkImplementation* linkImpl =
- cli.GetTarget()->GetLinkImplementation(cli.GetConfig());
+ cli.GetTarget()->GetLinkImplementation(
+ cli.GetConfig(), cmGeneratorTarget::LinkInterfaceFor::Link);
for (const cmLinkImplItem& iter : linkImpl->Libraries) {
if (iter.Target != nullptr &&
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index a01e6aef68..a47b3c03a7 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -114,7 +114,8 @@ bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin,
}
// Collect all static_library dependencies from the test target
cmLinkImplementationLibraries const* libs =
- testTarget->GetLinkImplementationLibraries(config);
+ testTarget->GetLinkImplementationLibraries(
+ config, cmGeneratorTarget::LinkInterfaceFor::Link);
if (libs) {
for (cmLinkItem const& item : libs->Libraries) {
cmGeneratorTarget const* depTarget = item.Target;
@@ -1266,7 +1267,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
std::map<cmGeneratorTarget const*, std::size_t> commonTargets;
for (std::string const& config : this->ConfigsList) {
cmLinkImplementationLibraries const* libs =
- this->GenTarget->GetLinkImplementationLibraries(config);
+ this->GenTarget->GetLinkImplementationLibraries(
+ config, cmGeneratorTarget::LinkInterfaceFor::Link);
if (libs) {
for (cmLinkItem const& item : libs->Libraries) {
cmGeneratorTarget const* libTarget = item.Target;