Merge topic 'cpack-external'

4c71548766 Help: Add release notes for CPack External generator
47c87cdd1f Help: Add documentation for CPack External generator
2ef966bc77 Testing: Add test for CPack External generator
80914d88da CPack: Add "CPack External" generator
3ced881db6 cmCPackGenerator: Store CPACK_INSTALL_CMAKE_PROJECTS in an internal field
4938abb600 cmCPackGenerator: Refactor InstallProjectViaInstallCMakeProjects()

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !2142
This commit is contained in:
Brad King
2018-07-03 14:54:57 +00:00
committed by Kitware Robot
23 changed files with 1369 additions and 291 deletions
+2 -1
View File
@@ -886,6 +886,8 @@ include_directories(
set(CPACK_SRCS
CPack/cmCPackArchiveGenerator.cxx
CPack/cmCPackComponentGroup.cxx
CPack/cmCPackDebGenerator.cxx
CPack/cmCPackExtGenerator.cxx
CPack/cmCPackGeneratorFactory.cxx
CPack/cmCPackGenerator.cxx
CPack/cmCPackLog.cxx
@@ -898,7 +900,6 @@ set(CPACK_SRCS
CPack/cmCPackTarCompressGenerator.cxx
CPack/cmCPackZIPGenerator.cxx
CPack/cmCPack7zGenerator.cxx
CPack/cmCPackDebGenerator.cxx
)
# CPack IFW generator
set(CPACK_SRCS ${CPACK_SRCS}
+25
View File
@@ -143,4 +143,29 @@ public:
std::vector<cmCPackComponentGroup*> Subgroups;
};
/** \class cmCPackInstallCMakeProject
* \brief A single quadruplet from the CPACK_INSTALL_CMAKE_PROJECTS variable.
*/
class cmCPackInstallCMakeProject
{
public:
/// The directory of the CMake project.
std::string Directory;
/// The name of the CMake project.
std::string ProjectName;
/// The name of the component (or component set) to install.
std::string Component;
/// The subdirectory to install into.
std::string SubDirectory;
/// The list of installation types.
std::vector<cmCPackInstallationType*> InstallationTypes;
/// The list of components.
std::vector<cmCPackComponent*> Components;
};
#endif
+291
View File
@@ -0,0 +1,291 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackExtGenerator.h"
#include "cmAlgorithms.h"
#include "cmCPackComponentGroup.h"
#include "cmCPackLog.h"
#include "cmSystemTools.h"
#include "cm_jsoncpp_value.h"
#include "cm_jsoncpp_writer.h"
#include "cmsys/FStream.hxx"
#include <utility>
#include <vector>
int cmCPackExtGenerator::InitializeInternal()
{
this->SetOption("CPACK_EXT_KNOWN_VERSIONS", "1.0");
if (!this->ReadListFile("Internal/CPack/CPackExt.cmake")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error while executing CPackExt.cmake" << std::endl);
return 0;
}
std::string major = this->GetOption("CPACK_EXT_SELECTED_MAJOR");
if (major == "1") {
this->Generator = cm::make_unique<cmCPackExtVersion1Generator>(this);
}
return this->Superclass::InitializeInternal();
}
int cmCPackExtGenerator::PackageFiles()
{
Json::StreamWriterBuilder builder;
builder["indentation"] = " ";
std::string filename = "package.json";
if (!this->packageFileNames.empty()) {
filename = this->packageFileNames[0];
}
cmsys::ofstream fout(filename.c_str());
std::unique_ptr<Json::StreamWriter> jout(builder.newStreamWriter());
Json::Value root(Json::objectValue);
if (!this->Generator->WriteToJSON(root)) {
return 0;
}
if (jout->write(root, &fout)) {
return 0;
}
return 1;
}
bool cmCPackExtGenerator::SupportsComponentInstallation() const
{
return true;
}
int cmCPackExtGenerator::InstallProjectViaInstallCommands(
bool setDestDir, const std::string& tempInstallDirectory)
{
(void)setDestDir;
(void)tempInstallDirectory;
return 1;
}
int cmCPackExtGenerator::InstallProjectViaInstallScript(
bool setDestDir, const std::string& tempInstallDirectory)
{
(void)setDestDir;
(void)tempInstallDirectory;
return 1;
}
int cmCPackExtGenerator::InstallProjectViaInstalledDirectories(
bool setDestDir, const std::string& tempInstallDirectory,
const mode_t* default_dir_mode)
{
(void)setDestDir;
(void)tempInstallDirectory;
(void)default_dir_mode;
return 1;
}
int cmCPackExtGenerator::RunPreinstallTarget(
const std::string& installProjectName, const std::string& installDirectory,
cmGlobalGenerator* globalGenerator, const std::string& buildConfig)
{
(void)installProjectName;
(void)installDirectory;
(void)globalGenerator;
(void)buildConfig;
return 1;
}
int cmCPackExtGenerator::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)
{
(void)setDestDir;
(void)installDirectory;
(void)baseTempInstallDirectory;
(void)default_dir_mode;
(void)component;
(void)componentInstall;
(void)installSubDirectory;
(void)buildConfig;
(void)absoluteDestFiles;
return 1;
}
cmCPackExtGenerator::cmCPackExtVersionGenerator::cmCPackExtVersionGenerator(
cmCPackExtGenerator* parent)
: Parent(parent)
{
}
int cmCPackExtGenerator::cmCPackExtVersionGenerator::WriteVersion(
Json::Value& root)
{
root["formatVersionMajor"] = this->GetVersionMajor();
root["formatVersionMinor"] = this->GetVersionMinor();
return 1;
}
int cmCPackExtGenerator::cmCPackExtVersionGenerator::WriteToJSON(
Json::Value& root)
{
if (!this->WriteVersion(root)) {
return 0;
}
const char* packageName = this->Parent->GetOption("CPACK_PACKAGE_NAME");
if (packageName) {
root["packageName"] = packageName;
}
const char* packageVersion =
this->Parent->GetOption("CPACK_PACKAGE_VERSION");
if (packageVersion) {
root["packageVersion"] = packageVersion;
}
const char* packageDescriptionFile =
this->Parent->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE");
if (packageDescriptionFile) {
root["packageDescriptionFile"] = packageDescriptionFile;
}
const char* packageDescriptionSummary =
this->Parent->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY");
if (packageDescriptionSummary) {
root["packageDescriptionSummary"] = packageDescriptionSummary;
}
const char* buildConfigCstr = this->Parent->GetOption("CPACK_BUILD_CONFIG");
if (buildConfigCstr) {
root["buildConfig"] = buildConfigCstr;
}
const char* defaultDirectoryPermissions =
this->Parent->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
if (defaultDirectoryPermissions && *defaultDirectoryPermissions) {
root["defaultDirectoryPermissions"] = defaultDirectoryPermissions;
}
if (cmSystemTools::IsInternallyOn(
this->Parent->GetOption("CPACK_SET_DESTDIR"))) {
root["setDestdir"] = true;
root["packagingInstallPrefix"] =
this->Parent->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
} else {
root["setDestdir"] = false;
}
root["stripFiles"] =
!cmSystemTools::IsOff(this->Parent->GetOption("CPACK_STRIP_FILES"));
root["warnOnAbsoluteInstallDestination"] =
this->Parent->IsOn("CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION");
root["errorOnAbsoluteInstallDestination"] =
this->Parent->IsOn("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION");
Json::Value& projects = root["projects"] = Json::Value(Json::arrayValue);
for (auto& project : this->Parent->CMakeProjects) {
Json::Value jsonProject(Json::objectValue);
jsonProject["projectName"] = project.ProjectName;
jsonProject["component"] = project.Component;
jsonProject["directory"] = project.Directory;
jsonProject["subDirectory"] = project.SubDirectory;
Json::Value& installationTypes = jsonProject["installationTypes"] =
Json::Value(Json::arrayValue);
for (auto& installationType : project.InstallationTypes) {
installationTypes.append(installationType->Name);
}
Json::Value& components = jsonProject["components"] =
Json::Value(Json::arrayValue);
for (auto& component : project.Components) {
components.append(component->Name);
}
projects.append(jsonProject);
}
Json::Value& installationTypes = root["installationTypes"] =
Json::Value(Json::objectValue);
for (auto& installationType : this->Parent->InstallationTypes) {
Json::Value& jsonInstallationType =
installationTypes[installationType.first] =
Json::Value(Json::objectValue);
jsonInstallationType["name"] = installationType.second.Name;
jsonInstallationType["displayName"] = installationType.second.DisplayName;
jsonInstallationType["index"] = installationType.second.Index;
}
Json::Value& components = root["components"] =
Json::Value(Json::objectValue);
for (auto& component : this->Parent->Components) {
Json::Value& jsonComponent = components[component.first] =
Json::Value(Json::objectValue);
jsonComponent["name"] = component.second.Name;
jsonComponent["displayName"] = component.second.DisplayName;
if (component.second.Group) {
jsonComponent["group"] = component.second.Group->Name;
}
jsonComponent["isRequired"] = component.second.IsRequired;
jsonComponent["isHidden"] = component.second.IsHidden;
jsonComponent["isDisabledByDefault"] =
component.second.IsDisabledByDefault;
jsonComponent["isDownloaded"] = component.second.IsDownloaded;
jsonComponent["description"] = component.second.Description;
jsonComponent["archiveFile"] = component.second.ArchiveFile;
Json::Value& cmpInstallationTypes = jsonComponent["installationTypes"] =
Json::Value(Json::arrayValue);
for (auto& installationType : component.second.InstallationTypes) {
cmpInstallationTypes.append(installationType->Name);
}
Json::Value& dependencies = jsonComponent["dependencies"] =
Json::Value(Json::arrayValue);
for (auto& dep : component.second.Dependencies) {
dependencies.append(dep->Name);
}
}
Json::Value& groups = root["componentGroups"] =
Json::Value(Json::objectValue);
for (auto& group : this->Parent->ComponentGroups) {
Json::Value& jsonGroup = groups[group.first] =
Json::Value(Json::objectValue);
jsonGroup["name"] = group.second.Name;
jsonGroup["displayName"] = group.second.DisplayName;
jsonGroup["description"] = group.second.Description;
jsonGroup["isBold"] = group.second.IsBold;
jsonGroup["isExpandedByDefault"] = group.second.IsExpandedByDefault;
if (group.second.ParentGroup) {
jsonGroup["parentGroup"] = group.second.ParentGroup->Name;
}
Json::Value& subgroups = jsonGroup["subgroups"] =
Json::Value(Json::arrayValue);
for (auto& subgroup : group.second.Subgroups) {
subgroups.append(subgroup->Name);
}
Json::Value& groupComponents = jsonGroup["components"] =
Json::Value(Json::arrayValue);
for (auto& component : group.second.Components) {
groupComponents.append(component->Name);
}
}
return 1;
}
+86
View File
@@ -0,0 +1,86 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmCPackExtGenerator_h
#define cmCPackExtGenerator_h
#include "cmCPackGenerator.h"
#include "cm_sys_stat.h"
#include <memory>
#include <string>
class cmGlobalGenerator;
namespace Json {
class Value;
}
/** \class cmCPackExtGenerator
* \brief A generator for CPack External packaging tools
*/
class cmCPackExtGenerator : public cmCPackGenerator
{
public:
cmCPackTypeMacro(cmCPackExtGenerator, cmCPackGenerator);
const char* GetOutputExtension() override { return ".json"; }
protected:
int InitializeInternal() override;
int PackageFiles() override;
bool SupportsComponentInstallation() const override;
int InstallProjectViaInstallCommands(
bool setDestDir, const std::string& tempInstallDirectory) override;
int InstallProjectViaInstallScript(
bool setDestDir, const std::string& tempInstallDirectory) override;
int InstallProjectViaInstalledDirectories(
bool setDestDir, const std::string& tempInstallDirectory,
const mode_t* default_dir_mode) override;
int RunPreinstallTarget(const std::string& installProjectName,
const std::string& installDirectory,
cmGlobalGenerator* globalGenerator,
const std::string& buildConfig) override;
int 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) override;
private:
class cmCPackExtVersionGenerator
{
public:
cmCPackExtVersionGenerator(cmCPackExtGenerator* parent);
virtual ~cmCPackExtVersionGenerator() = default;
virtual int WriteToJSON(Json::Value& root);
protected:
virtual int GetVersionMajor() = 0;
virtual int GetVersionMinor() = 0;
int WriteVersion(Json::Value& root);
cmCPackExtGenerator* Parent;
};
class cmCPackExtVersion1Generator : public cmCPackExtVersionGenerator
{
public:
using cmCPackExtVersionGenerator::cmCPackExtVersionGenerator;
protected:
int GetVersionMajor() override { return 1; }
int GetVersionMinor() override { return 0; }
};
std::unique_ptr<cmCPackExtVersionGenerator> Generator;
};
#endif
+310 -286
View File
@@ -545,10 +545,13 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
++it;
std::string installProjectName = *it;
++it;
std::string installComponent = *it;
cmCPackInstallCMakeProject project;
project.Directory = installDirectory;
project.ProjectName = installProjectName;
project.Component = *it;
++it;
std::string installSubDirectory = *it;
std::string installFile = installDirectory + "/cmake_install.cmake";
project.SubDirectory = *it;
std::vector<std::string> componentsVector;
@@ -559,34 +562,36 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
* - the user did not request Monolithic install
* (this works at CPack time too)
*/
if (this->SupportsComponentInstallation() &
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";
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) {
this->GetInstallationType(installProjectName, installType);
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(installComponent);
"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) {
GetComponent(installProjectName, comp);
project.Components.push_back(
this->GetComponent(project.ProjectName, comp));
}
componentInstall = true;
}
}
if (componentsVector.empty()) {
componentsVector.push_back(installComponent);
componentsVector.push_back(project.Component);
}
const char* buildConfigCstr = this->GetOption("CPACK_BUILD_CONFIG");
@@ -606,293 +611,27 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
// 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,
cmDuration::zero());
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;
}
if (!this->RunPreinstallTarget(project.ProjectName, project.Directory,
globalGenerator, buildConfig)) {
return 0;
}
delete globalGenerator;
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
"- Install project: " << installProjectName << std::endl);
"- Install project: " << project.ProjectName << std::endl);
// Run the installation for each component
for (std::string const& component : componentsVector) {
std::string tempInstallDirectory = baseTempInstallDirectory;
installComponent = component;
if (componentInstall) {
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
"- Install component: " << installComponent
<< std::endl);
}
cmake cm(cmake::RoleScript);
cm.SetHomeDirectory("");
cm.SetHomeOutputDirectory("");
cm.GetCurrentSnapshot().SetDefaultDefinitions();
cm.AddCMakePaths();
cm.SetProgressCallback(cmCPackGeneratorProgress, this);
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(installComponent);
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(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)
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
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.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[installComponent].Files.push_back(localFileName);
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"Adding file <"
<< localFileName << "> to component <"
<< installComponent << ">" << 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(installComponent);
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) {
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",
@@ -900,6 +639,291 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
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.c_str(), &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.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;
}
}
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);
cm.SetHomeDirectory("");
cm.SetHomeOutputDirectory("");
cm.GetCurrentSnapshot().SetDefaultDefinitions();
cm.AddCMakePaths();
cm.SetProgressCallback(cmCPackGeneratorProgress, this);
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
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.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;
+13
View File
@@ -15,6 +15,7 @@
#include "cm_sys_stat.h"
class cmCPackLog;
class cmGlobalGenerator;
class cmInstalledFile;
class cmMakefile;
@@ -185,6 +186,17 @@ protected:
bool setDestDir, const std::string& tempInstallDirectory,
const mode_t* default_dir_mode);
virtual int RunPreinstallTarget(const std::string& installProjectName,
const std::string& installDirectory,
cmGlobalGenerator* globalGenerator,
const std::string& buildConfig);
virtual int 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);
/**
* The various level of support of
* CPACK_SET_DESTDIR used by the generator.
@@ -271,6 +283,7 @@ protected:
*/
std::vector<std::string> files;
std::vector<cmCPackInstallCMakeProject> CMakeProjects;
std::map<std::string, cmCPackInstallationType> InstallationTypes;
/**
* The set of components.
+5
View File
@@ -12,6 +12,7 @@
# include "cmCPackFreeBSDGenerator.h"
#endif
#include "cmCPackDebGenerator.h"
#include "cmCPackExtGenerator.h"
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
#include "cmCPackNSISGenerator.h"
@@ -110,6 +111,10 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory()
this->RegisterGenerator("NuGet", "NuGet packages",
cmCPackNuGetGenerator::CreateGenerator);
}
if (cmCPackExtGenerator::CanGenerate()) {
this->RegisterGenerator("Ext", "CPack External packages",
cmCPackExtGenerator::CreateGenerator);
}
#ifdef __APPLE__
if (cmCPackDragNDropGenerator::CanGenerate()) {
this->RegisterGenerator("DragNDrop", "Mac OSX Drag And Drop",