summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2014-01-06 16:43:12 (GMT)
committerCMake Topic Stage <kwrobot@kitware.com>2014-01-06 16:43:12 (GMT)
commitdc08199848c20c7f76a68dbf54a85c736809ac57 (patch)
tree0d0d5b59269c8edc078450b8aeecc519affa6a2f
parentb225dbbd0235b545383105e0571f84a1bf6b1be0 (diff)
parent84fac67f90b275116efa9ec25f5fcb2c2bf7f6b4 (diff)
downloadCMake-dc08199848c20c7f76a68dbf54a85c736809ac57.zip
CMake-dc08199848c20c7f76a68dbf54a85c736809ac57.tar.gz
CMake-dc08199848c20c7f76a68dbf54a85c736809ac57.tar.bz2
Merge topic 'minor-cleanups'
84fac67 Don't allow include() of export(EXPORT) file at configure time. faedd2b cmTarget: Fix system include annotation propagation. 9eb06d0 add_library: Disallow invalid signatures for INTERFACE_LIBRARY. 10d65d5 cmTarget: Move a variable initialization closer to where it is used. 0f3e8e9 Undefine local preprocessor loop variables. 9ba47ee Genex: Reform error-checking for nullary/unary expressions. fa651c7 cmTarget: Remove some of the INTERFACE_LIBRARY whitelisted properties. 61d138a cmTarget: INTERFACE_LIBRARY is always EXCLUDE_FROM_ALL. 3429541 export: Rename some variables to reflect content type. 7461d67 cmTarget: Enable convenient include dir handling for INTERFACE_LIBRARY. 7fc6e3d cmTarget: Remove dead code. 2af966d Genex: Add EQUAL expression. 2d66380 cmTarget: Use strtol for numeric parsing.
-rw-r--r--Help/command/add_library.rst17
-rw-r--r--Help/manual/cmake-generator-expressions.7.rst2
-rw-r--r--Source/cmAddLibraryCommand.cxx88
-rw-r--r--Source/cmExportCommand.cxx10
-rw-r--r--Source/cmExportFileGenerator.cxx18
-rw-r--r--Source/cmExportFileGenerator.h2
-rw-r--r--Source/cmExportTryCompileFileGenerator.cxx2
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.cxx4
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.h4
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx131
-rw-r--r--Source/cmGeneratorTarget.cxx113
-rw-r--r--Source/cmGlobalGenerator.cxx32
-rw-r--r--Source/cmGlobalGenerator.h2
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx3
-rw-r--r--Source/cmTarget.cxx92
-rw-r--r--Source/cmTarget.h2
-rw-r--r--Tests/CompatibleInterface/CMakeLists.txt10
-rw-r--r--Tests/CompatibleInterface/main.cpp4
-rw-r--r--Tests/GeneratorExpression/CMakeLists.txt21
-rw-r--r--Tests/GeneratorExpression/check-part3.cmake21
-rw-r--r--Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt4
-rw-r--r--Tests/InterfaceLibrary/CMakeLists.txt6
-rw-r--r--Tests/InterfaceLibrary/definetestexe.cpp12
-rw-r--r--Tests/InterfaceLibrary/headerdir/CMakeLists.txt8
-rw-r--r--Tests/InterfaceLibrary/headerdir/iface_header.h1
-rw-r--r--Tests/InterfaceLibrary/libsdir/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/include/ExportExportInclude-result.txt1
-rw-r--r--Tests/RunCMake/include/ExportExportInclude-stderr.txt6
-rw-r--r--Tests/RunCMake/include/ExportExportInclude.cmake6
-rw-r--r--Tests/RunCMake/include/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/interface_library/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/interface_library/invalid_signature-result.txt1
-rw-r--r--Tests/RunCMake/interface_library/invalid_signature-stderr.txt89
-rw-r--r--Tests/RunCMake/interface_library/invalid_signature.cmake20
34 files changed, 581 insertions, 155 deletions
diff --git a/Help/command/add_library.rst b/Help/command/add_library.rst
index 45f1102..2d69c89 100644
--- a/Help/command/add_library.rst
+++ b/Help/command/add_library.rst
@@ -109,12 +109,21 @@ The signature
::
- add_library(<name> INTERFACE)
+ add_library(<name> INTERFACE [IMPORTED [GLOBAL]])
creates an interface target. An interface target does not directly
create build output, though it may have properties set on it and it
may be installed, exported and imported. Typically the INTERFACE_*
properties are populated on the interface target using the
-set_property(), target_link_libraries(), target_include_directories()
-and target_compile_defintions() commands, and then it is used as an
-argument to target_link_libraries() like any other target.
+:command:`set_property`, :command:`target_link_libraries`,
+:command:`target_include_directories`
+and :command:`target_compile_defintions` commands, and then it is used as an
+argument to :command:`target_link_libraries` like any other target.
+
+An ``INTERFACE`` :prop_tgt:`IMPORTED` target may also be created with this
+signature. An :prop_tgt:`IMPORTED` library target references a library defined
+outside the project. The target name has scope in the directory in which it is
+created and below, but the ``GLOBAL`` option extends visibility. It may be
+referenced like any target built within the project. :prop_tgt:`IMPORTED`
+libraries are useful for convenient reference from commands like
+:command:`target_link_libraries`.
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index ed28abd..12cfaf8 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -55,6 +55,8 @@ otherwise expands to nothing.
``0`` if ``?`` is ``1``, else ``1``
``$<STREQUAL:a,b>``
``1`` if ``a`` is STREQUAL ``b``, else ``0``
+``$<EQUAL:a,b>``
+ ``1`` if ``a`` is EQUAL ``b`` in a numeric comparison, else ``0``
``$<CONFIG:cfg>``
``1`` if config is ``cfg``, else ``0``. This is a case-insensitive comparison.
The mapping in :prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>` is also considered by
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index 0f98f35..2627445 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -49,47 +49,117 @@ bool cmAddLibraryCommand
std::string libType = *s;
if(libType == "STATIC")
{
+ if (type == cmTarget::INTERFACE_LIBRARY)
+ {
+ cmOStringStream e;
+ e << "INTERFACE library specified with conflicting STATIC type.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
++s;
type = cmTarget::STATIC_LIBRARY;
haveSpecifiedType = true;
}
else if(libType == "SHARED")
{
+ if (type == cmTarget::INTERFACE_LIBRARY)
+ {
+ cmOStringStream e;
+ e << "INTERFACE library specified with conflicting SHARED type.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
++s;
type = cmTarget::SHARED_LIBRARY;
haveSpecifiedType = true;
}
else if(libType == "MODULE")
{
+ if (type == cmTarget::INTERFACE_LIBRARY)
+ {
+ cmOStringStream e;
+ e << "INTERFACE library specified with conflicting MODULE type.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
++s;
type = cmTarget::MODULE_LIBRARY;
haveSpecifiedType = true;
}
else if(libType == "OBJECT")
{
+ if (type == cmTarget::INTERFACE_LIBRARY)
+ {
+ cmOStringStream e;
+ e << "INTERFACE library specified with conflicting OBJECT type.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
++s;
type = cmTarget::OBJECT_LIBRARY;
haveSpecifiedType = true;
}
else if(libType == "UNKNOWN")
{
+ if (type == cmTarget::INTERFACE_LIBRARY)
+ {
+ cmOStringStream e;
+ e << "INTERFACE library specified with conflicting UNKNOWN type.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
++s;
type = cmTarget::UNKNOWN_LIBRARY;
haveSpecifiedType = true;
}
else if(libType == "ALIAS")
{
+ if (type == cmTarget::INTERFACE_LIBRARY)
+ {
+ cmOStringStream e;
+ e << "INTERFACE library specified with conflicting ALIAS type.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
++s;
isAlias = true;
}
else if(libType == "INTERFACE")
{
+ if (haveSpecifiedType)
+ {
+ cmOStringStream e;
+ e << "INTERFACE library specified with conflicting/multiple types.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ if (isAlias)
+ {
+ cmOStringStream e;
+ e << "INTERFACE library specified with conflicting ALIAS type.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ if (excludeFromAll)
+ {
+ cmOStringStream e;
+ e << "INTERFACE library may not be used with EXCLUDE_FROM_ALL.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
++s;
type = cmTarget::INTERFACE_LIBRARY;
haveSpecifiedType = true;
}
else if(*s == "EXCLUDE_FROM_ALL")
{
+ if (type == cmTarget::INTERFACE_LIBRARY)
+ {
+ cmOStringStream e;
+ e << "INTERFACE library may not be used with EXCLUDE_FROM_ALL.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
++s;
excludeFromAll = true;
}
@@ -109,6 +179,24 @@ bool cmAddLibraryCommand
}
}
+ if (type == cmTarget::INTERFACE_LIBRARY)
+ {
+ if (s != args.end())
+ {
+ cmOStringStream e;
+ e << "INTERFACE library requires no source arguments.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ if (importGlobal && !importTarget)
+ {
+ cmOStringStream e;
+ e << "INTERFACE library specified as GLOBAL, but not as IMPORTED.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ }
+
bool nameOk = cmGeneratorExpression::IsValidTargetName(libName) &&
!cmGlobalGenerator::IsReservedTarget(libName);
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index b6bf870..7c97d8d 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -236,8 +236,14 @@ bool cmExportCommand
{
ebfg->AddConfiguration("");
}
-
- gg->AddBuildExportSet(ebfg);
+ if (this->ExportSet)
+ {
+ gg->AddBuildExportExportSet(ebfg);
+ }
+ else
+ {
+ gg->AddBuildExportSet(ebfg);
+ }
return true;
}
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 2a87e4f..4543f79 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -825,36 +825,36 @@ cmExportFileGenerator
::SetImportLinkProperty(std::string const& suffix,
cmTarget* target,
const char* propName,
- std::vector<std::string> const& libs,
+ std::vector<std::string> const& entries,
ImportPropertyMap& properties,
std::vector<std::string>& missingTargets
)
{
- // Skip the property if there are no libraries.
- if(libs.empty())
+ // Skip the property if there are no entries.
+ if(entries.empty())
{
return;
}
// Construct the property value.
- std::string link_libs;
+ std::string link_entries;
const char* sep = "";
- for(std::vector<std::string>::const_iterator li = libs.begin();
- li != libs.end(); ++li)
+ for(std::vector<std::string>::const_iterator li = entries.begin();
+ li != entries.end(); ++li)
{
// Separate this from the previous entry.
- link_libs += sep;
+ link_entries += sep;
sep = ";";
std::string temp = *li;
this->AddTargetNamespace(temp, target, missingTargets);
- link_libs += temp;
+ link_entries += temp;
}
// Store the property.
std::string prop = propName;
prop += suffix;
- properties[prop] = link_libs;
+ properties[prop] = link_entries;
}
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 6fd23b0..1438f4d 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -82,7 +82,7 @@ protected:
std::vector<std::string>& missingTargets);
void SetImportLinkProperty(std::string const& suffix,
cmTarget* target, const char* propName,
- std::vector<std::string> const& libs,
+ std::vector<std::string> const& entries,
ImportPropertyMap& properties,
std::vector<std::string>& missingTargets);
diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx
index d9bc04c..8d37b62 100644
--- a/Source/cmExportTryCompileFileGenerator.cxx
+++ b/Source/cmExportTryCompileFileGenerator.cxx
@@ -36,6 +36,8 @@ bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os)
CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(FIND_TARGETS)
+#undef FIND_TARGETS
+
this->PopulateProperties(te, properties, emittedDeps);
this->GenerateInterfaceProperties(te, os, properties);
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index 92f74f3..c2c4e20 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -40,6 +40,7 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(TEST_TRANSITIVE_PROPERTY_METHOD)
false)
)
+#undef TEST_TRANSITIVE_PROPERTY_METHOD
{
std::map<cmStdString, std::set<cmStdString> >::const_iterator it
= top->Seen.find(target);
@@ -191,7 +192,8 @@ bool
cmGeneratorExpressionDAGChecker::EvaluatingSystemIncludeDirectories() const
{
const char *prop = this->Property.c_str();
- return strcmp(prop, "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES") == 0;
+ return (strcmp(prop, "SYSTEM_INCLUDE_DIRECTORIES") == 0
+ || strcmp(prop, "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES") == 0);
}
//----------------------------------------------------------------------------
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
index fd47ad7..98ffd36 100644
--- a/Source/cmGeneratorExpressionDAGChecker.h
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -56,7 +56,9 @@ struct cmGeneratorExpressionDAGChecker
#define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) \
bool METHOD () const;
-CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(DECLARE_TRANSITIVE_PROPERTY_METHOD)
+ CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(DECLARE_TRANSITIVE_PROPERTY_METHOD)
+
+#undef DECLARE_TRANSITIVE_PROPERTY_METHOD
bool GetTransitivePropertiesOnly();
void SetTransitivePropertiesOnly()
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index c8010d0..f0e40ea 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -19,6 +19,7 @@
#include <cmsys/String.h>
#include <assert.h>
+#include <errno.h>
//----------------------------------------------------------------------------
#if !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x510
@@ -48,7 +49,7 @@ struct cmGeneratorExpressionNode
enum {
DynamicParameters = 0,
OneOrMoreParameters = -1,
- ZeroOrMoreParameters = -2
+ OneOrZeroParameters = -2
};
virtual ~cmGeneratorExpressionNode() {}
@@ -197,6 +198,92 @@ static const struct StrEqualNode : public cmGeneratorExpressionNode
} strEqualNode;
//----------------------------------------------------------------------------
+static const struct EqualNode : public cmGeneratorExpressionNode
+{
+ EqualNode() {}
+
+ virtual int NumExpectedParameters() const { return 2; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ char *pEnd;
+
+ int base = 0;
+ bool flipSign = false;
+
+ const char *lhs = parameters[0].c_str();
+ if (cmHasLiteralPrefix(lhs, "0b"))
+ {
+ base = 2;
+ lhs += 2;
+ }
+ if (cmHasLiteralPrefix(lhs, "-0b"))
+ {
+ base = 2;
+ lhs += 3;
+ flipSign = true;
+ }
+ if (cmHasLiteralPrefix(lhs, "+0b"))
+ {
+ base = 2;
+ lhs += 3;
+ }
+
+ long lnum = strtol(lhs, &pEnd, base);
+ if (pEnd == lhs || *pEnd != '\0' || errno == ERANGE)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<EQUAL> parameter " + parameters[0] + " is not a valid integer.");
+ return std::string();
+ }
+
+ if (flipSign)
+ {
+ lnum = -lnum;
+ }
+
+ base = 0;
+ flipSign = false;
+
+ const char *rhs = parameters[1].c_str();
+ if (cmHasLiteralPrefix(rhs, "0b"))
+ {
+ base = 2;
+ rhs += 2;
+ }
+ if (cmHasLiteralPrefix(rhs, "-0b"))
+ {
+ base = 2;
+ rhs += 3;
+ flipSign = true;
+ }
+ if (cmHasLiteralPrefix(rhs, "+0b"))
+ {
+ base = 2;
+ rhs += 3;
+ }
+
+ long rnum = strtol(rhs, &pEnd, base);
+ if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<EQUAL> parameter " + parameters[1] + " is not a valid integer.");
+ return std::string();
+ }
+
+ if (flipSign)
+ {
+ rnum = -rnum;
+ }
+
+ return lnum == rnum ? "1" : "0";
+ }
+} equalNode;
+
+//----------------------------------------------------------------------------
static const struct LowerCaseNode : public cmGeneratorExpressionNode
{
LowerCaseNode() {}
@@ -297,7 +384,7 @@ struct CompilerIdNode : public cmGeneratorExpressionNode
{
CompilerIdNode() {}
- virtual int NumExpectedParameters() const { return ZeroOrMoreParameters; }
+ virtual int NumExpectedParameters() const { return OneOrZeroParameters; }
std::string EvaluateWithLanguage(const std::vector<std::string> &parameters,
cmGeneratorExpressionContext *context,
@@ -343,12 +430,6 @@ static const struct CCompilerIdNode : public CompilerIdNode
const GeneratorExpressionContent *content,
cmGeneratorExpressionDAGChecker *dagChecker) const
{
- if (parameters.size() != 0 && parameters.size() != 1)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<C_COMPILER_ID> expression requires one or two parameters");
- return std::string();
- }
if (!context->HeadTarget)
{
reportError(context, content->GetOriginalExpression(),
@@ -371,12 +452,6 @@ static const struct CXXCompilerIdNode : public CompilerIdNode
const GeneratorExpressionContent *content,
cmGeneratorExpressionDAGChecker *dagChecker) const
{
- if (parameters.size() != 0 && parameters.size() != 1)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<CXX_COMPILER_ID> expression requires one or two parameters");
- return std::string();
- }
if (!context->HeadTarget)
{
reportError(context, content->GetOriginalExpression(),
@@ -394,7 +469,7 @@ struct CompilerVersionNode : public cmGeneratorExpressionNode
{
CompilerVersionNode() {}
- virtual int NumExpectedParameters() const { return ZeroOrMoreParameters; }
+ virtual int NumExpectedParameters() const { return OneOrZeroParameters; }
std::string EvaluateWithLanguage(const std::vector<std::string> &parameters,
cmGeneratorExpressionContext *context,
@@ -439,12 +514,6 @@ static const struct CCompilerVersionNode : public CompilerVersionNode
const GeneratorExpressionContent *content,
cmGeneratorExpressionDAGChecker *dagChecker) const
{
- if (parameters.size() != 0 && parameters.size() != 1)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<C_COMPILER_VERSION> expression requires one or two parameters");
- return std::string();
- }
if (!context->HeadTarget)
{
reportError(context, content->GetOriginalExpression(),
@@ -467,13 +536,6 @@ static const struct CxxCompilerVersionNode : public CompilerVersionNode
const GeneratorExpressionContent *content,
cmGeneratorExpressionDAGChecker *dagChecker) const
{
- if (parameters.size() != 0 && parameters.size() != 1)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<CXX_COMPILER_VERSION> expression requires one or two "
- "parameters");
- return std::string();
- }
if (!context->HeadTarget)
{
reportError(context, content->GetOriginalExpression(),
@@ -492,7 +554,7 @@ struct PlatformIdNode : public cmGeneratorExpressionNode
{
PlatformIdNode() {}
- virtual int NumExpectedParameters() const { return ZeroOrMoreParameters; }
+ virtual int NumExpectedParameters() const { return OneOrZeroParameters; }
std::string Evaluate(const std::vector<std::string> &parameters,
cmGeneratorExpressionContext *context,
@@ -710,6 +772,8 @@ static const char* targetPropertyTransitiveWhitelist[] = {
CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_NAME)
};
+#undef TRANSITIVE_PROPERTY_NAME
+
std::string getLinkedTargetsContent(const std::vector<std::string> &libraries,
cmTarget const* target,
cmTarget const* headTarget,
@@ -937,6 +1001,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
ASSERT_TRANSITIVE_PROPERTY_METHOD)
false);
}
+#undef ASSERT_TRANSITIVE_PROPERTY_METHOD
}
std::string linkedTargetsContent;
@@ -1492,6 +1557,8 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
return &targetSoNameFileDirNode;
else if (identifier == "STREQUAL")
return &strEqualNode;
+ else if (identifier == "EQUAL")
+ return &equalNode;
else if (identifier == "LOWER_CASE")
return &lowerCaseNode;
else if (identifier == "UPPER_CASE")
@@ -1733,6 +1800,12 @@ std::string GeneratorExpressionContent::EvaluateParameters(
reportError(context, this->GetOriginalExpression(), "$<" + identifier
+ "> expression requires at least one parameter.");
}
+ if (numExpected == cmGeneratorExpressionNode::OneOrZeroParameters
+ && parameters.size() > 2)
+ {
+ reportError(context, this->GetOriginalExpression(), "$<" + identifier
+ + "> expression requires one or zero parameters.");
+ }
return std::string();
}
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index fdd4e6d..6894cfc 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -18,9 +18,12 @@
#include "cmSourceFile.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
+#include "cmComputeLinkInformation.h"
#include <queue>
+#include "assert.h"
+
//----------------------------------------------------------------------------
cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t)
{
@@ -59,10 +62,50 @@ cmGeneratorTarget::GetSourceDepends(cmSourceFile* sf) const
return 0;
}
+static void handleSystemIncludesDep(cmMakefile *mf, const std::string &name,
+ const char *config, cmTarget *headTarget,
+ cmGeneratorExpressionDAGChecker *dagChecker,
+ std::vector<std::string>& result)
+{
+ cmTarget* depTgt = mf->FindTargetToUse(name.c_str());
+
+ if (!depTgt)
+ {
+ return;
+ }
+
+ cmListFileBacktrace lfbt;
+
+ if (const char* dirs =
+ depTgt->GetProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES"))
+ {
+ cmGeneratorExpression ge(lfbt);
+ cmSystemTools::ExpandListArgument(ge.Parse(dirs)
+ ->Evaluate(mf,
+ config, false, headTarget,
+ depTgt, dagChecker), result);
+ }
+ if (!depTgt->IsImported())
+ {
+ return;
+ }
+
+ if (const char* dirs =
+ depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES"))
+ {
+ cmGeneratorExpression ge(lfbt);
+ cmSystemTools::ExpandListArgument(ge.Parse(dirs)
+ ->Evaluate(mf,
+ config, false, headTarget,
+ depTgt, dagChecker), result);
+ }
+}
+
//----------------------------------------------------------------------------
bool cmGeneratorTarget::IsSystemIncludeDirectory(const char *dir,
const char *config) const
{
+ assert(this->GetType() != cmTarget::INTERFACE_LIBRARY);
std::string config_upper;
if(config && *config)
{
@@ -75,39 +118,81 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(const char *dir,
if (iter == this->SystemIncludesCache.end())
{
+ cmTarget::LinkImplementation const* impl
+ = this->Target->GetLinkImplementation(config, this->Target);
+ if(!impl)
+ {
+ return false;
+ }
+
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+ this->GetName(),
+ "SYSTEM_INCLUDE_DIRECTORIES", 0, 0);
+
std::vector<std::string> result;
for (std::set<cmStdString>::const_iterator
it = this->Target->GetSystemIncludeDirectories().begin();
it != this->Target->GetSystemIncludeDirectories().end(); ++it)
{
- cmListFileBacktrace lfbt;
cmGeneratorExpression ge(lfbt);
+ cmSystemTools::ExpandListArgument(ge.Parse(*it)
+ ->Evaluate(this->Makefile,
+ config, false, this->Target,
+ &dagChecker), result);
+ }
+
+ std::set<cmStdString> uniqueDeps;
+ for(std::vector<std::string>::const_iterator li = impl->Libraries.begin();
+ li != impl->Libraries.end(); ++li)
+ {
+ if (uniqueDeps.insert(*li).second)
+ {
+ cmTarget* tgt = this->Makefile->FindTargetToUse(li->c_str());
- cmGeneratorExpressionDAGChecker dagChecker(lfbt,
- this->GetName(),
- "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", 0, 0);
+ if (!tgt)
+ {
+ continue;
+ }
- cmSystemTools::ExpandListArgument(ge.Parse(*it)
- ->Evaluate(this->Makefile,
- config, false, this->Target,
- &dagChecker), result);
+ handleSystemIncludesDep(this->Makefile, *li, config, this->Target,
+ &dagChecker, result);
+
+ std::vector<std::string> deps;
+ tgt->GetTransitivePropertyLinkLibraries(config, this->Target, deps);
+
+ for(std::vector<std::string>::const_iterator di = deps.begin();
+ di != deps.end(); ++di)
+ {
+ if (uniqueDeps.insert(*di).second)
+ {
+ handleSystemIncludesDep(this->Makefile, *di, config, this->Target,
+ &dagChecker, result);
+ }
+ }
+ }
}
+ std::set<cmStdString> unique;
for(std::vector<std::string>::iterator li = result.begin();
li != result.end(); ++li)
{
cmSystemTools::ConvertToUnixSlashes(*li);
+ unique.insert(*li);
+ }
+ result.clear();
+ for(std::set<cmStdString>::iterator li = unique.begin();
+ li != unique.end(); ++li)
+ {
+ result.push_back(*li);
}
IncludeCacheType::value_type entry(config_upper, result);
iter = this->SystemIncludesCache.insert(entry).first;
}
- if (std::find(iter->second.begin(),
- iter->second.end(), dir) != iter->second.end())
- {
- return true;
- }
- return false;
+ std::string dirString = dir;
+ return std::binary_search(iter->second.begin(), iter->second.end(),
+ dirString);
}
//----------------------------------------------------------------------------
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 3b858af..eef8d6d 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -187,6 +187,13 @@ void cmGlobalGenerator::AddBuildExportSet(cmExportBuildFileGenerator* gen)
this->BuildExportSets[gen->GetMainExportFileName()] = gen;
}
+void
+cmGlobalGenerator::AddBuildExportExportSet(cmExportBuildFileGenerator* gen)
+{
+ this->BuildExportSets[gen->GetMainExportFileName()] = gen;
+ this->BuildExportExportSets[gen->GetMainExportFileName()] = gen;
+}
+
bool cmGlobalGenerator::GenerateImportFile(const std::string &file)
{
std::map<std::string, cmExportBuildFileGenerator*>::iterator it
@@ -207,7 +214,12 @@ cmGlobalGenerator::IsExportedTargetsFile(const std::string &filename) const
{
const std::map<std::string, cmExportBuildFileGenerator*>::const_iterator it
= this->BuildExportSets.find(filename);
- return it != this->BuildExportSets.end();
+ if (it == this->BuildExportSets.end())
+ {
+ return false;
+ }
+ return this->BuildExportExportSets.find(filename)
+ == this->BuildExportExportSets.end();
}
// Find the make program for the generator, required for try compiles
@@ -1164,17 +1176,6 @@ void cmGlobalGenerator::Generate()
// it builds by default.
this->FillLocalGeneratorToTargetMap();
- for (i = 0; i < this->LocalGenerators.size(); ++i)
- {
- cmMakefile* mf = this->LocalGenerators[i]->GetMakefile();
- cmTargets* targets = &(mf->GetTargets());
- for ( cmTargets::iterator it = targets->begin();
- it != targets->end(); ++ it )
- {
- it->second.FinalizeSystemIncludeDirectories();
- }
- }
-
// Generate project files
for (i = 0; i < this->LocalGenerators.size(); ++i)
{
@@ -1337,13 +1338,13 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo()
{
cmTarget* t = &ti->second;
+ t->AppendBuildInterfaceIncludes();
+
if (t->GetType() == cmTarget::INTERFACE_LIBRARY)
{
continue;
}
- t->AppendBuildInterfaceIncludes();
-
for (std::vector<cmValueWithOrigin>::const_iterator it
= noconfig_compile_definitions.begin();
it != noconfig_compile_definitions.end(); ++it)
@@ -1908,7 +1909,8 @@ bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
cmTarget& target)
{
- if(target.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
+ if(target.GetType() == cmTarget::INTERFACE_LIBRARY
+ || target.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
{
// This target is excluded from its directory.
return true;
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 049b0e6..fc5cab9 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -311,6 +311,7 @@ public:
std::map<std::string, cmExportBuildFileGenerator*>& GetBuildExportSets()
{return this->BuildExportSets;}
void AddBuildExportSet(cmExportBuildFileGenerator*);
+ void AddBuildExportExportSet(cmExportBuildFileGenerator*);
bool IsExportedTargetsFile(const std::string &filename) const;
bool GenerateImportFile(const std::string &file);
cmExportBuildFileGenerator*
@@ -375,6 +376,7 @@ protected:
// Sets of named target exports
cmExportSetMap ExportSets;
std::map<std::string, cmExportBuildFileGenerator*> BuildExportSets;
+ std::map<std::string, cmExportBuildFileGenerator*> BuildExportExportSets;
// Manifest of all targets that will be built for each configuration.
// This is computed just before local generators generate.
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index b5a46d0..381c1f5 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -488,7 +488,8 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root,
dir.c_str());
}
- if(!target.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
+ if(target.GetType() != cmTarget::INTERFACE_LIBRARY
+ && !target.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
{
allbuild->AddUtility(target.GetName());
}
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index ead48b9..b06480b 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -24,6 +24,7 @@
#include <set>
#include <stdlib.h> // required for atof
#include <assert.h>
+#include <errno.h>
const char* cmTarget::GetTargetTypeName(TargetType targetType)
{
@@ -1041,62 +1042,6 @@ cmTarget::AddSystemIncludeDirectories(const std::vector<std::string> &incs)
}
//----------------------------------------------------------------------------
-void cmTarget::FinalizeSystemIncludeDirectories()
-{
- for (std::vector<cmValueWithOrigin>::const_iterator
- it = this->Internal->LinkImplementationPropertyEntries.begin(),
- end = this->Internal->LinkImplementationPropertyEntries.end();
- it != end; ++it)
- {
- if (!cmGeneratorExpression::IsValidTargetName(it->Value)
- && cmGeneratorExpression::Find(it->Value) == std::string::npos)
- {
- continue;
- }
- {
- cmListFileBacktrace lfbt;
- cmGeneratorExpression ge(lfbt);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
- ge.Parse(it->Value);
- std::string targetName = cge->Evaluate(this->Makefile, 0,
- false, this, 0, 0);
- cmTarget *tgt = this->Makefile->FindTargetToUse(targetName.c_str());
- if (!tgt || tgt == this)
- {
- continue;
- }
- if (tgt->IsImported()
- && tgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")
- && !this->GetPropertyAsBool("NO_SYSTEM_FROM_IMPORTED"))
- {
- std::string includeGenex = "$<TARGET_PROPERTY:" +
- it->Value + ",INTERFACE_INCLUDE_DIRECTORIES>";
- if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
- {
- // Because it->Value is a generator expression, ensure that it
- // evaluates to the non-empty string before being used in the
- // TARGET_PROPERTY expression.
- includeGenex = "$<$<BOOL:" + it->Value + ">:" + includeGenex + ">";
- }
- this->SystemIncludeDirectories.insert(includeGenex);
- return; // The INTERFACE_SYSTEM_INCLUDE_DIRECTORIES are a subset
- // of the INTERFACE_INCLUDE_DIRECTORIES
- }
- }
- std::string includeGenex = "$<TARGET_PROPERTY:" +
- it->Value + ",INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>";
- if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
- {
- // Because it->Value is a generator expression, ensure that it
- // evaluates to the non-empty string before being used in the
- // TARGET_PROPERTY expression.
- includeGenex = "$<$<BOOL:" + it->Value + ">:" + includeGenex + ">";
- }
- this->SystemIncludeDirectories.insert(includeGenex);
- }
-}
-
-//----------------------------------------------------------------------------
void
cmTarget::AnalyzeLibDependencies( const cmMakefile& mf )
{
@@ -1402,14 +1347,10 @@ static bool whiteListedInterfaceProperty(const char *prop)
"COMPATIBLE_INTERFACE_NUMBER_MAX",
"COMPATIBLE_INTERFACE_NUMBER_MIN",
"COMPATIBLE_INTERFACE_STRING",
- "EXCLUDE_FROM_ALL",
- "EXCLUDE_FROM_DEFAULT_BUILD",
"EXPORT_NAME",
- "IMPORTED_LINK_INTERFACE_LANGUAGES",
"IMPORTED",
"NAME",
- "TYPE",
- "VERSION"
+ "TYPE"
};
if (std::binary_search(cmArrayBegin(builtIns),
@@ -1420,9 +1361,7 @@ static bool whiteListedInterfaceProperty(const char *prop)
return true;
}
- if (cmHasLiteralPrefix(prop, "EXCLUDE_FROM_DEFAULT_BUILD_")
- || cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LANGUAGES_")
- || cmHasLiteralPrefix(prop, "MAP_IMPORTED_CONFIG_"))
+ if (cmHasLiteralPrefix(prop, "MAP_IMPORTED_CONFIG_"))
{
return true;
}
@@ -1605,6 +1544,7 @@ void cmTarget::AppendBuildInterfaceIncludes()
if(this->GetType() != cmTarget::SHARED_LIBRARY &&
this->GetType() != cmTarget::STATIC_LIBRARY &&
this->GetType() != cmTarget::MODULE_LIBRARY &&
+ this->GetType() != cmTarget::INTERFACE_LIBRARY &&
!this->IsExecutableWithExports())
{
return;
@@ -2574,6 +2514,8 @@ void cmTarget::GetTargetVersion(bool soversion,
minor = 0;
patch = 0;
+ assert(this->GetType() != INTERFACE_LIBRARY);
+
// Look for a VERSION or SOVERSION property.
const char* prop = soversion? "SOVERSION" : "VERSION";
if(const char* version = this->GetProperty(prop))
@@ -2687,7 +2629,6 @@ const char *cmTarget::GetProperty(const char* prop,
this->GetType() == cmTarget::STATIC_LIBRARY ||
this->GetType() == cmTarget::SHARED_LIBRARY ||
this->GetType() == cmTarget::MODULE_LIBRARY ||
- this->GetType() == cmTarget::INTERFACE_LIBRARY ||
this->GetType() == cmTarget::UNKNOWN_LIBRARY)
{
if(strcmp(prop,"LOCATION") == 0)
@@ -3587,6 +3528,8 @@ void cmTarget::GetLibraryNames(std::string& name,
return;
}
+ assert(this->GetType() != INTERFACE_LIBRARY);
+
// Check for library version properties.
const char* version = this->GetProperty("VERSION");
const char* soversion = this->GetProperty("SOVERSION");
@@ -4162,6 +4105,8 @@ std::string cmTarget::GetOutputName(const char* config, bool implib) const
//----------------------------------------------------------------------------
std::string cmTarget::GetFrameworkVersion() const
{
+ assert(this->GetType() != INTERFACE_LIBRARY);
+
if(const char* fversion = this->GetProperty("FRAMEWORK_VERSION"))
{
return fversion;
@@ -4274,6 +4219,7 @@ std::pair<bool, const char*> consistentNumberProperty(const char *lhs,
const char *rhs,
CompatibleType t)
{
+ char *pEnd;
#if defined(_MSC_VER)
static const char* const null_ptr = 0;
@@ -4281,10 +4227,14 @@ std::pair<bool, const char*> consistentNumberProperty(const char *lhs,
# define null_ptr 0
#endif
- double lnum;
- double rnum;
- if(sscanf(lhs, "%lg", &lnum) != 1 ||
- sscanf(rhs, "%lg", &rnum) != 1)
+ long lnum = strtol(lhs, &pEnd, 0);
+ if (pEnd == lhs || *pEnd != '\0' || errno == ERANGE)
+ {
+ return std::pair<bool, const char*>(false, null_ptr);
+ }
+
+ long rnum = strtol(rhs, &pEnd, 0);
+ if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE)
{
return std::pair<bool, const char*>(false, null_ptr);
}
@@ -5586,9 +5536,6 @@ void cmTarget::ComputeLinkImplementation(const char* config,
LinkImplementation& impl,
cmTarget const* head) const
{
- // Compute which library configuration to link.
- cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config);
-
// Collect libraries directly linked in this configuration.
std::vector<std::string> llibs;
this->GetDirectLinkLibraries(config, llibs, head);
@@ -5681,6 +5628,7 @@ void cmTarget::ComputeLinkImplementation(const char* config,
impl.Libraries.push_back(item);
}
+ cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config);
LinkLibraryVectorType const& oldllibs = this->GetOriginalLinkLibraries();
for(cmTarget::LinkLibraryVectorType::const_iterator li = oldllibs.begin();
li != oldllibs.end(); ++li)
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index e026c59..4916648 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -568,8 +568,6 @@ public:
std::set<cmStdString> const & GetSystemIncludeDirectories() const
{ return this->SystemIncludeDirectories; }
- void FinalizeSystemIncludeDirectories();
-
bool LinkLanguagePropagatesToDependents() const
{ return this->TargetTypeValue == STATIC_LIBRARY; }
diff --git a/Tests/CompatibleInterface/CMakeLists.txt b/Tests/CompatibleInterface/CMakeLists.txt
index 5e64d2a..350b518 100644
--- a/Tests/CompatibleInterface/CMakeLists.txt
+++ b/Tests/CompatibleInterface/CMakeLists.txt
@@ -24,6 +24,8 @@ set_property(TARGET iface1 APPEND PROPERTY
COMPATIBLE_INTERFACE_NUMBER_MIN
NUMBER_MIN_PROP1
NUMBER_MIN_PROP2
+ NUMBER_MIN_PROP3
+ NUMBER_MIN_PROP4
)
set_property(TARGET iface1 APPEND PROPERTY
COMPATIBLE_INTERFACE_NUMBER_MAX
@@ -34,7 +36,7 @@ set_property(TARGET iface1 APPEND PROPERTY
set(CMAKE_DEBUG_TARGET_PROPERTIES
BOOL_PROP1 BOOL_PROP2 BOOL_PROP3 BOOL_PROP4
STRING_PROP1 STRING_PROP2 STRING_PROP3
- NUMBER_MIN_PROP1 NUMBER_MIN_PROP2
+ NUMBER_MIN_PROP1 NUMBER_MIN_PROP2 NUMBER_MIN_PROP3 NUMBER_MIN_PROP4
NUMBER_MAX_PROP1 NUMBER_MAX_PROP2
)
@@ -44,6 +46,8 @@ set_property(TARGET iface1 PROPERTY INTERFACE_STRING_PROP1 prop1)
set_property(TARGET iface1 PROPERTY INTERFACE_STRING_PROP2 prop2)
set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MIN_PROP1 100)
set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MIN_PROP2 200)
+set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MIN_PROP3 0x10)
+set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MIN_PROP4 0x10)
set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MAX_PROP1 100)
set_property(TARGET iface1 PROPERTY INTERFACE_NUMBER_MAX_PROP2 200)
@@ -56,6 +60,8 @@ set_property(TARGET CompatibleInterface PROPERTY STRING_PROP2 prop2)
set_property(TARGET CompatibleInterface PROPERTY STRING_PROP3 prop3)
set_property(TARGET CompatibleInterface PROPERTY NUMBER_MIN_PROP1 50)
set_property(TARGET CompatibleInterface PROPERTY NUMBER_MIN_PROP2 250)
+set_property(TARGET CompatibleInterface PROPERTY NUMBER_MIN_PROP3 0xa)
+set_property(TARGET CompatibleInterface PROPERTY NUMBER_MIN_PROP4 0x1A)
set_property(TARGET CompatibleInterface PROPERTY NUMBER_MAX_PROP1 50)
set_property(TARGET CompatibleInterface PROPERTY NUMBER_MAX_PROP2 250)
@@ -69,6 +75,8 @@ target_compile_definitions(CompatibleInterface
$<$<STREQUAL:$<TARGET_PROPERTY:STRING_PROP3>,prop3>:STRING_PROP3>
$<$<STREQUAL:$<TARGET_PROPERTY:NUMBER_MIN_PROP1>,50>:NUMBER_MIN_PROP1=50>
$<$<STREQUAL:$<TARGET_PROPERTY:NUMBER_MIN_PROP2>,200>:NUMBER_MIN_PROP2=200>
+ $<$<EQUAL:$<TARGET_PROPERTY:NUMBER_MIN_PROP3>,0xA>:NUMBER_MIN_PROP3=0xA>
+ $<$<STREQUAL:$<TARGET_PROPERTY:NUMBER_MIN_PROP4>,0x10>:NUMBER_MIN_PROP4=0x10>
$<$<STREQUAL:$<TARGET_PROPERTY:NUMBER_MAX_PROP1>,100>:NUMBER_MAX_PROP1=100>
$<$<STREQUAL:$<TARGET_PROPERTY:NUMBER_MAX_PROP2>,250>:NUMBER_MAX_PROP2=250>
)
diff --git a/Tests/CompatibleInterface/main.cpp b/Tests/CompatibleInterface/main.cpp
index fa299e9..e23625a 100644
--- a/Tests/CompatibleInterface/main.cpp
+++ b/Tests/CompatibleInterface/main.cpp
@@ -33,7 +33,9 @@ enum {
NumericMaxTest1 = sizeof(CMakeStaticAssert<NUMBER_MAX_PROP1 == 100>),
NumericMaxTest2 = sizeof(CMakeStaticAssert<NUMBER_MAX_PROP2 == 250>),
NumericMinTest1 = sizeof(CMakeStaticAssert<NUMBER_MIN_PROP1 == 50>),
- NumericMinTest2 = sizeof(CMakeStaticAssert<NUMBER_MIN_PROP2 == 200>)
+ NumericMinTest2 = sizeof(CMakeStaticAssert<NUMBER_MIN_PROP2 == 200>),
+ NumericMinTest3 = sizeof(CMakeStaticAssert<NUMBER_MIN_PROP3 == 0xA>),
+ NumericMinTest4 = sizeof(CMakeStaticAssert<NUMBER_MIN_PROP4 == 0x10>)
};
#include "iface2.h"
diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt
index 892f80f..4fb7ecd 100644
--- a/Tests/GeneratorExpression/CMakeLists.txt
+++ b/Tests/GeneratorExpression/CMakeLists.txt
@@ -196,6 +196,27 @@ add_custom_target(check-part3 ALL
-Dlower_case=$<LOWER_CASE:Mi,XeD>
-Dupper_case=$<UPPER_CASE:MiX,eD>
-Dmake_c_identifier=$<MAKE_C_IDENTIFIER:4f,oo:+bar-$>
+ -Dequal1=$<EQUAL:1,2>
+ -Dequal2=$<EQUAL:1,1>
+ -Dequal3=$<EQUAL:0x1,1>
+ -Dequal4=$<EQUAL:0x1,2>
+ -Dequal5=$<EQUAL:0xA,0xa>
+ -Dequal6=$<EQUAL:0xA,10>
+ -Dequal7=$<EQUAL:0xA,012>
+ -Dequal8=$<EQUAL:10,012>
+ -Dequal9=$<EQUAL:10,010>
+ -Dequal10=$<EQUAL:10,0b1010>
+ -Dequal11=$<EQUAL:-10,-0xa>
+ -Dequal12=$<EQUAL:10,+0xa>
+ -Dequal13=$<EQUAL:+10,+0xa>
+ -Dequal14=$<EQUAL:+10,0xa>
+ -Dequal15=$<EQUAL:-10,-0xa>
+ -Dequal16=$<EQUAL:-10,-0b1010>
+ -Dequal17=$<EQUAL:-10,+0b1010>
+ -Dequal18=$<EQUAL:10,+0b1010>
+ -Dequal19=$<EQUAL:10,+012>
+ -Dequal20=$<EQUAL:10,-012>
+ -Dequal21=$<EQUAL:-10,-012>
-P ${CMAKE_CURRENT_SOURCE_DIR}/check-part3.cmake
COMMAND ${CMAKE_COMMAND} -E echo "check done (part 3 of 3)"
VERBATIM
diff --git a/Tests/GeneratorExpression/check-part3.cmake b/Tests/GeneratorExpression/check-part3.cmake
index 3361eeb..2c6bf49 100644
--- a/Tests/GeneratorExpression/check-part3.cmake
+++ b/Tests/GeneratorExpression/check-part3.cmake
@@ -37,3 +37,24 @@ endforeach()
check(lower_case "mi,xed")
check(upper_case "MIX,ED")
check(make_c_identifier "_4f_oo__bar__")
+check(equal1 "0")
+check(equal2 "1")
+check(equal3 "1")
+check(equal4 "0")
+check(equal5 "1")
+check(equal6 "1")
+check(equal7 "1")
+check(equal8 "1")
+check(equal9 "0")
+check(equal10 "1")
+check(equal11 "1")
+check(equal12 "1")
+check(equal13 "1")
+check(equal14 "1")
+check(equal15 "1")
+check(equal16 "1")
+check(equal17 "0")
+check(equal18 "1")
+check(equal19 "1")
+check(equal20 "0")
+check(equal21 "1")
diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt
index 1f5c93b..abe9f74 100644
--- a/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt
+++ b/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt
@@ -25,6 +25,10 @@ add_library(imported_consumer imported_consumer.cpp)
target_link_libraries(imported_consumer iface)
target_compile_options(imported_consumer PRIVATE -Werror=unused-variable)
+add_library(imported_consumer2 imported_consumer.cpp)
+target_link_libraries(imported_consumer2 imported_consumer)
+target_compile_options(imported_consumer2 PRIVATE -Werror=unused-variable)
+
macro(do_try_compile error_option)
set(TC_ARGS
IFACE_TRY_COMPILE_${error_option}
diff --git a/Tests/InterfaceLibrary/CMakeLists.txt b/Tests/InterfaceLibrary/CMakeLists.txt
index 8154ced..b396eb6 100644
--- a/Tests/InterfaceLibrary/CMakeLists.txt
+++ b/Tests/InterfaceLibrary/CMakeLists.txt
@@ -6,13 +6,15 @@ project(InterfaceLibrary)
add_library(iface_nodepends INTERFACE)
target_compile_definitions(iface_nodepends INTERFACE IFACE_DEFINE)
+add_subdirectory(headerdir)
+
add_executable(InterfaceLibrary definetestexe.cpp)
-target_link_libraries(InterfaceLibrary iface_nodepends)
+target_link_libraries(InterfaceLibrary iface_nodepends headeriface)
add_subdirectory(libsdir)
add_executable(sharedlibtestexe sharedlibtestexe.cpp)
-target_link_libraries(sharedlibtestexe shared_iface)
+target_link_libraries(sharedlibtestexe shared_iface imported::iface)
add_library(broken EXCLUDE_FROM_ALL broken.cpp)
diff --git a/Tests/InterfaceLibrary/definetestexe.cpp b/Tests/InterfaceLibrary/definetestexe.cpp
index decd37c..e7a10c1 100644
--- a/Tests/InterfaceLibrary/definetestexe.cpp
+++ b/Tests/InterfaceLibrary/definetestexe.cpp
@@ -3,6 +3,18 @@
#error Expected IFACE_DEFINE
#endif
+#include "iface_header.h"
+
+#ifndef IFACE_HEADER_SRCDIR
+#error Expected IFACE_HEADER_SRCDIR
+#endif
+
+#include "iface_header_builddir.h"
+
+#ifndef IFACE_HEADER_BUILDDIR
+#error Expected IFACE_HEADER_BUILDDIR
+#endif
+
int main(int,char**)
{
return 0;
diff --git a/Tests/InterfaceLibrary/headerdir/CMakeLists.txt b/Tests/InterfaceLibrary/headerdir/CMakeLists.txt
new file mode 100644
index 0000000..98f521e
--- /dev/null
+++ b/Tests/InterfaceLibrary/headerdir/CMakeLists.txt
@@ -0,0 +1,8 @@
+
+set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)
+
+add_library(headeriface INTERFACE)
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/iface_header_builddir.h"
+ "#define IFACE_HEADER_BUILDDIR\n"
+)
diff --git a/Tests/InterfaceLibrary/headerdir/iface_header.h b/Tests/InterfaceLibrary/headerdir/iface_header.h
new file mode 100644
index 0000000..82dd157
--- /dev/null
+++ b/Tests/InterfaceLibrary/headerdir/iface_header.h
@@ -0,0 +1 @@
+#define IFACE_HEADER_SRCDIR
diff --git a/Tests/InterfaceLibrary/libsdir/CMakeLists.txt b/Tests/InterfaceLibrary/libsdir/CMakeLists.txt
index 6999646..4e529df 100644
--- a/Tests/InterfaceLibrary/libsdir/CMakeLists.txt
+++ b/Tests/InterfaceLibrary/libsdir/CMakeLists.txt
@@ -24,3 +24,5 @@ target_compile_definitions(shareddependlib
add_library(shared_iface INTERFACE)
target_link_libraries(shared_iface INTERFACE sharedlib)
+
+add_library(imported::iface INTERFACE IMPORTED GLOBAL)
diff --git a/Tests/RunCMake/include/ExportExportInclude-result.txt b/Tests/RunCMake/include/ExportExportInclude-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/include/ExportExportInclude-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/include/ExportExportInclude-stderr.txt b/Tests/RunCMake/include/ExportExportInclude-stderr.txt
new file mode 100644
index 0000000..70d013c
--- /dev/null
+++ b/Tests/RunCMake/include/ExportExportInclude-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error at ExportExportInclude.cmake:6 \(include\):
+ include could not find load file:
+
+ .*/Tests/RunCMake/include/ExportExportInclude-build/theTargets.cmake
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/include/ExportExportInclude.cmake b/Tests/RunCMake/include/ExportExportInclude.cmake
new file mode 100644
index 0000000..14e5d91
--- /dev/null
+++ b/Tests/RunCMake/include/ExportExportInclude.cmake
@@ -0,0 +1,6 @@
+
+add_library(iface INTERFACE)
+install(TARGETS iface EXPORT ifaceExport)
+
+export(EXPORT ifaceExport FILE "${CMAKE_CURRENT_BINARY_DIR}/theTargets.cmake")
+include("${CMAKE_CURRENT_BINARY_DIR}/theTargets.cmake")
diff --git a/Tests/RunCMake/include/RunCMakeTest.cmake b/Tests/RunCMake/include/RunCMakeTest.cmake
index 7fc9a12..bea7d5c 100644
--- a/Tests/RunCMake/include/RunCMakeTest.cmake
+++ b/Tests/RunCMake/include/RunCMakeTest.cmake
@@ -4,3 +4,4 @@ run_cmake(EmptyString)
run_cmake(EmptyStringOptional)
run_cmake(CMP0024-WARN)
run_cmake(CMP0024-NEW)
+run_cmake(ExportExportInclude)
diff --git a/Tests/RunCMake/interface_library/RunCMakeTest.cmake b/Tests/RunCMake/interface_library/RunCMakeTest.cmake
index d76600c..9ca9a77 100644
--- a/Tests/RunCMake/interface_library/RunCMakeTest.cmake
+++ b/Tests/RunCMake/interface_library/RunCMakeTest.cmake
@@ -4,5 +4,6 @@ run_cmake(invalid_name)
run_cmake(target_commands)
run_cmake(no_shared_libs)
run_cmake(whitelist)
+run_cmake(invalid_signature)
run_cmake(genex_link)
run_cmake(add_dependencies)
diff --git a/Tests/RunCMake/interface_library/invalid_signature-result.txt b/Tests/RunCMake/interface_library/invalid_signature-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/interface_library/invalid_signature-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/interface_library/invalid_signature-stderr.txt b/Tests/RunCMake/interface_library/invalid_signature-stderr.txt
new file mode 100644
index 0000000..701586a
--- /dev/null
+++ b/Tests/RunCMake/interface_library/invalid_signature-stderr.txt
@@ -0,0 +1,89 @@
+CMake Error at invalid_signature.cmake:2 \(add_library\):
+ add_library INTERFACE library requires no source arguments.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at invalid_signature.cmake:3 \(add_library\):
+ add_library INTERFACE library specified with conflicting/multiple types.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at invalid_signature.cmake:4 \(add_library\):
+ add_library INTERFACE library specified with conflicting/multiple types.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at invalid_signature.cmake:5 \(add_library\):
+ add_library INTERFACE library specified with conflicting/multiple types.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at invalid_signature.cmake:6 \(add_library\):
+ add_library INTERFACE library specified with conflicting/multiple types.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at invalid_signature.cmake:7 \(add_library\):
+ add_library INTERFACE library specified with conflicting/multiple types.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at invalid_signature.cmake:8 \(add_library\):
+ add_library INTERFACE library specified with conflicting/multiple types.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at invalid_signature.cmake:9 \(add_library\):
+ add_library INTERFACE library specified with conflicting STATIC type.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at invalid_signature.cmake:10 \(add_library\):
+ add_library INTERFACE library specified with conflicting SHARED type.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at invalid_signature.cmake:11 \(add_library\):
+ add_library INTERFACE library specified with conflicting MODULE type.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at invalid_signature.cmake:12 \(add_library\):
+ add_library INTERFACE library specified with conflicting OBJECT type.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at invalid_signature.cmake:13 \(add_library\):
+ add_library INTERFACE library specified with conflicting UNKNOWN type.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at invalid_signature.cmake:14 \(add_library\):
+ add_library INTERFACE library specified with conflicting ALIAS type.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at invalid_signature.cmake:15 \(add_library\):
+ add_library INTERFACE library specified with conflicting ALIAS type.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at invalid_signature.cmake:16 \(add_library\):
+ add_library INTERFACE library specified with conflicting/multiple types.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at invalid_signature.cmake:17 \(add_library\):
+ add_library INTERFACE library may not be used with EXCLUDE_FROM_ALL.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at invalid_signature.cmake:18 \(add_library\):
+ add_library INTERFACE library may not be used with EXCLUDE_FROM_ALL.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at invalid_signature.cmake:20 \(add_library\):
+ add_library INTERFACE library requires no source arguments.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/interface_library/invalid_signature.cmake b/Tests/RunCMake/interface_library/invalid_signature.cmake
new file mode 100644
index 0000000..67e3267
--- /dev/null
+++ b/Tests/RunCMake/interface_library/invalid_signature.cmake
@@ -0,0 +1,20 @@
+
+add_library(iface1 INTERFACE empty.cpp)
+add_library(iface3 STATIC INTERFACE)
+add_library(iface4 STATIC INTERFACE empty.cpp)
+add_library(iface5 SHARED INTERFACE)
+add_library(iface6 MODULE INTERFACE)
+add_library(iface7 OBJECT INTERFACE)
+add_library(iface8 UNKNOWN INTERFACE)
+add_library(iface9 INTERFACE STATIC)
+add_library(iface10 INTERFACE SHARED)
+add_library(iface11 INTERFACE MODULE)
+add_library(iface12 INTERFACE OBJECT)
+add_library(iface13 INTERFACE UNKNOWN)
+add_library(iface14 INTERFACE ALIAS)
+add_library(iface15 ALIAS INTERFACE)
+add_library(iface16 INTERFACE INTERFACE)
+add_library(iface17 INTERFACE EXCLUDE_FROM_ALL)
+add_library(iface18 EXCLUDE_FROM_ALL INTERFACE)
+add_library(iface19 GLOBAL INTERFACE)
+add_library(iface20 INTERFACE GLOBAL)