2 #include <msp/core/algorithm.h>
3 #include <msp/io/print.h>
4 #include <msp/strings/utils.h>
5 #include "binarypackage.h"
7 #include "filetarget.h"
8 #include "staticlibrary.h"
13 BinaryPackage::BinaryPackage(Builder &b, const string &n):
16 use_pkgconfig = false;
19 BinaryPackage *BinaryPackage::from_flags(Builder &builder, const string &name, const Flags &flags, const Flags &static_flags)
21 BinaryPackage *pkg = new BinaryPackage(builder, name);
22 pkg->use_pkgconfig = true;
24 process_flags(flags, pkg->export_binfo);
26 Flags exclusive_static_flags;
27 for(const string &f: static_flags)
28 if(!any_equals(flags, f))
29 exclusive_static_flags.push_back(f);
30 process_flags(exclusive_static_flags, pkg->static_binfo);
35 void BinaryPackage::process_flags(const Flags &flags, BuildInfo &binfo)
37 for(const string &f: flags)
39 if(!f.compare(0, 2, "-I"))
40 binfo.incpath.push_back(f.substr(2));
41 else if(!f.compare(0, 2, "-D"))
43 string::size_type equals = f.find('=');
44 if(equals!=string::npos)
45 binfo.defines[f.substr(2, equals-2)] = f.substr(equals+1);
47 binfo.defines[f.substr(2)] = string();
49 else if(!f.compare(0, 2, "-L"))
50 binfo.libpath.push_back(f.substr(2));
51 else if(!f.compare(0, 2, "-l"))
52 binfo.libs.push_back(f.substr(2));
53 else if(f=="-pthread")
58 void BinaryPackage::do_prepare()
60 auto is_relative = [](const FS::Path &p){ return !p.is_absolute(); };
61 bool has_relative_paths = any_of(export_binfo.libpath.begin(), export_binfo.libpath.end(), is_relative) ||
62 any_of(export_binfo.incpath.begin(), export_binfo.incpath.end(), is_relative);
64 vector<FS::Path> bases;
66 /* If we have any relative paths that need resolving, or we have no paths at
67 all and are not using pkg-config, look for files in prefix */
68 if(has_relative_paths || (!use_pkgconfig && export_binfo.libpath.empty() && export_binfo.incpath.empty()))
69 bases.push_back(builder.get_prefix());
71 // Always look in system locations
72 bases.push_back(FS::Path());
75 unsigned least_missing = numeric_limits<unsigned>::max();
77 for(const FS::Path &b: bases)
80 system = prefix.empty();
84 const Architecture &arch = builder.get_current_arch();
86 prefix /= arch.get_cross_prefix();
89 VirtualFileSystem::SearchPath libpath = export_binfo.libpath;
90 if(!system && libpath.empty())
91 libpath.push_back("lib");
92 for(FS::Path &p: libpath)
95 unsigned missing_count = 0;
97 for(const string &l: export_binfo.libs)
98 if(!builder.get_vfs().find_library(l, libpath, export_binfo.libmode, system))
100 first_missing = format("library %s", l);
102 VirtualFileSystem::SearchPath incpath = export_binfo.incpath;
103 if(!system && incpath.empty())
104 incpath.push_back("include");
105 for(FS::Path &p: incpath)
108 for(const string &h: headers)
109 if(!builder.get_vfs().find_header(h, 0, incpath, system))
116 builder.get_logger().log("configure", "%s found in %s", name, ((system && use_pkgconfig) ? "system" : base_path.str()));
119 else if(missing_count<least_missing)
121 least_missing = missing_count;
122 missing_name = first_missing;
126 if(base_path.empty())
128 string missing_descr = (least_missing>1 ? format("%s and %d other files", missing_name, least_missing-1) : missing_name);
129 builder.get_logger().log("problems", "Cannot locate %s for %s", missing_descr, name);
130 problems.push_back(format("Cannot locate %s", missing_descr));
134 /* Add default entries to paths if they're empty and the package was found
135 in a non-system location */
136 if(!system && export_binfo.incpath.empty())
137 export_binfo.incpath.push_back(base_path/"include");
138 if(!system && export_binfo.libpath.empty())
139 export_binfo.libpath.push_back(base_path/"lib");
141 if(has_relative_paths)
143 for(FS::Path &p: export_binfo.incpath)
145 for(FS::Path &p: export_binfo.libpath)
149 if(!static_binfo.libs.empty())
151 VirtualFileSystem::SearchPath combined_libpath = static_binfo.libpath;
152 combined_libpath.insert(combined_libpath.end(), export_binfo.libpath.begin(), export_binfo.libpath.end());
154 for(const string &l: export_binfo.libs)
155 if(Target *lib = builder.get_vfs().find_library(l, export_binfo.libpath, BuildInfo::FORCE_STATIC, system))
156 if(StaticLibrary *stlib = dynamic_cast<StaticLibrary *>(lib))
158 for(const string &s: static_binfo.libs)
159 stlib->add_required_library(s);
160 for(const FS::Path &p: combined_libpath)
161 stlib->add_library_path(p);
167 BinaryPackage::Loader::Loader(BinaryPackage &p):
168 DataFile::DerivedObjectLoader<BinaryPackage, Package::Loader>(p)
170 add("build_info", &Loader::build_info);
171 add("header", &Loader::header);
174 void BinaryPackage::Loader::build_info()
176 load_sub(obj.export_binfo);
179 void BinaryPackage::Loader::header(const string &h)
181 obj.headers.push_back(h);