diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-03-09 09:45:25 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-03-09 09:45:25 +0200 |
commit | fa6f9986dd73627643469c238b32dd92607f5214 (patch) | |
tree | de7ee1f4253ab815767b45c9ec0b03d802d01704 /build | |
parent | 2e98d3ec3aa57c7b1776d3bf5e7e219a9a3cb3af (diff) |
Add support for skipping already loaded/included buildfiles at top level
The idea is that a buildfile shall be included/loaded only once for any
given out_root.
Diffstat (limited to 'build')
-rw-r--r-- | build/b.cxx | 14 | ||||
-rw-r--r-- | build/lexer | 4 | ||||
-rw-r--r-- | build/parser | 8 | ||||
-rw-r--r-- | build/parser.cxx | 13 | ||||
-rw-r--r-- | build/scope | 8 |
5 files changed, 32 insertions, 15 deletions
diff --git a/build/b.cxx b/build/b.cxx index 0a1d8d2..ce10b22 100644 --- a/build/b.cxx +++ b/build/b.cxx @@ -269,7 +269,7 @@ main (int argc, char* argv[]) if (verb >= 4) { - trace << tn; + trace << tn << ':'; trace << " out_base: " << out_base.string (); trace << " src_base: " << src_base.string (); trace << " out_root: " << out_root.string (); @@ -293,6 +293,16 @@ main (int argc, char* argv[]) // path bf (src_base / path ("buildfile")); + // Check if this buildfile has already been loaded. + // + if (!proot_scope.buildfiles.insert (bf).second) + { + level4 ([&]{trace << "skipping already loaded " << bf;}); + continue; + } + + level4 ([&]{trace << "loading " << bf;}); + ifstream ifs (bf.string ()); if (!ifs.is_open ()) fail << "unable to open " << bf; @@ -302,7 +312,7 @@ main (int argc, char* argv[]) try { - p.parse_buildfile (ifs, bf, pbase_scope); + p.parse_buildfile (ifs, bf, pbase_scope, proot_scope); } catch (const std::ios_base::failure&) { diff --git a/build/lexer b/build/lexer index 787ba72..98a1390 100644 --- a/build/lexer +++ b/build/lexer @@ -127,8 +127,8 @@ namespace build bool eos_ {false}; lexer_mode mode_ {lexer_mode::normal}; - lexer_mode next_mode_; // Mode to switch to for the next token. - lexer_mode prev_mode_; // Mode to return to after this mode expires. + lexer_mode next_mode_ {lexer_mode::normal}; // Switch to for next token. + lexer_mode prev_mode_; // Return to after current mode expires. }; } diff --git a/build/parser b/build/parser index 25866bc..50e306d 100644 --- a/build/parser +++ b/build/parser @@ -7,7 +7,6 @@ #include <string> #include <iosfwd> -#include <unordered_set> #include <build/path> #include <build/token> @@ -29,7 +28,7 @@ namespace build // Issue diagnostics and throw failed in case of an error. // void - parse_buildfile (std::istream&, const path&, scope&); + parse_buildfile (std::istream&, const path&, scope& base, scope& root); buildspec parse_buildspec (std::istream&, const std::string& name); @@ -99,7 +98,8 @@ namespace build private: const std::string* path_; // Path processed by diagnostic_string(). lexer* lexer_; - scope* scope_; + scope* scope_; // Current base scope (out_base). + scope* root_; // Current root scope (out_root). target* default_target_; const path* out_root_; @@ -107,8 +107,6 @@ namespace build token peek_ {token_type::eos, false, 0, 0}; bool peeked_ {false}; - - std::unordered_set<path> include_; }; } diff --git a/build/parser.cxx b/build/parser.cxx index 2c629d6..343f5e1 100644 --- a/build/parser.cxx +++ b/build/parser.cxx @@ -37,18 +37,19 @@ namespace build typedef token_type type; void parser:: - parse_buildfile (istream& is, const path& p, scope& s) + parse_buildfile (istream& is, const path& p, scope& base, scope& root) { string rw (diag_relative_work (p)); path_ = &rw; lexer l (is, rw); lexer_ = &l; - scope_ = &s; + scope_ = &base; + root_ = &root; default_target_ = nullptr; - out_root_ = &s["out_root"].as<const path&> (); - src_root_ = &s["src_root"].as<const path&> (); + out_root_ = &root["out_root"].as<const path&> (); + src_root_ = &root["src_root"].as<const path&> (); token t (type::eos, false, 0, 0); type tt; @@ -477,7 +478,7 @@ namespace build p.normalize (); } - if (!include_.insert (p).second) + if (!root_->buildfiles.insert (p).second) { level4 ([&]{trace (l) << "skipping already included " << p;}); continue; @@ -955,7 +956,7 @@ namespace build lexer l (is, name); lexer_ = &l; - scope_ = root_scope; + scope_ = root_ = root_scope; // Turn on pairs recognition (e.g., src_root/=out_root/exe{foo bar}). // diff --git a/build/scope b/build/scope index b4f492d..e5c5fec 100644 --- a/build/scope +++ b/build/scope @@ -5,6 +5,8 @@ #ifndef BUILD_SCOPE #define BUILD_SCOPE +#include <unordered_set> + #include <build/path> #include <build/path-map> #include <build/variable> @@ -49,6 +51,12 @@ namespace build variable_map variables; prerequisite_set prerequisites; + // Set of buildfiles already loaded for this scope. The included + // buildfiles are checked against project root scope while + // imported -- against the overall root scope (root_scope). + // + std::unordered_set<path_type> buildfiles; + private: iterator i_; scope* parent_; |