From 2d6638008c2aeba6015d45160e52d78d92daf57d Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 26 Dec 2013 16:04:58 +0100 Subject: cmTarget: Use strtol for numeric parsing. On Windows apparently sscanf can not handle hex numbers. Test that numeric comparison works with hex numbers. --- Source/cmTarget.cxx | 14 ++++++++++---- Tests/CompatibleInterface/CMakeLists.txt | 10 +++++++++- Tests/CompatibleInterface/main.cpp | 4 +++- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index ead48b9..472f87d 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -24,6 +24,7 @@ #include #include // required for atof #include +#include const char* cmTarget::GetTargetTypeName(TargetType targetType) { @@ -4274,6 +4275,7 @@ std::pair consistentNumberProperty(const char *lhs, const char *rhs, CompatibleType t) { + char *pEnd; #if defined(_MSC_VER) static const char* const null_ptr = 0; @@ -4281,10 +4283,14 @@ std::pair 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(false, null_ptr); + } + + long rnum = strtol(rhs, &pEnd, 0); + if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE) { return std::pair(false, null_ptr); } diff --git a/Tests/CompatibleInterface/CMakeLists.txt b/Tests/CompatibleInterface/CMakeLists.txt index 5e64d2a..47e974a 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 $<$,prop3>:STRING_PROP3> $<$,50>:NUMBER_MIN_PROP1=50> $<$,200>:NUMBER_MIN_PROP2=200> + $<$,0xA>:NUMBER_MIN_PROP3=0xA> + $<$,0x10>:NUMBER_MIN_PROP4=0x10> $<$,100>:NUMBER_MAX_PROP1=100> $<$,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), NumericMaxTest2 = sizeof(CMakeStaticAssert), NumericMinTest1 = sizeof(CMakeStaticAssert), - NumericMinTest2 = sizeof(CMakeStaticAssert) + NumericMinTest2 = sizeof(CMakeStaticAssert), + NumericMinTest3 = sizeof(CMakeStaticAssert), + NumericMinTest4 = sizeof(CMakeStaticAssert) }; #include "iface2.h" -- cgit v0.12 From 2af966d9ab37cb22bd6173f938e83cc710923c3c Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 27 Dec 2013 12:42:37 +0100 Subject: Genex: Add EQUAL expression. Support decimal, hex, octal and binary literals. --- Help/manual/cmake-generator-expressions.7.rst | 2 + Source/cmGeneratorExpressionEvaluator.cxx | 89 +++++++++++++++++++++++++++ Tests/CompatibleInterface/CMakeLists.txt | 4 +- Tests/GeneratorExpression/CMakeLists.txt | 21 +++++++ Tests/GeneratorExpression/check-part3.cmake | 21 +++++++ 5 files changed, 135 insertions(+), 2 deletions(-) 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`` ``$`` ``1`` if ``a`` is STREQUAL ``b``, else ``0`` +``$`` + ``1`` if ``a`` is EQUAL ``b`` in a numeric comparison, else ``0`` ``$`` ``1`` if config is ``cfg``, else ``0``. This is a case-insensitive comparison. The mapping in :prop_tgt:`MAP_IMPORTED_CONFIG_` is also considered by diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index c8010d0..83d341e 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -19,6 +19,7 @@ #include #include +#include //---------------------------------------------------------------------------- #if !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x510 @@ -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 ¶meters, + 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(), + "$ 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(), + "$ 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() {} @@ -1492,6 +1579,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") diff --git a/Tests/CompatibleInterface/CMakeLists.txt b/Tests/CompatibleInterface/CMakeLists.txt index 47e974a..350b518 100644 --- a/Tests/CompatibleInterface/CMakeLists.txt +++ b/Tests/CompatibleInterface/CMakeLists.txt @@ -60,7 +60,7 @@ 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_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) @@ -75,7 +75,7 @@ target_compile_definitions(CompatibleInterface $<$,prop3>:STRING_PROP3> $<$,50>:NUMBER_MIN_PROP1=50> $<$,200>:NUMBER_MIN_PROP2=200> - $<$,0xA>:NUMBER_MIN_PROP3=0xA> + $<$,0xA>:NUMBER_MIN_PROP3=0xA> $<$,0x10>:NUMBER_MIN_PROP4=0x10> $<$,100>:NUMBER_MAX_PROP1=100> $<$,250>:NUMBER_MAX_PROP2=250> 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=$ -Dupper_case=$ -Dmake_c_identifier=$ + -Dequal1=$ + -Dequal2=$ + -Dequal3=$ + -Dequal4=$ + -Dequal5=$ + -Dequal6=$ + -Dequal7=$ + -Dequal8=$ + -Dequal9=$ + -Dequal10=$ + -Dequal11=$ + -Dequal12=$ + -Dequal13=$ + -Dequal14=$ + -Dequal15=$ + -Dequal16=$ + -Dequal17=$ + -Dequal18=$ + -Dequal19=$ + -Dequal20=$ + -Dequal21=$ -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") -- cgit v0.12 From 7fc6e3d607c79c1124b2ac93fac0dcddc326ef66 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 30 Dec 2013 20:35:15 +0100 Subject: cmTarget: Remove dead code. Whitelisting of properties already ensures that the LOCATION property will not be read from an INTERFACE_LIBRARY. --- Source/cmTarget.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 472f87d..b51ea2a 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -2688,7 +2688,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) -- cgit v0.12 From 7461d67cf37a40ce5a6c20e8eaf4cbfff1c7d27e Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 30 Dec 2013 14:35:08 +0100 Subject: cmTarget: Enable convenient include dir handling for INTERFACE_LIBRARY. Make the CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE variable affect INTERFACE_LIBRARY targets. --- Source/cmGlobalGenerator.cxx | 4 ++-- Source/cmTarget.cxx | 1 + Tests/InterfaceLibrary/CMakeLists.txt | 4 +++- Tests/InterfaceLibrary/definetestexe.cpp | 12 ++++++++++++ Tests/InterfaceLibrary/headerdir/CMakeLists.txt | 8 ++++++++ Tests/InterfaceLibrary/headerdir/iface_header.h | 1 + 6 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 Tests/InterfaceLibrary/headerdir/CMakeLists.txt create mode 100644 Tests/InterfaceLibrary/headerdir/iface_header.h diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 3b858af..0b58a45 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1337,13 +1337,13 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo() { cmTarget* t = &ti->second; + t->AppendBuildInterfaceIncludes(); + if (t->GetType() == cmTarget::INTERFACE_LIBRARY) { continue; } - t->AppendBuildInterfaceIncludes(); - for (std::vector::const_iterator it = noconfig_compile_definitions.begin(); it != noconfig_compile_definitions.end(); ++it) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index b51ea2a..91bd90f 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1606,6 +1606,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; diff --git a/Tests/InterfaceLibrary/CMakeLists.txt b/Tests/InterfaceLibrary/CMakeLists.txt index 8154ced..396a84a 100644 --- a/Tests/InterfaceLibrary/CMakeLists.txt +++ b/Tests/InterfaceLibrary/CMakeLists.txt @@ -6,8 +6,10 @@ 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) 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 -- cgit v0.12 From 3429541e1c853207ae77ac033f04888e6c84ebf8 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 30 Dec 2013 22:01:02 +0100 Subject: export: Rename some variables to reflect content type. This method is used with a list of languages. --- Source/cmExportFileGenerator.cxx | 18 +++++++++--------- Source/cmExportFileGenerator.h | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) 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 const& libs, + std::vector const& entries, ImportPropertyMap& properties, std::vector& 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::const_iterator li = libs.begin(); - li != libs.end(); ++li) + for(std::vector::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& missingTargets); void SetImportLinkProperty(std::string const& suffix, cmTarget* target, const char* propName, - std::vector const& libs, + std::vector const& entries, ImportPropertyMap& properties, std::vector& missingTargets); -- cgit v0.12 From 61d138aea2df9df2da7fa817b47131c73557fbdb Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 30 Dec 2013 22:12:30 +0100 Subject: cmTarget: INTERFACE_LIBRARY is always EXCLUDE_FROM_ALL. --- Source/cmGlobalGenerator.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 0b58a45..0a56771 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1908,7 +1908,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; -- cgit v0.12 From fa651c7a198d5c20e2bcb06df4673ec1a270d4d3 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 30 Dec 2013 22:05:55 +0100 Subject: cmTarget: Remove some of the INTERFACE_LIBRARY whitelisted properties. There is no need to allow EXCLUDE_* properties, because an INTERFACE_LIBRARY has no direct build output. IMPORTED_LINK_INTERFACE_LANGUAGES are relevant only to static libraries. VERSION is relevant only to the filename of direct build outputs, which INTERFACE_LIBRARY does not have. --- Source/cmGlobalXCodeGenerator.cxx | 3 ++- Source/cmTarget.cxx | 16 ++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) 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 91bd90f..3d1a4d4 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1403,14 +1403,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), @@ -1421,9 +1417,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; } @@ -2576,6 +2570,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)) @@ -3588,6 +3584,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"); @@ -4163,6 +4161,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; -- cgit v0.12 From 9ba47ee49b41569555f0ef85d7a5fce7ad09f0dc Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 31 Dec 2013 14:28:52 +0100 Subject: Genex: Reform error-checking for nullary/unary expressions. The error messages were incorrect (reporting that the expression requires one or two parameters), and repeated. Remove the now-unused ZeroOrMoreParameters enum value. --- Source/cmGeneratorExpressionEvaluator.cxx | 39 ++++++++----------------------- 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 83d341e..1ddafca 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -49,7 +49,7 @@ struct cmGeneratorExpressionNode enum { DynamicParameters = 0, OneOrMoreParameters = -1, - ZeroOrMoreParameters = -2 + OneOrZeroParameters = -2 }; virtual ~cmGeneratorExpressionNode() {} @@ -384,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 ¶meters, cmGeneratorExpressionContext *context, @@ -430,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(), - "$ expression requires one or two parameters"); - return std::string(); - } if (!context->HeadTarget) { reportError(context, content->GetOriginalExpression(), @@ -458,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(), - "$ expression requires one or two parameters"); - return std::string(); - } if (!context->HeadTarget) { reportError(context, content->GetOriginalExpression(), @@ -481,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 ¶meters, cmGeneratorExpressionContext *context, @@ -526,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(), - "$ expression requires one or two parameters"); - return std::string(); - } if (!context->HeadTarget) { reportError(context, content->GetOriginalExpression(), @@ -554,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(), - "$ expression requires one or two " - "parameters"); - return std::string(); - } if (!context->HeadTarget) { reportError(context, content->GetOriginalExpression(), @@ -579,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 ¶meters, cmGeneratorExpressionContext *context, @@ -1822,6 +1797,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(); } -- cgit v0.12 From 0f3e8e957f20c0e7c2ad4da326c073c94d7a5816 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 31 Dec 2013 14:34:16 +0100 Subject: Undefine local preprocessor loop variables. Most occurances of this pattern already contain the undef, so add it to the rest too. --- Source/cmExportTryCompileFileGenerator.cxx | 2 ++ Source/cmGeneratorExpressionDAGChecker.cxx | 1 + Source/cmGeneratorExpressionDAGChecker.h | 4 +++- Source/cmGeneratorExpressionEvaluator.cxx | 3 +++ 4 files changed, 9 insertions(+), 1 deletion(-) 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..84d7735 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 >::const_iterator it = top->Seen.find(target); 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 1ddafca..f0e40ea 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -772,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 &libraries, cmTarget const* target, cmTarget const* headTarget, @@ -999,6 +1001,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode ASSERT_TRANSITIVE_PROPERTY_METHOD) false); } +#undef ASSERT_TRANSITIVE_PROPERTY_METHOD } std::string linkedTargetsContent; -- cgit v0.12 From 10d65d50195e0183120e102c043cc9c96a16a36b Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 31 Dec 2013 14:35:14 +0100 Subject: cmTarget: Move a variable initialization closer to where it is used. This is more readable and easier to reason about. --- Source/cmTarget.cxx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 3d1a4d4..4b7bd3b 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -5592,9 +5592,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 llibs; this->GetDirectLinkLibraries(config, llibs, head); @@ -5687,6 +5684,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) -- cgit v0.12 From 9eb06d0dde52203d3f8ac91ea9a1c5396a09f8af Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 31 Dec 2013 14:52:07 +0100 Subject: add_library: Disallow invalid signatures for INTERFACE_LIBRARY. Document the valid signatures. Add a test for the IMPORTED GLOBAL signature. --- Help/command/add_library.rst | 17 ++++- Source/cmAddLibraryCommand.cxx | 88 +++++++++++++++++++++ Tests/InterfaceLibrary/CMakeLists.txt | 2 +- Tests/InterfaceLibrary/libsdir/CMakeLists.txt | 2 + .../RunCMake/interface_library/RunCMakeTest.cmake | 1 + .../interface_library/invalid_signature-result.txt | 1 + .../interface_library/invalid_signature-stderr.txt | 89 ++++++++++++++++++++++ .../interface_library/invalid_signature.cmake | 20 +++++ 8 files changed, 215 insertions(+), 5 deletions(-) create mode 100644 Tests/RunCMake/interface_library/invalid_signature-result.txt create mode 100644 Tests/RunCMake/interface_library/invalid_signature-stderr.txt create mode 100644 Tests/RunCMake/interface_library/invalid_signature.cmake 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( INTERFACE) + add_library( 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/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/Tests/InterfaceLibrary/CMakeLists.txt b/Tests/InterfaceLibrary/CMakeLists.txt index 396a84a..b396eb6 100644 --- a/Tests/InterfaceLibrary/CMakeLists.txt +++ b/Tests/InterfaceLibrary/CMakeLists.txt @@ -14,7 +14,7 @@ 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/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/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) -- cgit v0.12 From faedd2bea9c98fddd9e9f70deebdb53f8f369124 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 1 Jan 2014 15:49:05 +0100 Subject: cmTarget: Fix system include annotation propagation. Direct users of IMPORTED targets treat INTERFACE_INCLUDE_DIRECTORIES as SYSTEM, after commit a63fcbcb (Always consider includes from IMPORTED targets to be SYSTEM., 2013-08-29). It was intended that transitive use of an IMPORTED target would have the same behavior, but that did not work. The implementation processed only direct dependencies in cmTarget::FinalizeSystemIncludeDirectories. Implement transitive evaluation of dependencies by traversing the link interface of each target in the link implementation. --- Source/cmGeneratorExpressionDAGChecker.cxx | 3 +- Source/cmGeneratorTarget.cxx | 113 ++++++++++++++++++--- Source/cmGlobalGenerator.cxx | 11 -- Source/cmTarget.cxx | 56 ---------- Source/cmTarget.h | 2 - .../SystemIncludeDirectories/CMakeLists.txt | 4 + 6 files changed, 105 insertions(+), 84 deletions(-) diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 84d7735..c2c4e20 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -192,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/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 +#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& 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 result; for (std::set::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 uniqueDeps; + for(std::vector::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 deps; + tgt->GetTransitivePropertyLinkLibraries(config, this->Target, deps); + + for(std::vector::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 unique; for(std::vector::iterator li = result.begin(); li != result.end(); ++li) { cmSystemTools::ConvertToUnixSlashes(*li); + unique.insert(*li); + } + result.clear(); + for(std::set::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 0a56771..226a45a 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1164,17 +1164,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) { diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 4b7bd3b..b06480b 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1042,62 +1042,6 @@ cmTarget::AddSystemIncludeDirectories(const std::vector &incs) } //---------------------------------------------------------------------------- -void cmTarget::FinalizeSystemIncludeDirectories() -{ - for (std::vector::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 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 = "$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 = "$<$Value + ">:" + includeGenex + ">"; - } - this->SystemIncludeDirectories.insert(includeGenex); - return; // The INTERFACE_SYSTEM_INCLUDE_DIRECTORIES are a subset - // of the INTERFACE_INCLUDE_DIRECTORIES - } - } - std::string includeGenex = "$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 = "$<$Value + ">:" + includeGenex + ">"; - } - this->SystemIncludeDirectories.insert(includeGenex); - } -} - -//---------------------------------------------------------------------------- void cmTarget::AnalyzeLibDependencies( const cmMakefile& mf ) { 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 const & GetSystemIncludeDirectories() const { return this->SystemIncludeDirectories; } - void FinalizeSystemIncludeDirectories(); - bool LinkLanguagePropagatesToDependents() const { return this->TargetTypeValue == STATIC_LIBRARY; } 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} -- cgit v0.12 From 84fac67f90b275116efa9ec25f5fcb2c2bf7f6b4 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 26 Dec 2013 14:34:27 +0100 Subject: Don't allow include() of export(EXPORT) file at configure time. As a new feature it does not need to participate in CMP0024. Store cmExportBuildFileGenerator instances which correspond to the export(EXPORT) signature in a second map which does not own the pointers. This avoids the need to add cmExportBuildFileGenerator and dependencies to the bootstrap system. --- Source/cmExportCommand.cxx | 10 ++++++++-- Source/cmGlobalGenerator.cxx | 14 +++++++++++++- Source/cmGlobalGenerator.h | 2 ++ Tests/RunCMake/include/ExportExportInclude-result.txt | 1 + Tests/RunCMake/include/ExportExportInclude-stderr.txt | 6 ++++++ Tests/RunCMake/include/ExportExportInclude.cmake | 6 ++++++ Tests/RunCMake/include/RunCMakeTest.cmake | 1 + 7 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 Tests/RunCMake/include/ExportExportInclude-result.txt create mode 100644 Tests/RunCMake/include/ExportExportInclude-stderr.txt create mode 100644 Tests/RunCMake/include/ExportExportInclude.cmake 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/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 226a45a..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::iterator it @@ -207,7 +214,12 @@ cmGlobalGenerator::IsExportedTargetsFile(const std::string &filename) const { const std::map::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 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& 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 BuildExportSets; + std::map BuildExportExportSets; // Manifest of all targets that will be built for each configuration. // This is computed just before local generators generate. 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) -- cgit v0.12