mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-07 06:40:16 -05:00
Merge topic 'fortran-objects-as-sources-fix' into release-3.28
beb1393f8fMerge branch 'revert-exact-collation-depends-3.27' into fortran-objects-as-sources-fixa033dce326Makefiles: provide, but do not consume, "forward linked" target dirs7cd0adab1bcmCommonTargetGenerator: use modules from linked object-referenced targets1175f1c874LinkItem: track `cmSourceFile` instances for external objectsd2fa56772fNinja: support "forwarding" modules from other targetsec1e589becNinja: Revert exact collation dependencies for 3.2706df59b930cmCommonTargetGenerator: return forward linked target dirs toof8729ab366cmLocalUnixMakefileGenerator3: handle object-referencing Fortran modules ... Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: buildbot <buildbot@kitware.com> Merge-request: !8989
This commit is contained in:
@@ -163,43 +163,77 @@ std::string cmCommonTargetGenerator::GetIncludes(std::string const& l,
|
||||
return i->second;
|
||||
}
|
||||
|
||||
std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories(
|
||||
cmCommonTargetGenerator::LinkedTargetDirs
|
||||
cmCommonTargetGenerator::GetLinkedTargetDirectories(
|
||||
const std::string& lang, const std::string& config) const
|
||||
{
|
||||
std::vector<std::string> dirs;
|
||||
std::set<cmGeneratorTarget const*> emitted;
|
||||
LinkedTargetDirs dirs;
|
||||
std::set<cmGeneratorTarget const*> forward_emitted;
|
||||
std::set<cmGeneratorTarget const*> direct_emitted;
|
||||
cmGlobalCommonGenerator* const gg = this->GlobalCommonGenerator;
|
||||
|
||||
enum class Forwarding
|
||||
{
|
||||
Yes,
|
||||
No
|
||||
};
|
||||
|
||||
if (cmComputeLinkInformation* cli =
|
||||
this->GeneratorTarget->GetLinkInformation(config)) {
|
||||
auto addLinkedTarget = [this, &lang, &config, &dirs, &emitted,
|
||||
gg](cmGeneratorTarget const* linkee) {
|
||||
if (linkee &&
|
||||
!linkee->IsImported()
|
||||
// Skip targets that build after this one in a static lib cycle.
|
||||
&& gg->TargetOrderIndexLess(linkee, this->GeneratorTarget)
|
||||
// We can ignore the INTERFACE_LIBRARY items because
|
||||
// Target->GetLinkInformation already processed their
|
||||
// link interface and they don't have any output themselves.
|
||||
&& (linkee->GetType() != cmStateEnums::INTERFACE_LIBRARY
|
||||
// Synthesized targets may have relevant rules.
|
||||
|| linkee->IsSynthetic()) &&
|
||||
((lang == "CXX"_s && linkee->HaveCxx20ModuleSources()) ||
|
||||
(lang == "Fortran"_s && linkee->HaveFortranSources(config))) &&
|
||||
emitted.insert(linkee).second) {
|
||||
cmLocalGenerator* lg = linkee->GetLocalGenerator();
|
||||
std::string di = cmStrCat(lg->GetCurrentBinaryDirectory(), '/',
|
||||
lg->GetTargetDirectory(linkee));
|
||||
if (lg->GetGlobalGenerator()->IsMultiConfig()) {
|
||||
di = cmStrCat(di, '/', config);
|
||||
auto addLinkedTarget =
|
||||
[this, &lang, &config, &dirs, &direct_emitted, &forward_emitted,
|
||||
gg](cmGeneratorTarget const* linkee, Forwarding forward) {
|
||||
if (linkee &&
|
||||
!linkee->IsImported()
|
||||
// Skip targets that build after this one in a static lib cycle.
|
||||
&& gg->TargetOrderIndexLess(linkee, this->GeneratorTarget)
|
||||
// We can ignore the INTERFACE_LIBRARY items because
|
||||
// Target->GetLinkInformation already processed their
|
||||
// link interface and they don't have any output themselves.
|
||||
&& (linkee->GetType() != cmStateEnums::INTERFACE_LIBRARY
|
||||
// Synthesized targets may have relevant rules.
|
||||
|| linkee->IsSynthetic()) &&
|
||||
((lang == "CXX"_s && linkee->HaveCxx20ModuleSources()) ||
|
||||
(lang == "Fortran"_s && linkee->HaveFortranSources(config)))) {
|
||||
cmLocalGenerator* lg = linkee->GetLocalGenerator();
|
||||
std::string di = cmStrCat(lg->GetCurrentBinaryDirectory(), '/',
|
||||
lg->GetTargetDirectory(linkee));
|
||||
if (lg->GetGlobalGenerator()->IsMultiConfig()) {
|
||||
di = cmStrCat(di, '/', config);
|
||||
}
|
||||
if (forward == Forwarding::Yes &&
|
||||
forward_emitted.insert(linkee).second) {
|
||||
dirs.Forward.push_back(di);
|
||||
}
|
||||
if (direct_emitted.insert(linkee).second) {
|
||||
dirs.Direct.emplace_back(di);
|
||||
}
|
||||
}
|
||||
dirs.push_back(std::move(di));
|
||||
}
|
||||
};
|
||||
};
|
||||
for (auto const& item : cli->GetItems()) {
|
||||
addLinkedTarget(item.Target);
|
||||
if (item.Target) {
|
||||
addLinkedTarget(item.Target, Forwarding::No);
|
||||
} else if (item.ObjectSource && lang == "Fortran"_s
|
||||
/* Object source files do not have a language associated with
|
||||
them. */
|
||||
/* && item.ObjectSource->GetLanguage() == "Fortran"_s*/) {
|
||||
// Fortran modules provided by `$<TARGET_OBJECTS>` as linked items
|
||||
// should be collated for use in this target.
|
||||
addLinkedTarget(this->LocalCommonGenerator->FindGeneratorTargetToUse(
|
||||
item.ObjectSource->GetObjectLibrary()),
|
||||
Forwarding::Yes);
|
||||
}
|
||||
}
|
||||
for (cmGeneratorTarget const* target : cli->GetExternalObjectTargets()) {
|
||||
addLinkedTarget(target);
|
||||
addLinkedTarget(target, Forwarding::No);
|
||||
}
|
||||
if (lang == "Fortran"_s) {
|
||||
// Fortran modules provided by `$<TARGET_OBJECTS>` as sources should be
|
||||
// collated for use in this target.
|
||||
for (cmGeneratorTarget const* target :
|
||||
this->GeneratorTarget->GetSourceObjectLibraries(config)) {
|
||||
addLinkedTarget(target, Forwarding::Yes);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dirs;
|
||||
|
||||
@@ -74,8 +74,15 @@ protected:
|
||||
|
||||
std::string GetCompilerLauncher(std::string const& lang,
|
||||
std::string const& config);
|
||||
std::vector<std::string> GetLinkedTargetDirectories(
|
||||
const std::string& lang, const std::string& config) const;
|
||||
|
||||
struct LinkedTargetDirs
|
||||
{
|
||||
std::vector<std::string> Direct;
|
||||
std::vector<std::string> Forward;
|
||||
};
|
||||
|
||||
LinkedTargetDirs GetLinkedTargetDirectories(const std::string& lang,
|
||||
const std::string& config) const;
|
||||
std::string ComputeTargetCompilePDB(const std::string& config) const;
|
||||
|
||||
std::string GetLinkerLauncher(const std::string& config);
|
||||
|
||||
@@ -515,6 +515,7 @@ void cmComputeLinkDepends::AddLinkObject(cmLinkItem const& item)
|
||||
LinkEntry& entry = this->EntryList[index];
|
||||
entry.Item = BT<std::string>(item.AsStr(), item.Backtrace);
|
||||
entry.Kind = LinkEntry::Object;
|
||||
entry.ObjectSource = item.ObjectSource;
|
||||
|
||||
// Record explicitly linked object files separately.
|
||||
this->ObjectEntries.emplace_back(index);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
class cmGeneratorTarget;
|
||||
class cmGlobalGenerator;
|
||||
class cmMakefile;
|
||||
class cmSourceFile;
|
||||
class cmake;
|
||||
|
||||
/** \class cmComputeLinkDepends
|
||||
@@ -63,6 +64,9 @@ public:
|
||||
|
||||
BT<std::string> Item;
|
||||
cmGeneratorTarget const* Target = nullptr;
|
||||
// The source file representing the external object (used when linking
|
||||
// `$<TARGET_OBJECTS>`)
|
||||
cmSourceFile const* ObjectSource = nullptr;
|
||||
EntryKind Kind = Library;
|
||||
// The following member is for the management of items specified
|
||||
// through genex $<LINK_LIBRARY:...>
|
||||
|
||||
@@ -1176,7 +1176,7 @@ void cmComputeLinkInformation::AddItem(LinkEntry const& entry)
|
||||
: cmStateEnums::RuntimeBinaryArtifact;
|
||||
std::string exe = tgt->GetFullPath(config, artifact, true);
|
||||
this->Items.emplace_back(
|
||||
BT<std::string>(exe, item.Backtrace), ItemIsPath::Yes, tgt,
|
||||
BT<std::string>(exe, item.Backtrace), ItemIsPath::Yes, tgt, nullptr,
|
||||
this->FindLibraryFeature(entry.Feature == DEFAULT
|
||||
? "__CMAKE_LINK_EXECUTABLE"
|
||||
: entry.Feature));
|
||||
@@ -1197,7 +1197,7 @@ void cmComputeLinkInformation::AddItem(LinkEntry const& entry)
|
||||
} else if (this->GlobalGenerator->IsXcode() &&
|
||||
!tgt->GetImportedXcFrameworkPath(config).empty()) {
|
||||
this->Items.emplace_back(
|
||||
tgt->GetImportedXcFrameworkPath(config), ItemIsPath::Yes, tgt,
|
||||
tgt->GetImportedXcFrameworkPath(config), ItemIsPath::Yes, tgt, nullptr,
|
||||
this->FindLibraryFeature(entry.Feature == DEFAULT
|
||||
? "__CMAKE_LINK_XCFRAMEWORK"
|
||||
: entry.Feature));
|
||||
@@ -1679,15 +1679,15 @@ void cmComputeLinkInformation::AddTargetItem(LinkEntry const& entry)
|
||||
if (isImportedFrameworkFolderOnApple) {
|
||||
if (entry.Feature == DEFAULT) {
|
||||
this->AddLibraryFeature("FRAMEWORK");
|
||||
this->Items.emplace_back(item, ItemIsPath::Yes, target,
|
||||
this->Items.emplace_back(item, ItemIsPath::Yes, target, nullptr,
|
||||
this->FindLibraryFeature("FRAMEWORK"));
|
||||
} else {
|
||||
this->Items.emplace_back(item, ItemIsPath::Yes, target,
|
||||
this->Items.emplace_back(item, ItemIsPath::Yes, target, nullptr,
|
||||
this->FindLibraryFeature(entry.Feature));
|
||||
}
|
||||
} else {
|
||||
this->Items.emplace_back(
|
||||
item, ItemIsPath::Yes, target,
|
||||
item, ItemIsPath::Yes, target, nullptr,
|
||||
this->FindLibraryFeature(entry.Feature == DEFAULT
|
||||
? "__CMAKE_LINK_FRAMEWORK"
|
||||
: entry.Feature));
|
||||
@@ -1695,17 +1695,17 @@ void cmComputeLinkInformation::AddTargetItem(LinkEntry const& entry)
|
||||
} else {
|
||||
if (cmHasSuffix(entry.Feature, "FRAMEWORK"_s)) {
|
||||
this->Items.emplace_back(fwDescriptor->GetLinkName(), ItemIsPath::Yes,
|
||||
target,
|
||||
target, nullptr,
|
||||
this->FindLibraryFeature(entry.Feature));
|
||||
} else if (entry.Feature == DEFAULT &&
|
||||
isImportedFrameworkFolderOnApple) {
|
||||
this->AddLibraryFeature("FRAMEWORK");
|
||||
this->Items.emplace_back(fwDescriptor->GetLinkName(), ItemIsPath::Yes,
|
||||
target,
|
||||
target, nullptr,
|
||||
this->FindLibraryFeature("FRAMEWORK"));
|
||||
} else {
|
||||
this->Items.emplace_back(
|
||||
item, ItemIsPath::Yes, target,
|
||||
item, ItemIsPath::Yes, target, nullptr,
|
||||
this->FindLibraryFeature(entry.Feature == DEFAULT
|
||||
? "__CMAKE_LINK_LIBRARY"
|
||||
: entry.Feature));
|
||||
@@ -1714,7 +1714,7 @@ void cmComputeLinkInformation::AddTargetItem(LinkEntry const& entry)
|
||||
} else {
|
||||
// Now add the full path to the library.
|
||||
this->Items.emplace_back(
|
||||
item, ItemIsPath::Yes, target,
|
||||
item, ItemIsPath::Yes, target, nullptr,
|
||||
this->FindLibraryFeature(
|
||||
entry.Feature == DEFAULT ? "__CMAKE_LINK_LIBRARY" : entry.Feature));
|
||||
}
|
||||
@@ -1774,7 +1774,7 @@ void cmComputeLinkInformation::AddFullItem(LinkEntry const& entry)
|
||||
|
||||
// Now add the full path to the library.
|
||||
this->Items.emplace_back(
|
||||
item, ItemIsPath::Yes, nullptr,
|
||||
item, ItemIsPath::Yes, nullptr, entry.ObjectSource,
|
||||
this->FindLibraryFeature(
|
||||
entry.Feature == DEFAULT
|
||||
? (entry.Kind == cmComputeLinkDepends::LinkEntry::Object
|
||||
@@ -2000,13 +2000,13 @@ void cmComputeLinkInformation::AddFrameworkItem(LinkEntry const& entry)
|
||||
if (this->GlobalGenerator->IsXcode()) {
|
||||
// Add framework path - it will be handled by Xcode after it's added to
|
||||
// "Link Binary With Libraries" build phase
|
||||
this->Items.emplace_back(item, ItemIsPath::Yes, nullptr,
|
||||
this->Items.emplace_back(item, ItemIsPath::Yes, nullptr, nullptr,
|
||||
this->FindLibraryFeature(entry.Feature == DEFAULT
|
||||
? "FRAMEWORK"
|
||||
: entry.Feature));
|
||||
} else {
|
||||
this->Items.emplace_back(
|
||||
fwDescriptor->GetLinkName(), ItemIsPath::Yes, nullptr,
|
||||
fwDescriptor->GetLinkName(), ItemIsPath::Yes, nullptr, nullptr,
|
||||
this->FindLibraryFeature(entry.Feature == DEFAULT ? "FRAMEWORK"
|
||||
: entry.Feature));
|
||||
}
|
||||
@@ -2024,7 +2024,7 @@ void cmComputeLinkInformation::AddXcFrameworkItem(LinkEntry const& entry)
|
||||
plist->SelectSuitableLibrary(*this->Makefile, entry.Item.Backtrace)) {
|
||||
if (this->GlobalGenerator->IsXcode()) {
|
||||
this->Items.emplace_back(
|
||||
entry.Item.Value, ItemIsPath::Yes, nullptr,
|
||||
entry.Item.Value, ItemIsPath::Yes, nullptr, nullptr,
|
||||
this->FindLibraryFeature(entry.Feature == DEFAULT
|
||||
? "__CMAKE_LINK_XCFRAMEWORK"
|
||||
: entry.Feature));
|
||||
|
||||
@@ -22,6 +22,7 @@ class cmGeneratorTarget;
|
||||
class cmGlobalGenerator;
|
||||
class cmMakefile;
|
||||
class cmOrderDirectories;
|
||||
class cmSourceFile;
|
||||
class cmake;
|
||||
|
||||
/** \class cmComputeLinkInformation
|
||||
@@ -51,16 +52,21 @@ public:
|
||||
{
|
||||
Item(BT<std::string> v, ItemIsPath isPath,
|
||||
cmGeneratorTarget const* target = nullptr,
|
||||
cmSourceFile const* objectSource = nullptr,
|
||||
FeatureDescriptor const* feature = nullptr)
|
||||
: Value(std::move(v))
|
||||
, IsPath(isPath)
|
||||
, Target(target)
|
||||
, ObjectSource(objectSource)
|
||||
, Feature(feature)
|
||||
{
|
||||
}
|
||||
BT<std::string> Value;
|
||||
ItemIsPath IsPath = ItemIsPath::No;
|
||||
cmGeneratorTarget const* Target = nullptr;
|
||||
// The source file representing the external object (used when linking
|
||||
// `$<TARGET_OBJECTS>`)
|
||||
cmSourceFile const* ObjectSource = nullptr;
|
||||
|
||||
bool HasFeature() const { return this->Feature != nullptr; }
|
||||
const std::string& GetFeatureName() const
|
||||
|
||||
@@ -258,6 +258,12 @@ bool cmDependsFortran::LocateModules()
|
||||
}
|
||||
this->MatchRemoteModules(fin, targetDir);
|
||||
}
|
||||
|
||||
// TODO: Use `CMAKE_Fortran_TARGET_FORWARD_LINKED_INFO_FILES` to handle cases
|
||||
// described in #25425. Note that because Makefiles generators do not
|
||||
// implement relaxed object compilation as described in #15555, the issues
|
||||
// never actually cause build failures; only incremental build incorrectness.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -6898,6 +6898,7 @@ void cmGeneratorTarget::ExpandLinkItems(
|
||||
cmSourceFile const* sf =
|
||||
mf->GetSource(maybeObj, cmSourceFileLocationKind::Known);
|
||||
if (sf && sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
|
||||
item.ObjectSource = sf;
|
||||
iface.Objects.emplace_back(std::move(item));
|
||||
continue;
|
||||
}
|
||||
@@ -8044,35 +8045,38 @@ void cmGeneratorTarget::GetLanguages(std::set<std::string>& languages,
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<cmGeneratorTarget*> objectLibraries;
|
||||
std::vector<cmSourceFile const*> externalObjects;
|
||||
std::set<cmGeneratorTarget const*> objectLibraries;
|
||||
if (!this->GlobalGenerator->GetConfigureDoneCMP0026()) {
|
||||
std::vector<cmGeneratorTarget*> objectTargets;
|
||||
this->GetObjectLibrariesCMP0026(objectTargets);
|
||||
objectLibraries.reserve(objectTargets.size());
|
||||
for (cmGeneratorTarget* gt : objectTargets) {
|
||||
objectLibraries.push_back(gt);
|
||||
objectLibraries.insert(gt);
|
||||
}
|
||||
} else {
|
||||
this->GetExternalObjects(externalObjects, config);
|
||||
for (cmSourceFile const* extObj : externalObjects) {
|
||||
std::string objLib = extObj->GetObjectLibrary();
|
||||
if (cmGeneratorTarget* tgt =
|
||||
this->LocalGenerator->FindGeneratorTargetToUse(objLib)) {
|
||||
auto const objLibIt =
|
||||
std::find_if(objectLibraries.cbegin(), objectLibraries.cend(),
|
||||
[tgt](cmGeneratorTarget* t) { return t == tgt; });
|
||||
if (objectLibraries.cend() == objLibIt) {
|
||||
objectLibraries.push_back(tgt);
|
||||
}
|
||||
}
|
||||
}
|
||||
objectLibraries = this->GetSourceObjectLibraries(config);
|
||||
}
|
||||
for (cmGeneratorTarget* objLib : objectLibraries) {
|
||||
for (cmGeneratorTarget const* objLib : objectLibraries) {
|
||||
objLib->GetLanguages(languages, config);
|
||||
}
|
||||
}
|
||||
|
||||
std::set<cmGeneratorTarget const*> cmGeneratorTarget::GetSourceObjectLibraries(
|
||||
std::string const& config) const
|
||||
{
|
||||
std::set<cmGeneratorTarget const*> objectLibraries;
|
||||
std::vector<cmSourceFile const*> externalObjects;
|
||||
this->GetExternalObjects(externalObjects, config);
|
||||
for (cmSourceFile const* extObj : externalObjects) {
|
||||
std::string objLib = extObj->GetObjectLibrary();
|
||||
if (cmGeneratorTarget* tgt =
|
||||
this->LocalGenerator->FindGeneratorTargetToUse(objLib)) {
|
||||
objectLibraries.insert(tgt);
|
||||
}
|
||||
}
|
||||
|
||||
return objectLibraries;
|
||||
}
|
||||
|
||||
bool cmGeneratorTarget::IsLanguageUsed(std::string const& language,
|
||||
std::string const& config) const
|
||||
{
|
||||
@@ -8486,6 +8490,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
|
||||
cmSourceFile const* sf =
|
||||
mf->GetSource(maybeObj, cmSourceFileLocationKind::Known);
|
||||
if (sf && sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
|
||||
item.ObjectSource = sf;
|
||||
impl.Objects.emplace_back(std::move(item));
|
||||
continue;
|
||||
}
|
||||
@@ -9087,19 +9092,47 @@ std::string cmGeneratorTarget::GetImportedXcFrameworkPath(
|
||||
bool cmGeneratorTarget::HaveFortranSources(std::string const& config) const
|
||||
{
|
||||
auto sources = this->GetSourceFiles(config);
|
||||
return std::any_of(sources.begin(), sources.end(),
|
||||
[](BT<cmSourceFile*> const& sf) -> bool {
|
||||
return sf.Value->GetLanguage() == "Fortran"_s;
|
||||
});
|
||||
bool const have_direct = std::any_of(
|
||||
sources.begin(), sources.end(), [](BT<cmSourceFile*> const& sf) -> bool {
|
||||
return sf.Value->GetLanguage() == "Fortran"_s;
|
||||
});
|
||||
bool have_via_target_objects = false;
|
||||
if (!have_direct) {
|
||||
auto const sourceObjectLibraries = this->GetSourceObjectLibraries(config);
|
||||
have_via_target_objects =
|
||||
std::any_of(sourceObjectLibraries.begin(), sourceObjectLibraries.end(),
|
||||
[&config](cmGeneratorTarget const* tgt) -> bool {
|
||||
return tgt->HaveFortranSources(config);
|
||||
});
|
||||
}
|
||||
return have_direct || have_via_target_objects;
|
||||
}
|
||||
|
||||
bool cmGeneratorTarget::HaveFortranSources() const
|
||||
{
|
||||
auto sources = cmGeneratorTarget::GetAllConfigSources();
|
||||
return std::any_of(sources.begin(), sources.end(),
|
||||
[](AllConfigSource const& sf) -> bool {
|
||||
return sf.Source->GetLanguage() == "Fortran"_s;
|
||||
});
|
||||
auto sources = this->GetAllConfigSources();
|
||||
bool const have_direct = std::any_of(
|
||||
sources.begin(), sources.end(), [](AllConfigSource const& sf) -> bool {
|
||||
return sf.Source->GetLanguage() == "Fortran"_s;
|
||||
});
|
||||
bool have_via_target_objects = false;
|
||||
if (!have_direct) {
|
||||
std::vector<std::string> configs =
|
||||
this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
|
||||
for (auto const& config : configs) {
|
||||
auto const sourceObjectLibraries =
|
||||
this->GetSourceObjectLibraries(config);
|
||||
have_via_target_objects =
|
||||
std::any_of(sourceObjectLibraries.begin(), sourceObjectLibraries.end(),
|
||||
[&config](cmGeneratorTarget const* tgt) -> bool {
|
||||
return tgt->HaveFortranSources(config);
|
||||
});
|
||||
if (have_via_target_objects) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return have_direct || have_via_target_objects;
|
||||
}
|
||||
|
||||
bool cmGeneratorTarget::HaveCxx20ModuleSources(std::string* errorMessage) const
|
||||
|
||||
@@ -463,6 +463,11 @@ public:
|
||||
bool IsLanguageUsed(std::string const& language,
|
||||
std::string const& config) const;
|
||||
|
||||
// Get the set of targets directly referenced via `TARGET_OBJECTS` in the
|
||||
// source list for a configuration.
|
||||
std::set<cmGeneratorTarget const*> GetSourceObjectLibraries(
|
||||
std::string const& config) const;
|
||||
|
||||
bool IsCSharpOnly() const;
|
||||
|
||||
bool IsDotNetSdkTarget() const;
|
||||
|
||||
@@ -2527,6 +2527,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
|
||||
std::string const& arg_dd, std::vector<std::string> const& arg_ddis,
|
||||
std::string const& module_dir,
|
||||
std::vector<std::string> const& linked_target_dirs,
|
||||
std::vector<std::string> const& forward_modules_from_target_dirs,
|
||||
std::string const& arg_lang, std::string const& arg_modmapfmt,
|
||||
cmCxxModuleExportInfo const& export_info)
|
||||
{
|
||||
@@ -2804,6 +2805,51 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
|
||||
// use by dependents that reference this target in linked-target-dirs.
|
||||
std::string const target_mods_file = cmStrCat(
|
||||
cmSystemTools::GetFilenamePath(arg_dd), '/', arg_lang, "Modules.json");
|
||||
|
||||
// Populate the module map with those provided by linked targets first.
|
||||
for (std::string const& forward_modules_from_target_dir :
|
||||
forward_modules_from_target_dirs) {
|
||||
std::string const fmftn =
|
||||
cmStrCat(forward_modules_from_target_dir, '/', arg_lang, "Modules.json");
|
||||
Json::Value fmft;
|
||||
cmsys::ifstream fmftf(fmftn.c_str(), std::ios::in | std::ios::binary);
|
||||
if (!fmftf) {
|
||||
cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to open ",
|
||||
fmftn, " for module information"));
|
||||
return false;
|
||||
}
|
||||
Json::Reader reader;
|
||||
if (!reader.parse(fmftf, fmft, false)) {
|
||||
cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
|
||||
forward_modules_from_target_dir,
|
||||
reader.getFormattedErrorMessages()));
|
||||
return false;
|
||||
}
|
||||
if (!fmft.isObject()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto forward_info = [](Json::Value& target, Json::Value const& source) {
|
||||
if (!source.isObject()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto i = source.begin(); i != source.end(); ++i) {
|
||||
std::string const key = i.key().asString();
|
||||
if (target.isMember(key)) {
|
||||
continue;
|
||||
}
|
||||
target[key] = *i;
|
||||
}
|
||||
};
|
||||
|
||||
// Forward info from forwarding targets into our collation.
|
||||
Json::Value& tmi_target_modules = target_module_info["modules"];
|
||||
forward_info(tmi_target_modules, fmft["modules"]);
|
||||
forward_info(target_references, fmft["references"]);
|
||||
forward_info(target_usages, fmft["usages"]);
|
||||
}
|
||||
|
||||
cmGeneratedFileStream tmf(target_mods_file);
|
||||
tmf << target_module_info;
|
||||
|
||||
@@ -2891,6 +2937,16 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
|
||||
linked_target_dirs.push_back(tdi_linked_target_dir.asString());
|
||||
}
|
||||
}
|
||||
std::vector<std::string> forward_modules_from_target_dirs;
|
||||
Json::Value const& tdi_forward_modules_from_target_dirs =
|
||||
tdi["forward-modules-from-target-dirs"];
|
||||
if (tdi_forward_modules_from_target_dirs.isArray()) {
|
||||
for (auto const& tdi_forward_modules_from_target_dir :
|
||||
tdi_forward_modules_from_target_dirs) {
|
||||
forward_modules_from_target_dirs.push_back(
|
||||
tdi_forward_modules_from_target_dir.asString());
|
||||
}
|
||||
}
|
||||
std::string const compilerId = tdi["compiler-id"].asString();
|
||||
std::string const simulateId = tdi["compiler-simulate-id"].asString();
|
||||
std::string const compilerFrontendVariant =
|
||||
@@ -2914,7 +2970,8 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
|
||||
# endif
|
||||
return gg.WriteDyndepFile(dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld,
|
||||
arg_dd, arg_ddis, module_dir, linked_target_dirs,
|
||||
arg_lang, arg_modmapfmt, *export_info)
|
||||
forward_modules_from_target_dirs, arg_lang,
|
||||
arg_modmapfmt, *export_info)
|
||||
? 0
|
||||
: 1;
|
||||
}
|
||||
|
||||
@@ -430,6 +430,7 @@ public:
|
||||
std::string const& arg_dd, std::vector<std::string> const& arg_ddis,
|
||||
std::string const& module_dir,
|
||||
std::vector<std::string> const& linked_target_dirs,
|
||||
std::vector<std::string> const& forward_modules_from_target_dirs,
|
||||
std::string const& arg_lang, std::string const& arg_modmapfmt,
|
||||
cmCxxModuleExportInfo const& export_info);
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "cmTargetLinkLibraryType.h"
|
||||
|
||||
class cmGeneratorTarget;
|
||||
class cmSourceFile;
|
||||
|
||||
// Basic information about each link item.
|
||||
class cmLinkItem
|
||||
@@ -29,6 +30,9 @@ public:
|
||||
cmLinkItem(cmGeneratorTarget const* t, bool c, cmListFileBacktrace bt);
|
||||
std::string const& AsStr() const;
|
||||
cmGeneratorTarget const* Target = nullptr;
|
||||
// The source file representing the external object (used when linking
|
||||
// `$<TARGET_OBJECTS>`)
|
||||
cmSourceFile const* ObjectSource = nullptr;
|
||||
bool Cross = false;
|
||||
cmListFileBacktrace Backtrace;
|
||||
friend bool operator<(cmLinkItem const& l, cmLinkItem const& r);
|
||||
|
||||
@@ -1899,6 +1899,11 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
|
||||
: "OFF")
|
||||
<< ")\n\n";
|
||||
|
||||
bool requireFortran = false;
|
||||
if (target->HaveFortranSources(this->GetConfigName())) {
|
||||
requireFortran = true;
|
||||
}
|
||||
|
||||
auto const& implicitLangs =
|
||||
this->GetImplicitDepends(target, cmDependencyScannerKind::CMake);
|
||||
|
||||
@@ -1908,6 +1913,12 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
|
||||
cmakefileStream << "set(CMAKE_DEPENDS_LANGUAGES\n";
|
||||
for (auto const& implicitLang : implicitLangs) {
|
||||
cmakefileStream << " \"" << implicitLang.first << "\"\n";
|
||||
if (requireFortran && implicitLang.first == "Fortran"_s) {
|
||||
requireFortran = false;
|
||||
}
|
||||
}
|
||||
if (requireFortran) {
|
||||
cmakefileStream << " \"Fortran\"\n";
|
||||
}
|
||||
cmakefileStream << " )\n";
|
||||
|
||||
|
||||
@@ -3630,6 +3630,9 @@ void cmMakefile::AddTargetObject(std::string const& tgtName,
|
||||
this->GetOrCreateSource(objFile, true, cmSourceFileLocationKind::Known);
|
||||
sf->SetObjectLibrary(tgtName);
|
||||
sf->SetProperty("EXTERNAL_OBJECT", "1");
|
||||
// TODO: Compute a language for this object based on the associated source
|
||||
// file that compiles to it. Needs a policy as it likely affects link
|
||||
// language selection if done unconditionally.
|
||||
#if !defined(CMAKE_BOOTSTRAP)
|
||||
this->SourceGroups[this->ObjectLibrariesSourceGroupIndex].AddGroupFile(
|
||||
sf->ResolveFullPath());
|
||||
|
||||
@@ -1440,9 +1440,20 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
|
||||
"# Targets to which this target links which contain Fortran sources.\n"
|
||||
"set(CMAKE_Fortran_TARGET_LINKED_INFO_FILES\n";
|
||||
/* clang-format on */
|
||||
std::vector<std::string> const dirs =
|
||||
auto const dirs =
|
||||
this->GetLinkedTargetDirectories("Fortran", this->GetConfigName());
|
||||
for (std::string const& d : dirs) {
|
||||
for (std::string const& d : dirs.Direct) {
|
||||
*this->InfoFileStream << " \"" << d << "/DependInfo.cmake\"\n";
|
||||
}
|
||||
*this->InfoFileStream << " )\n";
|
||||
|
||||
/* clang-format off */
|
||||
*this->InfoFileStream
|
||||
<< "\n"
|
||||
"# Targets to which this target links which contain Fortran sources.\n"
|
||||
"set(CMAKE_Fortran_TARGET_FORWARD_LINKED_INFO_FILES\n";
|
||||
/* clang-format on */
|
||||
for (std::string const& d : dirs.Forward) {
|
||||
*this->InfoFileStream << " \"" << d << "/DependInfo.cmake\"\n";
|
||||
}
|
||||
*this->InfoFileStream << " )\n";
|
||||
|
||||
@@ -1175,6 +1175,15 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
|
||||
}
|
||||
}
|
||||
|
||||
// Check if there are Fortran objects which need to participate in forwarding
|
||||
// module requirements.
|
||||
if (this->GeneratorTarget->HaveFortranSources(config) &&
|
||||
!this->Configs[config].ScanningInfo.count("Fortran")) {
|
||||
ScanningFiles files;
|
||||
this->Configs[config].ScanningInfo["Fortran"].emplace_back(files);
|
||||
this->WriteCompileRule("Fortran", config, WithScanning::Yes);
|
||||
}
|
||||
|
||||
for (auto const& langScanningFiles : this->Configs[config].ScanningInfo) {
|
||||
std::string const& language = langScanningFiles.first;
|
||||
std::vector<ScanningFiles> const& scanningFiles = langScanningFiles.second;
|
||||
@@ -1197,10 +1206,13 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
|
||||
|
||||
this->WriteTargetDependInfo(language, config);
|
||||
|
||||
for (std::string const& l :
|
||||
this->GetLinkedTargetDirectories(language, config)) {
|
||||
build.ImplicitDeps.emplace_back(
|
||||
cmStrCat(l, '/', language, "Modules.json"));
|
||||
auto const linked_directories =
|
||||
this->GetLinkedTargetDirectories(language, config);
|
||||
for (std::string const& l : linked_directories.Direct) {
|
||||
build.ImplicitDeps.push_back(cmStrCat(l, '/', language, "Modules.json"));
|
||||
}
|
||||
for (std::string const& l : linked_directories.Forward) {
|
||||
build.ImplicitDeps.push_back(cmStrCat(l, '/', language, "Modules.json"));
|
||||
}
|
||||
|
||||
this->GetGlobalGenerator()->WriteBuild(this->GetImplFileStream(fileConfig),
|
||||
@@ -1900,10 +1912,18 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
|
||||
|
||||
Json::Value& tdi_linked_target_dirs = tdi["linked-target-dirs"] =
|
||||
Json::arrayValue;
|
||||
for (std::string const& l : this->GetLinkedTargetDirectories(lang, config)) {
|
||||
auto const linked_directories =
|
||||
this->GetLinkedTargetDirectories(lang, config);
|
||||
for (std::string const& l : linked_directories.Direct) {
|
||||
tdi_linked_target_dirs.append(l);
|
||||
}
|
||||
|
||||
Json::Value& tdi_forward_modules_from_target_dirs =
|
||||
tdi["forward-modules-from-target-dirs"] = Json::arrayValue;
|
||||
for (std::string const& l : linked_directories.Forward) {
|
||||
tdi_forward_modules_from_target_dirs.append(l);
|
||||
}
|
||||
|
||||
cmDyndepGeneratorCallbacks cb;
|
||||
cb.ObjectFilePath = [this](cmSourceFile const* sf, std::string const& cnf) {
|
||||
return this->GetObjectFilePath(sf, cnf);
|
||||
|
||||
@@ -137,3 +137,9 @@ add_subdirectory(Issue25252-iface-sources)
|
||||
|
||||
add_subdirectory(Issue25365-target-objects)
|
||||
add_subdirectory(Issue25365-target-objects-iface)
|
||||
|
||||
# Issue#25425
|
||||
add_subdirectory(ModulesViaTargetObjectsSource)
|
||||
add_subdirectory(ModulesViaSubdirTargetObjectsSource)
|
||||
add_subdirectory(ModulesViaTargetObjectsLink)
|
||||
add_subdirectory(ModulesViaSubdirTargetObjectsLink)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
add_subdirectory(subdir)
|
||||
|
||||
add_library(mvstol_lib dummy.f90)
|
||||
target_link_libraries(mvstol_lib PRIVATE "$<TARGET_OBJECTS:mvstol_obj>")
|
||||
target_include_directories(mvstol_lib PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/subdir")
|
||||
add_library(mvstol_use use.f90)
|
||||
target_link_libraries(mvstol_use PRIVATE mvstol_lib)
|
||||
@@ -0,0 +1,3 @@
|
||||
pure real function dummy()
|
||||
dummy = 4*atan(1.)
|
||||
end function
|
||||
@@ -0,0 +1 @@
|
||||
add_library(mvstol_obj STATIC obj.f90)
|
||||
@@ -0,0 +1,11 @@
|
||||
module m1
|
||||
|
||||
implicit none
|
||||
|
||||
contains
|
||||
|
||||
pure real function pi()
|
||||
pi = 4*atan(1.)
|
||||
end function
|
||||
|
||||
end module m1
|
||||
@@ -0,0 +1,13 @@
|
||||
module lib
|
||||
|
||||
use m1, only : pi
|
||||
|
||||
implicit none
|
||||
|
||||
contains
|
||||
|
||||
pure real function func()
|
||||
func = pi()
|
||||
end function
|
||||
|
||||
end module
|
||||
@@ -0,0 +1,6 @@
|
||||
add_subdirectory(subdir)
|
||||
|
||||
add_library(mvstos_lib "$<TARGET_OBJECTS:mvstos_obj>")
|
||||
target_include_directories(mvstos_lib PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/subdir")
|
||||
add_library(mvstos_use use.f90)
|
||||
target_link_libraries(mvstos_use PRIVATE mvstos_lib)
|
||||
@@ -0,0 +1 @@
|
||||
add_library(mvstos_obj OBJECT obj.f90)
|
||||
@@ -0,0 +1,11 @@
|
||||
module m1
|
||||
|
||||
implicit none
|
||||
|
||||
contains
|
||||
|
||||
pure real function pi()
|
||||
pi = 4*atan(1.)
|
||||
end function
|
||||
|
||||
end module m1
|
||||
@@ -0,0 +1,13 @@
|
||||
module lib
|
||||
|
||||
use m1, only : pi
|
||||
|
||||
implicit none
|
||||
|
||||
contains
|
||||
|
||||
pure real function func()
|
||||
func = pi()
|
||||
end function
|
||||
|
||||
end module
|
||||
@@ -0,0 +1,5 @@
|
||||
add_library(mvtol_obj STATIC obj.f90)
|
||||
add_library(mvtol_lib dummy.f90)
|
||||
target_link_libraries(mvtol_lib PRIVATE "$<TARGET_OBJECTS:mvtol_obj>")
|
||||
add_library(mvtol_use use.f90)
|
||||
target_link_libraries(mvtol_use PRIVATE mvtol_lib)
|
||||
@@ -0,0 +1,3 @@
|
||||
pure real function dummy()
|
||||
dummy = 4*atan(1.)
|
||||
end function
|
||||
@@ -0,0 +1,11 @@
|
||||
module m1
|
||||
|
||||
implicit none
|
||||
|
||||
contains
|
||||
|
||||
pure real function pi()
|
||||
pi = 4*atan(1.)
|
||||
end function
|
||||
|
||||
end module m1
|
||||
@@ -0,0 +1,13 @@
|
||||
module lib
|
||||
|
||||
use m1, only : pi
|
||||
|
||||
implicit none
|
||||
|
||||
contains
|
||||
|
||||
pure real function func()
|
||||
func = pi()
|
||||
end function
|
||||
|
||||
end module
|
||||
@@ -0,0 +1,4 @@
|
||||
add_library(mvtos_obj OBJECT obj.f90)
|
||||
add_library(mvtos_lib "$<TARGET_OBJECTS:mvtos_obj>")
|
||||
add_library(mvtos_use use.f90)
|
||||
target_link_libraries(mvtos_use PRIVATE mvtos_lib)
|
||||
@@ -0,0 +1,11 @@
|
||||
module m1
|
||||
|
||||
implicit none
|
||||
|
||||
contains
|
||||
|
||||
pure real function pi()
|
||||
pi = 4*atan(1.)
|
||||
end function
|
||||
|
||||
end module m1
|
||||
@@ -0,0 +1,13 @@
|
||||
module lib
|
||||
|
||||
use m1, only : pi
|
||||
|
||||
implicit none
|
||||
|
||||
contains
|
||||
|
||||
pure real function func()
|
||||
func = pi()
|
||||
end function
|
||||
|
||||
end module
|
||||
@@ -45,6 +45,7 @@
|
||||
"exports": [],
|
||||
"include-dirs": [],
|
||||
"language": "CXX",
|
||||
"forward-modules-from-target-dirs": [],
|
||||
"linked-target-dirs": [],
|
||||
"module-dir": "<BINARY_DIR>/CMakeFiles/ninja-bmi-install-private.dir<CONFIG_DIR>"
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"exports": [],
|
||||
"include-dirs": [],
|
||||
"language": "CXX",
|
||||
"forward-modules-from-target-dirs": [],
|
||||
"linked-target-dirs": [],
|
||||
"module-dir": "<BINARY_DIR>/CMakeFiles/ninja-bmi-install-public.dir<CONFIG_DIR>"
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
],
|
||||
"include-dirs": [],
|
||||
"language": "CXX",
|
||||
"forward-modules-from-target-dirs": [],
|
||||
"linked-target-dirs": [],
|
||||
"module-dir": "<BINARY_DIR>/CMakeFiles/ninja-exports-private.dir<CONFIG_DIR>"
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
],
|
||||
"include-dirs": [],
|
||||
"language": "CXX",
|
||||
"forward-modules-from-target-dirs": [],
|
||||
"linked-target-dirs": [],
|
||||
"module-dir": "<BINARY_DIR>/CMakeFiles/ninja-exports-public.dir<CONFIG_DIR>"
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
"exports": [],
|
||||
"include-dirs": [],
|
||||
"language": "CXX",
|
||||
"forward-modules-from-target-dirs": [],
|
||||
"linked-target-dirs": [],
|
||||
"module-dir": "<BINARY_DIR>/CMakeFiles/ninja-file-sets-private.dir<CONFIG_DIR>"
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
"exports": [],
|
||||
"include-dirs": [],
|
||||
"language": "CXX",
|
||||
"forward-modules-from-target-dirs": [],
|
||||
"linked-target-dirs": [],
|
||||
"module-dir": "<BINARY_DIR>/CMakeFiles/ninja-file-sets-public.dir<CONFIG_DIR>"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user