diff options
-rw-r--r-- | Source/CMakeVersion.cmake | 2 | ||||
-rw-r--r-- | Source/cmDocumentGeneratorExpressions.h | 1 | ||||
-rw-r--r-- | Source/cmGeneratorExpressionEvaluator.cxx | 18 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 83 | ||||
-rw-r--r-- | Source/cmTarget.h | 2 | ||||
-rw-r--r-- | Source/cmTargetCompileDefinitionsCommand.h | 3 | ||||
-rw-r--r-- | Source/cmTargetIncludeDirectoriesCommand.h | 3 | ||||
-rw-r--r-- | Source/cmTargetLinkLibrariesCommand.h | 7 | ||||
-rw-r--r-- | Source/cmTargetPropCommandBase.h | 1 | ||||
-rw-r--r-- | Source/cmake.cxx | 13 | ||||
-rw-r--r-- | Source/cmake.h | 2 | ||||
-rw-r--r-- | Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt | 2 | ||||
-rw-r--r-- | Tests/CMakeCommands/target_compile_definitions/consumer.cpp | 8 |
13 files changed, 144 insertions, 1 deletions
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index c71ba21..1e7fe50 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 10) -set(CMake_VERSION_TWEAK 20130111) +set(CMake_VERSION_TWEAK 20130115) #set(CMake_VERSION_RC 1) diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h index b8889ac..fa21907 100644 --- a/Source/cmDocumentGeneratorExpressions.h +++ b/Source/cmDocumentGeneratorExpressions.h @@ -37,6 +37,7 @@ "target in the same buildsystem. Expands to the empty string " \ "otherwise.\n" \ " $<TARGET_FILE:tgt> = main file (.exe, .so.1.2, .a)\n" \ + " $<TARGET_DEFINED:tgt> = '1' if tgt is a target, else '0'\n" \ " $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n" \ " $<TARGET_SONAME_FILE:tgt> = file with soname (.so.3)\n" \ "where \"tgt\" is the name of a target. " \ diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index f4e4131..8e40815a 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -289,6 +289,22 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode } configurationTestNode; +static const struct TargetDefinedNode : public cmGeneratorExpressionNode +{ + TargetDefinedNode() {} + + virtual int NumExpectedParameters() const { return 1; } + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *, + cmGeneratorExpressionDAGChecker *) const + { + return context->Makefile->FindTargetToUse(parameters.front().c_str()) + ? "1" : "0"; + } +} targetDefinedNode; + //---------------------------------------------------------------------------- static const char* targetPropertyTransitiveWhitelist[] = { "INTERFACE_INCLUDE_DIRECTORIES" @@ -702,6 +718,8 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier) return &buildInterfaceNode; else if (identifier == "INSTALL_INTERFACE") return &installInterfaceNode; + else if (identifier == "TARGET_DEFINED") + return &targetDefinedNode; return 0; } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 9b50b8e..6f68140 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -892,6 +892,19 @@ void cmTarget::DefineProperties(cmake *cm) "requirement for their INTERFACE_POSITION_INDEPENDENT_CODE property."); cm->DefineProperty + ("COMPATIBLE_INTERFACE_BOOL", cmProperty::TARGET, + "Properties which must be compatible with their link interface", + "The COMPATIBLE_INTERFACE_BOOL property may contain a list of properties" + "for this target which must be consistent when evaluated as a boolean " + "in the INTERFACE of all linked dependencies. For example, if a " + "property \"FOO\" appears in the list, then the \"INTERFACE_FOO\" " + "property content in all dependencies must be consistent with each " + "other, and with the \"FOO\" property in this target. " + "Consistency in this sense has the meaning that if the property is set," + "then it must have the same boolean value as all others, and if the " + "property is not set, then it is ignored."); + + cm->DefineProperty ("POST_INSTALL_SCRIPT", cmProperty::TARGET, "Deprecated install support.", "The PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT properties are the " @@ -2233,6 +2246,14 @@ static std::string targetNameGenex(const char *lib) } //---------------------------------------------------------------------------- +static bool isGeneratorExpression(const std::string &lib) +{ + const std::string::size_type openpos = lib.find("$<"); + return (openpos != std::string::npos) + && (lib.find(">", openpos) != std::string::npos); +} + +//---------------------------------------------------------------------------- void cmTarget::AddLinkLibrary(cmMakefile& mf, const char *target, const char* lib, LinkLibraryType llt) @@ -2254,6 +2275,11 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, llt).c_str()); } + if (isGeneratorExpression(lib)) + { + return; + } + cmTarget::LibraryID tmp; tmp.first = lib; tmp.second = llt; @@ -5299,6 +5325,58 @@ std::string cmTarget::CheckCMP0004(std::string const& item) } //---------------------------------------------------------------------------- +void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, + const char* config) +{ + const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); + + std::set<cmStdString> emitted; + + for(cmComputeLinkInformation::ItemVector::const_iterator li = + deps.begin(); + li != deps.end(); ++li) + { + if (!li->Target) + { + continue; + } + const char *prop = li->Target->GetProperty("COMPATIBLE_INTERFACE_BOOL"); + if (!prop) + { + continue; + } + + std::vector<std::string> props; + cmSystemTools::ExpandListArgument(prop, props); + + for(std::vector<std::string>::iterator pi = props.begin(); + pi != props.end(); ++pi) + { + if (this->Makefile->GetCMakeInstance() + ->GetIsPropertyDefined(pi->c_str(), + cmProperty::TARGET)) + { + cmOStringStream e; + e << "Target \"" << li->Target->GetName() << "\" has property \"" + << *pi << "\" listed in its COMPATIBLE_INTERFACE_BOOL property. " + "This is not allowed. Only user-defined properties may appear " + "listed in the COMPATIBLE_INTERFACE_BOOL property."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } + if(emitted.insert(*pi).second) + { + this->GetLinkInterfaceDependentBoolProperty(*pi, config); + if (cmSystemTools::GetErrorOccuredFlag()) + { + return; + } + } + } + } +} + +//---------------------------------------------------------------------------- cmComputeLinkInformation* cmTarget::GetLinkInformation(const char* config, cmTarget *head) { @@ -5319,6 +5397,11 @@ cmTarget::GetLinkInformation(const char* config, cmTarget *head) info = 0; } + if (info) + { + this->CheckPropertyCompatibility(info, config); + } + // Store the information for this configuration. cmTargetLinkInformationMap::value_type entry(key, info); i = this->LinkInformation.insert(entry).first; diff --git a/Source/cmTarget.h b/Source/cmTarget.h index b4d053d..0963c5c 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -626,6 +626,8 @@ private: cmTarget *head); cmTargetLinkInformationMap LinkInformation; + void CheckPropertyCompatibility(cmComputeLinkInformation *info, + const char* config); bool ComputeLinkInterface(const char* config, LinkInterface& iface, cmTarget *head); diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h index 707610e..4b066b7a 100644 --- a/Source/cmTargetCompileDefinitionsCommand.h +++ b/Source/cmTargetCompileDefinitionsCommand.h @@ -69,6 +69,9 @@ public: "INTERFACE_COMPILE_DEFINITIONS from. " "Repeated calls for the same <target> append items in the order called." "\n" + "Arguments to target_compile_definitions may use \"generator " + "expressions\" with the syntax \"$<...>\". " + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS ; } diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h index c1957d6..90e039c 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.h +++ b/Source/cmTargetIncludeDirectoriesCommand.h @@ -73,6 +73,9 @@ public: "directories must be absolute paths, not relative paths. " "Repeated calls for the same <target> append items in the order called." "\n" + "Arguments to target_include_directories may use \"generator " + "expressions\" with the syntax \"$<...>\". " + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS ; } diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h index 8e5823c..34fe54c 100644 --- a/Source/cmTargetLinkLibrariesCommand.h +++ b/Source/cmTargetLinkLibrariesCommand.h @@ -13,6 +13,7 @@ #define cmTargetLinkLibrariesCommand_h #include "cmCommand.h" +#include "cmDocumentGeneratorExpressions.h" /** \class cmTargetLinkLibrariesCommand * \brief Specify a list of libraries to link into executables. @@ -141,6 +142,12 @@ public: "However, if two archives are really so interdependent they should " "probably be combined into a single archive." ")" + "\n" + "Arguments to target_link_libraries may use \"generator expressions\" " + "with the syntax \"$<...>\". Note however, that generator expressions " + "will not be used in OLD handling of CMP0003 or CMP0004." + "\n" + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS ; } diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h index 90e3bbb..e757f9d 100644 --- a/Source/cmTargetPropCommandBase.h +++ b/Source/cmTargetPropCommandBase.h @@ -14,6 +14,7 @@ #define cmTargetPropCommandBase_h #include "cmCommand.h" +#include "cmDocumentGeneratorExpressions.h" class cmTarget; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index a44c825..2eecfba 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -3299,6 +3299,12 @@ int cmake::ExecuteLinkScript(std::vector<std::string>& args) int result = 0; while(result == 0 && cmSystemTools::GetLineFromStream(fin, command)) { + // Skip empty command lines. + if(command.find_first_not_of(" \t") == command.npos) + { + continue; + } + // Setup this command line. const char* cmd[2] = {command.c_str(), 0}; cmsysProcess_SetCommand(cp, cmd); @@ -3552,6 +3558,13 @@ void cmake::DefineProperty(const char *name, cmProperty::ScopeType scope, chained); } +bool cmake::GetIsPropertyDefined(const char *name, + cmProperty::ScopeType scope) +{ + return this->PropertyDefinitions[scope].find(name) != + this->PropertyDefinitions[scope].end(); +} + cmPropertyDefinition *cmake ::GetPropertyDefinition(const char *name, cmProperty::ScopeType scope) diff --git a/Source/cmake.h b/Source/cmake.h index e5aa076..f6fe0d6 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -341,6 +341,8 @@ class cmake bool chain = false, const char *variableGroup = 0); + bool GetIsPropertyDefined(const char *name, cmProperty::ScopeType scope); + // get property definition cmPropertyDefinition *GetPropertyDefinition (const char *name, cmProperty::ScopeType scope); diff --git a/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt b/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt index 84a23ef..a37c597 100644 --- a/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt +++ b/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt @@ -23,4 +23,6 @@ add_executable(consumer target_compile_definitions(consumer PRIVATE target_compile_definitions importedlib + $<$<TARGET_DEFINED:notdefined>:SHOULD_NOT_BE_DEFINED> + $<$<TARGET_DEFINED:importedlib>:SHOULD_BE_DEFINED> ) diff --git a/Tests/CMakeCommands/target_compile_definitions/consumer.cpp b/Tests/CMakeCommands/target_compile_definitions/consumer.cpp index e3788dd..1ef657d 100644 --- a/Tests/CMakeCommands/target_compile_definitions/consumer.cpp +++ b/Tests/CMakeCommands/target_compile_definitions/consumer.cpp @@ -15,4 +15,12 @@ #error Expected MY_IMPORTEDINTERFACE_DEFINE #endif +#ifdef SHOULD_NOT_BE_DEFINED +#error Unexpected SHOULD_NOT_BE_DEFINED +#endif + +#ifndef SHOULD_BE_DEFINED +#error Expected SHOULD_BE_DEFINED +#endif + int main() { return 0; } |