blob: 6dd439bb8ac168936b379ee6e0e3c19b3d178d87 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
// file : libbuild2/dynamic.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
#include <libbuild2/dynamic.hxx>
#include <libbuild2/scope.hxx>
#include <libbuild2/target.hxx>
#include <libbuild2/context.hxx>
#include <libbuild2/algorithm.hxx>
#include <libbuild2/diagnostics.hxx>
using namespace std;
using namespace butl;
namespace build2
{
bool
update_during_match (tracer& trace, action a, const target& t, timestamp ts)
{
// In particular, this function is used to make sure header dependencies
// are up to date.
//
// There would normally be a lot of headers for every source file (think
// all the system headers) and just calling execute_direct() on all of
// them can get expensive. At the same time, most of these headers are
// existing files that we will never be updating (again, system headers,
// for example) and the rule that will match them is the fallback
// file_rule. That rule has an optimization: it returns noop_recipe (which
// causes the target state to be automatically set to unchanged) if the
// file is known to be up to date. So we do the update "smartly".
//
const path_target* pt (t.is_a<path_target> ());
if (pt == nullptr)
ts = timestamp_unknown;
target_state os (t.matched_state (a));
if (os == target_state::unchanged)
{
if (ts == timestamp_unknown)
return false;
else
{
// We expect the timestamp to be known (i.e., existing file).
//
timestamp mt (pt->mtime ());
assert (mt != timestamp_unknown);
return mt > ts;
}
}
else
{
// We only want to return true if our call to execute() actually caused
// an update. In particular, the target could already have been in
// target_state::changed because of the dynamic dependency extraction
// run for some other target.
//
// @@ MT perf: so we are going to switch the phase and execute for
// any generated header.
//
phase_switch ps (t.ctx, run_phase::execute);
target_state ns (execute_direct (a, t));
if (ns != os && ns != target_state::unchanged)
{
l6 ([&]{trace << "updated " << t
<< "; old state " << os
<< "; new state " << ns;});
return true;
}
else
return ts != timestamp_unknown ? pt->newer (ts, ns) : false;
}
}
}
|