diff options
Diffstat (limited to 'Source')
23 files changed, 854 insertions, 318 deletions
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/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 3734784..c8cecc0 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 12) -set(CMake_VERSION_PATCH 20180702) +set(CMake_VERSION_PATCH 20180703) #set(CMake_VERSION_RC 1) 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<cmCPackComponentGroup*> 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<cmCPackInstallationType*> InstallationTypes; + + /// The list of components. + std::vector<cmCPackComponent*> Components; +}; + #endif diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 50499aa..c53dd32 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -664,6 +664,12 @@ int cmCPackDebGenerator::createDeb() cmGeneratedFileStream debStream; debStream.Open(outputPath.c_str(), false, true); cmArchiveWrite deb(debStream, cmArchiveWrite::CompressNone, "arbsd"); + + // uid/gid should be the one of the root user, and this root user has + // always uid/gid equal to 0. + deb.SetUIDAndGID(0u, 0u); + deb.SetUNAMEAndGNAME("root", "root"); + if (!deb.Add(tlDir + "debian-binary", tlDir.length()) || !deb.Add(tlDir + "control.tar.gz", tlDir.length()) || !deb.Add(tlDir + "data.tar" + compression_suffix, tlDir.length())) { 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 <utility> +#include <vector> + +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<cmCPackExtVersion1Generator>(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<Json::StreamWriter> 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 <memory> +#include <string> + +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<cmCPackExtVersionGenerator> Generator; +}; + +#endif diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index f15445b..7014676 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -545,10 +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; - std::string installFile = installDirectory + "/cmake_install.cmake"; + project.SubDirectory = *it; std::vector<std::string> componentsVector; @@ -559,34 +562,36 @@ 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_" + - cmSystemTools::UpperCase(installComponent) + "_INSTALL_TYPES"; + cmSystemTools::UpperCase(project.Component) + "_INSTALL_TYPES"; const char* installTypes = this->GetOption(installTypesVar); if (installTypes && *installTypes) { std::vector<std::string> 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"); @@ -606,297 +611,316 @@ 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(project.ProjectName, project.Directory, + globalGenerator, buildConfig)) { + return 0; } + 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) { - std::string tempInstallDirectory = baseTempInstallDirectory; - installComponent = component; - if (componentInstall) { - cmCPackLogger(cmCPackLog::LOG_OUTPUT, - "- Install component: " << installComponent - << std::endl); + if (!this->InstallCMakeProject( + setDestDir, project.Directory, baseTempInstallDirectory, + default_dir_mode, component, componentInstall, + project.SubDirectory, buildConfig, absoluteDestFiles)) { + return 0; } + } - 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"); - } - } + this->CMakeProjects.push_back(project); + } + } + this->SetOption("CPACK_ABSOLUTE_DESTINATION_FILES", + absoluteDestFiles.c_str()); + return 1; +} - 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); - } +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; + } + } - if (!setDestDir) { - tempInstallDirectory += this->GetPackagingInstallPrefix(); - } + return 1; +} - 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()); +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"; - 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); + if (componentInstall) { + cmCPackLogger(cmCPackLog::LOG_OUTPUT, + "- Install component: " << component << std::endl); + } - 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()); + 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(tempInstallDirectory, - default_dir_mode)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Problem creating temporary directory: " - << tempInstallDirectory << 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); + } - 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) { + tempInstallDirectory += this->GetPackagingInstallPrefix(); + } - 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()); - } + 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()); - // 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<std::string> 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()); - } + 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); - // 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(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()); - // 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<std::string> filesAfter = glA.GetFiles(); - std::sort(filesAfter.begin(), filesAfter.end()); - std::vector<std::string>::iterator diff; - std::vector<std::string> result(filesAfter.size()); - diff = std::set_difference(filesAfter.begin(), filesAfter.end(), - filesBefore.begin(), filesBefore.end(), - result.begin()); - - std::vector<std::string>::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); - } - } + if (!cmsys::SystemTools::MakeDirectory(tempInstallDirectory, + default_dir_mode)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Problem creating temporary directory: " + << tempInstallDirectory << std::endl); + return 0; + } - 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; - } + 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 (!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<std::string> 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<std::string> filesAfter = glA.GetFiles(); + std::sort(filesAfter.begin(), filesAfter.end()); + std::vector<std::string>::iterator diff; + std::vector<std::string> result(filesAfter.size()); + diff = std::set_difference(filesAfter.begin(), filesAfter.end(), + filesBefore.begin(), filesBefore.end(), + result.begin()); + + std::vector<std::string>::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..c13c649 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. @@ -271,6 +283,7 @@ protected: */ std::vector<std::string> files; + std::vector<cmCPackInstallCMakeProject> CMakeProjects; std::map<std::string, cmCPackInstallationType> InstallationTypes; /** * The set of components. 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", diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 9f2e01d..7f42035 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -98,6 +98,9 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", gte, cmGeneratorExpression::BuildInterface, properties, missingTargets); + this->PopulateInterfaceProperty("INTERFACE_LINK_DEPENDS", gte, + cmGeneratorExpression::BuildInterface, + properties, missingTargets); this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", gte, properties); diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 5f61571..ec68fce 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -420,6 +420,37 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface( } } +void cmExportFileGenerator::PopulateLinkDependsInterface( + cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule, + ImportPropertyMap& properties, std::vector<std::string>& missingTargets) +{ + cmGeneratorTarget* gt = tei->Target; + assert(preprocessRule == cmGeneratorExpression::InstallInterface); + + const char* propName = "INTERFACE_LINK_DEPENDS"; + const char* input = gt->GetProperty(propName); + + if (!input) { + return; + } + + if (!*input) { + properties[propName].clear(); + return; + } + + std::string prepro = + cmGeneratorExpression::Preprocess(input, preprocessRule, true); + if (!prepro.empty()) { + this->ResolveTargetsInGeneratorExpressions(prepro, gt, missingTargets); + + if (!checkInterfaceDirs(prepro, gt, propName)) { + return; + } + properties[propName] = prepro; + } +} + void cmExportFileGenerator::PopulateInterfaceProperty( const std::string& propName, cmGeneratorTarget* target, cmGeneratorExpression::PreprocessContext preprocessRule, diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 954e6c5..6ca2e07 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -147,6 +147,10 @@ protected: cmTargetExport* target, cmGeneratorExpression::PreprocessContext preprocessRule, ImportPropertyMap& properties, std::vector<std::string>& missingTargets); + void PopulateLinkDependsInterface( + cmTargetExport* target, + cmGeneratorExpression::PreprocessContext preprocessRule, + ImportPropertyMap& properties, std::vector<std::string>& missingTargets); void SetImportLinkInterface( const std::string& config, std::string const& suffix, diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 1db76ac..3595708 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -106,6 +106,8 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", gt, cmGeneratorExpression::InstallInterface, properties, missingTargets); + this->PopulateLinkDependsInterface( + te, cmGeneratorExpression::InstallInterface, properties, missingTargets); std::string errorMessage; if (!this->PopulateExportProperties(gt, properties, errorMessage)) { diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index cfe31f1..cd23904 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -26,7 +26,8 @@ struct cmGeneratorExpressionContext; SELECT(F, EvaluatingAutoUicOptions, AUTOUIC_OPTIONS) \ SELECT(F, EvaluatingSources, SOURCES) \ SELECT(F, EvaluatingCompileFeatures, COMPILE_FEATURES) \ - SELECT(F, EvaluatingLinkOptions, LINK_OPTIONS) + SELECT(F, EvaluatingLinkOptions, LINK_OPTIONS) \ + SELECT(F, EvaluatingLinkDepends, LINK_DEPENDS) #define CM_FOR_EACH_TRANSITIVE_PROPERTY(F) \ CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, CM_SELECT_BOTH) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 02f181e..3989ebe 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -3017,6 +3017,48 @@ void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result, } } +namespace { +void processLinkDepends( + cmGeneratorTarget const* tgt, + const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, + std::vector<std::string>& options, + std::unordered_set<std::string>& uniqueOptions, + cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, + std::string const& language) +{ + processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, + config, false, "link depends", language, + OptionsParse::None); +} +} + +void cmGeneratorTarget::GetLinkDepends(std::vector<std::string>& result, + const std::string& config, + const std::string& language) const +{ + std::vector<cmGeneratorTarget::TargetPropertyEntry*> linkDependsEntries; + std::unordered_set<std::string> uniqueOptions; + cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), "LINK_DEPENDS", + nullptr, nullptr); + + if (const char* linkDepends = this->GetProperty("LINK_DEPENDS")) { + std::vector<std::string> depends; + cmGeneratorExpression ge; + cmSystemTools::ExpandListArgument(linkDepends, depends); + for (const auto& depend : depends) { + std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(depend); + linkDependsEntries.push_back( + new cmGeneratorTarget::TargetPropertyEntry(std::move(cge))); + } + } + AddInterfaceEntries(this, config, "INTERFACE_LINK_DEPENDS", + linkDependsEntries); + processLinkDepends(this, linkDependsEntries, result, uniqueOptions, + &dagChecker, config, language); + + cmDeleteAll(linkDependsEntries); +} + void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const { if (this->IsImported()) { diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 5b77610..6a36116 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -425,6 +425,10 @@ public: const std::string& config, const std::string& language) const; + void GetLinkDepends(std::vector<std::string>& result, + const std::string& config, + const std::string& language) const; + bool IsSystemIncludeDirectory(const std::string& dir, const std::string& config, const std::string& language) const; diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 82f4683..b9845ba 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -97,15 +97,15 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( std::vector<std::string> commands; - // Build list of dependencies. - std::vector<std::string> depends; - this->AppendLinkDepends(depends); - // Get the language to use for linking this library. std::string linkLanguage = "CUDA"; std::string const objExt = this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION"); + // Build list of dependencies. + std::vector<std::string> depends; + this->AppendLinkDepends(depends, linkLanguage); + // Get the name of the device object to generate. std::string const targetOutputReal = this->GeneratorTarget->ObjectDirectory + "cmake_device_link" + objExt; @@ -294,13 +294,6 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) { std::vector<std::string> commands; - // Build list of dependencies. - std::vector<std::string> depends; - this->AppendLinkDepends(depends); - if (!this->DeviceLinkObject.empty()) { - depends.push_back(this->DeviceLinkObject); - } - // Get the name of the executable to generate. std::string targetName; std::string targetNameReal; @@ -378,6 +371,13 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) return; } + // Build list of dependencies. + std::vector<std::string> depends; + this->AppendLinkDepends(depends, linkLanguage); + if (!this->DeviceLinkObject.empty()) { + depends.push_back(this->DeviceLinkObject); + } + this->NumberOfProgressActions++; if (!this->NoRuleMessages) { cmLocalUnixMakefileGenerator3::EchoProgress progress; diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 036acc7..571e74b 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -260,15 +260,15 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( // code duplication. std::vector<std::string> commands; - // Build list of dependencies. - std::vector<std::string> depends; - this->AppendLinkDepends(depends); - // Get the language to use for linking this library. std::string linkLanguage = "CUDA"; std::string const objExt = this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION"); + // Build list of dependencies. + std::vector<std::string> depends; + this->AppendLinkDepends(depends, linkLanguage); + // Create set of linking flags. std::string linkFlags; this->GetTargetLinkFlags(linkFlags, linkLanguage); @@ -444,13 +444,6 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // code duplication. std::vector<std::string> commands; - // Build list of dependencies. - std::vector<std::string> depends; - this->AppendLinkDepends(depends); - if (!this->DeviceLinkObject.empty()) { - depends.push_back(this->DeviceLinkObject); - } - // Get the language to use for linking this library. std::string linkLanguage = this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); @@ -462,6 +455,13 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( return; } + // Build list of dependencies. + std::vector<std::string> depends; + this->AppendLinkDepends(depends, linkLanguage); + if (!this->DeviceLinkObject.empty()) { + depends.push_back(this->DeviceLinkObject); + } + // Create set of linking flags. std::string linkFlags; this->LocalGenerator->AppendFlags(linkFlags, extraFlags); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 08fcd8f..7cae305 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1387,7 +1387,7 @@ void cmMakefileTargetGenerator::AppendObjectDepends( } void cmMakefileTargetGenerator::AppendLinkDepends( - std::vector<std::string>& depends) + std::vector<std::string>& depends, const std::string& linkLanguage) { this->AppendObjectDepends(depends); @@ -1411,10 +1411,8 @@ void cmMakefileTargetGenerator::AppendLinkDepends( } // Add user-specified dependencies. - if (const char* linkDepends = - this->GeneratorTarget->GetProperty("LINK_DEPENDS")) { - cmSystemTools::ExpandListArgument(linkDepends, depends); - } + this->GeneratorTarget->GetLinkDepends(depends, this->ConfigName, + linkLanguage); } std::string cmMakefileTargetGenerator::GetLinkRule( diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index 4d1c9ec..f21362a 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -128,7 +128,8 @@ protected: void AppendObjectDepends(std::vector<std::string>& depends); // Append link rule dependencies (objects, etc.). - void AppendLinkDepends(std::vector<std::string>& depends); + void AppendLinkDepends(std::vector<std::string>& depends, + const std::string& linkLanguage); // Lookup the link rule for this target. std::string GetLinkRule(const std::string& linkRuleVar); diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 7394188..f94e5bc 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -625,7 +625,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() outputs.push_back(targetOutputReal); // Compute specific libraries to link with. cmNinjaDeps explicitDeps = this->GetObjects(); - cmNinjaDeps implicitDeps = this->ComputeLinkDeps(); + cmNinjaDeps implicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage); std::string frameworkPath; std::string linkPath; @@ -794,7 +794,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() // Compute specific libraries to link with. cmNinjaDeps explicitDeps = this->GetObjects(); - cmNinjaDeps implicitDeps = this->ComputeLinkDeps(); + cmNinjaDeps implicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage); if (!this->DeviceLinkObject.empty()) { explicitDeps.push_back(this->DeviceLinkObject); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 9d41948..df32f40 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -235,7 +235,8 @@ std::string cmNinjaTargetGenerator::ComputeIncludes( return includesString; } -cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const +cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps( + const std::string& linkLanguage) const { // Static libraries never depend on other targets for linking. if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY || @@ -270,13 +271,11 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const } // Add user-specified dependencies. - if (const char* linkDepends = - this->GeneratorTarget->GetProperty("LINK_DEPENDS")) { - std::vector<std::string> linkDeps; - cmSystemTools::ExpandListArgument(linkDepends, linkDeps); - std::transform(linkDeps.begin(), linkDeps.end(), - std::back_inserter(result), MapToNinjaPath()); - } + std::vector<std::string> linkDeps; + this->GeneratorTarget->GetLinkDepends(linkDeps, this->ConfigName, + linkLanguage); + std::transform(linkDeps.begin(), linkDeps.end(), std::back_inserter(result), + MapToNinjaPath()); return result; } diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 4660a3a..e58a8a0 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -95,7 +95,7 @@ protected: } /// @return the list of link dependency for the given target @a target. - cmNinjaDeps ComputeLinkDeps() const; + cmNinjaDeps ComputeLinkDeps(const std::string& linkLanguage) const; /// @return the source file path for the given @a source. std::string GetSourceFilePath(cmSourceFile const* source) const; |