summaryrefslogtreecommitdiffstats
path: root/Source/cmInstallCommand.cxx
diff options
context:
space:
mode:
authorKyle Edwards <kyle.edwards@kitware.com>2018-11-02 16:42:41 (GMT)
committerKyle Edwards <kyle.edwards@kitware.com>2018-11-07 19:08:48 (GMT)
commit9fc20a4f3e1865e409d960c87e2e4a366775b72b (patch)
tree5ea698da30b881b7ad4db2e3770e27727f93fcb9 /Source/cmInstallCommand.cxx
parent71db32660eed1f70c06b624e661f8f5c2b938907 (diff)
downloadCMake-9fc20a4f3e1865e409d960c87e2e4a366775b72b.zip
CMake-9fc20a4f3e1865e409d960c87e2e4a366775b72b.tar.gz
CMake-9fc20a4f3e1865e409d960c87e2e4a366775b72b.tar.bz2
install: Add sane set of defaults for DESTINATION and file type parameters
If the user does not specify a DESTINATION for a target type, the install() command checks to see if the appropriate variable from GNUInstallDirs is set. If it is not, then it uses an appropriate hard-coded guess. In addition, for FILES and DIRECTORY, the user can specify a file type instead of a DESTINATION, and the command will use the appropriate variable from GNUInstallDirs, or a hard-coded guess if it is not set.
Diffstat (limited to 'Source/cmInstallCommand.cxx')
-rw-r--r--Source/cmInstallCommand.cxx376
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 "";
+}