cmCommonTargetGenerator: return forward linked target dirs too

This will be used for module forwarding in order to support
`$<TARGET_OBJECTS>` usage in source and link libraries calls.
This commit is contained in:
Ben Boeckel 2023-11-20 10:10:16 -05:00
parent f8729ab366
commit 06df59b930
4 changed files with 62 additions and 38 deletions

View File

@ -163,50 +163,65 @@ 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);
addLinkedTarget(item.Target, Forwarding::No);
}
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);
addLinkedTarget(target, Forwarding::Yes);
}
}
}

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);

View File

@ -1440,9 +1440,9 @@ 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";

View File

@ -1206,10 +1206,10 @@ 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"));
}
this->GetGlobalGenerator()->WriteBuild(this->GetImplFileStream(fileConfig),
@ -1909,7 +1909,9 @@ 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);
}