X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbuilder.cpp;h=6eeaa2fa3ca3b39e05298b3bd780ff5401cccbaa;hb=HEAD;hp=6f90c9d417598747e74daedac3bb7e7e30301631;hpb=dd5f5ca28944ed2f8ddd62f8af672ed003938a8f;p=builder.git diff --git a/source/builder.cpp b/source/builder.cpp deleted file mode 100644 index 6f90c9d..0000000 --- a/source/builder.cpp +++ /dev/null @@ -1,354 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "androidtools.h" -#include "binarypackage.h" -#include "builder.h" -#include "builtintools.h" -#include "clangtools.h" -#include "datatool.h" -#include "gnutools.h" -#include "installedfile.h" -#include "microsofttools.h" -#include "package.h" -#include "sharedlibrary.h" -#include "sourcepackage.h" -#include "task.h" -#include "virtualtarget.h" - -using namespace std; -using namespace Msp; - -Builder::Builder(): - package_manager(*this), - native_arch(*this, string()), - vfs(*this), - build_graph(*this), - logger(&default_logger) -{ - set_architecture(string()); -} - -Builder::~Builder() -{ - if(current_arch!=&native_arch) - delete current_arch; -} - -void Builder::set_architecture(const string &name) -{ - if(current_arch!=&native_arch) - delete current_arch; - - if(name.empty()) - { - current_arch = &native_arch; - prefix = FS::get_home_dir()/"local"; - } - else - { - current_arch = new Architecture(*this, name); - prefix = FS::get_home_dir()/"local"/current_arch->get_name(); - } -} - -vector Builder::get_build_types() const -{ - vector keys; - keys.reserve(build_types.size()); - for(const auto &kvp: build_types) - keys.push_back(kvp.first); - return keys; -} - -const BuildType &Builder::get_build_type() const -{ - if(!build_type) - throw invalid_state("no build type"); - return *build_type; -} - -void Builder::set_build_type(const string &name) -{ - build_type = &get_item(build_types, name); -} - -void Builder::set_prefix(const FS::Path &p) -{ - prefix = p; -} - -void Builder::set_temp_directory(const FS::Path &p) -{ - tempdir = p; -} - -void Builder::add_default_tools() -{ - toolchain.add_toolchain(new GnuTools(*this, *current_arch)); - toolchain.add_toolchain(new ClangTools(*this, *current_arch)); - if(current_arch->get_system()=="android") - toolchain.add_toolchain(new AndroidTools(*this, *current_arch)); - if(current_arch->get_system()=="windows") - toolchain.add_toolchain(new MicrosoftTools(*this, *current_arch)); - toolchain.add_toolchain(new BuiltinTools(*this)); - toolchain.add_tool(new DataTool(*this)); - - auto i = find_if(toolchain.get_toolchains(), [](const Toolchain *tc){ return (tc->has_tool("CC") || tc->has_tool("CXX")); }); - if(i!=toolchain.get_toolchains().end()) - current_arch->refine((*i)->get_name()); -} - -void Builder::set_logger(const Logger *l) -{ - logger = (l ? l : &default_logger); -} - -vector Builder::collect_problems() const -{ - vector problems; - set broken_packages; - set broken_components; - set broken_tools; - - for(const auto &kvp: build_graph.get_targets()) - if(kvp.second->is_broken()) - { - for(const string &p: kvp.second->get_problems()) - problems.push_back(format("%s: %s", kvp.second->get_name(), p)); - - const Package *package = kvp.second->get_package(); - if(package && !package->get_problems().empty()) - broken_packages.insert(package); - - const Component *component = kvp.second->get_component(); - if(component && !component->get_problems().empty()) - broken_components.insert(component); - - const Tool *tool = kvp.second->get_tool(); - if(tool && !tool->get_problems().empty()) - broken_tools.insert(tool); - } - - // TODO Sort components after their packages, and targets last - for(const Package *p: broken_packages) - for(const string &b: p->get_problems()) - problems.push_back(format("%s: %s", p->get_name(), b)); - - for(const Component *c: broken_components) - for(const string &b: c->get_problems()) - problems.push_back(format("%s/%s: %s", c->get_package().get_name(), c->get_name(), b)); - - for(const Tool *t: broken_tools) - for(const string &b: t->get_problems()) - problems.push_back(format("%s: %s", t->get_tag(), b)); - - return problems; -} - -void Builder::load_build_file(const FS::Path &fn, const Config::InputOptions *opts, bool all) -{ - IO::BufferedFile in(fn.str()); - - get_logger().log("files", "Reading %s", fn); - - DataFile::Parser parser(in, fn.str()); - Loader loader(*this, opts, all); - loader.load(parser); -} - -void Builder::save_caches() -{ - for(const auto &kvp: package_manager.get_packages()) - kvp.second->save_caches(); -} - -int Builder::build(unsigned jobs, bool dry_run, bool show_progress) -{ - unsigned total = build_graph.count_rebuild_targets(); - - if(!total) - { - get_logger().log("summary", "Already up to date"); - return 0; - } - get_logger().log("summary", "Will build %d target%s", total, (total!=1 ? "s" : "")); - - vector tasks; - - unsigned count = 0; - - bool fail = false; - bool finish = false; - bool starved = false; - - while(!finish) - { - if(tasks.size()get_tool()) - { - if(show_progress) - IO::print("\033[K"); - get_logger().log("tasks", "%-4s %s", tgt->get_tool()->get_tag(), tgt->get_name()); - } - Task *task = tgt->build(); - if(task) - { - get_logger().log("commands", "%s", task->get_command()); - if(dry_run) - { - task->signal_finished.emit(true); - delete task; - } - else - { - task->start(); - tasks.push_back(task); - } - } - - if(show_progress) - IO::print("%d of %d target%s built\033[1G", count, total, (total!=1 ? "s" : "")); - } - else if(tasks.empty()) - finish = true; - else - starved = true; - } - else - Time::sleep(10*Time::msec); - - for(unsigned i=0; iwait(); - else - status = tasks[i]->check(); - - if(status!=Task::RUNNING) - { - ++count; - - delete tasks[i]; - tasks.erase(tasks.begin()+i); - if(status==Task::ERROR) - fail = true; - if(tasks.empty() && fail) - finish = true; - starved = false; - } - else - ++i; - } - } - - if(show_progress) - IO::print("\033[K"); - if(fail) - get_logger().log("summary", "Build failed"); - else if(show_progress) - get_logger().log("summary", "Build complete"); - - return fail; -} - -int Builder::clean(bool all, bool dry_run) -{ - // Cleaning doesn't care about ordering, so a simpler method can be used - - set clean_tgts; - deque queue; - queue.push_back(&build_graph.get_goals()); - - while(!queue.empty()) - { - Target *tgt = queue.front(); - queue.pop_front(); - - if(tgt->is_buildable() && (tgt->get_package()==&package_manager.get_main_package() || all)) - clean_tgts.insert(tgt); - - for(Target *t: tgt->get_dependencies()) - if(!clean_tgts.count(t)) - queue.push_back(t); - } - - for(Target *t: clean_tgts) - { - get_logger().log("tasks", "RM %s", t->get_name()); - if(!dry_run) - t->clean(); - } - - return 0; -} - - -Builder::Loader::Loader(Builder &b, const Config::InputOptions *o, bool a): - DataFile::ObjectLoader(b), - options(o), - conf_all(a) -{ - add("architecture", &Loader::architecture); - add("binary_package", &Loader::binpkg); - add("build_type", &Loader::build_type); - add("package", &Loader::package); - - if(!obj.top_loader) - obj.top_loader = this; - else if(!options && obj.top_loader!=this && obj.top_loader->conf_all) - options = obj.top_loader->options; -} - -Builder::Loader::~Loader() -{ - if(obj.top_loader==this) - obj.top_loader = 0; -} - -void Builder::Loader::architecture(const string &n) -{ - if(obj.current_arch->match_name(n)) - load_sub(*obj.current_arch); -} - -void Builder::Loader::binpkg(const string &n) -{ - BinaryPackage *pkg = new BinaryPackage(obj, n); - load_sub(*pkg); -} - -void Builder::Loader::build_type(const string &n) -{ - BuildType btype(n); - load_sub(btype); - auto i = obj.build_types.insert({ n, btype }).first; - if(!obj.build_type) - obj.build_type = &i->second; -} - -void Builder::Loader::package(const string &n) -{ - SourcePackage *pkg = new SourcePackage(obj, n, get_source()); - - load_sub(*pkg, options); - - if(obj.build_type) - pkg->set_build_type(*obj.build_type); -}