From 518080136d2b643b2b27ae1ef69cee28306c2f81 Mon Sep 17 00:00:00 2001 From: Brad King Date: Sun, 19 Feb 2006 18:47:13 -0500 Subject: ENH: Implemented FILES and PROGRAMS forms of the INSTALL command as replacements for the INSTALL_FILES and INSTALL_PROGRAMS commands. This addresses the request for absolute path install destinations in bug#2691. --- Source/CMakeLists.txt | 2 + Source/cmInstallCommand.cxx | 88 ++++++++++++++++++++++++++++++++++++ Source/cmInstallCommand.h | 49 +++++++++++++++----- Source/cmInstallFilesCommand.h | 9 +++- Source/cmInstallFilesGenerator.cxx | 47 +++++++++++++++++++ Source/cmInstallFilesGenerator.h | 39 ++++++++++++++++ Source/cmInstallProgramsCommand.h | 10 +++- Source/cmLocalGenerator.cxx | 51 ++++----------------- Tests/SimpleInstall/CMakeLists.txt | 3 +- Tests/SimpleInstallS2/CMakeLists.txt | 3 +- bootstrap | 1 + 11 files changed, 243 insertions(+), 59 deletions(-) create mode 100644 Source/cmInstallFilesGenerator.cxx create mode 100644 Source/cmInstallFilesGenerator.h diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index b7c83e6..00ee83a 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -117,6 +117,8 @@ SET(SRCS cmGlobalUnixMakefileGenerator3.h cmInstallGenerator.h cmInstallGenerator.cxx + cmInstallFilesGenerator.h + cmInstallFilesGenerator.cxx cmInstallScriptGenerator.h cmInstallScriptGenerator.cxx cmInstallTargetGenerator.h diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 0750173..6f86ee6 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -16,6 +16,7 @@ =========================================================================*/ #include "cmInstallCommand.h" +#include "cmInstallFilesGenerator.h" #include "cmInstallScriptGenerator.h" #include "cmInstallTargetGenerator.h" @@ -38,6 +39,14 @@ bool cmInstallCommand::InitialPass(std::vector const& args) { return this->HandleTargetsMode(args); } + else if(args[0] == "FILES") + { + return this->HandleFilesMode(args); + } + else if(args[0] == "PROGRAMS") + { + return this->HandleFilesMode(args); + } // Unknown mode. cmStdString e = "called with unknown mode "; @@ -284,6 +293,85 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) } //---------------------------------------------------------------------------- +bool cmInstallCommand::HandleFilesMode(std::vector const& args) +{ + // This is the FILES mode. + bool programs = (args[0] == "PROGRAMS"); + bool doing_files = true; + bool doing_destination = false; + std::vector files; + const char* destination = 0; + for(unsigned int i=1; i < args.size(); ++i) + { + if(args[i] == "DESTINATION") + { + // Switch to setting the destination property. + doing_files = false; + doing_destination = true; + } + else if(doing_files) + { + // Convert this file to a full path. + std::string file = args[i]; + if(!cmSystemTools::FileIsFullPath(file.c_str())) + { + file = m_Makefile->GetCurrentDirectory(); + file += "/"; + file += args[i]; + } + + // Make sure the file is not a directory. + if(cmSystemTools::FileIsDirectory(file.c_str())) + { + cmOStringStream e; + e << args[0] << " given directory \"" << args[i] << "\" to install."; + this->SetError(e.str().c_str()); + return false; + } + + // Store the file for installation. + files.push_back(file); + } + else if(doing_destination) + { + destination = args[i].c_str(); + doing_destination = false; + } + else + { + // Unknown argument. + cmOStringStream e; + e << args[0] << " given unknown argument \"" << args[i] << "\"."; + this->SetError(e.str().c_str()); + return false; + } + } + + // Check if there is something to do. + if(files.empty()) + { + return true; + } + if(!destination) + { + cmOStringStream e; + e << args[0] << " given no DESTINATION!"; + this->SetError(e.str().c_str()); + return false; + } + + // Compute destination path. + std::string dest; + this->ComputeDestination(destination, dest); + + // Create the files install generator. + m_Makefile->AddInstallGenerator( + new cmInstallFilesGenerator(files, dest.c_str(), programs)); + + return true; +} + +//---------------------------------------------------------------------------- void cmInstallCommand::ComputeDestination(const char* destination, std::string& dest) { diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h index 586209e..296bc3f 100644 --- a/Source/cmInstallCommand.h +++ b/Source/cmInstallCommand.h @@ -64,10 +64,19 @@ public: "This command generates installation rules for a project. " "Rules specified by calls to this command within a source directory " "are executed in order during installation. " - "The order across directories is not defined.\n" - "There are multiple signatures for this command:\n" + "The order across directories is not defined." + "\n" + "There are multiple signatures for this command. Some of them define " + "installation properties for files and targets. Properties common to " + "multiple signatures are covered here. DESTINATION arguments specify " + "the directory on disk to which a file will be installed. " + "If a full path (with a leading slash or drive letter) is given it " + "is used directly. If a relative path is given it is interpreted " + "relative to the value of CMAKE_INSTALL_PREFIX." + "\n" + "The TARGETS signature:\n" " INSTALL(TARGETS [targets...] [[LIBRARY|RUNTIME]\n" - " [DESTINATION ]\n" + " [DESTINATION ]\n" " ] [...])\n" "The TARGETS form specifies rules for installing targets from a " "project. There are two kinds of target files that may be " @@ -82,12 +91,8 @@ public: "apply. If neither is given the installation properties apply to " "both target types. If only one is given then only targets of that " "type will be installed (which can be used to install just a DLL or " - "just an import library).\n" - "DESTINATION arguments specify the directory on disk to which the " - "target file will be installed. " - "If a full path (with a leading slash or drive letter) is given it " - "is used directly. If a relative path is given it is interpreted " - "relative to the value of CMAKE_INSTALL_PREFIX.\n" + "just an import library)." + "\n" "One or more groups of properties may be specified in a single call " "to the TARGETS form of this command. A target may be installed more " "than once to different locations. Consider hypothetical " @@ -102,12 +107,33 @@ public: "installed to /bin and /some/full/path and its import library " "will be installed to /lib and /some/full/path. On non-DLL " "platforms mySharedLib will be installed to /lib and " - "/some/full/path.\n" + "/some/full/path." + "\n" + "The FILES signature:\n" + " INSTALL(FILES [files...] DESTINATION )\n" + "The FILES form specifies rules for installing files for a " + "project. File names given as relative paths are interpreted with " + "respect to the current source directory. Files installed by this " + "form are given the same permissions as the original file by default." + "\n" + "The PROGRAMS signature:\n" + " INSTALL(PROGRAMS [files...] DESTINATION )\n" + "The PROGRAMS form is identical to the FILES form except that the " + "default permissions for the installed file mark it as executable. " + "This form is intended to install programs that are not targets, " + "such as shell scripts. Use the TARGETS form to install targets " + "built within the project." + "\n" + "The SCRIPT signature:\n" " INSTALL(SCRIPT [SCRIPT [...]])\n" "The SCRIPT form will invoke the given CMake script files during " - "installation.\n" + "installation. If the script file name is a relative path " + "it will be interpreted with respect to the current source directory." + "\n" "NOTE: This command supercedes the INSTALL_TARGETS command and the " "target properties PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT. " + "It also replaces the FILES forms of the INSTALL_FILES and " + "INSTALL_PROGRAMS commands. " "The processing order of these install rules relative to those " "generated by INSTALL_TARGETS, INSTALL_FILES, and INSTALL_PROGRAMS " "commands is not defined.\n" @@ -119,6 +145,7 @@ public: private: bool HandleScriptMode(std::vector const& args); bool HandleTargetsMode(std::vector const& args); + bool HandleFilesMode(std::vector const& args); void ComputeDestination(const char* destination, std::string& dest); }; diff --git a/Source/cmInstallFilesCommand.h b/Source/cmInstallFilesCommand.h index c02e9ce..ed6fb2e 100644 --- a/Source/cmInstallFilesCommand.h +++ b/Source/cmInstallFilesCommand.h @@ -52,7 +52,7 @@ public: */ virtual const char* GetTerseDocumentation() { - return "Create install rules for files."; + return "Old installation command. Use the INSTALL command."; } /** @@ -69,7 +69,12 @@ public: virtual const char* GetFullDocumentation() { return - " INSTALL_FILES( extension file file ...)\n" + "This command has been superceded by the INSTALL command. It " + "is provided for compatibility with older CMake code. " + "The FILES form is directly replaced by the FILES form of the " + "INSTALL command. The regexp form can be expressed " + "more clearly using the GLOB form of the FILE command.\n" + " INSTALL_FILES( extension file file ...)\n" "Create rules to install the listed files with the given extension " "into the given directory. " "Only files existing in the current source tree or its corresponding " diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx new file mode 100644 index 0000000..7a73327 --- /dev/null +++ b/Source/cmInstallFilesGenerator.cxx @@ -0,0 +1,47 @@ +/*========================================================================= + + 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 "cmInstallFilesGenerator.h" + +#include "cmTarget.h" + +//---------------------------------------------------------------------------- +cmInstallFilesGenerator +::cmInstallFilesGenerator(std::vector const& files, + const char* dest, bool programs): + Files(files), Destination(dest), Programs(programs) +{ +} + +//---------------------------------------------------------------------------- +cmInstallFilesGenerator +::~cmInstallFilesGenerator() +{ +} + +//---------------------------------------------------------------------------- +void cmInstallFilesGenerator::GenerateScript(std::ostream& os) +{ + // Write code to install the files. + for(std::vector::const_iterator fi = this->Files.begin(); + fi != this->Files.end(); ++fi) + { + this->AddInstallRule(os, this->Destination.c_str(), + (this->Programs + ? cmTarget::INSTALL_PROGRAMS + : cmTarget::INSTALL_FILES), fi->c_str()); + } +} diff --git a/Source/cmInstallFilesGenerator.h b/Source/cmInstallFilesGenerator.h new file mode 100644 index 0000000..9d35c73 --- /dev/null +++ b/Source/cmInstallFilesGenerator.h @@ -0,0 +1,39 @@ +/*========================================================================= + + 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 cmInstallFilesGenerator_h +#define cmInstallFilesGenerator_h + +#include "cmInstallGenerator.h" + +/** \class cmInstallFilesGenerator + * \brief Generate file installation rules. + */ +class cmInstallFilesGenerator: public cmInstallGenerator +{ +public: + cmInstallFilesGenerator(std::vector const& files, + const char* dest, bool programs); + virtual ~cmInstallFilesGenerator(); + +protected: + virtual void GenerateScript(std::ostream& os); + std::vector Files; + std::string Destination; + bool Programs; +}; + +#endif diff --git a/Source/cmInstallProgramsCommand.h b/Source/cmInstallProgramsCommand.h index 7aff27f..f50403b 100644 --- a/Source/cmInstallProgramsCommand.h +++ b/Source/cmInstallProgramsCommand.h @@ -52,7 +52,7 @@ public: */ virtual const char* GetTerseDocumentation() { - return "Create install rules for programs."; + return "Old installation command. Use the INSTALL command."; } /** @@ -69,6 +69,11 @@ public: virtual const char* GetFullDocumentation() { return + "This command has been superceded by the INSTALL command. It " + "is provided for compatibility with older CMake code. " + "The FILES form is directly replaced by the PROGRAMS form of the " + "INSTALL command. The regexp form can be expressed more clearly " + "using the GLOB form of the FILE command.\n" " INSTALL_PROGRAMS( file1 file2 [file3 ...])\n" " INSTALL_PROGRAMS( FILES file1 [file2 ...])\n" "Create rules to install the listed programs into the given directory. " @@ -78,7 +83,8 @@ public: "In the second form any program in the current source directory that " "matches the regular expression will be installed.\n" "This command is intended to install programs that are not built " - "by cmake, such as shell scripts. See INSTALL_TARGETS to " + "by cmake, such as shell scripts. See the TARGETS form of " + "the INSTALL command to " "create installation rules for targets built by cmake.\n" "The directory is relative to the installation prefix, which " "is stored in the variable CMAKE_INSTALL_PREFIX."; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index b6e1369..e7d56a5 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -19,6 +19,7 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmInstallGenerator.h" +#include "cmInstallFilesGenerator.h" #include "cmInstallScriptGenerator.h" #include "cmInstallTargetGenerator.h" #include "cmMakefile.h" @@ -1679,52 +1680,18 @@ cmLocalGenerator break; case cmTarget::INSTALL_FILES: { - std::string sourcePath = m_Makefile->GetCurrentDirectory(); - std::string binaryPath = m_Makefile->GetCurrentOutputDirectory(); - sourcePath += "/"; - binaryPath += "/"; - const std::vector &sf = l->second.GetSourceLists(); - std::vector::const_iterator i; - for (i = sf.begin(); i != sf.end(); ++i) - { - std::string f = *i; - if(f.substr(0, sourcePath.length()) == sourcePath) - { - f = f.substr(sourcePath.length()); - } - else if(f.substr(0, binaryPath.length()) == binaryPath) - { - f = f.substr(binaryPath.length()); - } - cmInstallGenerator::AddInstallRule(os, destination.c_str(), - cmTarget::INSTALL_FILES, - i->c_str()); - } + // Use a file install generator. + cmInstallFilesGenerator g(l->second.GetSourceLists(), + destination.c_str(), false); + g.Generate(os, config, configurationTypes); } break; case cmTarget::INSTALL_PROGRAMS: { - std::string sourcePath = m_Makefile->GetCurrentDirectory(); - std::string binaryPath = m_Makefile->GetCurrentOutputDirectory(); - sourcePath += "/"; - binaryPath += "/"; - const std::vector &sf = l->second.GetSourceLists(); - std::vector::const_iterator i; - for (i = sf.begin(); i != sf.end(); ++i) - { - std::string f = *i; - if(f.substr(0, sourcePath.length()) == sourcePath) - { - f = f.substr(sourcePath.length()); - } - else if(f.substr(0, binaryPath.length()) == binaryPath) - { - f = f.substr(binaryPath.length()); - } - cmInstallGenerator::AddInstallRule(os, destination.c_str(), - cmTarget::INSTALL_PROGRAMS, - i->c_str()); - } + // Use a file install generator. + cmInstallFilesGenerator g(l->second.GetSourceLists(), + destination.c_str(), true); + g.Generate(os, config, configurationTypes); } break; case cmTarget::UTILITY: diff --git a/Tests/SimpleInstall/CMakeLists.txt b/Tests/SimpleInstall/CMakeLists.txt index f8ab86a..a12fdcd 100644 --- a/Tests/SimpleInstall/CMakeLists.txt +++ b/Tests/SimpleInstall/CMakeLists.txt @@ -90,7 +90,8 @@ ELSE(STAGE2) INSTALL(TARGETS SimpleInstall test1 test2 test3 test4 RUNTIME DESTINATION bin LIBRARY DESTINATION lib) - INSTALL_FILES(/include FILES lib1.h lib2.h lib3.h) + INSTALL(FILES lib1.h lib2.h DESTINATION include) + INSTALL_FILES(/include FILES lib3.h) # Test user-specified install scripts. INSTALL( diff --git a/Tests/SimpleInstallS2/CMakeLists.txt b/Tests/SimpleInstallS2/CMakeLists.txt index f8ab86a..a12fdcd 100644 --- a/Tests/SimpleInstallS2/CMakeLists.txt +++ b/Tests/SimpleInstallS2/CMakeLists.txt @@ -90,7 +90,8 @@ ELSE(STAGE2) INSTALL(TARGETS SimpleInstall test1 test2 test3 test4 RUNTIME DESTINATION bin LIBRARY DESTINATION lib) - INSTALL_FILES(/include FILES lib1.h lib2.h lib3.h) + INSTALL(FILES lib1.h lib2.h DESTINATION include) + INSTALL_FILES(/include FILES lib3.h) # Test user-specified install scripts. INSTALL( diff --git a/bootstrap b/bootstrap index d2974f8..52c3593 100755 --- a/bootstrap +++ b/bootstrap @@ -98,6 +98,7 @@ CMAKE_CXX_SOURCES="\ cmGlob \ cmLocalGenerator \ cmInstallGenerator \ + cmInstallFilesGenerator \ cmInstallScriptGenerator \ cmInstallTargetGenerator \ cmSourceFile \ -- cgit v0.12