]> git.tdb.fi Git - builder.git/blob - source/binary.cpp
Rewrite dependency finding algorithms in a few classes
[builder.git] / source / binary.cpp
1 #include <msp/core/algorithm.h>
2 #include <msp/fs/utils.h>
3 #include <msp/strings/format.h>
4 #include <msp/strings/utils.h>
5 #include "binary.h"
6 #include "builder.h"
7 #include "component.h"
8 #include "objectfile.h"
9 #include "sharedlibrary.h"
10 #include "sourcepackage.h"
11 #include "staticlibrary.h"
12 #include "tool.h"
13
14 using namespace std;
15 using namespace Msp;
16
17 Binary::Binary(Builder &b, const FS::Path &p):
18         FileTarget(b, p)
19 { }
20
21 Binary::Binary(Builder &b, const Component &c, const string &p, const list<ObjectFile *> &objs):
22         FileTarget(b, c.get_package(), c.get_package().get_output_directory()/p),
23         objects(objs)
24 {
25         component = &c;
26         for(ObjectFile *o: objects)
27                 add_dependency(*o);
28
29         nested_build_sig = true;
30         arch_in_build_sig = true;
31 }
32
33 void Binary::collect_build_info(BuildInfo &binfo) const
34 {
35         for(ObjectFile *o: objects)
36                 if(const Tool *obj_tool = o->get_tool())
37                         binfo.update_from(obj_tool->get_build_info());
38
39         Target::collect_build_info(binfo);
40
41         binfo.update_from(static_binfo);
42 }
43
44 void Binary::find_dependencies()
45 {
46         if(!component)
47                 return;
48
49         vector<Target *> static_libs;
50         vector<Target *> shared_libs;
51         vector<string> missing_libs;
52         find_dependencies(this, static_libs, shared_libs, missing_libs);
53
54         for(Target *t: static_libs)
55                 add_dependency(*t);
56         for(Target *t: shared_libs)
57                 add_dependency(*t);
58         for(const string &m: missing_libs)
59                 problems.push_back(format("Required library %s not found", m));
60 }
61
62 void Binary::find_dependencies(Target *tgt, vector<Target *> &static_libs, vector<Target *> &shared_libs, vector<string> &missing_libs)
63 {
64         BuildInfo binfo;
65         tgt->collect_build_info(binfo);
66         if(tgt!=this)
67         {
68                 static_binfo.libpath.insert(static_binfo.libpath.end(), binfo.libpath.begin(), binfo.libpath.end());
69                 static_binfo.keep_symbols.insert(static_binfo.keep_symbols.end(), binfo.keep_symbols.begin(), binfo.keep_symbols.end());
70                 if(binfo.threads)
71                         static_binfo.threads = true;
72         }
73
74         for(const string &l: binfo.libs)
75         {
76                 if(l.size()>10 && !l.compare(l.size()-10, 10, ".framework"))
77                         continue;
78
79                 BuildInfo::LibraryMode libmode = component->get_build_info().get_libmode_for(l);
80                 Target *lib = builder.get_vfs().find_library(l, binfo.libpath, libmode);
81                 if(lib)
82                 {
83                         Target *real = lib->get_real_target();
84                         if(StaticLibrary *stlib = dynamic_cast<StaticLibrary *>(real))
85                         {
86                                 /* Keep only the last occurrence of each static library.  This
87                                 ensures the order is correct for linking. */
88                                 auto i = find(static_libs, stlib);
89                                 if(i!=static_libs.end())
90                                         static_libs.erase(i);
91                                 static_libs.push_back(stlib);
92                                 find_dependencies(stlib, static_libs, shared_libs, missing_libs);
93                         }
94                         else if(!any_equals(shared_libs, lib))
95                                 shared_libs.push_back(lib);
96                 }
97                 else if(!any_equals(missing_libs, l))
98                         missing_libs.push_back(l);
99         }
100 }