123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845 |
- #include "cmComputeLinkDepends.h"
- #include "cmAlgorithms.h"
- #include "cmComputeComponentGraph.h"
- #include "cmGeneratorTarget.h"
- #include "cmGlobalGenerator.h"
- #include "cmLocalGenerator.h"
- #include "cmMakefile.h"
- #include "cmStateTypes.h"
- #include "cmSystemTools.h"
- #include "cmTarget.h"
- #include "cmake.h"
- #include <algorithm>
- #include <assert.h>
- #include <iterator>
- #include <sstream>
- #include <stdio.h>
- #include <string.h>
- #include <utility>
- cmComputeLinkDepends::cmComputeLinkDepends(const cmGeneratorTarget* target,
- const std::string& config)
- {
-
- this->Target = target;
- this->Makefile = this->Target->Target->GetMakefile();
- this->GlobalGenerator =
- this->Target->GetLocalGenerator()->GetGlobalGenerator();
- this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance();
-
- this->HasConfig = !config.empty();
- this->Config = (this->HasConfig) ? config : std::string();
- std::vector<std::string> debugConfigs =
- this->Makefile->GetCMakeInstance()->GetDebugConfigs();
- this->LinkType = CMP0003_ComputeLinkType(this->Config, debugConfigs);
-
- this->DebugMode = this->Makefile->IsOn("CMAKE_LINK_DEPENDS_DEBUG_MODE");
-
- this->OldLinkDirMode = false;
-
- this->CCG = nullptr;
- }
- cmComputeLinkDepends::~cmComputeLinkDepends()
- {
- cmDeleteAll(this->InferredDependSets);
- delete this->CCG;
- }
- void cmComputeLinkDepends::SetOldLinkDirMode(bool b)
- {
- this->OldLinkDirMode = b;
- }
- std::vector<cmComputeLinkDepends::LinkEntry> const&
- cmComputeLinkDepends::Compute()
- {
-
- this->AddDirectLinkEntries();
-
- while (!this->BFSQueue.empty()) {
-
- BFSEntry qe = this->BFSQueue.front();
- this->BFSQueue.pop();
-
- this->FollowLinkEntry(qe);
- }
-
- while (!this->SharedDepQueue.empty()) {
-
- this->HandleSharedDependency(this->SharedDepQueue.front());
- this->SharedDepQueue.pop();
- }
-
- this->InferDependencies();
-
- this->CleanConstraintGraph();
-
- if (this->DebugMode) {
- fprintf(stderr, "---------------------------------------"
- "---------------------------------------\n");
- fprintf(stderr, "Link dependency analysis for target %s, config %s\n",
- this->Target->GetName().c_str(),
- this->HasConfig ? this->Config.c_str() : "noconfig");
- this->DisplayConstraintGraph();
- }
-
- this->OrderLinkEntires();
-
-
-
- std::set<int> emmitted;
- for (std::vector<int>::const_reverse_iterator
- li = this->FinalLinkOrder.rbegin(),
- le = this->FinalLinkOrder.rend();
- li != le; ++li) {
- int i = *li;
- LinkEntry const& e = this->EntryList[i];
- cmGeneratorTarget const* t = e.Target;
-
- bool uniquify = t && t->GetType() == cmStateEnums::SHARED_LIBRARY;
- if (!uniquify || emmitted.insert(i).second) {
- this->FinalLinkEntries.push_back(e);
- }
- }
-
- std::reverse(this->FinalLinkEntries.begin(), this->FinalLinkEntries.end());
-
- if (this->DebugMode) {
- this->DisplayFinalEntries();
- }
- return this->FinalLinkEntries;
- }
- std::map<std::string, int>::iterator cmComputeLinkDepends::AllocateLinkEntry(
- std::string const& item)
- {
- std::map<std::string, int>::value_type index_entry(
- item, static_cast<int>(this->EntryList.size()));
- std::map<std::string, int>::iterator lei =
- this->LinkEntryIndex.insert(index_entry).first;
- this->EntryList.emplace_back();
- this->InferredDependSets.push_back(nullptr);
- this->EntryConstraintGraph.emplace_back();
- return lei;
- }
- int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item)
- {
-
- std::map<std::string, int>::iterator lei = this->LinkEntryIndex.find(item);
- if (lei != this->LinkEntryIndex.end()) {
-
- return lei->second;
- }
-
- lei = this->AllocateLinkEntry(item);
-
- int index = lei->second;
- LinkEntry& entry = this->EntryList[index];
- entry.Item = item;
- entry.Target = item.Target;
- entry.IsFlag = (!entry.Target && item[0] == '-' && item[1] != 'l' &&
- item.substr(0, 10) != "-framework");
-
- if (entry.Target) {
-
- BFSEntry qe = { index, nullptr };
- this->BFSQueue.push(qe);
- } else {
-
- std::string var = entry.Item;
- var += "_LIB_DEPENDS";
- if (const char* val = this->Makefile->GetDefinition(var)) {
-
- BFSEntry qe = { index, val };
- this->BFSQueue.push(qe);
- } else if (!entry.IsFlag) {
-
- this->InferredDependSets[index] = new DependSetList;
- }
- }
- return index;
- }
- void cmComputeLinkDepends::FollowLinkEntry(BFSEntry qe)
- {
-
- int depender_index = qe.Index;
- LinkEntry const& entry = this->EntryList[depender_index];
-
- if (entry.Target) {
-
- if (cmLinkInterface const* iface =
- entry.Target->GetLinkInterface(this->Config, this->Target)) {
- const bool isIface =
- entry.Target->GetType() == cmStateEnums::INTERFACE_LIBRARY;
-
- this->AddLinkEntries(depender_index, iface->Libraries);
- if (isIface) {
- return;
- }
-
- this->FollowSharedDeps(depender_index, iface);
-
- for (cmLinkItem const& oi : iface->WrongConfigLibraries) {
- this->CheckWrongConfigItem(oi);
- }
- }
- } else {
-
- this->AddVarLinkEntries(depender_index, qe.LibDepends);
- }
- }
- void cmComputeLinkDepends::FollowSharedDeps(int depender_index,
- cmLinkInterface const* iface,
- bool follow_interface)
- {
-
- if (this->SharedDepFollowed.insert(depender_index).second) {
- if (follow_interface) {
- this->QueueSharedDependencies(depender_index, iface->Libraries);
- }
- this->QueueSharedDependencies(depender_index, iface->SharedDeps);
- }
- }
- void cmComputeLinkDepends::QueueSharedDependencies(
- int depender_index, std::vector<cmLinkItem> const& deps)
- {
- for (cmLinkItem const& li : deps) {
- SharedDepEntry qe;
- qe.Item = li;
- qe.DependerIndex = depender_index;
- this->SharedDepQueue.push(qe);
- }
- }
- void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
- {
-
- std::map<std::string, int>::iterator lei =
- this->LinkEntryIndex.find(dep.Item);
- if (lei == this->LinkEntryIndex.end()) {
-
- lei = this->AllocateLinkEntry(dep.Item);
-
- LinkEntry& entry = this->EntryList[lei->second];
- entry.Item = dep.Item;
- entry.Target = dep.Item.Target;
-
-
-
- entry.IsSharedDep = true;
- }
-
- int index = lei->second;
- LinkEntry& entry = this->EntryList[index];
-
-
- this->EntryConstraintGraph[dep.DependerIndex].push_back(index);
-
- if (entry.Target) {
- if (cmLinkInterface const* iface =
- entry.Target->GetLinkInterface(this->Config, this->Target)) {
-
- this->FollowSharedDeps(index, iface, true);
- }
- }
- }
- void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
- const char* value)
- {
-
-
-
- std::vector<std::string> deplist;
- cmSystemTools::ExpandListArgument(value, deplist);
-
- std::vector<cmLinkItem> actual_libs;
- cmTargetLinkLibraryType llt = GENERAL_LibraryType;
- bool haveLLT = false;
- for (std::string const& d : deplist) {
- if (d == "debug") {
- llt = DEBUG_LibraryType;
- haveLLT = true;
- } else if (d == "optimized") {
- llt = OPTIMIZED_LibraryType;
- haveLLT = true;
- } else if (d == "general") {
- llt = GENERAL_LibraryType;
- haveLLT = true;
- } else if (!d.empty()) {
-
-
-
-
-
- if (!haveLLT) {
- std::string var = d;
- var += "_LINK_TYPE";
- if (const char* val = this->Makefile->GetDefinition(var)) {
- if (strcmp(val, "debug") == 0) {
- llt = DEBUG_LibraryType;
- } else if (strcmp(val, "optimized") == 0) {
- llt = OPTIMIZED_LibraryType;
- }
- }
- }
-
- if (llt == GENERAL_LibraryType || llt == this->LinkType) {
- actual_libs.emplace_back(d, this->FindTargetToLink(depender_index, d));
- } else if (this->OldLinkDirMode) {
- cmLinkItem item(d, this->FindTargetToLink(depender_index, d));
- this->CheckWrongConfigItem(item);
- }
-
- llt = GENERAL_LibraryType;
- haveLLT = false;
- }
- }
-
- this->AddLinkEntries(depender_index, actual_libs);
- }
- void cmComputeLinkDepends::AddDirectLinkEntries()
- {
-
- cmLinkImplementation const* impl =
- this->Target->GetLinkImplementation(this->Config);
- this->AddLinkEntries(-1, impl->Libraries);
- for (cmLinkItem const& wi : impl->WrongConfigLibraries) {
- this->CheckWrongConfigItem(wi);
- }
- }
- template <typename T>
- void cmComputeLinkDepends::AddLinkEntries(int depender_index,
- std::vector<T> const& libs)
- {
-
- std::map<int, DependSet> dependSets;
-
- for (T const& l : libs) {
-
-
- cmLinkItem const& item = l;
- if (item == this->Target->GetName() || item.empty()) {
- continue;
- }
-
- int dependee_index = this->AddLinkEntry(l);
-
- if (depender_index >= 0) {
- this->EntryConstraintGraph[depender_index].push_back(dependee_index);
- } else {
-
- this->OriginalEntries.push_back(dependee_index);
- }
-
- for (auto& dependSet : dependSets) {
-
-
-
-
- if (!this->EntryList[dependee_index].Target &&
- !this->EntryList[dependee_index].IsFlag &&
- dependee_index != dependSet.first) {
- dependSet.second.insert(dependee_index);
- }
- }
-
- if (this->InferredDependSets[dependee_index]) {
-
- dependSets[dependee_index];
- }
- }
-
- for (auto const& dependSet : dependSets) {
- this->InferredDependSets[dependSet.first]->push_back(dependSet.second);
- }
- }
- cmGeneratorTarget const* cmComputeLinkDepends::FindTargetToLink(
- int depender_index, const std::string& name)
- {
-
- cmGeneratorTarget const* from = this->Target;
- if (depender_index >= 0) {
- if (cmGeneratorTarget const* depender =
- this->EntryList[depender_index].Target) {
- from = depender;
- }
- }
- return from->FindTargetToLink(name);
- }
- void cmComputeLinkDepends::InferDependencies()
- {
-
-
-
- for (unsigned int depender_index = 0;
- depender_index < this->InferredDependSets.size(); ++depender_index) {
-
-
- DependSetList* sets = this->InferredDependSets[depender_index];
- if (!sets || sets->empty()) {
- continue;
- }
-
- DependSetList::const_iterator i = sets->begin();
- DependSet common = *i;
- for (++i; i != sets->end(); ++i) {
- DependSet intersection;
- std::set_intersection(common.begin(), common.end(), i->begin(), i->end(),
- std::inserter(intersection, intersection.begin()));
- common = intersection;
- }
-
- cmGraphEdgeList& edges = this->EntryConstraintGraph[depender_index];
- edges.insert(edges.end(), common.begin(), common.end());
- }
- }
- void cmComputeLinkDepends::CleanConstraintGraph()
- {
- for (cmGraphEdgeList& edgeList : this->EntryConstraintGraph) {
-
-
- std::sort(edgeList.begin(), edgeList.end());
-
- edgeList.erase(std::unique(edgeList.begin(), edgeList.end()),
- edgeList.end());
- }
- }
- void cmComputeLinkDepends::DisplayConstraintGraph()
- {
-
- std::ostringstream e;
- for (unsigned int i = 0; i < this->EntryConstraintGraph.size(); ++i) {
- EdgeList const& nl = this->EntryConstraintGraph[i];
- e << "item " << i << " is [" << this->EntryList[i].Item << "]\n";
- e << cmWrap(" item ", nl, " must follow it", "\n") << "\n";
- }
- fprintf(stderr, "%s\n", e.str().c_str());
- }
- void cmComputeLinkDepends::OrderLinkEntires()
- {
-
-
-
-
-
- this->CCG = new cmComputeComponentGraph(this->EntryConstraintGraph);
-
-
-
- Graph const& cgraph = this->CCG->GetComponentGraph();
- int n = static_cast<int>(cgraph.size());
- this->ComponentVisited.resize(cgraph.size(), 0);
- this->ComponentOrder.resize(cgraph.size(), n);
- this->ComponentOrderId = n;
-
-
- for (int c = n - 1; c >= 0; --c) {
- this->VisitComponent(c);
- }
-
- if (this->DebugMode) {
- this->DisplayComponents();
- }
-
- for (int originalEntry : this->OriginalEntries) {
- this->VisitEntry(originalEntry);
- }
-
-
- while (!this->PendingComponents.empty()) {
-
-
-
-
- int e = *this->PendingComponents.begin()->second.Entries.begin();
- this->VisitEntry(e);
- }
- }
- void cmComputeLinkDepends::DisplayComponents()
- {
- fprintf(stderr, "The strongly connected components are:\n");
- std::vector<NodeList> const& components = this->CCG->GetComponents();
- for (unsigned int c = 0; c < components.size(); ++c) {
- fprintf(stderr, "Component (%u):\n", c);
- NodeList const& nl = components[c];
- for (int i : nl) {
- fprintf(stderr, " item %d [%s]\n", i, this->EntryList[i].Item.c_str());
- }
- EdgeList const& ol = this->CCG->GetComponentGraphEdges(c);
- for (cmGraphEdge const& oi : ol) {
- int i = oi;
- fprintf(stderr, " followed by Component (%d)\n", i);
- }
- fprintf(stderr, " topo order index %d\n", this->ComponentOrder[c]);
- }
- fprintf(stderr, "\n");
- }
- void cmComputeLinkDepends::VisitComponent(unsigned int c)
- {
-
- if (this->ComponentVisited[c]) {
- return;
- }
-
- this->ComponentVisited[c] = 1;
-
-
-
- EdgeList const& nl = this->CCG->GetComponentGraphEdges(c);
- for (EdgeList::const_reverse_iterator ni = nl.rbegin(); ni != nl.rend();
- ++ni) {
- this->VisitComponent(*ni);
- }
-
- this->ComponentOrder[c] = --this->ComponentOrderId;
- }
- void cmComputeLinkDepends::VisitEntry(int index)
- {
-
- this->FinalLinkOrder.push_back(index);
-
- bool completed = false;
- int component = this->CCG->GetComponentMap()[index];
- std::map<int, PendingComponent>::iterator mi =
- this->PendingComponents.find(this->ComponentOrder[component]);
- if (mi != this->PendingComponents.end()) {
-
- PendingComponent& pc = mi->second;
-
- pc.Entries.erase(index);
- if (pc.Entries.empty()) {
-
- --pc.Count;
- if (pc.Count == 0) {
-
- this->PendingComponents.erase(mi);
- completed = true;
- } else {
-
- NodeList const& nl = this->CCG->GetComponent(component);
- assert(nl.size() > 1);
- pc.Entries.insert(nl.begin(), nl.end());
- }
- }
- } else {
-
- NodeList const& nl = this->CCG->GetComponent(component);
- if (nl.size() > 1) {
-
- PendingComponent& pc = this->MakePendingComponent(component);
-
- pc.Entries.erase(index);
- } else {
-
- completed = true;
- }
- }
-
-
- if (completed) {
- EdgeList const& ol = this->CCG->GetComponentGraphEdges(component);
- for (cmGraphEdge const& oi : ol) {
-
-
- this->MakePendingComponent(oi);
- }
- }
- }
- cmComputeLinkDepends::PendingComponent&
- cmComputeLinkDepends::MakePendingComponent(unsigned int component)
- {
-
- PendingComponent& pc =
- this->PendingComponents[this->ComponentOrder[component]];
- pc.Id = component;
- NodeList const& nl = this->CCG->GetComponent(component);
- if (nl.size() == 1) {
-
- pc.Count = 1;
- } else {
-
-
-
-
-
-
-
-
-
-
-
-
- pc.Count = this->ComputeComponentCount(nl);
- }
-
- pc.Entries.insert(nl.begin(), nl.end());
- return pc;
- }
- int cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl)
- {
- unsigned int count = 2;
- for (int ni : nl) {
- if (cmGeneratorTarget const* target = this->EntryList[ni].Target) {
- if (cmLinkInterface const* iface =
- target->GetLinkInterface(this->Config, this->Target)) {
- if (iface->Multiplicity > count) {
- count = iface->Multiplicity;
- }
- }
- }
- }
- return count;
- }
- void cmComputeLinkDepends::DisplayFinalEntries()
- {
- fprintf(stderr, "target [%s] links to:\n", this->Target->GetName().c_str());
- for (LinkEntry const& lei : this->FinalLinkEntries) {
- if (lei.Target) {
- fprintf(stderr, " target [%s]\n", lei.Target->GetName().c_str());
- } else {
- fprintf(stderr, " item [%s]\n", lei.Item.c_str());
- }
- }
- fprintf(stderr, "\n");
- }
- void cmComputeLinkDepends::CheckWrongConfigItem(cmLinkItem const& item)
- {
- if (!this->OldLinkDirMode) {
- return;
- }
-
-
-
- if (item.Target && !item.Target->IsImported()) {
- this->OldWrongConfigItems.insert(item.Target);
- }
- }
|