From f56b5a42b9aaaeb0c4e7dee894dea9686599b88c Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 24 Jun 2015 17:26:17 +0200 Subject: Implement proper target type detection in dependency injection --- build/cxx/rule.cxx | 67 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 60 insertions(+), 7 deletions(-) (limited to 'build/cxx') diff --git a/build/cxx/rule.cxx b/build/cxx/rule.cxx index cba1a1b..79b6072 100644 --- a/build/cxx/rule.cxx +++ b/build/cxx/rule.cxx @@ -4,6 +4,7 @@ #include +#include #include #include #include // size_t @@ -211,6 +212,37 @@ namespace build return r; } + // The strings used as the map key should be from the extension_pool. + // This way we can just compare pointers. + // + using ext_map = map; + + static ext_map + build_ext_map (scope& r) + { + ext_map m; + + if (auto val = r["h.ext"]) + m[&extension_pool.find (val.as ())] = &h::static_type; + + if (auto val = r["c.ext"]) + m[&extension_pool.find (val.as ())] = &c::static_type; + + if (auto val = r["hxx.ext"]) + m[&extension_pool.find (val.as ())] = &hxx::static_type; + + if (auto val = r["ixx.ext"]) + m[&extension_pool.find (val.as ())] = &ixx::static_type; + + if (auto val = r["txx.ext"]) + m[&extension_pool.find (val.as ())] = &txx::static_type; + + if (auto val = r["cxx.ext"]) + m[&extension_pool.find (val.as ())] = &cxx::static_type; + + return m; + } + void compile:: inject_prerequisites (action a, target& t, const cxx& s, scope& ds) const { @@ -326,18 +358,39 @@ namespace build // then assume it is a header. Otherwise, let the standard // mechanism derive the type from the extension. @@ TODO. // - const target_type* tt (&hxx::static_type); - //@@ TMP + // Determine the target type. // - if (e != nullptr) + const target_type* tt (nullptr); + + // See if this directory is part of any project out_root + // hierarchy. Note that this will miss all the headers + // that come from src_root (so they will be treated as + // generic C headers below). Generally, we don't have + // the ability to determine that some file belongs to + // src_root of some project. But that's not a problem + // for our purposes: it is only important for us to + // accurately determine target types for headers that + // could be auto-generated. + // + if (scope* r = scopes.find (d).root_scope ()) { - if (*e == "ixx") - tt = &ixx::static_type; - else if (*e == "txx") - tt = &txx::static_type; + // Get cahed (or build) a map of the extensions for the + // C/C++ files this project is using. + // + const ext_map& m (build_ext_map (*r)); + + auto i (m.find (e)); + if (i != m.end ()) + tt = i->second; } + // If it is outside any project, or the project doesn't have + // such an extension, assume it is a plain old C header. + // + if (tt == nullptr) + tt = &h::static_type; + path_target& pt ( static_cast (search (*tt, d, n, e, &ds))); -- cgit v1.1