From b8357db11d96eeb995b8443404e46466a493ab15 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 17 Jan 2008 15:54:49 -0500 Subject: ENH: Rename SET_PROPERITES command to SET_PROPERTY and give it a more powerful signature. --- Modules/CMakeGenericSystem.cmake | 2 +- Modules/FeatureSummary.cmake | 6 +- Modules/Platform/BlueGeneL.cmake | 2 +- Modules/Platform/Catamount.cmake | 2 +- Modules/Platform/Generic.cmake | 3 +- Modules/Platform/Linux.cmake | 2 +- Modules/Platform/UnixPaths.cmake | 2 +- Modules/Platform/eCos.cmake | 2 +- Source/cmBootstrapCommands.cxx | 4 +- Source/cmSetPropertiesCommand.cxx | 210 -------------------- Source/cmSetPropertiesCommand.h | 74 ------- Source/cmSetPropertyCommand.cxx | 408 ++++++++++++++++++++++++++++++++++++++ Source/cmSetPropertyCommand.h | 112 +++++++++++ Tests/DocTest/CMakeLists.txt | 2 +- Tests/Properties/CMakeLists.txt | 9 +- 15 files changed, 537 insertions(+), 303 deletions(-) delete mode 100644 Source/cmSetPropertiesCommand.cxx delete mode 100644 Source/cmSetPropertiesCommand.h create mode 100644 Source/cmSetPropertyCommand.cxx create mode 100644 Source/cmSetPropertyCommand.h diff --git a/Modules/CMakeGenericSystem.cmake b/Modules/CMakeGenericSystem.cmake index baecc52..d66e809 100644 --- a/Modules/CMakeGenericSystem.cmake +++ b/Modules/CMakeGenericSystem.cmake @@ -21,7 +21,7 @@ SET(CMAKE_FIND_LIBRARY_PREFIXES "lib") SET(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".a") # basically all general purpose OSs support shared libs -SET_PROPERTIES(GLOBAL PROPERTIES TARGET_SUPPORTS_SHARED_LIBS TRUE) +SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE) SET (CMAKE_SKIP_RPATH "NO" CACHE BOOL "If set, runtime paths are not added when using shared libraries.") diff --git a/Modules/FeatureSummary.cmake b/Modules/FeatureSummary.cmake index 40d6d7f..2452d7c 100644 --- a/Modules/FeatureSummary.cmake +++ b/Modules/FeatureSummary.cmake @@ -21,12 +21,12 @@ MACRO(SET_FEATURE_INFO _name _desc) SET(_url "${ARGV2}") SET(_comment "${ARGV3}") - SET_PROPERTIES(GLOBAL PROPERTIES ${_name}_DESCRIPTION "${_desc}" ) + SET_PROPERTY(GLOBAL PROPERTY ${_name}_DESCRIPTION "${_desc}" ) IF(_url MATCHES ".+") - SET_PROPERTIES(GLOBAL PROPERTIES ${_name}_URL "${_url}" ) + SET_PROPERTY(GLOBAL PROPERTY ${_name}_URL "${_url}" ) ENDIF(_url MATCHES ".+") IF(_comment MATCHES ".+") - SET_PROPERTIES(GLOBAL PROPERTIES ${_name}_COMMENT "${_comment}" ) + SET_PROPERTY(GLOBAL PROPERTY ${_name}_COMMENT "${_comment}" ) ENDIF(_comment MATCHES ".+") ENDMACRO(SET_FEATURE_INFO) diff --git a/Modules/Platform/BlueGeneL.cmake b/Modules/Platform/BlueGeneL.cmake index dc334cc..7794a26 100644 --- a/Modules/Platform/BlueGeneL.cmake +++ b/Modules/Platform/BlueGeneL.cmake @@ -1,5 +1,5 @@ #the compute nodes on BlueGene/L don't support shared libs -SET_PROPERTIES(GLOBAL PROPERTIES TARGET_SUPPORTS_SHARED_LIBS FALSE) +SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE) SET(CMAKE_SHARED_LIBRARY_C_FLAGS "") # -pic SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "") # -shared diff --git a/Modules/Platform/Catamount.cmake b/Modules/Platform/Catamount.cmake index cd619df..01493fc 100644 --- a/Modules/Platform/Catamount.cmake +++ b/Modules/Platform/Catamount.cmake @@ -1,5 +1,5 @@ #Catamount, which runs on the compute nodes of Cray machines, e.g. RedStorm, doesn't support shared libs -SET_PROPERTIES(GLOBAL PROPERTIES TARGET_SUPPORTS_SHARED_LIBS FALSE) +SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE) SET(CMAKE_SHARED_LIBRARY_C_FLAGS "") # -pic SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "") # -shared diff --git a/Modules/Platform/Generic.cmake b/Modules/Platform/Generic.cmake index b6629e2..00508b2 100644 --- a/Modules/Platform/Generic.cmake +++ b/Modules/Platform/Generic.cmake @@ -8,5 +8,4 @@ # and/or ${CMAKE_SYSTEM_NAME}--${CMAKE_SYSTEM_PROCESSOR}.cmake # (embedded) targets without operating system usually don't support shared libraries -SET_PROPERTIES(GLOBAL PROPERTIES TARGET_SUPPORTS_SHARED_LIBS FALSE) - +SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE) diff --git a/Modules/Platform/Linux.cmake b/Modules/Platform/Linux.cmake index 4de71d0..85178ce 100644 --- a/Modules/Platform/Linux.cmake +++ b/Modules/Platform/Linux.cmake @@ -52,5 +52,5 @@ INCLUDE(Platform/UnixPaths) # Debian has lib64 paths only for compatibility so they should not be # searched. IF(EXISTS "/etc/debian_version") - SET_PROPERTIES(GLOBAL PROPERTIES FIND_LIBRARY_USE_LIB64_PATHS FALSE) + SET_PROPERTY(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS FALSE) ENDIF(EXISTS "/etc/debian_version") diff --git a/Modules/Platform/UnixPaths.cmake b/Modules/Platform/UnixPaths.cmake index b7f060d..7ed85c0 100644 --- a/Modules/Platform/UnixPaths.cmake +++ b/Modules/Platform/UnixPaths.cmake @@ -54,4 +54,4 @@ LIST(APPEND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES ) # Enable use of lib64 search path variants by default. -SET_PROPERTIES(GLOBAL PROPERTIES FIND_LIBRARY_USE_LIB64_PATHS TRUE) +SET_PROPERTY(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS TRUE) diff --git a/Modules/Platform/eCos.cmake b/Modules/Platform/eCos.cmake index 9805965..e7709cc 100644 --- a/Modules/Platform/eCos.cmake +++ b/Modules/Platform/eCos.cmake @@ -47,7 +47,7 @@ SET(CMAKE_CXX_LINK_EXECUTABLE " -o -nostdlib -nostartfiles -L${ECOS_LIBTARGET_DIRECTORY} -Ttarget.ld ") # eCos doesn't support shared libs -SET_PROPERTIES(GLOBAL PROPERTIES TARGET_SUPPORTS_SHARED_LIBS FALSE) +SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE) SET(CMAKE_CXX_LINK_SHARED_LIBRARY ) SET(CMAKE_CXX_LINK_MODULE_LIBRARY ) diff --git a/Source/cmBootstrapCommands.cxx b/Source/cmBootstrapCommands.cxx index 77adce5..31533f0 100644 --- a/Source/cmBootstrapCommands.cxx +++ b/Source/cmBootstrapCommands.cxx @@ -72,7 +72,7 @@ #include "cmProjectCommand.cxx" #include "cmRaiseScopeCommand.cxx" #include "cmSetCommand.cxx" -#include "cmSetPropertiesCommand.cxx" +#include "cmSetPropertyCommand.cxx" #include "cmSetSourceFilesPropertiesCommand.cxx" #include "cmSetTargetPropertiesCommand.cxx" #include "cmSetTestsPropertiesCommand.cxx" @@ -132,7 +132,7 @@ void GetBootstrapCommands(std::list& commands) commands.push_back(new cmProjectCommand); commands.push_back(new cmRaiseScopeCommand); commands.push_back(new cmSetCommand); - commands.push_back(new cmSetPropertiesCommand); + commands.push_back(new cmSetPropertyCommand); commands.push_back(new cmSetSourceFilesPropertiesCommand); commands.push_back(new cmSetTargetPropertiesCommand); commands.push_back(new cmSetTestsPropertiesCommand); diff --git a/Source/cmSetPropertiesCommand.cxx b/Source/cmSetPropertiesCommand.cxx deleted file mode 100644 index 117d0df..0000000 --- a/Source/cmSetPropertiesCommand.cxx +++ /dev/null @@ -1,210 +0,0 @@ -/*========================================================================= - - Program: CMake - Cross-Platform Makefile Generator - Module: $RCSfile$ - Language: C++ - Date: $Date$ - Version: $Revision$ - - Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. - See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ -#include "cmSetPropertiesCommand.h" -#include "cmSetTargetPropertiesCommand.h" -#include "cmSetTestsPropertiesCommand.h" -#include "cmSetSourceFilesPropertiesCommand.h" - -// cmSetPropertiesCommand -bool cmSetPropertiesCommand::InitialPass( - std::vector const& args) -{ - if(args.size() < 2 ) - { - this->SetError("called with incorrect number of arguments"); - return false; - } - - // first collect up the list of files - std::vector propertyPairs; - bool doingFiles = true; - int numFiles = 0; - std::vector::const_iterator j; - for(j= args.begin(); j != args.end();++j) - { - if(*j == "PROPERTIES") - { - doingFiles = false; - // now loop through the rest of the arguments, new style - ++j; - while (j != args.end()) - { - propertyPairs.push_back(*j); - ++j; - if(j == args.end()) - { - this->SetError("called with incorrect number of arguments."); - return false; - } - propertyPairs.push_back(*j); - ++j; - } - // break out of the loop because j is already == end - break; - } - else if (doingFiles) - { - numFiles++; - } - else - { - this->SetError("called with illegal arguments, maybe missing " - "a PROPERTIES specifier?"); - return false; - } - } - if(propertyPairs.size() == 0) - { - this->SetError("called with illegal arguments, maybe missing " - "a PROPERTIES specifier?"); - return false; - } - - cmProperty::ScopeType scope; - const char *scopeName = 0; - if (args[0] == "GLOBAL" && numFiles == 1) - { - scope = cmProperty::GLOBAL; - } - else if (args[0] == "DIRECTORY" && numFiles >= 1) - { - scope = cmProperty::DIRECTORY; - if (numFiles == 2) - { - scopeName = args[1].c_str(); - } - } - else if (args[0] == "TARGET" && numFiles == 2) - { - scope = cmProperty::TARGET; - scopeName = args[1].c_str(); - } - else if (args[0] == "TEST" && numFiles == 2) - { - scope = cmProperty::TEST; - scopeName = args[1].c_str(); - } - else if (args[0] == "SOURCE_FILE" && numFiles == 2) - { - scope = cmProperty::SOURCE_FILE; - scopeName = args[1].c_str(); - } - else - { - this->SetError("called with illegal arguments."); - return false; - } - - switch (scope) - { - case cmProperty::TARGET: - { - bool ret = cmSetTargetPropertiesCommand:: - SetOneTarget(scopeName,propertyPairs, this->Makefile); - if (!ret) - { - std::string message = "Can not find target to add properties to: "; - message += scopeName; - this->SetError(message.c_str()); - return ret; - } - } - break; - case cmProperty::DIRECTORY: - { - // lookup the makefile from the directory name - cmLocalGenerator *lg = this->Makefile->GetLocalGenerator(); - if (numFiles == 2) - { - std::string sd = scopeName; - // make sure the start dir is a full path - if (!cmSystemTools::FileIsFullPath(sd.c_str())) - { - sd = this->Makefile->GetStartDirectory(); - sd += "/"; - sd += scopeName; - } - - // The local generators are associated with collapsed paths. - sd = cmSystemTools::CollapseFullPath(sd.c_str()); - - lg = this->Makefile->GetLocalGenerator()->GetGlobalGenerator()-> - FindLocalGenerator(sd.c_str()); - } - if (!lg) - { - this->SetError - ("DIRECTORY argument provided but requested directory not found. " - "This could be because the directory argument was invalid or, " - "it is valid but has not been processed yet."); - return false; - } - - for(j= propertyPairs.begin(); j != propertyPairs.end(); ++j) - { - const char *pn = j->c_str(); - ++j; - lg->GetMakefile()->SetProperty(pn,j->c_str()); - } - } - break; - case cmProperty::GLOBAL: - { - for(j= propertyPairs.begin(); j != propertyPairs.end(); ++j) - { - const char *pn = j->c_str(); - ++j; - this->Makefile->GetCMakeInstance()->SetProperty(pn, j->c_str()); - } - } - break; - case cmProperty::TEST: - { - std::string errors; - bool ret = cmSetTestsPropertiesCommand:: - SetOneTest(scopeName,propertyPairs, this->Makefile, errors); - if (!ret) - { - this->SetError(errors.c_str()); - return ret; - } - } - break; - case cmProperty::SOURCE_FILE: - { - std::string errors; - bool ret = cmSetSourceFilesPropertiesCommand:: - RunCommand(this->Makefile, - args.begin()+1, args.begin()+2, - args.begin() + 2, args.end(), - errors); - if (!ret) - { - this->SetError(errors.c_str()); - return ret; - } - } - break; - case cmProperty::VARIABLE: - case cmProperty::CACHED_VARIABLE: - // not handled by SetProperty - break; - } - - return true; -} - diff --git a/Source/cmSetPropertiesCommand.h b/Source/cmSetPropertiesCommand.h deleted file mode 100644 index ce85cbd..0000000 --- a/Source/cmSetPropertiesCommand.h +++ /dev/null @@ -1,74 +0,0 @@ -/*========================================================================= - - Program: CMake - Cross-Platform Makefile Generator - Module: $RCSfile$ - Language: C++ - Date: $Date$ - Version: $Revision$ - - Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. - See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ -#ifndef cmSetsPropertiesCommand_h -#define cmSetsPropertiesCommand_h - -#include "cmCommand.h" - -class cmSetPropertiesCommand : public cmCommand -{ -public: - virtual cmCommand* Clone() - { - return new cmSetPropertiesCommand; - } - - /** - * This is called when the command is first encountered in - * the input file. - */ - virtual bool InitialPass(std::vector const& args); - - /** - * The name of the command as specified in CMakeList.txt. - */ - virtual const char* GetName() { return "set_properties";} - - /** - * Succinct documentation. - */ - virtual const char* GetTerseDocumentation() - { - return "Set properties used by CMake."; - } - - /** - * Longer documentation. - */ - virtual const char* GetFullDocumentation() - { - return - " set_properties(scope_value\n" - " PROPERTIES prop1 value1\n" - " prop2 value2 ...)\n" - "Set properties on something. The scope_value is either GLOBAL, " - "DIRECTORY dir_name, TARGET tgt_name, SOURCE_FILE src_name, " - "or TEST test_name." - ; - } - - /** - * This determines if the command is invoked when in script mode. - */ - virtual bool IsScriptable() { return true; } - - cmTypeMacro(cmSetPropertiesCommand, cmCommand); -}; - - - -#endif diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx new file mode 100644 index 0000000..a0455aa --- /dev/null +++ b/Source/cmSetPropertyCommand.cxx @@ -0,0 +1,408 @@ +/*========================================================================= + + Program: CMake - Cross-Platform Makefile Generator + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "cmSetPropertyCommand.h" +#include "cmSetTargetPropertiesCommand.h" +#include "cmSetTestsPropertiesCommand.h" +#include "cmSetSourceFilesPropertiesCommand.h" + +//---------------------------------------------------------------------------- +cmSetPropertyCommand::cmSetPropertyCommand() +{ + this->AppendMode = false; +} + +//---------------------------------------------------------------------------- +bool cmSetPropertyCommand::InitialPass(std::vector const& args) +{ + if(args.size() < 2 ) + { + this->SetError("called with incorrect number of arguments"); + return false; + } + + // Get the scope on which to set the property. + std::vector::const_iterator arg = args.begin(); + cmProperty::ScopeType scope; + if(*arg == "GLOBAL") + { + scope = cmProperty::GLOBAL; + } + else if(*arg == "DIRECTORY") + { + scope = cmProperty::DIRECTORY; + } + else if(*arg == "TARGET") + { + scope = cmProperty::TARGET; + } + else if(*arg == "SOURCE") + { + scope = cmProperty::SOURCE_FILE; + } + else if(*arg == "TEST") + { + scope = cmProperty::TEST; + } + else + { + cmOStringStream e; + e << "given invalid scope " << *arg << ". " + << "Valid scopes are GLOBAL, DIRECTORY, TARGET, SOURCE, TEST."; + this->SetError(e.str().c_str()); + return false; + } + + // Parse the rest of the arguments up to the values. + enum Doing { DoingNone, DoingNames, DoingProperty, DoingValues }; + Doing doing = DoingNames; + const char* sep = ""; + for(++arg; arg != args.end(); ++arg) + { + if(*arg == "PROPERTY") + { + doing = DoingProperty; + } + else if(*arg == "APPEND") + { + doing = DoingNone; + this->AppendMode = true; + } + else if(doing == DoingNames) + { + this->Names.insert(*arg); + } + else if(doing == DoingProperty) + { + this->PropertyName = *arg; + doing = DoingValues; + } + else if(doing == DoingValues) + { + this->PropertyValue += sep; + sep = ";"; + this->PropertyValue += *arg; + } + else + { + cmOStringStream e; + e << "given invalid argument \"" << *arg << "\"."; + this->SetError(e.str().c_str()); + return false; + } + } + + // Make sure a property name was found. + if(this->PropertyName.empty()) + { + this->SetError("not given a PROPERTY argument."); + return false; + } + + // Dispatch property setting. + switch(scope) + { + case cmProperty::GLOBAL: return this->HandleGlobalMode(); + case cmProperty::DIRECTORY: return this->HandleDirectoryMode(); + case cmProperty::TARGET: return this->HandleTargetMode(); + case cmProperty::SOURCE_FILE: return this->HandleSourceMode(); + case cmProperty::TEST: return this->HandleTestMode(); + + case cmProperty::VARIABLE: + case cmProperty::CACHED_VARIABLE: + break; // should never happen + } + return true; +} + +//---------------------------------------------------------------------------- +bool cmSetPropertyCommand::ConstructValue(std::string& value, + const char* old) +{ + if(this->AppendMode) + { + // This is an append. Start with the original value. + if(old) + { + value = old; + } + } + else if(this->PropertyValue.empty()) + { + // This is a set to no values. Remove the property. + return false; + } + + // Add the new value. + if(!this->PropertyValue.empty()) + { + if(!value.empty()) + { + value += ";"; + } + value += this->PropertyValue; + } + + return true; +} + +//---------------------------------------------------------------------------- +bool cmSetPropertyCommand::HandleGlobalMode() +{ + if(!this->Names.empty()) + { + this->SetError("given names for GLOBAL scope."); + return false; + } + + // Set or append the property. + cmake* cm = this->Makefile->GetCMakeInstance(); + const char* name = this->PropertyName.c_str(); + std::string value; + if(this->ConstructValue(value, cm->GetProperty(name))) + { + // Set the new property. + cm->SetProperty(name, value.c_str()); + } + else + { + // Remove the property. + cm->SetProperty(name, 0); + } + + return true; +} + +//---------------------------------------------------------------------------- +bool cmSetPropertyCommand::HandleDirectoryMode() +{ + if(this->Names.size() > 1) + { + this->SetError("allows at most one name for DIRECTORY scope."); + return false; + } + + // Default to the current directory. + cmMakefile* mf = this->Makefile; + + // Lookup the directory if given. + if(!this->Names.empty()) + { + // Construct the directory name. Interpret relative paths with + // respect to the current directory. + std::string dir = *this->Names.begin(); + if(!cmSystemTools::FileIsFullPath(dir.c_str())) + { + dir = this->Makefile->GetCurrentDirectory(); + dir += "/"; + dir += *this->Names.begin(); + } + + // The local generators are associated with collapsed paths. + dir = cmSystemTools::CollapseFullPath(dir.c_str()); + + // Lookup the generator. + if(cmLocalGenerator* lg = + (this->Makefile->GetLocalGenerator() + ->GetGlobalGenerator()->FindLocalGenerator(dir.c_str()))) + { + // Use the makefile for the directory found. + mf = lg->GetMakefile(); + } + else + { + // Could not find the directory. + this->SetError + ("DIRECTORY scope provided but requested directory was not found. " + "This could be because the directory argument was invalid or, " + "it is valid but has not been processed yet."); + return false; + } + } + + // Set or append the property. + const char* name = this->PropertyName.c_str(); + std::string value; + if(this->ConstructValue(value, mf->GetProperty(name))) + { + // Set the new property. + mf->SetProperty(name, value.c_str()); + } + else + { + // Remove the property. + mf->SetProperty(name, 0); + } + + return true; +} + +//---------------------------------------------------------------------------- +bool cmSetPropertyCommand::HandleTargetMode() +{ + for(std::set::const_iterator ni = this->Names.begin(); + ni != this->Names.end(); ++ni) + { + if(cmTarget* target = + this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + ->FindTarget(0, ni->c_str(), true)) + { + // Handle the current target. + if(!this->HandleTarget(target)) + { + return false; + } + } + else + { + cmOStringStream e; + e << "could not find TARGET " << *ni + << ". Perhaps it has not yet been created."; + this->SetError(e.str().c_str()); + return false; + } + } + return true; +} + +//---------------------------------------------------------------------------- +bool cmSetPropertyCommand::HandleTarget(cmTarget* target) +{ + // Set or append the property. + const char* name = this->PropertyName.c_str(); + std::string value; + if(this->ConstructValue(value, target->GetProperty(name))) + { + // Set the new property. + target->SetProperty(name, value.c_str()); + } + else + { + // Remove the property. + target->SetProperty(name, 0); + } + + return true; +} + +//---------------------------------------------------------------------------- +bool cmSetPropertyCommand::HandleSourceMode() +{ + for(std::set::const_iterator ni = this->Names.begin(); + ni != this->Names.end(); ++ni) + { + // Get the source file. + if(cmSourceFile* sf = this->Makefile->GetOrCreateSource(ni->c_str())) + { + if(!this->HandleSource(sf)) + { + return false; + } + } + else + { + cmOStringStream e; + e << "given SOURCE name that could not be found or created: " << *ni; + this->SetError(e.str().c_str()); + return false; + } + } + return true; +} + +//---------------------------------------------------------------------------- +bool cmSetPropertyCommand::HandleSource(cmSourceFile* sf) +{ + // Set or append the property. + const char* name = this->PropertyName.c_str(); + std::string value; + if(this->ConstructValue(value, sf->GetProperty(name))) + { + // Set the new property. + sf->SetProperty(name, value.c_str()); + } + else + { + // Remove the property. + sf->SetProperty(name, 0); + } + + // TODO: MACOSX_PACKAGE_LOCATION special case in + // cmSetSourceFilesPropertiesCommand + // The logic should be moved to cmSourceFile. + + return true; +} + +//---------------------------------------------------------------------------- +bool cmSetPropertyCommand::HandleTestMode() +{ + // Loop over all tests looking for matching names. + std::vector const& tests = *this->Makefile->GetTests(); + for(std::vector::const_iterator ti = tests.begin(); + ti != tests.end(); ++ti) + { + cmTest* test = *ti; + std::set::const_iterator ni = + this->Names.find(test->GetName()); + if(ni != this->Names.end()) + { + if(this->HandleTest(test)) + { + this->Names.erase(ni); + } + else + { + return false; + } + } + } + + // Names that are still left were not found. + if(!this->Names.empty()) + { + cmOStringStream e; + e << "given TEST names that do not exist:\n"; + for(std::set::const_iterator ni = this->Names.begin(); + ni != this->Names.end(); ++ni) + { + e << " " << *ni << "\n"; + } + this->SetError(e.str().c_str()); + return false; + } + return true; +} + +//---------------------------------------------------------------------------- +bool cmSetPropertyCommand::HandleTest(cmTest* test) +{ + // Set or append the property. + const char* name = this->PropertyName.c_str(); + std::string value; + if(this->ConstructValue(value, test->GetProperty(name))) + { + // Set the new property. + test->SetProperty(name, value.c_str()); + } + else + { + // Remove the property. + test->SetProperty(name, 0); + } + + return true; +} diff --git a/Source/cmSetPropertyCommand.h b/Source/cmSetPropertyCommand.h new file mode 100644 index 0000000..c5de8e5 --- /dev/null +++ b/Source/cmSetPropertyCommand.h @@ -0,0 +1,112 @@ +/*========================================================================= + + Program: CMake - Cross-Platform Makefile Generator + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef cmSetsPropertiesCommand_h +#define cmSetsPropertiesCommand_h + +#include "cmCommand.h" + +class cmSetPropertyCommand : public cmCommand +{ +public: + cmSetPropertyCommand(); + + virtual cmCommand* Clone() + { + return new cmSetPropertyCommand; + } + + /** + * This is called when the command is first encountered in + * the input file. + */ + virtual bool InitialPass(std::vector const& args); + + /** + * The name of the command as specified in CMakeList.txt. + */ + virtual const char* GetName() { return "set_property";} + + /** + * Succinct documentation. + */ + virtual const char* GetTerseDocumentation() + { + return "Set a named property in a given scope."; + } + + /** + * Longer documentation. + */ + virtual const char* GetFullDocumentation() + { + return + " set_property(\n" + " [APPEND]\n" + " PROPERTY [value1 [value2 ...]])\n" + "Set one property on zero or more objects of a scope. " + "The first argument determines the scope in which the property " + "is set. It must be one of the following:\n" + "GLOBAL scope is unique and does not accept a name.\n" + "DIRECTORY scope defaults to the current directory but another " + "directory (already processed by CMake) may be named by full or " + "relative path.\n" + "TARGET scope may name zero or more existing targets.\n" + "SOURCE scope may name zero or more source files.\n" + "TEST scope may name zero or more existing tests.\n" + "The required PROPERTY option is immediately followed by the name " + "of the property to set. Remaining arguments are used to " + "compose the property value in the form of a semicolon-separated " + "list. " + "If the APPEND option is given the list is appended to any " + "existing property value." + ; + } + + /** + * This determines if the command is invoked when in script mode. + */ + virtual bool IsScriptable() { return true; } + + cmTypeMacro(cmSetPropertyCommand, cmCommand); + +private: + std::set Names; + std::string PropertyName; + std::string PropertyValue; + bool AppendMode; + + // Implementation of value construction. + bool ConstructValue(std::string& value, const char* old); + + // Implementation of each property type. + bool HandleGlobalMode(); + bool HandleDirectoryMode(); + bool HandleTargetMode(); + bool HandleTarget(cmTarget* target); + bool HandleSourceMode(); + bool HandleSource(cmSourceFile* sf); + bool HandleTestMode(); + bool HandleTest(cmTest* test); +}; + + + +#endif diff --git a/Tests/DocTest/CMakeLists.txt b/Tests/DocTest/CMakeLists.txt index 1789746..bd78992 100644 --- a/Tests/DocTest/CMakeLists.txt +++ b/Tests/DocTest/CMakeLists.txt @@ -2,5 +2,5 @@ project (DocTest) add_executable (DocTest DocTest.cxx) -set_properties(GLOBAL PROPERTIES REPORT_UNDEFINED_PROPERTIES +set_property(GLOBAL PROPERTY REPORT_UNDEFINED_PROPERTIES "${CMAKE_CURRENT_BINARY_DIR}/UndefinedProperties.txt") diff --git a/Tests/Properties/CMakeLists.txt b/Tests/Properties/CMakeLists.txt index 7b7bd2d..15b5e14 100644 --- a/Tests/Properties/CMakeLists.txt +++ b/Tests/Properties/CMakeLists.txt @@ -24,10 +24,9 @@ include_directories("${Properties_SOURCE_DIR}" "${Properties_BINARY_DIR}") # test generic property interfaces define_property(GLOBALTEST GLOBAL "A test property" "A long description of this test property" 0) -set_properties(GLOBAL PROPERTIES GLOBALTEST 1) -set_properties(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - PROPERTIES DIRECTORYTEST 1) -set_properties(SOURCE_FILE SubDir/properties3.cxx PROPERTIES SOURCETEST 1) +set_property(GLOBAL PROPERTY GLOBALTEST 1) +set_property(DIRECTORY PROPERTY DIRECTORYTEST 1) +set_property(SOURCE SubDir/properties3.cxx PROPERTY SOURCETEST 1) get_property(GLOBALRESULT GLOBAL GLOBALTEST) get_property(DIRECTORYRESULT DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" DIRECTORYTEST) @@ -46,7 +45,7 @@ endif (RESULT1 AND RESULT2 AND RESULT3 AND GLOBALRESULT AND DIRECTORYRESULT AND SOURCE_FILERESULT) # test the target property -set_properties(TARGET Properties PROPERTIES TARGETTEST 1) +set_property(TARGET Properties PROPERTY TARGETTEST 1) get_property(TARGETRESULT TARGET Properties TARGETTEST) if (NOT TARGETRESULT) message("Error: target result is TARGETRESULT=${TARGETRESULT}") -- cgit v0.12