aboutsummaryrefslogtreecommitdiff
path: root/build2
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2019-07-08 14:55:35 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2019-07-24 13:53:25 +0200
commit83bb02cada0b894d9134cc5489999e0f0fe8bd7c (patch)
tree1dedff27ce2b7d54bd6b0875c9125f4dafde2e80 /build2
parent1ba934bb973c234b68751ee5866365c14da4e795 (diff)
Move in build system module to separate library
Diffstat (limited to 'build2')
-rw-r--r--build2/b.cxx94
-rw-r--r--build2/bash/rule.cxx2
-rw-r--r--build2/bash/rule.hxx2
-rw-r--r--build2/buildfile9
-rw-r--r--build2/in/init.cxx110
-rw-r--r--build2/in/init.hxx37
-rw-r--r--build2/in/rule.cxx485
-rw-r--r--build2/in/rule.hxx88
-rw-r--r--build2/in/target.cxx62
-rw-r--r--build2/in/target.hxx46
-rw-r--r--build2/version/rule.cxx2
-rw-r--r--build2/version/rule.hxx2
12 files changed, 62 insertions, 877 deletions
diff --git a/build2/b.cxx b/build2/b.cxx
index a76a8e4..907784b 100644
--- a/build2/b.cxx
+++ b/build2/b.cxx
@@ -42,20 +42,18 @@
#include <libbuild2/parser.hxx>
+#include <build2/b-options.hxx>
+
+// Build system modules.
+//
#include <libbuild2/dist/init.hxx>
#include <libbuild2/test/init.hxx>
#include <libbuild2/config/init.hxx>
#include <libbuild2/install/init.hxx>
-#include <build2/b-options.hxx>
-
-using namespace butl;
-using namespace std;
-
+#include <libbuild2/in/init.hxx>
#include <build2/version/init.hxx>
-#include <build2/in/init.hxx>
-
#include <build2/bin/init.hxx>
#include <build2/c/init.hxx>
#include <build2/cc/init.hxx>
@@ -66,6 +64,9 @@ using namespace std;
# include <build2/bash/init.hxx>
#endif
+using namespace butl;
+using namespace std;
+
namespace build2
{
static options ops;
@@ -437,46 +438,51 @@ main (int argc, char* argv[])
using mf = module_functions;
auto& bm (builtin_modules);
- bm["config"] = config::build2_config_load ();
- bm["dist"] = dist::build2_dist_load ();
- bm["test"] = test::build2_test_load ();
- bm["install"] = install::build2_install_load ();
-
- bm["version"] = mf {&version::boot, &version::init};
-
- bm["in.base"] = mf {nullptr, &in::base_init};
- bm["in"] = mf {nullptr, &in::init};
-
- bm["bin.vars"] = mf {nullptr, &bin::vars_init};
- bm["bin.config"] = mf {nullptr, &bin::config_init};
- bm["bin"] = mf {nullptr, &bin::init};
- bm["bin.ar.config"] = mf {nullptr, &bin::ar_config_init};
- bm["bin.ar"] = mf {nullptr, &bin::ar_init};
- bm["bin.ld.config"] = mf {nullptr, &bin::ld_config_init};
- bm["bin.ld"] = mf {nullptr, &bin::ld_init};
- bm["bin.rc.config"] = mf {nullptr, &bin::rc_config_init};
- bm["bin.rc"] = mf {nullptr, &bin::rc_init};
-
- bm["cc.core.vars"] = mf {nullptr, &cc::core_vars_init};
- bm["cc.core.guess"] = mf {nullptr, &cc::core_guess_init};
- bm["cc.core.config"] = mf {nullptr, &cc::core_config_init};
- bm["cc.core"] = mf {nullptr, &cc::core_init};
- bm["cc.config"] = mf {nullptr, &cc::config_init};
- bm["cc"] = mf {nullptr, &cc::init};
-
- bm["c.guess"] = mf {nullptr, &c::guess_init};
- bm["c.config"] = mf {nullptr, &c::config_init};
- bm["c"] = mf {nullptr, &c::init};
-
- bm["cxx.guess"] = mf {nullptr, &cxx::guess_init};
- bm["cxx.config"] = mf {nullptr, &cxx::config_init};
- bm["cxx"] = mf {nullptr, &cxx::init};
+ auto reg = [] (module_load_function* lf)
+ {
+ for (const module_functions* i (lf ()); i->name != nullptr; ++i)
+ builtin_modules[i->name] = *i;
+ };
+
+ reg (&config::build2_config_load);
+ reg (&dist::build2_dist_load);
+ reg (&test::build2_test_load);
+ reg (&install::build2_install_load);
+
+ bm["version"] = mf {"version", &version::boot, &version::init};
+
+ reg (&in::build2_in_load);
+
+ bm["bin.vars"] = mf {"bin.vars", nullptr, &bin::vars_init};
+ bm["bin.config"] = mf {"bin.config", nullptr, &bin::config_init};
+ bm["bin"] = mf {"bin", nullptr, &bin::init};
+ bm["bin.ar.config"] = mf {"bin.ar.config", nullptr, &bin::ar_config_init};
+ bm["bin.ar"] = mf {"bin.ar", nullptr, &bin::ar_init};
+ bm["bin.ld.config"] = mf {"bin.ld.config", nullptr, &bin::ld_config_init};
+ bm["bin.ld"] = mf {"bin.ld", nullptr, &bin::ld_init};
+ bm["bin.rc.config"] = mf {"bin.rc.config", nullptr, &bin::rc_config_init};
+ bm["bin.rc"] = mf {"bin.rc", nullptr, &bin::rc_init};
+
+ bm["cc.core.vars"] = mf {"cc.core.vars", nullptr, &cc::core_vars_init};
+ bm["cc.core.guess"] = mf {"cc.core.guess", nullptr, &cc::core_guess_init};
+ bm["cc.core.config"] = mf {"cc.core.config", nullptr, &cc::core_config_init};
+ bm["cc.core"] = mf {"cc.core", nullptr, &cc::core_init};
+ bm["cc.config"] = mf {"cc.config", nullptr, &cc::config_init};
+ bm["cc"] = mf {"cc", nullptr, &cc::init};
+
+ bm["c.guess"] = mf {"c.guess", nullptr, &c::guess_init};
+ bm["c.config"] = mf {"c.config", nullptr, &c::config_init};
+ bm["c"] = mf {"c", nullptr, &c::init};
+
+ bm["cxx.guess"] = mf {"cxx.guess", nullptr, &cxx::guess_init};
+ bm["cxx.config"] = mf {"cxx.config", nullptr, &cxx::config_init};
+ bm["cxx"] = mf {"cxx", nullptr, &cxx::init};
#ifndef BUILD2_BOOTSTRAP
- bm["cli.config"] = mf {nullptr, &cli::config_init};
- bm["cli"] = mf {nullptr, &cli::init};
+ bm["cli.config"] = mf {"cli.config", nullptr, &cli::config_init};
+ bm["cli"] = mf {"cli", nullptr, &cli::init};
- bm["bash"] = mf {nullptr, &bash::init};
+ bm["bash"] = mf {"bash", nullptr, &bash::init};
#endif
}
diff --git a/build2/bash/rule.cxx b/build2/bash/rule.cxx
index 72e3219..a612d23 100644
--- a/build2/bash/rule.cxx
+++ b/build2/bash/rule.cxx
@@ -11,7 +11,7 @@
#include <libbuild2/algorithm.hxx>
#include <libbuild2/diagnostics.hxx>
-#include <build2/in/target.hxx>
+#include <libbuild2/in/target.hxx>
#include <build2/bash/target.hxx>
#include <build2/bash/utility.hxx>
diff --git a/build2/bash/rule.hxx b/build2/bash/rule.hxx
index a6ec235..c160bb7 100644
--- a/build2/bash/rule.hxx
+++ b/build2/bash/rule.hxx
@@ -10,7 +10,7 @@
#include <libbuild2/install/rule.hxx>
-#include <build2/in/rule.hxx>
+#include <libbuild2/in/rule.hxx>
namespace build2
{
diff --git a/build2/buildfile b/build2/buildfile
index eb22266..a940793 100644
--- a/build2/buildfile
+++ b/build2/buildfile
@@ -6,12 +6,19 @@ import libs = libbutl%lib{butl}
import libs += libpkgconf%lib{pkgconf}
include ../libbuild2/
+libs += ../libbuild2/lib{build2}
+
+for m: in
+{
+ include ../libbuild2/in/
+ libs += ../libbuild2/$m/lib{build2-$m}
+}
./: exe{b}: {hxx ixx txx cxx}{+b} libue{b}
libue{b}: {hxx ixx txx cxx}{** -b -b-options -**.test...} \
{hxx ixx cxx}{b-options} \
- ../libbuild2/lib{build2} $libs
+ $libs
# Unit tests.
#
diff --git a/build2/in/init.cxx b/build2/in/init.cxx
deleted file mode 100644
index f01fe20..0000000
--- a/build2/in/init.cxx
+++ /dev/null
@@ -1,110 +0,0 @@
-// file : build2/in/init.cxx -*- C++ -*-
-// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#include <build2/in/init.hxx>
-
-#include <libbuild2/scope.hxx>
-#include <libbuild2/context.hxx>
-#include <libbuild2/variable.hxx>
-#include <libbuild2/diagnostics.hxx>
-
-#include <build2/in/rule.hxx>
-#include <build2/in/target.hxx>
-
-using namespace std;
-
-namespace build2
-{
- namespace in
- {
- static const rule rule_ ("in", "in");
-
- bool
- base_init (scope& rs,
- scope&,
- const location&,
- unique_ptr<module_base>&,
- bool first,
- bool,
- const variable_map&)
- {
- tracer trace ("in::base_init");
- l5 ([&]{trace << "for " << rs;});
-
- assert (first);
-
- // Enter variables.
- //
- {
- auto& vp (var_pool.rw (rs));
-
- // Alternative variable substitution symbol with '$' being the
- // default.
- //
- vp.insert<string> ("in.symbol");
-
- // Substitution mode. Valid values are 'strict' (default) and 'lax'.
- // In the strict mode every substitution symbol is expected to start a
- // substitution with the double symbol (e.g., $$) serving as an escape
- // sequence.
- //
- // In the lax mode a pair of substitution symbols is only treated as a
- // substitution if what's between them looks like a build2 variable
- // name (i.e., doesn't contain spaces, etc). Everything else,
- // including unterminated substitution symbols, is copied as is. Note
- // also that in this mode the double symbol is not treated as an
- // escape sequence.
- //
- // The lax mode is mostly useful when trying to reuse existing .in
- // files, for example, from autoconf. Note, however, that the lax mode
- // is still stricter than the autoconf's semantics which also leaves
- // unknown substitutions as is.
- //
- vp.insert<string> ("in.substitution");
- }
-
- // Register target types.
- //
- rs.target_types.insert<in> ();
-
- return true;
- }
-
- bool
- init (scope& rs,
- scope& bs,
- const location& loc,
- unique_ptr<module_base>&,
- bool,
- bool,
- const variable_map&)
- {
- tracer trace ("in::init");
- l5 ([&]{trace << "for " << bs;});
-
- // Load in.base.
- //
- if (!cast_false<bool> (rs["in.base.loaded"]))
- load_module (rs, rs, "in.base", loc);
-
- // Register rules.
- //
- {
- auto& r (bs.rules);
-
- // There are rules that are "derived" from this generic in rule in
- // order to provide extended preprocessing functionality (see the
- // version module for an example). To make sure they are tried first
- // we register for path_target, not file, but in rule::match() we only
- // match if the target is a file. A bit of a hack.
- //
- r.insert<path_target> (perform_update_id, "in", rule_);
- r.insert<path_target> (perform_clean_id, "in", rule_);
- r.insert<path_target> (configure_update_id, "in", rule_);
- }
-
- return true;
- }
- }
-}
diff --git a/build2/in/init.hxx b/build2/in/init.hxx
deleted file mode 100644
index 3cf8ebf..0000000
--- a/build2/in/init.hxx
+++ /dev/null
@@ -1,37 +0,0 @@
-// file : build2/in/init.hxx -*- C++ -*-
-// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#ifndef BUILD2_IN_INIT_HXX
-#define BUILD2_IN_INIT_HXX
-
-#include <libbuild2/types.hxx>
-#include <libbuild2/utility.hxx>
-
-#include <libbuild2/module.hxx>
-
-namespace build2
-{
- namespace in
- {
- bool
- base_init (scope&,
- scope&,
- const location&,
- unique_ptr<module_base>&,
- bool,
- bool,
- const variable_map&);
-
- bool
- init (scope&,
- scope&,
- const location&,
- unique_ptr<module_base>&,
- bool,
- bool,
- const variable_map&);
- }
-}
-
-#endif // BUILD2_IN_INIT_HXX
diff --git a/build2/in/rule.cxx b/build2/in/rule.cxx
deleted file mode 100644
index 8a3244d..0000000
--- a/build2/in/rule.cxx
+++ /dev/null
@@ -1,485 +0,0 @@
-// file : build2/in/rule.cxx -*- C++ -*-
-// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#include <build2/in/rule.hxx>
-
-#include <cstdlib> // strtoull()
-
-#include <libbuild2/depdb.hxx>
-#include <libbuild2/scope.hxx>
-#include <libbuild2/target.hxx>
-#include <libbuild2/function.hxx>
-#include <libbuild2/algorithm.hxx>
-#include <libbuild2/filesystem.hxx>
-#include <libbuild2/diagnostics.hxx>
-
-#include <build2/in/target.hxx>
-
-using namespace std;
-using namespace butl;
-
-namespace build2
-{
- namespace in
- {
- bool rule::
- match (action a, target& xt, const string&) const
- {
- tracer trace ("in::rule::match");
-
- if (!xt.is_a<file> ()) // See module init() for details.
- return false;
-
- file& t (static_cast<file&> (xt));
-
- bool fi (false); // Found in.
- for (prerequisite_member p: group_prerequisite_members (a, t))
- {
- if (include (a, t, p) != include_type::normal) // Excluded/ad hoc.
- continue;
-
- fi = fi || p.is_a<in> ();
- }
-
- // Note that while normally we print these at verbosity level 4, this
- // one gets quite noisy since we try this rule for any file target.
- //
- if (!fi)
- l5 ([&]{trace << "no in file prerequisite for target " << t;});
-
- return fi;
- }
-
- recipe rule::
- apply (action a, target& xt) const
- {
- file& t (static_cast<file&> (xt));
-
- // Derive the file name.
- //
- t.derive_path ();
-
- // Inject dependency on the output directory.
- //
- inject_fsdir (a, t);
-
- // Match prerequisite members.
- //
- match_prerequisite_members (a,
- t,
- [this] (action a,
- const target& t,
- const prerequisite_member& p,
- include_type i)
- {
- return search (a, t, p, i);
- });
-
- 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_depdb; // Standard clean.
- default: return noop_recipe; // Configure update.
- }
- }
-
- target_state rule::
- perform_update (action a, const target& xt) const
- {
- tracer trace ("in::rule::perform_update");
-
- const file& t (xt.as<const file&> ());
- const path& tp (t.path ());
-
- // Substitution symbol.
- //
- char sym (symbol_);
- if (const string* s = cast_null<string> (t["in.symbol"]))
- {
- if (s->size () == 1)
- sym = s->front ();
- else
- fail << "invalid substitution symbol '" << *s << "'";
- }
-
- // Substitution mode.
- //
- bool strict (strict_);
- if (const string* s = cast_null<string> (t["in.substitution"]))
- {
- if (*s == "lax")
- strict = false;
- else if (*s != "strict")
- fail << "invalid substitution mode '" << *s << "'";
- }
-
- // Determine if anything needs to be updated.
- //
- timestamp mt (t.load_mtime ());
- auto pr (execute_prerequisites<in> (a, t, mt));
-
- bool update (!pr.first);
- target_state ts (update ? target_state::changed : *pr.first);
-
- const in& i (pr.second);
- const path& ip (i.path ());
-
- // We use depdb to track changes to the .in file name, symbol/mode, and
- // variable values that have been substituted.
- //
- depdb dd (tp + ".d");
-
- // First should come the rule name/version.
- //
- if (dd.expect (rule_id_ + " 1") != nullptr)
- l4 ([&]{trace << "rule mismatch forcing update of " << t;});
-
- // Then the substitution symbol.
- //
- if (dd.expect (string (1, sym)) != nullptr)
- l4 ([&]{trace << "substitution symbol mismatch forcing update of"
- << t;});
-
- // Then the substitution mode.
- //
- if (dd.expect (strict ? "strict" : "lax") != nullptr)
- l4 ([&]{trace << "substitution mode mismatch forcing update of"
- << t;});
-
- // Then the .in file.
- //
- if (dd.expect (i.path ()) != nullptr)
- l4 ([&]{trace << "in file mismatch forcing update of " << t;});
-
- // Update if any mismatch or depdb is newer that the output.
- //
- if (dd.writing () || dd.mtime > mt)
- update = true;
-
- // Substituted variable values.
- //
- // The plan is to save each substituted variable name and the hash of
- // its value one entry per line. Plus the line location of its expansion
- // for diagnostics.
- //
- // If update is true (i.e., the .in file has changes), then we simply
- // overwrite the whole list.
- //
- // If update is false, then we need to read each name/hash, query and
- // hash its current value, and compare. If hashes differ, then we need
- // to start overwriting from this variable (the prefix of variables
- // couldn't have changed since the .in file hasn't changed).
- //
- // Note that if the .in file substitutes the same variable multiple
- // times, then we will end up with multiple entries for such a variable.
- // For now we assume this is ok since this is probably not very common
- // and it makes the overall logic simpler.
- //
- // Note also that because updating the depdb essentially requires
- // performing the substitutions, this rule ignored the dry-run mode.
- //
- size_t dd_skip (0); // Number of "good" variable lines.
-
- if (update)
- {
- // If we are still reading, mark the next line for overwriting.
- //
- if (dd.reading ())
- {
- dd.read (); // Read the first variable line, if any.
- dd.write (); // Mark it for overwriting.
- }
- }
- else
- {
- while (dd.more ())
- {
- if (string* s = dd.read ())
- {
- // The line format is:
- //
- // <ln> <name> <hash>
- //
- // Note that <name> can contain spaces (see the constraint check
- // expressions in the version module).
- //
- char* e (nullptr);
- uint64_t ln (strtoull (s->c_str (), &e, 10));
-
- size_t p1 (*e == ' ' ? e - s->c_str () : string::npos);
- size_t p2 (s->rfind (' '));
-
- if (p1 != string::npos && p2 != string::npos && p2 - p1 > 1)
- {
- string n (*s, p1 + 1, p2 - p1 - 1);
-
- // Note that we have to call substitute(), not lookup() since it
- // can be overriden with custom substitution semantics.
- //
- optional<string> v (
- substitute (location (&ip, ln), a, t, n, strict));
-
- assert (v); // Rule semantics change without version increment?
-
- if (s->compare (p2 + 1,
- string::npos,
- sha256 (*v).string ()) == 0)
- {
- dd_skip++;
- continue;
- }
- else
- l4 ([&]{trace << n << " variable value mismatch forcing "
- << "update of " << t;});
- // Fall through.
- }
-
- dd.write (); // Mark this line for overwriting.
-
- // Fall through.
- }
-
- break;
- }
- }
-
- if (dd.writing ()) // Recheck.
- update = true;
-
- // If nothing changed, then we are done.
- //
- if (!update)
- {
- dd.close ();
- return ts;
- }
-
- if (verb >= 2)
- text << program_ << ' ' << ip << " >" << tp;
- else if (verb)
- text << program_ << ' ' << ip;
-
- // Read and process the file, one line at a time, while updating depdb.
- //
- const char* what;
- const path* whom;
- try
- {
- what = "open"; whom = &ip;
- ifdstream ifs (ip, fdopen_mode::in, ifdstream::badbit);
-
- // See fdopen() for details (umask, etc).
- //
- permissions prm (permissions::ru | permissions::wu |
- permissions::rg | permissions::wg |
- permissions::ro | permissions::wo);
-
- if (t.is_a<exe> ())
- prm |= permissions::xu | permissions::xg | permissions::xo;
-
- // Remove the existing file to make sure permissions take effect. If
- // this fails then presumable writing to it will fail as well and we
- // will complain there.
- //
- try_rmfile (tp, true /* ignore_error */);
-
- what = "open"; whom = &tp;
- ofdstream ofs (fdopen (tp,
- fdopen_mode::out | fdopen_mode::create,
- prm));
- auto_rmfile arm (tp);
-
- string s; // Reuse the buffer.
- for (size_t ln (1);; ++ln)
- {
- what = "read"; whom = &ip;
- if (!getline (ifs, s))
- break; // Could not read anything, not even newline.
-
- // Not tracking column for now (see also depdb above).
- //
- const location l (&ip, ln);
-
- // Scan the line looking for substiutions in the $<name>$ form. In
- // the strict mode treat $$ as an escape sequence.
- //
- for (size_t b (0), n, d; b != (n = s.size ()); b += d)
- {
- d = 1;
-
- if (s[b] != sym)
- continue;
-
- // Note that in the lax mode these should still be substitutions:
- //
- // @project@@
- // @@project@
-
- // Find the other end.
- //
- size_t e (b + 1);
- for (; e != (n = s.size ()); ++e)
- {
- if (s[e] == sym)
- {
- if (strict && e + 1 != n && s[e + 1] == sym) // Escape.
- s.erase (e, 1); // Keep one, erase the other.
- else
- break;
- }
- }
-
- if (e == n)
- {
- if (strict)
- fail (l) << "unterminated '" << sym << "'" << endf;
-
- break;
- }
-
- if (e - b == 1) // Escape (or just double symbol in the lax mode).
- {
- if (strict)
- s.erase (b, 1); // Keep one, erase the other.
-
- continue;
- }
-
- // We have a (potential, in the lax mode) substition with b
- // pointing to the opening symbol and e -- to the closing.
- //
- string name (s, b + 1, e - b -1);
- if (optional<string> val = substitute (l, a, t, name, strict))
- {
- // Save in depdb.
- //
- if (dd_skip == 0)
- {
- // The line format is:
- //
- // <ln> <name> <hash>
- //
- string s (to_string (ln));
- s += ' ';
- s += name;
- s += ' ';
- s += sha256 (*val).string ();
- dd.write (s);
- }
- else
- --dd_skip;
-
- // Patch the result in and adjust the delta.
- //
- s.replace (b, e - b + 1, *val);
- d = val->size ();
- }
- else
- d = e - b + 1; // Ignore this substitution.
- }
-
- what = "write"; whom = &tp;
- if (ln != 1)
- ofs << '\n'; // See below.
- ofs << s;
- }
-
- // Close depdb before closing the output file so its mtime is not
- // newer than of the output.
- //
- dd.close ();
-
- what = "close"; whom = &tp;
- ofs << '\n'; // Last write to make sure our mtime is older than dd.
- ofs.close ();
- arm.cancel ();
-
- what = "close"; whom = &ip;
- ifs.close ();
- }
- catch (const io_error& e)
- {
- fail << "unable to " << what << ' ' << *whom << ": " << e;
- }
-
- dd.check_mtime (tp);
-
- t.mtime (system_clock::now ());
- return target_state::changed;
- }
-
- prerequisite_target rule::
- search (action,
- const target& t,
- const prerequisite_member& p,
- include_type i) const
- {
- return prerequisite_target (&build2::search (t, p), i);
- }
-
- string rule::
- lookup (const location& l, action, const target& t, const string& n) const
- {
- if (auto x = t[n])
- {
- value v (*x);
-
- // For typed values call string() for conversion.
- //
- try
- {
- return convert<string> (
- v.type == nullptr
- ? move (v)
- : functions.call (&t.base_scope (),
- "string",
- vector_view<value> (&v, 1),
- l));
- }
- catch (const invalid_argument& e)
- {
- fail (l) << e <<
- info << "while substituting '" << n << "'" << endf;
- }
- }
- else
- fail (l) << "undefined variable '" << n << "'" << endf;
- }
-
- optional<string> rule::
- substitute (const location& l,
- action a,
- const target& t,
- const string& n,
- bool strict) const
- {
- // In the lax mode scan the fragment to make sure it is a variable name
- // (that is, it can be expanded in a buildfile as just $<name>; see
- // lexer's variable mode for details).
- //
- if (!strict)
- {
- for (size_t i (0), e (n.size ()); i != e; )
- {
- bool f (i == 0); // First.
- char c (n[i++]);
- bool l (i == e); // Last.
-
- if (c == '_' || (f ? alpha (c) : alnum (c)))
- continue;
-
- if (c == '.' && !l)
- continue;
-
- return nullopt; // Ignore this substitution.
- }
- }
-
- return lookup (l, a, t, n);
- }
- }
-}
diff --git a/build2/in/rule.hxx b/build2/in/rule.hxx
deleted file mode 100644
index 71dc032..0000000
--- a/build2/in/rule.hxx
+++ /dev/null
@@ -1,88 +0,0 @@
-// file : build2/in/rule.hxx -*- C++ -*-
-// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#ifndef BUILD2_IN_RULE_HXX
-#define BUILD2_IN_RULE_HXX
-
-#include <libbuild2/types.hxx>
-#include <libbuild2/utility.hxx>
-
-#include <libbuild2/rule.hxx>
-
-namespace build2
-{
- namespace in
- {
- // Preprocess an .in file.
- //
- // Note that a derived rule can use the target data pad to cache data
- // (e.g., in match()) to be used in substitute/lookup() calls.
- //
- // Note also that currently this rule ignores the dry-run mode (see
- // perform_update() for the rationale).
- //
- class rule: public build2::rule
- {
- public:
- // The rule id is used to form the rule name/version entry in depdb. The
- // program argument is the pseudo-program name to use in the command
- // line diagnostics.
- //
- rule (string rule_id,
- string program,
- char symbol = '$',
- bool strict = true)
- : rule_id_ (move (rule_id)),
- program_ (move (program)),
- symbol_ (symbol),
- strict_ (strict) {}
-
- virtual bool
- match (action, target&, const string&) const override;
-
- virtual recipe
- apply (action, target&) const override;
-
- virtual target_state
- perform_update (action, const target&) const;
-
- // Customization hooks.
- //
-
- // Perform prerequisite search.
- //
- virtual prerequisite_target
- search (action,
- const target&,
- const prerequisite_member&,
- include_type) const;
-
- // Perform variable lookup.
- //
- virtual string
- lookup (const location&,
- action,
- const target&,
- const string& name) const;
-
- // Perform variable substitution. Return nullopt if it should be
- // ignored.
- //
- virtual optional<string>
- substitute (const location&,
- action,
- const target&,
- const string& name,
- bool strict) const;
-
- protected:
- const string rule_id_;
- const string program_;
- char symbol_;
- bool strict_;
- };
- }
-}
-
-#endif // BUILD2_IN_RULE_HXX
diff --git a/build2/in/target.cxx b/build2/in/target.cxx
deleted file mode 100644
index 8dc520b..0000000
--- a/build2/in/target.cxx
+++ /dev/null
@@ -1,62 +0,0 @@
-// file : build2/in/target.cxx -*- C++ -*-
-// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#include <build2/in/target.hxx>
-
-using namespace std;
-
-namespace build2
-{
- namespace in
- {
- static const target*
- in_search (const target& xt, const prerequisite_key& cpk)
- {
- // If we have no extension then derive it from our target. Then delegate
- // to file_search().
- //
- prerequisite_key pk (cpk);
- optional<string>& e (pk.tk.ext);
-
- if (!e)
- {
- if (const file* t = xt.is_a<file> ())
- {
- const string& te (t->derive_extension ());
- e = te + (te.empty () ? "" : ".") + "in";
- }
- else
- fail << "prerequisite " << pk << " for a non-file target " << xt;
- }
-
- return file_search (xt, pk);
- }
-
- static bool
- in_pattern (const target_type&,
- const scope&,
- string&,
- optional<string>&,
- const location& l,
- bool)
- {
- fail (l) << "pattern in in{} prerequisite" << endf;
- }
-
- extern const char in_ext_def[] = ""; // No extension by default.
-
- const target_type in::static_type
- {
- "in",
- &file::static_type,
- &target_factory<in>,
- &target_extension_fix<in_ext_def>,
- nullptr, /* default_extension */ // Taken care of by search.
- &in_pattern,
- &target_print_1_ext_verb, // Same as file.
- &in_search,
- false
- };
- }
-}
diff --git a/build2/in/target.hxx b/build2/in/target.hxx
deleted file mode 100644
index 47b0eed..0000000
--- a/build2/in/target.hxx
+++ /dev/null
@@ -1,46 +0,0 @@
-// file : build2/in/target.hxx -*- C++ -*-
-// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#ifndef BUILD2_IN_TARGET_HXX
-#define BUILD2_IN_TARGET_HXX
-
-#include <libbuild2/types.hxx>
-#include <libbuild2/utility.hxx>
-
-#include <libbuild2/target.hxx>
-
-namespace build2
-{
- namespace in
- {
- // This is the venerable .in ("input") file that needs some kind of
- // preprocessing.
- //
- // One interesting aspect of this target type is that the prerequisite
- // search is target-dependent. Consider:
- //
- // hxx{version}: in{version.hxx} // version.hxx.in -> version.hxx
- //
- // Having to specify the header extension explicitly is inelegant. Instead
- // what we really want to write is this:
- //
- // hxx{version}: in{version}
- //
- // But how do we know that in{version} means version.hxx.in? That's where
- // the target-dependent search comes in: we take into account the target
- // we are a prerequisite of.
- //
- class in: public file
- {
- public:
- using file::file;
-
- public:
- static const target_type static_type;
- virtual const target_type& dynamic_type () const {return static_type;}
- };
- }
-}
-
-#endif // BUILD2_IN_TARGET_HXX
diff --git a/build2/version/rule.cxx b/build2/version/rule.cxx
index 912efe3..f110e3e 100644
--- a/build2/version/rule.cxx
+++ b/build2/version/rule.cxx
@@ -8,7 +8,7 @@
#include <libbuild2/target.hxx>
#include <libbuild2/diagnostics.hxx>
-#include <build2/in/target.hxx>
+#include <libbuild2/in/target.hxx>
#include <build2/version/module.hxx>
#include <build2/version/utility.hxx>
diff --git a/build2/version/rule.hxx b/build2/version/rule.hxx
index 6d841df..7bfb783 100644
--- a/build2/version/rule.hxx
+++ b/build2/version/rule.hxx
@@ -10,7 +10,7 @@
#include <libbuild2/install/rule.hxx>
-#include <build2/in/rule.hxx>
+#include <libbuild2/in/rule.hxx>
namespace build2
{