Skip to content

Commit 68b2954

Browse files
authored
Merge pull request #131 from ddunbar/directory-contents-recomputation-take-2
[BuildSystem] Fix bug where directory contents were always recomputed.
2 parents c8a84b3 + e226f17 commit 68b2954

File tree

3 files changed

+64
-6
lines changed

3 files changed

+64
-6
lines changed

lib/BuildSystem/BuildSystem.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,7 @@ class DirectoryContentsTask : public Task {
681681
if (info.isMissing()) {
682682
return value.isMissingInput();
683683
} else {
684-
return value.isExistingInput() && value.getOutputInfo() == info;
684+
return value.isDirectoryContents() && value.getOutputInfo() == info;
685685
}
686686
}
687687
};
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Check that directory contents are rebuilt *only* when appropriate.
2+
#
3+
# RUN: rm -rf %t.build
4+
# RUN: mkdir -p %t.build
5+
# RUN: cp %s %t.build/build.llbuild
6+
# RUN: mkdir -p %t.build/dir
7+
# RUN: %{llbuild} buildsystem build --serial --trace %t.initial.trace --chdir %t.build
8+
# RUN: %{FileCheck} --check-prefix=CHECK-INITIAL --input-file=%t.initial.trace %s
9+
#
10+
# CHECK-INITIAL: { "new-rule", "[[RULE_NAME:R[0-9]+]]", "Ddir" },
11+
# CHECK-INITIAL: { "rule-needs-to-run", "[[RULE_NAME]]", "never-built" },
12+
13+
14+
# A null rebuild shouldn't rebuild the directory.
15+
#
16+
# RUN: %{llbuild} buildsystem build --serial --trace %t.rebuild.trace --chdir %t.build
17+
# RUN: %{FileCheck} --check-prefix=CHECK-REBUILD --input-file=%t.rebuild.trace %s
18+
#
19+
# CHECK-REBUILD: { "new-rule", "[[RULE_NAME:R[0-9]+]]", "Ddir" },
20+
# CHECK-REBUILD: { "rule-does-not-need-to-run", "[[RULE_NAME]]" },
21+
22+
23+
# A rebuild after adding a new file should rebuild the directory.
24+
#
25+
# RUN: touch %t.build/dir/file
26+
# RUN: %{llbuild} buildsystem build --serial --trace %t.modified.trace --chdir %t.build
27+
# RUN: %{FileCheck} --check-prefix=CHECK-MODIFIED --input-file=%t.modified.trace %s
28+
#
29+
# CHECK-MODIFIED: { "new-rule", "[[RULE_NAME:R[0-9]+]]", "Ddir" },
30+
# CHECK-MODIFIED: { "rule-needs-to-run", "[[RULE_NAME]]", "invalid-value" },
31+
32+
client:
33+
name: basic
34+
35+
targets:
36+
"": ["<all>"]
37+
38+
commands:
39+
C.all:
40+
tool: phony
41+
inputs: ["dir/"]
42+
outputs: ["<all>"]

unittests/BuildSystem/BuildSystemTaskTests.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
using namespace llvm;
3333
using namespace llbuild;
34+
using namespace llbuild::basic;
3435
using namespace llbuild::buildsystem;
3536
using namespace llbuild::unittests;
3637

@@ -115,7 +116,8 @@ TEST(BuildSystemTaskTests, directoryContents) {
115116
/// Check the evaluation of directory signatures.
116117
TEST(BuildSystemTaskTests, directorySignature) {
117118
TmpDir tempDir{ __FUNCTION__ };
118-
119+
auto localFS = createLocalFileSystem();
120+
119121
// Create a directory with sample files.
120122
SmallString<256> fileA{ tempDir.str() };
121123
sys::path::append(fileA, "fileA");
@@ -159,25 +161,39 @@ TEST(BuildSystemTaskTests, directorySignature) {
159161
// Modify the immediate directory and rebuild.
160162
SmallString<256> fileC{ tempDir.str() };
161163
sys::path::append(fileC, "fileC");
162-
{
164+
165+
// We must write the file in a loop until the directory actually changes (we
166+
// currently assume we can trust the directory file info to detect changes,
167+
// which is not always strictly true).
168+
auto dirFileInfo = localFS->getFileInfo(tempDir.str());
169+
do {
163170
std::error_code ec;
171+
llvm::sys::fs::remove(fileC.str());
164172
llvm::raw_fd_ostream os(fileC, ec, llvm::sys::fs::F_Text);
165173
assert(!ec);
166174
os << "fileC";
167-
}
175+
} while (dirFileInfo == localFS->getFileInfo(tempDir.str()));
176+
168177
auto resultB = system.build(keyToBuild);
169178
ASSERT_TRUE(resultB.hasValue() && resultB->isDirectoryTreeSignature());
170179
ASSERT_TRUE(resultA->toData() != resultB->toData());
171180

172181
// Modify the subdirectory and rebuild.
173182
SmallString<256> subdirFileD{ subdirA };
174183
sys::path::append(subdirFileD, "fileD");
175-
{
184+
185+
// We must write the file in a loop until the directory actually changes (we
186+
// currently assume we can trust the directory file info to detect changes,
187+
// which is not always strictly true).
188+
dirFileInfo = localFS->getFileInfo(subdirA.str());
189+
do {
176190
std::error_code ec;
191+
llvm::sys::fs::remove(subdirFileD.str());
177192
llvm::raw_fd_ostream os(subdirFileD, ec, llvm::sys::fs::F_Text);
178193
assert(!ec);
179194
os << "fileD";
180-
}
195+
} while (dirFileInfo == localFS->getFileInfo(subdirA.str()));
196+
181197
auto resultC = system.build(keyToBuild);
182198
ASSERT_TRUE(resultC.hasValue() && resultC->isDirectoryTreeSignature());
183199
ASSERT_TRUE(resultA->toData() != resultB->toData());

0 commit comments

Comments
 (0)