1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-14 02:08:27 +08:00

export: Factor out CMake-specific export generation (1/2)

In order to support generation of Common Package Specifications, the
mechanisms CMake uses to export package information need to be made more
abstract. As a first step toward this, refactor cmInstallExportGenerator
so that logic specific to config.cmake and Android .mk lives in separate
subclasses.

While we're at it, clean up the code style a bit and try to use moves a
bit more consistently.

This is step 1 of 2. The next step will refactor the individual file
generators along similar lines, which will also involve creating
additional classes for format-agnostic logic that is shared between
build-tree and install-tree variants.
This commit is contained in:
Matthew Woehlke
2024-07-04 16:36:37 -04:00
parent 0352376e44
commit a6cc595772
13 changed files with 242 additions and 82 deletions

View File

@@ -311,6 +311,10 @@ add_library(
cmGraphVizWriter.h
cmImportedCxxModuleInfo.cxx
cmImportedCxxModuleInfo.h
cmInstallAndroidMKExportGenerator.cxx
cmInstallAndroidMKExportGenerator.h
cmInstallCMakeConfigExportGenerator.cxx
cmInstallCMakeConfigExportGenerator.h
cmInstallGenerator.h
cmInstallGenerator.cxx
cmInstallGetRuntimeDependenciesGenerator.h

View File

@@ -1635,6 +1635,18 @@ void cmExportFileGenerator::GenerateTargetFileSets(cmGeneratorTarget* gte,
}
}
std::string cmExportFileGenerator::GetCxxModuleFile(
std::string const& name) const
{
auto const& cxxModuleDirname = this->GetCxxModulesDirectory();
if (cxxModuleDirname.empty()) {
return {};
}
return cmStrCat(cmSystemTools::GetFilenamePath(this->MainImportFile), '/',
cxxModuleDirname, "/cxx-modules-", name, ".cmake");
}
void cmExportFileGenerator::GenerateCxxModuleInformation(
std::string const& name, std::ostream& os)
{
@@ -1648,14 +1660,8 @@ void cmExportFileGenerator::GenerateCxxModuleInformation(
<< "include(\"${CMAKE_CURRENT_LIST_DIR}/" << cxx_module_dirname
<< "/cxx-modules-" << name << ".cmake\")\n\n";
// Get the path to the file we're going to write.
std::string path = this->MainImportFile;
path = cmSystemTools::GetFilenamePath(path);
auto trampoline_path =
cmStrCat(path, '/', cxx_module_dirname, "/cxx-modules-", name, ".cmake");
// Include all configuration-specific include files.
cmGeneratedFileStream ap(trampoline_path, true);
cmGeneratedFileStream ap(this->GetCxxModuleFile(name), true);
ap.SetCopyIfDifferent(true);
this->GenerateCxxModuleConfigInformation(name, ap);

View File

@@ -207,6 +207,8 @@ protected:
virtual cmExportSet* GetExportSet() const { return nullptr; }
std::string GetCxxModuleFile(std::string const& name) const;
void SetRequiredCMakeVersion(unsigned int major, unsigned int minor,
unsigned int patch);

View File

@@ -51,7 +51,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
std::string expectedTargets;
std::string sep;
for (std::unique_ptr<cmTargetExport> const& te :
this->IEGen->GetExportSet()->GetTargetExports()) {
this->GetExportSet()->GetTargetExports()) {
if (te->NamelinkOnly) {
continue;
}
@@ -61,7 +61,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
allTargets.push_back(te.get());
} else {
std::ostringstream e;
e << "install(EXPORT \"" << this->IEGen->GetExportSet()->GetName()
e << "install(EXPORT \"" << this->GetExportSet()->GetName()
<< "\" ...) "
<< "includes target \"" << te->Target->GetName()
<< "\" more than once in the export set.";
@@ -172,7 +172,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
bool result = true;
std::string cxx_modules_name = this->IEGen->GetExportSet()->GetName();
std::string cxx_modules_name = this->GetExportSet()->GetName();
this->GenerateCxxModuleInformation(cxx_modules_name, os);
if (requiresConfigFiles) {
for (std::string const& c : this->Configurations) {
@@ -338,7 +338,7 @@ void cmExportInstallFileGenerator::GenerateImportTargetsConfig(
{
// Add each target in the set to the export.
for (std::unique_ptr<cmTargetExport> const& te :
this->IEGen->GetExportSet()->GetTargetExports()) {
this->GetExportSet()->GetTargetExports()) {
// Collect import properties for this target.
if (this->GetExportTargetType(te.get()) ==
cmStateEnums::INTERFACE_LIBRARY) {
@@ -559,8 +559,7 @@ void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
std::vector<std::string> const& exportFiles)
{
std::ostringstream e;
e << "install(EXPORT \"" << this->IEGen->GetExportSet()->GetName()
<< "\" ...) "
e << "install(EXPORT \"" << this->GetExportSet()->GetName() << "\" ...) "
<< "includes target \"" << depender->GetName()
<< "\" which requires target \"" << dependee->GetName() << "\" ";
if (exportFiles.empty()) {
@@ -742,6 +741,11 @@ void cmExportInstallFileGenerator::GenerateCxxModuleConfigInformation(
/* clang-format on */
}
std::string cmExportInstallFileGenerator::GetCxxModuleFile() const
{
return this->GetCxxModuleFile(this->GetExportSet()->GetName());
}
bool cmExportInstallFileGenerator::
GenerateImportCxxModuleConfigTargetInclusion(std::string const& name,
std::string const& config)

View File

@@ -51,6 +51,9 @@ public:
return this->ConfigImportFiles;
}
/** Get the temporary location of the config-agnostic C++ module file. */
std::string GetCxxModuleFile() const;
/** Get the per-config C++ module file generated for each configuration.
This maps from the configuration name to the file temporary location
for installation. */
@@ -118,6 +121,8 @@ protected:
std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet,
cmTargetExport* te) override;
using cmExportFileGenerator::GetCxxModuleFile;
std::string GetCxxModulesDirectory() const override;
void GenerateCxxModuleConfigInformation(std::string const&,
std::ostream&) const override;

View File

@@ -0,0 +1,38 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallAndroidMKExportGenerator.h"
#include <utility>
#include <cm/memory>
#include "cmExportInstallAndroidMKGenerator.h"
#include "cmExportInstallFileGenerator.h"
#include "cmListFileCache.h"
class cmExportSet;
cmInstallAndroidMKExportGenerator::cmInstallAndroidMKExportGenerator(
cmExportSet* exportSet, std::string destination, std::string filePermissions,
std::vector<std::string> const& configurations, std::string component,
MessageLevel message, bool excludeFromAll, std::string filename,
std::string targetNamespace, bool exportOld, cmListFileBacktrace backtrace)
: cmInstallExportGenerator(exportSet, std::move(destination),
std::move(filePermissions), configurations,
std::move(component), message, excludeFromAll,
std::move(filename), std::move(targetNamespace),
std::string{}, std::move(backtrace))
, ExportOld(exportOld)
{
this->EFGen = cm::make_unique<cmExportInstallAndroidMKGenerator>(this);
}
cmInstallAndroidMKExportGenerator::~cmInstallAndroidMKExportGenerator() =
default;
void cmInstallAndroidMKExportGenerator::GenerateScript(std::ostream& os)
{
this->EFGen->SetExportOld(this->ExportOld);
this->cmInstallExportGenerator::GenerateScript(os);
}

View File

@@ -0,0 +1,40 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
#include <iosfwd>
#include <string>
#include <vector>
#include "cmInstallExportGenerator.h"
class cmExportSet;
class cmListFileBacktrace;
/** \class cmInstallAndroidMKExportGenerator
* \brief Generate rules for creating Android .mk export files.
*/
class cmInstallAndroidMKExportGenerator : public cmInstallExportGenerator
{
public:
cmInstallAndroidMKExportGenerator(
cmExportSet* exportSet, std::string destination,
std::string filePermissions,
std::vector<std::string> const& configurations, std::string component,
MessageLevel message, bool excludeFromAll, std::string filename,
std::string targetNamespace, bool exportOld,
cmListFileBacktrace backtrace);
cmInstallAndroidMKExportGenerator(cmInstallAndroidMKExportGenerator const&) =
delete;
~cmInstallAndroidMKExportGenerator() override;
cmInstallAndroidMKExportGenerator& operator=(
cmInstallAndroidMKExportGenerator const&) = delete;
protected:
char const* InstallSubcommand() const override { return "EXPORT"; }
void GenerateScript(std::ostream& os) override;
bool const ExportOld;
};

View File

@@ -0,0 +1,40 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallCMakeConfigExportGenerator.h"
#include <utility>
#include <cm/memory>
#include "cmExportInstallFileGenerator.h"
#include "cmListFileCache.h"
class cmExportSet;
cmInstallCMakeConfigExportGenerator::cmInstallCMakeConfigExportGenerator(
cmExportSet* exportSet, std::string destination, std::string filePermissions,
std::vector<std::string> const& configurations, std::string component,
MessageLevel message, bool excludeFromAll, std::string filename,
std::string targetNamespace, std::string cxxModulesDirectory, bool exportOld,
bool exportPackageDependencies, cmListFileBacktrace backtrace)
: cmInstallExportGenerator(
exportSet, std::move(destination), std::move(filePermissions),
configurations, std::move(component), message, excludeFromAll,
std::move(filename), std::move(targetNamespace),
std::move(cxxModulesDirectory), std::move(backtrace))
, ExportOld(exportOld)
, ExportPackageDependencies(exportPackageDependencies)
{
this->EFGen = cm::make_unique<cmExportInstallFileGenerator>(this);
}
cmInstallCMakeConfigExportGenerator::~cmInstallCMakeConfigExportGenerator() =
default;
void cmInstallCMakeConfigExportGenerator::GenerateScript(std::ostream& os)
{
this->EFGen->SetExportOld(this->ExportOld);
this->EFGen->SetExportPackageDependencies(this->ExportPackageDependencies);
this->cmInstallExportGenerator::GenerateScript(os);
}

View File

@@ -0,0 +1,42 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
#include <iosfwd>
#include <string>
#include <vector>
#include "cmInstallExportGenerator.h"
class cmExportSet;
class cmListFileBacktrace;
/** \class cmInstallCMakeConfigExportGenerator
* \brief Generate rules for creating CMake export files.
*/
class cmInstallCMakeConfigExportGenerator : public cmInstallExportGenerator
{
public:
cmInstallCMakeConfigExportGenerator(
cmExportSet* exportSet, std::string destination,
std::string filePermissions,
std::vector<std::string> const& configurations, std::string component,
MessageLevel message, bool excludeFromAll, std::string filename,
std::string targetNamespace, std::string cxxModulesDirectory,
bool exportOld, bool exportPackageDependencies,
cmListFileBacktrace backtrace);
cmInstallCMakeConfigExportGenerator(
cmInstallCMakeConfigExportGenerator const&) = delete;
~cmInstallCMakeConfigExportGenerator() override;
cmInstallCMakeConfigExportGenerator& operator=(
cmInstallCMakeConfigExportGenerator const&) = delete;
protected:
char const* InstallSubcommand() const override { return "EXPORT"; }
void GenerateScript(std::ostream& os) override;
bool const ExportOld;
bool const ExportPackageDependencies;
};

View File

@@ -26,10 +26,11 @@
#include "cmFileSet.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmInstallAndroidMKExportGenerator.h"
#include "cmInstallCMakeConfigExportGenerator.h"
#include "cmInstallCommandArguments.h"
#include "cmInstallCxxModuleBmiGenerator.h"
#include "cmInstallDirectoryGenerator.h"
#include "cmInstallExportGenerator.h"
#include "cmInstallFileSetGenerator.h"
#include "cmInstallFilesGenerator.h"
#include "cmInstallGenerator.h"
@@ -2028,11 +2029,11 @@ bool HandleExportAndroidMKMode(std::vector<std::string> const& args,
// Create the export install generator.
helper.Makefile->AddInstallGenerator(
cm::make_unique<cmInstallExportGenerator>(
cm::make_unique<cmInstallAndroidMKExportGenerator>(
&exportSet, ica.GetDestination(), ica.GetPermissions(),
ica.GetConfigurations(), ica.GetComponent(), message,
ica.GetExcludeFromAll(), fname, name_space, "", exportOld, true, false,
helper.Makefile->GetBacktrace()));
ica.GetExcludeFromAll(), std::move(fname), std::move(name_space),
exportOld, helper.Makefile->GetBacktrace()));
return true;
#else
@@ -2151,11 +2152,11 @@ bool HandleExportMode(std::vector<std::string> const& args,
// Create the export install generator.
helper.Makefile->AddInstallGenerator(
cm::make_unique<cmInstallExportGenerator>(
cm::make_unique<cmInstallCMakeConfigExportGenerator>(
&exportSet, ica.GetDestination(), ica.GetPermissions(),
ica.GetConfigurations(), ica.GetComponent(), message,
ica.GetExcludeFromAll(), fname, name_space, cxx_modules_directory,
exportOld, false, exportPackageDependencies,
ica.GetExcludeFromAll(), std::move(fname), std::move(name_space),
std::move(cxx_modules_directory), exportOld, exportPackageDependencies,
helper.Makefile->GetBacktrace()));
return true;

View File

@@ -6,12 +6,7 @@
#include <sstream>
#include <utility>
#include <cm/memory>
#include "cmCryptoHash.h"
#ifndef CMAKE_BOOTSTRAP
# include "cmExportInstallAndroidMKGenerator.h"
#endif
#include "cmExportInstallFileGenerator.h"
#include "cmExportSet.h"
#include "cmInstallType.h"
@@ -22,29 +17,20 @@
#include "cmSystemTools.h"
cmInstallExportGenerator::cmInstallExportGenerator(
cmExportSet* exportSet, std::string const& destination,
std::string file_permissions, std::vector<std::string> const& configurations,
std::string const& component, MessageLevel message, bool exclude_from_all,
std::string filename, std::string name_space,
std::string cxx_modules_directory, bool exportOld, bool android,
bool exportPackageDependencies, cmListFileBacktrace backtrace)
: cmInstallGenerator(destination, configurations, component, message,
exclude_from_all, false, std::move(backtrace))
cmExportSet* exportSet, std::string destination, std::string filePermissions,
std::vector<std::string> const& configurations, std::string component,
MessageLevel message, bool excludeFromAll, std::string filename,
std::string targetNamespace, std::string cxxModulesDirectory,
cmListFileBacktrace backtrace)
: cmInstallGenerator(std::move(destination), configurations,
std::move(component), message, excludeFromAll, false,
std::move(backtrace))
, ExportSet(exportSet)
, FilePermissions(std::move(file_permissions))
, FilePermissions(std::move(filePermissions))
, FileName(std::move(filename))
, Namespace(std::move(name_space))
, CxxModulesDirectory(std::move(cxx_modules_directory))
, ExportOld(exportOld)
, ExportPackageDependencies(exportPackageDependencies)
, Namespace(std::move(targetNamespace))
, CxxModulesDirectory(std::move(cxxModulesDirectory))
{
if (android) {
#ifndef CMAKE_BOOTSTRAP
this->EFGen = cm::make_unique<cmExportInstallAndroidMKGenerator>(this);
#endif
} else {
this->EFGen = cm::make_unique<cmExportInstallFileGenerator>(this);
}
exportSet->AddInstallation(this);
}
@@ -92,7 +78,7 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os)
// Skip empty sets.
if (this->ExportSet->GetTargetExports().empty()) {
std::ostringstream e;
e << "INSTALL(EXPORT) given unknown export \""
e << "INSTALL(" << this->InstallSubcommand() << ") given unknown export \""
<< this->ExportSet->GetName() << "\"";
cmSystemTools::Error(e.str());
return;
@@ -108,7 +94,6 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os)
// Generate the import file for this export set.
this->EFGen->SetExportFile(this->MainImportFile.c_str());
this->EFGen->SetNamespace(this->Namespace);
this->EFGen->SetExportOld(this->ExportOld);
if (this->ConfigurationTypes->empty()) {
if (!this->ConfigurationName.empty()) {
this->EFGen->AddConfiguration(this->ConfigurationName);
@@ -120,7 +105,6 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os)
this->EFGen->AddConfiguration(c);
}
}
this->EFGen->SetExportPackageDependencies(this->ExportPackageDependencies);
this->EFGen->GenerateImportFile();
// Perform the main install script generation.
@@ -149,22 +133,18 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
// Now create a configuration-specific install rule for the C++ module import
// property file of each configuration.
auto cxx_module_dest =
auto const cxxModuleDestination =
cmStrCat(this->Destination, '/', this->CxxModulesDirectory);
std::string config_file_example;
for (auto const& i : this->EFGen->GetConfigCxxModuleFiles()) {
config_file_example = i.second;
break;
}
if (!config_file_example.empty()) {
auto const cxxModuleInstallFilePath = this->EFGen->GetCxxModuleFile();
if (!cxxModuleInstallFilePath.empty()) {
auto const cxxModuleFilename =
cmSystemTools::GetFilenameName(cxxModuleInstallFilePath);
// Remove old per-configuration export files if the main changes.
std::string installedDir = cmStrCat(
"$ENV{DESTDIR}", ConvertToAbsoluteDestination(cxx_module_dest), '/');
std::string installedFile = cmStrCat(installedDir, "/cxx-modules-",
this->ExportSet->GetName(), ".cmake");
std::string toInstallFile =
cmStrCat(cmSystemTools::GetFilenamePath(config_file_example),
"/cxx-modules-", this->ExportSet->GetName(), ".cmake");
std::string installedDir =
cmStrCat("$ENV{DESTDIR}",
ConvertToAbsoluteDestination(cxxModuleDestination), '/');
std::string installedFile = cmStrCat(installedDir, cxxModuleFilename);
os << indent << "if(EXISTS \"" << installedFile << "\")\n";
Indent indentN = indent.Next();
Indent indentNN = indentN.Next();
@@ -172,7 +152,7 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
/* clang-format off */
os << indentN << "file(DIFFERENT _cmake_export_file_changed FILES\n"
<< indentN << " \"" << installedFile << "\"\n"
<< indentN << " \"" << toInstallFile << "\")\n";
<< indentN << " \"" << cxxModuleInstallFilePath << "\")\n";
os << indentN << "if(_cmake_export_file_changed)\n";
os << indentNN << "file(GLOB _cmake_old_config_files \"" << installedDir
<< this->EFGen->GetConfigImportFileGlob() << "\")\n";
@@ -191,8 +171,8 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
// All of these files are siblings; get its location to know where the
// "anchor" file is.
files.push_back(toInstallFile);
this->AddInstallRule(os, cxx_module_dest, cmInstallType_FILES, files,
files.push_back(cxxModuleInstallFilePath);
this->AddInstallRule(os, cxxModuleDestination, cmInstallType_FILES, files,
false, this->FilePermissions.c_str(), nullptr,
nullptr, nullptr, indent);
files.clear();
@@ -201,7 +181,7 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
files.push_back(i.second);
std::string config_test = this->CreateConfigTest(i.first);
os << indent << "if(" << config_test << ")\n";
this->AddInstallRule(os, cxx_module_dest, cmInstallType_FILES, files,
this->AddInstallRule(os, cxxModuleDestination, cmInstallType_FILES, files,
false, this->FilePermissions.c_str(), nullptr,
nullptr, nullptr, indent.Next());
os << indent << "endif()\n";
@@ -210,9 +190,9 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
for (auto const& i : this->EFGen->GetConfigCxxModuleTargetFiles()) {
std::string config_test = this->CreateConfigTest(i.first);
os << indent << "if(" << config_test << ")\n";
this->AddInstallRule(os, cxx_module_dest, cmInstallType_FILES, i.second,
false, this->FilePermissions.c_str(), nullptr,
nullptr, nullptr, indent.Next());
this->AddInstallRule(os, cxxModuleDestination, cmInstallType_FILES,
i.second, false, this->FilePermissions.c_str(),
nullptr, nullptr, nullptr, indent.Next());
os << indent << "endif()\n";
files.clear();
}

View File

@@ -17,19 +17,18 @@ class cmListFileBacktrace;
class cmLocalGenerator;
/** \class cmInstallExportGenerator
* \brief Generate rules for creating an export files.
* \brief Support class for generating rules for creating export files.
*/
class cmInstallExportGenerator : public cmInstallGenerator
{
public:
cmInstallExportGenerator(cmExportSet* exportSet, std::string const& dest,
std::string file_permissions,
const std::vector<std::string>& configurations,
std::string const& component, MessageLevel message,
bool exclude_from_all, std::string filename,
std::string name_space,
std::string cxx_modules_directory, bool exportOld,
bool android, bool exportPackageDependencies,
cmInstallExportGenerator(cmExportSet* exportSet, std::string destination,
std::string filePermissions,
std::vector<std::string> const& configurations,
std::string component, MessageLevel message,
bool excludeFromAll, std::string filename,
std::string targetNamespace,
std::string cxxModulesDirectory,
cmListFileBacktrace backtrace);
cmInstallExportGenerator(const cmInstallExportGenerator&) = delete;
~cmInstallExportGenerator() override;
@@ -57,11 +56,11 @@ public:
}
protected:
virtual char const* InstallSubcommand() const = 0;
void GenerateScript(std::ostream& os) override;
void GenerateScriptConfigs(std::ostream& os, Indent indent) override;
void GenerateScriptActions(std::ostream& os, Indent indent) override;
void GenerateImportFile(cmExportSet const* exportSet);
void GenerateImportFile(const char* config, cmExportSet const* exportSet);
std::string TempDirCalculate() const;
void ComputeTempDir();
@@ -70,8 +69,6 @@ protected:
std::string const FileName;
std::string const Namespace;
std::string const CxxModulesDirectory;
bool const ExportOld;
bool const ExportPackageDependencies;
cmLocalGenerator* LocalGenerator = nullptr;
std::string TempDir;

View File

@@ -408,6 +408,7 @@ CMAKE_CXX_SOURCES="\
cmIncludeGuardCommand \
cmIncludeDirectoryCommand \
cmIncludeRegularExpressionCommand \
cmInstallCMakeConfigExportGenerator \
cmInstallCommand \
cmInstallCommandArguments \
cmInstallCxxModuleBmiGenerator \