From 15a8af21e8bd8354dfff2063e01f695f85efdeb8 Mon Sep 17 00:00:00 2001 From: Nils Gladitz Date: Thu, 15 May 2014 19:12:40 +0200 Subject: [PATCH] Add an "installed file" property scope Teach set_property and get_property an "INSTALL" property type to be associated with install-tree file paths. Make the properties available to CPack for use during packaging. Add a "prop_inst" Sphinx domain object type for documentation of such properties. --- Help/manual/cmake-developer.7.rst | 8 +- Help/manual/cmake-properties.7.rst | 6 + Source/CMakeLists.txt | 4 + Source/CPack/cmCPackGenerator.cxx | 8 ++ Source/CPack/cmCPackGenerator.h | 3 + Source/CPack/cpack.cxx | 9 +- Source/cmCPackPropertiesGenerator.cxx | 45 +++++++ Source/cmCPackPropertiesGenerator.h | 38 ++++++ Source/cmGetPropertyCommand.cxx | 37 +++++- Source/cmGetPropertyCommand.h | 1 + Source/cmGlobalGenerator.cxx | 44 +++++++ Source/cmGlobalGenerator.h | 2 + Source/cmInstalledFile.cxx | 115 ++++++++++++++++++ Source/cmInstalledFile.h | 83 +++++++++++++ Source/cmProperty.h | 2 +- Source/cmRST.cxx | 3 +- Source/cmSetPropertyCommand.cxx | 59 ++++++++- Source/cmSetPropertyCommand.h | 2 + Source/cmake.cxx | 35 ++++++ Source/cmake.h | 12 ++ Templates/CPackConfig.cmake.in | 8 ++ Tests/RunCMake/CMakeLists.txt | 1 + .../CPackInstallProperties/Append-check.cmake | 3 + .../CPackInstallProperties/Append.cmake | 2 + .../CPackInstallProperties/CMakeLists.txt | 6 + .../FilenameGenex-check.cmake | 3 + .../FilenameGenex.cmake | 7 ++ .../MultipleValues-check.cmake | 3 + .../MultipleValues.cmake | 1 + .../PerConfigValue-check.cmake | 13 ++ .../PerConfigValue.cmake | 14 +++ .../Replace-check.cmake | 3 + .../CPackInstallProperties/Replace.cmake | 2 + .../CPackInstallProperties/RunCMakeTest.cmake | 9 ++ .../CPackInstallProperties/Simple-check.cmake | 3 + .../CPackInstallProperties/Simple.cmake | 1 + .../ValueGenex-check.cmake | 3 + .../CPackInstallProperties/ValueGenex.cmake | 7 ++ .../CPackInstallProperties/check.cmake | 12 ++ .../RunCMake/CPackInstallProperties/test.cpp | 1 + Utilities/Sphinx/cmake.py | 4 + bootstrap | 2 + 42 files changed, 612 insertions(+), 12 deletions(-) create mode 100644 Source/cmCPackPropertiesGenerator.cxx create mode 100644 Source/cmCPackPropertiesGenerator.h create mode 100644 Source/cmInstalledFile.cxx create mode 100644 Source/cmInstalledFile.h create mode 100644 Tests/RunCMake/CPackInstallProperties/Append-check.cmake create mode 100644 Tests/RunCMake/CPackInstallProperties/Append.cmake create mode 100644 Tests/RunCMake/CPackInstallProperties/CMakeLists.txt create mode 100644 Tests/RunCMake/CPackInstallProperties/FilenameGenex-check.cmake create mode 100644 Tests/RunCMake/CPackInstallProperties/FilenameGenex.cmake create mode 100644 Tests/RunCMake/CPackInstallProperties/MultipleValues-check.cmake create mode 100644 Tests/RunCMake/CPackInstallProperties/MultipleValues.cmake create mode 100644 Tests/RunCMake/CPackInstallProperties/PerConfigValue-check.cmake create mode 100644 Tests/RunCMake/CPackInstallProperties/PerConfigValue.cmake create mode 100644 Tests/RunCMake/CPackInstallProperties/Replace-check.cmake create mode 100644 Tests/RunCMake/CPackInstallProperties/Replace.cmake create mode 100644 Tests/RunCMake/CPackInstallProperties/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/CPackInstallProperties/Simple-check.cmake create mode 100644 Tests/RunCMake/CPackInstallProperties/Simple.cmake create mode 100644 Tests/RunCMake/CPackInstallProperties/ValueGenex-check.cmake create mode 100644 Tests/RunCMake/CPackInstallProperties/ValueGenex.cmake create mode 100644 Tests/RunCMake/CPackInstallProperties/check.cmake create mode 100644 Tests/RunCMake/CPackInstallProperties/test.cpp diff --git a/Help/manual/cmake-developer.7.rst b/Help/manual/cmake-developer.7.rst index 7f3197018..f3af1e71a 100644 --- a/Help/manual/cmake-developer.7.rst +++ b/Help/manual/cmake-developer.7.rst @@ -331,10 +331,10 @@ documentation: See the :manual:`cmake-policies(7)` manual and the :command:`cmake_policy` command. -``prop_cache, prop_dir, prop_gbl, prop_sf, prop_test, prop_tgt`` - A CMake cache, directory, global, source file, test, or target - property, respectively. See the :manual:`cmake-properties(7)` manual - and the :command:`set_property` command. +``prop_cache, prop_dir, prop_gbl, prop_sf, prop_inst, prop_test, prop_tgt`` + A CMake cache, directory, global, source file, installed file, test, + or target property, respectively. See the :manual:`cmake-properties(7)` + manual and the :command:`set_property` command. ``variable`` A CMake language variable. diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 14d2e7fa3..f02b17f23 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -302,3 +302,9 @@ Properties on Cache Entries /prop_cache/STRINGS /prop_cache/TYPE /prop_cache/VALUE + +Properties on Installed Files +============================= + +.. toctree:: + :maxdepth: 1 diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 660c0c504..8ecf83c48 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -163,6 +163,8 @@ set(SRCS cmComputeLinkInformation.h cmComputeTargetDepends.h cmComputeTargetDepends.cxx + cmCPackPropertiesGenerator.h + cmCPackPropertiesGenerator.cxx cmCryptoHash.cxx cmCryptoHash.h cmCustomCommand.cxx @@ -243,6 +245,8 @@ set(SRCS cmInstallGenerator.h cmInstallGenerator.cxx cmInstallExportGenerator.cxx + cmInstalledFile.h + cmInstalledFile.cxx cmInstallFilesGenerator.h cmInstallFilesGenerator.cxx cmInstallScriptGenerator.h diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 9cdf5aad9..91f92c555 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -1313,6 +1313,14 @@ int cmCPackGenerator::CleanTemporaryDirectory() return 1; } +//---------------------------------------------------------------------- +cmInstalledFile const* cmCPackGenerator::GetInstalledFile( + std::string const& name) const +{ + cmake const* cm = this->MakefileMap->GetCMakeInstance(); + return cm->GetInstalledFile(name); +} + //---------------------------------------------------------------------- int cmCPackGenerator::PrepareGroupingKind() { diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index e780f0e64..ed89b53a8 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -47,6 +47,7 @@ class cmMakefile; class cmCPackLog; +class cmInstalledFile; /** \class cmCPackGenerator * \brief A superclass of all CPack Generators @@ -129,6 +130,8 @@ protected: int CleanTemporaryDirectory(); + cmInstalledFile const* GetInstalledFile(std::string const& name) const; + virtual const char* GetOutputExtension() { return ".cpack"; } virtual const char* GetOutputPostfix() { return 0; } diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 9eabdcae5..2aa599131 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -257,6 +257,11 @@ int main (int argc, char const* const* argv) return 1; } + if ( !cpackBuildConfig.empty() ) + { + globalMF->AddDefinition("CPACK_BUILD_CONFIG", cpackBuildConfig.c_str()); + } + if ( cmSystemTools::FileExists(cpackConfigFile.c_str()) ) { cpackConfigFile = @@ -317,10 +322,6 @@ int main (int argc, char const* const* argv) cpackProjectDirectory.c_str()); } } - if ( !cpackBuildConfig.empty() ) - { - globalMF->AddDefinition("CPACK_BUILD_CONFIG", cpackBuildConfig.c_str()); - } cpackDefinitions::MapType::iterator cdit; for ( cdit = definitions.Map.begin(); cdit != definitions.Map.end(); diff --git a/Source/cmCPackPropertiesGenerator.cxx b/Source/cmCPackPropertiesGenerator.cxx new file mode 100644 index 000000000..cf24c136f --- /dev/null +++ b/Source/cmCPackPropertiesGenerator.cxx @@ -0,0 +1,45 @@ +#include "cmCPackPropertiesGenerator.h" + +#include "cmLocalGenerator.h" + +cmCPackPropertiesGenerator::cmCPackPropertiesGenerator( + cmMakefile* mf, + cmInstalledFile const& installedFile, + std::vector const& configurations): + cmScriptGenerator("CPACK_BUILD_CONFIG", configurations), + Makefile(mf), + InstalledFile(installedFile) +{ + this->ActionsPerConfig = true; +} + +void cmCPackPropertiesGenerator::GenerateScriptForConfig(std::ostream& os, + const std::string& config, Indent const& indent) +{ + std::string const& expandedFileName = + this->InstalledFile.GetNameExpression().Evaluate(this->Makefile, config); + + cmInstalledFile::PropertyMapType const& properties = + this->InstalledFile.GetProperties(); + + for(cmInstalledFile::PropertyMapType::const_iterator i = properties.begin(); + i != properties.end(); ++i) + { + std::string const& name = i->first; + cmInstalledFile::Property const& property = i->second; + + os << indent << "set_property(INSTALL " << + cmLocalGenerator::EscapeForCMake(expandedFileName) << " PROPERTY " << + cmLocalGenerator::EscapeForCMake(name); + + for(cmInstalledFile::ExpressionVectorType::const_iterator + j = property.ValueExpressions.begin(); + j != property.ValueExpressions.end(); ++j) + { + std::string value = (*j)->Evaluate(this->Makefile, config); + os << " " << cmLocalGenerator::EscapeForCMake(value); + } + + os << ")\n"; + } +} diff --git a/Source/cmCPackPropertiesGenerator.h b/Source/cmCPackPropertiesGenerator.h new file mode 100644 index 000000000..71e2eaa42 --- /dev/null +++ b/Source/cmCPackPropertiesGenerator.h @@ -0,0 +1,38 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmCPackPropertiesGenerator_h +#define cmCPackPropertiesGenerator_h + +#include "cmScriptGenerator.h" +#include "cmInstalledFile.h" + +/** \class cmCPackPropertiesGenerator + * \brief Support class for generating CPackProperties.cmake. + * + */ +class cmCPackPropertiesGenerator: public cmScriptGenerator +{ +public: + cmCPackPropertiesGenerator( + cmMakefile* mf, + cmInstalledFile const& installedFile, + std::vector const& configurations); + +protected: + virtual void GenerateScriptForConfig(std::ostream& os, + const std::string& config, Indent const& indent); + + cmMakefile* Makefile; + cmInstalledFile const& InstalledFile; +}; + +#endif diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index 512d78994..9a88191f4 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -67,12 +67,16 @@ bool cmGetPropertyCommand { scope = cmProperty::CACHE; } + else if(args[1] == "INSTALL") + { + scope = cmProperty::INSTALL; + } else { cmOStringStream e; e << "given invalid scope " << args[1] << ". " << "Valid scopes are " - << "GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, VARIABLE, CACHE."; + << "GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, VARIABLE, CACHE, INSTALL."; this->SetError(e.str()); return false; } @@ -190,6 +194,7 @@ bool cmGetPropertyCommand case cmProperty::TEST: return this->HandleTestMode(); case cmProperty::VARIABLE: return this->HandleVariableMode(); case cmProperty::CACHE: return this->HandleCacheMode(); + case cmProperty::INSTALL: return this->HandleInstallMode(); case cmProperty::CACHED_VARIABLE: break; // should never happen @@ -395,3 +400,33 @@ bool cmGetPropertyCommand::HandleCacheMode() this->StoreResult(value); return true; } + +//---------------------------------------------------------------------------- +bool cmGetPropertyCommand::HandleInstallMode() +{ + if(this->Name.empty()) + { + this->SetError("not given name for INSTALL scope."); + return false; + } + + // Get the installed file. + cmake* cm = this->Makefile->GetCMakeInstance(); + + if(cmInstalledFile* file = cm->GetOrCreateInstalledFile( + this->Makefile, this->Name)) + { + std::string value; + bool isSet = file->GetProperty(this->PropertyName, value); + + return this->StoreResult(isSet ? value.c_str() : 0); + } + else + { + cmOStringStream e; + e << "given INSTALL name that could not be found or created: " + << this->Name; + this->SetError(e.str()); + return false; + } +} diff --git a/Source/cmGetPropertyCommand.h b/Source/cmGetPropertyCommand.h index 8c3738fbd..40b7dbc00 100644 --- a/Source/cmGetPropertyCommand.h +++ b/Source/cmGetPropertyCommand.h @@ -60,6 +60,7 @@ private: bool HandleTestMode(); bool HandleVariableMode(); bool HandleCacheMode(); + bool HandleInstallMode(); }; #endif diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 2a30593cc..dba4f4679 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -28,6 +28,7 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorExpressionEvaluationFile.h" #include "cmExportBuildFileGenerator.h" +#include "cmCPackPropertiesGenerator.h" #include #include @@ -1269,6 +1270,13 @@ void cmGlobalGenerator::Generate() } this->SetCurrentLocalGenerator(0); + if(!this->GenerateCPackPropertiesFile()) + { + this->GetCMakeInstance()->IssueMessage( + cmake::FATAL_ERROR, "Could not write CPack properties file.", + cmListFileBacktrace()); + } + for (std::map::iterator it = this->BuildExportSets.begin(); it != this->BuildExportSets.end(); ++it) @@ -3014,3 +3022,39 @@ std::string cmGlobalGenerator::ExpandCFGIntDir(const std::string& str, { return str; } + +//---------------------------------------------------------------------------- +bool cmGlobalGenerator::GenerateCPackPropertiesFile() +{ + cmake::InstalledFilesMap const& installedFiles = + this->CMakeInstance->GetInstalledFiles(); + + cmMakefile* mf = this->LocalGenerators[0]->GetMakefile(); + + std::vector configs; + std::string config = mf->GetConfigurations(configs, false); + + std::string path = this->CMakeInstance->GetStartOutputDirectory(); + path += "/CPackProperties.cmake"; + + if(!cmSystemTools::FileExists(path.c_str()) && installedFiles.empty()) + { + return true; + } + + cmGeneratedFileStream file(path.c_str()); + file << "# CPack properties\n"; + + for(cmake::InstalledFilesMap::const_iterator i = installedFiles.begin(); + i != installedFiles.end(); ++i) + { + cmInstalledFile const& installedFile = i->second; + + cmCPackPropertiesGenerator cpackPropertiesGenerator( + mf, installedFile, configs); + + cpackPropertiesGenerator.Generate(file, config, configs); + } + + return true; +} diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 14ec99a9f..617e708c4 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -329,6 +329,8 @@ public: virtual void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const; + bool GenerateCPackPropertiesFile(); + protected: typedef std::vector GeneratorVector; // for a project collect all its targets by following depend diff --git a/Source/cmInstalledFile.cxx b/Source/cmInstalledFile.cxx new file mode 100644 index 000000000..7e78ec000 --- /dev/null +++ b/Source/cmInstalledFile.cxx @@ -0,0 +1,115 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmInstalledFile.h" +#include "cmSystemTools.h" +#include "cmMakefile.h" + +//---------------------------------------------------------------------------- +cmInstalledFile::cmInstalledFile(): + NameExpression(0) +{ + +} + +//---------------------------------------------------------------------------- +cmInstalledFile::~cmInstalledFile() +{ + if(NameExpression) + { + delete NameExpression; + } +} + +//---------------------------------------------------------------------------- +void cmInstalledFile::SetName(cmMakefile* mf, const std::string& name) +{ + cmListFileBacktrace backtrace; + mf->GetBacktrace(backtrace); + cmGeneratorExpression ge(backtrace); + + this->Name = name; + this->NameExpression = ge.Parse(name).release(); +} + +//---------------------------------------------------------------------------- +std::string const& cmInstalledFile::GetName() const +{ + return this->Name; +} + +//---------------------------------------------------------------------------- +cmCompiledGeneratorExpression const& cmInstalledFile::GetNameExpression() const +{ + return *(this->NameExpression); +} + +//---------------------------------------------------------------------------- +void cmInstalledFile::RemoveProperty(const std::string& prop) +{ + this->Properties.erase(prop); +} + +//---------------------------------------------------------------------------- +void cmInstalledFile::SetProperty(cmMakefile const* mf, + const std::string& prop, const char* value) +{ + this->RemoveProperty(prop); + this->AppendProperty(mf, prop, value); +} + +//---------------------------------------------------------------------------- +void cmInstalledFile::AppendProperty(cmMakefile const* mf, + const std::string& prop, const char* value, bool /*asString*/) +{ + cmListFileBacktrace backtrace; + mf->GetBacktrace(backtrace); + cmGeneratorExpression ge(backtrace); + + Property& property = this->Properties[prop]; + property.ValueExpressions.push_back(ge.Parse(value).release()); +} + +//---------------------------------------------------------------------------- +bool cmInstalledFile::GetProperty( + const std::string& prop, std::string& value) const +{ + PropertyMapType::const_iterator i = this->Properties.find(prop); + if(i == this->Properties.end()) + { + return false; + } + + Property const& property = i->second; + + std::string output; + std::string separator; + + for(ExpressionVectorType::const_iterator + j = property.ValueExpressions.begin(); + j != property.ValueExpressions.end(); ++j) + { + output += separator; + output += (*j)->GetInput(); + separator = ";"; + } + + value = output; + return true; +} + +//---------------------------------------------------------------------------- +bool cmInstalledFile::GetPropertyAsBool(const std::string& prop) const +{ + std::string value; + bool isSet = this->GetProperty(prop, value); + return isSet && cmSystemTools::IsOn(value.c_str()); +} diff --git a/Source/cmInstalledFile.h b/Source/cmInstalledFile.h new file mode 100644 index 000000000..df28221bc --- /dev/null +++ b/Source/cmInstalledFile.h @@ -0,0 +1,83 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmInstalledFile_h +#define cmInstalledFile_h + +#include "cmGeneratorExpression.h" + +/** \class cmInstalledFile + * \brief Represents a file intended for installation. + * + * cmInstalledFile represents a file intended for installation. + */ +class cmInstalledFile +{ +public: + + typedef cmsys::auto_ptr + CompiledGeneratorExpressionPtrType; + + typedef std::vector + ExpressionVectorType; + + struct Property + { + Property() + { + + } + + ~Property() + { + for(ExpressionVectorType::iterator i = ValueExpressions.begin(); + i != ValueExpressions.end(); ++i) + { + delete *i; + } + } + + ExpressionVectorType ValueExpressions; + }; + + typedef std::map PropertyMapType; + + cmInstalledFile(); + + ~cmInstalledFile(); + + void RemoveProperty(const std::string& prop); + + void SetProperty(cmMakefile const* mf, + const std::string& prop, const char *value); + + void AppendProperty(cmMakefile const* mf, + const std::string& prop, const char* value,bool asString=false); + + bool GetProperty(const std::string& prop, std::string& value) const; + + bool GetPropertyAsBool(const std::string& prop) const; + + void SetName(cmMakefile* mf, const std::string& name); + + std::string const& GetName() const; + + cmCompiledGeneratorExpression const& GetNameExpression() const; + + PropertyMapType const& GetProperties() const { return this->Properties; } + +private: + std::string Name; + cmCompiledGeneratorExpression* NameExpression; + PropertyMapType Properties; +}; + +#endif diff --git a/Source/cmProperty.h b/Source/cmProperty.h index 34897e899..659c4c324 100644 --- a/Source/cmProperty.h +++ b/Source/cmProperty.h @@ -18,7 +18,7 @@ class cmProperty { public: enum ScopeType { TARGET, SOURCE_FILE, DIRECTORY, GLOBAL, CACHE, - TEST, VARIABLE, CACHED_VARIABLE }; + TEST, VARIABLE, CACHED_VARIABLE, INSTALL }; // set this property void Set(const std::string& name, const char *value); diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx index 7ff12dde6..cca995b12 100644 --- a/Source/cmRST.cxx +++ b/Source/cmRST.cxx @@ -39,7 +39,8 @@ cmRST::cmRST(std::ostream& os, std::string const& docroot): ModuleRST("^#\\[(=*)\\[\\.rst:$"), CMakeRole("(:cmake)?:(" "command|generator|variable|module|policy|" - "prop_cache|prop_dir|prop_gbl|prop_sf|prop_test|prop_tgt|" + "prop_cache|prop_dir|prop_gbl|prop_inst|prop_sf|" + "prop_test|prop_tgt|" "manual" "):`(<*([^`<]|[^` \t]<)*)([ \t]+<[^`]*>)?`"), Substitution("(^|[^A-Za-z0-9_])" diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx index 5f970f82a..c624d170a 100644 --- a/Source/cmSetPropertyCommand.cxx +++ b/Source/cmSetPropertyCommand.cxx @@ -61,11 +61,16 @@ bool cmSetPropertyCommand { scope = cmProperty::CACHE; } + else if(*arg == "INSTALL") + { + scope = cmProperty::INSTALL; + } else { cmOStringStream e; e << "given invalid scope " << *arg << ". " - << "Valid scopes are GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, CACHE."; + << "Valid scopes are GLOBAL, DIRECTORY, " + "TARGET, SOURCE, TEST, CACHE, INSTALL."; this->SetError(e.str()); return false; } @@ -135,6 +140,7 @@ bool cmSetPropertyCommand case cmProperty::SOURCE_FILE: return this->HandleSourceMode(); case cmProperty::TEST: return this->HandleTestMode(); case cmProperty::CACHE: return this->HandleCacheMode(); + case cmProperty::INSTALL: return this->HandleInstallMode(); case cmProperty::VARIABLE: case cmProperty::CACHED_VARIABLE: @@ -488,3 +494,54 @@ bool cmSetPropertyCommand::HandleCacheEntry(cmCacheManager::CacheIterator& it) return true; } + +//---------------------------------------------------------------------------- +bool cmSetPropertyCommand::HandleInstallMode() +{ + cmake* cm = this->Makefile->GetCMakeInstance(); + + for(std::set::const_iterator i = this->Names.begin(); + i != this->Names.end(); ++i) + { + if(cmInstalledFile* file = cm->GetOrCreateInstalledFile( + this->Makefile, *i)) + { + if(!this->HandleInstall(file)) + { + return false; + } + } + else + { + cmOStringStream e; + e << "given INSTALL name that could not be found or created: " << *i; + this->SetError(e.str()); + return false; + } + } + return true; +} + +//---------------------------------------------------------------------------- +bool cmSetPropertyCommand::HandleInstall(cmInstalledFile* file) +{ + // Set or append the property. + std::string const& name = this->PropertyName; + + cmMakefile* mf = this->Makefile; + + const char *value = this->PropertyValue.c_str(); + if (this->Remove) + { + file->RemoveProperty(name); + } + else if(this->AppendMode) + { + file->AppendProperty(mf, name, value, this->AppendAsString); + } + else + { + file->SetProperty(mf, name, value); + } + return true; +} diff --git a/Source/cmSetPropertyCommand.h b/Source/cmSetPropertyCommand.h index eaa023362..b06cb6857 100644 --- a/Source/cmSetPropertyCommand.h +++ b/Source/cmSetPropertyCommand.h @@ -62,6 +62,8 @@ private: bool HandleTest(cmTest* test); bool HandleCacheMode(); bool HandleCacheEntry(cmCacheManager::CacheIterator&); + bool HandleInstallMode(); + bool HandleInstall(cmInstalledFile* file); }; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 3e789901d..86652d3a3 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -2287,6 +2287,41 @@ bool cmake::GetPropertyAsBool(const std::string& prop) return cmSystemTools::IsOn(this->GetProperty(prop)); } +cmInstalledFile *cmake::GetOrCreateInstalledFile( + cmMakefile* mf, const std::string& name) +{ + std::map::iterator i = + this->InstalledFiles.find(name); + + if(i != this->InstalledFiles.end()) + { + cmInstalledFile &file = i->second; + return &file; + } + else + { + cmInstalledFile &file = this->InstalledFiles[name]; + file.SetName(mf, name); + return &file; + } +} + +cmInstalledFile const* cmake::GetInstalledFile(const std::string& name) const +{ + std::map::const_iterator i = + this->InstalledFiles.find(name); + + if(i != this->InstalledFiles.end()) + { + cmInstalledFile const& file = i->second; + return &file; + } + else + { + return 0; + } +} + int cmake::GetSystemInformation(std::vector& args) { // so create the directory diff --git a/Source/cmake.h b/Source/cmake.h index 33b4f74b6..0034e8536 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -16,6 +16,7 @@ #include "cmSystemTools.h" #include "cmPropertyDefinitionMap.h" #include "cmPropertyMap.h" +#include "cmInstalledFile.h" class cmGlobalGeneratorFactory; class cmGlobalGenerator; @@ -92,6 +93,7 @@ class cmake FIND_PACKAGE_MODE }; typedef std::map RegisteredCommandsMap; + typedef std::map InstalledFilesMap; /// Default constructor cmake(); @@ -280,6 +282,15 @@ class cmake // Get the properties cmPropertyMap &GetProperties() { return this->Properties; } + ///! Get or create an cmInstalledFile instance and return a pointer to it + cmInstalledFile *GetOrCreateInstalledFile( + cmMakefile* mf, const std::string& name); + + cmInstalledFile const* GetInstalledFile(const std::string& name) const; + + InstalledFilesMap const& GetInstalledFiles() const + { return this->InstalledFiles; } + ///! Do all the checks before running configure int DoPreConfigureChecks(); @@ -445,6 +456,7 @@ private: cmFileTimeComparison* FileComparison; std::string GraphVizFile; std::vector DebugConfigs; + InstalledFilesMap InstalledFiles; void UpdateConversionPathTable(); }; diff --git a/Templates/CPackConfig.cmake.in b/Templates/CPackConfig.cmake.in index 79b8d93ae..c00ea2a05 100644 --- a/Templates/CPackConfig.cmake.in +++ b/Templates/CPackConfig.cmake.in @@ -10,3 +10,11 @@ # usually begin with CPACK__xxxx. @_CPACK_OTHER_VARIABLES_@ + +if(NOT CPACK_PROPERTIES_FILE) + set(CPACK_PROPERTIES_FILE "@CMAKE_BINARY_DIR@/CPackProperties.cmake") +endif() + +if(EXISTS ${CPACK_PROPERTIES_FILE}) + include(${CPACK_PROPERTIES_FILE}) +endif() diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 7f6ebf103..07ed3970f 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -132,3 +132,4 @@ add_RunCMake_test(CheckModules) add_RunCMake_test(CommandLine) add_RunCMake_test(install) +add_RunCMake_test(CPackInstallProperties) diff --git a/Tests/RunCMake/CPackInstallProperties/Append-check.cmake b/Tests/RunCMake/CPackInstallProperties/Append-check.cmake new file mode 100644 index 000000000..017b30d7d --- /dev/null +++ b/Tests/RunCMake/CPackInstallProperties/Append-check.cmake @@ -0,0 +1,3 @@ +include(${RunCMake_SOURCE_DIR}/check.cmake) + +test_property("append.txt" CPACK_TEST_PROP "value1;value2;value3") diff --git a/Tests/RunCMake/CPackInstallProperties/Append.cmake b/Tests/RunCMake/CPackInstallProperties/Append.cmake new file mode 100644 index 000000000..cecc45f31 --- /dev/null +++ b/Tests/RunCMake/CPackInstallProperties/Append.cmake @@ -0,0 +1,2 @@ +set_property(INSTALL append.txt PROPERTY CPACK_TEST_PROP value1) +set_property(INSTALL append.txt PROPERTY CPACK_TEST_PROP value2 value3 APPEND) diff --git a/Tests/RunCMake/CPackInstallProperties/CMakeLists.txt b/Tests/RunCMake/CPackInstallProperties/CMakeLists.txt new file mode 100644 index 000000000..89ff7c49f --- /dev/null +++ b/Tests/RunCMake/CPackInstallProperties/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.0) + +project(${RunCMake_TEST} CXX) +include(${RunCMake_TEST}.cmake) + +include(CPack) diff --git a/Tests/RunCMake/CPackInstallProperties/FilenameGenex-check.cmake b/Tests/RunCMake/CPackInstallProperties/FilenameGenex-check.cmake new file mode 100644 index 000000000..8c9e967c3 --- /dev/null +++ b/Tests/RunCMake/CPackInstallProperties/FilenameGenex-check.cmake @@ -0,0 +1,3 @@ +include(${RunCMake_SOURCE_DIR}/check.cmake) + +test_property(${EXPECTED_MYTEST_NAME} CPACK_TEST_PROP2 PROP_VALUE2) diff --git a/Tests/RunCMake/CPackInstallProperties/FilenameGenex.cmake b/Tests/RunCMake/CPackInstallProperties/FilenameGenex.cmake new file mode 100644 index 000000000..1a373b928 --- /dev/null +++ b/Tests/RunCMake/CPackInstallProperties/FilenameGenex.cmake @@ -0,0 +1,7 @@ +add_executable(mytest test.cpp) + +file(GENERATE OUTPUT runtest_info.cmake CONTENT [[ +set(EXPECTED_MYTEST_NAME "$") +]]) + +set_property(INSTALL $ PROPERTY CPACK_TEST_PROP2 PROP_VALUE2) diff --git a/Tests/RunCMake/CPackInstallProperties/MultipleValues-check.cmake b/Tests/RunCMake/CPackInstallProperties/MultipleValues-check.cmake new file mode 100644 index 000000000..91278ba4a --- /dev/null +++ b/Tests/RunCMake/CPackInstallProperties/MultipleValues-check.cmake @@ -0,0 +1,3 @@ +include(${RunCMake_SOURCE_DIR}/check.cmake) + +test_property("multiple_values.txt" CPACK_TEST_PROP "value1;value2;value3") diff --git a/Tests/RunCMake/CPackInstallProperties/MultipleValues.cmake b/Tests/RunCMake/CPackInstallProperties/MultipleValues.cmake new file mode 100644 index 000000000..26db52acd --- /dev/null +++ b/Tests/RunCMake/CPackInstallProperties/MultipleValues.cmake @@ -0,0 +1 @@ +set_property(INSTALL multiple_values.txt PROPERTY CPACK_TEST_PROP value1 value2 value3) diff --git a/Tests/RunCMake/CPackInstallProperties/PerConfigValue-check.cmake b/Tests/RunCMake/CPackInstallProperties/PerConfigValue-check.cmake new file mode 100644 index 000000000..2966d88c9 --- /dev/null +++ b/Tests/RunCMake/CPackInstallProperties/PerConfigValue-check.cmake @@ -0,0 +1,13 @@ +include(${RunCMake_SOURCE_DIR}/check.cmake) + +file(GLOB INFO_FILES ${RunCMake_TEST_BINARY_DIR}/runtest_info_*.cmake) + +if(NOT INFO_FILES) + message(FATAL_ERROR "missing expected info files") +endif() + +foreach(INFO_FILE IN LISTS INFO_FILES) + include(${INFO_FILE}) + include(${RunCMake_TEST_BINARY_DIR}/CPackProperties.cmake) + test_property("config.cpp" FOO ${EXPECTED_MYTEST_NAME}) +endforeach() diff --git a/Tests/RunCMake/CPackInstallProperties/PerConfigValue.cmake b/Tests/RunCMake/CPackInstallProperties/PerConfigValue.cmake new file mode 100644 index 000000000..77fe8ed5d --- /dev/null +++ b/Tests/RunCMake/CPackInstallProperties/PerConfigValue.cmake @@ -0,0 +1,14 @@ +add_executable(mytest test.cpp) + +foreach(CONFIG IN LISTS CMAKE_CONFIGURATION_TYPES) + string(TOUPPER ${CONFIG} UPPER_CONFIG) + set_property(TARGET mytest PROPERTY + OUTPUT_NAME_${UPPER_CONFIG} bar_${CONFIG}) +endforeach() + +file(GENERATE OUTPUT runtest_info_$.cmake CONTENT [[ +set(CPACK_BUILD_CONFIG "$") +set(EXPECTED_MYTEST_NAME "$") +]]) + +set_property(INSTALL config.cpp PROPERTY FOO $) diff --git a/Tests/RunCMake/CPackInstallProperties/Replace-check.cmake b/Tests/RunCMake/CPackInstallProperties/Replace-check.cmake new file mode 100644 index 000000000..6e492e72d --- /dev/null +++ b/Tests/RunCMake/CPackInstallProperties/Replace-check.cmake @@ -0,0 +1,3 @@ +include(${RunCMake_SOURCE_DIR}/check.cmake) + +test_property("replace.txt" CPACK_TEST_PROP "value2") diff --git a/Tests/RunCMake/CPackInstallProperties/Replace.cmake b/Tests/RunCMake/CPackInstallProperties/Replace.cmake new file mode 100644 index 000000000..104d5a41f --- /dev/null +++ b/Tests/RunCMake/CPackInstallProperties/Replace.cmake @@ -0,0 +1,2 @@ +set_property(INSTALL replace.txt PROPERTY CPACK_TEST_PROP value1) +set_property(INSTALL replace.txt PROPERTY CPACK_TEST_PROP value2) diff --git a/Tests/RunCMake/CPackInstallProperties/RunCMakeTest.cmake b/Tests/RunCMake/CPackInstallProperties/RunCMakeTest.cmake new file mode 100644 index 000000000..d244ac5a1 --- /dev/null +++ b/Tests/RunCMake/CPackInstallProperties/RunCMakeTest.cmake @@ -0,0 +1,9 @@ +include(RunCMake) + +run_cmake(Simple) +run_cmake(FilenameGenex) +run_cmake(ValueGenex) +run_cmake(MultipleValues) +run_cmake(Append) +run_cmake(Replace) +run_cmake(PerConfigValue) diff --git a/Tests/RunCMake/CPackInstallProperties/Simple-check.cmake b/Tests/RunCMake/CPackInstallProperties/Simple-check.cmake new file mode 100644 index 000000000..6a7ee2aa4 --- /dev/null +++ b/Tests/RunCMake/CPackInstallProperties/Simple-check.cmake @@ -0,0 +1,3 @@ +include(${RunCMake_SOURCE_DIR}/check.cmake) + +test_property("foo/test.cpp" CPACK_TEST_PROP PROP_VALUE) diff --git a/Tests/RunCMake/CPackInstallProperties/Simple.cmake b/Tests/RunCMake/CPackInstallProperties/Simple.cmake new file mode 100644 index 000000000..2eb87553a --- /dev/null +++ b/Tests/RunCMake/CPackInstallProperties/Simple.cmake @@ -0,0 +1 @@ +set_property(INSTALL foo/test.cpp PROPERTY CPACK_TEST_PROP PROP_VALUE) diff --git a/Tests/RunCMake/CPackInstallProperties/ValueGenex-check.cmake b/Tests/RunCMake/CPackInstallProperties/ValueGenex-check.cmake new file mode 100644 index 000000000..cdfbcda22 --- /dev/null +++ b/Tests/RunCMake/CPackInstallProperties/ValueGenex-check.cmake @@ -0,0 +1,3 @@ +include(${RunCMake_SOURCE_DIR}/check.cmake) + +test_property("bar/test.cpp" CPACK_TEST_PROP ${EXPECTED_MYTEST_NAME}) diff --git a/Tests/RunCMake/CPackInstallProperties/ValueGenex.cmake b/Tests/RunCMake/CPackInstallProperties/ValueGenex.cmake new file mode 100644 index 000000000..2e1d4656c --- /dev/null +++ b/Tests/RunCMake/CPackInstallProperties/ValueGenex.cmake @@ -0,0 +1,7 @@ +add_executable(mytest test.cpp) + +file(GENERATE OUTPUT runtest_info.cmake CONTENT [[ +set(EXPECTED_MYTEST_NAME "$") +]]) + +set_property(INSTALL bar/test.cpp PROPERTY CPACK_TEST_PROP $) diff --git a/Tests/RunCMake/CPackInstallProperties/check.cmake b/Tests/RunCMake/CPackInstallProperties/check.cmake new file mode 100644 index 000000000..65aa467bd --- /dev/null +++ b/Tests/RunCMake/CPackInstallProperties/check.cmake @@ -0,0 +1,12 @@ +function(test_property FILE NAME EXPECTED_VALUE) + get_property(ACTUAL_VALUE INSTALL "${FILE}" PROPERTY "${NAME}") + + if(NOT "${ACTUAL_VALUE}" STREQUAL "${EXPECTED_VALUE}") + message(FATAL_ERROR "${NAME}@${FILE}: property mismatch expected [${EXPECTED_VALUE}] actual [${ACTUAL_VALUE}] (Config:${CPACK_BUILD_CONFIG})") + endif() +endfunction() + +set(CPACK_BUILD_CONFIG Debug) +include(${RunCMake_TEST_BINARY_DIR}/CPackProperties.cmake) + +include(${RunCMake_TEST_BINARY_DIR}/runtest_info.cmake OPTIONAL) diff --git a/Tests/RunCMake/CPackInstallProperties/test.cpp b/Tests/RunCMake/CPackInstallProperties/test.cpp new file mode 100644 index 000000000..237c8ce18 --- /dev/null +++ b/Tests/RunCMake/CPackInstallProperties/test.cpp @@ -0,0 +1 @@ +int main() {} diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py index 6e6e48a94..2629bb33c 100644 --- a/Utilities/Sphinx/cmake.py +++ b/Utilities/Sphinx/cmake.py @@ -142,6 +142,7 @@ _cmake_index_objs = { 'prop_cache': _cmake_index_entry('cache property'), 'prop_dir': _cmake_index_entry('directory property'), 'prop_gbl': _cmake_index_entry('global property'), + 'prop_inst': _cmake_index_entry('installed file property'), 'prop_sf': _cmake_index_entry('source file property'), 'prop_test': _cmake_index_entry('test property'), 'prop_tgt': _cmake_index_entry('target property'), @@ -269,6 +270,7 @@ class CMakeDomain(Domain): 'prop_cache': ObjType('prop_cache', 'prop_cache'), 'prop_dir': ObjType('prop_dir', 'prop_dir'), 'prop_gbl': ObjType('prop_gbl', 'prop_gbl'), + 'prop_inst': ObjType('prop_inst', 'prop_inst'), 'prop_sf': ObjType('prop_sf', 'prop_sf'), 'prop_test': ObjType('prop_test', 'prop_test'), 'prop_tgt': ObjType('prop_tgt', 'prop_tgt'), @@ -284,6 +286,7 @@ class CMakeDomain(Domain): # 'prop_cache': CMakeObject, # 'prop_dir': CMakeObject, # 'prop_gbl': CMakeObject, + # 'prop_inst': CMakeObject, # 'prop_sf': CMakeObject, # 'prop_test': CMakeObject, # 'prop_tgt': CMakeObject, @@ -298,6 +301,7 @@ class CMakeDomain(Domain): 'prop_cache': CMakeXRefRole(), 'prop_dir': CMakeXRefRole(), 'prop_gbl': CMakeXRefRole(), + 'prop_inst': CMakeXRefRole(), 'prop_sf': CMakeXRefRole(), 'prop_test': CMakeXRefRole(), 'prop_tgt': CMakeXRefRole(), diff --git a/bootstrap b/bootstrap index 233806c31..a3cc0a3ca 100755 --- a/bootstrap +++ b/bootstrap @@ -232,6 +232,7 @@ CMAKE_CXX_SOURCES="\ cmCommandArgumentLexer \ cmCommandArgumentParser \ cmCommandArgumentParserHelper \ + cmCPackPropertiesGenerator \ cmDefinitions \ cmDepends \ cmDependsC \ @@ -258,6 +259,7 @@ CMAKE_CXX_SOURCES="\ cmGeneratorExpression \ cmGlobalGenerator \ cmLocalGenerator \ + cmInstalledFile \ cmInstallGenerator \ cmInstallExportGenerator \ cmInstallFilesGenerator \