CMake/Source/CPack/IFW/cmCPackIFWGenerator.cxx

585 lines
18 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. */
#include "cmCPackIFWGenerator.h"
2016-09-07 01:21:35 +03:00
#include "CPack/cmCPackComponentGroup.h"
#include "CPack/cmCPackGenerator.h"
#include "CPack/cmCPackLog.h"
#include "cmCPackIFWInstaller.h"
#include "cmCPackIFWPackage.h"
#include "cmCPackIFWRepository.h"
#include "cmGeneratedFileStream.h"
#include "cmSystemTools.h"
#include "cmTimestamp.h"
#include "cmVersionConfig.h"
#include "cmXMLWriter.h"
#include <sstream>
#include <utility>
cmCPackIFWGenerator::cmCPackIFWGenerator()
{
}
cmCPackIFWGenerator::~cmCPackIFWGenerator()
{
}
bool cmCPackIFWGenerator::IsVersionLess(const char* version)
{
return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
FrameworkVersion.data(), version);
}
bool cmCPackIFWGenerator::IsVersionGreater(const char* version)
{
return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER,
FrameworkVersion.data(), version);
}
bool cmCPackIFWGenerator::IsVersionEqual(const char* version)
{
return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
FrameworkVersion.data(), version);
}
int cmCPackIFWGenerator::PackageFiles()
{
cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Configuration" << std::endl);
// Installer configuragion
Installer.GenerateInstallerFile();
// Packages configuration
Installer.GeneratePackageFiles();
std::string ifwTLD = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
std::string ifwTmpFile = ifwTLD;
ifwTmpFile += "/IFWOutput.log";
// Run repogen
if (!Installer.RemoteRepositories.empty()) {
std::string ifwCmd = RepoGen;
if (IsVersionLess("2.0.0")) {
ifwCmd += " -c " + this->toplevel + "/config/config.xml";
}
ifwCmd += " -p " + this->toplevel + "/packages";
if (!PkgsDirsVector.empty()) {
for (std::vector<std::string>::iterator it = PkgsDirsVector.begin();
it != PkgsDirsVector.end(); ++it) {
ifwCmd += " -p " + *it;
}
}
if (!OnlineOnly && !DownloadedPackages.empty()) {
ifwCmd += " -i ";
std::set<cmCPackIFWPackage*>::iterator it = DownloadedPackages.begin();
ifwCmd += (*it)->Name;
++it;
while (it != DownloadedPackages.end()) {
ifwCmd += "," + (*it)->Name;
++it;
}
}
ifwCmd += " " + this->toplevel + "/repository";
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ifwCmd << std::endl);
std::string output;
int retVal = 1;
cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Generate repository"
<< std::endl);
2016-06-27 23:44:16 +03:00
bool res = cmSystemTools::RunSingleCommand(ifwCmd.c_str(), &output,
&output, &retVal, CM_NULLPTR,
this->GeneratorVerbose, 0);
if (!res || retVal) {
cmGeneratedFileStream ofs(ifwTmpFile.c_str());
ofs << "# Run command: " << ifwCmd << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running IFW command: "
<< ifwCmd << std::endl
<< "Please check " << ifwTmpFile << " for errors"
<< std::endl);
return 0;
}
if (!Repository.RepositoryUpdate.empty() &&
!Repository.PatchUpdatesXml()) {
cmCPackLogger(cmCPackLog::LOG_WARNING, "Problem patch IFW \"Updates\" "
<< "file: " << this->toplevel + "/repository/Updates.xml"
<< std::endl);
}
cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- repository: "
<< this->toplevel << "/repository generated" << std::endl);
}
// Run binary creator
{
std::string ifwCmd = BinCreator;
ifwCmd += " -c " + this->toplevel + "/config/config.xml";
if (!Installer.Resources.empty()) {
ifwCmd += " -r ";
std::vector<std::string>::iterator it = Installer.Resources.begin();
std::string path = this->toplevel + "/resources/";
ifwCmd += path + *it;
++it;
while (it != Installer.Resources.end()) {
ifwCmd += "," + path + *it;
++it;
}
}
ifwCmd += " -p " + this->toplevel + "/packages";
if (!PkgsDirsVector.empty()) {
for (std::vector<std::string>::iterator it = PkgsDirsVector.begin();
it != PkgsDirsVector.end(); ++it) {
ifwCmd += " -p " + *it;
}
}
if (OnlineOnly) {
ifwCmd += " --online-only";
} else if (!DownloadedPackages.empty() &&
!Installer.RemoteRepositories.empty()) {
ifwCmd += " -e ";
std::set<cmCPackIFWPackage*>::iterator it = DownloadedPackages.begin();
ifwCmd += (*it)->Name;
++it;
while (it != DownloadedPackages.end()) {
ifwCmd += "," + (*it)->Name;
++it;
}
} else if (!DependentPackages.empty()) {
ifwCmd += " -i ";
// Binary
std::set<cmCPackIFWPackage*>::iterator bit = BinaryPackages.begin();
while (bit != BinaryPackages.end()) {
ifwCmd += (*bit)->Name + ",";
++bit;
}
// Depend
DependenceMap::iterator it = DependentPackages.begin();
ifwCmd += it->second.Name;
++it;
while (it != DependentPackages.end()) {
ifwCmd += "," + it->second.Name;
++it;
}
}
// TODO: set correct name for multipackages
if (!this->packageFileNames.empty()) {
ifwCmd += " " + packageFileNames[0];
} else {
ifwCmd += " installer";
}
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ifwCmd << std::endl);
std::string output;
int retVal = 1;
cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Generate package" << std::endl);
2016-06-27 23:44:16 +03:00
bool res = cmSystemTools::RunSingleCommand(ifwCmd.c_str(), &output,
&output, &retVal, CM_NULLPTR,
this->GeneratorVerbose, 0);
if (!res || retVal) {
cmGeneratedFileStream ofs(ifwTmpFile.c_str());
ofs << "# Run command: " << ifwCmd << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running IFW command: "
<< ifwCmd << std::endl
<< "Please check " << ifwTmpFile << " for errors"
<< std::endl);
return 0;
}
}
return 1;
}
const char* cmCPackIFWGenerator::GetPackagingInstallPrefix()
{
const char* defPrefix = cmCPackGenerator::GetPackagingInstallPrefix();
std::string tmpPref = defPrefix ? defPrefix : "";
if (this->Components.empty()) {
tmpPref += "packages/" + GetRootPackageName() + "/data";
}
this->SetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX", tmpPref.c_str());
return this->GetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX");
}
const char* cmCPackIFWGenerator::GetOutputExtension()
{
return ExecutableSuffix.c_str();
}
int cmCPackIFWGenerator::InitializeInternal()
{
// Search Qt Installer Framework tools
const std::string BinCreatorOpt = "CPACK_IFW_BINARYCREATOR_EXECUTABLE";
const std::string RepoGenOpt = "CPACK_IFW_REPOGEN_EXECUTABLE";
const std::string FrameworkVersionOpt = "CPACK_IFW_FRAMEWORK_VERSION";
if (!this->IsSet(BinCreatorOpt) || !this->IsSet(RepoGenOpt) ||
!this->IsSet(FrameworkVersionOpt)) {
this->ReadListFile("CPackIFW.cmake");
}
// Look 'binarycreator' executable (needs)
const char* BinCreatorStr = this->GetOption(BinCreatorOpt);
if (!BinCreatorStr || cmSystemTools::IsNOTFOUND(BinCreatorStr)) {
BinCreator = "";
} else {
BinCreator = BinCreatorStr;
}
if (BinCreator.empty()) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Cannot find QtIFW compiler \"binarycreator\": "
"likely it is not installed, or not in your PATH"
<< std::endl);
return 0;
}
// Look 'repogen' executable (optional)
const char* RepoGenStr = this->GetOption(RepoGenOpt);
if (!RepoGenStr || cmSystemTools::IsNOTFOUND(RepoGenStr)) {
RepoGen = "";
} else {
RepoGen = RepoGenStr;
}
// Framework version
if (const char* FrameworkVersionSrt = this->GetOption(FrameworkVersionOpt)) {
FrameworkVersion = FrameworkVersionSrt;
} else {
FrameworkVersion = "1.9.9";
}
// Variables that Change Behavior
// Resolve duplicate names
ResolveDuplicateNames = this->IsOn("CPACK_IFW_RESOLVE_DUPLICATE_NAMES");
// Additional packages dirs
PkgsDirsVector.clear();
if (const char* dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES")) {
cmSystemTools::ExpandListArgument(dirs, PkgsDirsVector);
}
// Installer
Installer.Generator = this;
Installer.ConfigureFromOptions();
// Repository
Repository.Generator = this;
Repository.Name = "Unspecified";
if (const char* site = this->GetOption("CPACK_DOWNLOAD_SITE")) {
Repository.Url = site;
Installer.RemoteRepositories.push_back(&Repository);
}
// Repositories
if (const char* RepoAllStr = this->GetOption("CPACK_IFW_REPOSITORIES_ALL")) {
std::vector<std::string> RepoAllVector;
cmSystemTools::ExpandListArgument(RepoAllStr, RepoAllVector);
for (std::vector<std::string>::iterator rit = RepoAllVector.begin();
rit != RepoAllVector.end(); ++rit) {
GetRepository(*rit);
}
}
if (const char* ifwDownloadAll = this->GetOption("CPACK_IFW_DOWNLOAD_ALL")) {
OnlineOnly = cmSystemTools::IsOn(ifwDownloadAll);
} else if (const char* cpackDownloadAll =
this->GetOption("CPACK_DOWNLOAD_ALL")) {
OnlineOnly = cmSystemTools::IsOn(cpackDownloadAll);
} else {
OnlineOnly = false;
}
if (!Installer.RemoteRepositories.empty() && RepoGen.empty()) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Cannot find QtIFW repository generator \"repogen\": "
"likely it is not installed, or not in your PATH"
<< std::endl);
return 0;
}
// Executable suffix
if (const char* optExeSuffix = this->GetOption("CMAKE_EXECUTABLE_SUFFIX")) {
ExecutableSuffix = optExeSuffix;
if (ExecutableSuffix.empty()) {
std::string sysName(this->GetOption("CMAKE_SYSTEM_NAME"));
if (sysName == "Linux") {
ExecutableSuffix = ".run";
}
}
} else {
ExecutableSuffix = cmCPackGenerator::GetOutputExtension();
}
return this->Superclass::InitializeInternal();
}
std::string cmCPackIFWGenerator::GetComponentInstallDirNameSuffix(
const std::string& componentName)
{
const std::string prefix = "packages/";
const std::string suffix = "/data";
if (componentPackageMethod == ONE_PACKAGE) {
return std::string(prefix + GetRootPackageName() + suffix);
}
return prefix + GetComponentPackageName(&Components[componentName]) + suffix;
}
cmCPackComponent* cmCPackIFWGenerator::GetComponent(
const std::string& projectName, const std::string& componentName)
{
ComponentsMap::iterator cit = Components.find(componentName);
if (cit != Components.end()) {
return &(cit->second);
}
cmCPackComponent* component =
cmCPackGenerator::GetComponent(projectName, componentName);
if (!component) {
return component;
}
std::string name = GetComponentPackageName(component);
PackagesMap::iterator pit = Packages.find(name);
if (pit != Packages.end()) {
return component;
}
cmCPackIFWPackage* package = &Packages[name];
package->Name = name;
package->Generator = this;
if (package->ConfigureFromComponent(component)) {
package->Installer = &Installer;
Installer.Packages.insert(
std::pair<std::string, cmCPackIFWPackage*>(name, package));
ComponentPackages.insert(
std::pair<cmCPackComponent*, cmCPackIFWPackage*>(component, package));
if (component->IsDownloaded) {
DownloadedPackages.insert(package);
} else {
BinaryPackages.insert(package);
}
} else {
Packages.erase(name);
cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot configure package \""
<< name << "\" for component \"" << component->Name << "\""
<< std::endl);
}
return component;
}
cmCPackComponentGroup* cmCPackIFWGenerator::GetComponentGroup(
const std::string& projectName, const std::string& groupName)
{
cmCPackComponentGroup* group =
cmCPackGenerator::GetComponentGroup(projectName, groupName);
if (!group) {
return group;
}
std::string name = GetGroupPackageName(group);
PackagesMap::iterator pit = Packages.find(name);
if (pit != Packages.end()) {
return group;
}
cmCPackIFWPackage* package = &Packages[name];
package->Name = name;
package->Generator = this;
if (package->ConfigureFromGroup(group)) {
package->Installer = &Installer;
Installer.Packages.insert(
std::pair<std::string, cmCPackIFWPackage*>(name, package));
GroupPackages.insert(
std::pair<cmCPackComponentGroup*, cmCPackIFWPackage*>(group, package));
BinaryPackages.insert(package);
} else {
Packages.erase(name);
cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot configure package \""
<< name << "\" for component group \"" << group->Name
<< "\"" << std::endl);
}
return group;
}
enum cmCPackGenerator::CPackSetDestdirSupport
cmCPackIFWGenerator::SupportsSetDestdir() const
{
return cmCPackGenerator::SETDESTDIR_SHOULD_NOT_BE_USED;
}
bool cmCPackIFWGenerator::SupportsAbsoluteDestination() const
{
return false;
}
bool cmCPackIFWGenerator::SupportsComponentInstallation() const
{
return true;
}
bool cmCPackIFWGenerator::IsOnePackage() const
{
return componentPackageMethod == ONE_PACKAGE;
}
std::string cmCPackIFWGenerator::GetRootPackageName()
{
// Default value
std::string name = "root";
if (const char* optIFW_PACKAGE_GROUP =
this->GetOption("CPACK_IFW_PACKAGE_GROUP")) {
// Configure from root group
cmCPackIFWPackage package;
package.Generator = this;
package.ConfigureFromGroup(optIFW_PACKAGE_GROUP);
name = package.Name;
} else if (const char* optIFW_PACKAGE_NAME =
this->GetOption("CPACK_IFW_PACKAGE_NAME")) {
// Configure from root package name
name = optIFW_PACKAGE_NAME;
} else if (const char* optPACKAGE_NAME =
this->GetOption("CPACK_PACKAGE_NAME")) {
// Configure from package name
name = optPACKAGE_NAME;
}
return name;
}
std::string cmCPackIFWGenerator::GetGroupPackageName(
cmCPackComponentGroup* group) const
{
std::string name;
if (!group) {
return name;
}
if (cmCPackIFWPackage* package = GetGroupPackage(group)) {
return package->Name;
}
const char* option =
GetOption("CPACK_IFW_COMPONENT_GROUP_" +
cmsys::SystemTools::UpperCase(group->Name) + "_NAME");
name = option ? option : group->Name;
if (group->ParentGroup) {
cmCPackIFWPackage* package = GetGroupPackage(group->ParentGroup);
bool dot = !ResolveDuplicateNames;
if (dot && name.substr(0, package->Name.size()) == package->Name) {
dot = false;
}
if (dot) {
name = package->Name + "." + name;
}
}
return name;
}
std::string cmCPackIFWGenerator::GetComponentPackageName(
cmCPackComponent* component) const
{
std::string name;
if (!component) {
return name;
}
if (cmCPackIFWPackage* package = GetComponentPackage(component)) {
return package->Name;
}
std::string prefix = "CPACK_IFW_COMPONENT_" +
cmsys::SystemTools::UpperCase(component->Name) + "_";
const char* option = GetOption(prefix + "NAME");
name = option ? option : component->Name;
if (component->Group) {
cmCPackIFWPackage* package = GetGroupPackage(component->Group);
if ((componentPackageMethod == ONE_PACKAGE_PER_GROUP) ||
IsOn(prefix + "COMMON")) {
return package->Name;
}
bool dot = !ResolveDuplicateNames;
if (dot && name.substr(0, package->Name.size()) == package->Name) {
dot = false;
}
if (dot) {
name = package->Name + "." + name;
}
}
return name;
}
cmCPackIFWPackage* cmCPackIFWGenerator::GetGroupPackage(
cmCPackComponentGroup* group) const
{
std::map<cmCPackComponentGroup*, cmCPackIFWPackage*>::const_iterator pit =
GroupPackages.find(group);
2016-06-27 23:44:16 +03:00
return pit != GroupPackages.end() ? pit->second : CM_NULLPTR;
}
cmCPackIFWPackage* cmCPackIFWGenerator::GetComponentPackage(
cmCPackComponent* component) const
{
std::map<cmCPackComponent*, cmCPackIFWPackage*>::const_iterator pit =
ComponentPackages.find(component);
2016-06-27 23:44:16 +03:00
return pit != ComponentPackages.end() ? pit->second : CM_NULLPTR;
}
cmCPackIFWRepository* cmCPackIFWGenerator::GetRepository(
const std::string& repositoryName)
{
RepositoriesMap::iterator rit = Repositories.find(repositoryName);
if (rit != Repositories.end()) {
return &(rit->second);
}
cmCPackIFWRepository* repository = &Repositories[repositoryName];
repository->Name = repositoryName;
repository->Generator = this;
if (repository->ConfigureFromOptions()) {
if (repository->Update == cmCPackIFWRepository::None) {
Installer.RemoteRepositories.push_back(repository);
} else {
Repository.RepositoryUpdate.push_back(repository);
}
} else {
Repositories.erase(repositoryName);
2016-06-27 23:44:16 +03:00
repository = CM_NULLPTR;
cmCPackLogger(cmCPackLog::LOG_WARNING, "Invalid repository \""
<< repositoryName << "\""
<< " configuration. Repository will be skipped."
<< std::endl);
}
return repository;
}
void cmCPackIFWGenerator::WriteGeneratedByToStrim(cmXMLWriter& xout)
{
std::ostringstream comment;
2015-07-16 22:53:57 +03:00
comment << "Generated by CPack " << CMake_VERSION << " IFW generator "
<< "for QtIFW ";
if (IsVersionLess("2.0")) {
2015-07-16 22:53:57 +03:00
comment << "less 2.0";
} else {
2015-07-16 22:53:57 +03:00
comment << FrameworkVersion;
}
2015-07-16 22:53:57 +03:00
comment << " tools at " << cmTimestamp().CurrentTime("", true);
xout.Comment(comment.str().c_str());
}