mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-06 13:51:33 -06:00
Genex: Add $<LINK_LANGUAGE:...> and $<LINK_LANG_AND_ID:...>
This MR may help to solve issues #19757 and #18008 Fixes: #19965
This commit is contained in:
@@ -103,6 +103,8 @@ const std::string& cmCompiledGeneratorExpression::EvaluateWithContext(
|
||||
if (!context.HadError) {
|
||||
this->HadContextSensitiveCondition = context.HadContextSensitiveCondition;
|
||||
this->HadHeadSensitiveCondition = context.HadHeadSensitiveCondition;
|
||||
this->HadLinkLanguageSensitiveCondition =
|
||||
context.HadLinkLanguageSensitiveCondition;
|
||||
this->SourceSensitiveTargets = context.SourceSensitiveTargets;
|
||||
}
|
||||
|
||||
@@ -119,6 +121,7 @@ cmCompiledGeneratorExpression::cmCompiledGeneratorExpression(
|
||||
, Quiet(false)
|
||||
, HadContextSensitiveCondition(false)
|
||||
, HadHeadSensitiveCondition(false)
|
||||
, HadLinkLanguageSensitiveCondition(false)
|
||||
{
|
||||
cmGeneratorExpressionLexer l;
|
||||
std::vector<cmGeneratorExpressionToken> tokens = l.Tokenize(this->Input);
|
||||
|
||||
@@ -137,6 +137,10 @@ public:
|
||||
{
|
||||
return this->HadHeadSensitiveCondition;
|
||||
}
|
||||
bool GetHadLinkLanguageSensitiveCondition() const
|
||||
{
|
||||
return this->HadLinkLanguageSensitiveCondition;
|
||||
}
|
||||
std::set<cmGeneratorTarget const*> GetSourceSensitiveTargets() const
|
||||
{
|
||||
return this->SourceSensitiveTargets;
|
||||
@@ -178,6 +182,7 @@ private:
|
||||
mutable std::string Output;
|
||||
mutable bool HadContextSensitiveCondition;
|
||||
mutable bool HadHeadSensitiveCondition;
|
||||
mutable bool HadLinkLanguageSensitiveCondition;
|
||||
mutable std::set<cmGeneratorTarget const*> SourceSensitiveTargets;
|
||||
};
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ cmGeneratorExpressionContext::cmGeneratorExpressionContext(
|
||||
, HadError(false)
|
||||
, HadContextSensitiveCondition(false)
|
||||
, HadHeadSensitiveCondition(false)
|
||||
, HadLinkLanguageSensitiveCondition(false)
|
||||
, EvaluateForBuildsystem(evaluateForBuildsystem)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ struct cmGeneratorExpressionContext
|
||||
bool HadError;
|
||||
bool HadContextSensitiveCondition;
|
||||
bool HadHeadSensitiveCondition;
|
||||
bool HadLinkLanguageSensitiveCondition;
|
||||
bool EvaluateForBuildsystem;
|
||||
};
|
||||
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
#include <cm/string_view>
|
||||
|
||||
#include "cm_static_string_view.hxx"
|
||||
|
||||
#include "cmGeneratorExpressionContext.h"
|
||||
#include "cmGeneratorExpressionEvaluator.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
@@ -170,6 +174,21 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingPICExpression()
|
||||
return top->Property == "INTERFACE_POSITION_INDEPENDENT_CODE";
|
||||
}
|
||||
|
||||
bool cmGeneratorExpressionDAGChecker::EvaluatingLinkExpression()
|
||||
{
|
||||
const cmGeneratorExpressionDAGChecker* top = this;
|
||||
const cmGeneratorExpressionDAGChecker* parent = this->Parent;
|
||||
while (parent) {
|
||||
top = parent;
|
||||
parent = parent->Parent;
|
||||
}
|
||||
|
||||
cm::string_view property(top->Property);
|
||||
|
||||
return property == "LINK_DIRECTORIES"_s || property == "LINK_OPTIONS"_s ||
|
||||
property == "LINK_DEPENDS"_s;
|
||||
}
|
||||
|
||||
bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(
|
||||
cmGeneratorTarget const* tgt)
|
||||
{
|
||||
@@ -180,18 +199,17 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(
|
||||
parent = parent->Parent;
|
||||
}
|
||||
|
||||
const char* prop = top->Property.c_str();
|
||||
cm::string_view prop(top->Property);
|
||||
|
||||
if (tgt) {
|
||||
return top->Target == tgt && strcmp(prop, "LINK_LIBRARIES") == 0;
|
||||
return top->Target == tgt && prop == "LINK_LIBRARIES"_s;
|
||||
}
|
||||
|
||||
return (strcmp(prop, "LINK_LIBRARIES") == 0 ||
|
||||
strcmp(prop, "LINK_INTERFACE_LIBRARIES") == 0 ||
|
||||
strcmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES") == 0 ||
|
||||
cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES_") ||
|
||||
cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_")) ||
|
||||
strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0;
|
||||
return prop == "LINK_LIBRARIES"_s || prop == "LINK_INTERFACE_LIBRARIES"_s ||
|
||||
prop == "IMPORTED_LINK_INTERFACE_LIBRARIES"_s ||
|
||||
cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES_") ||
|
||||
cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_") ||
|
||||
prop == "INTERFACE_LINK_LIBRARIES"_s;
|
||||
}
|
||||
|
||||
cmGeneratorTarget const* cmGeneratorExpressionDAGChecker::TopTarget() const
|
||||
|
||||
@@ -68,6 +68,7 @@ struct cmGeneratorExpressionDAGChecker
|
||||
|
||||
bool EvaluatingGenexExpression();
|
||||
bool EvaluatingPICExpression();
|
||||
bool EvaluatingLinkExpression();
|
||||
bool EvaluatingLinkLibraries(cmGeneratorTarget const* tgt = nullptr);
|
||||
|
||||
#define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) bool METHOD() const;
|
||||
|
||||
@@ -62,6 +62,9 @@ std::string cmGeneratorExpressionNode::EvaluateDependentExpression(
|
||||
if (cge->GetHadHeadSensitiveCondition()) {
|
||||
context->HadHeadSensitiveCondition = true;
|
||||
}
|
||||
if (cge->GetHadLinkLanguageSensitiveCondition()) {
|
||||
context->HadLinkLanguageSensitiveCondition = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1039,6 +1042,150 @@ static const struct CompileLanguageAndIdNode : public cmGeneratorExpressionNode
|
||||
}
|
||||
} languageAndIdNode;
|
||||
|
||||
static const struct LinkLanguageNode : public cmGeneratorExpressionNode
|
||||
{
|
||||
LinkLanguageNode() {} // NOLINT(modernize-use-equals-default)
|
||||
|
||||
int NumExpectedParameters() const override { return ZeroOrMoreParameters; }
|
||||
|
||||
std::string Evaluate(
|
||||
const std::vector<std::string>& parameters,
|
||||
cmGeneratorExpressionContext* context,
|
||||
const GeneratorExpressionContent* content,
|
||||
cmGeneratorExpressionDAGChecker* dagChecker) const override
|
||||
{
|
||||
if (!context->HeadTarget || !dagChecker ||
|
||||
!(dagChecker->EvaluatingLinkExpression() ||
|
||||
dagChecker->EvaluatingLinkLibraries())) {
|
||||
reportError(context, content->GetOriginalExpression(),
|
||||
"$<LINK_LANGUAGE:...> may only be used with binary targets "
|
||||
"to specify link libraries, link directories, link options "
|
||||
"and link depends.");
|
||||
return std::string();
|
||||
}
|
||||
if (dagChecker->EvaluatingLinkLibraries() && parameters.empty()) {
|
||||
reportError(
|
||||
context, content->GetOriginalExpression(),
|
||||
"$<LINK_LANGUAGE> is not supported in link libraries expression.");
|
||||
return std::string();
|
||||
}
|
||||
|
||||
cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
|
||||
std::string genName = gg->GetName();
|
||||
if (genName.find("Makefiles") == std::string::npos &&
|
||||
genName.find("Ninja") == std::string::npos &&
|
||||
genName.find("Visual Studio") == std::string::npos &&
|
||||
genName.find("Xcode") == std::string::npos &&
|
||||
genName.find("Watcom WMake") == std::string::npos) {
|
||||
reportError(context, content->GetOriginalExpression(),
|
||||
"$<LINK_LANGUAGE:...> not supported for this generator.");
|
||||
return std::string();
|
||||
}
|
||||
|
||||
if (dagChecker->EvaluatingLinkLibraries()) {
|
||||
context->HadHeadSensitiveCondition = true;
|
||||
context->HadLinkLanguageSensitiveCondition = true;
|
||||
}
|
||||
|
||||
if (parameters.empty()) {
|
||||
return context->Language;
|
||||
}
|
||||
|
||||
for (auto& param : parameters) {
|
||||
if (context->Language == param) {
|
||||
return "1";
|
||||
}
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
} linkLanguageNode;
|
||||
|
||||
namespace {
|
||||
struct LinkerId
|
||||
{
|
||||
static std::string Evaluate(const std::vector<std::string>& parameters,
|
||||
cmGeneratorExpressionContext* context,
|
||||
const GeneratorExpressionContent* content,
|
||||
const std::string& lang)
|
||||
{
|
||||
std::string const& linkerId =
|
||||
context->LG->GetMakefile()->GetSafeDefinition("CMAKE_" + lang +
|
||||
"_COMPILER_ID");
|
||||
if (parameters.empty()) {
|
||||
return linkerId;
|
||||
}
|
||||
if (linkerId.empty()) {
|
||||
return parameters.front().empty() ? "1" : "0";
|
||||
}
|
||||
static cmsys::RegularExpression linkerIdValidator("^[A-Za-z0-9_]*$");
|
||||
|
||||
for (auto& param : parameters) {
|
||||
if (!linkerIdValidator.find(param)) {
|
||||
reportError(context, content->GetOriginalExpression(),
|
||||
"Expression syntax not recognized.");
|
||||
return std::string();
|
||||
}
|
||||
|
||||
if (param == linkerId) {
|
||||
return "1";
|
||||
}
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static const struct LinkLanguageAndIdNode : public cmGeneratorExpressionNode
|
||||
{
|
||||
LinkLanguageAndIdNode() {} // NOLINT(modernize-use-equals-default)
|
||||
|
||||
int NumExpectedParameters() const override { return TwoOrMoreParameters; }
|
||||
|
||||
std::string Evaluate(
|
||||
const std::vector<std::string>& parameters,
|
||||
cmGeneratorExpressionContext* context,
|
||||
const GeneratorExpressionContent* content,
|
||||
cmGeneratorExpressionDAGChecker* dagChecker) const override
|
||||
{
|
||||
if (!context->HeadTarget || !dagChecker ||
|
||||
!(dagChecker->EvaluatingLinkExpression() ||
|
||||
dagChecker->EvaluatingLinkLibraries())) {
|
||||
reportError(
|
||||
context, content->GetOriginalExpression(),
|
||||
"$<LINK_LANG_AND_ID:lang,id> may only be used with binary targets "
|
||||
"to specify link libraries, link directories, link options, and link "
|
||||
"depends.");
|
||||
return std::string();
|
||||
}
|
||||
|
||||
cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
|
||||
std::string genName = gg->GetName();
|
||||
if (genName.find("Makefiles") == std::string::npos &&
|
||||
genName.find("Ninja") == std::string::npos &&
|
||||
genName.find("Visual Studio") == std::string::npos &&
|
||||
genName.find("Xcode") == std::string::npos &&
|
||||
genName.find("Watcom WMake") == std::string::npos) {
|
||||
reportError(
|
||||
context, content->GetOriginalExpression(),
|
||||
"$<LINK_LANG_AND_ID:lang,id> not supported for this generator.");
|
||||
return std::string();
|
||||
}
|
||||
|
||||
if (dagChecker->EvaluatingLinkLibraries()) {
|
||||
context->HadHeadSensitiveCondition = true;
|
||||
context->HadLinkLanguageSensitiveCondition = true;
|
||||
}
|
||||
|
||||
const std::string& lang = context->Language;
|
||||
if (lang == parameters.front()) {
|
||||
std::vector<std::string> idParameter((parameters.cbegin() + 1),
|
||||
parameters.cend());
|
||||
return LinkerId::Evaluate(idParameter, context, content, lang);
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
} linkLanguageAndIdNode;
|
||||
|
||||
std::string getLinkedTargetsContent(
|
||||
cmGeneratorTarget const* target, std::string const& prop,
|
||||
cmGeneratorExpressionContext* context,
|
||||
@@ -2314,6 +2461,8 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
|
||||
{ "LINK_ONLY", &linkOnlyNode },
|
||||
{ "COMPILE_LANG_AND_ID", &languageAndIdNode },
|
||||
{ "COMPILE_LANGUAGE", &languageNode },
|
||||
{ "LINK_LANG_AND_ID", &linkLanguageAndIdNode },
|
||||
{ "LINK_LANGUAGE", &linkLanguageNode },
|
||||
{ "SHELL_PATH", &shellPathNode }
|
||||
};
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <cm/memory>
|
||||
#include <cm/string_view>
|
||||
#include <cmext/algorithm>
|
||||
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
|
||||
@@ -307,6 +308,13 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
|
||||
this->SourceEntries, true);
|
||||
|
||||
this->PolicyMap = t->GetPolicyMap();
|
||||
|
||||
// Get hard-coded linker language
|
||||
if (this->Target->GetProperty("HAS_CXX")) {
|
||||
this->LinkerLanguage = "CXX";
|
||||
} else {
|
||||
this->LinkerLanguage = this->Target->GetSafeProperty("LINKER_LANGUAGE");
|
||||
}
|
||||
}
|
||||
|
||||
cmGeneratorTarget::~cmGeneratorTarget() = default;
|
||||
@@ -2222,11 +2230,12 @@ public:
|
||||
cmTargetCollectLinkLanguages(cmGeneratorTarget const* target,
|
||||
std::string config,
|
||||
std::unordered_set<std::string>& languages,
|
||||
cmGeneratorTarget const* head)
|
||||
cmGeneratorTarget const* head, bool secondPass)
|
||||
: Config(std::move(config))
|
||||
, Languages(languages)
|
||||
, HeadTarget(head)
|
||||
, Target(target)
|
||||
, SecondPass(secondPass)
|
||||
{
|
||||
this->Visited.insert(target);
|
||||
}
|
||||
@@ -2268,11 +2277,14 @@ public:
|
||||
if (!this->Visited.insert(item.Target).second) {
|
||||
return;
|
||||
}
|
||||
cmLinkInterface const* iface =
|
||||
item.Target->GetLinkInterface(this->Config, this->HeadTarget);
|
||||
cmLinkInterface const* iface = item.Target->GetLinkInterface(
|
||||
this->Config, this->HeadTarget, this->SecondPass);
|
||||
if (!iface) {
|
||||
return;
|
||||
}
|
||||
if (iface->HadLinkLanguageSensitiveCondition) {
|
||||
this->HadLinkLanguageSensitiveCondition = true;
|
||||
}
|
||||
|
||||
for (std::string const& language : iface->Languages) {
|
||||
this->Languages.insert(language);
|
||||
@@ -2283,12 +2295,19 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool GetHadLinkLanguageSensitiveCondition()
|
||||
{
|
||||
return HadLinkLanguageSensitiveCondition;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string Config;
|
||||
std::unordered_set<std::string>& Languages;
|
||||
cmGeneratorTarget const* HeadTarget;
|
||||
const cmGeneratorTarget* Target;
|
||||
std::set<cmGeneratorTarget const*> Visited;
|
||||
bool SecondPass;
|
||||
bool HadLinkLanguageSensitiveCondition = false;
|
||||
};
|
||||
|
||||
cmGeneratorTarget::LinkClosure const* cmGeneratorTarget::GetLinkClosure(
|
||||
@@ -2319,7 +2338,7 @@ public:
|
||||
{
|
||||
this->GG = this->Target->GetLocalGenerator()->GetGlobalGenerator();
|
||||
}
|
||||
void Consider(const char* lang)
|
||||
void Consider(const std::string& lang)
|
||||
{
|
||||
int preference = this->GG->GetLinkerPreference(lang);
|
||||
if (preference > this->Preference) {
|
||||
@@ -2352,40 +2371,36 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
|
||||
LinkClosure& lc) const
|
||||
bool cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
|
||||
LinkClosure& lc,
|
||||
bool secondPass) const
|
||||
{
|
||||
// Get languages built in this target.
|
||||
std::unordered_set<std::string> languages;
|
||||
cmLinkImplementation const* impl = this->GetLinkImplementation(config);
|
||||
cmLinkImplementation const* impl =
|
||||
this->GetLinkImplementation(config, secondPass);
|
||||
assert(impl);
|
||||
for (std::string const& li : impl->Languages) {
|
||||
languages.insert(li);
|
||||
}
|
||||
languages.insert(impl->Languages.cbegin(), impl->Languages.cend());
|
||||
|
||||
// Add interface languages from linked targets.
|
||||
cmTargetCollectLinkLanguages cll(this, config, languages, this);
|
||||
// cmTargetCollectLinkLanguages cll(this, config, languages, this,
|
||||
// secondPass);
|
||||
cmTargetCollectLinkLanguages cll(this, config, languages, this, secondPass);
|
||||
for (cmLinkImplItem const& lib : impl->Libraries) {
|
||||
cll.Visit(lib);
|
||||
}
|
||||
|
||||
// Store the transitive closure of languages.
|
||||
for (std::string const& lang : languages) {
|
||||
lc.Languages.push_back(lang);
|
||||
}
|
||||
cm::append(lc.Languages, languages);
|
||||
|
||||
// Choose the language whose linker should be used.
|
||||
if (this->GetProperty("HAS_CXX")) {
|
||||
lc.LinkerLanguage = "CXX";
|
||||
} else if (const char* linkerLang = this->GetProperty("LINKER_LANGUAGE")) {
|
||||
lc.LinkerLanguage = linkerLang;
|
||||
} else {
|
||||
if (secondPass || lc.LinkerLanguage.empty()) {
|
||||
// Find the language with the highest preference value.
|
||||
cmTargetSelectLinker tsl(this);
|
||||
|
||||
// First select from the languages compiled directly in this target.
|
||||
for (std::string const& l : impl->Languages) {
|
||||
tsl.Consider(l.c_str());
|
||||
tsl.Consider(l);
|
||||
}
|
||||
|
||||
// Now consider languages that propagate from linked targets.
|
||||
@@ -2393,12 +2408,50 @@ void cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
|
||||
std::string propagates =
|
||||
"CMAKE_" + lang + "_LINKER_PREFERENCE_PROPAGATES";
|
||||
if (this->Makefile->IsOn(propagates)) {
|
||||
tsl.Consider(lang.c_str());
|
||||
tsl.Consider(lang);
|
||||
}
|
||||
}
|
||||
|
||||
lc.LinkerLanguage = tsl.Choose();
|
||||
}
|
||||
|
||||
return impl->HadLinkLanguageSensitiveCondition ||
|
||||
cll.GetHadLinkLanguageSensitiveCondition();
|
||||
}
|
||||
|
||||
void cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
|
||||
LinkClosure& lc) const
|
||||
{
|
||||
bool secondPass = false;
|
||||
|
||||
{
|
||||
LinkClosure linkClosure;
|
||||
linkClosure.LinkerLanguage = this->LinkerLanguage;
|
||||
|
||||
// Get languages built in this target.
|
||||
secondPass = this->ComputeLinkClosure(config, linkClosure, false);
|
||||
this->LinkerLanguage = linkClosure.LinkerLanguage;
|
||||
if (!secondPass) {
|
||||
lc = std::move(linkClosure);
|
||||
}
|
||||
}
|
||||
|
||||
if (secondPass) {
|
||||
LinkClosure linkClosure;
|
||||
|
||||
this->ComputeLinkClosure(config, linkClosure, secondPass);
|
||||
lc = std::move(linkClosure);
|
||||
|
||||
// linker language must not be changed between the two passes
|
||||
if (this->LinkerLanguage != lc.LinkerLanguage) {
|
||||
std::ostringstream e;
|
||||
e << "Evaluation of $<LINK_LANGUAGE:...> or $<LINK_LAND_AND_ID:...> "
|
||||
"changes\nthe linker language for target \""
|
||||
<< this->GetName() << "\" (from '" << this->LinkerLanguage << "' to '"
|
||||
<< lc.LinkerLanguage << "') which is invalid.";
|
||||
cmSystemTools::Error(e.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cmGeneratorTarget::GetFullNameComponents(
|
||||
@@ -5479,7 +5532,8 @@ void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names,
|
||||
void cmGeneratorTarget::ExpandLinkItems(
|
||||
std::string const& prop, std::string const& value, std::string const& config,
|
||||
cmGeneratorTarget const* headTarget, bool usage_requirements_only,
|
||||
std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition) const
|
||||
std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition,
|
||||
bool& hadLinkLanguageSensitiveCondition) const
|
||||
{
|
||||
// Keep this logic in sync with ComputeLinkImplementationLibraries.
|
||||
cmGeneratorExpression ge;
|
||||
@@ -5491,19 +5545,28 @@ void cmGeneratorTarget::ExpandLinkItems(
|
||||
}
|
||||
std::vector<std::string> libs;
|
||||
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
|
||||
cmExpandList(
|
||||
cge->Evaluate(this->LocalGenerator, config, headTarget, &dagChecker, this),
|
||||
libs);
|
||||
cmExpandList(cge->Evaluate(this->LocalGenerator, config, headTarget,
|
||||
&dagChecker, this, headTarget->LinkerLanguage),
|
||||
libs);
|
||||
this->LookupLinkItems(libs, cge->GetBacktrace(), items);
|
||||
hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition();
|
||||
hadLinkLanguageSensitiveCondition =
|
||||
cge->GetHadLinkLanguageSensitiveCondition();
|
||||
}
|
||||
|
||||
cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
|
||||
const std::string& config, cmGeneratorTarget const* head) const
|
||||
{
|
||||
return this->GetLinkInterface(config, head, false);
|
||||
}
|
||||
|
||||
cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
|
||||
const std::string& config, cmGeneratorTarget const* head,
|
||||
bool secondPass) const
|
||||
{
|
||||
// Imported targets have their own link interface.
|
||||
if (this->IsImported()) {
|
||||
return this->GetImportLinkInterface(config, head, false);
|
||||
return this->GetImportLinkInterface(config, head, false, secondPass);
|
||||
}
|
||||
|
||||
// Link interfaces are not supported for executables that do not
|
||||
@@ -5516,6 +5579,10 @@ cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
|
||||
// Lookup any existing link interface for this configuration.
|
||||
cmHeadToLinkInterfaceMap& hm = this->GetHeadToLinkInterfaceMap(config);
|
||||
|
||||
if (secondPass) {
|
||||
hm.erase(head);
|
||||
}
|
||||
|
||||
// If the link interface does not depend on the head target
|
||||
// then return the one we computed first.
|
||||
if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) {
|
||||
@@ -5530,7 +5597,7 @@ cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
|
||||
if (!iface.AllDone) {
|
||||
iface.AllDone = true;
|
||||
if (iface.Exists) {
|
||||
this->ComputeLinkInterface(config, iface, head);
|
||||
this->ComputeLinkInterface(config, iface, head, secondPass);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5540,6 +5607,13 @@ cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
|
||||
void cmGeneratorTarget::ComputeLinkInterface(
|
||||
const std::string& config, cmOptionalLinkInterface& iface,
|
||||
cmGeneratorTarget const* headTarget) const
|
||||
{
|
||||
this->ComputeLinkInterface(config, iface, headTarget, false);
|
||||
}
|
||||
|
||||
void cmGeneratorTarget::ComputeLinkInterface(
|
||||
const std::string& config, cmOptionalLinkInterface& iface,
|
||||
cmGeneratorTarget const* headTarget, bool secondPass) const
|
||||
{
|
||||
if (iface.Explicit) {
|
||||
if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
|
||||
@@ -5552,7 +5626,8 @@ void cmGeneratorTarget::ComputeLinkInterface(
|
||||
emitted.insert(lib);
|
||||
}
|
||||
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
|
||||
cmLinkImplementation const* impl = this->GetLinkImplementation(config);
|
||||
cmLinkImplementation const* impl =
|
||||
this->GetLinkImplementation(config, secondPass);
|
||||
for (cmLinkImplItem const& lib : impl->Libraries) {
|
||||
if (emitted.insert(lib).second) {
|
||||
if (lib.Target) {
|
||||
@@ -5582,7 +5657,7 @@ void cmGeneratorTarget::ComputeLinkInterface(
|
||||
if (this->LinkLanguagePropagatesToDependents()) {
|
||||
// Targets using this archive need its language runtime libraries.
|
||||
if (cmLinkImplementation const* impl =
|
||||
this->GetLinkImplementation(config)) {
|
||||
this->GetLinkImplementation(config, secondPass)) {
|
||||
iface.Languages = impl->Languages;
|
||||
}
|
||||
}
|
||||
@@ -5978,7 +6053,8 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
|
||||
// The interface libraries have been explicitly set.
|
||||
this->ExpandLinkItems(linkIfaceProp, explicitLibraries, config, headTarget,
|
||||
usage_requirements_only, iface.Libraries,
|
||||
iface.HadHeadSensitiveCondition);
|
||||
iface.HadHeadSensitiveCondition,
|
||||
iface.HadLinkLanguageSensitiveCondition);
|
||||
} else if (!cmp0022NEW)
|
||||
// If CMP0022 is NEW then the plain tll signature sets the
|
||||
// INTERFACE_LINK_LIBRARIES, so if we get here then the project
|
||||
@@ -5998,9 +6074,11 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
|
||||
static const std::string newProp = "INTERFACE_LINK_LIBRARIES";
|
||||
if (const char* newExplicitLibraries = this->GetProperty(newProp)) {
|
||||
bool hadHeadSensitiveConditionDummy = false;
|
||||
bool hadLinkLanguageSensitiveConditionDummy = false;
|
||||
this->ExpandLinkItems(newProp, newExplicitLibraries, config,
|
||||
headTarget, usage_requirements_only, ifaceLibs,
|
||||
hadHeadSensitiveConditionDummy);
|
||||
hadHeadSensitiveConditionDummy,
|
||||
hadLinkLanguageSensitiveConditionDummy);
|
||||
}
|
||||
if (ifaceLibs != iface.Libraries) {
|
||||
std::string oldLibraries = cmJoin(impl->Libraries, ";");
|
||||
@@ -6037,7 +6115,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
|
||||
|
||||
const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface(
|
||||
const std::string& config, cmGeneratorTarget const* headTarget,
|
||||
bool usage_requirements_only) const
|
||||
bool usage_requirements_only, bool secondPass) const
|
||||
{
|
||||
cmGeneratorTarget::ImportInfo const* info = this->GetImportInfo(config);
|
||||
if (!info) {
|
||||
@@ -6050,6 +6128,10 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface(
|
||||
? this->GetHeadToLinkInterfaceUsageRequirementsMap(config)
|
||||
: this->GetHeadToLinkInterfaceMap(config));
|
||||
|
||||
if (secondPass) {
|
||||
hm.erase(headTarget);
|
||||
}
|
||||
|
||||
// If the link interface does not depend on the head target
|
||||
// then return the one we computed first.
|
||||
if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) {
|
||||
@@ -6063,7 +6145,8 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface(
|
||||
cmExpandList(info->Languages, iface.Languages);
|
||||
this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config,
|
||||
headTarget, usage_requirements_only, iface.Libraries,
|
||||
iface.HadHeadSensitiveCondition);
|
||||
iface.HadHeadSensitiveCondition,
|
||||
iface.HadLinkLanguageSensitiveCondition);
|
||||
std::vector<std::string> deps = cmExpandedList(info->SharedDeps);
|
||||
this->LookupLinkItems(deps, cmListFileBacktrace(), iface.SharedDeps);
|
||||
}
|
||||
@@ -6267,6 +6350,12 @@ cmGeneratorTarget::GetHeadToLinkInterfaceUsageRequirementsMap(
|
||||
|
||||
const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
|
||||
const std::string& config) const
|
||||
{
|
||||
return this->GetLinkImplementation(config, false);
|
||||
}
|
||||
|
||||
const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
|
||||
const std::string& config, bool secondPass) const
|
||||
{
|
||||
// There is no link implementation for imported targets.
|
||||
if (this->IsImported()) {
|
||||
@@ -6275,6 +6364,9 @@ const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
|
||||
|
||||
std::string CONFIG = cmSystemTools::UpperCase(config);
|
||||
cmOptionalLinkImplementation& impl = this->LinkImplMap[CONFIG][this];
|
||||
if (secondPass) {
|
||||
impl = cmOptionalLinkImplementation();
|
||||
}
|
||||
if (!impl.LibrariesDone) {
|
||||
impl.LibrariesDone = true;
|
||||
this->ComputeLinkImplementationLibraries(config, impl, this);
|
||||
@@ -6572,11 +6664,15 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
|
||||
cmGeneratorExpression ge(*btIt);
|
||||
std::unique_ptr<cmCompiledGeneratorExpression> const cge = ge.Parse(*le);
|
||||
std::string const& evaluated =
|
||||
cge->Evaluate(this->LocalGenerator, config, head, &dagChecker);
|
||||
cge->Evaluate(this->LocalGenerator, config, head, &dagChecker, nullptr,
|
||||
this->LinkerLanguage);
|
||||
cmExpandList(evaluated, llibs);
|
||||
if (cge->GetHadHeadSensitiveCondition()) {
|
||||
impl.HadHeadSensitiveCondition = true;
|
||||
}
|
||||
if (cge->GetHadLinkLanguageSensitiveCondition()) {
|
||||
impl.HadLinkLanguageSensitiveCondition = true;
|
||||
}
|
||||
|
||||
for (std::string const& lib : llibs) {
|
||||
if (this->IsLinkLookupScope(lib, lg)) {
|
||||
|
||||
@@ -357,7 +357,6 @@ public:
|
||||
};
|
||||
|
||||
LinkClosure const* GetLinkClosure(const std::string& config) const;
|
||||
void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const;
|
||||
|
||||
cmLinkImplementation const* GetLinkImplementation(
|
||||
const std::string& config) const;
|
||||
@@ -816,6 +815,7 @@ private:
|
||||
std::string& outPrefix, std::string& outBase,
|
||||
std::string& outSuffix) const;
|
||||
|
||||
mutable std::string LinkerLanguage;
|
||||
using LinkClosureMapType = std::map<std::string, LinkClosure>;
|
||||
mutable LinkClosureMapType LinkClosureMap;
|
||||
|
||||
@@ -850,6 +850,10 @@ private:
|
||||
void CheckPropertyCompatibility(cmComputeLinkInformation& info,
|
||||
const std::string& config) const;
|
||||
|
||||
void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const;
|
||||
bool ComputeLinkClosure(const std::string& config, LinkClosure& lc,
|
||||
bool secondPass) const;
|
||||
|
||||
struct LinkImplClosure : public std::vector<cmGeneratorTarget const*>
|
||||
{
|
||||
bool Done = false;
|
||||
@@ -868,6 +872,17 @@ private:
|
||||
std::string GetLinkInterfaceDependentStringAsBoolProperty(
|
||||
const std::string& p, const std::string& config) const;
|
||||
|
||||
friend class cmTargetCollectLinkLanguages;
|
||||
cmLinkInterface const* GetLinkInterface(const std::string& config,
|
||||
const cmGeneratorTarget* headTarget,
|
||||
bool secondPass) const;
|
||||
void ComputeLinkInterface(const std::string& config,
|
||||
cmOptionalLinkInterface& iface,
|
||||
const cmGeneratorTarget* head,
|
||||
bool secondPass) const;
|
||||
cmLinkImplementation const* GetLinkImplementation(const std::string& config,
|
||||
bool secondPass) const;
|
||||
|
||||
// Cache import information from properties for each configuration.
|
||||
struct ImportInfo
|
||||
{
|
||||
@@ -894,9 +909,10 @@ private:
|
||||
the link dependencies of this target. */
|
||||
std::string CheckCMP0004(std::string const& item) const;
|
||||
|
||||
cmLinkInterface const* GetImportLinkInterface(
|
||||
const std::string& config, const cmGeneratorTarget* head,
|
||||
bool usage_requirements_only) const;
|
||||
cmLinkInterface const* GetImportLinkInterface(const std::string& config,
|
||||
const cmGeneratorTarget* head,
|
||||
bool usage_requirements_only,
|
||||
bool secondPass = false) const;
|
||||
|
||||
using KindedSourcesMapType = std::map<std::string, KindedSources>;
|
||||
mutable KindedSourcesMapType KindedSourcesMap;
|
||||
@@ -940,7 +956,8 @@ private:
|
||||
const cmGeneratorTarget* headTarget,
|
||||
bool usage_requirements_only,
|
||||
std::vector<cmLinkItem>& items,
|
||||
bool& hadHeadSensitiveCondition) const;
|
||||
bool& hadHeadSensitiveCondition,
|
||||
bool& hadLinkLanguageSensitiveCondition) const;
|
||||
void LookupLinkItems(std::vector<std::string> const& names,
|
||||
cmListFileBacktrace const& bt,
|
||||
std::vector<cmLinkItem>& items) const;
|
||||
|
||||
@@ -81,6 +81,9 @@ struct cmLinkInterface : public cmLinkInterfaceLibraries
|
||||
std::vector<cmLinkItem> WrongConfigLibraries;
|
||||
|
||||
bool ImplementationIsInterface = false;
|
||||
|
||||
// Whether the list depends on a link language genex.
|
||||
bool HadLinkLanguageSensitiveCondition = false;
|
||||
};
|
||||
|
||||
struct cmOptionalLinkInterface : public cmLinkInterface
|
||||
@@ -100,6 +103,9 @@ struct cmLinkImplementation : public cmLinkImplementationLibraries
|
||||
{
|
||||
// Languages whose runtime libraries must be linked.
|
||||
std::vector<std::string> Languages;
|
||||
|
||||
// Whether the list depends on a link language genex.
|
||||
bool HadLinkLanguageSensitiveCondition = false;
|
||||
};
|
||||
|
||||
// Cache link implementation computation from each configuration.
|
||||
|
||||
Reference in New Issue
Block a user