summaryrefslogtreecommitdiffstats
path: root/Source/CPack/cmCPackGenerator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/CPack/cmCPackGenerator.cxx')
-rw-r--r--Source/CPack/cmCPackGenerator.cxx1551
1 files changed, 1551 insertions, 0 deletions
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
new file mode 100644
index 0000000..127bcf9
--- /dev/null
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -0,0 +1,1551 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackGenerator.h"
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/RegularExpression.hxx"
+#include <algorithm>
+#include <cstring>
+#include <memory> // IWYU pragma: keep
+#include <utility>
+
+#include "cmCPackComponentGroup.h"
+#include "cmCPackLog.h"
+#include "cmCryptoHash.h"
+#include "cmDuration.h"
+#include "cmFSPermissions.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmState.h"
+#include "cmStateSnapshot.h"
+#include "cmVersion.h"
+#include "cmWorkingDirectory.h"
+#include "cmXMLSafe.h"
+#include "cmake.h"
+
+#if defined(__HAIKU__)
+# include <FindDirectory.h>
+# include <StorageDefs.h>
+#endif
+
+cmCPackGenerator::cmCPackGenerator()
+{
+ this->GeneratorVerbose = cmSystemTools::OUTPUT_NONE;
+ this->MakefileMap = nullptr;
+ this->Logger = nullptr;
+ this->componentPackageMethod = ONE_PACKAGE_PER_GROUP;
+}
+
+cmCPackGenerator::~cmCPackGenerator()
+{
+ this->MakefileMap = nullptr;
+}
+
+void cmCPackGenerator::DisplayVerboseOutput(const std::string& msg,
+ float progress)
+{
+ (void)progress;
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE, "" << msg << std::endl);
+}
+
+int cmCPackGenerator::PrepareNames()
+{
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "Create temp directory." << std::endl);
+
+ // checks CPACK_SET_DESTDIR support
+ if (IsOn("CPACK_SET_DESTDIR")) {
+ if (SETDESTDIR_UNSUPPORTED == SupportsSetDestdir()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_SET_DESTDIR is set to ON but the '"
+ << Name << "' generator does NOT support it."
+ << std::endl);
+ return 0;
+ }
+ if (SETDESTDIR_SHOULD_NOT_BE_USED == SupportsSetDestdir()) {
+ cmCPackLogger(cmCPackLog::LOG_WARNING,
+ "CPACK_SET_DESTDIR is set to ON but it is "
+ << "usually a bad idea to do that with '" << Name
+ << "' generator. Use at your own risk." << std::endl);
+ }
+ }
+
+ std::string tempDirectory = this->GetOption("CPACK_PACKAGE_DIRECTORY");
+ tempDirectory += "/_CPack_Packages/";
+ const char* toplevelTag = this->GetOption("CPACK_TOPLEVEL_TAG");
+ if (toplevelTag) {
+ tempDirectory += toplevelTag;
+ tempDirectory += "/";
+ }
+ tempDirectory += this->GetOption("CPACK_GENERATOR");
+ std::string topDirectory = tempDirectory;
+ const char* pfname = this->GetOption("CPACK_PACKAGE_FILE_NAME");
+ if (!pfname) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_PACKAGE_FILE_NAME not specified" << std::endl);
+ return 0;
+ }
+ std::string outName = pfname;
+ tempDirectory += "/" + outName;
+ if (!this->GetOutputExtension()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "No output extension specified" << std::endl);
+ return 0;
+ }
+ outName += this->GetOutputExtension();
+ const char* pdir = this->GetOption("CPACK_PACKAGE_DIRECTORY");
+ if (!pdir) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_PACKAGE_DIRECTORY not specified" << std::endl);
+ return 0;
+ }
+
+ std::string destFile = pdir;
+ this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_PREFIX", destFile.c_str());
+ destFile += "/" + outName;
+ std::string outFile = topDirectory + "/" + outName;
+ this->SetOptionIfNotSet("CPACK_TOPLEVEL_DIRECTORY", topDirectory.c_str());
+ this->SetOptionIfNotSet("CPACK_TEMPORARY_DIRECTORY", tempDirectory.c_str());
+ this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_NAME", outName.c_str());
+ this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_PATH", destFile.c_str());
+ this->SetOptionIfNotSet("CPACK_TEMPORARY_PACKAGE_FILE_NAME",
+ outFile.c_str());
+ this->SetOptionIfNotSet("CPACK_INSTALL_DIRECTORY", this->GetInstallPath());
+ this->SetOptionIfNotSet(
+ "CPACK_NATIVE_INSTALL_DIRECTORY",
+ cmsys::SystemTools::ConvertToOutputPath(this->GetInstallPath()).c_str());
+ this->SetOptionIfNotSet("CPACK_TEMPORARY_INSTALL_DIRECTORY",
+ tempDirectory.c_str());
+
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Look for: CPACK_PACKAGE_DESCRIPTION_FILE" << std::endl);
+ const char* descFileName = this->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE");
+ if (descFileName) {
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Look for: " << descFileName << std::endl);
+ if (!cmSystemTools::FileExists(descFileName)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find description file name: ["
+ << descFileName << "]" << std::endl);
+ return 0;
+ }
+ cmsys::ifstream ifs(descFileName);
+ if (!ifs) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot open description file name: " << descFileName
+ << std::endl);
+ return 0;
+ }
+ std::ostringstream ostr;
+ std::string line;
+
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Read description file: " << descFileName << std::endl);
+ while (ifs && cmSystemTools::GetLineFromStream(ifs, line)) {
+ ostr << cmXMLSafe(line) << std::endl;
+ }
+ this->SetOptionIfNotSet("CPACK_PACKAGE_DESCRIPTION", ostr.str().c_str());
+ }
+ if (!this->GetOption("CPACK_PACKAGE_DESCRIPTION")) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
+ "Project description not specified. Please specify "
+ "CPACK_PACKAGE_DESCRIPTION or CPACK_PACKAGE_DESCRIPTION_FILE."
+ << std::endl);
+ return 0;
+ }
+ const char* algoSignature = this->GetOption("CPACK_PACKAGE_CHECKSUM");
+ if (algoSignature) {
+ if (!cmCryptoHash::New(algoSignature)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot recognize algorithm: " << algoSignature
+ << std::endl);
+ return 0;
+ }
+ }
+
+ this->SetOptionIfNotSet("CPACK_REMOVE_TOPLEVEL_DIRECTORY", "1");
+
+ return 1;
+}
+
+int cmCPackGenerator::InstallProject()
+{
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Install projects" << std::endl);
+ this->CleanTemporaryDirectory();
+
+ std::string bareTempInstallDirectory =
+ this->GetOption("CPACK_TEMPORARY_INSTALL_DIRECTORY");
+ std::string tempInstallDirectoryStr = bareTempInstallDirectory;
+ bool setDestDir = cmSystemTools::IsOn(this->GetOption("CPACK_SET_DESTDIR")) |
+ cmSystemTools::IsInternallyOn(this->GetOption("CPACK_SET_DESTDIR"));
+ if (!setDestDir) {
+ tempInstallDirectoryStr += this->GetPackagingInstallPrefix();
+ }
+
+ const char* tempInstallDirectory = tempInstallDirectoryStr.c_str();
+ int res = 1;
+ if (!cmsys::SystemTools::MakeDirectory(bareTempInstallDirectory)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem creating temporary directory: "
+ << (tempInstallDirectory ? tempInstallDirectory : "(NULL)")
+ << std::endl);
+ return 0;
+ }
+
+ if (setDestDir) {
+ std::string destDir = "DESTDIR=";
+ destDir += tempInstallDirectory;
+ cmSystemTools::PutEnv(destDir);
+ } else {
+ // Make sure there is no destdir
+ cmSystemTools::PutEnv("DESTDIR=");
+ }
+
+ // prepare default created directory permissions
+ mode_t default_dir_mode_v = 0;
+ mode_t* default_dir_mode = nullptr;
+ const char* default_dir_install_permissions =
+ this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
+ if (default_dir_install_permissions && *default_dir_install_permissions) {
+ std::vector<std::string> items;
+ cmSystemTools::ExpandListArgument(default_dir_install_permissions, items);
+ for (const auto& arg : items) {
+ if (!cmFSPermissions::stringToModeT(arg, default_dir_mode_v)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Invalid permission value '"
+ << arg
+ << "'."
+ " CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS "
+ "value is invalid."
+ << std::endl);
+ return 0;
+ }
+ }
+
+ default_dir_mode = &default_dir_mode_v;
+ }
+
+ // If the CPackConfig file sets CPACK_INSTALL_COMMANDS then run them
+ // as listed
+ if (!this->InstallProjectViaInstallCommands(setDestDir,
+ tempInstallDirectory)) {
+ return 0;
+ }
+
+ // If the CPackConfig file sets CPACK_INSTALL_SCRIPT then run them
+ // as listed
+ if (!this->InstallProjectViaInstallScript(setDestDir,
+ tempInstallDirectory)) {
+ return 0;
+ }
+
+ // If the CPackConfig file sets CPACK_INSTALLED_DIRECTORIES
+ // then glob it and copy it to CPACK_TEMPORARY_DIRECTORY
+ // This is used in Source packaging
+ if (!this->InstallProjectViaInstalledDirectories(
+ setDestDir, tempInstallDirectory, default_dir_mode)) {
+ return 0;
+ }
+
+ // If the project is a CMAKE project then run pre-install
+ // and then read the cmake_install script to run it
+ if (!this->InstallProjectViaInstallCMakeProjects(
+ setDestDir, bareTempInstallDirectory, default_dir_mode)) {
+ return 0;
+ }
+
+ if (setDestDir) {
+ cmSystemTools::PutEnv("DESTDIR=");
+ }
+
+ return res;
+}
+
+int cmCPackGenerator::InstallProjectViaInstallCommands(
+ bool setDestDir, const std::string& tempInstallDirectory)
+{
+ (void)setDestDir;
+ const char* installCommands = this->GetOption("CPACK_INSTALL_COMMANDS");
+ if (installCommands && *installCommands) {
+ std::string tempInstallDirectoryEnv = "CMAKE_INSTALL_PREFIX=";
+ tempInstallDirectoryEnv += tempInstallDirectory;
+ cmSystemTools::PutEnv(tempInstallDirectoryEnv);
+ std::vector<std::string> installCommandsVector;
+ cmSystemTools::ExpandListArgument(installCommands, installCommandsVector);
+ for (std::string const& ic : installCommandsVector) {
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ic << std::endl);
+ std::string output;
+ int retVal = 1;
+ bool resB = cmSystemTools::RunSingleCommand(
+ ic, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+ cmDuration::zero());
+ if (!resB || retVal) {
+ std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
+ tmpFile += "/InstallOutput.log";
+ cmGeneratedFileStream ofs(tmpFile);
+ ofs << "# Run command: " << ic << std::endl
+ << "# Output:" << std::endl
+ << output << std::endl;
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running install command: "
+ << ic << std::endl
+ << "Please check " << tmpFile << " for errors"
+ << std::endl);
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
+int cmCPackGenerator::InstallProjectViaInstalledDirectories(
+ bool setDestDir, const std::string& tempInstallDirectory,
+ const mode_t* default_dir_mode)
+{
+ (void)setDestDir;
+ (void)tempInstallDirectory;
+ std::vector<cmsys::RegularExpression> ignoreFilesRegex;
+ const char* cpackIgnoreFiles = this->GetOption("CPACK_IGNORE_FILES");
+ if (cpackIgnoreFiles) {
+ std::vector<std::string> ignoreFilesRegexString;
+ cmSystemTools::ExpandListArgument(cpackIgnoreFiles,
+ ignoreFilesRegexString);
+ for (std::string const& ifr : ignoreFilesRegexString) {
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Create ignore files regex for: " << ifr << std::endl);
+ ignoreFilesRegex.emplace_back(ifr);
+ }
+ }
+ const char* installDirectories =
+ this->GetOption("CPACK_INSTALLED_DIRECTORIES");
+ if (installDirectories && *installDirectories) {
+ std::vector<std::string> installDirectoriesVector;
+ cmSystemTools::ExpandListArgument(installDirectories,
+ installDirectoriesVector);
+ if (installDirectoriesVector.size() % 2 != 0) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
+ "CPACK_INSTALLED_DIRECTORIES should contain pairs of <directory> and "
+ "<subdirectory>. The <subdirectory> can be '.' to be installed in "
+ "the toplevel directory of installation."
+ << std::endl);
+ return 0;
+ }
+ std::vector<std::string>::iterator it;
+ const std::string& tempDir = tempInstallDirectory;
+ for (it = installDirectoriesVector.begin();
+ it != installDirectoriesVector.end(); ++it) {
+ std::vector<std::pair<std::string, std::string>> symlinkedFiles;
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl);
+ cmsys::Glob gl;
+ std::string top = *it;
+ it++;
+ std::string subdir = *it;
+ std::string findExpr = top;
+ findExpr += "/*";
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Install directory: " << top << std::endl);
+ gl.RecurseOn();
+ gl.SetRecurseListDirs(true);
+ if (!gl.FindFiles(findExpr)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find any files in the installed directory"
+ << std::endl);
+ return 0;
+ }
+ files = gl.GetFiles();
+ for (std::string const& gf : files) {
+ bool skip = false;
+ std::string inFile = gf;
+ if (cmSystemTools::FileIsDirectory(gf)) {
+ inFile += '/';
+ }
+ for (cmsys::RegularExpression& reg : ignoreFilesRegex) {
+ if (reg.find(inFile)) {
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Ignore file: " << inFile << std::endl);
+ skip = true;
+ }
+ }
+ if (skip) {
+ continue;
+ }
+ std::string filePath = tempDir;
+ filePath += "/" + subdir + "/" + cmSystemTools::RelativePath(top, gf);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Copy file: " << inFile << " -> " << filePath
+ << std::endl);
+ /* If the file is a symlink we will have to re-create it */
+ if (cmSystemTools::FileIsSymlink(inFile)) {
+ std::string targetFile;
+ std::string inFileRelative =
+ cmSystemTools::RelativePath(top, inFile);
+ cmSystemTools::ReadSymlink(inFile, targetFile);
+ symlinkedFiles.emplace_back(std::move(targetFile),
+ std::move(inFileRelative));
+ }
+ /* If it is not a symlink then do a plain copy */
+ else if (!(cmSystemTools::CopyFileIfDifferent(inFile, filePath) &&
+ cmSystemTools::CopyFileTime(inFile, filePath))) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem copying file: " << inFile << " -> "
+ << filePath << std::endl);
+ return 0;
+ }
+ }
+ /* rebuild symlinks in the installed tree */
+ if (!symlinkedFiles.empty()) {
+ std::string curDir = cmSystemTools::GetCurrentWorkingDirectory();
+ std::string goToDir = tempDir;
+ goToDir += "/" + subdir;
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Change dir to: " << goToDir << std::endl);
+ cmWorkingDirectory workdir(goToDir);
+ if (workdir.Failed()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Failed to change working directory to "
+ << goToDir << " : "
+ << std::strerror(workdir.GetLastResult())
+ << std::endl);
+ return 0;
+ }
+ for (auto const& symlinked : symlinkedFiles) {
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Will create a symlink: " << symlinked.second << "--> "
+ << symlinked.first
+ << std::endl);
+ // make sure directory exists for symlink
+ std::string destDir =
+ cmSystemTools::GetFilenamePath(symlinked.second);
+ if (!destDir.empty() &&
+ !cmSystemTools::MakeDirectory(destDir, default_dir_mode)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot create dir: "
+ << destDir << "\nTrying to create symlink: "
+ << symlinked.second << "--> " << symlinked.first
+ << std::endl);
+ }
+ if (!cmSystemTools::CreateSymlink(symlinked.first,
+ symlinked.second)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot create symlink: "
+ << symlinked.second << "--> " << symlinked.first
+ << std::endl);
+ return 0;
+ }
+ }
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Going back to: " << curDir << std::endl);
+ }
+ }
+ }
+ return 1;
+}
+
+int cmCPackGenerator::InstallProjectViaInstallScript(
+ bool setDestDir, const std::string& tempInstallDirectory)
+{
+ const char* cmakeScripts = this->GetOption("CPACK_INSTALL_SCRIPT");
+ if (cmakeScripts && *cmakeScripts) {
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Install scripts: " << cmakeScripts << std::endl);
+ std::vector<std::string> cmakeScriptsVector;
+ cmSystemTools::ExpandListArgument(cmakeScripts, cmakeScriptsVector);
+ for (std::string const& installScript : cmakeScriptsVector) {
+
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Install script: " << installScript << std::endl);
+
+ if (setDestDir) {
+ // For DESTDIR based packaging, use the *project* CMAKE_INSTALL_PREFIX
+ // underneath the tempInstallDirectory. The value of the project's
+ // CMAKE_INSTALL_PREFIX is sent in here as the value of the
+ // CPACK_INSTALL_PREFIX variable.
+
+ std::string dir;
+ if (this->GetOption("CPACK_INSTALL_PREFIX")) {
+ dir += this->GetOption("CPACK_INSTALL_PREFIX");
+ }
+ this->SetOption("CMAKE_INSTALL_PREFIX", dir.c_str());
+ cmCPackLogger(
+ cmCPackLog::LOG_DEBUG,
+ "- Using DESTDIR + CPACK_INSTALL_PREFIX... (this->SetOption)"
+ << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "- Setting CMAKE_INSTALL_PREFIX to '" << dir << "'"
+ << std::endl);
+ } else {
+ this->SetOption("CMAKE_INSTALL_PREFIX", tempInstallDirectory.c_str());
+
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "- Using non-DESTDIR install... (this->SetOption)"
+ << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "- Setting CMAKE_INSTALL_PREFIX to '"
+ << tempInstallDirectory << "'" << std::endl);
+ }
+
+ this->SetOptionIfNotSet("CMAKE_CURRENT_BINARY_DIR",
+ tempInstallDirectory.c_str());
+ this->SetOptionIfNotSet("CMAKE_CURRENT_SOURCE_DIR",
+ tempInstallDirectory.c_str());
+ bool res = this->MakefileMap->ReadListFile(installScript);
+ if (cmSystemTools::GetErrorOccuredFlag() || !res) {
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
+int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
+ bool setDestDir, const std::string& baseTempInstallDirectory,
+ const mode_t* default_dir_mode)
+{
+ const char* cmakeProjects = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS");
+ const char* cmakeGenerator = this->GetOption("CPACK_CMAKE_GENERATOR");
+ std::string absoluteDestFiles;
+ if (cmakeProjects && *cmakeProjects) {
+ if (!cmakeGenerator) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_INSTALL_CMAKE_PROJECTS is specified, but "
+ "CPACK_CMAKE_GENERATOR is not. CPACK_CMAKE_GENERATOR "
+ "is required to install the project."
+ << std::endl);
+ return 0;
+ }
+ std::vector<std::string> cmakeProjectsVector;
+ cmSystemTools::ExpandListArgument(cmakeProjects, cmakeProjectsVector);
+ std::vector<std::string>::iterator it;
+ for (it = cmakeProjectsVector.begin(); it != cmakeProjectsVector.end();
+ ++it) {
+ if (it + 1 == cmakeProjectsVector.end() ||
+ it + 2 == cmakeProjectsVector.end() ||
+ it + 3 == cmakeProjectsVector.end()) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
+ "Not enough items on list: CPACK_INSTALL_CMAKE_PROJECTS. "
+ "CPACK_INSTALL_CMAKE_PROJECTS should hold quadruplet of install "
+ "directory, install project name, install component, and install "
+ "subdirectory."
+ << std::endl);
+ return 0;
+ }
+ std::string installDirectory = *it;
+ ++it;
+ std::string installProjectName = *it;
+ ++it;
+ cmCPackInstallCMakeProject project;
+
+ project.Directory = installDirectory;
+ project.ProjectName = installProjectName;
+ project.Component = *it;
+ ++it;
+ project.SubDirectory = *it;
+
+ std::vector<std::string> componentsVector;
+
+ bool componentInstall = false;
+ /*
+ * We do a component install iff
+ * - the CPack generator support component
+ * - the user did not request Monolithic install
+ * (this works at CPack time too)
+ */
+ if (this->SupportsComponentInstallation() &&
+ !(this->IsOn("CPACK_MONOLITHIC_INSTALL"))) {
+ // Determine the installation types for this project (if provided).
+ std::string installTypesVar = "CPACK_" +
+ cmSystemTools::UpperCase(project.Component) + "_INSTALL_TYPES";
+ const char* installTypes = this->GetOption(installTypesVar);
+ if (installTypes && *installTypes) {
+ std::vector<std::string> installTypesVector;
+ cmSystemTools::ExpandListArgument(installTypes, installTypesVector);
+ for (std::string const& installType : installTypesVector) {
+ project.InstallationTypes.push_back(
+ this->GetInstallationType(project.ProjectName, installType));
+ }
+ }
+
+ // Determine the set of components that will be used in this project
+ std::string componentsVar =
+ "CPACK_COMPONENTS_" + cmSystemTools::UpperCase(project.Component);
+ const char* components = this->GetOption(componentsVar);
+ if (components && *components) {
+ cmSystemTools::ExpandListArgument(components, componentsVector);
+ for (std::string const& comp : componentsVector) {
+ project.Components.push_back(
+ this->GetComponent(project.ProjectName, comp));
+ }
+ componentInstall = true;
+ }
+ }
+ if (componentsVector.empty()) {
+ componentsVector.push_back(project.Component);
+ }
+
+ const char* buildConfigCstr = this->GetOption("CPACK_BUILD_CONFIG");
+ std::string buildConfig = buildConfigCstr ? buildConfigCstr : "";
+ cmGlobalGenerator* globalGenerator =
+ this->MakefileMap->GetCMakeInstance()->CreateGlobalGenerator(
+ cmakeGenerator);
+ if (!globalGenerator) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Specified package generator not found. "
+ "CPACK_CMAKE_GENERATOR value is invalid."
+ << std::endl);
+ return 0;
+ }
+ // set the global flag for unix style paths on cmSystemTools as
+ // soon as the generator is set. This allows gmake to be used
+ // on windows.
+ cmSystemTools::SetForceUnixPaths(globalGenerator->GetForceUnixPaths());
+
+ if (!this->RunPreinstallTarget(project.ProjectName, project.Directory,
+ globalGenerator, buildConfig)) {
+ return 0;
+ }
+
+ delete globalGenerator;
+
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Install project: " << project.ProjectName << std::endl);
+
+ // Run the installation for each component
+ for (std::string const& component : componentsVector) {
+ if (!this->InstallCMakeProject(
+ setDestDir, project.Directory, baseTempInstallDirectory,
+ default_dir_mode, component, componentInstall,
+ project.SubDirectory, buildConfig, absoluteDestFiles)) {
+ return 0;
+ }
+ }
+
+ this->CMakeProjects.push_back(project);
+ }
+ }
+ this->SetOption("CPACK_ABSOLUTE_DESTINATION_FILES",
+ absoluteDestFiles.c_str());
+ return 1;
+}
+
+int cmCPackGenerator::RunPreinstallTarget(
+ const std::string& installProjectName, const std::string& installDirectory,
+ cmGlobalGenerator* globalGenerator, const std::string& buildConfig)
+{
+ // Does this generator require pre-install?
+ if (const char* preinstall = globalGenerator->GetPreinstallTargetName()) {
+ std::string buildCommand = globalGenerator->GenerateCMakeBuildCommand(
+ preinstall, buildConfig, "", false);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "- Install command: " << buildCommand << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Run preinstall target for: " << installProjectName
+ << std::endl);
+ std::string output;
+ int retVal = 1;
+ bool resB = cmSystemTools::RunSingleCommand(
+ buildCommand, &output, &output, &retVal, installDirectory.c_str(),
+ this->GeneratorVerbose, cmDuration::zero());
+ if (!resB || retVal) {
+ std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
+ tmpFile += "/PreinstallOutput.log";
+ cmGeneratedFileStream ofs(tmpFile);
+ ofs << "# Run command: " << buildCommand << std::endl
+ << "# Directory: " << installDirectory << std::endl
+ << "# Output:" << std::endl
+ << output << std::endl;
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running install command: "
+ << buildCommand << std::endl
+ << "Please check " << tmpFile << " for errors"
+ << std::endl);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int cmCPackGenerator::InstallCMakeProject(
+ bool setDestDir, const std::string& installDirectory,
+ const std::string& baseTempInstallDirectory, const mode_t* default_dir_mode,
+ const std::string& component, bool componentInstall,
+ const std::string& installSubDirectory, const std::string& buildConfig,
+ std::string& absoluteDestFiles)
+{
+ std::string tempInstallDirectory = baseTempInstallDirectory;
+ std::string installFile = installDirectory + "/cmake_install.cmake";
+
+ if (componentInstall) {
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Install component: " << component << std::endl);
+ }
+
+ cmake cm(cmake::RoleScript, cmState::CPack);
+ cm.SetHomeDirectory("");
+ cm.SetHomeOutputDirectory("");
+ cm.GetCurrentSnapshot().SetDefaultDefinitions();
+ cm.AddCMakePaths();
+ cm.SetProgressCallback([this](const std::string& msg, float prog) {
+ this->DisplayVerboseOutput(msg, prog);
+ });
+ cm.SetTrace(this->Trace);
+ cm.SetTraceExpand(this->TraceExpand);
+ cmGlobalGenerator gg(&cm);
+ cmMakefile mf(&gg, cm.GetCurrentSnapshot());
+ if (!installSubDirectory.empty() && installSubDirectory != "/" &&
+ installSubDirectory != ".") {
+ tempInstallDirectory += installSubDirectory;
+ }
+ if (componentInstall) {
+ tempInstallDirectory += "/";
+ // Some CPack generators would rather chose
+ // the local installation directory suffix.
+ // Some (e.g. RPM) use
+ // one install directory for each component **GROUP**
+ // instead of the default
+ // one install directory for each component.
+ tempInstallDirectory += GetComponentInstallDirNameSuffix(component);
+ if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) {
+ tempInstallDirectory += "/";
+ tempInstallDirectory += this->GetOption("CPACK_PACKAGE_FILE_NAME");
+ }
+ }
+
+ const char* default_dir_inst_permissions =
+ this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
+ if (default_dir_inst_permissions && *default_dir_inst_permissions) {
+ mf.AddDefinition("CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS",
+ default_dir_inst_permissions);
+ }
+
+ if (!setDestDir) {
+ tempInstallDirectory += this->GetPackagingInstallPrefix();
+ }
+
+ if (setDestDir) {
+ // For DESTDIR based packaging, use the *project*
+ // CMAKE_INSTALL_PREFIX underneath the tempInstallDirectory. The
+ // value of the project's CMAKE_INSTALL_PREFIX is sent in here as
+ // the value of the CPACK_INSTALL_PREFIX variable.
+ //
+ // If DESTDIR has been 'internally set ON' this means that
+ // the underlying CPack specific generator did ask for that
+ // In this case we may override CPACK_INSTALL_PREFIX with
+ // CPACK_PACKAGING_INSTALL_PREFIX
+ // I know this is tricky and awkward but it's the price for
+ // CPACK_SET_DESTDIR backward compatibility.
+ if (cmSystemTools::IsInternallyOn(this->GetOption("CPACK_SET_DESTDIR"))) {
+ this->SetOption("CPACK_INSTALL_PREFIX",
+ this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"));
+ }
+ std::string dir;
+ if (this->GetOption("CPACK_INSTALL_PREFIX")) {
+ dir += this->GetOption("CPACK_INSTALL_PREFIX");
+ }
+ mf.AddDefinition("CMAKE_INSTALL_PREFIX", dir.c_str());
+
+ cmCPackLogger(
+ cmCPackLog::LOG_DEBUG,
+ "- Using DESTDIR + CPACK_INSTALL_PREFIX... (mf.AddDefinition)"
+ << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "- Setting CMAKE_INSTALL_PREFIX to '" << dir << "'"
+ << std::endl);
+
+ // Make sure that DESTDIR + CPACK_INSTALL_PREFIX directory
+ // exists:
+ //
+ if (cmSystemTools::StringStartsWith(dir.c_str(), "/")) {
+ dir = tempInstallDirectory + dir;
+ } else {
+ dir = tempInstallDirectory + "/" + dir;
+ }
+ /*
+ * We must re-set DESTDIR for each component
+ * We must not add the CPACK_INSTALL_PREFIX part because
+ * it will be added using the override of CMAKE_INSTALL_PREFIX
+ * The main reason for this awkward trick is that
+ * are using DESTDIR for 2 different reasons:
+ * - Because it was asked by the CPack Generator or the user
+ * using CPACK_SET_DESTDIR
+ * - Because it was already used for component install
+ * in order to put things in subdirs...
+ */
+ cmSystemTools::PutEnv(std::string("DESTDIR=") + tempInstallDirectory);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "- Creating directory: '" << dir << "'" << std::endl);
+
+ if (!cmsys::SystemTools::MakeDirectory(dir, default_dir_mode)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem creating temporary directory: " << dir
+ << std::endl);
+ return 0;
+ }
+ } else {
+ mf.AddDefinition("CMAKE_INSTALL_PREFIX", tempInstallDirectory.c_str());
+
+ if (!cmsys::SystemTools::MakeDirectory(tempInstallDirectory,
+ default_dir_mode)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem creating temporary directory: "
+ << tempInstallDirectory << std::endl);
+ return 0;
+ }
+
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "- Using non-DESTDIR install... (mf.AddDefinition)"
+ << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "- Setting CMAKE_INSTALL_PREFIX to '" << tempInstallDirectory
+ << "'" << std::endl);
+ }
+
+ if (!buildConfig.empty()) {
+ mf.AddDefinition("BUILD_TYPE", buildConfig.c_str());
+ }
+ std::string installComponentLowerCase = cmSystemTools::LowerCase(component);
+ if (installComponentLowerCase != "all") {
+ mf.AddDefinition("CMAKE_INSTALL_COMPONENT", component.c_str());
+ }
+
+ // strip on TRUE, ON, 1, one or several file names, but not on
+ // FALSE, OFF, 0 and an empty string
+ if (!cmSystemTools::IsOff(this->GetOption("CPACK_STRIP_FILES"))) {
+ mf.AddDefinition("CMAKE_INSTALL_DO_STRIP", "1");
+ }
+ // Remember the list of files before installation
+ // of the current component (if we are in component install)
+ std::string const& InstallPrefix = tempInstallDirectory;
+ std::vector<std::string> filesBefore;
+ std::string findExpr = tempInstallDirectory;
+ if (componentInstall) {
+ cmsys::Glob glB;
+ findExpr += "/*";
+ glB.RecurseOn();
+ glB.SetRecurseListDirs(true);
+ glB.FindFiles(findExpr);
+ filesBefore = glB.GetFiles();
+ std::sort(filesBefore.begin(), filesBefore.end());
+ }
+
+ // If CPack was asked to warn on ABSOLUTE INSTALL DESTINATION
+ // then forward request to cmake_install.cmake script
+ if (this->IsOn("CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION")) {
+ mf.AddDefinition("CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION", "1");
+ }
+ // If current CPack generator does support
+ // ABSOLUTE INSTALL DESTINATION or CPack has been asked for
+ // then ask cmake_install.cmake script to error out
+ // as soon as it occurs (before installing file)
+ if (!SupportsAbsoluteDestination() ||
+ this->IsOn("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION")) {
+ mf.AddDefinition("CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION", "1");
+ }
+ // do installation
+ bool res = mf.ReadListFile(installFile);
+ // forward definition of CMAKE_ABSOLUTE_DESTINATION_FILES
+ // to CPack (may be used by generators like CPack RPM or DEB)
+ // in order to transparently handle ABSOLUTE PATH
+ if (mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")) {
+ mf.AddDefinition("CPACK_ABSOLUTE_DESTINATION_FILES",
+ mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES"));
+ }
+
+ // Now rebuild the list of files after installation
+ // of the current component (if we are in component install)
+ if (componentInstall) {
+ cmsys::Glob glA;
+ glA.RecurseOn();
+ glA.SetRecurseListDirs(true);
+ glA.SetRecurseThroughSymlinks(false);
+ glA.FindFiles(findExpr);
+ std::vector<std::string> filesAfter = glA.GetFiles();
+ std::sort(filesAfter.begin(), filesAfter.end());
+ std::vector<std::string>::iterator diff;
+ std::vector<std::string> result(filesAfter.size());
+ diff = std::set_difference(filesAfter.begin(), filesAfter.end(),
+ filesBefore.begin(), filesBefore.end(),
+ result.begin());
+
+ std::vector<std::string>::iterator fit;
+ std::string localFileName;
+ // Populate the File field of each component
+ for (fit = result.begin(); fit != diff; ++fit) {
+ localFileName = cmSystemTools::RelativePath(InstallPrefix, *fit);
+ localFileName =
+ localFileName.substr(localFileName.find_first_not_of('/'));
+ Components[component].Files.push_back(localFileName);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Adding file <" << localFileName << "> to component <"
+ << component << ">" << std::endl);
+ }
+ }
+
+ if (nullptr != mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")) {
+ if (!absoluteDestFiles.empty()) {
+ absoluteDestFiles += ";";
+ }
+ absoluteDestFiles += mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES");
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Got some ABSOLUTE DESTINATION FILES: " << absoluteDestFiles
+ << std::endl);
+ // define component specific var
+ if (componentInstall) {
+ std::string absoluteDestFileComponent =
+ std::string("CPACK_ABSOLUTE_DESTINATION_FILES") + "_" +
+ GetComponentInstallDirNameSuffix(component);
+ if (nullptr != this->GetOption(absoluteDestFileComponent)) {
+ std::string absoluteDestFilesListComponent =
+ this->GetOption(absoluteDestFileComponent);
+ absoluteDestFilesListComponent += ";";
+ absoluteDestFilesListComponent +=
+ mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES");
+ this->SetOption(absoluteDestFileComponent,
+ absoluteDestFilesListComponent.c_str());
+ } else {
+ this->SetOption(absoluteDestFileComponent,
+ mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"));
+ }
+ }
+ }
+ if (cmSystemTools::GetErrorOccuredFlag() || !res) {
+ return 0;
+ }
+ return 1;
+}
+
+bool cmCPackGenerator::ReadListFile(const char* moduleName)
+{
+ bool retval;
+ std::string fullPath = this->MakefileMap->GetModulesFile(moduleName);
+ retval = this->MakefileMap->ReadListFile(fullPath);
+ // include FATAL_ERROR and ERROR in the return status
+ retval = retval && (!cmSystemTools::GetErrorOccuredFlag());
+ return retval;
+}
+
+void cmCPackGenerator::SetOptionIfNotSet(const std::string& op,
+ const char* value)
+{
+ const char* def = this->MakefileMap->GetDefinition(op);
+ if (def && *def) {
+ return;
+ }
+ this->SetOption(op, value);
+}
+
+void cmCPackGenerator::SetOption(const std::string& op, const char* value)
+{
+ if (!value) {
+ this->MakefileMap->RemoveDefinition(op);
+ return;
+ }
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ this->GetNameOfClass() << "::SetOption(" << op << ", " << value
+ << ")" << std::endl);
+ this->MakefileMap->AddDefinition(op, value);
+}
+
+int cmCPackGenerator::DoPackage()
+{
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "Create package using " << this->Name << std::endl);
+
+ // Prepare CPack internal name and check
+ // values for many CPACK_xxx vars
+ if (!this->PrepareNames()) {
+ return 0;
+ }
+
+ // Digest Component grouping specification
+ if (!this->PrepareGroupingKind()) {
+ return 0;
+ }
+
+ if (cmSystemTools::IsOn(
+ this->GetOption("CPACK_REMOVE_TOPLEVEL_DIRECTORY"))) {
+ const char* toplevelDirectory =
+ this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
+ if (cmSystemTools::FileExists(toplevelDirectory)) {
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Remove toplevel directory: " << toplevelDirectory
+ << std::endl);
+ if (!cmSystemTools::RepeatedRemoveDirectory(toplevelDirectory)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem removing toplevel directory: "
+ << toplevelDirectory << std::endl);
+ return 0;
+ }
+ }
+ }
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "About to install project " << std::endl);
+
+ if (!this->InstallProject()) {
+ return 0;
+ }
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "Done install project " << std::endl);
+
+ const char* tempPackageFileName =
+ this->GetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME");
+ const char* tempDirectory = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
+
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl);
+ cmsys::Glob gl;
+ std::string findExpr = tempDirectory;
+ findExpr += "/*";
+ gl.RecurseOn();
+ gl.SetRecurseListDirs(true);
+ gl.SetRecurseThroughSymlinks(false);
+ if (!gl.FindFiles(findExpr)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find any files in the packaging tree" << std::endl);
+ return 0;
+ }
+
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Create package" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Package files to: "
+ << (tempPackageFileName ? tempPackageFileName : "(NULL)")
+ << std::endl);
+ if (cmSystemTools::FileExists(tempPackageFileName)) {
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Remove old package file" << std::endl);
+ cmSystemTools::RemoveFile(tempPackageFileName);
+ }
+ if (cmSystemTools::IsOn(
+ this->GetOption("CPACK_INCLUDE_TOPLEVEL_DIRECTORY"))) {
+ tempDirectory = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
+ }
+
+ // The files to be installed
+ files = gl.GetFiles();
+
+ packageFileNames.clear();
+ /* Put at least one file name into the list of
+ * wanted packageFileNames. The specific generator
+ * may update this during PackageFiles.
+ * (either putting several names or updating the provided one)
+ */
+ packageFileNames.emplace_back(tempPackageFileName ? tempPackageFileName
+ : "");
+ toplevel = tempDirectory;
+ { // scope that enables package generators to run internal scripts with
+ // latest CMake policies enabled
+ cmMakefile::ScopePushPop pp{ this->MakefileMap };
+ this->MakefileMap->SetPolicyVersion(cmVersion::GetCMakeVersion(),
+ std::string());
+
+ if (!this->PackageFiles() || cmSystemTools::GetErrorOccuredFlag()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem compressing the directory" << std::endl);
+ return 0;
+ }
+ }
+
+ /* Prepare checksum algorithm*/
+ const char* algo = this->GetOption("CPACK_PACKAGE_CHECKSUM");
+ std::unique_ptr<cmCryptoHash> crypto = cmCryptoHash::New(algo ? algo : "");
+
+ /*
+ * Copy the generated packages to final destination
+ * - there may be several of them
+ * - the initially provided name may have changed
+ * (because the specific generator did 'normalize' it)
+ */
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Copying final package(s) [" << packageFileNames.size()
+ << "]:" << std::endl);
+ /* now copy package one by one */
+ for (std::string const& pkgFileName : packageFileNames) {
+ std::string tmpPF(this->GetOption("CPACK_OUTPUT_FILE_PREFIX"));
+ std::string filename(cmSystemTools::GetFilenameName(pkgFileName));
+ tempPackageFileName = pkgFileName.c_str();
+ tmpPF += "/" + filename;
+ const char* packageFileName = tmpPF.c_str();
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Copy final package(s): "
+ << (tempPackageFileName ? tempPackageFileName : "(NULL)")
+ << " to " << (packageFileName ? packageFileName : "(NULL)")
+ << std::endl);
+ if (!cmSystemTools::CopyFileIfDifferent(pkgFileName, tmpPF)) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
+ "Problem copying the package: "
+ << (tempPackageFileName ? tempPackageFileName : "(NULL)") << " to "
+ << (packageFileName ? packageFileName : "(NULL)") << std::endl);
+ return 0;
+ }
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- package: " << packageFileName << " generated."
+ << std::endl);
+
+ /* Generate checksum file */
+ if (crypto) {
+ std::string hashFile(this->GetOption("CPACK_OUTPUT_FILE_PREFIX"));
+ hashFile += "/" + filename;
+ hashFile += "." + cmSystemTools::LowerCase(algo);
+ cmsys::ofstream outF(hashFile.c_str());
+ if (!outF) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot create checksum file: " << hashFile
+ << std::endl);
+ return 0;
+ }
+ outF << crypto->HashFile(packageFileName) << " " << filename << "\n";
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- checksum file: " << hashFile << " generated."
+ << std::endl);
+ }
+ }
+
+ return 1;
+}
+
+int cmCPackGenerator::Initialize(const std::string& name, cmMakefile* mf)
+{
+ this->MakefileMap = mf;
+ this->Name = name;
+ // set the running generator name
+ this->SetOption("CPACK_GENERATOR", this->Name.c_str());
+ // Load the project specific config file
+ const char* config = this->GetOption("CPACK_PROJECT_CONFIG_FILE");
+ if (config) {
+ mf->ReadListFile(config);
+ }
+ int result = this->InitializeInternal();
+ if (cmSystemTools::GetErrorOccuredFlag()) {
+ return 0;
+ }
+
+ // If a generator subclass did not already set this option in its
+ // InitializeInternal implementation, and the project did not already set
+ // it, the default value should be:
+ this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/");
+
+ return result;
+}
+
+int cmCPackGenerator::InitializeInternal()
+{
+ return 1;
+}
+
+bool cmCPackGenerator::IsSet(const std::string& name) const
+{
+ return this->MakefileMap->IsSet(name);
+}
+
+bool cmCPackGenerator::IsOn(const std::string& name) const
+{
+ return cmSystemTools::IsOn(GetOption(name));
+}
+
+bool cmCPackGenerator::IsSetToOff(const std::string& op) const
+{
+ const char* ret = this->MakefileMap->GetDefinition(op);
+ if (ret && *ret) {
+ return cmSystemTools::IsOff(ret);
+ }
+ return false;
+}
+
+bool cmCPackGenerator::IsSetToEmpty(const std::string& op) const
+{
+ const char* ret = this->MakefileMap->GetDefinition(op);
+ if (ret) {
+ return !*ret;
+ }
+ return false;
+}
+
+const char* cmCPackGenerator::GetOption(const std::string& op) const
+{
+ const char* ret = this->MakefileMap->GetDefinition(op);
+ if (!ret) {
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Warning, GetOption return NULL for: " << op << std::endl);
+ }
+ return ret;
+}
+
+std::vector<std::string> cmCPackGenerator::GetOptions() const
+{
+ return this->MakefileMap->GetDefinitions();
+}
+
+int cmCPackGenerator::PackageFiles()
+{
+ return 0;
+}
+
+const char* cmCPackGenerator::GetInstallPath()
+{
+ if (!this->InstallPath.empty()) {
+ return this->InstallPath.c_str();
+ }
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ std::string prgfiles;
+ std::string sysDrive;
+ if (cmsys::SystemTools::GetEnv("ProgramFiles", prgfiles)) {
+ this->InstallPath = prgfiles;
+ } else if (cmsys::SystemTools::GetEnv("SystemDrive", sysDrive)) {
+ this->InstallPath = sysDrive;
+ this->InstallPath += "/Program Files";
+ } else {
+ this->InstallPath = "c:/Program Files";
+ }
+ this->InstallPath += "/";
+ this->InstallPath += this->GetOption("CPACK_PACKAGE_NAME");
+ this->InstallPath += "-";
+ this->InstallPath += this->GetOption("CPACK_PACKAGE_VERSION");
+#elif defined(__HAIKU__)
+ char dir[B_PATH_NAME_LENGTH];
+ if (find_directory(B_SYSTEM_DIRECTORY, -1, false, dir, sizeof(dir)) ==
+ B_OK) {
+ this->InstallPath = dir;
+ } else {
+ this->InstallPath = "/boot/system";
+ }
+#else
+ this->InstallPath = "/usr/local/";
+#endif
+ return this->InstallPath.c_str();
+}
+
+const char* cmCPackGenerator::GetPackagingInstallPrefix()
+{
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "GetPackagingInstallPrefix: '"
+ << this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX") << "'"
+ << std::endl);
+
+ return this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
+}
+
+std::string cmCPackGenerator::FindTemplate(const char* name)
+{
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Look for template: " << (name ? name : "(NULL)")
+ << std::endl);
+ std::string ffile = this->MakefileMap->GetModulesFile(name);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Found template: " << ffile << std::endl);
+ return ffile;
+}
+
+bool cmCPackGenerator::ConfigureString(const std::string& inString,
+ std::string& outString)
+{
+ this->MakefileMap->ConfigureString(inString, outString, true, false);
+ return true;
+}
+
+bool cmCPackGenerator::ConfigureFile(const std::string& inName,
+ const std::string& outName,
+ bool copyOnly /* = false */)
+{
+ return this->MakefileMap->ConfigureFile(inName, outName, copyOnly, true,
+ false) == 1;
+}
+
+int cmCPackGenerator::CleanTemporaryDirectory()
+{
+ std::string tempInstallDirectory =
+ this->GetOption("CPACK_TEMPORARY_INSTALL_DIRECTORY");
+ if (cmsys::SystemTools::FileExists(tempInstallDirectory)) {
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Clean temporary : " << tempInstallDirectory << std::endl);
+ if (!cmSystemTools::RepeatedRemoveDirectory(tempInstallDirectory)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem removing temporary directory: "
+ << tempInstallDirectory << std::endl);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+cmInstalledFile const* cmCPackGenerator::GetInstalledFile(
+ std::string const& name) const
+{
+ cmake const* cm = this->MakefileMap->GetCMakeInstance();
+ return cm->GetInstalledFile(name);
+}
+
+int cmCPackGenerator::PrepareGroupingKind()
+{
+ // find a component package method specified by the user
+ ComponentPackageMethod method = UNKNOWN_COMPONENT_PACKAGE_METHOD;
+
+ if (this->GetOption("CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE")) {
+ method = ONE_PACKAGE;
+ }
+
+ if (this->GetOption("CPACK_COMPONENTS_IGNORE_GROUPS")) {
+ method = ONE_PACKAGE_PER_COMPONENT;
+ }
+
+ if (this->GetOption("CPACK_COMPONENTS_ONE_PACKAGE_PER_GROUP")) {
+ method = ONE_PACKAGE_PER_GROUP;
+ }
+
+ std::string groupingType;
+
+ // Second way to specify grouping
+ if (nullptr != this->GetOption("CPACK_COMPONENTS_GROUPING")) {
+ groupingType = this->GetOption("CPACK_COMPONENTS_GROUPING");
+ }
+
+ if (!groupingType.empty()) {
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "[" << this->Name << "]"
+ << " requested component grouping = " << groupingType
+ << std::endl);
+ if (groupingType == "ALL_COMPONENTS_IN_ONE") {
+ method = ONE_PACKAGE;
+ } else if (groupingType == "IGNORE") {
+ method = ONE_PACKAGE_PER_COMPONENT;
+ } else if (groupingType == "ONE_PER_GROUP") {
+ method = ONE_PACKAGE_PER_GROUP;
+ } else {
+ cmCPackLogger(
+ cmCPackLog::LOG_WARNING,
+ "[" << this->Name << "]"
+ << " requested component grouping type <" << groupingType
+ << "> UNKNOWN not in (ALL_COMPONENTS_IN_ONE,IGNORE,ONE_PER_GROUP)"
+ << std::endl);
+ }
+ }
+
+ // Some components were defined but NO group
+ // fallback to default if not group based
+ if (method == ONE_PACKAGE_PER_GROUP && this->ComponentGroups.empty() &&
+ !this->Components.empty()) {
+ if (componentPackageMethod == ONE_PACKAGE) {
+ method = ONE_PACKAGE;
+ } else {
+ method = ONE_PACKAGE_PER_COMPONENT;
+ }
+ cmCPackLogger(
+ cmCPackLog::LOG_WARNING,
+ "[" << this->Name << "]"
+ << " One package per component group requested, "
+ << "but NO component groups exist: Ignoring component group."
+ << std::endl);
+ }
+
+ // if user specified packaging method, override the default packaging method
+ if (method != UNKNOWN_COMPONENT_PACKAGE_METHOD) {
+ componentPackageMethod = method;
+ }
+
+ const char* method_names[] = { "ALL_COMPONENTS_IN_ONE", "IGNORE_GROUPS",
+ "ONE_PER_GROUP" };
+
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "[" << this->Name << "]"
+ << " requested component grouping = "
+ << method_names[componentPackageMethod] << std::endl);
+
+ return 1;
+}
+
+std::string cmCPackGenerator::GetComponentInstallDirNameSuffix(
+ const std::string& componentName)
+{
+ return componentName;
+}
+std::string cmCPackGenerator::GetComponentPackageFileName(
+ const std::string& initialPackageFileName,
+ const std::string& groupOrComponentName, bool isGroupName)
+{
+
+ /*
+ * the default behavior is to use the
+ * component [group] name as a suffix
+ */
+ std::string suffix = "-" + groupOrComponentName;
+ /* check if we should use DISPLAY name */
+ std::string dispNameVar = "CPACK_" + Name + "_USE_DISPLAY_NAME_IN_FILENAME";
+ if (IsOn(dispNameVar)) {
+ /* the component Group case */
+ if (isGroupName) {
+ std::string groupDispVar = "CPACK_COMPONENT_GROUP_" +
+ cmSystemTools::UpperCase(groupOrComponentName) + "_DISPLAY_NAME";
+ const char* groupDispName = GetOption(groupDispVar);
+ if (groupDispName) {
+ suffix = "-" + std::string(groupDispName);
+ }
+ }
+ /* the [single] component case */
+ else {
+ std::string dispVar = "CPACK_COMPONENT_" +
+ cmSystemTools::UpperCase(groupOrComponentName) + "_DISPLAY_NAME";
+ const char* dispName = GetOption(dispVar);
+ if (dispName) {
+ suffix = "-" + std::string(dispName);
+ }
+ }
+ }
+ return initialPackageFileName + suffix;
+}
+
+enum cmCPackGenerator::CPackSetDestdirSupport
+cmCPackGenerator::SupportsSetDestdir() const
+{
+ return cmCPackGenerator::SETDESTDIR_SUPPORTED;
+}
+
+bool cmCPackGenerator::SupportsAbsoluteDestination() const
+{
+ return true;
+}
+
+bool cmCPackGenerator::SupportsComponentInstallation() const
+{
+ return false;
+}
+
+bool cmCPackGenerator::WantsComponentInstallation() const
+{
+ return (!IsOn("CPACK_MONOLITHIC_INSTALL") &&
+ SupportsComponentInstallation()
+ // check that we have at least one group or component
+ && (!this->ComponentGroups.empty() || !this->Components.empty()));
+}
+
+cmCPackInstallationType* cmCPackGenerator::GetInstallationType(
+ const std::string& projectName, const std::string& name)
+{
+ (void)projectName;
+ bool hasInstallationType = this->InstallationTypes.count(name) != 0;
+ cmCPackInstallationType* installType = &this->InstallationTypes[name];
+ if (!hasInstallationType) {
+ // Define the installation type
+ std::string macroPrefix =
+ "CPACK_INSTALL_TYPE_" + cmsys::SystemTools::UpperCase(name);
+ installType->Name = name;
+
+ const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME");
+ if (displayName && *displayName) {
+ installType->DisplayName = displayName;
+ } else {
+ installType->DisplayName = installType->Name;
+ }
+
+ installType->Index = static_cast<unsigned>(this->InstallationTypes.size());
+ }
+ return installType;
+}
+
+cmCPackComponent* cmCPackGenerator::GetComponent(
+ const std::string& projectName, const std::string& name)
+{
+ bool hasComponent = this->Components.count(name) != 0;
+ cmCPackComponent* component = &this->Components[name];
+ if (!hasComponent) {
+ // Define the component
+ std::string macroPrefix =
+ "CPACK_COMPONENT_" + cmsys::SystemTools::UpperCase(name);
+ component->Name = name;
+ const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME");
+ if (displayName && *displayName) {
+ component->DisplayName = displayName;
+ } else {
+ component->DisplayName = component->Name;
+ }
+ component->IsHidden = this->IsOn(macroPrefix + "_HIDDEN");
+ component->IsRequired = this->IsOn(macroPrefix + "_REQUIRED");
+ component->IsDisabledByDefault = this->IsOn(macroPrefix + "_DISABLED");
+ component->IsDownloaded = this->IsOn(macroPrefix + "_DOWNLOADED") ||
+ cmSystemTools::IsOn(this->GetOption("CPACK_DOWNLOAD_ALL"));
+
+ const char* archiveFile = this->GetOption(macroPrefix + "_ARCHIVE_FILE");
+ if (archiveFile && *archiveFile) {
+ component->ArchiveFile = archiveFile;
+ }
+
+ const char* plist = this->GetOption(macroPrefix + "_PLIST");
+ if (plist && *plist) {
+ component->Plist = plist;
+ }
+
+ const char* groupName = this->GetOption(macroPrefix + "_GROUP");
+ if (groupName && *groupName) {
+ component->Group = GetComponentGroup(projectName, groupName);
+ component->Group->Components.push_back(component);
+ } else {
+ component->Group = nullptr;
+ }
+
+ const char* description = this->GetOption(macroPrefix + "_DESCRIPTION");
+ if (description && *description) {
+ component->Description = description;
+ }
+
+ // Determine the installation types.
+ const char* installTypes = this->GetOption(macroPrefix + "_INSTALL_TYPES");
+ if (installTypes && *installTypes) {
+ std::vector<std::string> installTypesVector;
+ cmSystemTools::ExpandListArgument(installTypes, installTypesVector);
+ for (std::string const& installType : installTypesVector) {
+ component->InstallationTypes.push_back(
+ this->GetInstallationType(projectName, installType));
+ }
+ }
+
+ // Determine the component dependencies.
+ const char* depends = this->GetOption(macroPrefix + "_DEPENDS");
+ if (depends && *depends) {
+ std::vector<std::string> dependsVector;
+ cmSystemTools::ExpandListArgument(depends, dependsVector);
+ for (std::string const& depend : dependsVector) {
+ cmCPackComponent* child = GetComponent(projectName, depend);
+ component->Dependencies.push_back(child);
+ child->ReverseDependencies.push_back(component);
+ }
+ }
+ }
+ return component;
+}
+
+cmCPackComponentGroup* cmCPackGenerator::GetComponentGroup(
+ const std::string& projectName, const std::string& name)
+{
+ (void)projectName;
+ std::string macroPrefix =
+ "CPACK_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(name);
+ bool hasGroup = this->ComponentGroups.count(name) != 0;
+ cmCPackComponentGroup* group = &this->ComponentGroups[name];
+ if (!hasGroup) {
+ // Define the group
+ group->Name = name;
+ const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME");
+ if (displayName && *displayName) {
+ group->DisplayName = displayName;
+ } else {
+ group->DisplayName = group->Name;
+ }
+
+ const char* description = this->GetOption(macroPrefix + "_DESCRIPTION");
+ if (description && *description) {
+ group->Description = description;
+ }
+ group->IsBold = this->IsOn(macroPrefix + "_BOLD_TITLE");
+ group->IsExpandedByDefault = this->IsOn(macroPrefix + "_EXPANDED");
+ const char* parentGroupName =
+ this->GetOption(macroPrefix + "_PARENT_GROUP");
+ if (parentGroupName && *parentGroupName) {
+ group->ParentGroup = GetComponentGroup(projectName, parentGroupName);
+ group->ParentGroup->Subgroups.push_back(group);
+ } else {
+ group->ParentGroup = nullptr;
+ }
+ }
+ return group;
+}