]> git.tdb.fi Git - builder.git/commitdiff
Move package management to a separate class
authorMikko Rasa <tdb@tdb.fi>
Sat, 23 Jun 2012 18:50:13 +0000 (21:50 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sun, 8 Jul 2012 21:08:54 +0000 (00:08 +0300)
source/binarypackage.cpp
source/binarypackage.h
source/builder.cpp
source/builder.h
source/component.cpp
source/package.cpp
source/packagemanager.cpp [new file with mode: 0644]
source/packagemanager.h [new file with mode: 0644]
source/sourcepackage.cpp

index bc3e5c929ec41af7d6a5b515f2ac2a17501c50b1..8c3571d103ac4fb9cc955e7178d3a8b745d26d95 100644 (file)
@@ -29,15 +29,12 @@ void BinaryPackage::create_build_info()
                        *i = (path/i->substr(1)).str();
 }
 
-BinaryPackage *BinaryPackage::from_pkgconfig(Builder &builder, const string &name)
+BinaryPackage *BinaryPackage::from_flags(Builder &builder, const std::string &name, const vector<string> &flags)
 {
-       string info = builder.run_pkgconfig(name, "flags");
-
        BinaryPackage *pkg = new BinaryPackage(builder, name);
        pkg->use_pkgconfig = true;
        BuildInfo &binfo = pkg->export_binfo;
 
-       vector<string> flags = split(info);
        for(vector<string>::const_iterator i=flags.begin(); i!=flags.end(); ++i)
        {
                if(!i->compare(0, 2, "-I"))
index ff077f8c362ed385ce09152517038c0de3536977..8c0d0e9ec39c7a741c94fe908a8f92aa08d74803 100644 (file)
@@ -34,7 +34,7 @@ public:
 
        bool get_need_path() const { return need_path; }
 
-       static BinaryPackage *from_pkgconfig(Builder &, const std::string &);
+       static BinaryPackage *from_flags(Builder &, const std::string &, const std::vector<std::string> &);
 private:
        virtual void create_build_info();
 };
index 2c28b7931631e2a3d06bf7f32b2c4e8539f8a0ac..393cfc5d62598cf6649c9366fd69ddd904c67371 100644 (file)
@@ -17,7 +17,6 @@
 #include "binarypackage.h"
 #include "builder.h"
 #include "copy.h"
-#include "externaltask.h"
 #include "gnuarchiver.h"
 #include "gnuccompiler.h"
 #include "gnucxxcompiler.h"
@@ -35,6 +34,7 @@ using namespace std;
 using namespace Msp;
 
 Builder::Builder(int argc, char **argv):
+       package_manager(*this),
        main_pkg(0),
        native_arch(*this, string()),
        vfs(*this),
@@ -59,6 +59,7 @@ Builder::Builder(int argc, char **argv):
        StringList cmdline_warn;
        string prfx;
        string arch;
+       bool no_externals = false;
 
        GetOpt getopt;
        getopt.add_option('a', "analyze",    analyze_mode,  GetOpt::REQUIRED_ARG).set_help("Perform analysis.  MODE can be deps, alldeps or rebuild.", "MODE");
@@ -124,6 +125,8 @@ Builder::Builder(int argc, char **argv):
 
        cwd = FS::getcwd();
 
+       package_manager.set_no_externals(no_externals);
+
        load_build_file((FS::get_sys_data_dir(argv[0], "builder")/"builderrc").str());
        load_build_file((FS::get_user_data_dir("builder")/"rc").str());
 
@@ -170,15 +173,10 @@ Builder::Builder(int argc, char **argv):
                vector<string> warns = split(*i, ',');
                warnings.insert(warnings.end(), warns.begin(), warns.end());
        }
-
-       pkg_path.push_back(cwd/".");
-       pkg_path.push_back(cwd/"..");
 }
 
 Builder::~Builder()
 {
-       for(PackageMap::iterator i=packages.begin(); i!=packages.end(); ++i)
-               delete i->second;
        for(TargetMap::iterator i=targets.begin(); i!=targets.end(); ++i)
                delete i->second;
        delete analyzer;
@@ -244,8 +242,9 @@ int Builder::main()
 
        if(verbose>=1)
        {
+               const PackageManager::PackageMap &packages = package_manager.get_packages();
                unsigned n_packages = 0;
-               for(PackageMap::const_iterator i=packages.begin(); i!=packages.end(); ++i)
+               for(PackageManager::PackageMap::const_iterator i=packages.begin(); i!=packages.end(); ++i)
                        if(i->second && i->second->is_configured())
                                ++n_packages;
                IO::print("%d active packages, %d targets\n", n_packages, targets.size());
@@ -253,7 +252,8 @@ int Builder::main()
 
        if(verbose>=2)
        {
-               for(PackageMap::const_iterator i=packages.begin(); i!=packages.end(); ++i)
+               const PackageManager::PackageMap &packages = package_manager.get_packages();
+               for(PackageManager::PackageMap::const_iterator i=packages.begin(); i!=packages.end(); ++i)
                {
                        if(!i->second->is_configured())
                                continue;
@@ -302,72 +302,6 @@ int Builder::main()
        return exit_code;
 }
 
-string Builder::run_pkgconfig(const string &pkg, const string &what)
-{
-       ExternalTask::Arguments argv;
-       argv.push_back("pkg-config");
-       if(what=="cflags" || what=="libs")
-               argv.push_back("--"+what);
-       else if(what=="flags")
-       {
-               argv.push_back("--cflags");
-               argv.push_back("--libs");
-       }
-       else
-               argv.push_back("--variable="+what);
-       argv.push_back(pkg);
-
-       if(verbose>=4)
-               IO::print("Running %s\n", 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();
-}
-
-Package *Builder::get_package(const string &name)
-{
-       PackageMap::iterator i = packages.find(format("%s/%s", name, current_arch->get_system()));
-       if(i==packages.end())
-               i = packages.find(name);
-       if(i!=packages.end())
-               return i->second;
-
-       if(!no_externals)
-       {
-               FS::Path path = get_package_location(name);
-               if(!path.empty() && !load_build_file(path/"Build"))
-               {
-                       i = packages.find(name);
-                       if(i!=packages.end())
-                               return i->second;
-               }
-       }
-
-       Package *pkg = 0;
-       try
-       {
-               // Package source not found - create a binary package
-               pkg = BinaryPackage::from_pkgconfig(*this, name);
-       }
-       catch(...)
-       {
-               problem(name, "not found");
-       }
-
-       packages.insert(PackageMap::value_type(name, pkg));
-
-       return pkg;
-}
-
 Target *Builder::get_target(const string &n) const
 {
        TargetMap::const_iterator i = targets.find(n);
@@ -417,52 +351,6 @@ void Builder::usage(const char *reason, const char *argv0, bool brief)
        }
 }
 
-FS::Path Builder::get_package_location(const string &name)
-{
-       if(verbose>=3)
-               IO::print("Looking for package %s\n", name);
-
-       try
-       {
-               // Try to get source directory with pkgconfig
-               string srcdir = strip(run_pkgconfig(name, "source"));
-               if(!srcdir.empty())
-                       return srcdir;
-       }
-       catch(...)
-       { }
-
-       if(pkg_dirs.empty())
-       {
-               for(list<FS::Path>::const_iterator i=pkg_path.begin(); i!=pkg_path.end(); ++i)
-               {
-                       list<string> files = list_files(*i);
-                       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);
-                       }
-               }
-               if(verbose>=3)
-                       IO::print("%d packages found in path\n", 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)
-       {
-               string base = 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))
-                       return *i;
-       }
-
-       return FS::Path();
-}
-
 int Builder::load_build_file(const FS::Path &fn)
 {
        if(!FS::exists(fn))
@@ -493,7 +381,8 @@ int Builder::create_targets()
        Target *tarballs = new VirtualTarget(*this, "tarballs");
        world->add_depend(tarballs);
 
-       for(PackageMap::const_iterator i=packages.begin(); i!=packages.end(); ++i)
+       const PackageManager::PackageMap &packages = package_manager.get_packages();
+       for(PackageManager::PackageMap::const_iterator i=packages.begin(); i!=packages.end(); ++i)
                if(i->second && i->second->is_configured())
                        i->second->create_targets();
 
@@ -536,7 +425,7 @@ int Builder::create_targets()
                                i->second->force_rebuild();
        }
 
-       for(PackageMap::iterator i=packages.begin(); i!=packages.end(); ++i)
+       for(PackageManager::PackageMap::const_iterator i=packages.begin(); i!=packages.end(); ++i)
                if(SourcePackage *spkg = dynamic_cast<SourcePackage *>(i->second))
                        spkg->get_deps_cache().save();
 
@@ -703,7 +592,6 @@ void Builder::Loader::binpkg(const string &n)
 {
        BinaryPackage *pkg = new BinaryPackage(bld, n);
        load_sub(*pkg);
-       bld.packages.insert(PackageMap::value_type(n, pkg));
 }
 
 void Builder::Loader::cross_prefix(const string &a, const string &p)
@@ -726,7 +614,6 @@ void Builder::Loader::package(const string &n)
                bld.main_pkg = pkg;
 
        load_sub(*pkg);
-       bld.packages.insert(PackageMap::value_type(n, pkg));
 }
 
 
index 7a33ab8f86d6022a142e99eaad17d9f3da8e59ff..99b380497b7422809dcb9d686e518a6aec83f543 100644 (file)
@@ -10,6 +10,7 @@
 #include "architecture.h"
 #include "config.h"
 #include "misc.h"
+#include "packagemanager.h"
 #include "problem.h"
 #include "target.h"
 #include "toolchain.h"
@@ -59,19 +60,14 @@ public:
        typedef std::list<Target *> TargetList;
 
 private:
-       typedef std::list<Package *> PackageList;
-       typedef std::map<std::string, Package *> PackageMap;
        typedef std::map<std::string, StringMap> ProfileTemplateMap;
 
        StringList cmdline_targets;
        StringMap cmdline_options;
        Msp::FS::Path cwd;
 
-       PackageMap packages;
+       PackageManager package_manager;
        SourcePackage *main_pkg;
-       PathList pkg_path;
-       PathList pkg_dirs;
-       bool no_externals;
 
        TargetMap targets;
        TargetList new_tgts;
@@ -111,16 +107,10 @@ public:
        int main();
        unsigned get_verbose() const { return verbose; }
        bool get_dry_run() const { return dry_run; }
-       bool get_build_all() const { return build_all; }
-
-       /** Gets a package by name, possibly creating it.  Returns 0 if the package
-       could not be located. */
-       Package *get_package(const std::string &);
 
+       PackageManager &get_package_manager() { return package_manager; }
        SourcePackage *get_main_package() const { return main_pkg; }
 
-       std::string run_pkgconfig(const std::string &, const std::string &);
-
        /** Looks up a target by name.  Returns 0 if no such target exists. */
        Target *get_target(const std::string &) const;
 
@@ -145,15 +135,11 @@ public:
 
        static void usage(const char *, const char *, bool);
 
-private:
-       /** Determines the source directory of a package.  Pkg-config is consulted
-       first, and if it fails, the package path is searched for matches. */
-       Msp::FS::Path get_package_location(const std::string &);
-
        /** Loads a build file.  Returns 0 on success or -1 if the file could not be
        opened. */
        int load_build_file(const Msp::FS::Path &);
 
+private:
        /** Creates targets for all packages and prepares them for building.
        Returns 0 if everything went ok, -1 if something bad happened and a build
        shouldn't be attempted. */
index c4908c99a4986f9a0beeec2a8f78acbfd15c7c5e..5c859f7eaf80e01d0734f0d3fc4de4891be736c1 100644 (file)
@@ -273,7 +273,7 @@ void Component::Loader::source(const string &s)
 
 void Component::Loader::require(const string &n)
 {
-       Package *req = comp.pkg.get_builder().get_package(n);
+       Package *req = comp.pkg.get_builder().get_package_manager().find_package(n);
        if(req)
                comp.requires.push_back(req);
 }
index c4710bca79a4f6082b7dd3e7b62297e85a247599..8a05ddc89699950dd5d59ce2977741b4f4be47ad 100644 (file)
@@ -13,7 +13,9 @@ Package::Package(Builder &b, const string &n):
        name(n),
        conf_done(false),
        use_pkgconfig(true)
-{ }
+{
+       builder.get_package_manager().add_package(this);
+}
 
 void Package::configure(const StringMap &opts, unsigned flag)
 {
@@ -45,7 +47,7 @@ Package::Loader::Loader(Package &p):
 
 void Package::Loader::require(const string &n)
 {
-       Package *req = pkg.builder.get_package(n);
+       Package *req = pkg.builder.get_package_manager().find_package(n);
        if(req)
                pkg.requires.push_back(req);
 }
diff --git a/source/packagemanager.cpp b/source/packagemanager.cpp
new file mode 100644 (file)
index 0000000..c3d6939
--- /dev/null
@@ -0,0 +1,163 @@
+#include <msp/fs/dir.h>
+#include <msp/fs/stat.h>
+#include <msp/fs/utils.h>
+#include <msp/io/print.h>
+#include <msp/strings/format.h>
+#include <msp/strings/utils.h>
+#include <msp/time/units.h>
+#include <msp/time/utils.h>
+#include "binarypackage.h"
+#include "builder.h"
+#include "externaltask.h"
+#include "package.h"
+#include "packagemanager.h"
+
+using namespace std;
+using namespace Msp;
+
+PackageManager::PackageManager(Builder &b):
+       builder(b),
+       no_externals(false)
+{
+       pkg_path.push_back(builder.get_cwd()/".");
+       pkg_path.push_back(builder.get_cwd()/"..");
+}
+
+PackageManager::~PackageManager()
+{
+       for(PackageMap::iterator i=packages.begin(); i!=packages.end(); ++i)
+               delete i->second;
+}
+
+void PackageManager::set_no_externals(bool x)
+{
+       no_externals = x;
+}
+
+void PackageManager::add_package(Package *pkg)
+{
+       PackageMap::iterator i = packages.find(pkg->get_name());
+       if(i!=packages.end())
+       {
+               if(i->second!=pkg)
+                       throw invalid_argument("Package name conflict");
+               else
+                       throw logic_error("Package is already managed");
+       }
+
+       packages.insert(PackageMap::value_type(pkg->get_name(), pkg));
+}
+
+Package *PackageManager::find_package(const string &name)
+{
+       PackageMap::iterator i = packages.find(format("%s/%s", name, builder.get_current_arch().get_system()));
+       if(i==packages.end())
+               i = packages.find(name);
+       if(i!=packages.end())
+               return i->second;
+
+       if(!no_externals)
+       {
+               FS::Path path = get_package_location(name);
+               if(!path.empty() && !builder.load_build_file(path/"Build"))
+               {
+                       i = packages.find(name);
+                       if(i!=packages.end())
+                               return i->second;
+               }
+       }
+
+       Package *pkg = 0;
+       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);
+       }
+       catch(...)
+       {
+               builder.problem(name, "not found");
+       }
+
+       packages.insert(PackageMap::value_type(name, pkg));
+
+       return pkg;
+}
+
+string PackageManager::run_pkgconfig(const string &pkg, const string &what)
+{
+       ExternalTask::Arguments argv;
+       argv.push_back("pkg-config");
+       if(what=="cflags" || what=="libs")
+               argv.push_back("--"+what);
+       else if(what=="flags")
+       {
+               argv.push_back("--cflags");
+               argv.push_back("--libs");
+       }
+       else
+               argv.push_back("--variable="+what);
+       argv.push_back(pkg);
+
+       if(builder.get_verbose()>=4)
+               IO::print("Running %s\n", 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();
+}
+
+FS::Path PackageManager::get_package_location(const string &name)
+{
+       if(builder.get_verbose()>=3)
+               IO::print("Looking for package %s\n", name);
+
+       try
+       {
+               // Try to get source directory with pkgconfig
+               string srcdir = strip(run_pkgconfig(name, "source"));
+               if(!srcdir.empty())
+                       return srcdir;
+       }
+       catch(...)
+       { }
+
+       if(pkg_dirs.empty())
+       {
+               for(list<FS::Path>::const_iterator i=pkg_path.begin(); i!=pkg_path.end(); ++i)
+               {
+                       list<string> files = list_files(*i);
+                       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);
+                       }
+               }
+               if(builder.get_verbose()>=3)
+                       IO::print("%d packages found in path\n", 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)
+       {
+               string base = 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))
+                       return *i;
+       }
+
+       return FS::Path();
+}
diff --git a/source/packagemanager.h b/source/packagemanager.h
new file mode 100644 (file)
index 0000000..96c3dca
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef PACKAGEMANAGER_H_
+#define PACKAGEMANAGER_H_
+
+#include <list>
+#include <map>
+#include <string>
+#include <msp/fs/path.h>
+
+class Builder;
+class Package;
+
+/**
+Keeps track of packages.  Also responsible for locating previously unknown
+packages by name.
+*/
+class PackageManager
+{
+public:
+       typedef std::map<std::string, Package *> PackageMap;
+
+private:
+       typedef std::list<Msp::FS::Path> SearchPath;
+
+       Builder &builder;
+       SearchPath pkg_path;
+       SearchPath pkg_dirs;
+       bool no_externals;
+       PackageMap packages;
+
+public:
+       PackageManager(Builder &);
+       ~PackageManager();
+
+       void set_no_externals(bool);
+
+       /** Adds a package to the manager.  Called from Package constructor. */
+       void add_package(Package *);
+
+       /** Returns a package from the cache. */
+       Package *get_package(const std::string &);
+
+       const PackageMap &get_packages() const { return packages; }
+
+       /** Locates a package and creates it if necessary. */
+       Package *find_package(const std::string &);
+
+private:
+       std::string run_pkgconfig(const std::string &, const std::string &);
+
+       /** Determines the source directory of a package.  Pkg-config is consulted
+       first, and if it fails, the package path is searched for matches. */
+       Msp::FS::Path get_package_location(const std::string &);
+};
+
+#endif
index 246a6db5187db78ac9b88264b171f8f9b2530dba..d66a36fb4b247c289db1825df1f8c2e667fb7543 100644 (file)
@@ -143,7 +143,7 @@ void SourcePackage::do_configure(const StringMap &opts, unsigned flag)
                {
                        const StringList &reqs = i->get_requires();
                        for(StringList::const_iterator j=reqs.begin(); j!=reqs.end(); ++j)
-                               if(Package *pkg = builder.get_package(*j))
+                               if(Package *pkg = builder.get_package_manager().find_package(*j))
                                        requires.push_back(pkg);
                }