Genex: Add generator expressions $<DEVICE_LINK> and $<HOST_LINK>

These generator expressions can only be used in link options properties.
These expressions return the arguments respectively for device and host link
step, otherwise return an empty string.
This commit is contained in:
Marc Chevrier
2020-04-05 17:21:57 +02:00
parent 38332fc4fa
commit 3fdae5acaa
94 changed files with 572 additions and 11 deletions
@@ -163,6 +163,13 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkExpression() const
property == "LINK_DEPENDS"_s;
}
bool cmGeneratorExpressionDAGChecker::EvaluatingLinkOptionsExpression() const
{
cm::string_view property(this->Top()->Property);
return property == "LINK_OPTIONS"_s;
}
bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(
cmGeneratorTarget const* tgt) const
{
+1
View File
@@ -69,6 +69,7 @@ struct cmGeneratorExpressionDAGChecker
bool EvaluatingGenexExpression() const;
bool EvaluatingPICExpression() const;
bool EvaluatingLinkExpression() const;
bool EvaluatingLinkOptionsExpression() const;
bool EvaluatingLinkLibraries(cmGeneratorTarget const* tgt = nullptr) const;
+68
View File
@@ -15,6 +15,7 @@
#include <cm/iterator>
#include <cm/string_view>
#include <cm/vector>
#include <cmext/algorithm>
#include "cmsys/RegularExpression.hxx"
@@ -1187,6 +1188,70 @@ static const struct LinkLanguageAndIdNode : public cmGeneratorExpressionNode
}
} linkLanguageAndIdNode;
static const struct HostLinkNode : public cmGeneratorExpressionNode
{
HostLinkNode() {} // 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->EvaluatingLinkOptionsExpression()) {
reportError(context, content->GetOriginalExpression(),
"$<HOST_LINK:...> may only be used with binary targets "
"to specify link options.");
return std::string();
}
return context->HeadTarget->IsDeviceLink() ? std::string()
: cmJoin(parameters, ";");
}
} hostLinkNode;
static const struct DeviceLinkNode : public cmGeneratorExpressionNode
{
DeviceLinkNode() {} // 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->EvaluatingLinkOptionsExpression()) {
reportError(context, content->GetOriginalExpression(),
"$<DEVICE_LINK:...> may only be used with binary targets "
"to specify link options.");
return std::string();
}
if (context->HeadTarget->IsDeviceLink()) {
std::vector<std::string> list;
cmExpandLists(parameters.begin(), parameters.end(), list);
const auto DL_BEGIN = "<DEVICE_LINK>"_s;
const auto DL_END = "</DEVICE_LINK>"_s;
cm::erase_if(list, [&](const std::string& item) {
return item == DL_BEGIN || item == DL_END;
});
list.insert(list.begin(), static_cast<std::string>(DL_BEGIN));
list.push_back(static_cast<std::string>(DL_END));
return cmJoin(list, ";");
}
return std::string();
}
} deviceLinkNode;
std::string getLinkedTargetsContent(
cmGeneratorTarget const* target, std::string const& prop,
cmGeneratorExpressionContext* context,
@@ -1304,6 +1369,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
context, content->GetOriginalExpression(),
"$<TARGET_PROPERTY:prop> may only be used with binary targets. "
"It may not be used with add_custom_command or add_custom_target. "
" "
"Specify the target to read a property from using the "
"$<TARGET_PROPERTY:tgt,prop> signature instead.");
return std::string();
@@ -2464,6 +2530,8 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
{ "COMPILE_LANGUAGE", &languageNode },
{ "LINK_LANG_AND_ID", &linkLanguageAndIdNode },
{ "LINK_LANGUAGE", &linkLanguageNode },
{ "HOST_LINK", &hostLinkNode },
{ "DEVICE_LINK", &deviceLinkNode },
{ "SHELL_PATH", &shellPathNode }
};
+14 -10
View File
@@ -5532,6 +5532,13 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
return propContent;
}
bool cmGeneratorTarget::SetDeviceLink(bool deviceLink)
{
bool previous = this->DeviceLink;
this->DeviceLink = deviceLink;
return previous;
}
bool cmGeneratorTarget::GetLinkInterfaceDependentBoolProperty(
const std::string& p, const std::string& config) const
{
@@ -5955,7 +5962,6 @@ const cmLinkInterfaceLibraries* cmGeneratorTarget::GetLinkInterfaceLibraries(
}
// Lookup any existing link interface for this configuration.
std::string CONFIG = cmSystemTools::UpperCase(config);
cmHeadToLinkInterfaceMap& hm =
(usage_requirements_only
? this->GetHeadToLinkInterfaceUsageRequirementsMap(config)
@@ -6377,7 +6383,6 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface(
return nullptr;
}
std::string CONFIG = cmSystemTools::UpperCase(config);
cmHeadToLinkInterfaceMap& hm =
(usage_requirements_only
? this->GetHeadToLinkInterfaceUsageRequirementsMap(config)
@@ -6591,16 +6596,15 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
cmHeadToLinkInterfaceMap& cmGeneratorTarget::GetHeadToLinkInterfaceMap(
const std::string& config) const
{
std::string CONFIG = cmSystemTools::UpperCase(config);
return this->LinkInterfaceMap[CONFIG];
return this->LinkInterfaceMap[cmSystemTools::UpperCase(config)];
}
cmHeadToLinkInterfaceMap&
cmGeneratorTarget::GetHeadToLinkInterfaceUsageRequirementsMap(
const std::string& config) const
{
std::string CONFIG = cmSystemTools::UpperCase(config);
return this->LinkInterfaceUsageRequirementsOnlyMap[CONFIG];
return this
->LinkInterfaceUsageRequirementsOnlyMap[cmSystemTools::UpperCase(config)];
}
const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
@@ -6617,8 +6621,8 @@ const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
return nullptr;
}
std::string CONFIG = cmSystemTools::UpperCase(config);
cmOptionalLinkImplementation& impl = this->LinkImplMap[CONFIG][this];
cmOptionalLinkImplementation& impl =
this->LinkImplMap[cmSystemTools::UpperCase(config)][this];
if (secondPass) {
impl = cmOptionalLinkImplementation();
}
@@ -6877,8 +6881,8 @@ cmGeneratorTarget::GetLinkImplementationLibrariesInternal(
}
// Populate the link implementation libraries for this configuration.
std::string CONFIG = cmSystemTools::UpperCase(config);
HeadToLinkImplementationMap& hm = this->LinkImplMap[CONFIG];
HeadToLinkImplementationMap& hm =
this->LinkImplMap[cmSystemTools::UpperCase(config)];
// If the link implementation does not depend on the head target
// then return the one we computed first.
+19
View File
@@ -204,6 +204,24 @@ public:
const char* GetLinkInterfaceDependentNumberMaxProperty(
const std::string& p, const std::string& config) const;
class DeviceLinkSetter
{
public:
DeviceLinkSetter(cmGeneratorTarget& target)
: Target(target)
{
this->PreviousState = target.SetDeviceLink(true);
}
~DeviceLinkSetter() { this->Target.SetDeviceLink(this->PreviousState); };
private:
cmGeneratorTarget& Target;
bool PreviousState;
};
bool SetDeviceLink(bool deviceLink);
bool IsDeviceLink() const { return this->DeviceLink; }
cmLinkInterface const* GetLinkInterface(
const std::string& config, const cmGeneratorTarget* headTarget) const;
void ComputeLinkInterface(const std::string& config,
@@ -829,6 +847,7 @@ private:
mutable std::string LinkerLanguage;
using LinkClosureMapType = std::map<std::string, LinkClosure>;
mutable LinkClosureMapType LinkClosureMap;
bool DeviceLink = false;
// Returns ARCHIVE, LIBRARY, or RUNTIME based on platform and type.
const char* GetOutputTargetType(cmStateEnums::ArtifactType artifact) const;
+1 -1
View File
@@ -87,7 +87,7 @@ void cmExpandLists(InputIt first, InputIt last,
std::vector<std::string>& argsOut)
{
for (; first != last; ++first) {
ExpandList(*first, argsOut);
cmExpandList(*first, argsOut);
}
}