aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-03-09 09:45:25 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-03-09 09:45:25 +0200
commitfa6f9986dd73627643469c238b32dd92607f5214 (patch)
treede7ee1f4253ab815767b45c9ec0b03d802d01704
parent2e98d3ec3aa57c7b1776d3bf5e7e219a9a3cb3af (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.
-rw-r--r--build/b.cxx14
-rw-r--r--build/lexer4
-rw-r--r--build/parser8
-rw-r--r--build/parser.cxx13
-rw-r--r--build/scope8
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_;