-#include <algorithm>
+#include <msp/core/algorithm.h>
#include <msp/fs/utils.h>
#include <msp/strings/format.h>
#include <msp/strings/utils.h>
if(!component)
return;
- list<Target *> queue;
- list<Target *> dep_libs;
- set<string> missing_libs;
- queue.push_back(this);
- for(auto j=queue.begin(); j!=queue.end(); ++j)
+ vector<Target *> static_libs;
+ vector<Target *> shared_libs;
+ vector<string> missing_libs;
+ find_dependencies(this, static_libs, shared_libs, missing_libs);
+
+ for(Target *t: static_libs)
+ add_dependency(*t);
+ for(Target *t: shared_libs)
+ add_dependency(*t);
+ for(const string &m: missing_libs)
+ problems.push_back(format("Required library %s not found", m));
+}
+
+void Binary::find_dependencies(Target *tgt, vector<Target *> &static_libs, vector<Target *> &shared_libs, vector<string> &missing_libs)
+{
+ BuildInfo binfo;
+ tgt->collect_build_info(binfo);
+ if(tgt!=this)
{
- Target *tgt = *j;
+ static_binfo.libpath.insert(static_binfo.libpath.end(), binfo.libpath.begin(), binfo.libpath.end());
+ static_binfo.keep_symbols.insert(static_binfo.keep_symbols.end(), binfo.keep_symbols.begin(), binfo.keep_symbols.end());
+ if(binfo.threads)
+ static_binfo.threads = true;
+ }
- BuildInfo binfo;
- tgt->collect_build_info(binfo);
- if(tgt!=this)
- {
- static_binfo.libpath.insert(static_binfo.libpath.end(), binfo.libpath.begin(), binfo.libpath.end());
- static_binfo.keep_symbols.insert(static_binfo.keep_symbols.end(), binfo.keep_symbols.begin(), binfo.keep_symbols.end());
- if(binfo.threads)
- static_binfo.threads = true;
- }
+ for(const string &l: binfo.libs)
+ {
+ if(l.size()>10 && !l.compare(l.size()-10, 10, ".framework"))
+ continue;
- auto insert_pos = j;
- ++insert_pos;
- for(const string &l: binfo.libs)
+ BuildInfo::LibraryMode libmode = component->get_build_info().get_libmode_for(l);
+ Target *lib = builder.get_vfs().find_library(l, binfo.libpath, libmode);
+ if(lib)
{
- if(l.size()>10 && !l.compare(l.size()-10, 10, ".framework"))
- continue;
-
- BuildInfo::LibraryMode libmode = component->get_build_info().get_libmode_for(l);
- Target *lib = builder.get_vfs().find_library(l, binfo.libpath, libmode);
- if(lib)
+ Target *real = lib->get_real_target();
+ if(StaticLibrary *stlib = dynamic_cast<StaticLibrary *>(real))
{
- Target *real = lib->get_real_target();
- if(StaticLibrary *stlib = dynamic_cast<StaticLibrary *>(real))
- queue.insert(insert_pos, stlib);
- else
- dep_libs.push_back(lib);
+ /* Keep only the last occurrence of each static library. This
+ ensures the order is correct for linking. */
+ auto i = find(static_libs, stlib);
+ if(i!=static_libs.end())
+ static_libs.erase(i);
+ static_libs.push_back(stlib);
+ find_dependencies(stlib, static_libs, shared_libs, missing_libs);
}
- else if(missing_libs.insert(l).second)
- problems.push_back(format("Required library %s not found", l));
+ else if(!any_equals(shared_libs, lib))
+ shared_libs.push_back(lib);
}
+ else if(!any_equals(missing_libs, l))
+ missing_libs.push_back(l);
}
-
- queue.pop_front();
- dep_libs.splice(dep_libs.begin(), queue);
-
- /* Add only the last occurrence of each library to the actual dependencies.
- This ensures that static library ordering is correct. */
- for(auto i=dep_libs.begin(); i!=dep_libs.end(); ++i)
- if(!any_of(next(i), dep_libs.end(), [i](Target *d){ return d==*i; }))
- add_dependency(**i);
}
protected:
void find_dependencies() override;
+private:
+ void find_dependencies(Target *, std::vector<Target *> &, std::vector<Target *> &, std::vector<std::string> &);
};
#endif
+#include <deque>
#include <msp/core/algorithm.h>
#include <msp/fs/dir.h>
#include <msp/fs/stat.h>
const Package::Requirements &pkg_reqs = package.get_required_packages();
Package::Requirements direct_reqs = requires;
direct_reqs.insert(direct_reqs.end(), pkg_reqs.begin(), pkg_reqs.end());
+ for(Package *r: direct_reqs)
+ final_build_info.update_from(r->get_exported_build_info(), BuildInfo::DEPENDENCY);
Package::Requirements all_reqs = direct_reqs;
- for(Package *r: all_reqs)
+ deque<Package *> queue(direct_reqs.begin(), direct_reqs.end());
+ while(!queue.empty())
{
- BuildInfo::UpdateLevel level = BuildInfo::CHAINED;
- if(any_equals(direct_reqs, r))
- level = BuildInfo::DEPENDENCY;
- final_build_info.update_from(r->get_exported_build_info(), level);
-
- for(Package *q: r->get_required_packages())
- if(!any_equals(all_reqs, q))
- all_reqs.push_back(q);
+ Package *req = queue.front();
+ queue.pop_front();
+
+ for(Package *r: req->get_required_packages())
+ if(!any_equals(all_reqs, r))
+ {
+ final_build_info.update_from(r->get_exported_build_info(), BuildInfo::CHAINED);
+ all_reqs.push_back(r);
+ queue.push_back(r);
+ }
}
final_build_info.update_from(package.get_build_info());
void ObjectFile::find_dependencies()
{
- for(Target *d: depends)
+ vector<FileTarget *> headers;
+ find_dependencies(source, headers);
+ for(FileTarget *h: headers)
{
- d->prepare();
- find_dependencies(dynamic_cast<FileTarget *>(d));
+ add_dependency(*h);
+ if(h->get_real_target()->is_buildable())
+ h->signal_modified.connect(sigc::mem_fun(this, static_cast<void (ObjectFile::*)()>(&ObjectFile::find_dependencies)));
}
}
-void ObjectFile::find_dependencies(FileTarget *tgt)
+void ObjectFile::find_dependencies(FileTarget &tgt, vector<FileTarget *> &headers)
{
- FileTarget *rtgt = dynamic_cast<FileTarget *>(tgt->get_real_target());
- const Dependencies &tdeps = rtgt->get_transitive_dependencies();
- Dependencies deps_to_add;
- if(rtgt==tgt)
- {
- /* We are using the target from its original location, so dependencies
- apply directly */
- deps_to_add = tdeps;
- }
- else
+ tgt.prepare();
+
+ FileTarget *rtgt = dynamic_cast<FileTarget *>(tgt.get_real_target());
+ Dependencies deps_to_add = rtgt->get_transitive_dependencies();
+ if(rtgt!=&tgt)
{
FS::Path inst_dir = rtgt->get_component()->get_install_map().get_install_location(*rtgt);
/* The target has been displaced by installing it. Displace any
dependencies that come from the same package as well. */
const SourcePackage *tpkg = rtgt->get_package();
- for(Target *d: tdeps)
+ for(Target *&d: deps_to_add)
{
FileTarget *file = dynamic_cast<FileTarget *>(d);
if(file && file->get_package()==tpkg && FS::descendant_depth(file->get_path(), tpkg->get_source_directory())>=0)
{
const Component *tcomp = file->get_component();
FS::Path dep_inst = tcomp->get_install_map().get_install_location(*file);
- FS::Path displaced = FS::dirname(tgt->get_path())/FS::relative(dep_inst, inst_dir)/FS::basename(file->get_path());
- if(Target *ddep = builder.get_vfs().get_target(displaced))
- deps_to_add.push_back(ddep);
- else
+ FS::Path displaced = FS::dirname(tgt.get_path())/FS::relative(dep_inst, inst_dir)/FS::basename(file->get_path());
+ d = builder.get_vfs().get_target(displaced);
+ if(!d)
{
+ /* If the target was in an overlay directory and the displaced
+ dependency is not found, try removing the overlay from the path. */
string last_dir = FS::basename(FS::dirname(displaced));
if(any_equals(tcomp->get_overlays(), last_dir))
{
displaced = displaced.subpath(0, displaced.size()-2)/FS::basename(file->get_path());
- if((ddep = builder.get_vfs().get_target(displaced)))
- deps_to_add.push_back(ddep);
+ d = builder.get_vfs().get_target(displaced);
}
}
}
- else
- deps_to_add.push_back(d);
}
}
for(Target *d: deps_to_add)
- if(!any_equals(depends, d))
+ if(FileTarget *file = dynamic_cast<FileTarget *>(d))
{
- add_dependency(*d);
- if(d->get_real_target()->is_buildable())
- d->signal_modified.connect(sigc::mem_fun(this, static_cast<void (ObjectFile::*)()>(&ObjectFile::find_dependencies)));
+ auto i = lower_bound(headers, file);
+ if(i==headers.end() || *i!=file)
+ {
+ headers.insert(i, file);
+ find_dependencies(*file, headers);
+ }
}
}
private:
void find_dependencies() override;
- void find_dependencies(FileTarget *);
+ void find_dependencies(FileTarget &, std::vector<FileTarget *> &);
};
#endif