/* 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 #include 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::iterator it = PkgsDirsVector.begin(); it != PkgsDirsVector.end(); ++it) { ifwCmd += " -p " + *it; } } if (!OnlineOnly && !DownloadedPackages.empty()) { ifwCmd += " -i "; std::set::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::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::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::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::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 RepoAllVector; cmSystemTools::ExpandListArgument(RepoAllStr, RepoAllVector); for (std::vector::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(name, package)); ComponentPackages.insert( std::pair(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(name, package)); GroupPackages.insert( std::pair(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::const_iterator pit = GroupPackages.find(group); return pit != GroupPackages.end() ? pit->second : CM_NULLPTR; } cmCPackIFWPackage* cmCPackIFWGenerator::GetComponentPackage( cmCPackComponent* component) const { std::map::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()); }