]> git.tdb.fi Git - builder.git/blobdiff - source/builder.cpp
Implement PackageManager::get_package
[builder.git] / source / builder.cpp
index e6619b1382ff91b02846117c264af9645b382472..c599e269408adb38d4b38c75808d19ef71dc83a6 100644 (file)
@@ -21,6 +21,7 @@
 #include "gnucxxcompiler.h"
 #include "gnulinker.h"
 #include "installedfile.h"
+#include "mingwdlltool.h"
 #include "package.h"
 #include "pkgconfiggenerator.h"
 #include "sharedlibrary.h"
@@ -34,10 +35,10 @@ using namespace Msp;
 
 Builder::Builder(int argc, char **argv):
        package_manager(*this),
-       main_pkg(0),
        native_arch(*this, string()),
        build_type(0),
        vfs(*this),
+       build_graph(*this),
        analyzer(0),
        build(false),
        clean(0),
@@ -56,7 +57,6 @@ Builder::Builder(int argc, char **argv):
        string work_dir;
        bool full_paths = false;
        unsigned max_depth = 4;
-       StringList cmdline_warn;
        string prfx;
        string temp_str;
        string arch;
@@ -68,7 +68,7 @@ Builder::Builder(int argc, char **argv):
 
        GetOpt getopt;
        getopt.add_option('a', "analyze",    analyze_mode,  GetOpt::REQUIRED_ARG).set_help("Perform dependency analysis.", "MODE");
-       getopt.add_option('b', "build",      build,         GetOpt::NO_ARG).set_help("Perform build even if doing analysis.");
+       getopt.add_option('b', "build",      build,         GetOpt::NO_ARG).set_help("Perform build even if also doing something else.");
        getopt.add_option('c', "clean",      clean,         GetOpt::NO_ARG).set_help("Clean buildable targets.");
        getopt.add_option('f', "file",       build_file,    GetOpt::REQUIRED_ARG).set_help("Read build instructions from FILE.", "FILE");
        getopt.add_option('h', "help",       help,          GetOpt::NO_ARG).set_help("Print this message.");
@@ -145,19 +145,20 @@ Builder::Builder(int argc, char **argv):
        {
                string::size_type equal = i->find('=');
                if(equal!=string::npos)
-                       cmdline_options.insert(StringMap::value_type(i->substr(0, equal), i->substr(equal+1)));
+                       cmdline_options.insert(Config::InputOptions::value_type(i->substr(0, equal), i->substr(equal+1)));
                else
                        cmdline_targets.push_back(*i);
        }
 
-       if(cmdline_targets.empty())
-               cmdline_targets.push_back("default");
-
        if(!work_dir.empty())
                FS::chdir(work_dir);
 
        cwd = FS::getcwd();
 
+       package_manager.append_package_path(cwd);
+       package_manager.append_package_path(cwd/"..");
+       package_manager.append_binary_package_path(FS::get_sys_data_dir(argv[0], "builder"));
+
        package_manager.set_no_externals(no_externals);
 
        if(arch.empty())
@@ -165,8 +166,12 @@ Builder::Builder(int argc, char **argv):
        else
                current_arch = new Architecture(*this, arch);
 
-       load_build_file((FS::get_sys_data_dir(argv[0], "builder")/"builderrc").str());
-       load_build_file((FS::get_user_data_dir("builder")/"rc").str());
+       list<FS::Path> start_files;
+       start_files.push_back(FS::get_sys_data_dir(argv[0], "builder")/"builderrc");
+       start_files.push_back(FS::get_user_data_dir("builder")/"rc");
+       for(list<FS::Path>::const_iterator i=start_files.begin(); i!=start_files.end(); ++i)
+               if(FS::exists(*i))
+                       load_build_file(*i);
 
        if(prfx.empty())
        {
@@ -196,18 +201,19 @@ Builder::Builder(int argc, char **argv):
        toolchain.add_tool(new Copy(*this));
        toolchain.add_tool(new Tar(*this));
        toolchain.add_tool(new PkgConfigGenerator(*this));
+       if(current_arch->get_system()=="windows")
+               toolchain.add_tool(new MingwDllTool(*this, *current_arch));
 }
 
 Builder::~Builder()
 {
-       for(TargetMap::iterator i=targets.begin(); i!=targets.end(); ++i)
-               delete i->second;
        delete analyzer;
 }
 
 int Builder::main()
 {
-       if(load_build_file(cwd/build_file))
+       FS::Path main_file = cwd/build_file;
+       if(!FS::exists(main_file))
        {
                if(help)
                {
@@ -216,11 +222,13 @@ int Builder::main()
                }
                else
                {
-                       IO::print(IO::cerr, "No build info here.\n");
+                       IO::print(IO::cerr, "The file %s does not exist.\n", main_file);
                        return 1;
                }
        }
 
+       load_build_file(main_file);
+
        if(help)
        {
                usage(0, "builder", false);
@@ -249,7 +257,7 @@ int Builder::main()
        list<string> package_details;
        for(PackageManager::PackageMap::const_iterator i=packages.begin(); i!=packages.end(); ++i)
        {
-               if(!i->second || !i->second->is_prepared())
+               if(!i->second->is_prepared())
                        continue;
 
                string line = i->second->get_name();
@@ -259,7 +267,8 @@ int Builder::main()
 
                        unsigned count = 0;
                        unsigned to_be_built = 0;
-                       for(TargetMap::iterator j=targets.begin(); j!=targets.end(); ++j)
+                       const BuildGraph::TargetMap &targets = build_graph.get_targets();
+                       for(BuildGraph::TargetMap::const_iterator j=targets.begin(); j!=targets.end(); ++j)
                                if(j->second->get_package()==i->second)
                                {
                                        ++count;
@@ -278,7 +287,7 @@ int Builder::main()
                package_details.push_back(line);
        }
 
-       logger.log("summary", format("%d active packages, %d targets", package_details.size(), targets.size()));
+       logger.log("summary", format("%d active packages, %d targets", package_details.size(), build_graph.get_targets().size()));
        for(list<string>::const_iterator i=package_details.begin(); i!=package_details.end(); ++i)
                logger.log("packages", *i);
 
@@ -297,38 +306,17 @@ int Builder::main()
 
        if(clean)
                exit_code = do_clean();
-       else if(build)
+       if(build)
                exit_code = do_build();
 
        return exit_code;
 }
 
-Target *Builder::get_target(const string &n) const
-{
-       TargetMap::const_iterator i = targets.find(n);
-       if(i!=targets.end())
-               return i->second;
-       return 0;
-}
-
 void Builder::problem(const string &p, const string &d)
 {
        problems.push_back(Problem(p, d));
 }
 
-void Builder::add_target(Target *t)
-{
-       targets.insert(TargetMap::value_type(t->get_name(), t));
-}
-
-void Builder::add_primary_target(Target &t)
-{
-       get_target("world")->add_dependency(t);
-
-       if(t.get_package()==main_pkg && t.get_component() && t.get_component()->is_default())
-               get_target("default")->add_dependency(t);
-}
-
 void Builder::usage(const char *reason, const char *argv0, bool brief)
 {
        if(reason)
@@ -345,11 +333,8 @@ void Builder::usage(const char *reason, const char *argv0, bool brief)
        }
 }
 
-int Builder::load_build_file(const FS::Path &fn)
+void Builder::load_build_file(const FS::Path &fn)
 {
-       if(!FS::exists(fn))
-               return -1;
-
        IO::BufferedFile in(fn.str());
 
        logger.log("files", format("Reading %s", fn));
@@ -357,30 +342,16 @@ int Builder::load_build_file(const FS::Path &fn)
        DataFile::Parser parser(in, fn.str());
        Loader loader(*this);
        loader.load(parser);
-
-       return 0;
 }
 
 bool Builder::prepare_build()
 {
-       Target *world = new VirtualTarget(*this, "world");
-
-       Target *def_tgt = new VirtualTarget(*this, "default");
-       world->add_dependency(*def_tgt);
+       package_manager.get_main_package().prepare();
 
-       Target *install = new VirtualTarget(*this, "install");
-       world->add_dependency(*install);
-
-       Target *tarballs = new VirtualTarget(*this, "tarballs");
-       world->add_dependency(*tarballs);
-
-       main_pkg->prepare();
-
-       // Make the cmdline target depend on all targets mentioned on the command line
-       Target *cmdline = new VirtualTarget(*this, "cmdline");
-       for(list<string>::iterator i=cmdline_targets.begin(); i!=cmdline_targets.end(); ++i)
+       // Add targets from command line as goals
+       for(NameList::iterator i=cmdline_targets.begin(); i!=cmdline_targets.end(); ++i)
        {
-               Target *tgt = get_target(*i);
+               Target *tgt = build_graph.get_target(*i);
                if(!tgt)
                        tgt = vfs.get_target(*i);
                if(!tgt)
@@ -391,13 +362,13 @@ bool Builder::prepare_build()
                        return false;
                }
 
-               cmdline->add_dependency(*tgt);
+               build_graph.add_goal(*tgt);
        }
 
-       cmdline->prepare();
+       build_graph.prepare();
 
        // Apply what-ifs
-       for(StringList::iterator i=what_if.begin(); i!=what_if.end(); ++i)
+       for(NameList::iterator i=what_if.begin(); i!=what_if.end(); ++i)
        {
                FileTarget *tgt = vfs.get_target(cwd/ *i);
                if(!tgt)
@@ -409,11 +380,7 @@ bool Builder::prepare_build()
        }
 
        if(build_all)
-       {
-               for(TargetMap::iterator i=targets.begin(); i!=targets.end(); ++i)
-                       if(i->second->is_buildable() && !i->second->needs_rebuild())
-                               i->second->force_rebuild();
-       }
+               build_graph.force_full_rebuild();
 
        if(!dry_run)
        {
@@ -427,12 +394,7 @@ bool Builder::prepare_build()
 
 int Builder::do_build()
 {
-       Target *cmdline = get_target("cmdline");
-
-       unsigned total = 0;
-       for(map<string, Target *>::const_iterator i=targets.begin(); i!=targets.end(); ++i)
-               if(i->second->is_buildable() && i->second->needs_rebuild())
-                       ++total;
+       unsigned total = build_graph.count_rebuild_targets();
 
        if(!total)
        {
@@ -453,7 +415,7 @@ int Builder::do_build()
        {
                if(tasks.size()<jobs && !fail && !starved)
                {
-                       Target *tgt = cmdline->get_buildable_target();
+                       Target *tgt = build_graph.get_buildable_target();
                        if(tgt)
                        {
                                if(tgt->get_tool())
@@ -533,14 +495,14 @@ int Builder::do_clean()
 
        set<Target *> clean_tgts;
        list<Target *> queue;
-       queue.push_back(get_target("cmdline"));
+       queue.push_back(build_graph.get_target("cmdline"));
 
        while(!queue.empty())
        {
                Target *tgt = queue.front();
                queue.erase(queue.begin());
 
-               if(tgt->is_buildable() && (tgt->get_package()==main_pkg || clean>=2))
+               if(tgt->is_buildable() && (tgt->get_package()==&package_manager.get_main_package() || clean>=2))
                        clean_tgts.insert(tgt);
 
                const Target::Dependencies &deps = tgt->get_dependencies();
@@ -561,12 +523,13 @@ int Builder::do_clean()
 
 void Builder::package_help()
 {
-       const Config &config = main_pkg->get_config();
+       SourcePackage &main_pkg = dynamic_cast<SourcePackage &>(package_manager.get_main_package());
+       const Config &config = main_pkg.get_config();
        const Config::OptionMap &options = config.get_options();
 
        IO::print("Required packages:\n  ");
-       const PackageList &requires = main_pkg->get_required_packages();
-       for(PackageList::const_iterator i=requires.begin(); i!=requires.end(); ++i)
+       const Package::Requirements &requires = main_pkg.get_required_packages();
+       for(Package::Requirements::const_iterator i=requires.begin(); i!=requires.end(); ++i)
        {
                if(i!=requires.begin())
                        IO::print(", ");
@@ -626,10 +589,8 @@ void Builder::Loader::profile(const string &)
 void Builder::Loader::package(const string &n)
 {
        SourcePackage *pkg = new SourcePackage(obj, n, get_source());
-       if(!obj.main_pkg)
-               obj.main_pkg = pkg;
 
-       if(obj.conf_all || pkg==obj.main_pkg)
+       if(obj.conf_all || pkg==&obj.package_manager.get_main_package())
                load_sub(*pkg, obj.cmdline_options);
        else
                load_sub(*pkg);