semantics, as described in the <<ref_rule,rule reference>>.
3. _Order-only dependencies_, expressed with the syntax +|| _dep1_
- _dep2_+ on the end of a build line. When these are missing, the
- output is not rebuilt until they are built, but once they are
- available further changes to the files do not affect the output.
+ _dep2_+ on the end of a build line. When these are out of date, the
+ output is not rebuilt until they are built, but changes in order-only
+ dependencies alone do not cause the output to be rebuilt.
+
Order-only dependencies can be useful for bootstrapping dependencies
that are only discovered during build time: for example, to generate a
ASSERT_EQ(1u, commands_ran_.size());
}
+TEST_F(BuildTest, RebuildOrderOnlyDeps) {
+ string err;
+ ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
+"rule cc\n command = cc $in\n"
+"rule true\n command = true\n"
+"build oo.h: cc oo.h.in\n"
+"build foo.o: cc foo.c || oo.h\n"));
+
+ fs_.Create("foo.c", now_, "");
+ fs_.Create("oo.h.in", now_, "");
+
+ // foo.o and order-only dep dirty, build both.
+ EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
+ EXPECT_TRUE(builder_.Build(&err));
+ ASSERT_EQ("", err);
+ ASSERT_EQ(2u, commands_ran_.size());
+
+ // all clean, no rebuild.
+ commands_ran_.clear();
+ state_.Reset();
+ EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
+ EXPECT_EQ("", err);
+ EXPECT_TRUE(builder_.AlreadyUpToDate());
+
+ // order-only dep missing, build it only.
+ fs_.RemoveFile("oo.h");
+ commands_ran_.clear();
+ state_.Reset();
+ EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
+ EXPECT_TRUE(builder_.Build(&err));
+ ASSERT_EQ("", err);
+ ASSERT_EQ(1u, commands_ran_.size());
+ ASSERT_EQ("cc oo.h.in", commands_ran_[0]);
+
+ now_++;
+
+ // order-only dep dirty, build it only.
+ fs_.Create("oo.h.in", now_, "");
+ commands_ran_.clear();
+ state_.Reset();
+ EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
+ EXPECT_TRUE(builder_.Build(&err));
+ ASSERT_EQ("", err);
+ ASSERT_EQ(1u, commands_ran_.size());
+ ASSERT_EQ("cc oo.h.in", commands_ran_[0]);
+}
+
TEST_F(BuildTest, Phony) {
string err;
ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
}
}
- if (is_order_only(i - inputs_.begin())) {
- // Order-only deps only make us dirty if they're missing.
- if (!(*i)->file_->exists()) {
- dirty = true;
- outputs_ready_ = false;
- }
- continue;
- }
-
// If an input is not ready, neither are our outputs.
if (Edge* edge = (*i)->in_edge_)
if (!edge->outputs_ready_)
outputs_ready_ = false;
- // If a regular input is dirty (or missing), we're dirty.
- // Otherwise consider mtime.
- if ((*i)->dirty_) {
- dirty = true;
- } else {
- if ((*i)->file_->mtime_ > most_recent_input)
- most_recent_input = (*i)->file_->mtime_;
+ if (!is_order_only(i - inputs_.begin())) {
+ // If a regular input is dirty (or missing), we're dirty.
+ // Otherwise consider mtime.
+ if ((*i)->dirty_) {
+ dirty = true;
+ } else {
+ if ((*i)->file_->mtime_ > most_recent_input)
+ most_recent_input = (*i)->file_->mtime_;
+ }
}
}