CMake/Source/CPack/IFW/cmCPackIFWGenerator.cxx

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());
}