From bd3176cbbd40e8f22c513ea30e94eb415c3ed3c3 Mon Sep 17 00:00:00 2001 From: q66 Date: Tue, 24 Apr 2018 01:50:55 +0200 Subject: [PATCH] restructure octabuild --- main.cc | 314 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 163 insertions(+), 151 deletions(-) diff --git a/main.cc b/main.cc index 7d96814..7d4e789 100644 --- a/main.cc +++ b/main.cc @@ -27,165 +27,86 @@ using cscript::cs_bcode; namespace fs = ostd::fs; namespace build = ostd::build; -struct ob_state: cs_state { - void rule_add( - build::make &mk, string_range tgt, string_range dep, cs_bcode *body, - bool action = false - ) { - cscript::util::ListParser p{*this, tgt}; - while (p.parse()) { - auto &rl = mk.rule(p.get_item()).action(action); - cscript::util::ListParser lp{*this, dep}; - while (lp.parse()) { - rl.depend(lp.get_item()); - } - if (cscript::cs_code_is_empty(body)) { - continue; - } - rl.body([body = cs_bcode_ref(body), this](auto tgt, auto srcs) { - cs_stacked_value targetv, sourcev, sourcesv; +static void rule_add( + cs_state &cs, build::make &mk, + string_range target, string_range depends, + cs_bcode *body, bool action = false +) { + cscript::util::ListParser p{cs, target}; + while (p.parse()) { + auto &rl = mk.rule(p.get_item()).action(action); + cscript::util::ListParser lp{cs, depends}; + while (lp.parse()) { + rl.depend(lp.get_item()); + } + if (cscript::cs_code_is_empty(body)) { + continue; + } + rl.body([body = cs_bcode_ref(body), &cs](auto tgt, auto srcs) { + cs_stacked_value targetv, sourcev, sourcesv; - if (!targetv.set_alias(new_ident("target"))) { + if (!targetv.set_alias(cs.new_ident("target"))) { + throw build::make_error{ + "internal error: could not set alias 'target'" + }; + } + targetv.set_cstr(tgt); + targetv.push(); + + if (!srcs.empty()) { + if (!sourcev.set_alias(cs.new_ident("source"))) { throw build::make_error{ - "internal error: could not set alias 'target'" + "internal error: could not set alias 'source'" }; } - targetv.set_cstr(tgt); - targetv.push(); - - if (!srcs.empty()) { - if (!sourcev.set_alias(new_ident("source"))) { - throw build::make_error{ - "internal error: could not set alias 'source'" - }; - } - if (!sourcesv.set_alias(new_ident("sources"))) { - throw build::make_error{ - "internal error: could not set alias 'sources'" - }; - } - - sourcev.set_cstr(srcs[0]); - sourcev.push(); - - auto dsv = ostd::appender(); - ostd::format(dsv, "%(%s %)", srcs); - sourcesv.set_str(std::move(dsv.get())); - sourcesv.push(); + if (!sourcesv.set_alias(cs.new_ident("sources"))) { + throw build::make_error{ + "internal error: could not set alias 'sources'" + }; } - try { - this->run(body); - } catch (cscript::cs_error const &e) { - throw build::make_error{e.what()}; - } - }); - } - } + sourcev.set_cstr(srcs[0]); + sourcev.push(); - void register_rulecmds(build::make &mk) { - new_command("rule", "sse", [this, &mk](auto &, auto args, auto &) { - this->rule_add( - mk, args[0].get_strr(), args[1].get_strr(), args[2].get_code() - ); + auto dsv = ostd::appender(); + ostd::format(dsv, "%(%s %)", srcs); + sourcesv.set_str(std::move(dsv.get())); + sourcesv.push(); + } + + try { + cs.run(body); + } catch (cscript::cs_error const &e) { + throw build::make_error{e.what()}; + } }); - - new_command("action", "se", [this, &mk](auto &, auto args, auto &) { - this->rule_add( - mk, args[0].get_strr(), nullptr, args[1].get_code(), true - ); - }); - - new_command("depend", "ss", [this, &mk](auto &, auto args, auto &) { - this->rule_add(mk, args[0].get_strr(), args[1].get_strr(), nullptr); - }); - } -}; +} -void do_main(int argc, char **argv) { - ob_state os; - os.init_libs(); +static void init_rulelib(cs_state &cs, build::make &mk) { + cs.new_command("rule", "sse", [&cs, &mk](auto &, auto args, auto &) { + rule_add( + cs, mk, args[0].get_strr(), args[1].get_strr(), args[2].get_code() + ); + }); - bool ignore_env = false; + cs.new_command("action", "se", [&cs, &mk](auto &, auto args, auto &) { + rule_add( + cs, mk, args[0].get_strr(), nullptr, args[1].get_code(), true + ); + }); - int ncpus = std::thread::hardware_concurrency(); - os.new_ivar("numcpus", 4096, 1, ncpus); + cs.new_command("depend", "ss", [&cs, &mk](auto &, auto args, auto &) { + rule_add(cs, mk, args[0].get_strr(), args[1].get_strr(), nullptr); + }); +} - ostd::arg_parser ap; - - auto &help = ap.add_optional("-h", "--help", 0) - .help("print this message and exit") - .action(ostd::arg_print_help(ap)); - - int jobs = 1; - ap.add_optional("-j", "--jobs", 1) - .help("specify the number of jobs to use (default: 1)") - .action(ostd::arg_store_format("%d", jobs)); - - std::string curdir; - ap.add_optional("-C", "--change-directory", 1) - .help("change to DIRECTORY before running") - .metavar("DIRECTORY") - .action(ostd::arg_store_str(curdir)); - - std::string deffile = "obuild.cfg"; - ap.add_optional("-f", "--file", 1) - .help("specify the file to run (default: obuild.cfg)") - .action(ostd::arg_store_str(deffile)); - - std::string fcont; - ap.add_optional("-e", "--execute", 1) - .help("evaluate a string instead of a file") - .metavar("STR") - .action(ostd::arg_store_str(fcont)); - - ap.add_optional("-E", "--ignore-env", 0) - .help("ignore environment variables") - .action(ostd::arg_store_true(ignore_env)); - - std::string action = "default"; - ap.add_positional("action", ostd::arg_value::OPTIONAL) - .help("the action to perform") - .action(ostd::arg_store_str(action)); - - try { - ap.parse(argc, argv); - } catch (ostd::arg_error const &e) { - ostd::cerr.writefln("%s: %s", argv[0], e.what()); - ap.print_help(ostd::cerr.iter()); - throw build::make_error{""}; - } - - if (help.used()) { - return; - } - - if (!jobs) { - jobs = ncpus; - } - jobs = std::max(1, jobs); - - try { - if (!curdir.empty()) { - fs::current_path(curdir); - } - } catch (fs::fs_error const &e) { - throw build::make_error{ - "failed changing directory: %s (0s)", curdir, e.what() - }; - } - - os.new_ivar("numjobs", 4096, 1, jobs); - - build::make mk{build::make_task_simple, jobs}; - os.register_rulecmds(mk); - - os.new_command("echo", "C", [](auto &, auto args, auto &) { +static void init_baselib(cs_state &cs, build::make &mk, bool ignore_env) { + cs.new_command("echo", "C", [](auto &, auto args, auto &) { writeln(args[0].get_strr()); }); - os.new_command("shell", "C", [&mk](auto &, auto args, auto &) { + cs.new_command("shell", "C", [&mk](auto &, auto args, auto &) { mk.push_task([ds = std::string(args[0].get_strr())]() { if (system(ds.data())) { throw build::make_error{""}; @@ -193,7 +114,7 @@ void do_main(int argc, char **argv) { }); }); - os.new_command("getenv", "ss", [ignore_env](auto &, auto args, auto &res) { + cs.new_command("getenv", "ss", [ignore_env](auto &, auto args, auto &res) { if (ignore_env) { res.set_cstr(""); return; @@ -203,7 +124,13 @@ void do_main(int argc, char **argv) { )); }); - os.new_command("extreplace", "sss", [](auto &cs, auto args, auto &res) { + cs.new_command("invoke", "s", [&mk](auto &, auto args, auto &) { + mk.exec(args[0].get_strr()); + }); +} + +static void init_pathlib(cs_state &cs) { + cs.new_command("extreplace", "sss", [](auto &cs, auto args, auto &res) { string_range lst = args[0].get_strr(); string_range oldext = args[1].get_strr(); string_range newext = args[2].get_strr(); @@ -233,11 +160,7 @@ void do_main(int argc, char **argv) { res.set_str(std::move(ret)); }); - os.new_command("invoke", "s", [&mk](auto &, auto args, auto &) { - mk.exec(args[0].get_strr()); - }); - - os.new_command("glob", "C", [](auto &cs, auto args, auto &res) { + cs.new_command("glob", "C", [](auto &cs, auto args, auto &res) { auto ret = ostd::appender(); auto app = ostd::appender>(); cscript::util::ListParser p{cs, args[0].get_strr()}; @@ -247,11 +170,100 @@ void do_main(int argc, char **argv) { ostd::format(ret, "%(%s %)", app.get()); res.set_str(std::move(ret.get())); }); +} - if ((!fcont.empty() && !os.run_bool(fcont)) || !os.run_file(deffile)) { +void do_main(int argc, char **argv) { + /* cubescript interpreter */ + cs_state cs; + cs.init_libs(); + + /* arg values */ + std::string action = "default"; + std::string deffile = "obuild.cfg"; + std::string curdir; + std::string fcont; + bool ignore_env = false; + int jobs = 1; + + /* input options */ + { + ostd::arg_parser ap; + + auto &help = ap.add_optional("-h", "--help", 0) + .help("print this message and exit") + .action(ostd::arg_print_help(ap)); + + ap.add_optional("-j", "--jobs", 1) + .help("specify the number of jobs to use (default: 1)") + .action(ostd::arg_store_format("%d", jobs)); + + ap.add_optional("-C", "--change-directory", 1) + .help("change to DIRECTORY before running") + .metavar("DIRECTORY") + .action(ostd::arg_store_str(curdir)); + + ap.add_optional("-f", "--file", 1) + .help("specify the file to run (default: obuild.cfg)") + .action(ostd::arg_store_str(deffile)); + + ap.add_optional("-e", "--execute", 1) + .help("evaluate a string instead of a file") + .metavar("STR") + .action(ostd::arg_store_str(fcont)); + + ap.add_optional("-E", "--ignore-env", 0) + .help("ignore environment variables") + .action(ostd::arg_store_true(ignore_env)); + + ap.add_positional("action", ostd::arg_value::OPTIONAL) + .help("the action to perform") + .action(ostd::arg_store_str(action)); + + try { + ap.parse(argc, argv); + } catch (ostd::arg_error const &e) { + ostd::cerr.writefln("%s: %s", argv[0], e.what()); + ap.print_help(ostd::cerr.iter()); + throw build::make_error{""}; + } + + if (help.used()) { + return; + } + } + + int ncpus = std::thread::hardware_concurrency(); + jobs = std::max(1, jobs ? jobs : ncpus); + + /* core cubescript variables */ + cs.new_ivar("numcpus", 4096, 1, ncpus); + cs.new_ivar("numjobs", 4096, 1, jobs); + + /* switch to target directory */ + try { + if (!curdir.empty()) { + fs::current_path(curdir); + } + } catch (fs::fs_error const &e) { + throw build::make_error{ + "failed changing directory: %s (%s)", curdir, e.what() + }; + } + + /* init buildsystem, use simple tasks, cubescript cannot into coroutines */ + build::make mk{build::make_task_simple, jobs}; + + /* octabuild cubescript libs */ + init_rulelib(cs, mk); + init_baselib(cs, mk, ignore_env); + init_pathlib(cs); + + /* parse rules */ + if ((!fcont.empty() && !cs.run_bool(fcont)) || !cs.run_file(deffile)) { throw build::make_error{"failed creating rules"}; } + /* make */ mk.exec(action); }