1 #include <msp/fs/dir.h>
2 #include <msp/fs/stat.h>
3 #include <msp/fs/utils.h>
4 #include <msp/io/print.h>
5 #include <msp/strings/format.h>
6 #include <msp/strings/utils.h>
7 #include <msp/time/units.h>
8 #include <msp/time/utils.h>
9 #include "binarypackage.h"
11 #include "externaltask.h"
13 #include "packagemanager.h"
18 PackageManager::PackageManager(Builder &b):
22 pkg_path.push_back(builder.get_cwd()/".");
23 pkg_path.push_back(builder.get_cwd()/"..");
26 PackageManager::~PackageManager()
28 for(PackageMap::iterator i=packages.begin(); i!=packages.end(); ++i)
32 void PackageManager::set_no_externals(bool x)
37 void PackageManager::add_package(Package *pkg)
39 PackageMap::iterator i = packages.find(pkg->get_name());
43 throw invalid_argument("Package name conflict");
45 throw logic_error("Package is already managed");
48 packages.insert(PackageMap::value_type(pkg->get_name(), pkg));
51 Package *PackageManager::find_package(const string &name)
53 PackageMap::iterator i = packages.find(format("%s/%s", name, builder.get_current_arch().get_system()));
55 i = packages.find(name);
61 FS::Path path = get_package_location(name);
62 if(!path.empty() && !builder.load_build_file(path/"Build"))
64 i = packages.find(name);
73 // Package source not found - create a binary package
74 string flags_str = run_pkgconfig(name, "flags");
75 vector<string> flags = split(flags_str);
76 pkg = BinaryPackage::from_flags(builder, name, flags);
80 builder.problem(name, "not found");
83 packages.insert(PackageMap::value_type(name, pkg));
88 string PackageManager::run_pkgconfig(const string &pkg, const string &what)
90 ExternalTask::Arguments argv;
91 argv.push_back("pkg-config");
92 if(what=="cflags" || what=="libs")
93 argv.push_back("--"+what);
94 else if(what=="flags")
96 argv.push_back("--cflags");
97 argv.push_back("--libs");
100 argv.push_back("--variable="+what);
103 if(builder.get_verbose()>=4)
104 IO::print("Running %s\n", join(argv.begin(), argv.end()));
106 ExternalTask task(argv);
107 task.set_stdout(ExternalTask::CAPTURE);
108 task.set_stderr(ExternalTask::IGNORE);
111 while((status=task.check())==Task::RUNNING)
112 Time::sleep(10*Time::msec);
113 if(status==Task::ERROR)
114 throw runtime_error(format("pkg-config for package %s failed", pkg));
116 return task.get_output();
119 FS::Path PackageManager::get_package_location(const string &name)
121 if(builder.get_verbose()>=3)
122 IO::print("Looking for package %s\n", name);
126 // Try to get source directory with pkgconfig
127 string srcdir = strip(run_pkgconfig(name, "source"));
136 for(list<FS::Path>::const_iterator i=pkg_path.begin(); i!=pkg_path.end(); ++i)
138 list<string> files = list_files(*i);
139 for(list<string>::const_iterator j=files.begin(); j!=files.end(); ++j)
141 FS::Path full = *i / *j;
142 if(FS::exists(full/"Build"))
143 pkg_dirs.push_back(full);
146 if(builder.get_verbose()>=3)
147 IO::print("%d packages found in path\n", pkg_dirs.size());
150 bool msp = !name.compare(0, 3, "msp");
151 for(list<FS::Path>::const_iterator i=pkg_dirs.begin(); i!=pkg_dirs.end(); ++i)
153 string base = basename(*i);
154 unsigned dash = base.rfind('-');
156 if(!base.compare(0, dash, name))
158 else if(msp && !base.compare(0, dash-3, name, 3, string::npos))