Merge topic 'tll-includes-defines'
e48d842
Cache context-independent includes on evaluation.089fe1c
Optimize genex evaluation for includes and defines.179f495
find_package: Reword <package>_NO_INTERFACES documentatione7b579b
Test workaround of bad interface include directories from depends.77cecb7
Add includes and compile definitions with target_link_libraries.0b92602
Add the $<LINKED:...> generator expression.0fa7f69
Add API to check if we're reading a includes or defines property.2c3654c
Add a way to exclude INTERFACE properties from exported targets.d4297d5
Export targets to a targets file, not a Config file.df4d2b2
Make it an error for INSTALL_PREFIX to be evaluated.7ceeba9
Advance more when preprocessing exported strings.30268b4
Handle reading empty properties defined by the link interface.
This commit is contained in:
commit
ec85306025
|
@ -51,6 +51,14 @@
|
|||
"on the target tgt.\n" \
|
||||
"Note that tgt is not added as a dependency of the target this " \
|
||||
"expression is evaluated on.\n" \
|
||||
" $<LINKED:item> = An empty string if item is not a " \
|
||||
"target. If item is a target then the " \
|
||||
"INTERFACE_INCLUDE_DIRECTORIES or INTERFACE_COMPILE_DEFINITIONS " \
|
||||
"content is read from the target. " \
|
||||
"This generator expression can only be used in evaluation of the " \
|
||||
"INCLUDE_DIRECTORIES or COMPILE_DEFINITIONS property. Note that " \
|
||||
"this expression is for internal use and may be changed or removed " \
|
||||
"in the future.\n" \
|
||||
" $<TARGET_POLICY:pol> = '1' if the policy was NEW when " \
|
||||
"the 'head' target was created, else '0'. If the policy was not " \
|
||||
"set, the warning message for the policy will be emitted. This " \
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include <cmsys/auto_ptr.hxx>
|
||||
|
||||
#include "assert.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmExportFileGenerator::cmExportFileGenerator()
|
||||
{
|
||||
|
@ -160,7 +162,7 @@ void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
|
|||
preprocessRule);
|
||||
if (!prepro.empty())
|
||||
{
|
||||
this->ResolveTargetsInGeneratorExpressions(prepro, target,
|
||||
this->ResolveTargetsInGeneratorExpressions(prepro, target, propName,
|
||||
missingTargets);
|
||||
properties[outputName] = prepro;
|
||||
}
|
||||
|
@ -264,15 +266,16 @@ void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target,
|
|||
{
|
||||
if (!properties.empty())
|
||||
{
|
||||
os << "if(NOT ${CMAKE_FIND_PACKAGE_NAME}_NO_INTERFACES)\n";
|
||||
std::string targetName = this->Namespace;
|
||||
targetName += target->GetName();
|
||||
os << "set_target_properties(" << targetName << " PROPERTIES\n";
|
||||
os << " set_target_properties(" << targetName << " PROPERTIES\n";
|
||||
for(ImportPropertyMap::const_iterator pi = properties.begin();
|
||||
pi != properties.end(); ++pi)
|
||||
{
|
||||
os << " " << pi->first << " \"" << pi->second << "\"\n";
|
||||
os << " " << pi->first << " \"" << pi->second << "\"\n";
|
||||
}
|
||||
os << ")\n\n";
|
||||
os << " )\nendif()\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -323,13 +326,14 @@ static bool isGeneratorExpression(const std::string &lib)
|
|||
void
|
||||
cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
|
||||
std::string &input,
|
||||
cmTarget* target,
|
||||
cmTarget* target, const char *propName,
|
||||
std::vector<std::string> &missingTargets,
|
||||
FreeTargetsReplace replace)
|
||||
{
|
||||
if (replace == NoReplaceFreeTargets)
|
||||
{
|
||||
this->ResolveTargetsInGeneratorExpression(input, target, missingTargets);
|
||||
this->ResolveTargetsInGeneratorExpression(input, target, propName,
|
||||
missingTargets);
|
||||
return;
|
||||
}
|
||||
std::vector<std::string> parts;
|
||||
|
@ -348,7 +352,7 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
|
|||
{
|
||||
this->ResolveTargetsInGeneratorExpression(
|
||||
*li,
|
||||
target,
|
||||
target, propName,
|
||||
missingTargets);
|
||||
}
|
||||
input += sep + *li;
|
||||
|
@ -360,7 +364,7 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
|
|||
void
|
||||
cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
|
||||
std::string &input,
|
||||
cmTarget* target,
|
||||
cmTarget* target, const char *propName,
|
||||
std::vector<std::string> &missingTargets)
|
||||
{
|
||||
std::string::size_type pos = 0;
|
||||
|
@ -391,10 +395,61 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
|
|||
{
|
||||
input.replace(nameStartPos, commaPos - nameStartPos, targetName);
|
||||
}
|
||||
lastPos = pos + targetName.size();
|
||||
lastPos = nameStartPos + targetName.size() + 1;
|
||||
}
|
||||
|
||||
std::string errorString;
|
||||
pos = 0;
|
||||
lastPos = pos;
|
||||
while((pos = input.find("$<LINKED:", lastPos)) != input.npos)
|
||||
{
|
||||
std::string::size_type nameStartPos = pos + sizeof("$<LINKED:") - 1;
|
||||
std::string::size_type endPos = input.find(">", nameStartPos);
|
||||
if (endPos == input.npos)
|
||||
{
|
||||
errorString = "$<LINKED:...> expression incomplete";
|
||||
break;
|
||||
}
|
||||
std::string targetName = input.substr(nameStartPos,
|
||||
endPos - nameStartPos);
|
||||
if(targetName.find("$<") != input.npos)
|
||||
{
|
||||
errorString = "$<LINKED:...> requires its parameter to be a "
|
||||
"literal.";
|
||||
break;
|
||||
}
|
||||
if (this->AddTargetNamespace(targetName, target, missingTargets))
|
||||
{
|
||||
assert(propName); // The link libraries strings will
|
||||
// never contain $<LINKED>
|
||||
std::string replacement = "$<TARGET_PROPERTY:"
|
||||
+ targetName + "," + propName;
|
||||
input.replace(pos, endPos - pos, replacement);
|
||||
lastPos = pos + replacement.size() + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pos != 0)
|
||||
{
|
||||
if (input[pos - 1] == ';')
|
||||
{
|
||||
--pos;
|
||||
}
|
||||
}
|
||||
else if (input[endPos + 1] == ';')
|
||||
{
|
||||
++endPos;
|
||||
}
|
||||
input.replace(pos, endPos - pos + 1, "");
|
||||
lastPos = pos;
|
||||
}
|
||||
}
|
||||
if (!errorString.empty())
|
||||
{
|
||||
mf->IssueMessage(cmake::FATAL_ERROR, errorString);
|
||||
return;
|
||||
}
|
||||
|
||||
pos = 0;
|
||||
lastPos = pos;
|
||||
while((pos = input.find("$<TARGET_NAME:", lastPos)) != input.npos)
|
||||
|
@ -490,7 +545,7 @@ cmExportFileGenerator
|
|||
preprocessRule);
|
||||
if (!prepro.empty())
|
||||
{
|
||||
this->ResolveTargetsInGeneratorExpressions(prepro, target,
|
||||
this->ResolveTargetsInGeneratorExpressions(prepro, target, 0,
|
||||
missingTargets,
|
||||
ReplaceFreeTargets);
|
||||
properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = prepro;
|
||||
|
|
|
@ -119,7 +119,7 @@ protected:
|
|||
};
|
||||
|
||||
void ResolveTargetsInGeneratorExpressions(std::string &input,
|
||||
cmTarget* target,
|
||||
cmTarget* target, const char *propName,
|
||||
std::vector<std::string> &missingTargets,
|
||||
FreeTargetsReplace replace = NoReplaceFreeTargets);
|
||||
|
||||
|
@ -150,7 +150,7 @@ private:
|
|||
std::vector<std::string> &missingTargets);
|
||||
|
||||
void ResolveTargetsInGeneratorExpression(std::string &input,
|
||||
cmTarget* target,
|
||||
cmTarget* target, const char *propName,
|
||||
std::vector<std::string> &missingTargets);
|
||||
|
||||
virtual void ReplaceInstallPrefix(std::string &input);
|
||||
|
|
|
@ -376,6 +376,26 @@ void cmFindPackageCommand::GenerateDocumentation()
|
|||
"The package configuration file may set <package>_FOUND to false "
|
||||
"to tell find_package that component requirements are not satisfied."
|
||||
"\n"
|
||||
"A package configuration file may include() a <package>Targets.cmake "
|
||||
"file, created by install(EXPORT) in the upstream source, to import "
|
||||
"targets into the downstream consumer. "
|
||||
"When a new version of the upstream adds INTERFACE properties not "
|
||||
"present in a previous version it can change behavior for existing "
|
||||
"downstreams. "
|
||||
"In order to remain source compatible the upstream package configuration "
|
||||
"file may set <package>_NO_INTERFACES to disable INTERFACE properties. "
|
||||
"For example, code of the form:\n"
|
||||
" if(<package>_FIND_VERSION VERSION_LESS <new-version>\n"
|
||||
" AND NOT <package>_INTERFACES)\n"
|
||||
" set(<package>_NO_INTERFACES 1)\n"
|
||||
" endif()\n"
|
||||
" include(\"${CMAKE_CURRENT_LIST_DIR}/<package>Targets.cmake\")\n"
|
||||
"tells <package>Targets.cmake not to provide the INTERFACE properties "
|
||||
"unless the downstream requests at least <new-version> or sets "
|
||||
"<package>_INTERFACES to explicitly request them. "
|
||||
"This allows consumers to decide when to enable the new interfaces when "
|
||||
"upgrading."
|
||||
"\n"
|
||||
"See the cmake_policy() command documentation for discussion of the "
|
||||
"NO_POLICY_SCOPE option."
|
||||
;
|
||||
|
|
|
@ -88,6 +88,7 @@ const char *cmCompiledGeneratorExpression::Evaluate(
|
|||
context.Config = config;
|
||||
context.Quiet = quiet;
|
||||
context.HadError = false;
|
||||
context.HadContextSensitiveCondition = false;
|
||||
context.HeadTarget = headTarget;
|
||||
context.CurrentTarget = currentTarget ? currentTarget : headTarget;
|
||||
context.Backtrace = this->Backtrace;
|
||||
|
@ -109,6 +110,10 @@ const char *cmCompiledGeneratorExpression::Evaluate(
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (!context.HadError)
|
||||
{
|
||||
this->HadContextSensitiveCondition = context.HadContextSensitiveCondition;
|
||||
}
|
||||
|
||||
this->Targets = context.Targets;
|
||||
// TODO: Return a std::string from here instead?
|
||||
|
@ -118,7 +123,8 @@ const char *cmCompiledGeneratorExpression::Evaluate(
|
|||
cmCompiledGeneratorExpression::cmCompiledGeneratorExpression(
|
||||
cmListFileBacktrace const& backtrace,
|
||||
const char *input)
|
||||
: Backtrace(backtrace), Input(input ? input : "")
|
||||
: Backtrace(backtrace), Input(input ? input : ""),
|
||||
HadContextSensitiveCondition(false)
|
||||
{
|
||||
cmGeneratorExpressionLexer l;
|
||||
std::vector<cmGeneratorExpressionToken> tokens =
|
||||
|
|
|
@ -100,6 +100,10 @@ public:
|
|||
{
|
||||
return this->Backtrace;
|
||||
}
|
||||
bool GetHadContextSensitiveCondition() const
|
||||
{
|
||||
return this->HadContextSensitiveCondition;
|
||||
}
|
||||
|
||||
private:
|
||||
cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace,
|
||||
|
@ -118,6 +122,7 @@ private:
|
|||
mutable std::set<cmTarget*> Targets;
|
||||
mutable std::map<cmStdString, cmStdString> SeenTargetProperties;
|
||||
mutable std::string Output;
|
||||
mutable bool HadContextSensitiveCondition;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,7 +24,33 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
|
|||
: Parent(parent), Target(target), Property(property),
|
||||
Content(content), Backtrace(backtrace)
|
||||
{
|
||||
const cmGeneratorExpressionDAGChecker *top = this;
|
||||
const cmGeneratorExpressionDAGChecker *p = this->Parent;
|
||||
while (p)
|
||||
{
|
||||
top = p;
|
||||
p = p->Parent;
|
||||
}
|
||||
this->CheckResult = this->checkGraph();
|
||||
|
||||
if (CheckResult == DAG && (top->Property == "INCLUDE_DIRECTORIES"
|
||||
|| top->Property == "COMPILE_DEFINITIONS") )
|
||||
{
|
||||
std::map<cmStdString, std::set<cmStdString> >::const_iterator it
|
||||
= top->Seen.find(target);
|
||||
if (it != top->Seen.end())
|
||||
{
|
||||
const std::set<cmStdString> &propSet = it->second;
|
||||
const std::set<cmStdString>::const_iterator i = propSet.find(property);
|
||||
if (i != propSet.end())
|
||||
{
|
||||
this->CheckResult = ALREADY_SEEN;
|
||||
return;
|
||||
}
|
||||
}
|
||||
const_cast<cmGeneratorExpressionDAGChecker *>(top)
|
||||
->Seen[target].insert(property);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -125,3 +151,19 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries()
|
|||
|| strncmp(prop, "LINK_INTERFACE_LIBRARIES_", 26) == 0
|
||||
|| strncmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_", 35) == 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmGeneratorExpressionDAGChecker::EvaluatingIncludeDirectories()
|
||||
{
|
||||
const char *prop = this->Property.c_str();
|
||||
return (strcmp(prop, "INCLUDE_DIRECTORIES") == 0
|
||||
|| strcmp(prop, "INTERFACE_INCLUDE_DIRECTORIES") == 0 );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmGeneratorExpressionDAGChecker::EvaluatingCompileDefinitions()
|
||||
{
|
||||
const char *prop = this->Property.c_str();
|
||||
return (strcmp(prop, "COMPILE_DEFINITIONS") == 0
|
||||
|| strcmp(prop, "INTERFACE_COMPILE_DEFINITIONS") == 0 );
|
||||
}
|
||||
|
|
|
@ -28,7 +28,8 @@ struct cmGeneratorExpressionDAGChecker
|
|||
enum Result {
|
||||
DAG,
|
||||
SELF_REFERENCE,
|
||||
CYCLIC_REFERENCE
|
||||
CYCLIC_REFERENCE,
|
||||
ALREADY_SEEN
|
||||
};
|
||||
|
||||
Result check() const;
|
||||
|
@ -37,6 +38,8 @@ struct cmGeneratorExpressionDAGChecker
|
|||
const std::string &expr);
|
||||
|
||||
bool EvaluatingLinkLibraries();
|
||||
bool EvaluatingIncludeDirectories();
|
||||
bool EvaluatingCompileDefinitions();
|
||||
|
||||
private:
|
||||
Result checkGraph() const;
|
||||
|
@ -45,6 +48,7 @@ private:
|
|||
const cmGeneratorExpressionDAGChecker * const Parent;
|
||||
const std::string Target;
|
||||
const std::string Property;
|
||||
std::map<cmStdString, std::set<cmStdString> > Seen;
|
||||
const GeneratorExpressionContent * const Content;
|
||||
const cmListFileBacktrace Backtrace;
|
||||
Result CheckResult;
|
||||
|
|
|
@ -238,6 +238,7 @@ static const struct ConfigurationNode : public cmGeneratorExpressionNode
|
|||
const GeneratorExpressionContent *,
|
||||
cmGeneratorExpressionDAGChecker *) const
|
||||
{
|
||||
context->HadContextSensitiveCondition = true;
|
||||
return context->Config ? context->Config : "";
|
||||
}
|
||||
} configurationNode;
|
||||
|
@ -262,6 +263,7 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
|
|||
"Expression syntax not recognized.");
|
||||
return std::string();
|
||||
}
|
||||
context->HadContextSensitiveCondition = true;
|
||||
if (!context->Config)
|
||||
{
|
||||
return parameters.front().empty() ? "1" : "0";
|
||||
|
@ -435,6 +437,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
|||
case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
|
||||
// No error. We just skip cyclic references.
|
||||
return std::string();
|
||||
case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
|
||||
// No error. We're not going to find anything new here.
|
||||
return std::string();
|
||||
case cmGeneratorExpressionDAGChecker::DAG:
|
||||
break;
|
||||
}
|
||||
|
@ -452,12 +457,14 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
|||
}
|
||||
if (propertyName == "POSITION_INDEPENDENT_CODE")
|
||||
{
|
||||
context->HadContextSensitiveCondition = true;
|
||||
return target->GetLinkInterfaceDependentBoolProperty(
|
||||
"POSITION_INDEPENDENT_CODE", context->Config) ? "1" : "0";
|
||||
}
|
||||
if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
|
||||
context->Config))
|
||||
{
|
||||
context->HadContextSensitiveCondition = true;
|
||||
return target->GetLinkInterfaceDependentBoolProperty(
|
||||
propertyName,
|
||||
context->Config) ? "1" : "0";
|
||||
|
@ -465,9 +472,12 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
|||
if (target->IsLinkInterfaceDependentStringProperty(propertyName,
|
||||
context->Config))
|
||||
{
|
||||
return target->GetLinkInterfaceDependentStringProperty(
|
||||
context->HadContextSensitiveCondition = true;
|
||||
const char *propContent =
|
||||
target->GetLinkInterfaceDependentStringProperty(
|
||||
propertyName,
|
||||
context->Config);
|
||||
return propContent ? propContent : "";
|
||||
}
|
||||
|
||||
return std::string();
|
||||
|
@ -481,12 +491,19 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
|||
if (targetPropertyTransitiveWhitelist[i] == propertyName)
|
||||
{
|
||||
cmGeneratorExpression ge(context->Backtrace);
|
||||
return ge.Parse(prop)->Evaluate(context->Makefile,
|
||||
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
|
||||
std::string result = cge->Evaluate(context->Makefile,
|
||||
context->Config,
|
||||
context->Quiet,
|
||||
context->HeadTarget,
|
||||
target,
|
||||
&dagChecker);
|
||||
|
||||
if (cge->GetHadContextSensitiveCondition())
|
||||
{
|
||||
context->HadContextSensitiveCondition = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return prop;
|
||||
|
@ -580,6 +597,9 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode
|
|||
"be used with add_custom_command.");
|
||||
return std::string();
|
||||
}
|
||||
|
||||
context->HadContextSensitiveCondition = true;
|
||||
|
||||
for (size_t i = 0;
|
||||
i < (sizeof(targetPolicyWhitelist) /
|
||||
sizeof(*targetPolicyWhitelist));
|
||||
|
@ -619,19 +639,114 @@ static const struct InstallPrefixNode : public cmGeneratorExpressionNode
|
|||
{
|
||||
InstallPrefixNode() {}
|
||||
|
||||
virtual bool GeneratesContent() const { return false; }
|
||||
virtual bool GeneratesContent() const { return true; }
|
||||
virtual int NumExpectedParameters() const { return 0; }
|
||||
|
||||
std::string Evaluate(const std::vector<std::string> &,
|
||||
cmGeneratorExpressionContext *,
|
||||
const GeneratorExpressionContent *,
|
||||
cmGeneratorExpressionContext *context,
|
||||
const GeneratorExpressionContent *content,
|
||||
cmGeneratorExpressionDAGChecker *) const
|
||||
{
|
||||
reportError(context, content->GetOriginalExpression(),
|
||||
"INSTALL_PREFIX is a marker for install(EXPORT) only. It "
|
||||
"should never be evaluated.");
|
||||
return std::string();
|
||||
}
|
||||
|
||||
} installPrefixNode;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static const struct LinkedNode : public cmGeneratorExpressionNode
|
||||
{
|
||||
LinkedNode() {}
|
||||
|
||||
virtual bool GeneratesContent() const { return true; }
|
||||
virtual int NumExpectedParameters() const { return 1; }
|
||||
virtual bool RequiresLiteralInput() const { return true; }
|
||||
|
||||
std::string Evaluate(const std::vector<std::string> ¶meters,
|
||||
cmGeneratorExpressionContext *context,
|
||||
const GeneratorExpressionContent *content,
|
||||
cmGeneratorExpressionDAGChecker *dagChecker) const
|
||||
{
|
||||
if (dagChecker->EvaluatingIncludeDirectories())
|
||||
{
|
||||
return this->GetInterfaceProperty(parameters.front(),
|
||||
"INCLUDE_DIRECTORIES",
|
||||
context, content, dagChecker);
|
||||
}
|
||||
if (dagChecker->EvaluatingCompileDefinitions())
|
||||
{
|
||||
return this->GetInterfaceProperty(parameters.front(),
|
||||
"COMPILE_DEFINITIONS",
|
||||
context, content, dagChecker);
|
||||
}
|
||||
|
||||
reportError(context, content->GetOriginalExpression(),
|
||||
"$<LINKED:...> may only be used in INCLUDE_DIRECTORIES and "
|
||||
"COMPILE_DEFINITIONS properties.");
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string GetInterfaceProperty(const std::string &item,
|
||||
const std::string &prop,
|
||||
cmGeneratorExpressionContext *context,
|
||||
const GeneratorExpressionContent *content,
|
||||
cmGeneratorExpressionDAGChecker *dagCheckerParent) const
|
||||
{
|
||||
cmTarget *target = context->CurrentTarget
|
||||
->GetMakefile()->FindTargetToUse(item.c_str());
|
||||
if (!target)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
std::string propertyName = "INTERFACE_" + prop;
|
||||
const char *propContent = target->GetProperty(propertyName.c_str());
|
||||
if (!propContent)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
|
||||
target->GetName(),
|
||||
propertyName,
|
||||
content,
|
||||
dagCheckerParent);
|
||||
|
||||
switch (dagChecker.check())
|
||||
{
|
||||
case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
|
||||
dagChecker.reportError(context, content->GetOriginalExpression());
|
||||
return std::string();
|
||||
case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
|
||||
// No error. We just skip cyclic references.
|
||||
return std::string();
|
||||
case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
|
||||
// No error. We're not going to find anything new here.
|
||||
return std::string();
|
||||
case cmGeneratorExpressionDAGChecker::DAG:
|
||||
break;
|
||||
}
|
||||
|
||||
cmGeneratorExpression ge(context->Backtrace);
|
||||
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(propContent);
|
||||
std::string result = cge->Evaluate(context->Makefile,
|
||||
context->Config,
|
||||
context->Quiet,
|
||||
context->HeadTarget,
|
||||
target,
|
||||
&dagChecker);
|
||||
if (cge->GetHadContextSensitiveCondition())
|
||||
{
|
||||
context->HadContextSensitiveCondition = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} linkedNode;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<bool linker, bool soname>
|
||||
struct TargetFilesystemArtifactResultCreator
|
||||
|
@ -869,6 +984,8 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
|
|||
return &targetDefinedNode;
|
||||
else if (identifier == "INSTALL_PREFIX")
|
||||
return &installPrefixNode;
|
||||
else if (identifier == "LINKED")
|
||||
return &linkedNode;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ struct cmGeneratorExpressionContext
|
|||
// directly or indirectly in the property.
|
||||
bool Quiet;
|
||||
bool HadError;
|
||||
bool HadContextSensitiveCondition;
|
||||
};
|
||||
|
||||
struct cmGeneratorExpressionDAGChecker;
|
||||
|
|
|
@ -134,6 +134,7 @@ public:
|
|||
: ge(cge)
|
||||
{}
|
||||
const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge;
|
||||
std::vector<std::string> CachedIncludes;
|
||||
};
|
||||
std::vector<IncludeDirectoriesEntry*> IncludeDirectoriesEntries;
|
||||
};
|
||||
|
@ -2778,22 +2779,36 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
|
|||
end = this->Internal->IncludeDirectoriesEntries.end();
|
||||
it != end; ++it)
|
||||
{
|
||||
std::vector<std::string> entryIncludes;
|
||||
cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(this->Makefile,
|
||||
config,
|
||||
false,
|
||||
this,
|
||||
&dagChecker),
|
||||
entryIncludes);
|
||||
|
||||
bool testIsOff = true;
|
||||
bool cacheIncludes = false;
|
||||
std::vector<std::string> entryIncludes = (*it)->CachedIncludes;
|
||||
if(!entryIncludes.empty())
|
||||
{
|
||||
testIsOff = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(this->Makefile,
|
||||
config,
|
||||
false,
|
||||
this,
|
||||
&dagChecker),
|
||||
entryIncludes);
|
||||
if (!(*it)->ge->GetHadContextSensitiveCondition())
|
||||
{
|
||||
cacheIncludes = true;
|
||||
}
|
||||
}
|
||||
std::string usedIncludes;
|
||||
for(std::vector<std::string>::const_iterator
|
||||
for(std::vector<std::string>::iterator
|
||||
li = entryIncludes.begin(); li != entryIncludes.end(); ++li)
|
||||
{
|
||||
std::string inc = *li;
|
||||
if (!cmSystemTools::IsOff(inc.c_str()))
|
||||
if (testIsOff && !cmSystemTools::IsOff(li->c_str()))
|
||||
{
|
||||
cmSystemTools::ConvertToUnixSlashes(inc);
|
||||
cmSystemTools::ConvertToUnixSlashes(*li);
|
||||
}
|
||||
std::string inc = *li;
|
||||
|
||||
if(uniqueIncludes.insert(inc).second)
|
||||
{
|
||||
|
@ -2804,6 +2819,10 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (cacheIncludes)
|
||||
{
|
||||
(*it)->CachedIncludes = entryIncludes;
|
||||
}
|
||||
if (!usedIncludes.empty())
|
||||
{
|
||||
this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG,
|
||||
|
|
|
@ -514,6 +514,9 @@ public:
|
|||
|
||||
const char *GetLinkInterfaceDependentStringProperty(const std::string &p,
|
||||
const char *config);
|
||||
|
||||
std::string GetDebugGeneratorExpressions(const std::string &value,
|
||||
cmTarget::LinkLibraryType llt);
|
||||
private:
|
||||
/**
|
||||
* A list of direct dependencies. Use in conjunction with DependencyMap.
|
||||
|
@ -659,9 +662,6 @@ private:
|
|||
|
||||
void ProcessSourceExpression(std::string const& expr);
|
||||
|
||||
std::string GetDebugGeneratorExpressions(const std::string &value,
|
||||
cmTarget::LinkLibraryType llt);
|
||||
|
||||
// The cmMakefile instance that owns this target. This should
|
||||
// always be set.
|
||||
cmMakefile* Makefile;
|
||||
|
|
|
@ -249,11 +249,52 @@ cmTargetLinkLibrariesCommand
|
|||
this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static std::string compileProperty(cmTarget *tgt, const std::string &lib,
|
||||
bool isGenex,
|
||||
const std::string &property,
|
||||
cmTarget::LinkLibraryType llt)
|
||||
{
|
||||
std::string value = !isGenex ? "$<LINKED:" + lib + ">"
|
||||
: "$<$<TARGET_DEFINED:" + lib + ">:" +
|
||||
"$<TARGET_PROPERTY:" + lib +
|
||||
",INTERFACE_" + property + ">"
|
||||
">";
|
||||
|
||||
return tgt->GetDebugGeneratorExpressions(value, llt);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool isGeneratorExpression(const std::string &lib)
|
||||
{
|
||||
const std::string::size_type openpos = lib.find("$<");
|
||||
return (openpos != std::string::npos)
|
||||
&& (lib.find(">", openpos) != std::string::npos);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
|
||||
cmTarget::LinkLibraryType llt)
|
||||
{
|
||||
const bool isGenex = isGeneratorExpression(lib);
|
||||
|
||||
cmsys::RegularExpression targetNameValidator;
|
||||
targetNameValidator.compile("^[A-Za-z0-9_.:-]+$");
|
||||
const bool potentialTargetName = targetNameValidator.find(lib);
|
||||
|
||||
if (potentialTargetName || isGenex)
|
||||
{
|
||||
this->Target->AppendProperty("INCLUDE_DIRECTORIES",
|
||||
compileProperty(this->Target, lib,
|
||||
isGenex,
|
||||
"INCLUDE_DIRECTORIES", llt).c_str());
|
||||
this->Target->AppendProperty("COMPILE_DEFINITIONS",
|
||||
compileProperty(this->Target, lib,
|
||||
isGenex,
|
||||
"COMPILE_DEFINITIONS", llt).c_str());
|
||||
}
|
||||
|
||||
// Handle normal case first.
|
||||
if(this->CurrentProcessingState != ProcessingLinkInterface)
|
||||
{
|
||||
|
@ -266,6 +307,18 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
|
|||
}
|
||||
}
|
||||
|
||||
if (potentialTargetName || isGenex)
|
||||
{
|
||||
this->Target->AppendProperty("INTERFACE_COMPILE_DEFINITIONS",
|
||||
compileProperty(this->Target, lib,
|
||||
isGenex,
|
||||
"COMPILE_DEFINITIONS", llt).c_str());
|
||||
this->Target->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
|
||||
compileProperty(this->Target, lib,
|
||||
isGenex,
|
||||
"INCLUDE_DIRECTORIES", llt).c_str());
|
||||
}
|
||||
|
||||
// Get the list of configurations considered to be DEBUG.
|
||||
std::vector<std::string> const& debugConfigs =
|
||||
this->Makefile->GetCMakeInstance()->GetDebugConfigs();
|
||||
|
|
|
@ -97,6 +97,15 @@ public:
|
|||
"Calls to other signatures of this command may set the property "
|
||||
"making any libraries linked exclusively by this signature private."
|
||||
"\n"
|
||||
"Target usage requirements are also consumed by this command. If the "
|
||||
"<target> is linked to another target which has "
|
||||
"a populated INTERFACE_INCLUDE_DIRECTORIES, the content of it is "
|
||||
"appended to the INCLUDE_DIRECTORIES of <target>. Similarly, the "
|
||||
"INTERFACE_COMPILE_DEFINITONS of a dependee are added to the "
|
||||
"COMPILE_DEFINITONS of <target>, and the "
|
||||
"INTERFACE_POSITION_INDEPENDENT_CODE property is used to determine the "
|
||||
"POSITION_INDEPENDENT_CODE property of <target>."
|
||||
"\n"
|
||||
" target_link_libraries(<target> LINK_INTERFACE_LIBRARIES\n"
|
||||
" [[debug|optimized|general] <lib>] ...)\n"
|
||||
"The LINK_INTERFACE_LIBRARIES mode appends the libraries "
|
||||
|
|
|
@ -16,9 +16,15 @@ add_executable(consumer
|
|||
"${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp"
|
||||
)
|
||||
|
||||
add_library(linked UNKNOWN IMPORTED)
|
||||
set_property(TARGET linked PROPERTY
|
||||
INTERFACE_COMPILE_DEFINITIONS "MY_LINKED_DEFINE")
|
||||
|
||||
|
||||
target_compile_definitions(consumer
|
||||
PRIVATE $<TARGET_PROPERTY:target_compile_definitions,INTERFACE_COMPILE_DEFINITIONS>
|
||||
$<$<TARGET_DEFINED:notdefined>:SHOULD_NOT_BE_DEFINED>
|
||||
$<$<TARGET_DEFINED:target_compile_definitions>:SHOULD_BE_DEFINED>
|
||||
$<LINKED:linked>
|
||||
-DDASH_D_DEFINE
|
||||
)
|
||||
|
|
|
@ -23,4 +23,8 @@
|
|||
#error Expected DASH_D_DEFINE
|
||||
#endif
|
||||
|
||||
#ifndef MY_LINKED_DEFINE
|
||||
#error Expected MY_LINKED_DEFINE
|
||||
#endif
|
||||
|
||||
int main() { return 0; }
|
||||
|
|
|
@ -17,6 +17,9 @@ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/poison/common.h" "#error Should not be i
|
|||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/cure")
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cure/common.h" "#define CURE_DEFINE\n")
|
||||
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/linkedinclude")
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/linkedinclude/linkedinclude.h" "#define LINKEDINCLUDE_DEFINE\n")
|
||||
|
||||
add_executable(target_include_directories
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/main.cpp"
|
||||
)
|
||||
|
@ -42,7 +45,13 @@ add_executable(consumer
|
|||
"${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp"
|
||||
)
|
||||
|
||||
add_library(linked UNKNOWN IMPORTED)
|
||||
set_property(TARGET linked PROPERTY
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/linkedinclude")
|
||||
|
||||
target_include_directories(consumer
|
||||
PRIVATE $<TARGET_PROPERTY:target_include_directories,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
PRIVATE
|
||||
$<TARGET_PROPERTY:target_include_directories,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<LINKED:linked>
|
||||
relative_dir
|
||||
)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "publicinclude.h"
|
||||
#include "interfaceinclude.h"
|
||||
#include "relative_dir.h"
|
||||
#include "linkedinclude.h"
|
||||
|
||||
#ifdef PRIVATEINCLUDE_DEFINE
|
||||
#error Unexpected PRIVATEINCLUDE_DEFINE
|
||||
|
@ -24,4 +25,8 @@
|
|||
#error Expected RELATIVE_DIR_DEFINE
|
||||
#endif
|
||||
|
||||
#ifndef LINKEDINCLUDE_DEFINE
|
||||
#error Expected LINKEDINCLUDE_DEFINE
|
||||
#endif
|
||||
|
||||
int main() { return 0; }
|
||||
|
|
|
@ -62,10 +62,6 @@ assert_property(targetA LINK_INTERFACE_LIBRARIES "")
|
|||
|
||||
add_subdirectory(subdir)
|
||||
target_link_libraries(targetA subdirlib)
|
||||
set_property(TARGET targetA APPEND PROPERTY
|
||||
INCLUDE_DIRECTORIES
|
||||
$<TARGET_PROPERTY:subdirlib,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
)
|
||||
|
||||
target_link_libraries(targetA depB depC)
|
||||
|
||||
|
@ -87,3 +83,24 @@ set_property(TARGET depD APPEND PROPERTY
|
|||
|
||||
add_executable(targetB targetB.cpp)
|
||||
target_link_libraries(targetB depD)
|
||||
|
||||
macro(create_header _name)
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${_name}")
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_name}/${_name}.h" "//${_name}.h\n")
|
||||
endmacro()
|
||||
|
||||
create_header(foo)
|
||||
create_header(bar)
|
||||
|
||||
add_library(depG SHARED depG.cpp)
|
||||
generate_export_header(depG)
|
||||
target_include_directories(depG INTERFACE
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/foo"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/bar"
|
||||
)
|
||||
target_compile_definitions(depG INTERFACE
|
||||
TEST_DEF
|
||||
)
|
||||
|
||||
add_executable(targetC targetC.cpp)
|
||||
target_link_libraries(targetC depG)
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
#include "depG.h"
|
||||
|
||||
int DepG::foo()
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
#include "depg_export.h"
|
||||
|
||||
struct DEPG_EXPORT DepG
|
||||
{
|
||||
int foo();
|
||||
};
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
#include "depG.h"
|
||||
|
||||
#include "foo.h"
|
||||
#include "bar.h"
|
||||
|
||||
#ifndef TEST_DEF
|
||||
#error Expected TEST_DEF definition
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
DepG g;
|
||||
|
||||
return g.foo();
|
||||
}
|
|
@ -48,10 +48,22 @@ target_compile_definitions(CompatibleInterface
|
|||
add_library(iface2 SHARED iface2.cpp)
|
||||
generate_export_header(iface2)
|
||||
|
||||
set_property(TARGET iface2 APPEND PROPERTY
|
||||
COMPATIBLE_INTERFACE_STRING
|
||||
Iface2_PROP
|
||||
)
|
||||
|
||||
# For the LINK_LIBRARIES and related properties, we should not evaluate
|
||||
# properties defined only in the interface - they should be implicitly zero
|
||||
set_property(TARGET iface2
|
||||
APPEND PROPERTY
|
||||
LINK_INTERFACE_LIBRARIES $<$<BOOL:$<TARGET_PROPERTY:BOOL_PROP4>>:nonexistant>
|
||||
)
|
||||
target_link_libraries(CompatibleInterface iface2)
|
||||
target_link_libraries(CompatibleInterface iface2
|
||||
$<$<BOOL:$<TARGET_PROPERTY:Iface2_PROP>>:nonexistant>
|
||||
)
|
||||
# Test that this does not segfault:
|
||||
target_compile_definitions(CompatibleInterface
|
||||
PRIVATE
|
||||
$<$<BOOL:$<TARGET_PROPERTY:Iface2_PROP>>:SOME_DEFINE>
|
||||
)
|
||||
|
|
|
@ -90,23 +90,7 @@ set_property(TARGET testLibCycleA PROPERTY LINK_INTERFACE_MULTIPLICITY 3)
|
|||
# Test exporting dependent libraries into different exports
|
||||
add_library(testLibRequired testLibRequired.c)
|
||||
add_library(testLibDepends testLibDepends.c)
|
||||
set_property(TARGET testLibDepends APPEND PROPERTY
|
||||
INCLUDE_DIRECTORIES
|
||||
$<TARGET_PROPERTY:testLibRequired,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
)
|
||||
set_property(TARGET testLibDepends APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS
|
||||
$<TARGET_PROPERTY:testLibRequired,INTERFACE_COMPILE_DEFINITIONS>
|
||||
)
|
||||
set_property(TARGET testLibDepends APPEND PROPERTY
|
||||
INTERFACE_INCLUDE_DIRECTORIES
|
||||
$<TARGET_PROPERTY:testLibRequired,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
)
|
||||
set_property(TARGET testLibDepends APPEND PROPERTY
|
||||
INTERFACE_COMPILE_DEFINITIONS
|
||||
$<TARGET_PROPERTY:testLibRequired,INTERFACE_COMPILE_DEFINITIONS>
|
||||
)
|
||||
target_link_libraries(testLibDepends testLibRequired)
|
||||
target_link_libraries(testLibDepends LINK_PUBLIC testLibRequired)
|
||||
|
||||
macro(add_include_lib _libName)
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_libName}.c" "// no content\n")
|
||||
|
@ -234,11 +218,30 @@ install(TARGETS testLibRequired
|
|||
testLibIncludeRequired6
|
||||
testSharedLibRequired
|
||||
EXPORT RequiredExp DESTINATION lib )
|
||||
install(EXPORT RequiredExp NAMESPACE Req:: FILE testLibRequiredConfig.cmake DESTINATION lib/cmake/testLibRequired)
|
||||
install(EXPORT RequiredExp NAMESPACE Req:: FILE testLibRequiredTargets.cmake DESTINATION lib/cmake/testLibRequired)
|
||||
|
||||
install(TARGETS testLibDepends testSharedLibDepends EXPORT DependsExp DESTINATION lib )
|
||||
install(EXPORT DependsExp FILE testLibDependsConfig.cmake DESTINATION lib/cmake/testLibDepends)
|
||||
install(EXPORT DependsExp FILE testLibDependsTargets.cmake DESTINATION lib/cmake/testLibDepends)
|
||||
|
||||
file(WRITE
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/testLibRequiredConfig.cmake"
|
||||
"
|
||||
if(\${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION VERSION_LESS 2.3 AND NOT \${CMAKE_FIND_PACKAGE_NAME}_INTERFACES)
|
||||
set(\${CMAKE_FIND_PACKAGE_NAME}_NO_INTERFACES 1)
|
||||
endif()
|
||||
include(\"\${CMAKE_CURRENT_LIST_DIR}/testLibRequiredTargets.cmake\")
|
||||
set(\${CMAKE_FIND_PACKAGE_NAME}_INCLUDE_DIRS \"${CMAKE_CURRENT_BINARY_DIR}\" \"${CMAKE_CURRENT_SOURCE_DIR}\" )
|
||||
"
|
||||
)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
write_basic_package_version_file( testLibRequiredConfigVersion.cmake VERSION 2.5 COMPATIBILITY AnyNewerVersion)
|
||||
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/testLibRequiredConfig.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/testLibRequiredConfigVersion.cmake"
|
||||
DESTINATION lib/cmake/testLibRequired
|
||||
)
|
||||
|
||||
# Install and export from install tree.
|
||||
install(
|
||||
|
|
|
@ -5,8 +5,8 @@ include(${Import_BINARY_DIR}/../Export/ExportBuildTree.cmake)
|
|||
include(${CMAKE_INSTALL_PREFIX}/lib/exp/exp.cmake)
|
||||
|
||||
# Import two exports, where the Depends one depends on an exported target from the Required one:
|
||||
include(${CMAKE_INSTALL_PREFIX}/lib/cmake/testLibRequired/testLibRequiredConfig.cmake)
|
||||
include(${CMAKE_INSTALL_PREFIX}/lib/cmake/testLibDepends/testLibDependsConfig.cmake)
|
||||
include(${CMAKE_INSTALL_PREFIX}/lib/cmake/testLibRequired/testLibRequiredTargets.cmake)
|
||||
include(${CMAKE_INSTALL_PREFIX}/lib/cmake/testLibDepends/testLibDependsTargets.cmake)
|
||||
|
||||
# Try referencing an executable imported from the install tree.
|
||||
add_custom_command(
|
||||
|
@ -159,18 +159,11 @@ endif()
|
|||
|
||||
add_executable(deps_iface deps_iface.c)
|
||||
target_link_libraries(deps_iface testLibDepends)
|
||||
target_include_directories(deps_iface PRIVATE $<TARGET_PROPERTY:testLibDepends,INTERFACE_INCLUDE_DIRECTORIES>)
|
||||
target_compile_definitions(deps_iface PRIVATE $<TARGET_PROPERTY:testLibDepends,INTERFACE_COMPILE_DEFINITIONS>)
|
||||
|
||||
add_executable(deps_shared_iface deps_shared_iface.cpp)
|
||||
target_link_libraries(deps_shared_iface testSharedLibDepends)
|
||||
target_include_directories(deps_shared_iface
|
||||
PRIVATE
|
||||
$<TARGET_PROPERTY:testSharedLibDepends,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
)
|
||||
target_compile_definitions(deps_shared_iface
|
||||
PRIVATE
|
||||
$<TARGET_PROPERTY:testSharedLibDepends,INTERFACE_COMPILE_DEFINITIONS>
|
||||
$<$<BOOL:$<TARGET_PROPERTY:POSITION_INDEPENDENT_CODE>>:PIC_PROPERTY_IS_ON>
|
||||
$<$<BOOL:$<TARGET_PROPERTY:CUSTOM_PROP>>:CUSTOM_PROPERTY_IS_ON>
|
||||
$<$<STREQUAL:$<TARGET_PROPERTY:CUSTOM_STRING>,testcontent>:CUSTOM_STRING_IS_MATCH>
|
||||
|
@ -200,13 +193,8 @@ endif()
|
|||
|
||||
add_executable(deps_shared_iface2 deps_shared_iface.cpp)
|
||||
target_link_libraries(deps_shared_iface2 bld_testSharedLibDepends bld_subdirlib)
|
||||
target_include_directories(deps_shared_iface2
|
||||
PRIVATE
|
||||
$<TARGET_PROPERTY:bld_testSharedLibDepends,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:bld_subdirlib,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
)
|
||||
target_compile_definitions(deps_shared_iface2
|
||||
PRIVATE $<TARGET_PROPERTY:bld_testSharedLibDepends,INTERFACE_COMPILE_DEFINITIONS> TEST_SUBDIR_LIB
|
||||
PRIVATE TEST_SUBDIR_LIB
|
||||
$<$<BOOL:$<TARGET_PROPERTY:POSITION_INDEPENDENT_CODE>>:PIC_PROPERTY_IS_ON>
|
||||
$<$<BOOL:$<TARGET_PROPERTY:CUSTOM_PROP>>:CUSTOM_PROPERTY_IS_ON>
|
||||
$<$<STREQUAL:$<TARGET_PROPERTY:CUSTOM_STRING>,testcontent>:CUSTOM_STRING_IS_MATCH>
|
||||
|
|
|
@ -17,3 +17,8 @@ add_executable(imp_testTransExe1 imp_testTransExe1.c)
|
|||
target_link_libraries(imp_testTransExe1 imp_lib1)
|
||||
add_executable(imp_testTransExe1b imp_testTransExe1.c)
|
||||
target_link_libraries(imp_testTransExe1b imp_lib1b)
|
||||
|
||||
# Test package INTERFACE controls
|
||||
add_subdirectory(package_old_old)
|
||||
add_subdirectory(package_new_old)
|
||||
add_subdirectory(package_new_new)
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
find_package(testLibRequired 2.5 REQUIRED)
|
||||
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
|
||||
"
|
||||
#include \"testSharedLibRequired.h\"
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
TestSharedLibRequired req;
|
||||
return req.foo();
|
||||
}
|
||||
"
|
||||
)
|
||||
|
||||
get_target_property(prop Req::testSharedLibRequired INTERFACE_INCLUDE_DIRECTORIES)
|
||||
if (NOT prop)
|
||||
message(SEND_ERROR "Interface of Req::testSharedLibRequired should not be empty")
|
||||
endif()
|
||||
|
||||
add_executable(new_new_test "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
|
||||
target_link_libraries(new_new_test Req::testSharedLibRequired)
|
|
@ -0,0 +1,24 @@
|
|||
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
find_package(testLibRequired 2.5 REQUIRED)
|
||||
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
|
||||
"
|
||||
#include \"testSharedLibRequired.h\"
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
TestSharedLibRequired req;
|
||||
return req.foo();
|
||||
}
|
||||
"
|
||||
)
|
||||
|
||||
get_target_property(prop Req::testSharedLibRequired INTERFACE_INCLUDE_DIRECTORIES)
|
||||
if ("${prop}" STREQUAL "")
|
||||
message(SEND_ERROR "Interface of Req::testSharedLibRequired should not be empty")
|
||||
endif()
|
||||
|
||||
add_executable(new_old_test "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
|
||||
target_link_libraries(new_old_test Req::testSharedLibRequired)
|
||||
include_directories(${testLibRequired_INCLUDE_DIRS})
|
|
@ -0,0 +1,24 @@
|
|||
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
find_package(testLibRequired 2.1 REQUIRED)
|
||||
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
|
||||
"
|
||||
#include \"testSharedLibRequired.h\"
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
TestSharedLibRequired req;
|
||||
return req.foo();
|
||||
}
|
||||
"
|
||||
)
|
||||
|
||||
get_target_property(prop Req::testSharedLibRequired INTERFACE_INCLUDE_DIRECTORIES)
|
||||
if (prop)
|
||||
message(SEND_ERROR "Interface of Req::testSharedLibRequired should be empty, but is ${prop}")
|
||||
endif()
|
||||
|
||||
add_executable(old_old_test "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
|
||||
target_link_libraries(old_old_test Req::testSharedLibRequired)
|
||||
include_directories(${testLibRequired_INCLUDE_DIRS})
|
|
@ -89,7 +89,6 @@ add_custom_target(check-part2 ALL
|
|||
-Dtest_install_interface=$<INSTALL_INTERFACE:install>
|
||||
-Dtest_target_name_1=$<TARGET_NAME:tgt,ok>
|
||||
-Dtest_target_name_2=$<TARGET_NAME:tgt:ok>
|
||||
-Dtest_install_prefix=$<INSTALL_PREFIX>
|
||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/check-part2.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "check done (part 2 of 2)"
|
||||
VERBATIM
|
||||
|
|
|
@ -26,4 +26,3 @@ check(test_build_interface "build")
|
|||
check(test_install_interface "")
|
||||
check(test_target_name_1 "tgt,ok")
|
||||
check(test_target_name_2 "tgt:ok")
|
||||
check(test_install_prefix "")
|
||||
|
|
|
@ -82,3 +82,44 @@ add_custom_target(test_custom_target
|
|||
$<TARGET_PROPERTY:TargetIncludeDirectories,COMPILE_DEFINITIONS>
|
||||
WORKING_DIRECTORY
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bad")
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/bad/common.h" "#error Should not be included\n")
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/good")
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/good/common.h" "#include \"othergood.h\"\n")
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/othergood")
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/othergood/othergood.h" "// No error\n")
|
||||
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/libothergood.cpp" "// No content \n")
|
||||
add_library(libothergood "${CMAKE_CURRENT_BINARY_DIR}/libothergood.cpp")
|
||||
set_property(TARGET libothergood APPEND PROPERTY
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/othergood"
|
||||
)
|
||||
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/libgood.cpp" "// No content \n")
|
||||
add_library(libgood "${CMAKE_CURRENT_BINARY_DIR}/libgood.cpp")
|
||||
set_property(TARGET libgood APPEND PROPERTY
|
||||
INTERFACE_INCLUDE_DIRECTORIES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/good;$<TARGET_PROPERTY:libothergood,INTERFACE_INCLUDE_DIRECTORIES>"
|
||||
)
|
||||
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/libbad.cpp" "// No content \n")
|
||||
add_library(libbad "${CMAKE_CURRENT_BINARY_DIR}/libbad.cpp")
|
||||
set_property(TARGET libbad APPEND PROPERTY
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/bad"
|
||||
)
|
||||
|
||||
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib5.cpp" "#include \"common.h\"\n")
|
||||
add_library(lib5 "${CMAKE_CURRENT_BINARY_DIR}/lib5.cpp")
|
||||
|
||||
# Assuming the link order must be:
|
||||
target_link_libraries(lib5 libbad libgood)
|
||||
|
||||
# Oops!.
|
||||
# As include directory order and link order are the same when using target_link_libraries, we have to
|
||||
# get the libgood includes in before the libbad includes.
|
||||
# We do that with this command:
|
||||
target_include_directories(lib5
|
||||
BEFORE PRIVATE $<LINKED:libgood>
|
||||
)
|
||||
|
|
|
@ -12,29 +12,10 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
|||
add_executable(Qt4Targets WIN32 main.cpp)
|
||||
target_link_libraries(Qt4Targets Qt4::QtGui)
|
||||
|
||||
set_property(TARGET Qt4Targets APPEND PROPERTY
|
||||
INCLUDE_DIRECTORIES
|
||||
$<TARGET_PROPERTY:Qt4::QtGui,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
)
|
||||
set_property(TARGET Qt4Targets APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS
|
||||
$<TARGET_PROPERTY:Qt4::QtGui,INTERFACE_COMPILE_DEFINITIONS>
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
if (TARGET Qt4::QAxServer)
|
||||
add_executable(activeqtexe WIN32 activeqtexe.cpp)
|
||||
set_property(TARGET activeqtexe PROPERTY QT4_NO_LINK_QTMAIN ON)
|
||||
target_link_libraries(activeqtexe Qt4::QAxServer Qt4::QtGui)
|
||||
set_property(TARGET activeqtexe APPEND PROPERTY
|
||||
INCLUDE_DIRECTORIES
|
||||
$<TARGET_PROPERTY:Qt4::QAxServer,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:Qt4::QtGui,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
)
|
||||
set_property(TARGET activeqtexe APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS
|
||||
$<TARGET_PROPERTY:Qt4::QAxServer,INTERFACE_COMPILE_DEFINITIONS>
|
||||
$<TARGET_PROPERTY:Qt4::QtGui,INTERFACE_COMPILE_DEFINITIONS>
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,9 @@
|
|||
CMake Error at BadInstallPrefix.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<INSTALL_PREFIX>
|
||||
|
||||
INSTALL_PREFIX is a marker for install\(EXPORT\) only. It should never be
|
||||
evaluated.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,3 @@
|
|||
add_custom_target(check ALL COMMAND check
|
||||
$<INSTALL_PREFIX>/include
|
||||
VERBATIM)
|
|
@ -7,3 +7,4 @@ run_cmake(BadNOT)
|
|||
run_cmake(BadStrEqual)
|
||||
run_cmake(BadZero)
|
||||
run_cmake(BadTargetName)
|
||||
run_cmake(BadInstallPrefix)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,7 @@
|
|||
CMake Error:
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINKED:something>
|
||||
|
||||
\$<LINKED:...> may only be used in INCLUDE_DIRECTORIES and
|
||||
COMPILE_DEFINITIONS properties.$
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
|
||||
"int main(int, char **) { return 0; }\n")
|
||||
|
||||
add_executable(TargetPropertyGeneratorExpressions
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
|
||||
target_link_libraries(TargetPropertyGeneratorExpressions "$<LINKED:something>")
|
|
@ -15,3 +15,4 @@ run_cmake(BadInvalidName5)
|
|||
run_cmake(BadInvalidName6)
|
||||
run_cmake(BadInvalidName7)
|
||||
run_cmake(BadInvalidName8)
|
||||
run_cmake(BadLinked)
|
||||
|
|
Loading…
Reference in New Issue