Merge topic 'fortran-objects-as-sources-fix' into release-3.28

beb1393f8f Merge branch 'revert-exact-collation-depends-3.27' into fortran-objects-as-sources-fix
a033dce326 Makefiles: provide, but do not consume, "forward linked" target dirs
7cd0adab1b cmCommonTargetGenerator: use modules from linked object-referenced targets
1175f1c874 LinkItem: track `cmSourceFile` instances for external objects
d2fa56772f Ninja: support "forwarding" modules from other targets
ec1e589bec Ninja: Revert exact collation dependencies for 3.27
06df59b930 cmCommonTargetGenerator: return forward linked target dirs too
f8729ab366 cmLocalUnixMakefileGenerator3: 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:
Brad King
2023-11-27 13:36:28 +00:00
committed by Kitware Robot
39 changed files with 419 additions and 78 deletions
+62 -28
View File
@@ -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;
+9 -2
View File
@@ -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);
+1
View File
@@ -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);
+4
View File
@@ -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:...>
+13 -13
View File
@@ -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));
+6
View File
@@ -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
+6
View File
@@ -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;
}
+60 -27
View File
@@ -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
+5
View File
@@ -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;
+58 -1
View File
@@ -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;
}
+1
View File
@@ -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);
+4
View File
@@ -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);
+11
View File
@@ -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";
+3
View File
@@ -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());
+13 -2
View File
@@ -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";
+25 -5
View File
@@ -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);
+6
View File
@@ -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>"
}