CMake/Source/CPack/cmCPackGenerator.cxx

1459 lines
55 KiB
C++
Raw Normal View History

Simplify CMake per-source license notices Per-source copyright/license notice headers that spell out copyright holder names and years are hard to maintain and often out-of-date or plain wrong. Precise contributor information is already maintained automatically by the version control tool. Ultimately it is the receiver of a file who is responsible for determining its licensing status, and per-source notices are merely a convenience. Therefore it is simpler and more accurate for each source to have a generic notice of the license name and references to more detailed information on copyright holders and full license terms. Our `Copyright.txt` file now contains a list of Contributors whose names appeared source-level copyright notices. It also references version control history for more precise information. Therefore we no longer need to spell out the list of Contributors in each source file notice. Replace CMake per-source copyright/license notice headers with a short description of the license and links to `Copyright.txt` and online information available from "https://cmake.org/licensing". The online URL also handles cases of modules being copied out of our source into other projects, so we can drop our notices about replacing links with full license text. Run the `Utilities/Scripts/filter-notices.bash` script to perform the majority of the replacements mechanically. Manually fix up shebang lines and trailing newlines in a few files. Manually update the notices in a few files that the script does not handle.
2016-09-27 22:01:08 +03:00
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
2007-11-06 00:55:45 +03:00
#include "cmCPackGenerator.h"
2006-01-02 07:21:05 +03:00
#include "cmCPackComponentGroup.h"
#include "cmCPackLog.h"
#include "cmCryptoHash.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
2016-09-07 01:21:35 +03:00
#include "cmState.h"
#include "cmXMLSafe.h"
2016-09-07 01:21:35 +03:00
#include "cm_auto_ptr.hxx"
#include "cmake.h"
2006-01-02 07:21:05 +03:00
#include <algorithm>
#include <cmsys/FStream.hxx>
#include <cmsys/Glob.hxx>
2016-09-07 01:21:35 +03:00
#include <cmsys/RegularExpression.hxx>
#include <list>
2016-09-07 01:21:35 +03:00
#include <utility>
2006-01-02 07:21:05 +03:00
#if defined(__HAIKU__)
#include <FindDirectory.h>
#include <StorageDefs.h>
#endif
2007-11-06 00:55:45 +03:00
cmCPackGenerator::cmCPackGenerator()
2006-01-02 07:21:05 +03:00
{
this->GeneratorVerbose = cmSystemTools::OUTPUT_NONE;
2016-06-27 23:44:16 +03:00
this->MakefileMap = CM_NULLPTR;
this->Logger = CM_NULLPTR;
this->componentPackageMethod = ONE_PACKAGE_PER_GROUP;
2006-01-02 07:21:05 +03:00
}
2007-11-06 00:55:45 +03:00
cmCPackGenerator::~cmCPackGenerator()
2006-01-02 07:21:05 +03:00
{
2016-06-27 23:44:16 +03:00
this->MakefileMap = CM_NULLPTR;
2006-01-02 07:21:05 +03:00
}
void cmCPackGeneratorProgress(const char* msg, float prog, void* ptr)
{
2007-11-06 00:55:45 +03:00
cmCPackGenerator* self = static_cast<cmCPackGenerator*>(ptr);
self->DisplayVerboseOutput(msg, prog);
}
void cmCPackGenerator::DisplayVerboseOutput(const char* msg, float progress)
{
2006-06-04 02:43:30 +04:00
(void)progress;
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "" << msg << std::endl);
}
2007-11-06 00:55:45 +03:00
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;
2016-08-18 20:47:32 +03:00
}
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");
2006-01-02 07:21:05 +03:00
tempDirectory += "/_CPack_Packages/";
const char* toplevelTag = this->GetOption("CPACK_TOPLEVEL_TAG");
if (toplevelTag) {
tempDirectory += toplevelTag;
tempDirectory += "/";
}
2006-01-02 07:21:05 +03:00
tempDirectory += this->GetOption("CPACK_GENERATOR");
std::string topDirectory = tempDirectory;
2008-03-07 19:06:44 +03:00
const char* pfname = this->GetOption("CPACK_PACKAGE_FILE_NAME");
if (!pfname) {
2008-03-07 19:06:44 +03:00
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);
2008-03-07 19:06:44 +03:00
return 0;
}
2006-01-02 07:21:05 +03:00
outName += this->GetOutputExtension();
2008-03-07 19:06:44 +03:00
const char* pdir = this->GetOption("CPACK_PACKAGE_DIRECTORY");
if (!pdir) {
2008-03-07 19:06:44 +03:00
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_PACKAGE_DIRECTORY not specified" << std::endl);
return 0;
}
2006-01-02 07:21:05 +03:00
2008-03-07 19:06:44 +03:00
std::string destFile = pdir;
this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_PREFIX", destFile.c_str());
2006-01-02 07:21:05 +03:00
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",
2006-05-12 22:44:24 +04:00
outFile.c_str());
this->SetOptionIfNotSet("CPACK_INSTALL_DIRECTORY", this->GetInstallPath());
this->SetOptionIfNotSet(
"CPACK_NATIVE_INSTALL_DIRECTORY",
2006-01-02 07:21:05 +03:00
cmsys::SystemTools::ConvertToOutputPath(this->GetInstallPath()).c_str());
this->SetOptionIfNotSet("CPACK_TEMPORARY_INSTALL_DIRECTORY",
tempDirectory.c_str());
2006-01-02 07:21:05 +03:00
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);
2006-01-02 07:21:05 +03:00
return 0;
}
cmsys::ifstream ifs(descFileName);
if (!ifs) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Cannot open description file name: " << descFileName
<< std::endl);
2006-01-02 07:21:05 +03:00
return 0;
}
std::ostringstream ostr;
2006-01-02 07:21:05 +03:00
std::string line;
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Read description file: " << descFileName << std::endl);
while (ifs && cmSystemTools::GetLineFromStream(ifs, line)) {
ostr << cmXMLSafe(line) << std::endl;
2006-01-02 07:21:05 +03:00
}
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);
2006-01-02 07:21:05 +03:00
return 0;
}
const char* algoSignature = this->GetOption("CPACK_PACKAGE_CHECKSUM");
if (algoSignature) {
if (cmCryptoHash::New(algoSignature).get() == CM_NULLPTR) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot recognize algorithm: "
<< algoSignature << std::endl);
return 0;
}
}
2006-01-02 07:21:05 +03:00
this->SetOptionIfNotSet("CPACK_REMOVE_TOPLEVEL_DIRECTORY", "1");
2006-01-02 07:21:05 +03:00
return 1;
}
2007-11-06 00:55:45 +03:00
int cmCPackGenerator::InstallProject()
2006-01-02 07:21:05 +03:00
{
cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Install projects" << std::endl);
2006-06-09 21:45:09 +04:00
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.c_str())) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem creating temporary directory: "
<< (tempInstallDirectory ? tempInstallDirectory : "(NULL)")
<< std::endl);
2006-01-02 07:21:05 +03:00
return 0;
}
if (setDestDir) {
2006-01-02 07:21:05 +03:00
std::string destDir = "DESTDIR=";
destDir += tempInstallDirectory;
2014-11-23 13:05:50 +03:00
cmSystemTools::PutEnv(destDir);
} else {
// Make sure there is no destdir
cmSystemTools::PutEnv("DESTDIR=");
}
2006-06-09 21:45:09 +04:00
// 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)) {
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)) {
return 0;
}
if (setDestDir) {
cmSystemTools::PutEnv("DESTDIR=");
}
return res;
}
2007-11-06 00:55:45 +03:00
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;
2014-11-23 13:05:50 +03:00
cmSystemTools::PutEnv(tempInstallDirectoryEnv);
std::vector<std::string> installCommandsVector;
cmSystemTools::ExpandListArgument(installCommands, installCommandsVector);
std::vector<std::string>::iterator it;
for (it = installCommandsVector.begin(); it != installCommandsVector.end();
++it) {
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << *it << std::endl);
std::string output;
int retVal = 1;
2016-06-27 23:44:16 +03:00
bool resB =
cmSystemTools::RunSingleCommand(it->c_str(), &output, &output, &retVal,
CM_NULLPTR, this->GeneratorVerbose, 0);
if (!resB || retVal) {
std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
tmpFile += "/InstallOutput.log";
cmGeneratedFileStream ofs(tmpFile.c_str());
ofs << "# Run command: " << *it << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
cmCPackLogger(
cmCPackLog::LOG_ERROR, "Problem running install command: "
<< *it << std::endl
<< "Please check " << tmpFile << " for errors" << std::endl);
return 0;
}
}
}
return 1;
}
2007-11-06 00:55:45 +03:00
int cmCPackGenerator::InstallProjectViaInstalledDirectories(
bool setDestDir, const std::string& tempInstallDirectory)
{
(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);
std::vector<std::string>::iterator it;
for (it = ignoreFilesRegexString.begin();
it != ignoreFilesRegexString.end(); ++it) {
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Create ignore files regex for: " << *it << std::endl);
ignoreFilesRegex.push_back(it->c_str());
}
}
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 "
2006-03-09 16:32:08 +03:00
"<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::list<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();
std::vector<std::string>::iterator gfit;
std::vector<cmsys::RegularExpression>::iterator regIt;
for (gfit = files.begin(); gfit != files.end(); ++gfit) {
bool skip = false;
std::string inFile = *gfit;
if (cmSystemTools::FileIsDirectory(*gfit)) {
inFile += '/';
}
for (regIt = ignoreFilesRegex.begin(); regIt != ignoreFilesRegex.end();
++regIt) {
if (regIt->find(inFile.c_str())) {
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Ignore file: " << inFile << std::endl);
skip = true;
}
}
if (skip) {
continue;
}
std::string filePath = tempDir;
filePath += "/" + subdir + "/" +
cmSystemTools::RelativePath(top.c_str(), gfit->c_str());
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.c_str(), inFile.c_str());
cmSystemTools::ReadSymlink(inFile, targetFile);
symlinkedFiles.push_back(
std::pair<std::string, std::string>(targetFile, inFileRelative));
}
/* If it is not a symlink then do a plain copy */
else if (!(cmSystemTools::CopyFileIfDifferent(inFile.c_str(),
filePath.c_str()) &&
cmSystemTools::CopyFileTime(inFile.c_str(),
filePath.c_str()))) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying file: "
<< inFile << " -> " << filePath << std::endl);
return 0;
}
}
/* rebuild symlinks in the installed tree */
if (!symlinkedFiles.empty()) {
std::list<std::pair<std::string, std::string> >::iterator symlinkedIt;
std::string curDir = cmSystemTools::GetCurrentWorkingDirectory();
std::string goToDir = tempDir;
goToDir += "/" + subdir;
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Change dir to: " << goToDir
<< std::endl);
cmSystemTools::ChangeDirectory(goToDir);
for (symlinkedIt = symlinkedFiles.begin();
symlinkedIt != symlinkedFiles.end(); ++symlinkedIt) {
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Will create a symlink: "
<< symlinkedIt->second << "--> "
<< symlinkedIt->first << std::endl);
// make sure directory exists for symlink
std::string destDir =
cmSystemTools::GetFilenamePath(symlinkedIt->second);
if (!destDir.empty() && !cmSystemTools::MakeDirectory(destDir)) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot create dir: "
<< destDir << "\nTrying to create symlink: "
<< symlinkedIt->second << "--> "
<< symlinkedIt->first << std::endl);
}
2014-11-23 13:05:50 +03:00
if (!cmSystemTools::CreateSymlink(symlinkedIt->first,
symlinkedIt->second)) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot create symlink: "
<< symlinkedIt->second << "--> "
<< symlinkedIt->first << std::endl);
return 0;
}
}
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Going back to: " << curDir
<< std::endl);
cmSystemTools::ChangeDirectory(curDir);
}
}
}
return 1;
}
2006-06-09 21:45:09 +04:00
2007-11-06 00:55:45 +03:00
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);
std::vector<std::string>::iterator it;
for (it = cmakeScriptsVector.begin(); it != cmakeScriptsVector.end();
++it) {
std::string installScript = *it;
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);
}
2006-10-15 15:54:52 +04:00
this->SetOptionIfNotSet("CMAKE_CURRENT_BINARY_DIR",
tempInstallDirectory.c_str());
2006-10-15 15:54:52 +04:00
this->SetOptionIfNotSet("CMAKE_CURRENT_SOURCE_DIR",
tempInstallDirectory.c_str());
int res = this->MakefileMap->ReadListFile(installScript.c_str());
if (cmSystemTools::GetErrorOccuredFlag() || !res) {
return 0;
}
}
}
return 1;
}
2007-11-06 00:55:45 +03:00
int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
bool setDestDir, const std::string& baseTempInstallDirectory)
{
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,
2006-05-12 22:44:24 +04:00
"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;
std::string installComponent = *it;
++it;
std::string installSubDirectory = *it;
std::string installFile = installDirectory + "/cmake_install.cmake";
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(installComponent) + "_INSTALL_TYPES";
const char* installTypes = this->GetOption(installTypesVar);
if (installTypes && *installTypes) {
std::vector<std::string> installTypesVector;
cmSystemTools::ExpandListArgument(installTypes, installTypesVector);
std::vector<std::string>::iterator installTypeIt;
for (installTypeIt = installTypesVector.begin();
installTypeIt != installTypesVector.end(); ++installTypeIt) {
this->GetInstallationType(installProjectName, *installTypeIt);
}
}
// Determine the set of components that will be used in this project
std::string componentsVar =
"CPACK_COMPONENTS_" + cmSystemTools::UpperCase(installComponent);
const char* components = this->GetOption(componentsVar);
if (components && *components) {
cmSystemTools::ExpandListArgument(components, componentsVector);
std::vector<std::string>::iterator compIt;
for (compIt = componentsVector.begin();
compIt != componentsVector.end(); ++compIt) {
GetComponent(installProjectName, *compIt);
}
componentInstall = true;
}
}
if (componentsVector.empty()) {
componentsVector.push_back(installComponent);
}
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
2006-05-03 23:17:09 +04:00
// soon as the generator is set. This allows gmake to be used
// on windows.
cmSystemTools::SetForceUnixPaths(globalGenerator->GetForceUnixPaths());
// 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.c_str(), &output, &output, &retVal,
installDirectory.c_str(), this->GeneratorVerbose, 0);
if (!resB || retVal) {
std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
tmpFile += "/PreinstallOutput.log";
cmGeneratedFileStream ofs(tmpFile.c_str());
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;
}
}
delete globalGenerator;
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
"- Install project: " << installProjectName << std::endl);
// Run the installation for each component
std::vector<std::string>::iterator componentIt;
for (componentIt = componentsVector.begin();
componentIt != componentsVector.end(); ++componentIt) {
std::string tempInstallDirectory = baseTempInstallDirectory;
installComponent = *componentIt;
if (componentInstall) {
cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Install component: "
<< installComponent << std::endl);
}
cmake cm;
cm.SetHomeDirectory("");
cm.SetHomeOutputDirectory("");
cm.GetCurrentSnapshot().SetDefaultDefinitions();
cm.AddCMakePaths();
cm.SetProgressCallback(cmCPackGeneratorProgress, this);
cmGlobalGenerator gg(&cm);
CM_AUTO_PTR<cmMakefile> mf(
new cmMakefile(&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(installComponent);
if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) {
tempInstallDirectory += "/";
tempInstallDirectory += this->GetOption("CPACK_PACKAGE_FILE_NAME");
}
}
if (!setDestDir) {
tempInstallDirectory += this->GetPackagingInstallPrefix();
}
if (setDestDir) {
2008-10-02 17:18:47 +04:00
// 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.
2010-09-16 00:41:41 +04:00
if (cmSystemTools::IsInternallyOn(
this->GetOption("CPACK_SET_DESTDIR"))) {
2010-09-16 00:41:41 +04:00
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.c_str())) {
cmCPackLogger(
cmCPackLog::LOG_ERROR,
"Problem creating temporary directory: " << dir << std::endl);
return 0;
}
} else {
2008-10-02 17:18:47 +04:00
mf->AddDefinition("CMAKE_INSTALL_PREFIX",
tempInstallDirectory.c_str());
if (!cmsys::SystemTools::MakeDirectory(
tempInstallDirectory.c_str())) {
ENH: Further refinement of the CPack components functionality from Doug Gregor. Details: ========== - New cpack_add_component, cpack_add_component_group, and cpack_add_install_type "commands" defined as macros in the CPack module. - Documentation for all of the variables and commands in the CPack module. - Added get_cmake_property(... COMPONENTS) to CMake to ask for the names of all components. Used in the CPack module to automatically build component-based installers. (Set CPACK_MONOLITHIC_INSTALL to turn off component-based installation). - A group can declare its PARENT_GROUP, to build an arbitrary hierarchy of groups. - New CPack command cpack_configure_downloads, which creates an installer that downloads only the selected components on-the-fly. Those components marked DOWNLOADED will be separate packages downloaded on-the-fly (or, all packages can be marked as such with the ALL option to cpack_configure_downloads). Individual components are compressed with ZIP at installer-creation time and downloaded/uncompressed by the installer as needed. This feature is only available on Windows with NSIS at the moment. - NSIS installers can install themselves and enable the "Change" button in Add/Remove programs, allowing users to go back and install or remove components. This can be disabled through cpack_configure_downloads, because it's only really useful is most of the application's functionality is in downloaded components. - Bug fix: automatically install everything whose COMPONENT was not specified (it's a hidden, required group) - Bug fix: fixed removal of components when re-running the NSIS installer and unchecking components - Bug fix: NSIS installers now only install/remove the minimal number of files when re-run to update the installation (or by clicking "Change" in Add/Remove programs)
2008-07-08 19:52:25 +04:00
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem creating temporary directory: "
<< tempInstallDirectory << std::endl);
ENH: Further refinement of the CPack components functionality from Doug Gregor. Details: ========== - New cpack_add_component, cpack_add_component_group, and cpack_add_install_type "commands" defined as macros in the CPack module. - Documentation for all of the variables and commands in the CPack module. - Added get_cmake_property(... COMPONENTS) to CMake to ask for the names of all components. Used in the CPack module to automatically build component-based installers. (Set CPACK_MONOLITHIC_INSTALL to turn off component-based installation). - A group can declare its PARENT_GROUP, to build an arbitrary hierarchy of groups. - New CPack command cpack_configure_downloads, which creates an installer that downloads only the selected components on-the-fly. Those components marked DOWNLOADED will be separate packages downloaded on-the-fly (or, all packages can be marked as such with the ALL option to cpack_configure_downloads). Individual components are compressed with ZIP at installer-creation time and downloaded/uncompressed by the installer as needed. This feature is only available on Windows with NSIS at the moment. - NSIS installers can install themselves and enable the "Change" button in Add/Remove programs, allowing users to go back and install or remove components. This can be disabled through cpack_configure_downloads, because it's only really useful is most of the application's functionality is in downloaded components. - Bug fix: automatically install everything whose COMPONENT was not specified (it's a hidden, required group) - Bug fix: fixed removal of components when re-running the NSIS installer and unchecking components - Bug fix: NSIS installers now only install/remove the minimal number of files when re-run to update the installation (or by clicking "Change" in Add/Remove programs)
2008-07-08 19:52:25 +04:00
return 0;
}
ENH: Further refinement of the CPack components functionality from Doug Gregor. Details: ========== - New cpack_add_component, cpack_add_component_group, and cpack_add_install_type "commands" defined as macros in the CPack module. - Documentation for all of the variables and commands in the CPack module. - Added get_cmake_property(... COMPONENTS) to CMake to ask for the names of all components. Used in the CPack module to automatically build component-based installers. (Set CPACK_MONOLITHIC_INSTALL to turn off component-based installation). - A group can declare its PARENT_GROUP, to build an arbitrary hierarchy of groups. - New CPack command cpack_configure_downloads, which creates an installer that downloads only the selected components on-the-fly. Those components marked DOWNLOADED will be separate packages downloaded on-the-fly (or, all packages can be marked as such with the ALL option to cpack_configure_downloads). Individual components are compressed with ZIP at installer-creation time and downloaded/uncompressed by the installer as needed. This feature is only available on Windows with NSIS at the moment. - NSIS installers can install themselves and enable the "Change" button in Add/Remove programs, allowing users to go back and install or remove components. This can be disabled through cpack_configure_downloads, because it's only really useful is most of the application's functionality is in downloaded components. - Bug fix: automatically install everything whose COMPONENT was not specified (it's a hidden, required group) - Bug fix: fixed removal of components when re-running the NSIS installer and unchecking components - Bug fix: NSIS installers now only install/remove the minimal number of files when re-run to update the installation (or by clicking "Change" in Add/Remove programs)
2008-07-08 19:52:25 +04:00
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(installComponent);
if (installComponentLowerCase != "all") {
mf->AddDefinition("CMAKE_INSTALL_COMPONENT",
installComponent.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)
const char* InstallPrefix = tempInstallDirectory.c_str();
std::vector<std::string> filesBefore;
std::string findExpr(InstallPrefix);
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
int res = mf->ReadListFile(installFile.c_str());
// 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.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->c_str());
localFileName = localFileName.substr(
localFileName.find_first_not_of('/'), std::string::npos);
Components[installComponent].Files.push_back(localFileName);
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Adding file <"
<< localFileName << "> to component <"
<< installComponent << ">" << std::endl);
}
}
2016-06-27 23:44:16 +03:00
if (CM_NULLPTR !=
mf->GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")) {
if (!absoluteDestFiles.empty()) {
absoluteDestFiles += ";";
}
2010-09-16 00:41:41 +04:00
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(installComponent);
2016-06-27 23:44:16 +03:00
if (CM_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;
}
}
}
}
2010-09-16 00:41:41 +04:00
this->SetOption("CPACK_ABSOLUTE_DESTINATION_FILES",
absoluteDestFiles.c_str());
return 1;
2006-01-02 07:21:05 +03:00
}
2007-11-06 00:55:45 +03:00
bool cmCPackGenerator::ReadListFile(const char* moduleName)
{
bool retval;
std::string fullPath = this->MakefileMap->GetModulesFile(moduleName);
retval = this->MakefileMap->ReadListFile(fullPath.c_str());
// 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)
2006-01-02 07:21:05 +03:00
{
if (!value) {
this->MakefileMap->RemoveDefinition(op);
2006-01-02 07:21:05 +03:00
return;
}
cmCPackLogger(cmCPackLog::LOG_DEBUG, this->GetNameOfClass()
<< "::SetOption(" << op << ", " << value << ")"
<< std::endl);
this->MakefileMap->AddDefinition(op, value);
2006-01-02 07:21:05 +03:00
}
int cmCPackGenerator::DoPackage()
2006-01-02 07:21:05 +03:00
{
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()) {
2006-01-02 07:21:05 +03:00
return 0;
}
2008-03-07 19:06:44 +03:00
// 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);
2008-03-07 19:06:44 +03:00
if (!this->InstallProject()) {
2006-01-02 07:21:05 +03:00
return 0;
}
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Done install project " << std::endl);
2006-01-02 07:21:05 +03:00
const char* tempPackageFileName =
this->GetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME");
2006-01-02 07:21:05 +03:00
const char* tempDirectory = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
2006-01-03 00:14:21 +03:00
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl);
2006-01-02 07:21:05 +03:00
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);
2006-01-02 07:21:05 +03:00
return 0;
}
2006-01-02 07:21:05 +03:00
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.push_back(tempPackageFileName ? tempPackageFileName : "");
toplevel = tempDirectory;
if (!this->PackageFiles() || cmSystemTools::GetErrorOccuredFlag()) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem compressing the directory"
<< std::endl);
2006-01-02 07:21:05 +03:00
return 0;
}
2006-01-02 07:21:05 +03:00
/* Prepare checksum algorithm*/
const char* algo = this->GetOption("CPACK_PACKAGE_CHECKSUM");
CM_AUTO_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);
std::vector<std::string>::iterator it;
/* now copy package one by one */
for (it = packageFileNames.begin(); it != packageFileNames.end(); ++it) {
std::string tmpPF(this->GetOption("CPACK_OUTPUT_FILE_PREFIX"));
std::string filename(cmSystemTools::GetFilenameName(*it));
tempPackageFileName = it->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(tempPackageFileName,
packageFileName)) {
cmCPackLogger(
cmCPackLog::LOG_ERROR, "Problem copying the package: "
<< (tempPackageFileName ? tempPackageFileName : "(NULL)") << " to "
<< (packageFileName ? packageFileName : "(NULL)") << std::endl);
return 0;
2006-01-02 07:21:05 +03:00
}
cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- package: "
<< packageFileName << " generated." << std::endl);
/* Generate checksum file */
if (crypto.get() != CM_NULLPTR) {
std::string hashFile(this->GetOption("CPACK_OUTPUT_FILE_PREFIX"));
hashFile +=
"/" + filename.substr(0, filename.rfind(this->GetOutputExtension()));
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);
}
}
2006-01-02 07:21:05 +03:00
return 1;
}
int cmCPackGenerator::Initialize(const std::string& name, cmMakefile* mf)
2006-01-02 07:21:05 +03:00
{
this->MakefileMap = mf;
2006-03-10 21:06:26 +03:00
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;
}
2007-11-06 00:55:45 +03:00
int cmCPackGenerator::InitializeInternal()
{
2006-01-02 07:21:05 +03:00
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));
}
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;
2006-01-02 07:21:05 +03:00
}
std::vector<std::string> cmCPackGenerator::GetOptions() const
{
return this->MakefileMap->GetDefinitions();
}
int cmCPackGenerator::PackageFiles()
2006-01-02 07:21:05 +03:00
{
return 0;
}
2007-11-06 00:55:45 +03:00
const char* cmCPackGenerator::GetInstallPath()
2006-01-02 07:21:05 +03:00
{
if (!this->InstallPath.empty()) {
2006-03-10 21:06:26 +03:00
return this->InstallPath.c_str();
}
2006-01-02 07:21:05 +03:00
#if defined(_WIN32) && !defined(__CYGWIN__)
std::string prgfiles;
std::string sysDrive;
if (cmsys::SystemTools::GetEnv("ProgramFiles", prgfiles)) {
2006-03-10 21:06:26 +03:00
this->InstallPath = prgfiles;
} else if (cmsys::SystemTools::GetEnv("SystemDrive", sysDrive)) {
2006-03-10 21:06:26 +03:00
this->InstallPath = sysDrive;
this->InstallPath += "/Program Files";
} else {
2006-03-10 21:06:26 +03:00
this->InstallPath = "c:/Program Files";
}
2006-03-10 21:06:26 +03:00
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";
}
2006-01-02 07:21:05 +03:00
#else
2006-03-10 21:06:26 +03:00
this->InstallPath = "/usr/local/";
2006-01-02 07:21:05 +03:00
#endif
2006-03-10 21:06:26 +03:00
return this->InstallPath.c_str();
2006-01-02 07:21:05 +03:00
}
2007-11-06 00:55:45 +03:00
const char* cmCPackGenerator::GetPackagingInstallPrefix()
{
cmCPackLogger(cmCPackLog::LOG_DEBUG, "GetPackagingInstallPrefix: '"
<< this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX") << "'"
<< std::endl);
return this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
}
2007-11-06 00:55:45 +03:00
std::string cmCPackGenerator::FindTemplate(const char* name)
2006-01-02 07:21:05 +03:00
{
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;
2006-01-02 07:21:05 +03:00
}
2007-11-06 00:55:45 +03:00
bool cmCPackGenerator::ConfigureString(const std::string& inString,
std::string& outString)
{
this->MakefileMap->ConfigureString(inString, outString, true, false);
return true;
}
bool cmCPackGenerator::ConfigureFile(const char* inName, const char* outName,
bool copyOnly /* = false */)
2006-01-02 07:21:05 +03:00
{
return this->MakefileMap->ConfigureFile(inName, outName, copyOnly, true,
false) == 1;
2006-01-02 07:21:05 +03:00
}
2006-06-09 21:45:09 +04:00
2007-11-06 00:55:45 +03:00
int cmCPackGenerator::CleanTemporaryDirectory()
2006-06-09 21:45:09 +04:00
{
std::string tempInstallDirectoryWithPostfix =
this->GetOption("CPACK_TEMPORARY_INSTALL_DIRECTORY");
const char* tempInstallDirectory = tempInstallDirectoryWithPostfix.c_str();
if (cmsys::SystemTools::FileExists(tempInstallDirectory)) {
2006-06-09 21:45:09 +04:00
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
"- Clean temporary : " << tempInstallDirectory << std::endl);
if (!cmSystemTools::RepeatedRemoveDirectory(tempInstallDirectory)) {
2006-06-09 21:45:09 +04:00
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem removing temporary directory: "
<< tempInstallDirectory << std::endl);
2006-06-09 21:45:09 +04:00
return 0;
}
}
2006-06-09 21:45:09 +04:00
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
2016-06-27 23:44:16 +03:00
if (CM_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, "["
2011-04-01 21:21:51 +04:00
<< this->Name << "]"
<< " requested component grouping type <" << groupingType
2011-04-01 21:21:51 +04:00
<< "> 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) {
ENH: Further refinement of the CPack components functionality from Doug Gregor. Details: ========== - New cpack_add_component, cpack_add_component_group, and cpack_add_install_type "commands" defined as macros in the CPack module. - Documentation for all of the variables and commands in the CPack module. - Added get_cmake_property(... COMPONENTS) to CMake to ask for the names of all components. Used in the CPack module to automatically build component-based installers. (Set CPACK_MONOLITHIC_INSTALL to turn off component-based installation). - A group can declare its PARENT_GROUP, to build an arbitrary hierarchy of groups. - New CPack command cpack_configure_downloads, which creates an installer that downloads only the selected components on-the-fly. Those components marked DOWNLOADED will be separate packages downloaded on-the-fly (or, all packages can be marked as such with the ALL option to cpack_configure_downloads). Individual components are compressed with ZIP at installer-creation time and downloaded/uncompressed by the installer as needed. This feature is only available on Windows with NSIS at the moment. - NSIS installers can install themselves and enable the "Change" button in Add/Remove programs, allowing users to go back and install or remove components. This can be disabled through cpack_configure_downloads, because it's only really useful is most of the application's functionality is in downloaded components. - Bug fix: automatically install everything whose COMPONENT was not specified (it's a hidden, required group) - Bug fix: fixed removal of components when re-running the NSIS installer and unchecking components - Bug fix: NSIS installers now only install/remove the minimal number of files when re-run to update the installation (or by clicking "Change" in Add/Remove programs)
2008-07-08 19:52:25 +04:00
component->ArchiveFile = archiveFile;
}
ENH: Further refinement of the CPack components functionality from Doug Gregor. Details: ========== - New cpack_add_component, cpack_add_component_group, and cpack_add_install_type "commands" defined as macros in the CPack module. - Documentation for all of the variables and commands in the CPack module. - Added get_cmake_property(... COMPONENTS) to CMake to ask for the names of all components. Used in the CPack module to automatically build component-based installers. (Set CPACK_MONOLITHIC_INSTALL to turn off component-based installation). - A group can declare its PARENT_GROUP, to build an arbitrary hierarchy of groups. - New CPack command cpack_configure_downloads, which creates an installer that downloads only the selected components on-the-fly. Those components marked DOWNLOADED will be separate packages downloaded on-the-fly (or, all packages can be marked as such with the ALL option to cpack_configure_downloads). Individual components are compressed with ZIP at installer-creation time and downloaded/uncompressed by the installer as needed. This feature is only available on Windows with NSIS at the moment. - NSIS installers can install themselves and enable the "Change" button in Add/Remove programs, allowing users to go back and install or remove components. This can be disabled through cpack_configure_downloads, because it's only really useful is most of the application's functionality is in downloaded components. - Bug fix: automatically install everything whose COMPONENT was not specified (it's a hidden, required group) - Bug fix: fixed removal of components when re-running the NSIS installer and unchecking components - Bug fix: NSIS installers now only install/remove the minimal number of files when re-run to update the installation (or by clicking "Change" in Add/Remove programs)
2008-07-08 19:52:25 +04:00
const char* groupName = this->GetOption(macroPrefix + "_GROUP");
if (groupName && *groupName) {
component->Group = GetComponentGroup(projectName, groupName);
component->Group->Components.push_back(component);
} else {
2016-06-27 23:44:16 +03:00
component->Group = CM_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);
std::vector<std::string>::iterator installTypesIt;
for (installTypesIt = installTypesVector.begin();
installTypesIt != installTypesVector.end(); ++installTypesIt) {
component->InstallationTypes.push_back(
this->GetInstallationType(projectName, *installTypesIt));
}
}
// Determine the component dependencies.
const char* depends = this->GetOption(macroPrefix + "_DEPENDS");
if (depends && *depends) {
std::vector<std::string> dependsVector;
cmSystemTools::ExpandListArgument(depends, dependsVector);
std::vector<std::string>::iterator dependIt;
for (dependIt = dependsVector.begin(); dependIt != dependsVector.end();
++dependIt) {
cmCPackComponent* child = GetComponent(projectName, *dependIt);
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) {
ENH: Further refinement of the CPack components functionality from Doug Gregor. Details: ========== - New cpack_add_component, cpack_add_component_group, and cpack_add_install_type "commands" defined as macros in the CPack module. - Documentation for all of the variables and commands in the CPack module. - Added get_cmake_property(... COMPONENTS) to CMake to ask for the names of all components. Used in the CPack module to automatically build component-based installers. (Set CPACK_MONOLITHIC_INSTALL to turn off component-based installation). - A group can declare its PARENT_GROUP, to build an arbitrary hierarchy of groups. - New CPack command cpack_configure_downloads, which creates an installer that downloads only the selected components on-the-fly. Those components marked DOWNLOADED will be separate packages downloaded on-the-fly (or, all packages can be marked as such with the ALL option to cpack_configure_downloads). Individual components are compressed with ZIP at installer-creation time and downloaded/uncompressed by the installer as needed. This feature is only available on Windows with NSIS at the moment. - NSIS installers can install themselves and enable the "Change" button in Add/Remove programs, allowing users to go back and install or remove components. This can be disabled through cpack_configure_downloads, because it's only really useful is most of the application's functionality is in downloaded components. - Bug fix: automatically install everything whose COMPONENT was not specified (it's a hidden, required group) - Bug fix: fixed removal of components when re-running the NSIS installer and unchecking components - Bug fix: NSIS installers now only install/remove the minimal number of files when re-run to update the installation (or by clicking "Change" in Add/Remove programs)
2008-07-08 19:52:25 +04:00
group->ParentGroup = GetComponentGroup(projectName, parentGroupName);
group->ParentGroup->Subgroups.push_back(group);
} else {
2016-06-27 23:44:16 +03:00
group->ParentGroup = CM_NULLPTR;
}
}
return group;
}