From 4938abb6002cb60501a0da651059ca0aefeed24f Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Fri, 8 Jun 2018 10:48:25 -0400 Subject: cmCPackGenerator: Refactor InstallProjectViaInstallCMakeProjects() This refactoring will allow cmCPackExtGenerator to skip the install step while still gathering up information about the CPack components and groups. Besides, this function was too long, and needed to be broken up anyway. --- Source/CPack/cmCPackGenerator.cxx | 552 ++++++++++++++++++++------------------ Source/CPack/cmCPackGenerator.h | 12 + 2 files changed, 296 insertions(+), 268 deletions(-) diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index f15445b..6924873 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -548,7 +548,6 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( std::string installComponent = *it; ++it; std::string installSubDirectory = *it; - std::string installFile = installDirectory + "/cmake_install.cmake"; std::vector componentsVector; @@ -559,7 +558,7 @@ 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_" + @@ -606,38 +605,11 @@ 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(installProjectName, installDirectory, + globalGenerator, buildConfig)) { + return 0; } + delete globalGenerator; cmCPackLogger(cmCPackLog::LOG_OUTPUT, @@ -645,258 +617,302 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( // 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); + if (!this->InstallCMakeProject( + setDestDir, installDirectory, baseTempInstallDirectory, + default_dir_mode, component, componentInstall, + installSubDirectory, buildConfig, absoluteDestFiles)) { + return 0; } + } + } + } + this->SetOption("CPACK_ABSOLUTE_DESTINATION_FILES", + absoluteDestFiles.c_str()); + return 1; +} - 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"); - } - } +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; + } + } - 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); - } + return 1; +} - if (!setDestDir) { - tempInstallDirectory += this->GetPackagingInstallPrefix(); - } +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 (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()); + if (componentInstall) { + cmCPackLogger(cmCPackLog::LOG_OUTPUT, + "- Install component: " << component << std::endl); + } - 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); + 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"); + } + } - 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()); + 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 (!cmsys::SystemTools::MakeDirectory(tempInstallDirectory, - default_dir_mode)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem creating temporary directory: " - << tempInstallDirectory << std::endl); - return 0; - } + if (!setDestDir) { + tempInstallDirectory += this->GetPackagingInstallPrefix(); + } - 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 (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()); - 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()); - } + 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); - // 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 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 (!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 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")); - } + if (!cmsys::SystemTools::MakeDirectory(tempInstallDirectory, + default_dir_mode)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Problem creating temporary directory: " + << tempInstallDirectory << std::endl); + return 0; + } - // 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 filesAfter = glA.GetFiles(); - std::sort(filesAfter.begin(), filesAfter.end()); - std::vector::iterator diff; - std::vector result(filesAfter.size()); - diff = std::set_difference(filesAfter.begin(), filesAfter.end(), - filesBefore.begin(), filesBefore.end(), - result.begin()); - - std::vector::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); - } - } + 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 (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) { - return 0; - } + 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 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 filesAfter = glA.GetFiles(); + std::sort(filesAfter.begin(), filesAfter.end()); + std::vector::iterator diff; + std::vector result(filesAfter.size()); + diff = std::set_difference(filesAfter.begin(), filesAfter.end(), + filesBefore.begin(), filesBefore.end(), + result.begin()); + + std::vector::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")); } } } - this->SetOption("CPACK_ABSOLUTE_DESTINATION_FILES", - absoluteDestFiles.c_str()); + if (cmSystemTools::GetErrorOccuredFlag() || !res) { + return 0; + } return 1; } diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index c22f36b..9128f36 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -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. -- cgit v0.12 From 3ced881db63a97eb402bd68be5e45298371f4519 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Fri, 8 Jun 2018 15:08:36 -0400 Subject: cmCPackGenerator: Store CPACK_INSTALL_CMAKE_PROJECTS in an internal field By storing this information in an internal field in the class, it can be used later on by generators that need it. --- Source/CPack/cmCPackComponentGroup.h | 25 +++++++++++++++++++++++++ Source/CPack/cmCPackGenerator.cxx | 30 +++++++++++++++++++----------- Source/CPack/cmCPackGenerator.h | 1 + 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/Source/CPack/cmCPackComponentGroup.h b/Source/CPack/cmCPackComponentGroup.h index f2907db..bb980d7 100644 --- a/Source/CPack/cmCPackComponentGroup.h +++ b/Source/CPack/cmCPackComponentGroup.h @@ -143,4 +143,29 @@ public: std::vector 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 InstallationTypes; + + /// The list of components. + std::vector Components; +}; + #endif diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 6924873..7014676 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -545,9 +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; + project.SubDirectory = *it; std::vector componentsVector; @@ -562,30 +566,32 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( !(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 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"); @@ -605,7 +611,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( // on windows. cmSystemTools::SetForceUnixPaths(globalGenerator->GetForceUnixPaths()); - if (!this->RunPreinstallTarget(installProjectName, installDirectory, + if (!this->RunPreinstallTarget(project.ProjectName, project.Directory, globalGenerator, buildConfig)) { return 0; } @@ -613,17 +619,19 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( 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) { if (!this->InstallCMakeProject( - setDestDir, installDirectory, baseTempInstallDirectory, + setDestDir, project.Directory, baseTempInstallDirectory, default_dir_mode, component, componentInstall, - installSubDirectory, buildConfig, absoluteDestFiles)) { + project.SubDirectory, buildConfig, absoluteDestFiles)) { return 0; } } + + this->CMakeProjects.push_back(project); } } this->SetOption("CPACK_ABSOLUTE_DESTINATION_FILES", diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index 9128f36..c13c649 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -283,6 +283,7 @@ protected: */ std::vector files; + std::vector CMakeProjects; std::map InstallationTypes; /** * The set of components. -- cgit v0.12 From 80914d88da3e5c997158fd3cc703a39b6673f780 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Fri, 8 Jun 2018 15:14:10 -0400 Subject: CPack: Add "CPack External" generator This generator doesn't actually package the files. Instead, it provides a metadata JSON file that can be used by external packaging software to do its own packaging. This JSON file provides information about the components, component groups, installation types, and CMake projects. --- Modules/Internal/CPack/CPackExt.cmake | 53 ++++++ Source/CMakeLists.txt | 3 +- Source/CPack/cmCPackExtGenerator.cxx | 291 +++++++++++++++++++++++++++++++ Source/CPack/cmCPackExtGenerator.h | 86 +++++++++ Source/CPack/cmCPackGeneratorFactory.cxx | 5 + 5 files changed, 437 insertions(+), 1 deletion(-) create mode 100644 Modules/Internal/CPack/CPackExt.cmake create mode 100644 Source/CPack/cmCPackExtGenerator.cxx create mode 100644 Source/CPack/cmCPackExtGenerator.h diff --git a/Modules/Internal/CPack/CPackExt.cmake b/Modules/Internal/CPack/CPackExt.cmake new file mode 100644 index 0000000..e52d978 --- /dev/null +++ b/Modules/Internal/CPack/CPackExt.cmake @@ -0,0 +1,53 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +if(NOT "${CPACK_EXT_REQUESTED_VERSIONS}" STREQUAL "") + unset(_found_major) + + foreach(_req_version IN LISTS CPACK_EXT_REQUESTED_VERSIONS) + if(_req_version MATCHES "^([0-9]+)\\.([0-9]+)$") + set(_req_major "${CMAKE_MATCH_1}") + set(_req_minor "${CMAKE_MATCH_2}") + + foreach(_known_version IN LISTS CPACK_EXT_KNOWN_VERSIONS) + string(REGEX MATCH + "^([0-9]+)\\.([0-9]+)$" + _known_version_dummy + "${_known_version}" + ) + + set(_known_major "${CMAKE_MATCH_1}") + set(_known_minor "${CMAKE_MATCH_2}") + + if(_req_major EQUAL _known_major AND NOT _known_minor LESS _req_minor) + set(_found_major "${_known_major}") + set(_found_minor "${_known_minor}") + break() + endif() + endforeach() + + if(DEFINED _found_major) + break() + endif() + endif() + endforeach() + + if(DEFINED _found_major) + set(CPACK_EXT_SELECTED_MAJOR "${_found_major}") + set(CPACK_EXT_SELECTED_MINOR "${_found_minor}") + set(CPACK_EXT_SELECTED_VERSION "${_found_major}.${_found_minor}") + else() + message(FATAL_ERROR + "Could not find a suitable version in CPACK_EXT_REQUESTED_VERSIONS" + ) + endif() +else() + list(GET CPACK_EXT_KNOWN_VERSIONS 0 CPACK_EXT_SELECTED_VERSION) + string(REGEX MATCH + "^([0-9]+)\\.([0-9]+)$" + _dummy + "${CPACK_EXT_SELECTED_VERSION}" + ) + set(CPACK_EXT_SELECTED_MAJOR "${CMAKE_MATCH_1}") + set(CPACK_EXT_SELECTED_MINOR "${CMAKE_MATCH_2}") +endif() diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 6623ba4..0457984 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -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} diff --git a/Source/CPack/cmCPackExtGenerator.cxx b/Source/CPack/cmCPackExtGenerator.cxx new file mode 100644 index 0000000..c36b098 --- /dev/null +++ b/Source/CPack/cmCPackExtGenerator.cxx @@ -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 +#include + +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(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 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; +} diff --git a/Source/CPack/cmCPackExtGenerator.h b/Source/CPack/cmCPackExtGenerator.h new file mode 100644 index 0000000..fa12d7f --- /dev/null +++ b/Source/CPack/cmCPackExtGenerator.h @@ -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 +#include + +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 Generator; +}; + +#endif diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx index d47e5ed..8ef24f7 100644 --- a/Source/CPack/cmCPackGeneratorFactory.cxx +++ b/Source/CPack/cmCPackGeneratorFactory.cxx @@ -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", -- cgit v0.12 From 2ef966bc77e9efd036747ee9d6977e2f2c7e024d Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Mon, 11 Jun 2018 15:33:23 -0400 Subject: Testing: Add test for CPack External generator This test case ensures that the CPack External generator produces the proper .json file, and also ensures that the version negotation with CPACK_EXT_REQUESTED_VERSIONS works properly. --- Tests/RunCMake/CMakeLists.txt | 2 +- Tests/RunCMake/CPack/Ext/Helpers.cmake | 31 ++++ Tests/RunCMake/CPack/Ext/Prerequirements.cmake | 0 Tests/RunCMake/CPack/RunCMakeTest.cmake | 3 +- Tests/RunCMake/CPack/VerifyResult.cmake | 8 +- Tests/RunCMake/CPack/tests/EXT/ExpectedFiles.cmake | 6 + Tests/RunCMake/CPack/tests/EXT/VerifyResult.cmake | 3 + .../RunCMake/CPack/tests/EXT/bad_major-stderr.txt | 6 + .../RunCMake/CPack/tests/EXT/bad_minor-stderr.txt | 6 + .../RunCMake/CPack/tests/EXT/expected-json-1.0.txt | 176 +++++++++++++++++++++ .../CPack/tests/EXT/invalid_bad-stderr.txt | 6 + Tests/RunCMake/CPack/tests/EXT/test.cmake | 83 ++++++++++ 12 files changed, 326 insertions(+), 4 deletions(-) create mode 100644 Tests/RunCMake/CPack/Ext/Helpers.cmake create mode 100644 Tests/RunCMake/CPack/Ext/Prerequirements.cmake create mode 100644 Tests/RunCMake/CPack/tests/EXT/ExpectedFiles.cmake create mode 100644 Tests/RunCMake/CPack/tests/EXT/VerifyResult.cmake create mode 100644 Tests/RunCMake/CPack/tests/EXT/bad_major-stderr.txt create mode 100644 Tests/RunCMake/CPack/tests/EXT/bad_minor-stderr.txt create mode 100644 Tests/RunCMake/CPack/tests/EXT/expected-json-1.0.txt create mode 100644 Tests/RunCMake/CPack/tests/EXT/invalid_bad-stderr.txt create mode 100644 Tests/RunCMake/CPack/tests/EXT/test.cmake diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index daf3940..dcc7c98 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -422,7 +422,7 @@ if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") add_RunCMake_test(ctest_labels_for_subprojects) endif() -add_RunCMake_test_group(CPack "DEB;RPM;7Z;TBZ2;TGZ;TXZ;TZ;ZIP;STGZ") +add_RunCMake_test_group(CPack "DEB;RPM;7Z;TBZ2;TGZ;TXZ;TZ;ZIP;STGZ;Ext") # add a test to make sure symbols are exported from a shared library # for MSVC compilers CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS property is used add_RunCMake_test(AutoExportDll) diff --git a/Tests/RunCMake/CPack/Ext/Helpers.cmake b/Tests/RunCMake/CPack/Ext/Helpers.cmake new file mode 100644 index 0000000..2c67e06 --- /dev/null +++ b/Tests/RunCMake/CPack/Ext/Helpers.cmake @@ -0,0 +1,31 @@ +function(getPackageNameGlobexpr NAME COMPONENT VERSION REVISION FILE_NO RESULT_VAR) + set(${RESULT_VAR} "${NAME}-${VERSION}-*.json" PARENT_SCOPE) +endfunction() + +function(getPackageContentList FILE RESULT_VAR) + set("${RESULT_VAR}" "" PARENT_SCOPE) +endfunction() + +function(toExpectedContentList FILE_NO CONTENT_VAR) + set("${CONTENT_VAR}" "" PARENT_SCOPE) +endfunction() + +set(ALL_FILES_GLOB "*.json") + +function(check_ext_json EXPECTED_FILE ACTUAL_FILE) + file(READ "${EXPECTED_FILE}" _expected_regex) + file(READ "${ACTUAL_FILE}" _actual_contents) + + string(REGEX REPLACE "\n+$" "" _expected_regex "${_expected_regex}") + string(REGEX REPLACE "\n+$" "" _actual_contents "${_actual_contents}") + + if(NOT "${_actual_contents}" MATCHES "${_expected_regex}") + message(FATAL_ERROR + "Output JSON does not match expected regex.\n" + "Expected regex:\n" + "${_expected_regex}\n" + "Actual output:\n" + "${_actual_contents}\n" + ) + endif() +endfunction() diff --git a/Tests/RunCMake/CPack/Ext/Prerequirements.cmake b/Tests/RunCMake/CPack/Ext/Prerequirements.cmake new file mode 100644 index 0000000..e69de29 diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake index 4b7f146..bc25b12 100644 --- a/Tests/RunCMake/CPack/RunCMakeTest.cmake +++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake @@ -18,7 +18,7 @@ run_cpack_test(GENERATE_SHLIBS_LDCONFIG "DEB" true "COMPONENT") run_cpack_test(INSTALL_SCRIPTS "RPM" false "COMPONENT") run_cpack_test(LONG_FILENAMES "DEB" false "MONOLITHIC") run_cpack_test_subtests(MAIN_COMPONENT "invalid;found" "RPM" false "COMPONENT") -run_cpack_test(MINIMAL "RPM;DEB;7Z;TBZ2;TGZ;TXZ;TZ;ZIP;STGZ" false "MONOLITHIC;COMPONENT") +run_cpack_test(MINIMAL "RPM;DEB;7Z;TBZ2;TGZ;TXZ;TZ;ZIP;STGZ;Ext" false "MONOLITHIC;COMPONENT") run_cpack_test_subtests(PACKAGE_CHECKSUM "invalid;MD5;SHA1;SHA224;SHA256;SHA384;SHA512" "TGZ" false "MONOLITHIC") run_cpack_test(PARTIALLY_RELOCATABLE_WARNING "RPM" false "COMPONENT") run_cpack_test(PER_COMPONENT_FIELDS "RPM;DEB" false "COMPONENT") @@ -31,3 +31,4 @@ run_cpack_test(USER_FILELIST "RPM" false "MONOLITHIC") run_cpack_test(MD5SUMS "DEB" false "MONOLITHIC;COMPONENT") run_cpack_test(CPACK_INSTALL_SCRIPT "ZIP" false "MONOLITHIC") run_cpack_test(DEB_PACKAGE_VERSION_BACK_COMPATIBILITY "DEB" false "MONOLITHIC;COMPONENT") +run_cpack_test_subtests(EXT "none;good;good_multi;bad_major;bad_minor;invalid_good;invalid_bad" "Ext" false "MONOLITHIC;COMPONENT") diff --git a/Tests/RunCMake/CPack/VerifyResult.cmake b/Tests/RunCMake/CPack/VerifyResult.cmake index 1f5ab87..af12d37 100644 --- a/Tests/RunCMake/CPack/VerifyResult.cmake +++ b/Tests/RunCMake/CPack/VerifyResult.cmake @@ -56,8 +56,12 @@ if(NOT EXPECTED_FILES_COUNT EQUAL 0) set(EXPECTED_FILE_CONTENT_${file_no_} "${EXPECTED_FILE_CONTENT_${file_no_}_LIST}") toExpectedContentList("${file_no_}" "EXPECTED_FILE_CONTENT_${file_no_}") - list(SORT PACKAGE_CONTENT) - list(SORT EXPECTED_FILE_CONTENT_${file_no_}) + if(NOT PACKAGE_CONTENT STREQUAL "") + list(SORT PACKAGE_CONTENT) + endif() + if(NOT EXPECTED_FILE_CONTENT_${file_no_} STREQUAL "") + list(SORT EXPECTED_FILE_CONTENT_${file_no_}) + endif() if(PACKAGE_CONTENT STREQUAL EXPECTED_FILE_CONTENT_${file_no_}) set(expected_content_list TRUE) diff --git a/Tests/RunCMake/CPack/tests/EXT/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/EXT/ExpectedFiles.cmake new file mode 100644 index 0000000..2634111 --- /dev/null +++ b/Tests/RunCMake/CPack/tests/EXT/ExpectedFiles.cmake @@ -0,0 +1,6 @@ +if(RunCMake_SUBTEST_SUFFIX MATCHES "^(none|good(_multi)?|invalid_good)$") + set(EXPECTED_FILES_COUNT "1") + set(EXPECTED_FILE_CONTENT_1_LIST "/share;/share/cpack-test;/share/cpack-test/f1.txt;/share/cpack-test/f2.txt;/share/cpack-test/f3.txt;/share/cpack-test/f4.txt") +else() + set(EXPECTED_FILES_COUNT "0") +endif() diff --git a/Tests/RunCMake/CPack/tests/EXT/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/EXT/VerifyResult.cmake new file mode 100644 index 0000000..97b74f7 --- /dev/null +++ b/Tests/RunCMake/CPack/tests/EXT/VerifyResult.cmake @@ -0,0 +1,3 @@ +if(RunCMake_SUBTEST_SUFFIX MATCHES "^(none|good(_multi)?|invalid_good)") + check_ext_json("${src_dir}/tests/EXT/expected-json-1.0.txt" "${FOUND_FILE_1}") +endif() diff --git a/Tests/RunCMake/CPack/tests/EXT/bad_major-stderr.txt b/Tests/RunCMake/CPack/tests/EXT/bad_major-stderr.txt new file mode 100644 index 0000000..372c5e4 --- /dev/null +++ b/Tests/RunCMake/CPack/tests/EXT/bad_major-stderr.txt @@ -0,0 +1,6 @@ +CMake Error at .*/Modules/Internal/CPack/CPackExt\.cmake:[0-9]+ \(message\): + Could not find a suitable version in CPACK_EXT_REQUESTED_VERSIONS + + +CPack Error: Error while executing CPackExt\.cmake +CPack Error: Cannot initialize the generator Ext diff --git a/Tests/RunCMake/CPack/tests/EXT/bad_minor-stderr.txt b/Tests/RunCMake/CPack/tests/EXT/bad_minor-stderr.txt new file mode 100644 index 0000000..372c5e4 --- /dev/null +++ b/Tests/RunCMake/CPack/tests/EXT/bad_minor-stderr.txt @@ -0,0 +1,6 @@ +CMake Error at .*/Modules/Internal/CPack/CPackExt\.cmake:[0-9]+ \(message\): + Could not find a suitable version in CPACK_EXT_REQUESTED_VERSIONS + + +CPack Error: Error while executing CPackExt\.cmake +CPack Error: Cannot initialize the generator Ext diff --git a/Tests/RunCMake/CPack/tests/EXT/expected-json-1.0.txt b/Tests/RunCMake/CPack/tests/EXT/expected-json-1.0.txt new file mode 100644 index 0000000..b96cf0b --- /dev/null +++ b/Tests/RunCMake/CPack/tests/EXT/expected-json-1.0.txt @@ -0,0 +1,176 @@ +^\{ + "componentGroups" :[ ] + \{ + "f12" :[ ] + \{ + "components" :[ ] + \[ + "f1", + "f2" + \], + "description" : "Component group for files 1 and 2", + "displayName" : "Files 1 and 2", + "isBold" : false, + "isExpandedByDefault" : false, + "name" : "f12", + "parentGroup" : "f1234", + "subgroups" : \[\] + \}, + "f1234" :[ ] + \{ + "components" : \[\], + "description" : "Component group for all files", + "displayName" : "Files 1-4", + "isBold" : false, + "isExpandedByDefault" : false, + "name" : "f1234", + "subgroups" :[ ] + \[ + "f12", + "f34" + \] + \}, + "f34" :[ ] + \{ + "components" :[ ] + \[ + "f3", + "f4" + \], + "description" : "Component group for files 3 and 4", + "displayName" : "Files 3 and 4", + "isBold" : false, + "isExpandedByDefault" : false, + "name" : "f34", + "parentGroup" : "f1234", + "subgroups" : \[\] + \} + \}, + "components" :[ ] + \{ + "f1" :[ ] + \{ + "archiveFile" : "", + "dependencies" : \[\], + "description" : "Component for file 1", + "displayName" : "File 1", + "group" : "f12", + "installationTypes" :[ ] + \[ + "full", + "f12" + \], + "isDisabledByDefault" : false, + "isDownloaded" : false, + "isHidden" : false, + "isRequired" : false, + "name" : "f1" + \}, + "f2" :[ ] + \{ + "archiveFile" : "", + "dependencies" :[ ] + \[ + "f1" + \], + "description" : "Component for file 2", + "displayName" : "File 2", + "group" : "f12", + "installationTypes" :[ ] + \[ + "full", + "f12" + \], + "isDisabledByDefault" : false, + "isDownloaded" : false, + "isHidden" : false, + "isRequired" : false, + "name" : "f2" + \}, + "f3" :[ ] + \{ + "archiveFile" : "", + "dependencies" :[ ] + \[ + "f1", + "f2" + \], + "description" : "Component for file 3", + "displayName" : "File 3", + "group" : "f34", + "installationTypes" :[ ] + \[ + "full" + \], + "isDisabledByDefault" : false, + "isDownloaded" : false, + "isHidden" : false, + "isRequired" : false, + "name" : "f3" + \}, + "f4" :[ ] + \{ + "archiveFile" : "", + "dependencies" :[ ] + \[ + "f2", + "f3", + "f1" + \], + "description" : "Component for file 4", + "displayName" : "File 4", + "group" : "f34", + "installationTypes" :[ ] + \[ + "full" + \], + "isDisabledByDefault" : false, + "isDownloaded" : false, + "isHidden" : false, + "isRequired" : false, + "name" : "f4" + \} + \}, + "errorOnAbsoluteInstallDestination" : false, + "formatVersionMajor" : 1, + "formatVersionMinor" : 0, + "installationTypes" :[ ] + \{ + "f12" :[ ] + \{ + "displayName" : "Only files 1 and 2", + "index" : 2, + "name" : "f12" + \}, + "full" :[ ] + \{ + "displayName" : "Full installation", + "index" : 1, + "name" : "full" + \} + \}, + "packageDescriptionFile" : ".*/Templates/CPack\.GenericDescription\.txt", + "packageDescriptionSummary" : "EXT-(none|good(_multi)?|invalid_good)-subtest-(MONOLITHIC|COMPONENT)-type built using CMake", + "packageName" : "ext", + "packageVersion" : "0\.1\.1", + "projects" :[ ] + \[ + \{ + "component" : "ALL", + "components" :[ ] + \[ + "f1", + "f2", + "f3", + "f4" + \], + "directory" : ".*/Tests/RunCMake/Ext/CPack/EXT-build-(none|good(_multi)?|invalid_good)-subtest", + "installationTypes" : \[\], + "projectName" : "EXT-(none|good(_multi)?|invalid_good)-subtest-(MONOLITHIC|COMPONENT)-type", + "subDirectory" : "/" + \} + \], + "setDestdir" : false, + "stripFiles" : false, + "warnOnAbsoluteInstallDestination" : false +\}$ diff --git a/Tests/RunCMake/CPack/tests/EXT/invalid_bad-stderr.txt b/Tests/RunCMake/CPack/tests/EXT/invalid_bad-stderr.txt new file mode 100644 index 0000000..372c5e4 --- /dev/null +++ b/Tests/RunCMake/CPack/tests/EXT/invalid_bad-stderr.txt @@ -0,0 +1,6 @@ +CMake Error at .*/Modules/Internal/CPack/CPackExt\.cmake:[0-9]+ \(message\): + Could not find a suitable version in CPACK_EXT_REQUESTED_VERSIONS + + +CPack Error: Error while executing CPackExt\.cmake +CPack Error: Cannot initialize the generator Ext diff --git a/Tests/RunCMake/CPack/tests/EXT/test.cmake b/Tests/RunCMake/CPack/tests/EXT/test.cmake new file mode 100644 index 0000000..6bd3cb8 --- /dev/null +++ b/Tests/RunCMake/CPack/tests/EXT/test.cmake @@ -0,0 +1,83 @@ +include(CPackComponent) + +if(RunCMake_SUBTEST_SUFFIX STREQUAL "none") + unset(CPACK_EXT_REQUESTED_VERSIONS) +elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "good") + set(CPACK_EXT_REQUESTED_VERSIONS "1.0") +elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "good_multi") + set(CPACK_EXT_REQUESTED_VERSIONS "1.0;2.0") +elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "bad_major") + set(CPACK_EXT_REQUESTED_VERSIONS "2.0") +elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "bad_minor") + set(CPACK_EXT_REQUESTED_VERSIONS "1.1") +elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "invalid_good") + set(CPACK_EXT_REQUESTED_VERSIONS "1;1.0") +elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "invalid_bad") + set(CPACK_EXT_REQUESTED_VERSIONS "1") +endif() + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/f1.txt" test1) +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/f2.txt" test2) +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/f3.txt" test3) +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/f4.txt" test4) + +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/f1.txt" DESTINATION share/cpack-test COMPONENT f1) +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/f2.txt" DESTINATION share/cpack-test COMPONENT f2) +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/f3.txt" DESTINATION share/cpack-test COMPONENT f3) +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/f4.txt" DESTINATION share/cpack-test COMPONENT f4) + +cpack_add_component(f1 + DISPLAY_NAME "File 1" + DESCRIPTION "Component for file 1" + GROUP f12 + INSTALL_TYPES full f12 +) + +cpack_add_component(f2 + DISPLAY_NAME "File 2" + DESCRIPTION "Component for file 2" + GROUP f12 + DEPENDS f1 + INSTALL_TYPES full f12 +) + +cpack_add_component(f3 + DISPLAY_NAME "File 3" + DESCRIPTION "Component for file 3" + GROUP f34 + DEPENDS f1 f2 + INSTALL_TYPES full +) + +cpack_add_component(f4 + DISPLAY_NAME "File 4" + DESCRIPTION "Component for file 4" + GROUP f34 + DEPENDS f2 f3 f1 + INSTALL_TYPES full +) + +cpack_add_component_group(f12 + DISPLAY_NAME "Files 1 and 2" + DESCRIPTION "Component group for files 1 and 2" + PARENT_GROUP f1234 +) + +cpack_add_component_group(f34 + DISPLAY_NAME "Files 3 and 4" + DESCRIPTION "Component group for files 3 and 4" + PARENT_GROUP f1234 +) + +cpack_add_component_group(f1234 + DISPLAY_NAME "Files 1-4" + DESCRIPTION "Component group for all files" +) + +cpack_add_install_type(full + DISPLAY_NAME "Full installation" +) + +cpack_add_install_type(f12 + DISPLAY_NAME "Only files 1 and 2" +) -- cgit v0.12 From 47c87cdd1ff61abb153b2b5e081532fa7f7465eb Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Fri, 22 Jun 2018 13:16:41 -0400 Subject: Help: Add documentation for CPack External generator --- Help/cpack_gen/external.rst | 249 +++++++++++++++++++++++++++++++++++++ Help/manual/cpack-generators.7.rst | 1 + 2 files changed, 250 insertions(+) create mode 100644 Help/cpack_gen/external.rst diff --git a/Help/cpack_gen/external.rst b/Help/cpack_gen/external.rst new file mode 100644 index 0000000..a69866d --- /dev/null +++ b/Help/cpack_gen/external.rst @@ -0,0 +1,249 @@ +CPack External Generator +------------------------ + +CPack provides many generators to create packages for a variety of platforms +and packaging systems. The intention is for CMake/CPack to be a complete +end-to-end solution for building and packaging a software project. However, it +may not always be possible to use CPack for the entire packaging process, due +to either technical limitations or policies that require the use of certain +tools. For this reason, CPack provides the "External" generator, which allows +external packaging software to take advantage of some of the functionality +provided by CPack, such as component installation and the dependency graph. + +The CPack External generator doesn't actually package any files. Instead, it +generates a .json file containing the CPack internal metadata, which gives +external software information on how to package the software. This metadata +file contains a list of CPack components and component groups, the various +options passed to :command:`cpack_add_component` and +:command:`cpack_add_component_group`, the dependencies between the components +and component groups, and various other options passed to CPack. + +Format +^^^^^^ + +The file produced by the CPack External generator is a .json file with an +object as its root. This root object will always provide two fields: +``formatVersionMajor`` and ``formatVersionMinor``, which are always integers +that describe the output format of the generator. Backwards-compatible changes +to the output format (for example, adding a new field that didn't exist before) +cause the minor version to be incremented, and backwards-incompatible changes +(for example, deleting a field or changing its meaning) cause the major version +to be incremented and the minor version reset to 0. The format version is +always of the format ``major.minor``. In other words, it always has exactly two +parts, separated by a period. + +You can request one or more specific versions of the output format as described +below with :variable:`CPACK_EXT_REQUESTED_VERSIONS`. The output format will +have a major version that exactly matches the requested major version, and a +minor version that is greater than or equal to the requested minor version. If +no version is requested with :variable:`CPACK_EXT_REQUESTED_VERSIONS`, the +latest known major version is used by default. Currently, the only supported +format is 1.0, which is described below. + +Version 1.0 +*********** + +In addition to the standard format fields, format version 1.0 provides the +following fields in the root: + +``components`` + The ``components`` field is an object with component names as the keys and + objects describing the components as the values. The component objects have + the following fields: + + ``name`` + The name of the component. This is always the same as the key in the + ``components`` object. + + ``displayName`` + The value of the ``DISPLAY_NAME`` field passed to + :command:`cpack_add_component`. + + ``description`` + The value of the ``DESCRIPTION`` field passed to + :command:`cpack_add_component`. + + ``isHidden`` + True if ``HIDDEN`` was passed to :command:`cpack_add_component`, false if + it was not. + + ``isRequired`` + True if ``REQUIRED`` was passed to :command:`cpack_add_component`, false if + it was not. + + ``isDisabledByDefault`` + True if ``DISABLED`` was passed to :command:`cpack_add_component`, false if + it was not. + + ``group`` + Only present if ``GROUP`` was passed to :command:`cpack_add_component`. If + so, this field is a string value containing the component's group. + + ``dependencies`` + An array of components the component depends on. This contains the values + in the ``DEPENDS`` argument passed to :command:`cpack_add_component`. If no + ``DEPENDS`` argument was passed, this is an empty list. + + ``installationTypes`` + An array of installation types the component is part of. This contains the + values in the ``INSTALL_TYPES`` argument passed to + :command:`cpack_add_component`. If no ``INSTALL_TYPES`` argument was + passed, this is an empty list. + + ``isDownloaded`` + True if ``DOWNLOADED`` was passed to :command:`cpack_add_component`, false + if it was not. + + ``archiveFile`` + The name of the archive file passed with the ``ARCHIVE_FILE`` argument to + :command:`cpack_add_component`. If no ``ARCHIVE_FILE`` argument was passed, + this is an empty string. + +``componentGroups`` + The ``componentGroups`` field is an object with component group names as the + keys and objects describing the component groups as the values. The component + group objects have the following fields: + + ``name`` + The name of the component group. This is always the same as the key in the + ``componentGroups`` object. + + ``displayName`` + The value of the ``DISPLAY_NAME`` field passed to + :command:`cpack_add_component_group`. + + ``description`` + The value of the ``DESCRIPTION`` field passed to + :command:`cpack_add_component_group`. + + ``parentGroup`` + Only present if ``PARENT_GROUP`` was passed to + :command:`cpack_add_component_group`. If so, this field is a string value + containing the component group's parent group. + + ``isExpandedByDefault`` + True if ``EXPANDED`` was passed to :command:`cpack_add_component_group`, + false if it was not. + + ``isBold`` + True if ``BOLD_TITLE`` was passed to :command:`cpack_add_component_group`, + false if it was not. + + ``components`` + An array of names of components that are direct members of the group + (components that have this group as their ``GROUP``). Components of + subgroups are not included. + + ``subgroups`` + An array of names of component groups that are subgroups of the group + (groups that have this group as their ``PARENT_GROUP``). + +``installationTypes`` + The ``installationTypes`` field is an object with installation type names as + the keys and objects describing the installation types as the values. The + installation type objects have the following fields: + + ``name`` + The name of the installation type. This is always the same as the key in + the ``installationTypes`` object. + + ``displayName`` + The value of the ``DISPLAY_NAME`` field passed to + :command:`cpack_add_install_type`. + + ``index`` + The integer index of the installation type in the list. + +``projects`` + The ``projects`` field is an array of objects describing CMake projects which + comprise the CPack project. The values in this field are derived from + :variable:`CPACK_INSTALL_CMAKE_PROJECTS`. In most cases, this will be only a + single project. The project objects have the following fields: + + ``projectName`` + The project name passed to :variable:`CPACK_INSTALL_CMAKE_PROJECTS`. + + ``component`` + The name of the component or component set which comprises the project. + + ``directory`` + The build directory of the CMake project. This is the directory which + contains the ``cmake_install.cmake`` script. + + ``subDirectory`` + The subdirectory to install the project into inside the CPack package. + +``packageName`` + The package name given in :variable:`CPACK_PACKAGE_NAME`. Only present if + this option is set. + +``packageVersion`` + The package version given in :variable:`CPACK_PACKAGE_VERSION`. Only present + if this option is set. + +``packageDescriptionFile`` + The package description file given in + :variable:`CPACK_PACKAGE_DESCRIPTION_FILE`. Only present if this option is + set. + +``packageDescriptionSummary`` + The package description summary given in + :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY`. Only present if this option is + set. + +``buildConfig`` + The build configuration given to CPack with the ``-C`` option. Only present + if this option is set. + +``defaultDirectoryPermissions`` + The default directory permissions given in + :variable:`CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS`. Only present if this + option is set. + +``setDestdir`` + True if :variable:`CPACK_SET_DESTDIR` is true, false if it is not. + +``packagingInstallPrefix`` + The install prefix given in :variable:`CPACK_PACKAGING_INSTALL_PREFIX`. Only + present if :variable:`CPACK_SET_DESTDIR` is true. + +``stripFiles`` + True if :variable:`CPACK_STRIP_FILES` is true, false if it is not. + +``warnOnAbsoluteInstallDestination`` + True if :variable:`CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION` is true, false + if it is not. + +``errorOnAbsoluteInstallDestination`` + True if :variable:`CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION` is true, + false if it is not. + +Variables specific to CPack External generator +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. variable:: CPACK_EXT_REQUESTED_VERSIONS + + This variable is used to request a specific version of the CPack External + generator. It is a list of ``major.minor`` values, separated by semicolons. + + If this variable is set to a non-empty value, the CPack External generator + will iterate through each item in the list to search for a version that it + knows how to generate. Requested versions should be listed in order of + descending preference by the client software, as the first matching version + in the list will be generated. + + The generator knows how to generate the version if it has a versioned + generator whose major version exactly matches the requested major version, + and whose minor version is greater than or equal to the requested minor + version. For example, if ``CPACK_EXT_REQUESTED_VERSIONS`` contains 1.0, and + the CPack External generator knows how to generate 1.1, it will generate 1.1. + If the generator doesn't know how to generate a version in the list, it skips + the version and looks at the next one. If it doesn't know how to generate any + of the requested versions, an error is thrown. + + If this variable is not set, or is empty, the CPack External generator will + generate the highest major and minor version that it knows how to generate. + + If an invalid version is encountered in ``CPACK_EXT_REQUESTED_VERSIONS`` (one + that doesn't match ``major.minor``, where ``major`` and ``minor`` are + integers), it is ignored. diff --git a/Help/manual/cpack-generators.7.rst b/Help/manual/cpack-generators.7.rst index 4614b1c..ade9149 100644 --- a/Help/manual/cpack-generators.7.rst +++ b/Help/manual/cpack-generators.7.rst @@ -18,6 +18,7 @@ Generators /cpack_gen/cygwin /cpack_gen/deb /cpack_gen/dmg + /cpack_gen/external /cpack_gen/freebsd /cpack_gen/ifw /cpack_gen/nsis -- cgit v0.12 From 4c7154876622b7639c7f0907adfed52a980985f6 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Thu, 14 Jun 2018 15:32:27 -0400 Subject: Help: Add release notes for CPack External generator --- Help/release/dev/cpack-external.rst | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 Help/release/dev/cpack-external.rst diff --git a/Help/release/dev/cpack-external.rst b/Help/release/dev/cpack-external.rst new file mode 100644 index 0000000..fb9a061 --- /dev/null +++ b/Help/release/dev/cpack-external.rst @@ -0,0 +1,8 @@ +cpack-external +-------------- + +* CPack gained a new :cpack_gen:`CPack External Generator` which is used to + export the CPack metadata in a format that other software can understand. The + intention of this generator is to allow external packaging software to take + advantage of CPack's features when it may not be possible to use CPack for + the entire packaging process. -- cgit v0.12