diff options
Diffstat (limited to 'build2/cli/rule.cxx')
-rw-r--r-- | build2/cli/rule.cxx | 336 |
1 files changed, 0 insertions, 336 deletions
diff --git a/build2/cli/rule.cxx b/build2/cli/rule.cxx deleted file mode 100644 index 99b6bee..0000000 --- a/build2/cli/rule.cxx +++ /dev/null @@ -1,336 +0,0 @@ -// file : build2/cli/rule.cxx -*- C++ -*- -// license : MIT; see accompanying LICENSE file - -#include <build2/cli/rule.hxx> - -#include <libbuild2/depdb.hxx> -#include <libbuild2/scope.hxx> -#include <libbuild2/target.hxx> -#include <libbuild2/context.hxx> -#include <libbuild2/algorithm.hxx> -#include <libbuild2/filesystem.hxx> -#include <libbuild2/diagnostics.hxx> - -#include <build2/cli/target.hxx> - -namespace build2 -{ - namespace cli - { - // Figure out if name contains stem and, optionally, calculate prefix and - // suffix. - // - static bool - match_stem (const string& name, const string& stem, - string* prefix = nullptr, string* suffix = nullptr) - { - size_t p (name.find (stem)); - - if (p != string::npos) - { - if (prefix != nullptr) - prefix->assign (name, 0, p); - - if (suffix != nullptr) - suffix->assign (name, p + stem.size (), string::npos); - - return true; - } - - return false; - } - - bool compile_rule:: - match (action a, target& t, const string&) const - { - tracer trace ("cli::compile_rule::match"); - - // Find the .cli source file. - // - auto find = [&trace, a, &t] (auto&& r) -> optional<prerequisite_member> - { - for (prerequisite_member p: r) - { - // If excluded or ad hoc, then don't factor it into our tests. - // - if (include (a, t, p) != include_type::normal) - continue; - - if (p.is_a<cli> ()) - { - // Check that the stem match. - // - if (match_stem (t.name, p.name ())) - return p; - - l4 ([&]{trace << ".cli file stem '" << p.name () << "' " - << "doesn't match target " << t;}); - } - } - - return nullopt; - }; - - if (cli_cxx* pt = t.is_a<cli_cxx> ()) - { - // The cli.cxx{} group. - // - cli_cxx& t (*pt); - - // See if we have a .cli source file. - // - if (!find (group_prerequisite_members (a, t))) - { - l4 ([&]{trace << "no .cli source file for target " << t;}); - return false; - } - - // Figure out the member list. - // - // At this stage, no further changes to cli.options are possible and - // we can determine whether the --suppress-inline option is present. - // - // Passing the group as a "reference target" is a bit iffy, - // conceptually. - // - t.h = &search<cxx::hxx> (t, t.dir, t.out, t.name); - t.c = &search<cxx::cxx> (t, t.dir, t.out, t.name); - t.i = find_option ("--suppress-inline", t, "cli.options") - ? nullptr - : &search<cxx::ixx> (t, t.dir, t.out, t.name); - - return true; - } - else - { - // One of the ?xx{} members. - // - - // Check if there is a corresponding cli.cxx{} group. - // - const cli_cxx* g (t.ctx.targets.find<cli_cxx> (t.dir, t.out, t.name)); - - // If not or if it has no prerequisites (happens when we use it to - // set cli.options) and this target has a cli{} prerequisite, then - // synthesize the dependency. - // - if (g == nullptr || !g->has_prerequisites ()) - { - if (optional<prerequisite_member> p = find ( - prerequisite_members (a, t))) - { - if (g == nullptr) - g = &t.ctx.targets.insert<cli_cxx> (t.dir, t.out, t.name, trace); - - g->prerequisites (prerequisites {p->as_prerequisite ()}); - } - } - - if (g == nullptr) - return false; - - // For ixx{}, verify it is part of the group (i.e., not disabled - // via --suppress-inline). - // - if (t.is_a<cxx::ixx> () && - find_option ("--suppress-inline", *g, "cli.options")) - return false; - - t.group = g; - return true; - } - } - - recipe compile_rule:: - apply (action a, target& xt) const - { - if (cli_cxx* pt = xt.is_a<cli_cxx> ()) - { - cli_cxx& t (*pt); - - // Derive file names for the members. - // - t.h->derive_path (); - t.c->derive_path (); - if (t.i != nullptr) - t.i->derive_path (); - - // Inject dependency on the output directory. - // - inject_fsdir (a, t); - - // Match prerequisites. - // - match_prerequisite_members (a, t); - - // For update inject dependency on the CLI compiler target. - // - if (a == perform_update_id) - inject (a, t, ctgt); - - switch (a) - { - case perform_update_id: return [this] (action a, const target& t) - { - return perform_update (a, t); - }; - case perform_clean_id: return &perform_clean_group_depdb; - default: return noop_recipe; // Configure/dist update. - } - } - else - { - const cli_cxx& g (xt.group->as<cli_cxx> ()); - build2::match (a, g); - return group_recipe; // Execute the group's recipe. - } - } - - static void - append_extension (cstrings& args, - const path_target& t, - const char* option, - const char* default_extension) - { - const string* e (t.ext ()); - assert (e != nullptr); // Should have been figured out in apply(). - - if (*e != default_extension) - { - // CLI needs the extension with the leading dot (unless it is empty) - // while we store the extension without. But if there is an extension, - // then we can get it (with the dot) from the file name. - // - args.push_back (option); - args.push_back (e->empty () - ? e->c_str () - : t.path ().extension_cstring () - 1); - } - } - - target_state compile_rule:: - perform_update (action a, const target& xt) const - { - tracer trace ("cli::compile_rule::perform_update"); - - // The rule has been matched which means the members should be resolved - // and paths assigned. We use the header file as our "target path" for - // timestamp, depdb, etc. - // - const cli_cxx& t (xt.as<cli_cxx> ()); - const path& tp (t.h->path ()); - - // Update prerequisites and determine if any relevant ones render us - // out-of-date. Note that currently we treat all the prerequisites as - // potentially affecting the result (think prologues/epilogues, CLI - // compiler target itself, etc). - // - timestamp mt (t.load_mtime (tp)); - auto pr (execute_prerequisites<cli> (a, t, mt)); - - bool update (!pr.first); - target_state ts (update ? target_state::changed : *pr.first); - - const cli& s (pr.second); - - // We use depdb to track changes to the .cli file name, options, - // compiler, etc. - // - depdb dd (tp + ".d"); - { - // First should come the rule name/version. - // - if (dd.expect ("cli.compile 1") != nullptr) - l4 ([&]{trace << "rule mismatch forcing update of " << t;}); - - // Then the compiler checksum. - // - if (dd.expect (csum) != nullptr) - l4 ([&]{trace << "compiler mismatch forcing update of " << t;}); - - // Then the options checksum. - // - sha256 cs; - append_options (cs, t, "cli.options"); - - if (dd.expect (cs.string ()) != nullptr) - l4 ([&]{trace << "options mismatch forcing update of " << t;}); - - // Finally the .cli input file. - // - if (dd.expect (s.path ()) != nullptr) - l4 ([&]{trace << "input file mismatch forcing update of " << t;}); - } - - // Update if depdb mismatch. - // - if (dd.writing () || dd.mtime > mt) - update = true; - - dd.close (); - - // If nothing changed, then we are done. - // - if (!update) - return ts; - - // Translate paths to relative (to working directory). This results in - // easier to read diagnostics. - // - path relo (relative (t.dir)); - path rels (relative (s.path ())); - - const process_path& pp (ctgt.process_path ()); - cstrings args {pp.recall_string ()}; - - // See if we need to pass --output-{prefix,suffix} - // - string prefix, suffix; - match_stem (t.name, s.name, &prefix, &suffix); - - if (!prefix.empty ()) - { - args.push_back ("--output-prefix"); - args.push_back (prefix.c_str ()); - } - - if (!suffix.empty ()) - { - args.push_back ("--output-suffix"); - args.push_back (suffix.c_str ()); - } - - // See if we need to pass any --?xx-suffix options. - // - append_extension (args, *t.h, "--hxx-suffix", "hxx"); - append_extension (args, *t.c, "--cxx-suffix", "cxx"); - if (t.i != nullptr) - append_extension (args, *t.i, "--ixx-suffix", "ixx"); - - append_options (args, t, "cli.options"); - - if (!relo.empty ()) - { - args.push_back ("-o"); - args.push_back (relo.string ().c_str ()); - } - - args.push_back (rels.string ().c_str ()); - args.push_back (nullptr); - - if (verb >= 2) - print_process (args); - else if (verb) - text << "cli " << s; - - if (!t.ctx.dry_run) - { - run (pp, args); - dd.check_mtime (tp); - } - - t.mtime (system_clock::now ()); - return target_state::changed; - } - } -} |