mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
c++modules: use synthetic interface objects for import std
Fixes: #27999
This commit is contained in:
@@ -708,7 +708,7 @@ void cmGeneratorTarget::GetObjectSources(
|
||||
this->VisitedConfigsForObjects.insert(config);
|
||||
}
|
||||
|
||||
void cmGeneratorTarget::ComputeObjectMapping()
|
||||
void cmGeneratorTarget::ComputeObjectMapping() const
|
||||
{
|
||||
auto const& configs =
|
||||
this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
|
||||
@@ -863,7 +863,8 @@ bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang,
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string const& cmGeneratorTarget::GetObjectName(cmSourceFile const* file)
|
||||
std::string const& cmGeneratorTarget::GetObjectName(
|
||||
cmSourceFile const* file) const
|
||||
{
|
||||
this->ComputeObjectMapping();
|
||||
auto const useShortPaths = this->GetUseShortObjectNames()
|
||||
@@ -906,7 +907,7 @@ void cmGeneratorTarget::AddExplicitObjectName(cmSourceFile const* sf)
|
||||
|
||||
bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
|
||||
{
|
||||
const_cast<cmGeneratorTarget*>(this)->ComputeObjectMapping();
|
||||
this->ComputeObjectMapping();
|
||||
auto it = this->ExplicitObjectName.find(file);
|
||||
return it != this->ExplicitObjectName.end();
|
||||
}
|
||||
@@ -5377,8 +5378,9 @@ bool CreateCxxStdlibTarget(cmMakefile* makefile, cmLocalGenerator* lg,
|
||||
metadata = std::move(*parseResult.Meta);
|
||||
}
|
||||
|
||||
auto* stdlibTgt = makefile->AddLibrary(
|
||||
"@cmake_cxx_std", cm::TargetType::STATIC_LIBRARY, {}, true);
|
||||
auto* stdlibTgt = makefile->AddImportedTarget(
|
||||
"@cmake_cxx_std", cm::TargetType::INTERFACE_LIBRARY,
|
||||
cm::ImportedTargetScope::Local);
|
||||
cmCxxModuleMetadata::PopulateTarget(*stdlibTgt, *metadata, configs);
|
||||
cmStandardLevelResolver standardResolver(makefile);
|
||||
standardResolver.AddRequiredTargetFeature(stdlibTgt, "cxx_std_20");
|
||||
@@ -5387,7 +5389,13 @@ bool CreateCxxStdlibTarget(cmMakefile* makefile, cmLocalGenerator* lg,
|
||||
gt->ComputeCompileFeatures(config);
|
||||
}
|
||||
|
||||
lg->AddGeneratorTarget(std::move(gt));
|
||||
auto compilerId = makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_ID");
|
||||
if (compilerId == "MSVC") {
|
||||
stdlibTgt->SetCxxModuleNeedsInterfaceObjects(true);
|
||||
}
|
||||
|
||||
lg->AddImportedGeneratorTarget(gt.get());
|
||||
lg->AddOwnedImportedGeneratorTarget(std::move(gt));
|
||||
|
||||
#endif // CMAKE_BOOTSTRAP
|
||||
|
||||
@@ -5541,6 +5549,9 @@ cmGeneratorTarget const* cmGeneratorTarget::GetCxxSyntheticTarget(
|
||||
auto* lg = this->GetLocalGenerator();
|
||||
auto* tgt =
|
||||
mf->AddSynthesizedTarget(cm::TargetType::INTERFACE_LIBRARY, targetName);
|
||||
if (model->CxxModuleNeedsInterfaceObjects()) {
|
||||
tgt->SetCxxModuleNeedsInterfaceObjects(true);
|
||||
}
|
||||
|
||||
// Copy relevant information from the existing target.
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ public:
|
||||
|
||||
void GetObjectSources(std::vector<cmSourceFile const*>&,
|
||||
std::string const& config) const;
|
||||
std::string const& GetObjectName(cmSourceFile const* file);
|
||||
std::string const& GetObjectName(cmSourceFile const* file) const;
|
||||
char const* GetCustomObjectExtension() const;
|
||||
|
||||
bool HasExplicitObjectName(cmSourceFile const* file) const;
|
||||
@@ -233,7 +233,7 @@ public:
|
||||
|
||||
std::set<cmLinkItem> const& GetUtilityItems() const;
|
||||
|
||||
void ComputeObjectMapping();
|
||||
void ComputeObjectMapping() const;
|
||||
|
||||
cmValue GetFeature(std::string const& feature,
|
||||
std::string const& config) const;
|
||||
|
||||
@@ -422,7 +422,9 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
|
||||
kind = SourceKindCustomCommand;
|
||||
} else if (!this->Target->IsNormal() && !this->Target->IsImported() &&
|
||||
fs && (fs->GetType() == cm::FileSetMetadata::CXX_MODULES)) {
|
||||
kind = SourceKindCxxModuleSource;
|
||||
kind = this->Target->CxxModuleNeedsInterfaceObjects()
|
||||
? SourceKindObjectSource
|
||||
: SourceKindCxxModuleSource;
|
||||
} else if (this->Target->GetType() == cm::TargetType::UTILITY ||
|
||||
this->Target->GetType() == cm::TargetType::INTERFACE_LIBRARY
|
||||
// XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
|
||||
|
||||
@@ -2680,7 +2680,8 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
|
||||
std::vector<std::string> const& linked_target_dirs,
|
||||
std::vector<std::string> const& forward_modules_from_target_dirs,
|
||||
std::string const& native_target_dir, std::string const& arg_lang,
|
||||
std::string const& arg_modmapfmt, cmCxxModuleExportInfo const& export_info)
|
||||
std::string const& arg_modmapfmt, cmCxxModuleExportInfo const& export_info,
|
||||
Json::Value const* cxx_interface_objects)
|
||||
{
|
||||
// Setup path conversions.
|
||||
{
|
||||
@@ -3066,8 +3067,40 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
|
||||
return {};
|
||||
};
|
||||
|
||||
return cmDyndepCollation::WriteDyndepMetadata(arg_lang, objects, export_info,
|
||||
cb);
|
||||
if (!cmDyndepCollation::WriteDyndepMetadata(arg_lang, objects, export_info,
|
||||
cb)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write the interface objects response file if configured.
|
||||
if (cxx_interface_objects && cxx_interface_objects->isObject()) {
|
||||
Json::Value const& rspFile = (*cxx_interface_objects)["rsp-file"];
|
||||
Json::Value const& moduleObjects =
|
||||
(*cxx_interface_objects)["module-objects"];
|
||||
if (rspFile.isString() && moduleObjects.isObject()) {
|
||||
std::set<std::string> usedModules;
|
||||
for (cmScanDepInfo const& object : objects) {
|
||||
for (auto const& r : object.Requires) {
|
||||
usedModules.insert(r.LogicalName);
|
||||
}
|
||||
}
|
||||
|
||||
cmGeneratedFileStream rsp(rspFile.asString());
|
||||
rsp.SetCopyIfDifferent(true);
|
||||
auto* lg = this->LocalGenerators.back().get();
|
||||
for (auto i = moduleObjects.begin(); i != moduleObjects.end(); ++i) {
|
||||
std::string moduleName = i.key().asString();
|
||||
if (usedModules.count(moduleName)) {
|
||||
rsp << lg->ConvertToOutputFormat(
|
||||
lg->MaybeRelativeToTopBinDir((*i).asString()),
|
||||
cmOutputConverter::RESPONSE)
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
|
||||
@@ -3182,6 +3215,11 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
|
||||
|
||||
auto export_info = cmDyndepCollation::ParseExportInfo(tdi);
|
||||
|
||||
Json::Value const* cxx_interface_objects = nullptr;
|
||||
if (tdi.isMember("cxx-interface-objects")) {
|
||||
cxx_interface_objects = &tdi["cxx-interface-objects"];
|
||||
}
|
||||
|
||||
cmake cm(cmState::Role::Internal);
|
||||
cm.SetHomeDirectory(dir_top_src);
|
||||
cm.SetHomeOutputDirectory(dir_top_bld);
|
||||
@@ -3200,7 +3238,7 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
|
||||
arg_dd, arg_ddis, module_dir, linked_target_dirs,
|
||||
forward_modules_from_target_dirs,
|
||||
native_target_dir, arg_lang, arg_modmapfmt,
|
||||
*export_info)
|
||||
*export_info, cxx_interface_objects)
|
||||
? 0
|
||||
: 1;
|
||||
}
|
||||
|
||||
@@ -434,8 +434,8 @@ public:
|
||||
std::vector<std::string> const& linked_target_dirs,
|
||||
std::vector<std::string> const& forward_modules_from_target_dirs,
|
||||
std::string const& native_target_dir, std::string const& arg_lang,
|
||||
std::string const& arg_modmapfmt,
|
||||
cmCxxModuleExportInfo const& export_info);
|
||||
std::string const& arg_modmapfmt, cmCxxModuleExportInfo const& export_info,
|
||||
Json::Value const* cxx_interface_objects = nullptr);
|
||||
|
||||
virtual std::string BuildAlias(std::string const& alias,
|
||||
std::string const& /*config*/) const
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "cmStateTypes.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmTarget.h"
|
||||
#include "cmTargetTypes.h"
|
||||
#include "cmValue.h"
|
||||
|
||||
@@ -1386,6 +1387,30 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
|
||||
vars["LINK_PATH"] = frameworkPath + linkPath;
|
||||
vars["CONFIG"] = config;
|
||||
|
||||
// Add interface objects response file to link flags if configured.
|
||||
{
|
||||
bool multiConfig = this->GetGlobalGenerator()->IsMultiConfig();
|
||||
std::string configDir = multiConfig ? cmStrCat('/', config) : "";
|
||||
bool hasInterfaceObjects = false;
|
||||
for (auto const& pair :
|
||||
this->GetGeneratorTarget()->GetSyntheticDeps(config)) {
|
||||
if (pair.first->Target->CxxModuleNeedsInterfaceObjects()) {
|
||||
hasInterfaceObjects = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasInterfaceObjects) {
|
||||
std::string rspPath =
|
||||
cmStrCat(this->GeneratorTarget->GetSupportDirectory(), configDir,
|
||||
"/CXXInterfaceObjects.rsp");
|
||||
vars["LINK_FLAGS"] += cmStrCat(
|
||||
" @",
|
||||
this->GetLocalGenerator()->ConvertToOutputFormat(
|
||||
this->ConvertToNinjaPath(rspPath), cmOutputConverter::SHELL));
|
||||
linkBuild.ImplicitDeps.emplace_back(this->ConvertToNinjaPath(rspPath));
|
||||
}
|
||||
}
|
||||
|
||||
// Compute architecture specific link flags. Yes, these go into a different
|
||||
// variable for executables, probably due to a mistake made when duplicating
|
||||
// code between the Makefile executable and library generators.
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "cmRange.h"
|
||||
#include "cmRulePlaceholderExpander.h"
|
||||
#include "cmSourceFile.h"
|
||||
#include "cmSourceFileLocationKind.h"
|
||||
#include "cmState.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
@@ -291,7 +292,8 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
|
||||
R"(" but the source is not classified as a "CXX" source.)"));
|
||||
}
|
||||
|
||||
if (!this->GeneratorTarget->Target->IsNormal()) {
|
||||
if (!this->GeneratorTarget->Target->IsNormal() &&
|
||||
!this->GeneratorTarget->Target->CxxModuleNeedsInterfaceObjects()) {
|
||||
if (this->GetMakefile()
|
||||
->GetDefinition("CMAKE_CXX_COMPILE_BMI")
|
||||
.IsEmpty()) {
|
||||
@@ -1356,6 +1358,25 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
|
||||
build.Outputs.push_back(this->GetDyndepFilePath(language, config));
|
||||
build.ImplicitOuts.emplace_back(
|
||||
cmStrCat(this->GetObjectFileDir(config), '/', language, "Modules.json"));
|
||||
// Add interface objects response file as implicit output if needed.
|
||||
{
|
||||
bool multiConfig = this->GetGlobalGenerator()->IsMultiConfig();
|
||||
std::string configDir = multiConfig ? cmStrCat('/', config) : "";
|
||||
std::string rspPath =
|
||||
cmStrCat(this->GeneratorTarget->GetSupportDirectory(), configDir,
|
||||
"/CXXInterfaceObjects.rsp");
|
||||
bool hasInterfaceObjects = false;
|
||||
for (auto const& pair :
|
||||
this->GeneratorTarget->GetSyntheticDeps(config)) {
|
||||
if (pair.first->Target->CxxModuleNeedsInterfaceObjects()) {
|
||||
hasInterfaceObjects = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasInterfaceObjects) {
|
||||
build.ImplicitOuts.emplace_back(this->ConvertToNinjaPath(rspPath));
|
||||
}
|
||||
}
|
||||
build.ImplicitDeps.emplace_back(
|
||||
this->GetTargetDependInfoPath(language, config));
|
||||
{
|
||||
@@ -2440,6 +2461,70 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
|
||||
config, cb);
|
||||
#endif
|
||||
|
||||
// Collect interface objects from tagged synthetics for the response file.
|
||||
{
|
||||
auto const& synthDeps = this->GeneratorTarget->GetSyntheticDeps(config);
|
||||
if (!synthDeps.empty()) {
|
||||
bool multiConfig = this->GetGlobalGenerator()->IsMultiConfig();
|
||||
std::string configDir = multiConfig ? cmStrCat('/', config) : "";
|
||||
std::string configUpper = cmSystemTools::UpperCase(config);
|
||||
std::string modulesProp = cmStrCat("IMPORTED_CXX_MODULES_", configUpper);
|
||||
|
||||
Json::Value interfaceObjects(Json::objectValue);
|
||||
Json::Value moduleObjects(Json::objectValue);
|
||||
bool hasInterfaceObjects = false;
|
||||
|
||||
for (auto const& pair : synthDeps) {
|
||||
auto const* nativeGT = pair.first;
|
||||
if (!nativeGT->Target->CxxModuleNeedsInterfaceObjects()) {
|
||||
continue;
|
||||
}
|
||||
hasInterfaceObjects = true;
|
||||
|
||||
for (auto const* synthGT : pair.second) {
|
||||
std::string objDir =
|
||||
cmStrCat(synthGT->GetSupportDirectory(), configDir);
|
||||
cmValue importedModules = synthGT->Target->GetProperty(modulesProp);
|
||||
if (!importedModules) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto const& entry : cmList{ *importedModules }) {
|
||||
auto nameSep = entry.find('=');
|
||||
if (nameSep == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
auto moduleName = entry.substr(0, nameSep);
|
||||
auto nameAndPath = entry.substr(nameSep + 1);
|
||||
auto commaSep = nameAndPath.find(',');
|
||||
std::string sourcePath = commaSep == std::string::npos
|
||||
? nameAndPath
|
||||
: nameAndPath.substr(0, commaSep);
|
||||
|
||||
cmSourceFile const* sf = synthGT->Makefile->GetSource(
|
||||
sourcePath, cmSourceFileLocationKind::Known);
|
||||
if (!sf) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string const& objName = synthGT->GetObjectName(sf);
|
||||
std::string objPath = cmStrCat(objDir, '/', objName);
|
||||
moduleObjects[moduleName] = objPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasInterfaceObjects) {
|
||||
std::string rspPath =
|
||||
cmStrCat(this->GeneratorTarget->GetSupportDirectory(), configDir,
|
||||
"/CXXInterfaceObjects.rsp");
|
||||
interfaceObjects["rsp-file"] = rspPath;
|
||||
interfaceObjects["module-objects"] = moduleObjects;
|
||||
tdi["cxx-interface-objects"] = interfaceObjects;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string const tdin = this->GetTargetDependInfoPath(lang, config);
|
||||
cmGeneratedFileStream tdif(tdin);
|
||||
tdif << tdi;
|
||||
|
||||
@@ -632,6 +632,7 @@ public:
|
||||
bool IsSymbolic = false;
|
||||
bool IsForTryCompile = false;
|
||||
bool IsExportPassthrough = false;
|
||||
bool CxxModuleNeedsInterfaceObjects = false;
|
||||
cmTarget::Visibility TargetVisibility;
|
||||
std::set<BT<std::pair<std::string, bool>>> Utilities;
|
||||
std::set<std::string> CodegenDependencies;
|
||||
@@ -1190,6 +1191,16 @@ cmGlobalGenerator* cmTarget::GetGlobalGenerator() const
|
||||
return this->impl->Makefile->GetGlobalGenerator();
|
||||
}
|
||||
|
||||
bool cmTarget::CxxModuleNeedsInterfaceObjects() const
|
||||
{
|
||||
return this->impl->CxxModuleNeedsInterfaceObjects;
|
||||
}
|
||||
|
||||
void cmTarget::SetCxxModuleNeedsInterfaceObjects(bool v)
|
||||
{
|
||||
this->impl->CxxModuleNeedsInterfaceObjects = v;
|
||||
}
|
||||
|
||||
BTs<std::string> const* cmTarget::GetLanguageStandardProperty(
|
||||
std::string const& propertyName) const
|
||||
{
|
||||
|
||||
@@ -314,6 +314,10 @@ public:
|
||||
cmStringRange GetInstallIncludeDirectoriesEntries(
|
||||
cmTargetExport const& te) const;
|
||||
|
||||
//! Control if the target generates object files for module interfaces
|
||||
bool CxxModuleNeedsInterfaceObjects() const;
|
||||
void SetCxxModuleNeedsInterfaceObjects(bool);
|
||||
|
||||
BTs<std::string> const* GetLanguageStandardProperty(
|
||||
std::string const& propertyName) const;
|
||||
|
||||
|
||||
@@ -2,6 +2,11 @@ import std;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
// std::chrono::current_zone() references _Global_tzdb_list, which is
|
||||
// provided by std.ixx.obj on MSVC. Ensure we get a failed link if this
|
||||
// definition isn't available.
|
||||
static_cast<void>(std::chrono::current_zone());
|
||||
|
||||
if (argc > 0 && argv[0]) {
|
||||
std::string argv0 = argv[0];
|
||||
std::cout << "program: " << argv0 << std::endl;
|
||||
|
||||
Reference in New Issue
Block a user