diff options
Diffstat (limited to 'Source/cmInstallCommand.cxx')
-rw-r--r-- | Source/cmInstallCommand.cxx | 376 |
1 files changed, 297 insertions, 79 deletions
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index fbc5278..7c8458a 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -3,6 +3,7 @@ #include "cmInstallCommand.h" #include "cmsys/Glob.hxx" +#include <set> #include <sstream> #include <stddef.h> #include <utility> @@ -33,8 +34,8 @@ class cmExecutionStatus; static cmInstallTargetGenerator* CreateInstallTargetGenerator( cmTarget& target, const cmInstallCommandArguments& args, bool impLib, - cmListFileBacktrace const& backtrace, bool forceOpt = false, - bool namelink = false) + cmListFileBacktrace const& backtrace, const std::string& destination, + bool forceOpt = false, bool namelink = false) { cmInstallGenerator::MessageLevel message = cmInstallGenerator::SelectMessageLevel(target.GetMakefile()); @@ -42,25 +43,49 @@ static cmInstallTargetGenerator* CreateInstallTargetGenerator( const char* component = namelink ? args.GetNamelinkComponent().c_str() : args.GetComponent().c_str(); return new cmInstallTargetGenerator( - target.GetName(), args.GetDestination().c_str(), impLib, + target.GetName(), destination.c_str(), impLib, args.GetPermissions().c_str(), args.GetConfigurations(), component, message, args.GetExcludeFromAll(), args.GetOptional() || forceOpt, backtrace); } +static cmInstallTargetGenerator* CreateInstallTargetGenerator( + cmTarget& target, const cmInstallCommandArguments& args, bool impLib, + cmListFileBacktrace const& backtrace, bool forceOpt = false, + bool namelink = false) +{ + return CreateInstallTargetGenerator(target, args, impLib, backtrace, + args.GetDestination(), forceOpt, + namelink); +} + static cmInstallFilesGenerator* CreateInstallFilesGenerator( cmMakefile* mf, const std::vector<std::string>& absFiles, - const cmInstallCommandArguments& args, bool programs) + const cmInstallCommandArguments& args, bool programs, + const std::string& destination) { cmInstallGenerator::MessageLevel message = cmInstallGenerator::SelectMessageLevel(mf); return new cmInstallFilesGenerator( - absFiles, args.GetDestination().c_str(), programs, - args.GetPermissions().c_str(), args.GetConfigurations(), - args.GetComponent().c_str(), message, args.GetExcludeFromAll(), - args.GetRename().c_str(), args.GetOptional()); + absFiles, destination.c_str(), programs, args.GetPermissions().c_str(), + args.GetConfigurations(), args.GetComponent().c_str(), message, + args.GetExcludeFromAll(), args.GetRename().c_str(), args.GetOptional()); } +static cmInstallFilesGenerator* CreateInstallFilesGenerator( + cmMakefile* mf, const std::vector<std::string>& absFiles, + const cmInstallCommandArguments& args, bool programs) +{ + return CreateInstallFilesGenerator(mf, absFiles, args, programs, + args.GetDestination()); +} + +static const std::set<std::string> allowedTypes{ + "BIN", "SBIN", "LIB", "INCLUDE", "SYSCONF", + "SHAREDSTATE", "LOCALSTATE", "RUNSTATE", "DATA", "INFO", + "LOCALE", "MAN", "DOC", +}; + // cmInstallCommand bool cmInstallCommand::InitialPass(std::vector<std::string> const& args, cmExecutionStatus&) @@ -335,6 +360,17 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) "At most one of these two options may be specified."); return false; } + if (!genericArgs.GetType().empty() || !archiveArgs.GetType().empty() || + !libraryArgs.GetType().empty() || !runtimeArgs.GetType().empty() || + !objectArgs.GetType().empty() || !frameworkArgs.GetType().empty() || + !bundleArgs.GetType().empty() || !privateHeaderArgs.GetType().empty() || + !publicHeaderArgs.GetType().empty() || !resourceArgs.GetType().empty()) { + std::ostringstream e; + e << "TARGETS given TYPE option. The TYPE option may only be specified in " + " install(FILES) and install(DIRECTORIES)."; + this->SetError(e.str()); + return false; + } // Select the mode for installing symlinks to versioned shared libraries. cmInstallTargetGenerator::NamelinkModeType namelinkMode = @@ -447,8 +483,12 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) target, runtimeArgs, false, this->Makefile->GetBacktrace()); } if ((archiveGenerator == nullptr) && (runtimeGenerator == nullptr)) { - this->SetError("Library TARGETS given no DESTINATION!"); - return false; + archiveGenerator = CreateInstallTargetGenerator( + target, archiveArgs, true, this->Makefile->GetBacktrace(), + this->GetArchiveDestination(nullptr)); + runtimeGenerator = CreateInstallTargetGenerator( + target, runtimeArgs, false, this->Makefile->GetBacktrace(), + this->GetRuntimeDestination(nullptr)); } } else { // This is a non-DLL platform. @@ -474,30 +514,22 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) } } else { // The shared library uses the LIBRARY properties. - if (!libraryArgs.GetDestination().empty()) { - if (namelinkMode != cmInstallTargetGenerator::NamelinkModeOnly) { - libraryGenerator = CreateInstallTargetGenerator( - target, libraryArgs, false, this->Makefile->GetBacktrace()); - libraryGenerator->SetNamelinkMode( - cmInstallTargetGenerator::NamelinkModeSkip); - } - if (namelinkMode != cmInstallTargetGenerator::NamelinkModeSkip) { - namelinkGenerator = CreateInstallTargetGenerator( - target, libraryArgs, false, this->Makefile->GetBacktrace(), - false, true); - namelinkGenerator->SetNamelinkMode( - cmInstallTargetGenerator::NamelinkModeOnly); - } - namelinkOnly = - (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly); - } else { - std::ostringstream e; - e << "TARGETS given no LIBRARY DESTINATION for shared library " - "target \"" - << target.GetName() << "\"."; - this->SetError(e.str()); - return false; + if (namelinkMode != cmInstallTargetGenerator::NamelinkModeOnly) { + libraryGenerator = CreateInstallTargetGenerator( + target, libraryArgs, false, this->Makefile->GetBacktrace(), + this->GetLibraryDestination(&libraryArgs)); + libraryGenerator->SetNamelinkMode( + cmInstallTargetGenerator::NamelinkModeSkip); + } + if (namelinkMode != cmInstallTargetGenerator::NamelinkModeSkip) { + namelinkGenerator = CreateInstallTargetGenerator( + target, libraryArgs, false, this->Makefile->GetBacktrace(), + this->GetLibraryDestination(&libraryArgs), false, true); + namelinkGenerator->SetNamelinkMode( + cmInstallTargetGenerator::NamelinkModeOnly); } + namelinkOnly = + (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly); } } } break; @@ -524,17 +556,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) } } else { // Static libraries use ARCHIVE properties. - if (!archiveArgs.GetDestination().empty()) { - archiveGenerator = CreateInstallTargetGenerator( - target, archiveArgs, false, this->Makefile->GetBacktrace()); - } else { - std::ostringstream e; - e << "TARGETS given no ARCHIVE DESTINATION for static library " - "target \"" - << target.GetName() << "\"."; - this->SetError(e.str()); - return false; - } + archiveGenerator = CreateInstallTargetGenerator( + target, archiveArgs, false, this->Makefile->GetBacktrace(), + this->GetArchiveDestination(&archiveArgs)); } } break; case cmStateEnums::MODULE_LIBRARY: { @@ -602,17 +626,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) } } else { // Executables use the RUNTIME properties. - if (!runtimeArgs.GetDestination().empty()) { - runtimeGenerator = CreateInstallTargetGenerator( - target, runtimeArgs, false, this->Makefile->GetBacktrace()); - } else { - std::ostringstream e; - e << "TARGETS given no RUNTIME DESTINATION for executable " - "target \"" - << target.GetName() << "\"."; - this->SetError(e.str()); - return false; - } + runtimeGenerator = CreateInstallTargetGenerator( + target, runtimeArgs, false, this->Makefile->GetBacktrace(), + this->GetRuntimeDestination(&runtimeArgs)); } // On DLL platforms an executable may also have an import @@ -659,15 +675,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) } // Create the files install generator. - if (!privateHeaderArgs.GetDestination().empty()) { - privateHeaderGenerator = CreateInstallFilesGenerator( - this->Makefile, absFiles, privateHeaderArgs, false); - } else { - std::ostringstream e; - e << "INSTALL TARGETS - target " << target.GetName() << " has " - << "PRIVATE_HEADER files but no PRIVATE_HEADER DESTINATION."; - cmSystemTools::Message(e.str().c_str(), "Warning"); - } + privateHeaderGenerator = CreateInstallFilesGenerator( + this->Makefile, absFiles, privateHeaderArgs, false, + this->GetIncludeDestination(&privateHeaderArgs)); } files = target.GetProperty("PUBLIC_HEADER"); @@ -680,15 +690,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) } // Create the files install generator. - if (!publicHeaderArgs.GetDestination().empty()) { - publicHeaderGenerator = CreateInstallFilesGenerator( - this->Makefile, absFiles, publicHeaderArgs, false); - } else { - std::ostringstream e; - e << "INSTALL TARGETS - target " << target.GetName() << " has " - << "PUBLIC_HEADER files but no PUBLIC_HEADER DESTINATION."; - cmSystemTools::Message(e.str().c_str(), "Warning"); - } + publicHeaderGenerator = CreateInstallFilesGenerator( + this->Makefile, absFiles, publicHeaderArgs, false, + this->GetIncludeDestination(&publicHeaderArgs)); } files = target.GetProperty("RESOURCE"); @@ -824,6 +828,14 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) return false; } + std::string type = ica.GetType(); + if (!type.empty() && allowedTypes.count(type) == 0) { + std::ostringstream e; + e << args[0] << " given non-type \"" << type << "\" with TYPE argument."; + this->SetError(e.str()); + return false; + } + const std::vector<std::string>& filesVector = files.GetVector(); // Check if there is something to do. @@ -886,7 +898,17 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) return false; } - if (ica.GetDestination().empty()) { + if (!type.empty() && !ica.GetDestination().empty()) { + std::ostringstream e; + e << args[0] + << " given both TYPE and DESTINATION arguments. You may only specify " + "one."; + this->SetError(e.str()); + return false; + } + + std::string destination = this->GetDestinationForType(&ica, type); + if (destination.empty()) { // A destination is required. std::ostringstream e; e << args[0] << " given no DESTINATION!"; @@ -895,8 +917,8 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) } // Create the files install generator. - this->Makefile->AddInstallGenerator( - CreateInstallFilesGenerator(this->Makefile, absFiles, ica, programs)); + this->Makefile->AddInstallGenerator(CreateInstallFilesGenerator( + this->Makefile, absFiles, ica, programs, destination)); // Tell the global generator about any installation component names // specified. @@ -920,7 +942,8 @@ bool cmInstallCommand::HandleDirectoryMode( DoingPermsDir, DoingPermsMatch, DoingConfigurations, - DoingComponent + DoingComponent, + DoingType }; Doing doing = DoingDirs; bool in_match_mode = false; @@ -934,6 +957,7 @@ bool cmInstallCommand::HandleDirectoryMode( std::vector<std::string> configurations; std::string component = this->DefaultComponentName; std::string literal_args; + std::string type; for (unsigned int i = 1; i < args.size(); ++i) { if (args[i] == "DESTINATION") { if (in_match_mode) { @@ -946,6 +970,17 @@ bool cmInstallCommand::HandleDirectoryMode( // Switch to setting the destination property. doing = DoingDestination; + } else if (args[i] == "TYPE") { + if (in_match_mode) { + std::ostringstream e; + e << args[0] << " does not allow \"" << args[i] + << "\" after PATTERN or REGEX."; + this->SetError(e.str()); + return false; + } + + // Switch to setting the type. + doing = DoingType; } else if (args[i] == "OPTIONAL") { if (in_match_mode) { std::ostringstream e; @@ -1106,6 +1141,17 @@ bool cmInstallCommand::HandleDirectoryMode( } else if (doing == DoingDestination) { destination = args[i].c_str(); doing = DoingNone; + } else if (doing == DoingType) { + if (allowedTypes.count(args[i]) == 0) { + std::ostringstream e; + e << args[0] << " given non-type \"" << args[i] + << "\" with TYPE argument."; + this->SetError(e.str()); + return false; + } + + type = args[i]; + doing = DoingNone; } else if (doing == DoingPattern) { // Convert the pattern to a regular expression. Require a // leading slash and trailing end-of-string in the matched @@ -1179,10 +1225,22 @@ bool cmInstallCommand::HandleDirectoryMode( if (dirs.empty()) { return true; } + std::string destinationStr; if (!destination) { - // A destination is required. + if (type.empty()) { + // A destination is required. + std::ostringstream e; + e << args[0] << " given no DESTINATION!"; + this->SetError(e.str()); + return false; + } + destinationStr = this->GetDestinationForType(nullptr, type); + destination = destinationStr.c_str(); + } else if (!type.empty()) { std::ostringstream e; - e << args[0] << " given no DESTINATION!"; + e << args[0] + << " given both TYPE and DESTINATION arguments. You may only specify " + "one."; this->SetError(e.str()); return false; } @@ -1456,3 +1514,163 @@ bool cmInstallCommand::CheckCMP0006(bool& failure) } return false; } + +std::string cmInstallCommand::GetDestination( + const cmInstallCommandArguments* args, const std::string& varName, + const std::string& guess) +{ + if (args && !args->GetDestination().empty()) { + return args->GetDestination(); + } + std::string val = this->Makefile->GetSafeDefinition(varName); + if (!val.empty()) { + return val; + } + return guess; +} + +std::string cmInstallCommand::GetRuntimeDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_BINDIR", "bin"); +} + +std::string cmInstallCommand::GetSbinDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_SBINDIR", "sbin"); +} + +std::string cmInstallCommand::GetArchiveDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib"); +} + +std::string cmInstallCommand::GetLibraryDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib"); +} + +std::string cmInstallCommand::GetIncludeDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_INCLUDEDIR", "include"); +} + +std::string cmInstallCommand::GetSysconfDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_SYSCONFDIR", "etc"); +} + +std::string cmInstallCommand::GetSharedStateDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_SHAREDSTATEDIR", "com"); +} + +std::string cmInstallCommand::GetLocalStateDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_LOCALSTATEDIR", "var"); +} + +std::string cmInstallCommand::GetRunStateDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_RUNSTATEDIR", + this->GetLocalStateDestination(nullptr) + + "/run"); +} + +std::string cmInstallCommand::GetDataRootDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_DATAROOTDIR", "share"); +} + +std::string cmInstallCommand::GetDataDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_DATADIR", + this->GetDataRootDestination(nullptr)); +} + +std::string cmInstallCommand::GetInfoDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_INFODIR", + this->GetDataRootDestination(nullptr) + "/info"); +} + +std::string cmInstallCommand::GetLocaleDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_LOCALEDIR", + this->GetDataRootDestination(nullptr) + + "/locale"); +} + +std::string cmInstallCommand::GetManDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_MANDIR", + this->GetDataRootDestination(nullptr) + "/man"); +} + +std::string cmInstallCommand::GetDocDestination( + const cmInstallCommandArguments* args) +{ + return this->GetDestination(args, "CMAKE_INSTALL_DOCDIR", + this->GetDataRootDestination(nullptr) + "/doc"); +} + +std::string cmInstallCommand::GetDestinationForType( + const cmInstallCommandArguments* args, const std::string& type) +{ + if (args && !args->GetDestination().empty()) { + return args->GetDestination(); + } + if (type == "BIN") { + return this->GetRuntimeDestination(nullptr); + } + if (type == "SBIN") { + return this->GetSbinDestination(nullptr); + } + if (type == "SYSCONF") { + return this->GetSysconfDestination(nullptr); + } + if (type == "SHAREDSTATE") { + return this->GetSharedStateDestination(nullptr); + } + if (type == "LOCALSTATE") { + return this->GetLocalStateDestination(nullptr); + } + if (type == "RUNSTATE") { + return this->GetRunStateDestination(nullptr); + } + if (type == "LIB") { + return this->GetLibraryDestination(nullptr); + } + if (type == "INCLUDE") { + return this->GetIncludeDestination(nullptr); + } + if (type == "DATA") { + return this->GetDataDestination(nullptr); + } + if (type == "INFO") { + return this->GetInfoDestination(nullptr); + } + if (type == "LOCALE") { + return this->GetLocaleDestination(nullptr); + } + if (type == "MAN") { + return this->GetManDestination(nullptr); + } + if (type == "DOC") { + return this->GetDocDestination(nullptr); + } + return ""; +} |