+#include <cstdlib>
#include <msp/fs/dir.h>
#include <msp/fs/stat.h>
#include <msp/fs/utils.h>
PackageManager::PackageManager(Builder &b):
builder(b),
- no_externals(false)
-{
- pkg_path.push_back(builder.get_cwd()/".");
- pkg_path.push_back(builder.get_cwd()/"..");
-}
+ no_externals(false),
+ main_pkg(0),
+ env_set(false)
+{ }
PackageManager::~PackageManager()
{
delete i->second;
}
+void PackageManager::append_package_path(const FS::Path &p)
+{
+ pkg_path.push_back(p);
+}
+
+void PackageManager::append_binary_package_path(const FS::Path &p)
+{
+ binpkg_path.push_back(p);
+}
+
void PackageManager::set_no_externals(bool x)
{
no_externals = x;
throw logic_error("Package is already managed");
}
+ if(packages.empty())
+ main_pkg = pkg;
+
packages.insert(PackageMap::value_type(pkg->get_name(), pkg));
}
-Package *PackageManager::find_package(const string &name)
+Package *PackageManager::get_package(const string &name) const
{
- PackageMap::iterator i = packages.find(format("%s/%s", name, builder.get_current_arch().get_system()));
- if(i==packages.end())
- i = packages.find(name);
+ PackageMap::const_iterator i = packages.find(name);
if(i!=packages.end())
return i->second;
+ return 0;
+}
+
+Package &PackageManager::get_main_package() const
+{
+ if(!main_pkg)
+ throw logic_error("No packages");
+ return *main_pkg;
+}
+
+Package *PackageManager::find_package(const string &name)
+{
+ if(not_found.count(name))
+ return 0;
+
+ if(Package *pkg = get_package(name))
+ return pkg;
+
if(!no_externals)
{
FS::Path path = get_package_location(name);
- if(!path.empty() && !builder.load_build_file(path/"Build"))
+ if(!path.empty())
{
- i = packages.find(name);
+ builder.load_build_file(path/"Build");
+ PackageMap::iterator i = packages.find(name);
if(i!=packages.end())
return i->second;
}
}
- Package *pkg = 0;
+ FS::Path path = get_binary_package_file(name);
+ if(!path.empty())
+ {
+ builder.load_build_file(path);
+ if(Package *pkg = get_package(name))
+ return pkg;
+ }
+
try
{
// Package source not found - create a binary package
string flags_str = run_pkgconfig(name, "flags");
vector<string> flags = split(flags_str);
- pkg = BinaryPackage::from_flags(builder, name, flags);
+ Package *pkg = BinaryPackage::from_flags(builder, name, flags);
+ packages.insert(PackageMap::value_type(name, pkg));
+ return pkg;
}
catch(...)
{
- builder.problem(name, "not found");
+ not_found.insert(name);
+ return 0;
}
-
- packages.insert(PackageMap::value_type(name, pkg));
-
- return pkg;
}
string PackageManager::run_pkgconfig(const string &pkg, const string &what)
{
+ if(!env_set)
+ {
+ const FS::Path &prefix = builder.get_prefix();
+ if(prefix.str()!="/usr")
+ {
+ FS::Path pcdir = prefix/"lib/pkgconfig";
+ if(const char *pcp = getenv("PKG_CONFIG_PATH"))
+ {
+ vector<string> path = split(pcp, ':');
+ bool found = false;
+ for(vector<string>::const_iterator i=path.begin(); (!found && i!=path.end()); ++i)
+ found = (*i==pcdir.str());
+ if(!found)
+ {
+ path.push_back(pcdir.str());
+ setenv("PKG_CONFIG_PATH", join(path.begin(), path.end(), ":").c_str(), true);
+ }
+ }
+ else
+ setenv("PKG_CONFIG_PATH", pcdir.str().c_str(), true);
+ }
+ }
+
ExternalTask::Arguments argv;
argv.push_back("pkg-config");
if(what=="cflags" || what=="libs")
argv.push_back("--variable="+what);
argv.push_back(pkg);
- if(builder.get_verbose()>=4)
- IO::print("Running %s\n", join(argv.begin(), argv.end()));
+ builder.get_logger().log("auxcommands", format("Running %s", join(argv.begin(), argv.end())));
- ExternalTask task(argv);
- task.set_stdout(ExternalTask::CAPTURE);
- task.set_stderr(ExternalTask::IGNORE);
- task.start();
- Task::Status status;
- while((status=task.check())==Task::RUNNING)
- Time::sleep(10*Time::msec);
- if(status==Task::ERROR)
- throw runtime_error(format("pkg-config for package %s failed", pkg));
-
- return task.get_output();
+ return ExternalTask::run_and_capture_output(argv);
}
FS::Path PackageManager::get_package_location(const string &name)
{
- if(builder.get_verbose()>=3)
- IO::print("Looking for package %s\n", name);
+ builder.get_logger().log("packagemgr", format("Looking for source package %s", name));
try
{
// Try to get source directory with pkgconfig
string srcdir = strip(run_pkgconfig(name, "source"));
- if(!srcdir.empty())
+ if(!srcdir.empty() && FS::exists(FS::Path(srcdir)/"Build"))
return srcdir;
}
catch(...)
if(pkg_dirs.empty())
{
- for(list<FS::Path>::const_iterator i=pkg_path.begin(); i!=pkg_path.end(); ++i)
+ for(SearchPath::const_iterator i=pkg_path.begin(); i!=pkg_path.end(); ++i)
{
+ builder.get_logger().log("files", format("Traversing %s", *i));
list<string> files = list_files(*i);
+ unsigned count = 0;
for(list<string>::const_iterator j=files.begin(); j!=files.end(); ++j)
{
FS::Path full = *i / *j;
if(FS::exists(full/"Build"))
+ {
pkg_dirs.push_back(full);
+ ++count;
+ }
}
+
+ builder.get_logger().log("packagemgr", format("%d source packages found in %s", count, *i));
}
- if(builder.get_verbose()>=3)
- IO::print("%d packages found in path\n", pkg_dirs.size());
+
+ builder.get_logger().log("packagemgr", format("%d source packages found", pkg_dirs.size()));
}
bool msp = !name.compare(0, 3, "msp");
- for(list<FS::Path>::const_iterator i=pkg_dirs.begin(); i!=pkg_dirs.end(); ++i)
+ for(SearchPath::const_iterator i=pkg_dirs.begin(); i!=pkg_dirs.end(); ++i)
{
- string base = basename(*i);
+ string base = FS::basename(*i);
unsigned dash = base.rfind('-');
if(!base.compare(0, dash, name))
return *i;
- else if(msp && !base.compare(0, dash-3, name, 3, string::npos))
+ else if(msp && !base.compare(0, dash, name, 3, string::npos))
+ return *i;
+ }
+
+ return FS::Path();
+}
+
+FS::Path PackageManager::get_binary_package_file(const string &name)
+{
+ builder.get_logger().log("packagemgr", format("Looking for binary package %s", name));
+
+ if(binpkg_files.empty())
+ {
+ for(list<FS::Path>::const_iterator i=binpkg_path.begin(); i!=binpkg_path.end(); ++i)
+ {
+ builder.get_logger().log("files", format("Traversing %s", *i));
+ list<string> files = list_filtered(*i, "\\.bpk$");
+ for(list<string>::const_iterator j=files.begin(); j!=files.end(); ++j)
+ binpkg_files.push_back(*i / *j);
+ builder.get_logger().log("packagemgr", format("%d binary packages found in %s", files.size(), *i));
+ }
+
+ builder.get_logger().log("packagemgr", format("%d binary packages found", binpkg_files.size()));
+ }
+
+ for(SearchPath::const_iterator i=binpkg_files.begin(); i!=binpkg_files.end(); ++i)
+ {
+ string base = FS::basepart(FS::basename(*i));
+ if(base==name)
return *i;
}
return FS::Path();
}
+
+void PackageManager::save_all_caches() const
+{
+ for(PackageMap::const_iterator i=packages.begin(); i!=packages.end(); ++i)
+ i->second->save_caches();
+}