aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build2/cc/compile-rule.cxx54
-rw-r--r--build2/cc/parser.hxx2
2 files changed, 42 insertions, 14 deletions
diff --git a/build2/cc/compile-rule.cxx b/build2/cc/compile-rule.cxx
index 96b5029..d6fea9f 100644
--- a/build2/cc/compile-rule.cxx
+++ b/build2/cc/compile-rule.cxx
@@ -865,7 +865,7 @@ namespace build2
u = true; // Database is invalid, force re-parse.
translation_unit tu;
- for (bool f (true);; f = false)
+ for (bool first (true);; first = false)
{
if (u)
{
@@ -873,10 +873,14 @@ namespace build2
if (cs != p.second)
{
- assert (f); // Unchanged TU has a different checksum?
+ assert (first); // Unchanged TU has a different checksum?
dd.write (p.second);
}
- else if (f) // Don't clear if it was forced.
+ //
+ // Don't clear if it was forced or the checksum should not be
+ // relied upon.
+ //
+ else if (first && !cs.empty ())
{
// Clear the update flag and set the touch flag. Unless there
// is no object file, of course. See also the md.mt logic
@@ -894,11 +898,11 @@ namespace build2
if (modules)
{
- if (u || !f)
+ if (u || !first)
{
string s (to_string (tu.mod));
- if (f)
+ if (first)
dd.expect (s);
else
dd.write (s);
@@ -963,10 +967,10 @@ namespace build2
dd.close ();
- // If the preprocessed output is suitable for compilation and is not
- // disabled, then pass it along.
+ // If the preprocessed output is suitable for compilation, then pass
+ // it along.
//
- if (psrc.second && !cast_false<bool> (t[c_reprocess]))
+ if (psrc.second)
{
md.psrc = move (psrc.first);
@@ -1422,6 +1426,8 @@ namespace build2
l5 ([&]{trace << "target: " << t;});
+ bool reprocess (cast_false<bool> (t[c_reprocess]));
+
auto_rmfile psrc;
bool puse (true);
@@ -1630,7 +1636,7 @@ namespace build2
// Return NULL if the dependency information goes to stdout and a
// pointer to the temporary file path otherwise.
//
- auto init_args = [&t, a, li,
+ auto init_args = [&t, a, li, reprocess,
&src, &md, &psrc, &sense_diag,
&rs, &bs,
pp, &env, &args, &args_gen, &args_i, &out, &drm,
@@ -1677,6 +1683,14 @@ namespace build2
//
args.push_back (cpath.recall_string ());
+ // If we are re-processing the translation unit, then allow the
+ // translation unit to detect header/module dependency extraction.
+ // This can be used to work around separate preprocessing bugs in
+ // the compiler.
+ //
+ if (reprocess)
+ args.push_back ("-D__build2_preprocess");
+
// Add *.export.poptions from prerequisite libraries.
//
append_lib_options (bs, args, a, t, li);
@@ -2790,14 +2804,17 @@ namespace build2
}
}
- // Add the terminating blank line (we are updated depdb).
+ // Add the terminating blank line (we are updating depdb).
//
dd.expect ("");
- puse = puse && !psrc.path.empty ();
+ puse = puse && !reprocess && !psrc.path.empty ();
return make_pair (move (psrc), puse);
}
+ // Return the translation unit information (first) and its checksum
+ // (second). If the checksum is empty, then it should not be used.
+ //
pair<translation_unit, string> compile_rule::
parse_unit (action a,
file& t,
@@ -2831,6 +2848,8 @@ namespace build2
cstrings args;
const path* sp; // Source path.
+ bool reprocess (cast_false<bool> (t[c_reprocess]));
+
bool ps; // True if extracting from psrc.
if (md.pp < preprocessed::modules)
{
@@ -2840,7 +2859,7 @@ namespace build2
// may extend cc.reprocess to allow specifying where reprocessing is
// needed).
//
- ps = !psrc.path.empty () && !cast_false<bool> (t[c_reprocess]);
+ ps = !psrc.path.empty () && !reprocess;
sp = &(ps ? psrc.path : src.path ());
// VC's preprocessed output, if present, is fully preprocessed.
@@ -2852,6 +2871,9 @@ namespace build2
//
args.push_back (cpath.recall_string ());
+ if (reprocess)
+ args.push_back ("-D__build2_preprocess");
+
append_lib_options (t.base_scope (), args, a, t, lo);
append_options (args, t, c_poptions);
@@ -3008,7 +3030,13 @@ namespace build2
tu.mod.iface = true;
}
- return pair<translation_unit, string> (move (tu), p.checksum);
+ // If we were forced to reprocess, assume the checksum is not
+ // accurate (parts of the translation unit could have been
+ // #ifdef'ed out; see __build2_preprocess).
+ //
+ return pair<translation_unit, string> (
+ move (tu),
+ reprocess ? string () : move (p.checksum));
}
// Fall through.
diff --git a/build2/cc/parser.hxx b/build2/cc/parser.hxx
index a4fd5f8..f2ecc36 100644
--- a/build2/cc/parser.hxx
+++ b/build2/cc/parser.hxx
@@ -38,7 +38,7 @@ namespace build2
parse_module_name (token&);
public:
- string checksum; // Translation unit checksum.
+ string checksum; // Translation unit checksum.
private:
lexer* l_;