diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2017-06-29 11:38:27 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2017-06-29 11:38:27 +0200 |
commit | be14f6c87cb3eeb9e3a2ac93802c9c236c191aa5 (patch) | |
tree | 1d19f375e60f05ddeb9ec8fa2672beecdc8d810e | |
parent | b752b85660d2fff149b0822ebe21e9f2d4ee4e1d (diff) |
Pass entire BMI graph, not only direct imports and re-exports
All current implementations require access to the entire graph (though
Clang embeds the file references so we don't need to pass the options).
-rw-r--r-- | build2/cc/compile.cxx | 81 | ||||
-rw-r--r-- | build2/cc/compile.hxx | 12 | ||||
-rw-r--r-- | tests/cc/modules/testscript | 39 |
3 files changed, 102 insertions, 30 deletions
diff --git a/build2/cc/compile.cxx b/build2/cc/compile.cxx index 9b8f31b..fd4b452 100644 --- a/build2/cc/compile.cxx +++ b/build2/cc/compile.cxx @@ -129,9 +129,9 @@ namespace build2 bool mod; // True if bmi*{} and src is x_mod. prerequisite_member src; preprocessed pp = preprocessed::none; - auto_rmfile psrc; // Preprocessed source, if any. - timestamp mt = timestamp_unknown; // Target timestamp. - modules_positions mod_pos = {0, 0}; // 0 if not present. + auto_rmfile psrc; // Preprocessed source, if any. + timestamp mt = timestamp_unknown; // Target timestamp. + module_positions mod_pos = {0, 0, 0}; }; compile:: @@ -2552,7 +2552,7 @@ namespace build2 // Resolve imported modules to bmi*{} targets. // - modules_positions compile:: + module_positions compile:: search_modules (action act, file& t, lorder lo, @@ -2678,7 +2678,7 @@ namespace build2 // shallow (from the BMI's point of view) reference to the module (or an // implicit import, if you will). Do you see where it's going? Nowever // good, that's right. This shallow reference means that the compiler - // should be able to find BMIs for all the re-imported modules, + // should be able to find BMIs for all the re-exported modules, // recursive. The good news is we are actually in a pretty good shape to // handle this: after match all our prerequisite BMIs will have their // prerequisite BMIs known, recursively. The only bit that is missing is @@ -2713,6 +2713,17 @@ namespace build2 // we are going to do is save another position, that of the start of // these copied-over targets, and will only execute up to this point. // + // And after implementing this came the reality check: all the current + // implementations require access to all the imported BMIs, not only + // re-exported. Some (like Clang) store references to imported BMI files + // so we actually don't need to pass any extra options but they still + // need access to the BMIs (and things will most likely have to be done + // differenly for distributed compilation). + // + // So the revised plan: on the off chance that some implementation will + // do it differently we will continue maintaing the imported/re-exported + // split and how much to copy-over can be made compiler specific. + // // As a first sub-step of step #1, move all the re-exported imports to // the end of the vector. This will make sure they end up at the end // of prerequisite_targets. @@ -2936,8 +2947,8 @@ namespace build2 // Post-process the list of our (direct) imports. While at it, calculate // the checksum of all (direct and indirect) bmi{} paths. // - size_t ex_start (n); - size_t ex_tail (pts.size ()); + size_t exported (n); + size_t copied (pts.size ()); for (size_t i (0); i != n; ++i) { @@ -2945,8 +2956,8 @@ namespace build2 // Determine the position of the first re-exported bmi{}. // - if (m.exported && ex_start == n) - ex_start = i; + if (m.exported && exported == n) + exported = i; const target* bt (pts[start + i]); @@ -2983,10 +2994,9 @@ namespace build2 // cs.append (static_cast<const file&> (*bt).path ().string ()); - // Copy over re-exported bmi{} from our prerequisites weeding out - // duplicates. + // Copy over bmi{}s from our prerequisites weeding out duplicates. // - if (size_t j = bt->data<match_data> ().mod_pos.ex_start) + if (size_t j = bt->data<match_data> ().mod_pos.start) { // Hard to say whether we should reserve or not. We will probably // get quite a bit of duplications. @@ -3020,15 +3030,15 @@ namespace build2 } } - if (ex_tail == pts.size ()) // No copied tail. - ex_tail = 0; + if (copied == pts.size ()) // No copied tail. + copied = 0; - if (ex_start == n) // No (own) re-exported imports. - ex_start = ex_tail; + if (exported == n) // No (own) re-exported imports. + exported = copied; else - ex_start += start; // Rebase. + exported += start; // Rebase. - return modules_positions {ex_start, ex_tail}; + return module_positions {start, exported, copied}; } // Filter cl.exe noise (msvc.cxx). @@ -3037,10 +3047,31 @@ namespace build2 msvc_filter_cl (ifdstream&, const path& src); void compile:: - append_modules (cstrings& args, strings& stor, const file& t) const + append_modules (cstrings& args, + strings& stor, + const file& t, + const module_positions& mp) const { - for (const target* pt: t.prerequisite_targets) + size_t n (t.prerequisite_targets.size ()); + + // Clang embeds module file references so we only need to specify + // our direct imports. + // + // If/when we get the ability to specify the mapping in a file, we + // should probably pass the whole list. + // + switch (cid) { + case compiler_id::clang: n = mp.copied != 0 ? mp.copied : n; break; + case compiler_id::gcc: + case compiler_id::msvc: break; // All of them. + case compiler_id::icc: assert (false); + } + + for (size_t i (mp.start); i != n; ++i) + { + const target* pt (t.prerequisite_targets[i]); + if (pt == nullptr) continue; @@ -3104,7 +3135,7 @@ namespace build2 (mod ? *x_mod : x_src), act, t, md.mt, nullptr, - md.mod_pos.ex_tail)); // See search_modules() for details. + md.mod_pos.copied)); // See search_modules() for details. if (pr.first) { @@ -3214,8 +3245,8 @@ namespace build2 if (!find_option_prefixes ({"/MD", "/MT"}, args)) args.push_back ("/MD"); - if (modules) - append_modules (args, mods, t); + if (md.mod_pos.start != 0) + append_modules (args, mods, t, md.mod_pos); // The presence of /Zi or /ZI causes the compiler to write debug info // to the .pdb file. By default it is a shared file called vcNN.pdb @@ -3279,8 +3310,8 @@ namespace build2 args.push_back ("-fPIC"); } - if (modules) - append_modules (args, mods, t); + if (md.mod_pos.start != 0) + append_modules (args, mods, t, md.mod_pos); // Note: the order of the following options is relied upon below. // diff --git a/build2/cc/compile.hxx b/build2/cc/compile.hxx index ed9c18d..778a637 100644 --- a/build2/cc/compile.hxx +++ b/build2/cc/compile.hxx @@ -30,10 +30,11 @@ namespace build2 // Positions of the re-exported bmi{}s. See search_modules() for // details. // - struct modules_positions + struct module_positions { - size_t ex_start; - size_t ex_tail; + size_t start; // First imported bmi*{}, 0 if none. + size_t exported; // First re-exported bmi*{}, 0 if none. + size_t copied; // First copied-over bmi*{}, 0 if none. }; class compile: public rule, virtual common @@ -111,12 +112,13 @@ namespace build2 const file&, match_data&, module_info&&, depdb&, bool&) const; - modules_positions + module_positions search_modules (action, file&, lorder, const target_type&, const file&, module_imports&&, sha256&) const; void - append_modules (cstrings&, strings&, const file&) const; + append_modules (cstrings&, strings&, + const file&, const module_positions&) const; // Language selection option (for VC) or the value for the -x option. // diff --git a/tests/cc/modules/testscript b/tests/cc/modules/testscript index d35de50..1fb1345 100644 --- a/tests/cc/modules/testscript +++ b/tests/cc/modules/testscript @@ -285,6 +285,45 @@ if ($cxx.id.type != "clang") EOI } +: import +: +: Test module import. Currently, all the implementation require access to the +: entire, recursively-explored list of BMIs. +: +{ + # Note: using VC export module fixup support. + + +cat <<EOI >=base.mxx + export module foo.base; + import foo.core; + export int g (int i) {return f (i);} + EOI + + +cat <<EOI >=extra.mxx + export module foo.extra; + import foo.base; + export int h (int i) {return g (i);} + EOI + + : basic + : + ln -s ../base.mxx ../../core.mxx ../../core.cxx ./; + cat <<EOI >=driver.cxx; + import foo.base; + int main (int argc, char*[]) {return g (argc);} + EOI + $* test clean <'exe{test}: cxx{driver core} mxx{core base}' + + : recursive + : + ln -s ../base.mxx ../extra.mxx ../../core.mxx ../../core.cxx ./; + cat <<EOI >=driver.cxx; + import foo.extra; + int main (int argc, char*[]) {return h (argc);} + EOI + $* test clean <'exe{test}: cxx{driver core} mxx{core base extra}' +} + : resolve-change : : Test detection of module name to BMI resolution change. |