blob: ca574d4a5a0c0d960a74deefa52e88fae518ed65 [file] [log] [blame]
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLinkItemGraphVisitor.h"
#include <map>
#include <utility>
#include <vector>
#include "cmGeneratorTarget.h"
#include "cmLinkItem.h"
#include "cmMakefile.h"
void cmLinkItemGraphVisitor::VisitItem(cmLinkItem const& item)
{
if (this->ItemVisited(item)) {
return;
}
this->OnItem(item);
this->VisitLinks(item, item);
}
void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item,
cmLinkItem const& rootItem)
{
if (!item.Target) {
return;
}
for (auto const& config : item.Target->Makefile->GetGeneratorConfigs(
cmMakefile::IncludeEmptyConfig)) {
this->VisitLinks(item, rootItem, config);
}
}
void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item,
cmLinkItem const& rootItem,
std::string const& config)
{
auto const& target = *item.Target;
DependencyMap dependencies;
cmLinkItemGraphVisitor::GetDependencies(target, config, dependencies);
for (auto const& d : dependencies) {
auto const& dependency = d.second;
auto const& dependencyType = dependency.first;
auto const& dependee = dependency.second;
this->VisitItem(dependee);
if (this->LinkVisited(item, dependee)) {
continue;
}
this->OnDirectLink(item, dependee, dependencyType);
if (rootItem.AsStr() != item.AsStr()) {
this->OnIndirectLink(rootItem, dependee);
}
// Visit all the direct and indirect links.
this->VisitLinks(dependee, dependee);
this->VisitLinks(dependee, item);
this->VisitLinks(dependee, rootItem);
}
}
bool cmLinkItemGraphVisitor::ItemVisited(cmLinkItem const& item)
{
auto& collection = this->VisitedItems;
bool const visited = collection.find(item.AsStr()) != collection.cend();
if (!visited) {
collection.insert(item.AsStr());
}
return visited;
}
bool cmLinkItemGraphVisitor::LinkVisited(cmLinkItem const& depender,
cmLinkItem const& dependee)
{
auto const link = std::make_pair(depender.AsStr(), dependee.AsStr());
bool const linkVisited =
this->VisitedLinks.find(link) != this->VisitedLinks.cend();
if (!linkVisited) {
this->VisitedLinks.insert(link);
}
return linkVisited;
}
void cmLinkItemGraphVisitor::GetDependencies(cmGeneratorTarget const& target,
std::string const& config,
DependencyMap& dependencies)
{
const auto* implementationLibraries = target.GetLinkImplementationLibraries(
config, cmGeneratorTarget::UseTo::Link);
if (implementationLibraries) {
for (auto const& lib : implementationLibraries->Libraries) {
auto const& name = lib.AsStr();
dependencies[name] = Dependency(DependencyType::LinkPrivate, lib);
}
}
const auto* interfaceLibraries = target.GetLinkInterfaceLibraries(
config, &target, cmGeneratorTarget::UseTo::Compile);
if (interfaceLibraries) {
for (auto const& lib : interfaceLibraries->Libraries) {
auto const& name = lib.AsStr();
if (dependencies.find(name) != dependencies.cend()) {
dependencies[name] = Dependency(DependencyType::LinkPublic, lib);
} else {
dependencies[name] = Dependency(DependencyType::LinkInterface, lib);
}
}
}
std::vector<cmGeneratorTarget*> objectLibraries;
target.GetObjectLibrariesCMP0026(objectLibraries);
for (auto const& lib : objectLibraries) {
auto const& name = lib->GetName();
if (dependencies.find(name) == dependencies.cend()) {
auto objectItem = cmLinkItem(lib, false, lib->GetBacktrace());
dependencies[name] = Dependency(DependencyType::Object, objectItem);
}
}
auto const& utilityItems = target.GetUtilityItems();
for (auto const& item : utilityItems) {
auto const& name = item.AsStr();
if (dependencies.find(name) == dependencies.cend()) {
dependencies[name] = Dependency(DependencyType::Utility, item);
}
}
}