2 #include <msp/fs/dir.h>
3 #include <msp/fs/stat.h>
4 #include <msp/fs/utils.h>
5 #include <msp/io/print.h>
6 #include <msp/strings/format.h>
7 #include <msp/strings/utils.h>
8 #include <msp/time/units.h>
9 #include <msp/time/utils.h>
10 #include "binarypackage.h"
12 #include "externaltask.h"
14 #include "packagemanager.h"
19 PackageManager::PackageManager(Builder &b):
26 PackageManager::~PackageManager()
28 for(PackageMap::iterator i=packages.begin(); i!=packages.end(); ++i)
32 void PackageManager::append_package_path(const FS::Path &p)
34 pkg_path.push_back(p);
37 void PackageManager::append_binary_package_path(const FS::Path &p)
39 binpkg_path.push_back(p);
42 void PackageManager::set_no_externals(bool x)
47 void PackageManager::add_package(Package *pkg)
49 PackageMap::iterator i = packages.find(pkg->get_name());
53 throw invalid_argument("Package name conflict");
55 throw logic_error("Package is already managed");
61 packages.insert(PackageMap::value_type(pkg->get_name(), pkg));
64 Package *PackageManager::get_package(const string &name) const
66 PackageMap::const_iterator i = packages.find(name);
73 Package &PackageManager::get_main_package() const
76 throw logic_error("No packages");
80 Package *PackageManager::find_package(const string &name)
82 if(not_found.count(name))
85 if(Package *pkg = get_package(name))
90 FS::Path path = get_package_location(name);
93 builder.load_build_file(path/"Build");
94 PackageMap::iterator i = packages.find(name);
100 FS::Path path = get_binary_package_file(name);
103 builder.load_build_file(path);
104 if(Package *pkg = get_package(name))
110 // Package source not found - create a binary package
111 string flags_str = run_pkgconfig(name, "flags");
112 BinaryPackage::Flags flags = split(flags_str);
113 flags_str = run_pkgconfig(name, "staticflags");
114 BinaryPackage::Flags static_flags = split(flags_str);
115 Package *pkg = BinaryPackage::from_flags(builder, name, flags, static_flags);
116 packages.insert(PackageMap::value_type(name, pkg));
121 not_found.insert(name);
126 string PackageManager::run_pkgconfig(const string &pkg, const string &what)
130 const FS::Path &prefix = builder.get_prefix();
131 if(prefix.str()!="/usr")
133 FS::Path pcdir = prefix/"lib/pkgconfig";
134 if(const char *pcp = getenv("PKG_CONFIG_PATH"))
136 vector<string> path = split(pcp, ':');
138 for(vector<string>::const_iterator i=path.begin(); (!found && i!=path.end()); ++i)
139 found = (*i==pcdir.str());
142 path.push_back(pcdir.str());
143 setenv("PKG_CONFIG_PATH", join(path.begin(), path.end(), ":").c_str(), true);
147 setenv("PKG_CONFIG_PATH", pcdir.str().c_str(), true);
151 ExternalTask::Arguments argv;
152 argv.push_back("pkg-config");
153 if(what=="cflags" || what=="libs")
154 argv.push_back("--"+what);
155 else if(what=="flags" || what=="staticflags")
157 argv.push_back("--cflags");
158 argv.push_back("--libs");
159 if(what=="staticflags")
160 argv.push_back("--static");
163 argv.push_back("--variable="+what);
166 builder.get_logger().log("auxcommands", format("Running %s", join(argv.begin(), argv.end())));
168 return ExternalTask::run_and_capture_output(argv);
171 FS::Path PackageManager::get_package_location(const string &name)
173 builder.get_logger().log("packagemgr", format("Looking for source package %s", name));
177 // Try to get source directory with pkgconfig
178 string srcdir = strip(run_pkgconfig(name, "source"));
179 if(!srcdir.empty() && FS::exists(FS::Path(srcdir)/"Build"))
187 for(SearchPath::const_iterator i=pkg_path.begin(); i!=pkg_path.end(); ++i)
189 builder.get_logger().log("files", format("Traversing %s", *i));
190 list<string> files = list_files(*i);
192 for(list<string>::const_iterator j=files.begin(); j!=files.end(); ++j)
194 FS::Path full = *i / *j;
195 if(FS::exists(full/"Build"))
197 pkg_dirs.push_back(full);
202 builder.get_logger().log("packagemgr", format("%d source packages found in %s", count, *i));
205 builder.get_logger().log("packagemgr", format("%d source packages found", pkg_dirs.size()));
208 bool msp = !name.compare(0, 3, "msp");
209 for(SearchPath::const_iterator i=pkg_dirs.begin(); i!=pkg_dirs.end(); ++i)
211 string base = FS::basename(*i);
212 unsigned dash = base.rfind('-');
214 if(!base.compare(0, dash, name))
216 else if(msp && !base.compare(0, dash, name, 3, string::npos))
223 FS::Path PackageManager::get_binary_package_file(const string &name)
225 builder.get_logger().log("packagemgr", format("Looking for binary package %s", name));
227 if(binpkg_files.empty())
229 for(list<FS::Path>::const_iterator i=binpkg_path.begin(); i!=binpkg_path.end(); ++i)
231 builder.get_logger().log("files", format("Traversing %s", *i));
232 list<string> files = list_filtered(*i, "\\.bpk$");
233 for(list<string>::const_iterator j=files.begin(); j!=files.end(); ++j)
234 binpkg_files.push_back(*i / *j);
235 builder.get_logger().log("packagemgr", format("%d binary packages found in %s", files.size(), *i));
238 builder.get_logger().log("packagemgr", format("%d binary packages found", binpkg_files.size()));
241 for(SearchPath::const_iterator i=binpkg_files.begin(); i!=binpkg_files.end(); ++i)
243 string base = FS::basepart(FS::basename(*i));
251 void PackageManager::save_all_caches() const
253 for(PackageMap::const_iterator i=packages.begin(); i!=packages.end(); ++i)
254 i->second->save_caches();