X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbuildercli.cpp;h=bf53c2912dfd59c964a9e8d96f26e14796105eea;hb=7c2db9e2b91da953701be233336c5bfa1f3c4af0;hp=bcd439e854c6fc9afb05df7832c0e192c3f87845;hpb=1dad660f7bbda5ef3239fd6374e0f8a77e19eaaa;p=builder.git diff --git a/source/buildercli.cpp b/source/buildercli.cpp index bcd439e..bf53c29 100644 --- a/source/buildercli.cpp +++ b/source/buildercli.cpp @@ -8,11 +8,14 @@ #include "buildercli.h" #include "filetarget.h" #include "sourcepackage.h" +#include "tool.h" +#include "toolchain.h" using namespace std; using namespace Msp; BuilderCLI::BuilderCLI(int argc, char **argv): + RegisteredApplication("builder"), analyzer(0), build(false), clean(0), @@ -63,10 +66,17 @@ BuilderCLI::BuilderCLI(int argc, char **argv): getopt.add_option( "max-depth", max_depth, GetOpt::REQUIRED_ARG).set_help("Show up to NUM levels in analysis.", "NUM"); getopt.add_option( "prefix", prefix, GetOpt::REQUIRED_ARG).set_help("Install things to DIR.", "DIR"); getopt.add_option( "tempdir", tempdir, GetOpt::REQUIRED_ARG).set_help("Store temporary files in DIR.", "DIR"); - usagemsg = getopt.generate_usage(argv[0])+" [ ...]"; - helpmsg = getopt.generate_help(); + getopt.add_argument("target", cmdline_targets, GetOpt::OPTIONAL_ARG).set_help("Target(s) to build"); getopt(argc, argv); + if(help) + { + helpmsg = "Usage:\n "; + helpmsg += getopt.generate_usage(argv[0], true); + helpmsg += "\n\n"; + helpmsg += getopt.generate_help(); + } + if(silent) --verbose; if(verbose>=1) @@ -85,12 +95,9 @@ BuilderCLI::BuilderCLI(int argc, char **argv): logger.enable_channel("files"); logger.enable_channel("auxcommands"); } - for(list::const_iterator i=log_channels.begin(); i!=log_channels.end(); ++i) - { - vector parts = split(*i, ','); - for(vector::const_iterator j=parts.begin(); j!=parts.end(); ++j) - logger.enable_channel(*j); - } + for(const string &c: log_channels) + for(const string &p: split(c, ',')) + logger.enable_channel(p); builder.set_logger(&logger); if(!analyze_mode.empty()) @@ -114,14 +121,16 @@ BuilderCLI::BuilderCLI(int argc, char **argv): else if(!clean && !create_makefile) build = true; - const vector &args = getopt.get_args(); - for(vector::const_iterator i=args.begin(); i!=args.end(); ++i) + for(auto i=cmdline_targets.begin(); i!=cmdline_targets.end(); ) { string::size_type equal = i->find('='); if(equal!=string::npos) + { cmdline_options.insert(Config::InputOptions::value_type(i->substr(0, equal), i->substr(equal+1))); + cmdline_targets.erase(i++); + } else - cmdline_targets.push_back(*i); + ++i; } if(!work_dir.empty()) @@ -133,18 +142,18 @@ BuilderCLI::BuilderCLI(int argc, char **argv): 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.append_binary_package_path(FS::get_sys_data_dir()/"packages"); package_manager.set_no_externals(no_externals); - builder.set_architecture(arch); + builder.set_architecture(tolower(arch)); list 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::const_iterator i=start_files.begin(); i!=start_files.end(); ++i) - if(FS::exists(*i)) - builder.load_build_file(*i); + start_files.push_back(FS::get_sys_data_dir()/"builderrc"); + start_files.push_back(FS::get_user_data_dir()/"rc"); + for(const FS::Path &f: start_files) + if(FS::exists(f)) + builder.load_build_file(f); if(!prefix.empty()) builder.set_prefix(cwd/prefix); @@ -156,6 +165,18 @@ BuilderCLI::BuilderCLI(int argc, char **argv): builder.set_build_type(build_type); builder.add_default_tools(); + + const Toolchain &toolchain = builder.get_toolchain(); + for(auto i=cmdline_options.begin(); i!=cmdline_options.end(); ) + { + if(toolchain.has_tool(i->first)) + { + toolchain.get_tool(i->first).set_command(i->second); + cmdline_options.erase(i++); + } + else + ++i; + } } BuilderCLI::~BuilderCLI() @@ -166,26 +187,24 @@ BuilderCLI::~BuilderCLI() int BuilderCLI::main() { FS::Path main_file = cwd/build_file; - if(!FS::exists(main_file)) + if(FS::exists(main_file)) { - if(help) - { - usage(0, "builder", false); - return 0; - } - else - { - IO::print(IO::cerr, "The file %s does not exist.\n", main_file); - return 1; - } + builder.load_build_file(main_file, &cmdline_options, conf_all); + if(!dry_run && !cmdline_options.empty()) + builder.save_caches(); + } + else if(!help) + { + IO::print(IO::cerr, "The file %s does not exist.\n", main_file); + return 1; } - - builder.load_build_file(main_file, &cmdline_options, conf_all); if(help) { - usage(0, "builder", false); - IO::print("\n"); + IO::print("Builder 1.0\n" + "Copyright © 2006-2013 Mikkosoft Productions, Mikko Rasa\n" + "Licensed under the GPL\n\n" + "%s", helpmsg); package_help(); return 0; } @@ -211,26 +230,24 @@ int BuilderCLI::main() BuildGraph &build_graph = builder.get_build_graph(); PackageManager &package_manager = builder.get_package_manager(); - const PackageManager::PackageMap &packages = package_manager.get_packages(); list package_details; - for(PackageManager::PackageMap::const_iterator i=packages.begin(); i!=packages.end(); ++i) + for(const auto &kvp: package_manager.get_packages()) { - if(!i->second->is_prepared()) + if(!kvp.second->is_prepared()) continue; - string line = i->second->get_name(); - if(dynamic_cast(i->second)) + string line = kvp.second->get_name(); + if(dynamic_cast(kvp.second)) { line += '*'; unsigned count = 0; unsigned to_be_built = 0; - 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) + for(const auto &kvp2: build_graph.get_targets()) + if(kvp2.second->get_package()==kvp.second) { ++count; - if(j->second->needs_rebuild()) + if(kvp2.second->needs_rebuild()) ++to_be_built; } if(count) @@ -246,18 +263,18 @@ int BuilderCLI::main() } logger.log("summary", format("%d active packages, %d targets", package_details.size(), build_graph.get_targets().size())); - for(list::const_iterator i=package_details.begin(); i!=package_details.end(); ++i) - logger.log("packages", *i); + for(const string &d: package_details) + logger.log("packages", d); if(analyzer) analyzer->analyze(); - const Builder::ProblemList &problems = builder.get_problems(); - if(!problems.empty()) + if(build_graph.get_goals().is_broken()) { + list problems = builder.collect_problems(); IO::print(IO::cerr, "The following problems were detected:\n"); - for(Builder::ProblemList::const_iterator i=problems.begin(); i!=problems.end(); ++i) - IO::print(IO::cerr, " %s: %s\n", i->package, i->descr); + for(const string &p: problems) + IO::print(IO::cerr, " %s\n", p); if(!analyzer) IO::print(IO::cerr, "Please fix them and try again.\n"); return 1; @@ -268,6 +285,9 @@ int BuilderCLI::main() if(build) exit_code = builder.build(jobs, dry_run, show_progress); + if(!dry_run) + builder.save_caches(); + return exit_code; } @@ -278,21 +298,16 @@ bool BuilderCLI::prepare_build() during preparation. */ BuildGraph &build_graph = builder.get_build_graph(); PackageManager &package_manager = builder.get_package_manager(); - VirtualFileSystem &vfs = builder.get_vfs(); package_manager.get_main_package().prepare(); // Add targets from command line as goals - for(NameList::iterator i=cmdline_targets.begin(); i!=cmdline_targets.end(); ++i) + for(const string &t: cmdline_targets) { - Target *tgt = build_graph.get_target(*i); - if(!tgt) - tgt = vfs.get_target(*i); - if(!tgt) - tgt = vfs.get_target(cwd/ *i); + Target *tgt = resolve_target(t); if(!tgt) { - IO::print("I don't know anything about %s\n", *i); + IO::print("I don't know anything about %s\n", t); return false; } @@ -302,12 +317,12 @@ bool BuilderCLI::prepare_build() build_graph.prepare(); // Apply what-ifs - for(NameList::iterator i=what_if.begin(); i!=what_if.end(); ++i) + for(const string &w: what_if) { - FileTarget *tgt = vfs.get_target(cwd/ *i); + FileTarget *tgt = dynamic_cast(resolve_target(w)); if(!tgt) { - IO::print(IO::cerr, "Unknown what-if target %s\n", *i); + IO::print(IO::cerr, "Unknown what-if target %s\n", w); return false; } tgt->touch(); @@ -317,56 +332,61 @@ bool BuilderCLI::prepare_build() build_graph.force_full_rebuild(); if(!dry_run) - { - const PackageManager::PackageMap &packages = package_manager.get_packages(); - for(PackageManager::PackageMap::const_iterator i=packages.begin(); i!=packages.end(); ++i) - i->second->save_caches(); - } + package_manager.save_all_caches(); return true; } -void BuilderCLI::usage(const char *reason, const char *argv0, bool brief) +Target *BuilderCLI::resolve_target(const string &name) { - if(reason) - IO::print(IO::cerr, "%s\n", reason); - - if(brief) - IO::print(IO::cerr, "Usage: %s\n", usagemsg); - else - { - IO::print(IO::cerr, "Builder 1.0\n\n"); - IO::print(IO::cerr, "Usage: %s [options] [ ...]\n\n", argv0); - IO::print(IO::cerr, "Options:\n"); - IO::print(IO::cerr, helpmsg); - } + Target *tgt = builder.get_build_graph().get_target(name); + if(!tgt) + tgt = builder.get_vfs().get_target(cwd/name); + return tgt; } void BuilderCLI::package_help() { PackageManager &package_manager = builder.get_package_manager(); + if(package_manager.get_packages().empty()) + return; + SourcePackage &main_pkg = dynamic_cast(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 Package::Requirements &requires = main_pkg.get_required_packages(); - for(Package::Requirements::const_iterator i=requires.begin(); i!=requires.end(); ++i) + + if(!requires.empty() || !options.empty()) + IO::print("\nHelp for package %s:\n", main_pkg.get_name()); + + if(!requires.empty()) { - if(i!=requires.begin()) - IO::print(", "); - IO::print((*i)->get_name()); + IO::print("\nRequired packages:\n "); + for(auto i=requires.begin(); i!=requires.end(); ++i) + { + if(i!=requires.begin()) + IO::print(", "); + IO::print((*i)->get_name()); + } + IO::print("\n"); } - IO::print("\n\nPackage configuration:\n"); - for(Config::OptionMap::const_iterator i=options.begin(); i!=options.end(); ++i) + + if(!options.empty()) { - const Config::Option &opt = i->second; - IO::print(" %s: %s (%s)", opt.name, opt.description, opt.value); - if(opt.value!=opt.default_value) - IO::print(" [%s]", opt.default_value); - IO::print("\n"); + IO::print("\nPackage configuration:\n"); + for(const auto &kvp: options) + { + const Config::Option &opt = kvp.second; + string line = format(" %s: %s (%s)", opt.name, opt.description, opt.value); + if(!opt.choices.empty()) + { + line += " {"; + line += join(opt.choices.begin(), opt.choices.end(), " "); + line += '}'; + } + else if(opt.value!=opt.default_value) + line += format(" [%s]", opt.default_value); + IO::print("%s\n", line); + } } } - -string BuilderCLI::usagemsg; -string BuilderCLI::helpmsg;