]> git.tdb.fi Git - builder.git/blob - source/binarypackage.cpp
Remove most container typedefs and refactor others
[builder.git] / source / binarypackage.cpp
1 #include <msp/core/algorithm.h>
2 #include <msp/io/print.h>
3 #include <msp/strings/utils.h>
4 #include "binarypackage.h"
5 #include "builder.h"
6 #include "filetarget.h"
7 #include "staticlibrary.h"
8
9 using namespace std;
10 using namespace Msp;
11
12 BinaryPackage::BinaryPackage(Builder &b, const string &n):
13         Package(b, n)
14 {
15         use_pkgconfig = false;
16 }
17
18 BinaryPackage *BinaryPackage::from_flags(Builder &builder, const string &name, const Flags &flags, const Flags &static_flags)
19 {
20         BinaryPackage *pkg = new BinaryPackage(builder, name);
21         pkg->use_pkgconfig = true;
22
23         process_flags(flags, pkg->export_binfo);
24
25         Flags exclusive_static_flags;
26         for(const string &f: static_flags)
27                 if(!any_equals(flags, f))
28                         exclusive_static_flags.push_back(f);
29         process_flags(exclusive_static_flags, pkg->static_binfo);
30
31         return pkg;
32 }
33
34 void BinaryPackage::process_flags(const Flags &flags, BuildInfo &binfo)
35 {
36         for(const string &f: flags)
37         {
38                 if(!f.compare(0, 2, "-I"))
39                         binfo.incpath.push_back(f.substr(2));
40                 else if(!f.compare(0, 2, "-D"))
41                 {
42                         string::size_type equals = f.find('=');
43                         if(equals!=string::npos)
44                                 binfo.defines[f.substr(2, equals-2)] = f.substr(equals+1);
45                         else
46                                 binfo.defines[f.substr(2)] = string();
47                 }
48                 else if(!f.compare(0, 2, "-L"))
49                         binfo.libpath.push_back(f.substr(2));
50                 else if(!f.compare(0, 2, "-l"))
51                         binfo.libs.push_back(f.substr(2));
52                 else if(f=="-pthread")
53                         binfo.threads = true;
54         }
55 }
56
57 void BinaryPackage::do_prepare()
58 {
59         auto is_relative = [](const FS::Path &p){ return !p.is_absolute(); };
60         bool has_relative_paths = any_of(export_binfo.libpath.begin(), export_binfo.libpath.end(), is_relative) ||
61                 any_of(export_binfo.incpath.begin(), export_binfo.incpath.end(), is_relative);
62
63         list<FS::Path> bases;
64
65         /* If we have any relative paths that need resolving, or we have no paths at
66         all and are not using pkg-config, look for files in prefix */
67         if(has_relative_paths || (!use_pkgconfig && export_binfo.libpath.empty() && export_binfo.incpath.empty()))
68                 bases.push_back(builder.get_prefix());
69
70         // Always look in system locations
71         bases.push_back(FS::Path());
72
73         bool system = false;
74         for(const FS::Path &b: bases)
75         {
76                 FS::Path prefix = b;
77                 system = prefix.empty();
78                 if(system)
79                 {
80                         prefix = "/usr";
81                         const Architecture &arch = builder.get_current_arch();
82                         if(arch.is_cross())
83                                 prefix /= arch.get_cross_prefix();
84                 }
85
86                 VirtualFileSystem::SearchPath libpath = export_binfo.libpath;
87                 if(!system && libpath.empty())
88                         libpath.push_back("lib");
89                 for(FS::Path &p: libpath)
90                         p = prefix/p;
91
92                 bool all_found = true;
93                 for(const string &l: export_binfo.libs)
94                         all_found &= (builder.get_vfs().find_library(l, libpath, export_binfo.libmode, system)!=0);
95
96                 VirtualFileSystem::SearchPath incpath = export_binfo.incpath;
97                 if(!system && incpath.empty())
98                         incpath.push_back("include");
99                 for(FS::Path &p: incpath)
100                         p = prefix/p;
101
102                 for(const string &h: headers)
103                         all_found &= (builder.get_vfs().find_header(h, 0, incpath, system)!=0);
104
105                 if(all_found)
106                 {
107                         base_path = prefix;
108                         builder.get_logger().log("configure", format("%s found in %s", name, ((system && use_pkgconfig) ? "system" : base_path.str())));
109                         break;
110                 }
111         }
112
113         if(base_path.empty())
114         {
115                 // TODO report which files were not found
116                 builder.get_logger().log("problems", format("Cannot locate files for %s", name));
117                 problems.push_back("Cannot locate files");
118                 return;
119         }
120
121         /* Add default entries to paths if they're empty and the package was found
122         in a non-system location */
123         if(!system && export_binfo.incpath.empty())
124                 export_binfo.incpath.push_back(base_path/"include");
125         if(!system && export_binfo.libpath.empty())
126                 export_binfo.libpath.push_back(base_path/"lib");
127
128         if(has_relative_paths)
129         {
130                 for(FS::Path &p: export_binfo.incpath)
131                         p = base_path/p;
132                 for(FS::Path &p: export_binfo.libpath)
133                         p = base_path/p;
134         }
135
136         if(!static_binfo.libs.empty())
137         {
138                 VirtualFileSystem::SearchPath combined_libpath = static_binfo.libpath;
139                 combined_libpath.insert(combined_libpath.end(), export_binfo.libpath.begin(), export_binfo.libpath.end());
140
141                 for(const string &l: export_binfo.libs)
142                         if(Target *lib = builder.get_vfs().find_library(l, export_binfo.libpath, BuildInfo::FORCE_STATIC, system))
143                                 if(StaticLibrary *stlib = dynamic_cast<StaticLibrary *>(lib))
144                                 {
145                                         for(const string &s: static_binfo.libs)
146                                                 stlib->add_required_library(s);
147                                         for(const FS::Path &p: combined_libpath)
148                                                 stlib->add_library_path(p);
149                                 }
150         }
151 }
152
153
154 BinaryPackage::Loader::Loader(BinaryPackage &p):
155         DataFile::DerivedObjectLoader<BinaryPackage, Package::Loader>(p)
156 {
157         add("build_info", &Loader::build_info);
158         add("header",     &Loader::header);
159 }
160
161 void BinaryPackage::Loader::build_info()
162 {
163         load_sub(obj.export_binfo);
164 }
165
166 void BinaryPackage::Loader::header(const string &h)
167 {
168         obj.headers.push_back(h);
169 }