CMake/Source/CPack/IFW/cmCPackIFWGenerator.cxx
Brad King 86578eccf2 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 15:14:44 -04:00

585 lines
18 KiB
C++

/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackIFWGenerator.h"
#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);
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);
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);
return pit != GroupPackages.end() ? pit->second : CM_NULLPTR;
}
cmCPackIFWPackage* cmCPackIFWGenerator::GetComponentPackage(
cmCPackComponent* component) const
{
std::map<cmCPackComponent*, cmCPackIFWPackage*>::const_iterator pit =
ComponentPackages.find(component);
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);
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;
comment << "Generated by CPack " << CMake_VERSION << " IFW generator "
<< "for QtIFW ";
if (IsVersionLess("2.0")) {
comment << "less 2.0";
} else {
comment << FrameworkVersion;
}
comment << " tools at " << cmTimestamp().CurrentTime("", true);
xout.Comment(comment.str().c_str());
}