summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2013-02-05 19:46:43 (GMT)
committerCMake Topic Stage <kwrobot@kitware.com>2013-02-05 19:46:43 (GMT)
commitec85306025ae787e08d4ce097fde966f1809c74f (patch)
treeb583e726d1ab08212554cf299bb653604c72ff2a
parent020525845a3999078e4f7897d293c5aeab20af87 (diff)
parente48d84209cde93b43fcfb305897b4f52cd18a55f (diff)
downloadCMake-ec85306025ae787e08d4ce097fde966f1809c74f.zip
CMake-ec85306025ae787e08d4ce097fde966f1809c74f.tar.gz
CMake-ec85306025ae787e08d4ce097fde966f1809c74f.tar.bz2
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 documentation e7b579b 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.
-rw-r--r--Source/cmDocumentGeneratorExpressions.h8
-rw-r--r--Source/cmExportFileGenerator.cxx75
-rw-r--r--Source/cmExportFileGenerator.h4
-rw-r--r--Source/cmFindPackageCommand.cxx20
-rw-r--r--Source/cmGeneratorExpression.cxx8
-rw-r--r--Source/cmGeneratorExpression.h5
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.cxx42
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.h6
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx127
-rw-r--r--Source/cmGeneratorExpressionEvaluator.h1
-rw-r--r--Source/cmTarget.cxx41
-rw-r--r--Source/cmTarget.h6
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx53
-rw-r--r--Source/cmTargetLinkLibrariesCommand.h9
-rw-r--r--Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt6
-rw-r--r--Tests/CMakeCommands/target_compile_definitions/consumer.cpp4
-rw-r--r--Tests/CMakeCommands/target_include_directories/CMakeLists.txt11
-rw-r--r--Tests/CMakeCommands/target_include_directories/consumer.cpp5
-rw-r--r--Tests/CMakeCommands/target_link_libraries/CMakeLists.txt25
-rw-r--r--Tests/CMakeCommands/target_link_libraries/depG.cpp7
-rw-r--r--Tests/CMakeCommands/target_link_libraries/depG.h7
-rw-r--r--Tests/CMakeCommands/target_link_libraries/targetC.cpp16
-rw-r--r--Tests/CompatibleInterface/CMakeLists.txt14
-rw-r--r--Tests/ExportImport/Export/CMakeLists.txt41
-rw-r--r--Tests/ExportImport/Import/A/CMakeLists.txt18
-rw-r--r--Tests/ExportImport/Import/CMakeLists.txt5
-rw-r--r--Tests/ExportImport/Import/package_new_new/CMakeLists.txt23
-rw-r--r--Tests/ExportImport/Import/package_new_old/CMakeLists.txt24
-rw-r--r--Tests/ExportImport/Import/package_old_old/CMakeLists.txt24
-rw-r--r--Tests/GeneratorExpression/CMakeLists.txt1
-rw-r--r--Tests/GeneratorExpression/check-part2.cmake1
-rw-r--r--Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt41
-rw-r--r--Tests/Qt4Targets/CMakeLists.txt19
-rw-r--r--Tests/RunCMake/GeneratorExpression/BadInstallPrefix-result.txt1
-rw-r--r--Tests/RunCMake/GeneratorExpression/BadInstallPrefix-stderr.txt9
-rw-r--r--Tests/RunCMake/GeneratorExpression/BadInstallPrefix.cmake3
-rw-r--r--Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-result.txt1
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-stderr.txt7
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked.cmake7
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake1
41 files changed, 633 insertions, 94 deletions
diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h
index 8b80a8a..3993f7d 100644
--- a/Source/cmDocumentGeneratorExpressions.h
+++ b/Source/cmDocumentGeneratorExpressions.h
@@ -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 " \
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index dbe64e9..7e4c3df 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -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,12 +395,63 @@ 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)
{
std::string::size_type nameStartPos = pos + sizeof("$<TARGET_NAME:") - 1;
@@ -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;
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 776be61..5ad27bf 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -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);
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 470ceca..6e78bd7 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -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."
;
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 78ae8f2..7add1bf 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -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 =
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index 8f1aef6..700fe03 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -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
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index 269211b..b9069ef 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -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 );
+}
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
index 3169291..a2e5ce4 100644
--- a/Source/cmGeneratorExpressionDAGChecker.h
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -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;
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index f74b69e..5d94718 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -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,20 +639,115 @@ 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> &parameters,
+ 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;
}
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
index fb6c7ee..37d5c86 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -32,6 +32,7 @@ struct cmGeneratorExpressionContext
// directly or indirectly in the property.
bool Quiet;
bool HadError;
+ bool HadContextSensitiveCondition;
};
struct cmGeneratorExpressionDAGChecker;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 132154c..ca0e24b 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -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,
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index cf2d4c4..7577a59 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -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;
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index f42b0f6..cb913f5 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -250,10 +250,51 @@ cmTargetLinkLibrariesCommand
}
//----------------------------------------------------------------------------
+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();
diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h
index 3da3950..aaabdfa 100644
--- a/Source/cmTargetLinkLibrariesCommand.h
+++ b/Source/cmTargetLinkLibrariesCommand.h
@@ -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 "
diff --git a/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt b/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt
index 8a4437b..0bfcc1b 100644
--- a/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt
@@ -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
)
diff --git a/Tests/CMakeCommands/target_compile_definitions/consumer.cpp b/Tests/CMakeCommands/target_compile_definitions/consumer.cpp
index 1a46aa5..c077593 100644
--- a/Tests/CMakeCommands/target_compile_definitions/consumer.cpp
+++ b/Tests/CMakeCommands/target_compile_definitions/consumer.cpp
@@ -23,4 +23,8 @@
#error Expected DASH_D_DEFINE
#endif
+#ifndef MY_LINKED_DEFINE
+#error Expected MY_LINKED_DEFINE
+#endif
+
int main() { return 0; }
diff --git a/Tests/CMakeCommands/target_include_directories/CMakeLists.txt b/Tests/CMakeCommands/target_include_directories/CMakeLists.txt
index 7529283..a564918 100644
--- a/Tests/CMakeCommands/target_include_directories/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_include_directories/CMakeLists.txt
@@ -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
)
diff --git a/Tests/CMakeCommands/target_include_directories/consumer.cpp b/Tests/CMakeCommands/target_include_directories/consumer.cpp
index 82b800a..ccffd9c 100644
--- a/Tests/CMakeCommands/target_include_directories/consumer.cpp
+++ b/Tests/CMakeCommands/target_include_directories/consumer.cpp
@@ -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; }
diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
index 1d0e342..cd0fe11 100644
--- a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
@@ -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)
diff --git a/Tests/CMakeCommands/target_link_libraries/depG.cpp b/Tests/CMakeCommands/target_link_libraries/depG.cpp
new file mode 100644
index 0000000..65b9655
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depG.cpp
@@ -0,0 +1,7 @@
+
+#include "depG.h"
+
+int DepG::foo()
+{
+ return 0;
+}
diff --git a/Tests/CMakeCommands/target_link_libraries/depG.h b/Tests/CMakeCommands/target_link_libraries/depG.h
new file mode 100644
index 0000000..1a36589
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depG.h
@@ -0,0 +1,7 @@
+
+#include "depg_export.h"
+
+struct DEPG_EXPORT DepG
+{
+ int foo();
+};
diff --git a/Tests/CMakeCommands/target_link_libraries/targetC.cpp b/Tests/CMakeCommands/target_link_libraries/targetC.cpp
new file mode 100644
index 0000000..ff6ba66
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/targetC.cpp
@@ -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();
+}
diff --git a/Tests/CompatibleInterface/CMakeLists.txt b/Tests/CompatibleInterface/CMakeLists.txt
index 259b5a1..329510b 100644
--- a/Tests/CompatibleInterface/CMakeLists.txt
+++ b/Tests/CompatibleInterface/CMakeLists.txt
@@ -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>
+)
diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt
index 47521d8..ae938cd 100644
--- a/Tests/ExportImport/Export/CMakeLists.txt
+++ b/Tests/ExportImport/Export/CMakeLists.txt
@@ -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(
diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt
index e9bd2ba..0337130 100644
--- a/Tests/ExportImport/Import/A/CMakeLists.txt
+++ b/Tests/ExportImport/Import/A/CMakeLists.txt
@@ -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>
diff --git a/Tests/ExportImport/Import/CMakeLists.txt b/Tests/ExportImport/Import/CMakeLists.txt
index 3fc78a2..237f8fa 100644
--- a/Tests/ExportImport/Import/CMakeLists.txt
+++ b/Tests/ExportImport/Import/CMakeLists.txt
@@ -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)
diff --git a/Tests/ExportImport/Import/package_new_new/CMakeLists.txt b/Tests/ExportImport/Import/package_new_new/CMakeLists.txt
new file mode 100644
index 0000000..4e6f642
--- /dev/null
+++ b/Tests/ExportImport/Import/package_new_new/CMakeLists.txt
@@ -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)
diff --git a/Tests/ExportImport/Import/package_new_old/CMakeLists.txt b/Tests/ExportImport/Import/package_new_old/CMakeLists.txt
new file mode 100644
index 0000000..e675d64
--- /dev/null
+++ b/Tests/ExportImport/Import/package_new_old/CMakeLists.txt
@@ -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})
diff --git a/Tests/ExportImport/Import/package_old_old/CMakeLists.txt b/Tests/ExportImport/Import/package_old_old/CMakeLists.txt
new file mode 100644
index 0000000..3b27330
--- /dev/null
+++ b/Tests/ExportImport/Import/package_old_old/CMakeLists.txt
@@ -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})
diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt
index a40a541..ecbbedf 100644
--- a/Tests/GeneratorExpression/CMakeLists.txt
+++ b/Tests/GeneratorExpression/CMakeLists.txt
@@ -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
diff --git a/Tests/GeneratorExpression/check-part2.cmake b/Tests/GeneratorExpression/check-part2.cmake
index 0b50204..8855a97 100644
--- a/Tests/GeneratorExpression/check-part2.cmake
+++ b/Tests/GeneratorExpression/check-part2.cmake
@@ -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 "")
diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
index 21159e0..5387377 100644
--- a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
+++ b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
@@ -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>
+)
diff --git a/Tests/Qt4Targets/CMakeLists.txt b/Tests/Qt4Targets/CMakeLists.txt
index d3aba74..d0c9c66 100644
--- a/Tests/Qt4Targets/CMakeLists.txt
+++ b/Tests/Qt4Targets/CMakeLists.txt
@@ -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()
diff --git a/Tests/RunCMake/GeneratorExpression/BadInstallPrefix-result.txt b/Tests/RunCMake/GeneratorExpression/BadInstallPrefix-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/BadInstallPrefix-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GeneratorExpression/BadInstallPrefix-stderr.txt b/Tests/RunCMake/GeneratorExpression/BadInstallPrefix-stderr.txt
new file mode 100644
index 0000000..271eb6e
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/BadInstallPrefix-stderr.txt
@@ -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\)
diff --git a/Tests/RunCMake/GeneratorExpression/BadInstallPrefix.cmake b/Tests/RunCMake/GeneratorExpression/BadInstallPrefix.cmake
new file mode 100644
index 0000000..fcfc3eb
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/BadInstallPrefix.cmake
@@ -0,0 +1,3 @@
+add_custom_target(check ALL COMMAND check
+ $<INSTALL_PREFIX>/include
+ VERBATIM)
diff --git a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
index 8a69675..62bf29b 100644
--- a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
@@ -7,3 +7,4 @@ run_cmake(BadNOT)
run_cmake(BadStrEqual)
run_cmake(BadZero)
run_cmake(BadTargetName)
+run_cmake(BadInstallPrefix)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-stderr.txt
new file mode 100644
index 0000000..4cd9cdd
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-stderr.txt
@@ -0,0 +1,7 @@
+CMake Error:
+ Error evaluating generator expression:
+
+ \$<LINKED:something>
+
+ \$<LINKED:...> may only be used in INCLUDE_DIRECTORIES and
+ COMPILE_DEFINITIONS properties.$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked.cmake
new file mode 100644
index 0000000..542ea76
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked.cmake
@@ -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>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake
index 0ee3238..ea48f61 100644
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake
@@ -15,3 +15,4 @@ run_cmake(BadInvalidName5)
run_cmake(BadInvalidName6)
run_cmake(BadInvalidName7)
run_cmake(BadInvalidName8)
+run_cmake(BadLinked)