From 27379d7b081be852c2b290a98db548cffffbff04 Mon Sep 17 00:00:00 2001 From: Ken Martin Date: Thu, 7 Dec 2006 09:45:32 -0500 Subject: ENH: make properties a bit more formal with documentation and chaining --- Source/CMakeLists.txt | 8 +- Source/cmAuxSourceDirectoryCommand.cxx | 2 + Source/cmCPluginAPI.cxx | 20 ++ Source/cmCPluginAPI.h | 7 + Source/cmCommands.cxx | 4 + Source/cmCreateTestSourceList.cxx | 3 + Source/cmDefinePropertyCommand.cxx | 64 +++++ Source/cmDefinePropertyCommand.h | 74 ++++++ Source/cmDocumentation.cxx | 83 +++++++ Source/cmDocumentation.h | 10 +- Source/cmFLTKWrapUICommand.cxx | 2 + Source/cmForEachCommand.cxx | 3 +- Source/cmGlobalGenerator.cxx | 1 + Source/cmIfCommand.cxx | 3 +- Source/cmInstallFilesCommand.cxx | 3 +- Source/cmInstallProgramsCommand.cxx | 3 +- Source/cmLocalGenerator.cxx | 7 +- Source/cmMacroCommand.cxx | 3 +- Source/cmMakefile.cxx | 91 +++++-- Source/cmMakefile.h | 14 +- Source/cmPropertyMap.cxx | 12 +- Source/cmSetDirectoryPropertiesCommand.cxx | 47 ++-- Source/cmSetDirectoryPropertiesCommand.h | 8 + Source/cmSetTargetPropertiesCommand.cxx | 46 ++-- Source/cmSetTargetPropertiesCommand.h | 9 +- Source/cmSourceFile.cxx | 135 +++++++++-- Source/cmSourceFile.h | 16 +- Source/cmTarget.cxx | 261 +++++++++++++++++++-- Source/cmTarget.h | 12 +- Source/cmTest.cxx | 63 ++++- Source/cmTest.h | 20 +- Source/cmVTKMakeInstantiatorCommand.cxx | 4 + Source/cmVTKWrapJavaCommand.cxx | 2 + Source/cmVTKWrapPythonCommand.cxx | 4 + Source/cmVTKWrapTclCommand.cxx | 4 + Source/cmWhileCommand.cxx | 3 +- Source/cmake.cxx | 140 +++++++++++ Source/cmake.h | 29 +++ Source/cmakemain.cxx | 11 + Tests/Complex/Library/CMakeLists.txt | 2 + Tests/ComplexOneConfig/Library/CMakeLists.txt | 2 + Tests/ComplexRelativePaths/Library/CMakeLists.txt | 2 + Tests/LoadCommand/CMakeCommands/cmTestCommand.c | 10 +- .../CMakeCommands/cmTestCommand.c | 10 +- 44 files changed, 1130 insertions(+), 127 deletions(-) create mode 100644 Source/cmDefinePropertyCommand.cxx create mode 100644 Source/cmDefinePropertyCommand.h diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 5311c72..ebb8112 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -146,10 +146,10 @@ SET(SRCS cmProperty.h cmPropertyDefinition.cxx cmPropertyDefinition.h -# cmPropertyDefinitionMap.cxx -# cmPropertyDefinitionMap.h -# cmPropertyMap.cxx -# cmPropertyMap.h + cmPropertyDefinitionMap.cxx + cmPropertyDefinitionMap.h + cmPropertyMap.cxx + cmPropertyMap.h cmSourceFile.cxx cmSourceFile.h cmSourceGroup.cxx diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx index 37dee8c..1c0388d 100644 --- a/Source/cmAuxSourceDirectoryCommand.cxx +++ b/Source/cmAuxSourceDirectoryCommand.cxx @@ -69,6 +69,8 @@ bool cmAuxSourceDirectoryCommand::InitialPass // add the file as a class file so // depends can be done cmSourceFile cmfile; + cmfile.GetProperties().SetCMakeInstance + (this->Makefile->GetCMakeInstance()); cmfile.SetName(fullname.c_str(), this->Makefile->GetCurrentDirectory(), this->Makefile->GetSourceExtensions(), diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index f2a1cca..7b1f603 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -507,6 +507,14 @@ void * CCONV cmCreateSourceFile() return (void *)(new cmSourceFile); } +void * CCONV cmCreateNewSourceFile(void *arg) +{ + cmMakefile *mf = static_cast(arg); + cmSourceFile *sf = new cmSourceFile; + sf->GetProperties().SetCMakeInstance(mf->GetCMakeInstance()); + return (void *)sf; +} + void CCONV cmDestroySourceFile(void *arg) { cmSourceFile *sf = static_cast(arg); @@ -624,6 +632,16 @@ void CCONV cmFree(void *data) free(data); } +void CCONV DefineSourceFileProperty (void *arg, const char *name, + const char *briefDocs, + const char *longDocs, + int chained) +{ + cmMakefile *mf = static_cast(arg); + mf->GetCMakeInstance()->DefineProperty(name,cmProperty::SOURCE_FILE, + briefDocs, longDocs,chained); +} + } // close the extern "C" scope cmCAPI cmStaticCAPI = @@ -683,5 +701,7 @@ cmCAPI cmStaticCAPI = cmAddCustomCommandToOutput, cmAddCustomCommandToTarget, cmDisplayStatus, + cmCreateNewSourceFile, + DefineSourceFileProperty, }; diff --git a/Source/cmCPluginAPI.h b/Source/cmCPluginAPI.h index 84f7906..fe6a386 100644 --- a/Source/cmCPluginAPI.h +++ b/Source/cmCPluginAPI.h @@ -170,6 +170,13 @@ typedef struct /* display status information */ void (CCONV *DisplaySatus) (void *info, const char *message); + /* new functions added after 2.4 */ + void *(CCONV *CreateNewSourceFile) (void *mf); + void (CCONV *DefineSourceFileProperty) (void *mf, const char *name, + const char *briefDocs, + const char *longDocs, + int chained); + /* this is the end of the C function stub API structure */ } cmCAPI; diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 8c3cff4..ec6f84b 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -20,6 +20,7 @@ #include "cmAuxSourceDirectoryCommand.cxx" #include "cmBuildNameCommand.cxx" #include "cmCreateTestSourceList.cxx" +#include "cmDefinePropertyCommand.cxx" #include "cmElseIfCommand.cxx" #include "cmEnableLanguageCommand.cxx" #include "cmEndMacroCommand.cxx" @@ -44,6 +45,7 @@ #include "cmRemoveDefinitionsCommand.cxx" #include "cmSeparateArgumentsCommand.cxx" #include "cmSetDirectoryPropertiesCommand.cxx" +#include "cmSetPropertiesCommand.cxx" #include "cmSetTargetPropertiesCommand.cxx" #include "cmSetTestsPropertiesCommand.cxx" #include "cmSourceGroupCommand.cxx" @@ -75,6 +77,7 @@ void GetPredefinedCommands(std::list& commands.push_back(new cmAuxSourceDirectoryCommand); commands.push_back(new cmBuildNameCommand); commands.push_back(new cmCreateTestSourceList); + commands.push_back(new cmDefinePropertyCommand); commands.push_back(new cmElseIfCommand); commands.push_back(new cmEnableLanguageCommand); commands.push_back(new cmEndMacroCommand); @@ -100,6 +103,7 @@ void GetPredefinedCommands(std::list& commands.push_back(new cmRemoveDefinitionsCommand); commands.push_back(new cmSeparateArgumentsCommand); commands.push_back(new cmSetDirectoryPropertiesCommand); + commands.push_back(new cmSetPropertiesCommand); commands.push_back(new cmSetTargetPropertiesCommand); commands.push_back(new cmSetTestsPropertiesCommand); commands.push_back(new cmSourceGroupCommand); diff --git a/Source/cmCreateTestSourceList.cxx b/Source/cmCreateTestSourceList.cxx index 02071dd..89253e9 100644 --- a/Source/cmCreateTestSourceList.cxx +++ b/Source/cmCreateTestSourceList.cxx @@ -172,6 +172,7 @@ bool cmCreateTestSourceList::InitialPass(std::vector const& args) // Create the source list cmSourceFile cfile; + cfile.GetProperties().SetCMakeInstance(this->Makefile->GetCMakeInstance()); std::string sourceListValue; cfile.SetProperty("ABSTRACT","0"); @@ -185,6 +186,8 @@ bool cmCreateTestSourceList::InitialPass(std::vector const& args) for(i = testsBegin; i != tests.end(); ++i) { cmSourceFile icfile; + icfile.GetProperties(). + SetCMakeInstance(this->Makefile->GetCMakeInstance()); icfile.SetProperty("ABSTRACT","0"); icfile.SetName(i->c_str(), this->Makefile->GetCurrentDirectory(), diff --git a/Source/cmDefinePropertyCommand.cxx b/Source/cmDefinePropertyCommand.cxx new file mode 100644 index 0000000..15a8cf5 --- /dev/null +++ b/Source/cmDefinePropertyCommand.cxx @@ -0,0 +1,64 @@ +/*========================================================================= + + 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 "cmDefinePropertyCommand.h" +#include "cmake.h" + +// cmDefinePropertiesCommand +bool cmDefinePropertyCommand::InitialPass( + std::vector const& args) +{ + if(args.size() < 5 ) + { + this->SetError("called with incorrect number of arguments"); + return false; + } + + // determine the scope + cmProperty::ScopeType scope; + if (args[1] == "GLOBAL") + { + scope = cmProperty::GLOBAL; + } + else if (args[1] == "DIRECTORY") + { + scope = cmProperty::DIRECTORY; + } + else if (args[1] == "TARGET") + { + scope = cmProperty::TARGET; + } + else if (args[1] == "SOURCE_FILE") + { + scope = cmProperty::SOURCE_FILE; + } + else if (args[1] == "TEST") + { + scope = cmProperty::TEST; + } + else + { + this->SetError("called with illegal arguments."); + return false; + } + + this->Makefile->GetCMakeInstance()->DefineProperty + (args[0].c_str(), scope,args[2].c_str(), args[3].c_str(), + cmSystemTools::IsOn(args[4].c_str())); + + return true; +} + diff --git a/Source/cmDefinePropertyCommand.h b/Source/cmDefinePropertyCommand.h new file mode 100644 index 0000000..125296f --- /dev/null +++ b/Source/cmDefinePropertyCommand.h @@ -0,0 +1,74 @@ +/*========================================================================= + + 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 cmDefinesPropertyCommand_h +#define cmDefinesPropertyCommand_h + +#include "cmCommand.h" + +class cmDefinePropertyCommand : public cmCommand +{ +public: + virtual cmCommand* Clone() + { + return new cmDefinePropertyCommand; + } + + /** + * 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 "DEFINE_PROPERTY";} + + /** + * Succinct documentation. + */ + virtual const char* GetTerseDocumentation() + { + return "Define properties used by CMake."; + } + + /** + * Longer documentation. + */ + virtual const char* GetFullDocumentation() + { + return + " DEFINE_PROPERTY(property_name scope_value\n" + " short_description\n" + " full_description chain)\n" + "Define a property for a scope. The scope_value is either GLOBAL " + "DIRECTORY, TARGET, TEST, SOURCE_FILE. The short and full " + "descriptions are used to document the property, chain indicates " + "if that property chains such that a request for the property " + "on a target will chain up to the directory if it is not set on the " + "target. In such cases the property's scope is the most specific. " + "In that example the scope would be TARGET even though it can " + "chain up to DIRECTORY and GLOBAL." + ; + } + + cmTypeMacro(cmDefinePropertyCommand, cmCommand); +}; + + + +#endif diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx index 392ba4b..53b1342 100644 --- a/Source/cmDocumentation.cxx +++ b/Source/cmDocumentation.cxx @@ -52,6 +52,14 @@ static const cmDocumentationEntry cmDocumentationCommandsHeader[] = }; //---------------------------------------------------------------------------- +static const cmDocumentationEntry cmDocumentationPropertiesHeader[] = +{ + {0, + "The following properties are available in CMakeLists.txt code:", 0}, + {0,0,0} +}; + +//---------------------------------------------------------------------------- static const cmDocumentationEntry cmDocumentationModulesHeader[] = { {0, @@ -226,8 +234,11 @@ bool cmDocumentation::PrintDocumentation(Type ht, std::ostream& os) return this->PrintDocumentationSingle(os); case cmDocumentation::SingleModule: return this->PrintDocumentationSingleModule(os); + case cmDocumentation::SingleProperty: + return this->PrintDocumentationSingleProperty(os); case cmDocumentation::List: return this->PrintDocumentationList(os); case cmDocumentation::ModuleList: return this->PrintModuleList(os); + case cmDocumentation::PropertyList: return this->PrintPropertyList(os); case cmDocumentation::Full: return this->PrintDocumentationFull(os); case cmDocumentation::HTML: return this->PrintDocumentationHTML(os); case cmDocumentation::Man: return this->PrintDocumentationMan(os); @@ -470,6 +481,15 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv) i = i+1; } } + else if(strcmp(argv[i], "--help-property") == 0) + { + type = cmDocumentation::SingleProperty; + if((i+1 < argc) && !this->IsOption(argv[i+1])) + { + this->SinglePropertyName = argv[i+1]; + i = i+1; + } + } else if(strcmp(argv[i], "--help-command-list") == 0) { type = cmDocumentation::List; @@ -478,6 +498,10 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv) { type = cmDocumentation::ModuleList; } + else if(strcmp(argv[i], "--help-property-list") == 0) + { + type = cmDocumentation::PropertyList; + } else if(strcmp(argv[i], "--copyright") == 0) { type = cmDocumentation::Copyright; @@ -556,6 +580,13 @@ void cmDocumentation::SetCommandsSection(const cmDocumentationEntry* section) } //---------------------------------------------------------------------------- +void cmDocumentation::SetPropertiesSection(const cmDocumentationEntry* section) +{ + this->SetSection(cmDocumentationPropertiesHeader, section, 0, + this->PropertiesSection); +} + +//---------------------------------------------------------------------------- void cmDocumentation ::SetGeneratorsSection(const cmDocumentationEntry* section) { @@ -1119,6 +1150,35 @@ bool cmDocumentation::PrintDocumentationSingleModule(std::ostream& os) } //---------------------------------------------------------------------------- +bool cmDocumentation::PrintDocumentationSingleProperty(std::ostream& os) +{ + if(this->PropertiesSection.empty()) + { + os << "Internal error: properties list is empty." << std::endl; + return false; + } + if(this->SinglePropertyName.length() == 0) + { + os << "Argument --help-property needs a property name.\n"; + return false; + } + for(cmDocumentationEntry* entry = &this->PropertiesSection[0]; + entry->brief; ++entry) + { + if(entry->name && this->SinglePropertyName == entry->name) + { + this->PrintDocumentationCommand(os, entry); + return true; + } + } + // Argument was not a command. Complain. + os << "Argument \"" << this->SinglePropertyName.c_str() + << "\" to --help-property is not a CMake property. " + << "Use --help-property-list to see all properties.\n"; + return false; +} + +//---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationList(std::ostream& os) { if(this->CommandsSection.empty()) @@ -1138,6 +1198,25 @@ bool cmDocumentation::PrintDocumentationList(std::ostream& os) } //---------------------------------------------------------------------------- +bool cmDocumentation::PrintPropertyList(std::ostream& os) +{ + if(this->PropertiesSection.empty()) + { + os << "Internal error: properties list is empty." << std::endl; + return false; + } + for(cmDocumentationEntry* entry = &this->PropertiesSection[0]; + entry->brief; ++entry) + { + if(entry->name) + { + os << entry->name << std::endl; + } + } + return true; +} + +//---------------------------------------------------------------------------- bool cmDocumentation::PrintModuleList(std::ostream& os) { this->CreateModulesSection(); @@ -1261,6 +1340,10 @@ void cmDocumentation::CreateFullDocumentation() { this->AddSection("Standard CMake Modules", &this->ModulesSection[0]); } + if(!this->PropertiesSection.empty()) + { + this->AddSection("Standard Properties", &this->PropertiesSection[0]); + } this->AddSection("Copyright", cmDocumentationCopyright); this->AddSection("See Also", cmDocumentationStandardSeeAlso); } diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h index 6ce777e..53ced44 100644 --- a/Source/cmDocumentation.h +++ b/Source/cmDocumentation.h @@ -29,7 +29,8 @@ public: // High-level interface for standard documents: /** Types of help provided. */ - enum Type { None, Usage, Single, SingleModule, List, ModuleList, + enum Type { None, Usage, Single, SingleModule, SingleProperty, + List, ModuleList, PropertyList, Full, HTML, Man, Copyright, Version }; /** @@ -70,6 +71,9 @@ public: /** Set the listfile commands for standard document generation. */ void SetCommandsSection(const cmDocumentationEntry*); + /** Set the properties for standard document generation. */ + void SetPropertiesSection(const cmDocumentationEntry*); + /** Set the generator descriptions for standard document generation. */ void SetGeneratorsSection(const cmDocumentationEntry*); @@ -132,8 +136,10 @@ private: bool PrintVersion(std::ostream& os); bool PrintDocumentationList(std::ostream& os); bool PrintModuleList(std::ostream& os); + bool PrintPropertyList(std::ostream& os); bool PrintDocumentationSingle(std::ostream& os); bool PrintDocumentationSingleModule(std::ostream& os); + bool PrintDocumentationSingleProperty(std::ostream& os); bool PrintDocumentationUsage(std::ostream& os); bool PrintDocumentationFull(std::ostream& os); bool PrintDocumentationHTML(std::ostream& os); @@ -159,11 +165,13 @@ private: std::vector OptionsSection; std::vector CommandsSection; std::vector ModulesSection; + std::vector PropertiesSection; std::vector GeneratorsSection; std::vector SeeAlsoSection; std::string SeeAlsoString; std::string SingleCommand; std::string SingleModuleName; + std::string SinglePropertyName; std::string CMakeRoot; std::vector< char* > ModuleStrings; std::vector< const char* > Names; diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx index 2412d55..d9457ba 100644 --- a/Source/cmFLTKWrapUICommand.cxx +++ b/Source/cmFLTKWrapUICommand.cxx @@ -54,6 +54,8 @@ bool cmFLTKWrapUICommand::InitialPass(std::vector const& args) if (!curr || !curr->GetPropertyAsBool("WRAP_EXCLUDE")) { cmSourceFile header_file; + header_file.GetProperties().SetCMakeInstance + (this->Makefile->GetCMakeInstance()); std::string srcName = cmSystemTools::GetFilenameWithoutExtension(*i); const bool headerFileOnly = true; header_file.SetName(srcName.c_str(), diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index 0d9bc7a..1f9b84c 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -87,7 +87,8 @@ ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) mf.ExpandArguments(lff.Arguments, expandedArguments); if ((!expandedArguments.empty() && (expandedArguments[0] == this->Args[0])) - || mf.IsOn("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS")) + || cmSystemTools::IsOn + (mf.GetPropertyOrDefinition("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS"))) { return true; } diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 71166a0..62d1b2f 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1595,6 +1595,7 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget( { // Package cmTarget target; + target.GetProperties().SetCMakeInstance(this->CMakeInstance); target.SetType(cmTarget::GLOBAL_TARGET, name); target.SetInAll(false); diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx index 2e21da1..265c0d6 100644 --- a/Source/cmIfCommand.cxx +++ b/Source/cmIfCommand.cxx @@ -96,7 +96,8 @@ bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, { if (!cmSystemTools::Strucmp(lff.Name.c_str(),"endif")) { - if (mf.IsOn("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS") + if (cmSystemTools::IsOn + (mf.GetPropertyOrDefinition("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS")) || lff.Arguments == this->Args) { return true; diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx index 12b7fdc..2809e2e 100644 --- a/Source/cmInstallFilesCommand.cxx +++ b/Source/cmInstallFilesCommand.cxx @@ -36,8 +36,9 @@ bool cmInstallFilesCommand // Create an INSTALL_FILES target specifically for this path. this->TargetName = "INSTALL_FILES_"+args[0]; cmTarget& target = this->Makefile->GetTargets()[this->TargetName]; - target.SetInAll(false); target.SetType(cmTarget::INSTALL_FILES, this->TargetName.c_str()); + target.SetMakefile(this->Makefile); + target.SetInAll(false); target.SetInstallPath(args[0].c_str()); if((args.size() > 1) && (args[1] == "FILES")) diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx index e38f0a6..b04b1e1 100644 --- a/Source/cmInstallProgramsCommand.cxx +++ b/Source/cmInstallProgramsCommand.cxx @@ -33,8 +33,9 @@ bool cmInstallProgramsCommand // Create an INSTALL_PROGRAMS target specifically for this path. this->TargetName = "INSTALL_PROGRAMS_"+args[0]; cmTarget& target = this->Makefile->GetTargets()[this->TargetName]; - target.SetInAll(false); target.SetType(cmTarget::INSTALL_PROGRAMS, this->TargetName.c_str()); + target.SetMakefile(this->Makefile); + target.SetInAll(false); target.SetInstallPath(args[0].c_str()); std::vector::const_iterator s = args.begin(); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index d437899..ea5aaec 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -117,6 +117,7 @@ void cmLocalGenerator::SetGlobalGenerator(cmGlobalGenerator *gg) this->GlobalGenerator = gg; // setup the home directories + this->Makefile->GetProperties().SetCMakeInstance(gg->GetCMakeInstance()); this->Makefile->SetHomeDirectory( gg->GetCMakeInstance()->GetHomeDirectory()); this->Makefile->SetHomeOutputDirectory( @@ -200,15 +201,15 @@ void cmLocalGenerator::GenerateTestFiles() fout << "\""; } fout << ")" << std::endl; - std::map::const_iterator pit; - const std::map* mpit = &test->GetProperties(); + cmPropertyMap::const_iterator pit; + cmPropertyMap* mpit = &test->GetProperties(); if ( mpit->size() ) { fout << "SET_TESTS_PROPERTIES(" << test->GetName() << " PROPERTIES "; for ( pit = mpit->begin(); pit != mpit->end(); ++ pit ) { fout << " " << pit->first.c_str() << " \""; - const char* value = pit->second.c_str(); + const char* value = pit->second.GetValue(); for ( ; *value; ++ value ) { switch ( *value ) diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index 8253fee..f5c4187 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -316,7 +316,8 @@ ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf) mf.ExpandArguments(lff.Arguments, expandedArguments); if ((!expandedArguments.empty() && (expandedArguments[0] == this->Args[0])) - || mf.IsOn("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS")) + || cmSystemTools::IsOn + (mf.GetPropertyOrDefinition("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS"))) { return true; } diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index e4814de..4054bdf 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -816,9 +816,9 @@ void cmMakefile::AddUtilityCommand(const char* utilityName, bool all, { // Create a target instance for this utility. cmTarget target; + target.SetMakefile(this); target.SetType(cmTarget::UTILITY, utilityName); target.SetInAll(all); - target.SetMakefile(this); if(!comment) { @@ -1309,6 +1309,7 @@ void cmMakefile::AddLibrary(const char* lname, int shared, default: target.SetType(cmTarget::STATIC_LIBRARY, lname); } + target.SetMakefile(this); // Clear its dependencies. Otherwise, dependencies might persist // over changes in CMakeLists.txt, making the information stale and @@ -1316,7 +1317,6 @@ void cmMakefile::AddLibrary(const char* lname, int shared, target.ClearDependencyInformation( *this, lname ); target.SetInAll(in_all); target.GetSourceLists() = srcs; - target.SetMakefile(this); this->AddGlobalLinkInformation(lname, target); cmTargets::iterator it = this->Targets.insert(cmTargets::value_type(lname,target)).first; @@ -1329,9 +1329,9 @@ cmTarget* cmMakefile::AddExecutable(const char *exeName, { cmTarget target; target.SetType(cmTarget::EXECUTABLE, exeName); + target.SetMakefile(this); target.SetInAll(in_all); target.GetSourceLists() = srcs; - target.SetMakefile(this); this->AddGlobalLinkInformation(exeName, target); cmTargets::iterator it = this->Targets.insert(cmTargets::value_type(exeName,target)).first; @@ -2281,6 +2281,7 @@ cmSourceFile* cmMakefile::GetOrCreateSource(const char* sourceName, // we must create one cmSourceFile file; + file.GetProperties().SetCMakeInstance(this->GetCMakeInstance()); std::string path = cmSystemTools::GetFilenamePath(src); if(generated) { @@ -2328,6 +2329,7 @@ cmSourceFile* cmMakefile::GetOrCreateSource(const char* sourceName, this->AddSource(file); src = file.GetFullPath(); ret = this->GetSource(src.c_str()); + ret->GetProperties().SetCMakeInstance(this->GetCMakeInstance()); if (!ret) { cmSystemTools::Error( @@ -2738,11 +2740,28 @@ void cmMakefile::SetProperty(const char* prop, const char* value) { value = "NOTFOUND"; } - this->Properties[prop] = value; + + this->Properties.SetProperty(prop,value,cmProperty::DIRECTORY); +} + +const char *cmMakefile::GetPropertyOrDefinition(const char* prop) +{ + const char *ret = this->GetProperty(prop, cmProperty::DIRECTORY); + if (!ret) + { + ret = this->GetDefinition(prop); + } + return ret; } const char *cmMakefile::GetProperty(const char* prop) { + return this->GetProperty(prop, cmProperty::DIRECTORY); +} + +const char *cmMakefile::GetProperty(const char* prop, + cmProperty::ScopeType scope) +{ // watch for specific properties if (!strcmp("PARENT_DIRECTORY",prop)) { @@ -2764,24 +2783,21 @@ const char *cmMakefile::GetProperty(const char* prop) } this->SetProperty("LISTFILE_STACK",tmp.c_str()); } - std::map::const_iterator i = - this->Properties.find(prop); - if (i != this->Properties.end()) + + bool chain = false; + const char *retVal = + this->Properties.GetPropertyValue(prop, scope, chain); + if (chain) { - return i->second.c_str(); + return this->GetCMakeInstance()->GetProperty(prop,scope); } - return 0; + + return retVal; } -bool cmMakefile::GetPropertyAsBool(const char* prop) const +bool cmMakefile::GetPropertyAsBool(const char* prop) { - std::map::const_iterator i = - this->Properties.find(prop); - if (i != this->Properties.end()) - { - return cmSystemTools::IsOn(i->second.c_str()); - } - return false; + return cmSystemTools::IsOn(this->GetProperty(prop)); } @@ -2810,6 +2826,7 @@ cmTest* cmMakefile::CreateTest(const char* testName) } test = new cmTest; test->SetName(testName); + test->SetMakefile(this); this->Tests.push_back(test); return test; } @@ -2855,3 +2872,43 @@ std::string cmMakefile::GetListFileStack() } return tmp; } + +// define properties +void cmMakefile::DefineProperties(cmake *cm) +{ + cm->DefineProperty + ("ADDITIONAL_MAKE_CLEAN_FILES", cmProperty::DIRECTORY, + "Addditional files to clean during the make clean stage.", + "A list of files that will be cleaned as a part of the " + "\"make clean\" stage. "); + + cm->DefineProperty + ("CLEAN_NO_CUSTOM", cmProperty::DIRECTORY, + "Should the output of custom commands be left.", + "If this is true then the outputs of custom commands for this " + "directory will not be removed during the \"make clean\" stage. "); + + cm->DefineProperty + ("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS", cmProperty::DIRECTORY, + "Allow loops to have non-matching closing statements.", + "If this is set then the closing statement of control " + "structures in CMake will not require an exact match to the " + "opening statement. For example IF(foo) will not require " + "ENDIF(foo) but simple ENDIF() will work.", + true); + + cm->DefineProperty + ("LISTFILE_STACK", cmProperty::DIRECTORY, + "The current stack of listfiles being processed.", + "This property is mainly useful when trying to debug errors " + "in your CMake scripts. It returns a list of what list files " + "are currently being processed, in order. So if one listfile " + "does an INCLUDE command then that is effectively pushing " + "the included listfile onto the stack."); + + cm->DefineProperty + ("TEST_INCLUDE_FILE", cmProperty::DIRECTORY, + "A cmake file that will be included when ctest is run.", + "If you specify TEST_INCLUDE_FILE, that file will be " + "included and processed when ctest is run on the directory."); +} diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 943466f..cc4d3c9 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -22,6 +22,7 @@ #include "cmTarget.h" #include "cmListFileCache.h" #include "cmCacheManager.h" +#include "cmPropertyMap.h" #if defined(CMAKE_BUILD_WITH_CMAKE) #include "cmSourceGroup.h" @@ -697,7 +698,12 @@ public: ///! Set/Get a property of this directory void SetProperty(const char *prop, const char *value); const char *GetProperty(const char *prop); - bool GetPropertyAsBool(const char *prop) const; + const char *GetPropertyOrDefinition(const char *prop); + const char *GetProperty(const char *prop, cmProperty::ScopeType scope); + bool GetPropertyAsBool(const char *prop); + + // Get the properties + cmPropertyMap &GetProperties() { return this->Properties; }; typedef std::map DefinitionMap; ///! Initialize a makefile from its parent @@ -711,6 +717,10 @@ public: { this->InstallGenerators.push_back(g); } std::vector& GetInstallGenerators() { return this->InstallGenerators; } + + // Define the properties + static void DefineProperties(cmake *cm); + protected: // add link libraries and directories to the target void AddGlobalLinkInformation(const char* name, cmTarget& target); @@ -791,7 +801,7 @@ private: cmsys::RegularExpression cmDefineRegex; cmsys::RegularExpression cmDefine01Regex; - std::map Properties; + cmPropertyMap Properties; // should this makefile be processed before or after processing the parent bool PreOrder; diff --git a/Source/cmPropertyMap.cxx b/Source/cmPropertyMap.cxx index 7e4c3fc..925bfdd 100644 --- a/Source/cmPropertyMap.cxx +++ b/Source/cmPropertyMap.cxx @@ -18,6 +18,9 @@ #include "cmSystemTools.h" #include "cmake.h" +// define STRICT to get checking of all set and get property calls +//#define STRICT + cmProperty *cmPropertyMap::GetOrCreateProperty(const char *name) { cmPropertyMap::iterator it = this->find(name); @@ -41,7 +44,7 @@ void cmPropertyMap::SetProperty(const char *name, const char *value, return; } -#if 0 +#ifdef STRICT if (!this->CMakeInstance) { cmSystemTools::Error("CMakeInstance not set on a property map!"); @@ -92,7 +95,7 @@ const char *cmPropertyMap } // has the property been defined? -#if 0 +#ifdef STRICT if (!this->CMakeInstance) { cmSystemTools::Error("CMakeInstance not set on a property map!"); @@ -131,7 +134,10 @@ const char *cmPropertyMap if (it == this->end()) { // should we chain up? - chain = this->CMakeInstance->IsPropertyChained(name,scope); + if (this->CMakeInstance) + { + chain = this->CMakeInstance->IsPropertyChained(name,scope); + } return 0; } diff --git a/Source/cmSetDirectoryPropertiesCommand.cxx b/Source/cmSetDirectoryPropertiesCommand.cxx index e329e37..427ac73 100644 --- a/Source/cmSetDirectoryPropertiesCommand.cxx +++ b/Source/cmSetDirectoryPropertiesCommand.cxx @@ -27,59 +27,74 @@ bool cmSetDirectoryPropertiesCommand::InitialPass( this->SetError("called with incorrect number of arguments"); return false; } + + std::string errors; + bool ret = + cmSetDirectoryPropertiesCommand::RunCommand(this->Makefile, + args.begin() + 1, + args.end(), errors); + if (!ret) + { + this->SetError(errors.c_str()); + } + return ret; +} - std::vector::const_iterator ait; - for ( ait = args.begin()+1; - ait != args.end(); - ait += 2 ) +bool cmSetDirectoryPropertiesCommand +::RunCommand(cmMakefile *mf, + std::vector::const_iterator ait, + std::vector::const_iterator aitend, + std::string &errors) +{ + for (; ait != aitend; ait += 2 ) { - if ( ait +1 == args.end() ) + if ( ait +1 == aitend) { - this->SetError("Wrong number of arguments"); + errors = "Wrong number of arguments"; return false; } const std::string& prop = *ait; const std::string& value = *(ait+1); if ( prop == "VARIABLES" ) { - this->SetError - ("Variables and cache variables should be set using SET command"); + errors = + "Variables and cache variables should be set using SET command"; return false; } else if ( prop == "MACROS" ) { - this->SetError - ("Commands and macros cannot be set using SET_CMAKE_PROPERTIES"); + errors = + "Commands and macros cannot be set using SET_CMAKE_PROPERTIES"; return false; } else if ( prop == "INCLUDE_DIRECTORIES" ) { std::vector varArgsExpanded; cmSystemTools::ExpandListArgument(value, varArgsExpanded); - this->Makefile->SetIncludeDirectories(varArgsExpanded); + mf->SetIncludeDirectories(varArgsExpanded); } else if ( prop == "LINK_DIRECTORIES" ) { std::vector varArgsExpanded; cmSystemTools::ExpandListArgument(value, varArgsExpanded); - this->Makefile->SetLinkDirectories(varArgsExpanded); + mf->SetLinkDirectories(varArgsExpanded); } else if ( prop == "INCLUDE_REGULAR_EXPRESSION" ) { - this->Makefile->SetIncludeRegularExpression(value.c_str()); + mf->SetIncludeRegularExpression(value.c_str()); } else { if ( prop == "ADDITIONAL_MAKE_CLEAN_FILES" ) { // This property is not inherrited - if ( strcmp(this->Makefile->GetCurrentDirectory(), - this->Makefile->GetStartDirectory()) != 0 ) + if ( strcmp(mf->GetCurrentDirectory(), + mf->GetStartDirectory()) != 0 ) { continue; } } - this->Makefile->SetProperty(prop.c_str(), value.c_str()); + mf->SetProperty(prop.c_str(), value.c_str()); } } diff --git a/Source/cmSetDirectoryPropertiesCommand.h b/Source/cmSetDirectoryPropertiesCommand.h index ea9afbf..143ceb3 100644 --- a/Source/cmSetDirectoryPropertiesCommand.h +++ b/Source/cmSetDirectoryPropertiesCommand.h @@ -52,6 +52,14 @@ public: } /** + * Static entry point for use by other commands + */ + static bool RunCommand(cmMakefile *mf, + std::vector::const_iterator ait, + std::vector::const_iterator aitend, + std::string &errors); + + /** * Longer documentation. */ virtual const char* GetFullDocumentation() diff --git a/Source/cmSetTargetPropertiesCommand.cxx b/Source/cmSetTargetPropertiesCommand.cxx index cb7d60e..f7910a0 100644 --- a/Source/cmSetTargetPropertiesCommand.cxx +++ b/Source/cmSetTargetPropertiesCommand.cxx @@ -71,27 +71,14 @@ bool cmSetTargetPropertiesCommand::InitialPass( return false; } - cmTargets& targets = this->Makefile->GetTargets(); // now loop over all the targets int i; - unsigned int k; for(i = 0; i < numFiles; ++i) { - // if the file is already in the makefile just set properites on it - cmTargets::iterator t = targets.find(args[i]); - if ( t != targets.end()) + bool ret = cmSetTargetPropertiesCommand::SetOneTarget + (args[i].c_str(),propertyPairs,this->Makefile); + if (!ret) { - cmTarget& target = t->second; - // now loop through all the props and set them - for (k = 0; k < propertyPairs.size(); k = k + 2) - { - target.SetProperty(propertyPairs[k].c_str(), - propertyPairs[k+1].c_str()); - } - } - // if file is not already in the makefile, then add it - else - { std::string message = "Can not find target to add properties to: "; message += args[i]; this->SetError(message.c_str()); @@ -101,3 +88,30 @@ bool cmSetTargetPropertiesCommand::InitialPass( return true; } +bool cmSetTargetPropertiesCommand +::SetOneTarget(const char *tname, + std::vector &propertyPairs, + cmMakefile *mf) +{ + cmTargets& targets = mf->GetTargets(); + + // if the file is already in the makefile just set properites on it + cmTargets::iterator t = targets.find(tname); + if ( t != targets.end()) + { + cmTarget& target = t->second; + // now loop through all the props and set them + unsigned int k; + for (k = 0; k < propertyPairs.size(); k = k + 2) + { + target.SetProperty(propertyPairs[k].c_str(), + propertyPairs[k+1].c_str()); + } + } + // if file is not already in the makefile, then add it + else + { + return false; + } + return true; +} diff --git a/Source/cmSetTargetPropertiesCommand.h b/Source/cmSetTargetPropertiesCommand.h index 009127f..c25895c 100644 --- a/Source/cmSetTargetPropertiesCommand.h +++ b/Source/cmSetTargetPropertiesCommand.h @@ -36,7 +36,7 @@ public: /** * The name of the command as specified in CMakeList.txt. */ - virtual const char* GetName() { return "SET_TARGET_PROPERTIES";} + virtual const char* GetName() { return "SET_TARGET_PROPERTIES";} /** * Succinct documentation. @@ -47,6 +47,13 @@ public: } /** + * Used by this command and cmSetPropertiesCommand + */ + static bool SetOneTarget(const char *tname, + std::vector &propertyPairs, + cmMakefile *mf); + + /** * Longer documentation. */ virtual const char* GetFullDocumentation() diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index 7f2c663..52148b2 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -17,7 +17,7 @@ #include "cmSourceFile.h" #include "cmSystemTools.h" - +#include "cmake.h" // Set the name of the class and the full path to the file. // The class must be found in dir and end in name.cxx, name.txx, @@ -179,7 +179,8 @@ void cmSourceFile::SetProperty(const char* prop, const char* value) { value = "NOTFOUND"; } - this->Properties[prop] = value; + + this->Properties.SetProperty(prop, value, cmProperty::SOURCE_FILE); } const char *cmSourceFile::GetProperty(const char* prop) const @@ -191,24 +192,14 @@ const char *cmSourceFile::GetProperty(const char* prop) const return this->FullPath.c_str(); } - std::map::const_iterator i = - this->Properties.find(prop); - if (i != this->Properties.end()) - { - return i->second.c_str(); - } - return 0; + bool chain = false; + return this->Properties.GetPropertyValue(prop,cmProperty::SOURCE_FILE, + chain); } bool cmSourceFile::GetPropertyAsBool(const char* prop) const { - std::map::const_iterator i = - this->Properties.find(prop); - if (i != this->Properties.end()) - { - return cmSystemTools::IsOn(i->second.c_str()); - } - return false; + return cmSystemTools::IsOn(this->GetProperty(prop)); } void cmSourceFile::SetCustomCommand(cmCustomCommand* cc) @@ -229,3 +220,115 @@ const std::string& cmSourceFile::GetSourceNameWithoutLastExtension() } return this->SourceNameWithoutLastExtension; } + +cmSourceFile::cmSourceFile() +{ + this->CustomCommand = 0; +} + +// define properties +void cmSourceFile::DefineProperties(cmake *cm) +{ + // define properties + cm->DefineProperty + ("ABSTRACT", cmProperty::SOURCE_FILE, + "Is this source file an abstract class.", + "A property ona source file that indicates if the source file " + "represents a class that is abstract. This only makes sense for " + "languages that have a notion of an abstract class and it is " + "only used by somw tools that wrap classes into other languages."); + + cm->DefineProperty + ("COMPILE_FLAGS", cmProperty::SOURCE_FILE, + "Additional flags to be added when compiling this source file.", + "These flags will be added to the list of compile flags when " + "this source file."); + + cm->DefineProperty + ("EXTERNAL_OBJECT", cmProperty::SOURCE_FILE, + "If set to true then this is an object file.", + "If this property is set to true then the source file " + "is really an object file and should not be compiled. " + "It will still be linked into the target though."); + + cm->DefineProperty + ("EXTRA_CONTENT", cmProperty::SOURCE_FILE, + "Is this file part of a target's extra content.", + "If this property is set, the source file will be added to the " + "target's list of extra content. This is used by makefile " + "generators for some sort of Mac budle framework support."); + + cm->DefineProperty + ("GENERATED", cmProperty::SOURCE_FILE, + "Is this source file generated as part of the build process.", + "If a source file is generated by the build process CMake will " + "handle it differently in temrs of dependency checking etc. " + "Otherwise having a non-existent source file could create problems."); + + cm->DefineProperty + ("HEADER_FILE_ONLY", cmProperty::SOURCE_FILE, + "Is this source file only a header file.", + "A property ona source file that indicates if the source file " + "is a header file with no associated implementation. This is " + "set automatically based on the file extension and is used by " + "CMake to determine is certain dependency information should be " + "computed."); + + cm->DefineProperty + ("KEEP_EXTENSION", cmProperty::SOURCE_FILE, + "Make th eoutput file have the same extension as the source file.", + "If this property is set then the file extension of the output " + "file will be the same as that of the source file. Normally " + "the output file extension is computed based on the language " + "of the source file, for example .cxx will go to a .o extension."); + + cm->DefineProperty + ("LANGUAGE", cmProperty::SOURCE_FILE, + "What programming language is the file.", + "A property that can be set to indicate what programming language " + "the source file is. If it is not set the language is determined " + "based on the file extension. Typical values are CXX C etc."); + + cm->DefineProperty + ("LOCATION", cmProperty::SOURCE_FILE, + "The full path to a source file.", + "A read only property on a SOURCE FILE that contains the full path " + "to the source file."); + + cm->DefineProperty + ("MACOSX_PACKAGE_LOCATION", cmProperty::SOURCE_FILE, + "Location for MACOSX bundles and frameworks.", + "MACOSX_PACKAGE_LOCATION is the property of a file within a mac osx " + "bundle or framework that specifies where this file should be " + "copied. This makes sense for things like icons and other " + "resources."); + + cm->DefineProperty + ("MACOSX_CONTENT", cmProperty::SOURCE_FILE, + "If true then this is part of a MACOSX bundle or framework.", + "MACOSX_CONTENT is a flag that if true this file will be copied " + "to the bundle or framework."); + + cm->DefineProperty + ("OBJECT_DEPENDS", cmProperty::SOURCE_FILE, + "Additional dependencies.", + "Additional dependencies that should be checked as part of " + "building this source file."); + + cm->DefineProperty + ("SYMBOLIC", cmProperty::SOURCE_FILE, + "Is this just a name for a rule.", + "If SYMBOLIC (boolean) is set to true the build system will be " + "informed that the source file is not actually created on disk but " + "instead used as a symbolic name for a build rule."); + + cm->DefineProperty + ("WRAP_EXCLUDE", cmProperty::SOURCE_FILE, + "Exclude this source file from any code wrapping techniques.", + "Some packages can wrap source files into alternate languages " + "to provide additional functionality. For example, C++ code " + "can be wrapped into Java or Python etc using SWIG etc. " + "If WRAP_EXCLUDE is set to true (1 etc) that indicates then " + "this source file should not be wrapped."); +} + diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index c8391e2..0b636ef 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -18,6 +18,9 @@ #define cmSourceFile_h #include "cmCustomCommand.h" +#include "cmPropertyMap.h" + +class cmake; /** \class cmSourceFile * \brief Represent a class loaded from a makefile. @@ -32,10 +35,7 @@ public: * Construct instance as a concrete class with both a * .h and .cxx file. */ - cmSourceFile() - { - this->CustomCommand = 0; - } + cmSourceFile(); ~cmSourceFile() { this->SetCustomCommand(0); @@ -108,8 +108,14 @@ public: */ const std::string& GetSourceNameWithoutLastExtension(); + // Get the properties + cmPropertyMap &GetProperties() { return this->Properties; }; + + // Define the properties + static void DefineProperties(cmake *cm); + private: - std::map Properties; + cmPropertyMap Properties; cmCustomCommand *CustomCommand; std::string FullPath; std::string SourceName; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 0b6f21d..857cdba 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -15,6 +15,7 @@ =========================================================================*/ #include "cmTarget.h" +#include "cmake.h" #include "cmMakefile.h" #include "cmSourceFile.h" #include "cmLocalGenerator.h" @@ -36,6 +37,230 @@ cmTarget::cmTarget() this->LinkLibrariesAnalyzed = false; this->LinkDirectoriesComputed = false; this->HaveInstallRule = false; + +} + +// define properties +void cmTarget::DefineProperties(cmake *cm) +{ + cm->DefineProperty + ("BUILD_WITH_INSTALL_RPATH", cmProperty::TARGET, + "Should build tree targets have install tree rpaths.", + "BUILD_WITH_INSTALL_RPATH is a boolean specifying whether to link " + "the target in the build tree with the INSTALL_RPATH. This takes " + "precedence over SKIP_BUILD_RPATH and avoids the need for relinking " + "before installation."); + + cm->DefineProperty + ("CLEAN_DIRECT_OUTPUT", cmProperty::TARGET, + "Do not delete other varients of this target.", + "When a library is built CMake by default generates code to remove " + "any existing library using all possible names. This is needed " + "to support libraries that switch between STATIC and SHARED by " + "a user option. However when using OUTPUT_NAME to build a static " + "and shared library of the same name using different logical target " + "names the two targets will remove each other's files. This can be " + "prevented by setting the CLEAN_DIRECT_OUTPUT property to 1."); + + cm->DefineProperty + ("COMPILE_FLAGS", cmProperty::TARGET, + "Additional flags to yse when compiling this target's sources.", + "The COMPILE_FLAGS property sets additional compiler flags used " + "to build sources within the target. It may also be used to pass " + "additional preprocessor definitions."); + + cm->DefineProperty + ("DEFINE_SYMBOL", cmProperty::TARGET, + "Define a symbol when compiling this target's sources.", + "DEFINE_SYMBOL sets the name of the preprocessor symbol defined when " + "compiling sources in a shared library. " + "If not set here then it is set to target_EXPORTS by default " + "(with some substitutions if the target is not a valid C " + "identifier). This is useful for headers to know whether they are " + "being included from inside their library our outside to properly " + "setup dllexport/dllimport decorations. "); + + cm->DefineProperty + ("DEBUG_POSTFIX", cmProperty::TARGET, + "A postfix that will be applied to this target when build debug.", + "A property on a target that sepcifies a postfix to add to the " + "target name when built in debug mode. For example foo.dll " + "versus fooD.dll"); + + cm->DefineProperty + ("EchoString", cmProperty::TARGET, + "A message to be displayed when the target it built.", + "A message to display on some generaters (such as makefiles) when " + "the target is built."); + + cm->DefineProperty + ("HAS_CXX", cmProperty::TARGET, + "Force a target to use the CXX linker.", + "Setting HAS_CXX on a target will force the target to use the " + "C++ linker (and C++ runtime libraries) for linking even if the " + "target has no C++ code in it."); + + cm->DefineProperty + ("IMPORT_PREFIX", cmProperty::TARGET, + "What comes before the import library name.", + "Similar to the target property PREFIX, but used for import libraries " + "(typically corresponding to a DLL) instead of regular libraries. " + "A target property that can be set to override the prefix " + "(such as \"lib\") on an import library name."); + + cm->DefineProperty + ("IMPORT_SUFFIX", cmProperty::TARGET, + "What comes after the import library name.", + "Similar to the target property SUFFIX, but used for import libraries " + "(typically corresponding to a DLL) instead of regular libraries. " + "A target property that can be set to override the suffix " + "(such as \".lib\") on an import library name."); + + cm->DefineProperty + ("IN_ALL", cmProperty::TARGET, + "Is this target part of the all target.", + "A property on a target that indicates if the target is included as " + "part of the default build target. If it is, then with a Makefile " + "for example typing make will couse this target to be built as well. " + "The same concept applies to the default build of other generators."); + + cm->DefineProperty + ("INSTALL_NAME_DIR", cmProperty::TARGET, + "Mac OSX directory name for installed targets.", + "INSTALL_NAME_DIR is a string specifying the " + "directory portion of the \"install_name\" field of shared libraries " + "on Mac OSX to use in the installed targets. "); + + cm->DefineProperty + ("INSTALL_RPATH", cmProperty::TARGET, + "The rpath to use for installed targets.", + "A semicolon-separated list specifying the rpath " + "to use in installed targets (for platforms that support it)."); + + cm->DefineProperty + ("INSTALL_RPATH_USE_LINK_PATH", cmProperty::TARGET, + "Add paths to linker search and installed rpath.", + "INSTALL_RPATH_USE_LINK_PATH is a boolean that if set to true will " + "append directories in the linker search path and outside the " + "project to the INSTALL_RPATH. "); + + cm->DefineProperty + ("LINK_FLAGS", cmProperty::TARGET, + "Additional flags to use when linking this target.", + "The LINK_FLAGS property can be used to add extra flags to the " + "link step of a target. LINK_FLAGS_ will add to the " + "configuration , " + "for example, DEBUG, RELEASE, MINSIZEREL, RELWITHDEBINFO. "); + + cm->DefineProperty + ("LINKER_LANGUAGE", cmProperty::TARGET, + "What tool to use for linking, based on language.", + "The LINKER_LANGUAGE property is used to change the tool " + "used to link an executable or shared library. The default is " + "set the language to match the files in the library. CXX and C " + "are common values for this property."); + + cm->DefineProperty + ("LOCATION", cmProperty::TARGET, + "Where a target will be written on disk.", + "A read only property on a target that indicates where that target " + "will be written. For libraries and execuatables this will be where " + "the file is written on disk. This property is computed based on a " + "number of other settings."); + + cm->DefineProperty + ("OUTPUT_NAME", cmProperty::TARGET, + "Sets the real name of a target when it is built.", + "Sets the real name of a target when it is built and " + "can be used to help create two targets of the same name even though " + "CMake requires unique logical target names. There is also a " + "_OUTPUT_NAME that can set the output name on a " + "per-configuration basis."); + + cm->DefineProperty + ("PRE_INSTALL_SCRIPT", cmProperty::TARGET, + "Deprecated install support.", + "The PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT properties are the " + "old way to specify CMake scripts to run before and after " + "installing a target. They are used only when the old " + "INSTALL_TARGETS command is used to install the target. Use the " + "INSTALL command instead."); + + cm->DefineProperty + ("PREFIX", cmProperty::TARGET, + "What comes before the library name.", + "A target property that can be set to override the prefix " + "(such as \"lib\") on a library name."); + + cm->DefineProperty + ("POST_INSTALL_SCRIPT", cmProperty::TARGET, + "Deprecated install support.", + "The PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT properties are the " + "old way to specify CMake scripts to run before and after " + "installing a target. They are used only when the old " + "INSTALL_TARGETS command is used to install the target. Use the " + "INSTALL command instead."); + + cm->DefineProperty + ("SKIP_BUILD_RPATH", cmProperty::TARGET, + "Should rpaths be used for the build tree.", + "SKIP_BUILD_RPATH is a boolean specifying whether to skip automatic " + "generation of an rpath allowing the target to run from the " + "build tree. "); + + cm->DefineProperty + ("SOVERSION", cmProperty::TARGET, + "What version number is this target.", + "For shared libraries VERSION and SOVERSION can be used to specify " + "the build version and api version respectively. When building or " + "installing appropriate symlinks are created if the platform " + "supports symlinks and the linker supports so-names. " + "If only one of both is specified the missing is assumed to have " + "the same version number. " + "For shared libraries and executables on Windows the VERSION " + "attribute is parsed to extract a \"major.minor\" version number. " + "These numbers are used as the image version of the binary. "); + + cm->DefineProperty + ("STATIC_LIBRARY_FLAGS", cmProperty::TARGET, + "Extra flags to use when linking static libraries.", + "Extra flags to use when linking a static library."); + + cm->DefineProperty + ("SUFFIX", cmProperty::TARGET, + "What comes after the library name.", + "A target property that can be set to override the suffix " + "(such as \".so\") on a library name."); + + cm->DefineProperty + ("VERSION", cmProperty::TARGET, + "What version number is this target.", + "For shared libraries VERSION and SOVERSION can be used to specify " + "the build version and api version respectively. When building or " + "installing appropriate symlinks are created if the platform " + "supports symlinks and the linker supports so-names. " + "If only one of both is specified the missing is assumed to have " + "the same version number. " + "For executables VERSION can be used to specify the build version. " + "When building or installing appropriate symlinks are created if " + "the platform supports symlinks. " + "For shared libraries and executables on Windows the VERSION " + "attribute is parsed to extract a \"major.minor\" version number. " + "These numbers are used as the image version of the binary. "); + + + cm->DefineProperty + ("WIN32_EXECUTABLE", cmProperty::TARGET, + "Used to specify Windows executable with a WinMain entry point.", + "This can be set to indicate that a target is a Windows executable " + "in contrast to a console application for example. This changes " + "how the executable will be linked."); + + + // define some properties without documentation + cm->DefineProperty("DEBUG_OUTPUT_NAME", cmProperty::TARGET,0,0); + cm->DefineProperty("RELEASE_OUTPUT_NAME", cmProperty::TARGET,0,0); + cm->DefineProperty("LINK_FLAGS_DEBUG", cmProperty::TARGET,0,0); } void cmTarget::SetType(TargetType type, const char* name) @@ -60,6 +285,9 @@ void cmTarget::SetMakefile(cmMakefile* mf) // Set our makefile. this->Makefile = mf; + // set the cmake instance of the properties + this->Properties.SetCMakeInstance(mf->GetCMakeInstance()); + // Setup default property values. this->SetPropertyDefault("INSTALL_NAME_DIR", ""); this->SetPropertyDefault("INSTALL_RPATH", ""); @@ -332,6 +560,8 @@ void cmTarget::GenerateSourceFilesFromSourceLists( cmMakefile &mf) if (!done) { cmSourceFile file; + file.GetProperties(). + SetCMakeInstance(this->Makefile->GetCMakeInstance()); file.SetProperty("ABSTRACT","0"); file.SetName(temps.c_str(), mf.GetCurrentDirectory(), mf.GetSourceExtensions(), @@ -841,7 +1071,8 @@ void cmTarget::SetProperty(const char* prop, const char* value) { value = "NOTFOUND"; } - this->Properties[prop] = value; + + this->Properties.SetProperty(prop, value, cmProperty::TARGET); } const char* cmTarget::GetDirectory(const char* config) @@ -925,6 +1156,12 @@ void cmTarget::GetTargetVersion(int& major, int& minor) const char *cmTarget::GetProperty(const char* prop) { + return this->GetProperty(prop, cmProperty::TARGET); +} + +const char *cmTarget::GetProperty(const char* prop, + cmProperty::ScopeType scope) +{ // watch for special "computed" properties that are dependent on other // properties or variables, always recompute them if (!strcmp(prop,"LOCATION")) @@ -984,25 +1221,21 @@ const char *cmTarget::GetProperty(const char* prop) } return 0; } - - std::map::const_iterator i = - this->Properties.find(prop); - if (i != this->Properties.end()) + + bool chain = false; + const char *retVal = + this->Properties.GetPropertyValue(prop, scope, chain); + if (chain) { - return i->second.c_str(); + return this->Makefile->GetProperty(prop,scope); } - return 0; + + return retVal; } bool cmTarget::GetPropertyAsBool(const char* prop) { - std::map::const_iterator i = - this->Properties.find(prop); - if (i != this->Properties.end()) - { - return cmSystemTools::IsOn(i->second.c_str()); - } - return false; + return cmSystemTools::IsOn(this->GetProperty(prop)); } const char* cmTarget::GetLinkerLanguage(cmGlobalGenerator* gg) diff --git a/Source/cmTarget.h b/Source/cmTarget.h index d6e3f8d..de70c49 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -18,7 +18,9 @@ #define cmTarget_h #include "cmCustomCommand.h" +#include "cmPropertyMap.h" +class cmake; class cmMakefile; class cmSourceFile; class cmGlobalGenerator; @@ -165,6 +167,7 @@ public: ///! Set/Get a property of this target file void SetProperty(const char *prop, const char *value); const char *GetProperty(const char *prop); + const char *GetProperty(const char *prop, cmProperty::ScopeType scope); bool GetPropertyAsBool(const char *prop); /** Get the directory in which this target will be built. If the @@ -249,6 +252,12 @@ public: std::string GetInstallNameDirForBuildTree(const char* config); std::string GetInstallNameDirForInstallTree(const char* config); + // Get the properties + cmPropertyMap &GetProperties() { return this->Properties; }; + + // Define the properties + static void DefineProperties(cmake *cm); + private: /** * A list of direct dependencies. Use in conjunction with DependencyMap. @@ -320,6 +329,7 @@ private: // Use a makefile variable to set a default for the given property. // If the variable is not defined use the given default instead. void SetPropertyDefault(const char* property, const char* default_value); + private: std::string Name; std::vector PreBuildCommands; @@ -342,7 +352,7 @@ private: std::string Location; std::set Utilities; bool RecordDependencies; - std::map Properties; + cmPropertyMap Properties; LinkLibraryVectorType OriginalLinkLibraries; // The cmMakefile instance that owns this target. This should diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx index ee7d952..42b15aa 100644 --- a/Source/cmTest.cxx +++ b/Source/cmTest.cxx @@ -17,9 +17,12 @@ #include "cmTest.h" #include "cmSystemTools.h" +#include "cmake.h" +#include "cmMakefile.h" cmTest::cmTest() { + this->Makefile = 0; } cmTest::~cmTest() @@ -52,24 +55,18 @@ void cmTest::SetArguments(const std::vector& args) const char *cmTest::GetProperty(const char* prop) const { - std::map::const_iterator i = - this->Properties.find(prop); - if (i != this->Properties.end()) + bool chain = false; + const char *retVal = + this->Properties.GetPropertyValue(prop, cmProperty::TEST, chain); + if (chain) { - return i->second.c_str(); + return this->Makefile->GetProperty(prop,cmProperty::TEST); } - return 0; } bool cmTest::GetPropertyAsBool(const char* prop) const { - std::map::const_iterator i = - this->Properties.find(prop); - if (i != this->Properties.end()) - { - return cmSystemTools::IsOn(i->second.c_str()); - } - return false; + return cmSystemTools::IsOn(this->GetProperty(prop)); } void cmTest::SetProperty(const char* prop, const char* value) @@ -82,6 +79,46 @@ void cmTest::SetProperty(const char* prop, const char* value) { value = "NOTFOUND"; } - this->Properties[prop] = value; + + this->Properties.SetProperty(prop, value, cmProperty::TEST); +} + +//---------------------------------------------------------------------------- +void cmTest::SetMakefile(cmMakefile* mf) +{ + // Set our makefile. + this->Makefile = mf; + this->Properties.SetCMakeInstance(mf->GetCMakeInstance()); } +// define properties +void cmTest::DefineProperties(cmake *cm) +{ + // define properties + cm->DefineProperty + ("FAIL_REGULAR_EXPRESSION", cmProperty::TEST, + "If the output matches this regular expression tes test will fail.", + "If set, if the output matches one of " + "specified regular expressions, the test will fail." + "For example: PASS_REGULAR_EXPRESSION \"[^a-z]Error;ERROR;Failed\""); + + cm->DefineProperty + ("MEASUREMENT", cmProperty::TEST, + "Specify a DART meansurement and value to be reported for a test.", + "If set to a name then that name will be reported to DART as a " + "named measurement with a value of 1. You may also specify a value " + "by setting MEASUREMENT to \"measurement=value\"."); + + cm->DefineProperty + ("PASS_REGULAR_EXPRESSION", cmProperty::TEST, + "The output must match this regular expression for the test to pass.", + "If set, the test output will be checked " + "against the specified regular expressions and at least one of the" + " regular expressions has to match, otherwise the test will fail."); + + cm->DefineProperty + ("WILL_FAIL", cmProperty::TEST, + "If set to true, this will invert the pass/fail flag of the test.", + "This property can be used for tests that are expected to fail and " + "return a non zero return code."); +} diff --git a/Source/cmTest.h b/Source/cmTest.h index 2f12835..9594a46 100644 --- a/Source/cmTest.h +++ b/Source/cmTest.h @@ -18,6 +18,8 @@ #define cmTest_h #include "cmCustomCommand.h" +#include "cmPropertyMap.h" +class cmMakefile; /** \class cmTest * \brief Represent a test @@ -52,16 +54,24 @@ public: void SetProperty(const char *prop, const char *value); const char *GetProperty(const char *prop) const; bool GetPropertyAsBool(const char *prop) const; - const std::map& GetProperties() const - { - return this->Properties; - } + cmPropertyMap &GetProperties() { return this->Properties; }; + // Define the properties + static void DefineProperties(cmake *cm); + + ///! Set the cmMakefile that owns this test + void SetMakefile(cmMakefile *mf); + cmMakefile *GetMakefile() { return this->Makefile;}; + private: - std::map Properties; + cmPropertyMap Properties; cmStdString Name; cmStdString Command; std::vector Args; + + // The cmMakefile instance that owns this target. This should + // always be set. + cmMakefile* Makefile; }; #endif diff --git a/Source/cmVTKMakeInstantiatorCommand.cxx b/Source/cmVTKMakeInstantiatorCommand.cxx index f39c6b5..9f7a2f9 100644 --- a/Source/cmVTKMakeInstantiatorCommand.cxx +++ b/Source/cmVTKMakeInstantiatorCommand.cxx @@ -164,6 +164,8 @@ cmVTKMakeInstantiatorCommand // Add the generated source file into the source list. cmSourceFile file; + file.GetProperties().SetCMakeInstance + (this->Makefile->GetCMakeInstance()); file.SetProperty("WRAP_EXCLUDE","1"); file.SetProperty("ABSTRACT","0"); file.SetName(fileName.c_str(), filePath.c_str(), @@ -204,6 +206,8 @@ cmVTKMakeInstantiatorCommand // Add the generated source file into the source list. cmSourceFile file; + file.GetProperties().SetCMakeInstance + (this->Makefile->GetCMakeInstance()); file.SetProperty("WRAP_EXCLUDE","1"); file.SetProperty("ABSTRACT","0"); file.SetName(fileName.c_str(), filePath.c_str(), diff --git a/Source/cmVTKWrapJavaCommand.cxx b/Source/cmVTKWrapJavaCommand.cxx index fd1c16f..11f0dc6 100644 --- a/Source/cmVTKWrapJavaCommand.cxx +++ b/Source/cmVTKWrapJavaCommand.cxx @@ -70,6 +70,8 @@ bool cmVTKWrapJavaCommand::InitialPass(std::vector const& argsIn) if (!curr || !curr->GetPropertyAsBool("WRAP_EXCLUDE")) { cmSourceFile file; + file.GetProperties().SetCMakeInstance + (this->Makefile->GetCMakeInstance()); if (curr) { file.SetProperty("ABSTRACT",curr->GetProperty("ABSTRACT")); diff --git a/Source/cmVTKWrapPythonCommand.cxx b/Source/cmVTKWrapPythonCommand.cxx index fb2653e..9b3ea35 100644 --- a/Source/cmVTKWrapPythonCommand.cxx +++ b/Source/cmVTKWrapPythonCommand.cxx @@ -70,6 +70,8 @@ bool cmVTKWrapPythonCommand::InitialPass(std::vector const& if (!curr || !curr->GetPropertyAsBool("WRAP_EXCLUDE")) { cmSourceFile file; + file.GetProperties().SetCMakeInstance + (this->Makefile->GetCMakeInstance()); if (curr) { file.SetProperty("ABSTRACT",curr->GetProperty("ABSTRACT")); @@ -90,6 +92,8 @@ bool cmVTKWrapPythonCommand::InitialPass(std::vector const& } cmSourceFile cfile; + cfile.GetProperties().SetCMakeInstance + (this->Makefile->GetCMakeInstance()); cfile.SetProperty("ABSTRACT","0"); this->CreateInitFile(res); cfile.SetName(initName.c_str(), this->Makefile->GetCurrentOutputDirectory(), diff --git a/Source/cmVTKWrapTclCommand.cxx b/Source/cmVTKWrapTclCommand.cxx index 25de30f..57e3f99 100644 --- a/Source/cmVTKWrapTclCommand.cxx +++ b/Source/cmVTKWrapTclCommand.cxx @@ -106,6 +106,8 @@ bool cmVTKWrapTclCommand::InitialPass(std::vector const& argsIn) if (!curr || !curr->GetPropertyAsBool("WRAP_EXCLUDE")) { cmSourceFile file; + file.GetProperties().SetCMakeInstance + (this->Makefile->GetCMakeInstance()); std::string srcDir = cdir; if (curr) { @@ -128,6 +130,8 @@ bool cmVTKWrapTclCommand::InitialPass(std::vector const& argsIn) } // add the init file cmSourceFile cfile; + cfile.GetProperties().SetCMakeInstance + (this->Makefile->GetCMakeInstance()); cfile.SetProperty("ABSTRACT","0"); std::string newName = this->LibraryName; newName += "Init"; diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx index eccd73e..e4e17d9 100644 --- a/Source/cmWhileCommand.cxx +++ b/Source/cmWhileCommand.cxx @@ -81,7 +81,8 @@ ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) if(!cmSystemTools::Strucmp(lff.Name.c_str(),"endwhile")) { if (lff.Arguments == this->Args - || mf.IsOn("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS")) + || cmSystemTools::IsOn + (mf.GetPropertyOrDefinition("CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS"))) { return true; } diff --git a/Source/cmake.cxx b/Source/cmake.cxx index db91e21..2d813f5 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -23,7 +23,9 @@ #include "cmCommand.h" #include "cmFileTimeComparison.h" #include "cmGeneratedFileStream.h" +#include "cmSourceFile.h" #include "cmVersion.h" +#include "cmTest.h" #if defined(CMAKE_BUILD_WITH_CMAKE) # include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback. @@ -116,6 +118,14 @@ cmake::cmake() this->ClearBuildSystem = false; this->FileComparison = new cmFileTimeComparison; + this->Properties.SetCMakeInstance(this); + + // initialize properties + cmSourceFile::DefineProperties(this); + cmTarget::DefineProperties(this); + cmMakefile::DefineProperties(this); + cmTest::DefineProperties(this); + #ifdef __APPLE__ struct rlimit rlp; if(!getrlimit(RLIMIT_STACK, &rlp)) @@ -1990,6 +2000,28 @@ void cmake::GetCommandDocumentation( v.push_back(empty); } +void cmake::GetPropertiesDocumentation(std::vector& v) +{ + // get the properties for cmake + + // get them for any generators + + // get them for Directories + this->DirectoryProperties.GetPropertiesDocumentation(v); + + // get them for targets + this->TargetProperties.GetPropertiesDocumentation(v); + + // get them for source files + this->SourceFileProperties.GetPropertiesDocumentation(v); + + // get them for tests + this->TestProperties.GetPropertiesDocumentation(v); + + cmDocumentationEntry empty = {0,0,0}; + v.push_back(empty); +} + void cmake::GetGeneratorDocumentation(std::vector& v) { for(RegisteredGeneratorsMap::const_iterator i = this->Generators.begin(); @@ -2766,3 +2798,111 @@ int cmake::ExecuteLinkScript(std::vector& args) // Return the final resulting return value. return result; } + +void cmake::DefineProperty(const char *name, cmProperty::ScopeType scope, + const char *ShortDescription, + const char *FullDescription, + bool chained) +{ + switch (scope) + { + case cmProperty::GLOBAL: + this->GlobalProperties.DefineProperty(name,scope,ShortDescription, + FullDescription, chained); + break; + case cmProperty::TARGET: + this->TargetProperties.DefineProperty(name,scope,ShortDescription, + FullDescription, chained); + break; + case cmProperty::SOURCE_FILE: + this->SourceFileProperties.DefineProperty(name,scope,ShortDescription, + FullDescription, chained); + break; + case cmProperty::DIRECTORY: + this->DirectoryProperties.DefineProperty(name,scope,ShortDescription, + FullDescription, chained); + break; + case cmProperty::TEST: + this->TestProperties.DefineProperty(name,scope,ShortDescription, + FullDescription, chained); + break; + } +} + +bool cmake::IsPropertyDefined(const char *name, cmProperty::ScopeType scope) +{ + switch (scope) + { + case cmProperty::GLOBAL: + return this->GlobalProperties.IsPropertyDefined(name); + break; + case cmProperty::TARGET: + return this->TargetProperties.IsPropertyDefined(name); + break; + case cmProperty::SOURCE_FILE: + return this->SourceFileProperties.IsPropertyDefined(name); + break; + case cmProperty::DIRECTORY: + return this->DirectoryProperties.IsPropertyDefined(name); + break; + case cmProperty::TEST: + return this->TestProperties.IsPropertyDefined(name); + break; + } + + return false; +} + +bool cmake::IsPropertyChained(const char *name, cmProperty::ScopeType scope) +{ + switch (scope) + { + case cmProperty::GLOBAL: + return this->GlobalProperties.IsPropertyChained(name); + break; + case cmProperty::TARGET: + return this->TargetProperties.IsPropertyChained(name); + break; + case cmProperty::SOURCE_FILE: + return this->SourceFileProperties.IsPropertyChained(name); + break; + case cmProperty::DIRECTORY: + return this->DirectoryProperties.IsPropertyChained(name); + break; + case cmProperty::TEST: + return this->DirectoryProperties.IsPropertyChained(name); + break; + } + + return false; +} + +void cmake::SetProperty(const char* prop, const char* value) +{ + if (!prop) + { + return; + } + if (!value) + { + value = "NOTFOUND"; + } + + this->Properties.SetProperty(prop, value, cmProperty::TARGET); +} + +const char *cmake::GetProperty(const char* prop) +{ + return this->GetProperty(prop, cmProperty::GLOBAL); +} + +const char *cmake::GetProperty(const char* prop, cmProperty::ScopeType scope) +{ + bool chain = false; + return this->Properties.GetPropertyValue(prop, scope, chain); +} + +bool cmake::GetPropertyAsBool(const char* prop) +{ + return cmSystemTools::IsOn(this->GetProperty(prop)); +} diff --git a/Source/cmake.h b/Source/cmake.h index 39dbd2f..c32e3f1 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -41,6 +41,8 @@ #define cmake_h #include "cmSystemTools.h" +#include "cmPropertyDefinitionMap.h" +#include "cmPropertyMap.h" class cmGlobalGenerator; class cmLocalGenerator; @@ -235,8 +237,18 @@ class cmake cmVariableWatch* GetVariableWatch() { return this->VariableWatch; } void GetCommandDocumentation(std::vector&) const; + void GetPropertiesDocumentation(std::vector&); void GetGeneratorDocumentation(std::vector&); + ///! Set/Get a property of this target file + void SetProperty(const char *prop, const char *value); + const char *GetProperty(const char *prop); + const char *GetProperty(const char *prop, cmProperty::ScopeType scope); + bool GetPropertyAsBool(const char *prop); + + // Get the properties + cmPropertyMap &GetProperties() { return this->Properties; }; + ///! Do all the checks before running configure int DoPreConfigureChecks(); @@ -278,7 +290,24 @@ class cmake bool GetDebugOutput() { return this->DebugOutput; } void DebugOutputOn() { this->DebugOutput = true;} + // Define a property + void DefineProperty(const char *name, cmProperty::ScopeType scope, + const char *ShortDescription, + const char *FullDescription, + bool chain = false); + + // Is a property defined? + bool IsPropertyDefined(const char *name, cmProperty::ScopeType scope); + bool IsPropertyChained(const char *name, cmProperty::ScopeType scope); + protected: + cmPropertyMap Properties; + cmPropertyDefinitionMap TargetProperties; + cmPropertyDefinitionMap SourceFileProperties; + cmPropertyDefinitionMap DirectoryProperties; + cmPropertyDefinitionMap TestProperties; + cmPropertyDefinitionMap GlobalProperties; + typedef cmGlobalGenerator* (*CreateGeneratorFunctionType)(); typedef std::map RegisteredGeneratorsMap; diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index f183ae2..d636559 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -18,6 +18,7 @@ #include "cmCacheManager.h" #include "cmListFileCache.h" #include "cmakewizard.h" +#include "cmSourceFile.h" #ifdef CMAKE_BUILD_WITH_CMAKE #include "cmDynamicLoader.h" @@ -100,6 +101,13 @@ static const cmDocumentationEntry cmDocumentationOptions[] = "The list contains all modules for which help may be obtained by using " "the --help-module argument followed by a module name. If a file is " "specified, the help is written into it."}, + {"--help-property prop [file]", + "Print help for a single property and exit.", + "Full documentation specific to the given module is displayed."}, + {"--help-property-list [file]", "List available properties and exit.", + "The list contains all properties for which help may be obtained by using " + "the --help-property argument followed by a property name. If a file is " + "specified, the help is written into it."}, {0,0,0} }; @@ -157,8 +165,10 @@ int do_cmake(int ac, char** av) hcm.AddCMakePaths(av[0]); doc.SetCMakeRoot(hcm.GetCacheDefinition("CMAKE_ROOT")); std::vector commands; + std::vector properties; std::vector generators; hcm.GetCommandDocumentation(commands); + hcm.GetPropertiesDocumentation(properties); hcm.GetGeneratorDocumentation(generators); doc.SetName("cmake"); doc.SetNameSection(cmDocumentationName); @@ -167,6 +177,7 @@ int do_cmake(int ac, char** av) doc.SetGeneratorsSection(&generators[0]); doc.SetOptionsSection(cmDocumentationOptions); doc.SetCommandsSection(&commands[0]); + doc.SetPropertiesSection(&properties[0]); doc.SetSeeAlsoList(cmDocumentationSeeAlso); int result = doc.PrintRequestedDocumentation(std::cout)? 0:1; diff --git a/Tests/Complex/Library/CMakeLists.txt b/Tests/Complex/Library/CMakeLists.txt index a06745b..3a74efc 100644 --- a/Tests/Complex/Library/CMakeLists.txt +++ b/Tests/Complex/Library/CMakeLists.txt @@ -45,6 +45,8 @@ ADD_LIBRARY(CMakeTestLibraryShared SHARED ${SharedLibrarySources}) ADD_LIBRARY(CMakeTestModule MODULE moduleFile.c) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DTEST_C_FLAGS") ADD_LIBRARY(CMakeTestCLibraryShared SHARED testConly.c) +DEFINE_PROPERTY(FOO TARGET "a test property" + "A simple etst proerty that means nothign and is used for nothing" 0) SET_TARGET_PROPERTIES(CMakeTestCLibraryShared PROPERTIES FOO BAR) IF(NOT BEOS) # No libm on BeOS. SET_TARGET_PROPERTIES(CMakeTestCLibraryShared PROPERTIES LINK_FLAGS "-lm") diff --git a/Tests/ComplexOneConfig/Library/CMakeLists.txt b/Tests/ComplexOneConfig/Library/CMakeLists.txt index a06745b..3a74efc 100644 --- a/Tests/ComplexOneConfig/Library/CMakeLists.txt +++ b/Tests/ComplexOneConfig/Library/CMakeLists.txt @@ -45,6 +45,8 @@ ADD_LIBRARY(CMakeTestLibraryShared SHARED ${SharedLibrarySources}) ADD_LIBRARY(CMakeTestModule MODULE moduleFile.c) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DTEST_C_FLAGS") ADD_LIBRARY(CMakeTestCLibraryShared SHARED testConly.c) +DEFINE_PROPERTY(FOO TARGET "a test property" + "A simple etst proerty that means nothign and is used for nothing" 0) SET_TARGET_PROPERTIES(CMakeTestCLibraryShared PROPERTIES FOO BAR) IF(NOT BEOS) # No libm on BeOS. SET_TARGET_PROPERTIES(CMakeTestCLibraryShared PROPERTIES LINK_FLAGS "-lm") diff --git a/Tests/ComplexRelativePaths/Library/CMakeLists.txt b/Tests/ComplexRelativePaths/Library/CMakeLists.txt index a06745b..3a74efc 100644 --- a/Tests/ComplexRelativePaths/Library/CMakeLists.txt +++ b/Tests/ComplexRelativePaths/Library/CMakeLists.txt @@ -45,6 +45,8 @@ ADD_LIBRARY(CMakeTestLibraryShared SHARED ${SharedLibrarySources}) ADD_LIBRARY(CMakeTestModule MODULE moduleFile.c) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DTEST_C_FLAGS") ADD_LIBRARY(CMakeTestCLibraryShared SHARED testConly.c) +DEFINE_PROPERTY(FOO TARGET "a test property" + "A simple etst proerty that means nothign and is used for nothing" 0) SET_TARGET_PROPERTIES(CMakeTestCLibraryShared PROPERTIES FOO BAR) IF(NOT BEOS) # No libm on BeOS. SET_TARGET_PROPERTIES(CMakeTestCLibraryShared PROPERTIES LINK_FLAGS "-lm") diff --git a/Tests/LoadCommand/CMakeCommands/cmTestCommand.c b/Tests/LoadCommand/CMakeCommands/cmTestCommand.c index 36bf33b..6b4f48f 100644 --- a/Tests/LoadCommand/CMakeCommands/cmTestCommand.c +++ b/Tests/LoadCommand/CMakeCommands/cmTestCommand.c @@ -99,18 +99,24 @@ static int CCONV InitialPass(void *inf, void *mf, int argc, char *argv[]) } info->CAPI->AddDefineFlag(mf, "-DADDED_DEFINITION"); - source_file = info->CAPI->CreateSourceFile(); + source_file = info->CAPI->CreateNewSourceFile(mf); cstr = info->CAPI->SourceFileGetSourceName(source_file); sprintf(buffer, "Shold be empty (source file name): [%s]", cstr); info->CAPI->DisplaySatus(mf, buffer); cstr = info->CAPI->SourceFileGetFullPath(source_file); - sprintf(buffer, "Shold be empty (source file full path): [%s]", cstr); + sprintf(buffer, "Should be empty (source file full path): [%s]", cstr); info->CAPI->DisplaySatus(mf, buffer); + info->CAPI->DefineSourceFileProperty(mf,"SOME_PROPERTY","unused old prop", + "This property is no longer used", + 0); if ( info->CAPI->SourceFileGetPropertyAsBool(source_file, "SOME_PROPERTY") ) { info->CAPI->SetError(mf, "Property SOME_PROPERTY should not be defined"); return 0; } + info->CAPI->DefineSourceFileProperty(mf,"SOME_PROPERTY2","nice prop", + "This property is for testing.", + 0); info->CAPI->SourceFileSetProperty(source_file, "SOME_PROPERTY2", "HERE"); cstr = info->CAPI->SourceFileGetProperty(source_file, "ABSTRACT"); sprintf(buffer, "Should be 0 (source file abstract property): [%p]", cstr); diff --git a/Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c b/Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c index 36bf33b..6b4f48f 100644 --- a/Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c +++ b/Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c @@ -99,18 +99,24 @@ static int CCONV InitialPass(void *inf, void *mf, int argc, char *argv[]) } info->CAPI->AddDefineFlag(mf, "-DADDED_DEFINITION"); - source_file = info->CAPI->CreateSourceFile(); + source_file = info->CAPI->CreateNewSourceFile(mf); cstr = info->CAPI->SourceFileGetSourceName(source_file); sprintf(buffer, "Shold be empty (source file name): [%s]", cstr); info->CAPI->DisplaySatus(mf, buffer); cstr = info->CAPI->SourceFileGetFullPath(source_file); - sprintf(buffer, "Shold be empty (source file full path): [%s]", cstr); + sprintf(buffer, "Should be empty (source file full path): [%s]", cstr); info->CAPI->DisplaySatus(mf, buffer); + info->CAPI->DefineSourceFileProperty(mf,"SOME_PROPERTY","unused old prop", + "This property is no longer used", + 0); if ( info->CAPI->SourceFileGetPropertyAsBool(source_file, "SOME_PROPERTY") ) { info->CAPI->SetError(mf, "Property SOME_PROPERTY should not be defined"); return 0; } + info->CAPI->DefineSourceFileProperty(mf,"SOME_PROPERTY2","nice prop", + "This property is for testing.", + 0); info->CAPI->SourceFileSetProperty(source_file, "SOME_PROPERTY2", "HERE"); cstr = info->CAPI->SourceFileGetProperty(source_file, "ABSTRACT"); sprintf(buffer, "Should be 0 (source file abstract property): [%p]", cstr); -- cgit v0.12