From c699c956d75dfaaded5bb24c5ea16edc73588649 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 27 Mar 2015 16:14:10 +0200 Subject: Rework dependency state dump support We now have a combined (scopes, variables, and targets) dump. --- build/b.cxx | 2 +- build/context | 12 ++++- build/context.cxx | 19 +++++--- build/cxx/rule.cxx | 8 ++-- build/diagnostics | 10 ++--- build/diagnostics.cxx | 20 +++++---- build/dump | 3 -- build/dump.cxx | 116 ++++++++++++++++++++++++++++++++++++++----------- build/name.cxx | 2 +- build/parser.cxx | 6 +-- build/prerequisite.cxx | 4 +- build/spec.cxx | 2 +- build/target.cxx | 2 +- 13 files changed, 142 insertions(+), 64 deletions(-) diff --git a/build/b.cxx b/build/b.cxx index 0443b4b..c676f8a 100644 --- a/build/b.cxx +++ b/build/b.cxx @@ -144,7 +144,7 @@ main (int argc, char* argv[]) // Trace verbosity. // - verb = 4; + verb = 5; // Register modules. // diff --git a/build/context b/build/context index ac6e29c..723f9f9 100644 --- a/build/context +++ b/build/context @@ -77,10 +77,18 @@ namespace build out_src (const path& src, const path& out_root, const path& src_root); // If possible and beneficial, translate an absolute, normalized path - // into relative to the work directory. + // into relative to the relative_base directory, which is normally + // work. // path - relative_work (const path&); + relative (const path&); + + // By default this points to work. Setting this to something else + // should only be done in tightly controlled, non-parallel + // situations (see dump). If base is empty, then relative() + // returns the original path. + // + extern const path* relative_base; } #include diff --git a/build/context.cxx b/build/context.cxx index 92f3db9..872a428 100644 --- a/build/context.cxx +++ b/build/context.cxx @@ -106,13 +106,20 @@ namespace build return out_root / s.leaf (src_root); } + const path* relative_base = &work; + path - relative_work (const path& p) + relative (const path& p) { - if (p.sub (work)) - return p.leaf (work); + const path& b (*relative_base); + + if (b.empty ()) + return p; + + if (p.sub (b)) + return p.leaf (b); - // If work is a sub-path of {src,out}_root and this path is also a + // If base is a sub-path of {src,out}_root and this path is also a // sub-path of it, then use '..' to form a relative path. // // Don't think this is a good heuristic. For example, why shouldn't @@ -125,9 +132,9 @@ namespace build return p.relative (work); */ - if (p.root_directory () == work.root_directory ()) + if (p.root_directory () == b.root_directory ()) { - path r (p.relative (work)); + path r (p.relative (b)); if (r.string ().size () < p.string ().size ()) return r; diff --git a/build/cxx/rule.cxx b/build/cxx/rule.cxx index f53dd3b..549d987 100644 --- a/build/cxx/rule.cxx +++ b/build/cxx/rule.cxx @@ -282,8 +282,8 @@ namespace build // Translate paths to relative (to working directory) ones. This // results in easier to read diagnostics. // - path ro (relative_work (o.path ())); - path rs (relative_work (s->path ())); + path ro (relative (o.path ())); + path rs (relative (s->path ())); const char* args[] = { "g++-4.9", @@ -580,7 +580,7 @@ namespace build // Translate paths to relative (to working directory) ones. This // results in easier to read diagnostics. // - path re (relative_work (e.path ())); + path re (relative (e.path ())); vector ro; vector args {"g++-4.9", "-std=c++14", "-g", "-o"}; @@ -591,7 +591,7 @@ namespace build { if (const obj* o = dynamic_cast (p.target)) { - ro.push_back (relative_work (o->path ())); + ro.push_back (relative (o->path ())); args.push_back (ro.back ().string ().c_str ()); } } diff --git a/build/diagnostics b/build/diagnostics index 270fa7a..68f449b 100644 --- a/build/diagnostics +++ b/build/diagnostics @@ -23,17 +23,17 @@ namespace build // class failed: public std::exception {}; - // In addition to calling relative_work(), this function also uses - // shorter notations such as '~/'. If the path is the same as work, - // it returns '.'. + // In addition to calling relative(), this function also uses shorter + // notations such as '~/'. If the path is the same as base, it returns + // '.'. // std::string - diag_relative_work (const path&); + diag_relative (const path&); inline std::ostream& operator<< (std::ostream& os, const path& p) { - return os << diag_relative_work (p); + return os << diag_relative (p); } // Print process commmand line. diff --git a/build/diagnostics.cxx b/build/diagnostics.cxx index f5802de..53d1a09 100644 --- a/build/diagnostics.cxx +++ b/build/diagnostics.cxx @@ -14,11 +14,13 @@ using namespace std; namespace build { string - diag_relative_work (const path& p) + diag_relative (const path& p) { + const path& b (*relative_base); + if (p.absolute ()) { - if (p == work) + if (p == b) return "."; #ifndef _WIN32 @@ -26,26 +28,26 @@ namespace build return "~"; #endif - path rw (relative_work (p)); + path rb (relative (p)); #ifndef _WIN32 - if (rw.relative ()) + if (rb.relative ()) { // See if the original path with the ~/ shortcut is better - // that the relative to work. + // that the relative to base. // if (p.sub (home)) { path rh (p.leaf (home)); - if (rw.string ().size () > rh.string ().size () + 2) // 2 for '~/' + if (rb.string ().size () > rh.string ().size () + 2) // 2 for '~/' return "~/" + rh.string (); } } - else if (rw.sub (home)) - return "~/" + rw.leaf (home).string (); + else if (rb.sub (home)) + return "~/" + rb.leaf (home).string (); #endif - return rw.string (); + return rb.string (); } return p.string (); diff --git a/build/dump b/build/dump index e3cc5d2..48da079 100644 --- a/build/dump +++ b/build/dump @@ -9,9 +9,6 @@ namespace build { void dump (); - - void - dump_scopes (); } #endif // BUILD_DUMP diff --git a/build/dump.cxx b/build/dump.cxx index 98b0ff2..45ec584 100644 --- a/build/dump.cxx +++ b/build/dump.cxx @@ -4,6 +4,7 @@ #include +#include #include #include #include @@ -11,53 +12,54 @@ #include #include #include +#include #include using namespace std; namespace build { - void - dump () + static void + dump_target (const target& t) { - cout << endl; + cerr << t << ':'; - for (const auto& pt: targets) + for (const prerequisite& p: t.prerequisites) { - target& t (*pt); - - cout << t << ':'; - - for (const auto& p: t.prerequisites) - { - cout << ' ' << p; - } - - cout << endl; + cerr << ' ' << p; } - - cout << endl; } static void - dump_scope (scope& p, scope_map::iterator& i, string& ind) + dump_scope (scope& p, + scope_map::iterator& i, + string& ind, + set& rts) { - string d (diag_relative_work (p.path ())); + string d (diag_relative (p.path ())); if (d.back () != path::traits::directory_separator) d += '/'; cerr << ind << d << ":" << endl - << ind << '{' << endl; + << ind << '{'; + + const path* orb (relative_base); + relative_base = &p.path (); ind += " "; + bool vb (false), sb (false); // Variable/scope block. + + // Variables. + // for (const auto& e: p.variables) { const variable& var (e.first); const value_ptr& val (e.second); - cerr << ind << var.name << " = "; + cerr << endl + << ind << var.name << " = "; if (val == nullptr) cerr << "[undefined]"; @@ -68,28 +70,90 @@ namespace build cerr << dynamic_cast (*val).data; } - cerr << endl; + vb = true; } - // Print nested scopes of which we are a parent. + // Nested scopes of which we are a parent. // for (auto e (scopes.end ()); i != e && i->second.parent () == &p; ) { + if (vb) + { + cerr << endl; + vb = false; + } + + if (sb) + cerr << endl; // Extra newline between scope blocks. + + cerr << endl; scope& s (i->second); - dump_scope (s, ++i, ind); + dump_scope (s, ++i, ind, rts); + + sb = true; + } + + // Targets. + // + for (const auto& pt: targets) + { + const target& t (*pt); + const scope* ts (&scopes.find (t.dir)); + + bool f (false); + + if (ts == &p) + { + // If this is the ultimate root scope, check that this target + // hasn't been handled by the src logic below. + // + f = (ts != root_scope || rts.find (&t) == rts.end ()); + } + // If this target is in the ultimate root scope and we have a + // corresponding src directory (i.e., we are a scope inside a + // project), check whether this target is in our src. + // + else if (ts == root_scope && p.src_path_ != nullptr) + { + if (t.dir.sub (p.src_path ())) + { + // Check that it hasn't already been handled by a more qualified + // scope. + // + f = rts.insert (&t).second; + } + } + + if (!f) + continue; + + if (vb || sb) + { + cerr << endl; + vb = sb = false; + } + + cerr << endl + << ind; + dump_target (t); } ind.resize (ind.size () - 2); - cerr << ind << '}' << endl; + relative_base = orb; + + cerr << endl + << ind << '}'; } void - dump_scopes () + dump () { string ind; + set rts; auto i (scopes.begin ()); scope& r (i->second); // Root scope. assert (&r == root_scope); - dump_scope (r, ++i, ind); + dump_scope (r, ++i, ind, rts); + cerr << endl; } } diff --git a/build/name.cxx b/build/name.cxx index 46e2440..ebc7372 100644 --- a/build/name.cxx +++ b/build/name.cxx @@ -24,7 +24,7 @@ namespace build if (!n.dir.empty ()) { - string s (diag_relative_work (n.dir)); + string s (diag_relative (n.dir)); // If both type and value are empty, there will be nothing printed. // diff --git a/build/parser.cxx b/build/parser.cxx index 809841f..b21dd6f 100644 --- a/build/parser.cxx +++ b/build/parser.cxx @@ -40,7 +40,7 @@ namespace build void parser:: parse_buildfile (istream& is, const path& p, scope& root, scope& base) { - string rw (diag_relative_work (p)); + string rw (diag_relative (p)); // Relative to work. path_ = &rw; lexer l (is, rw); @@ -431,7 +431,7 @@ namespace build level4 ([&]{trace (t) << "entering " << p;}); - string rw (diag_relative_work (p)); + string rw (diag_relative (p)); // Relative to work. const string* op (path_); path_ = &rw; @@ -558,7 +558,7 @@ namespace build level4 ([&]{trace (t) << "entering " << p;}); - string rw (diag_relative_work (p)); + string rw (diag_relative (p)); // Relative to work. const string* op (path_); path_ = &rw; diff --git a/build/prerequisite.cxx b/build/prerequisite.cxx index feb6381..aa6c53c 100644 --- a/build/prerequisite.cxx +++ b/build/prerequisite.cxx @@ -28,7 +28,7 @@ namespace build // if (!p.dir.absolute ()) { - string s (diag_relative_work (p.scope.path ())); + string s (diag_relative (p.scope.path ())); if (s != ".") { @@ -45,7 +45,7 @@ namespace build // if (!p.dir.empty ()) { - string s (diag_relative_work (p.dir)); + string s (diag_relative (p.dir)); if (s != ".") { diff --git a/build/spec.cxx b/build/spec.cxx index d68154f..a1f6283 100644 --- a/build/spec.cxx +++ b/build/spec.cxx @@ -17,7 +17,7 @@ namespace build { if (!s.src_base.empty ()) { - string d (diag_relative_work (s.src_base)); + string d (diag_relative (s.src_base)); if (d != ".") { diff --git a/build/target.cxx b/build/target.cxx index 1a8fbf7..dc85402 100644 --- a/build/target.cxx +++ b/build/target.cxx @@ -116,7 +116,7 @@ namespace build if (!k.dir->empty ()) { - string s (diag_relative_work (*k.dir)); + string s (diag_relative (*k.dir)); if (s != ".") { -- cgit v1.1