summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2018-11-28 11:11:10 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2018-11-28 11:11:10 +0200
commit8901004f9e783fb3a30e2ddb1e69e8f8a7d085f5 (patch)
tree11d4b80a099d1dcea5404ec45c52201d9ec23b38
parent9190569b69e34468841b18b33c98f78e66a3d26e (diff)
downloadbuild2-8901004f9e783fb3a30e2ddb1e69e8f8a7d085f5.tar.gz
build2-8901004f9e783fb3a30e2ddb1e69e8f8a7d085f5.tar.xz
build2-8901004f9e783fb3a30e2ddb1e69e8f8a7d085f5.zip
Add --[no-]mtime-check options to control this behavior at runtime
By default the checks are enabled only for the staged toolchain.
-rw-r--r--build2/b-options.cxx15
-rw-r--r--build2/b-options.hxx8
-rw-r--r--build2/b-options.ixx12
-rw-r--r--build2/b.cli13
-rw-r--r--build2/b.cxx5
-rw-r--r--build2/cc/compile-rule.cxx9
-rw-r--r--build2/cc/link-rule.cxx2
-rw-r--r--build2/cli/rule.cxx2
-rw-r--r--build2/config.hxx.in9
-rw-r--r--build2/depdb.cxx35
-rw-r--r--build2/depdb.hxx36
-rw-r--r--build2/depdb.ixx23
-rw-r--r--build2/in/rule.cxx2
13 files changed, 127 insertions, 44 deletions
diff --git a/build2/b-options.cxx b/build2/b-options.cxx
index 23ebae73..6409f3e7 100644
--- a/build2/b-options.cxx
+++ b/build2/b-options.cxx
@@ -612,6 +612,8 @@ namespace build2
max_stack_ (),
max_stack_specified_ (false),
serial_stop_ (),
+ mtime_check_ (),
+ no_mtime_check_ (),
structured_result_ (),
match_only_ (),
no_column_ (),
@@ -793,6 +795,15 @@ namespace build2
<< " default concurrency)." << ::std::endl;
os << std::endl
+ << "\033[1m--mtime-check\033[0m Perform file modification time sanity checks. These checks" << ::std::endl
+ << " can be helpful in diagnosing spurious rebuilds and are" << ::std::endl
+ << " enabled by default for the staged version of the build" << ::std::endl
+ << " system. Use \033[1m--no-mtime-check\033[0m to disable." << ::std::endl;
+
+ os << std::endl
+ << "\033[1m--no-mtime-check\033[0m Don't perform file modification time sanity checks." << ::std::endl;
+
+ os << std::endl
<< "\033[1m--structured-result\033[0m Write the result of execution in a structured form. In" << ::std::endl
<< " this mode, instead of printing to \033[1mSTDERR\033[0m diagnostics" << ::std::endl
<< " messages about the outcome of executing actions on" << ::std::endl
@@ -926,6 +937,10 @@ namespace build2
&::build2::cl::thunk< options, bool, &options::serial_stop_ >;
_cli_options_map_["-s"] =
&::build2::cl::thunk< options, bool, &options::serial_stop_ >;
+ _cli_options_map_["--mtime-check"] =
+ &::build2::cl::thunk< options, bool, &options::mtime_check_ >;
+ _cli_options_map_["--no-mtime-check"] =
+ &::build2::cl::thunk< options, bool, &options::no_mtime_check_ >;
_cli_options_map_["--structured-result"] =
&::build2::cl::thunk< options, bool, &options::structured_result_ >;
_cli_options_map_["--match-only"] =
diff --git a/build2/b-options.hxx b/build2/b-options.hxx
index 0aad125c..94a87abc 100644
--- a/build2/b-options.hxx
+++ b/build2/b-options.hxx
@@ -473,6 +473,12 @@ namespace build2
serial_stop () const;
const bool&
+ mtime_check () const;
+
+ const bool&
+ no_mtime_check () const;
+
+ const bool&
structured_result () const;
const bool&
@@ -558,6 +564,8 @@ namespace build2
size_t max_stack_;
bool max_stack_specified_;
bool serial_stop_;
+ bool mtime_check_;
+ bool no_mtime_check_;
bool structured_result_;
bool match_only_;
bool no_column_;
diff --git a/build2/b-options.ixx b/build2/b-options.ixx
index 2b6e8b04..b05ed668 100644
--- a/build2/b-options.ixx
+++ b/build2/b-options.ixx
@@ -346,6 +346,18 @@ namespace build2
}
inline const bool& options::
+ mtime_check () const
+ {
+ return this->mtime_check_;
+ }
+
+ inline const bool& options::
+ no_mtime_check () const
+ {
+ return this->no_mtime_check_;
+ }
+
+ inline const bool& options::
structured_result () const
{
return this->structured_result_;
diff --git a/build2/b.cli b/build2/b.cli
index 77f50ba9..68ef0fec 100644
--- a/build2/b.cli
+++ b/build2/b.cli
@@ -508,6 +508,19 @@ namespace build2
\c{-j 0} for default concurrency)."
}
+ bool --mtime-check
+ {
+ "Perform file modification time sanity checks. These checks can be
+ helpful in diagnosing spurious rebuilds and are enabled by default
+ for the staged version of the build system. Use \cb{--no-mtime-check}
+ to disable."
+ }
+
+ bool --no-mtime-check
+ {
+ "Don't perform file modification time sanity checks."
+ }
+
bool --structured-result
{
"Write the result of execution in a structured form. In this mode,
diff --git a/build2/b.cxx b/build2/b.cxx
index 74dc7a21..bb7ec418 100644
--- a/build2/b.cxx
+++ b/build2/b.cxx
@@ -327,7 +327,10 @@ main (int argc, char* argv[])
// Validate options.
//
if (ops.progress () && ops.no_progress ())
- fail << "inconsistent progress display options";
+ fail << "both --progress and --no-progress specified";
+
+ if (ops.mtime_check () && ops.no_mtime_check ())
+ fail << "both --mtime-check and --no-mtime-check specified";
// Global initializations.
//
diff --git a/build2/cc/compile-rule.cxx b/build2/cc/compile-rule.cxx
index 93261936..897a9f16 100644
--- a/build2/cc/compile-rule.cxx
+++ b/build2/cc/compile-rule.cxx
@@ -4250,8 +4250,13 @@ namespace build2
}
// Make sure depdb is no older than any of our prerequisites (see md.mt
- // logic description above for details).
+ // logic description above for details). Also save the sequence start
+ // time if doing mtime checks (see the depdb::check_mtime() call below).
//
+ timestamp start (depdb::mtime_check ()
+ ? system_clock::now ()
+ : timestamp_unknown);
+
touch (md.dd, false, verb_never);
const scope& bs (t.base_scope ());
@@ -4670,7 +4675,7 @@ namespace build2
}
timestamp now (system_clock::now ());
- depdb::verify (timestamp_unknown, md.dd, tp, now);
+ depdb::check_mtime (start, md.dd, tp, now);
// Should we go to the filesystem and get the new mtime? We know the
// file has been modified, so instead just use the current clock time.
diff --git a/build2/cc/link-rule.cxx b/build2/cc/link-rule.cxx
index 47c058d0..ca517000 100644
--- a/build2/cc/link-rule.cxx
+++ b/build2/cc/link-rule.cxx
@@ -2554,7 +2554,7 @@ namespace build2
}
rm.cancel ();
- dd.verify (tp);
+ dd.check_mtime (tp);
// Should we go to the filesystem and get the new mtime? We know the
// file has been modified, so instead just use the current clock time.
diff --git a/build2/cli/rule.cxx b/build2/cli/rule.cxx
index d07af158..626d0ee0 100644
--- a/build2/cli/rule.cxx
+++ b/build2/cli/rule.cxx
@@ -324,7 +324,7 @@ namespace build2
run (cli, args);
- dd.verify (tp);
+ dd.check_mtime (tp);
t.mtime (system_clock::now ());
return target_state::changed;
diff --git a/build2/config.hxx.in b/build2/config.hxx.in
index af42fcd0..e84fd6ae 100644
--- a/build2/config.hxx.in
+++ b/build2/config.hxx.in
@@ -21,6 +21,15 @@
//
#define BUILD2_STAGE true
+// Modification time sanity checks are by default only enabled for the staged
+// version but this can be overridden at runtime with --[no-]mtime-check.
+//
+#if BUILD2_STAGE
+# define BUILD2_MTIME_CHECK true
+#else
+# define BUILD2_MTIME_CHECK false
+#endif
+
#ifdef BUILD2_BOOTSTRAP
#else
#endif
diff --git a/build2/depdb.cxx b/build2/depdb.cxx
index 94b845de..f89daba9 100644
--- a/build2/depdb.cxx
+++ b/build2/depdb.cxx
@@ -272,9 +272,8 @@ namespace build2
change (true /* truncate */);
}
-#ifdef BUILD2_MTIME_CHECK
- start_ = system_clock::now ();
-#endif
+ if (mtime_check ())
+ start_ = system_clock::now ();
os_.put ('\0'); // The "end marker".
os_.close ();
@@ -296,13 +295,9 @@ namespace build2
#endif
}
-#ifdef BUILD2_MTIME_CHECK
void depdb::
- verify (const path_type& t, timestamp e)
+ check_mtime_ (const path_type& t, timestamp e)
{
- if (state_ != state::write)
- return;
-
// We could call the static version but then we would have lost additional
// information for some platforms.
//
@@ -315,18 +310,21 @@ namespace build2
e = system_clock::now ();
fail << "backwards modification times detected:\n"
- << start_ << " sequence start\n"
+ << " " << start_ << " sequence start\n"
#if defined(__FreeBSD__)
- << mtime << " close mtime\n"
+ << " " << mtime << " close mtime\n"
#endif
- << d_mt << " " << path.string () << '\n'
- << t_mt << " " << t.string () << '\n'
- << e << " sequence end";
+ << " " << d_mt << " " << path.string () << '\n'
+ << " " << t_mt << " " << t.string () << '\n'
+ << " " << e << " sequence end";
}
}
void depdb::
- verify (timestamp s, const path_type& d, const path_type& t, timestamp e)
+ check_mtime_ (timestamp s,
+ const path_type& d,
+ const path_type& t,
+ timestamp e)
{
timestamp t_mt (file_mtime (t));
timestamp d_mt (file_mtime (d));
@@ -334,11 +332,10 @@ namespace build2
if (d_mt > t_mt)
{
fail << "backwards modification times detected:\n"
- << s << " sequence start\n"
- << d_mt << " " << d.string () << '\n'
- << t_mt << " " << t.string () << '\n'
- << e << " sequence end";
+ << " " << s << " sequence start\n"
+ << " " << d_mt << " " << d.string () << '\n'
+ << " " << t_mt << " " << t.string () << '\n'
+ << " " << e << " sequence end";
}
}
-#endif // BUILD2_MTIME_CHECK
}
diff --git a/build2/depdb.hxx b/build2/depdb.hxx
index 66d89e99..f93f16c4 100644
--- a/build2/depdb.hxx
+++ b/build2/depdb.hxx
@@ -10,8 +10,6 @@
#include <build2/types.hxx>
#include <build2/utility.hxx>
-#define BUILD2_MTIME_CHECK
-
namespace build2
{
// Auxiliary dependency database (those .d files). Uses io_error and
@@ -110,8 +108,8 @@ namespace build2
// may be left in the old/currupt state. Note that in the read mode this
// function will "chop off" lines that haven't been read.
//
- // Make sure to also call verify() after updating the target to perform
- // the target/database modification times sanity check.
+ // Make sure to also call check_mtime() after updating the target to
+ // perform the target/database modification times sanity checks.
//
void
close ();
@@ -119,13 +117,18 @@ namespace build2
// Perform target/database modification times sanity check.
//
void
- verify (const path_type& target, timestamp end = timestamp_unknown);
+ check_mtime (const path_type& target, timestamp end = timestamp_unknown);
static void
- verify (timestamp start,
- const path_type& db,
- const path_type& target,
- timestamp end);
+ check_mtime (timestamp start,
+ const path_type& db,
+ const path_type& target,
+ timestamp end);
+
+ // Return true if mtime checks are enabled.
+ //
+ static bool
+ mtime_check ();
// Read the next line. If the result is not NULL, then it is a pointer to
// the next line in the database (which you are free to move from). If you
@@ -251,13 +254,16 @@ namespace build2
string*
read_ ();
- private:
- uint64_t pos_; // Start of the last returned line.
- string line_; // Current line.
+ void
+ check_mtime_ (const path_type&, timestamp);
+
+ static void
+ check_mtime_ (timestamp, const path_type&, const path_type&, timestamp);
-#ifdef BUILD2_MTIME_CHECK
- timestamp start_;
-#endif
+ private:
+ uint64_t pos_; // Start of the last returned line.
+ string line_; // Current line.
+ timestamp start_; // Sequence start (mtime check).
};
}
diff --git a/build2/depdb.ixx b/build2/depdb.ixx
index 46fdb286..ecaf102b 100644
--- a/build2/depdb.ixx
+++ b/build2/depdb.ixx
@@ -13,15 +13,30 @@ namespace build2
os_.~ofdstream ();
}
-#ifndef BUILD2_MTIME_CHECK
+ inline bool depdb::
+ mtime_check ()
+ {
+ // Note: options were validated in main().
+ //
+ return (ops. mtime_check () ? true :
+ ops.no_mtime_check () ? false :
+ BUILD2_MTIME_CHECK);
+ }
+
inline void depdb::
- verify (const path_type&, timestamp)
+ check_mtime (const path_type& t, timestamp e)
{
+ if (state_ == state::write && mtime_check ())
+ check_mtime_ (t, e);
}
inline void depdb::
- verify (timestamp, const path_type&, const path_type&, timestamp)
+ check_mtime (timestamp s,
+ const path_type& d,
+ const path_type& t,
+ timestamp e)
{
+ if (mtime_check ())
+ check_mtime_ (s, d, t, e);
}
-#endif
}
diff --git a/build2/in/rule.cxx b/build2/in/rule.cxx
index 1395958c..924bf954 100644
--- a/build2/in/rule.cxx
+++ b/build2/in/rule.cxx
@@ -401,7 +401,7 @@ namespace build2
fail << "unable to " << what << ' ' << *whom << ": " << e;
}
- dd.verify (tp);
+ dd.check_mtime (tp);
t.mtime (system_clock::now ());
return target_state::changed;