Skip to content

Commit 17e20c3

Browse files
committed
rdar://105156287 ([ownership-analysis] Restrict mustScanAfterPaths to user scripts)
1 parent afa610a commit 17e20c3

File tree

9 files changed

+51
-57
lines changed

9 files changed

+51
-57
lines changed

include/llbuild/BuildSystem/Command.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class Command : public basic::JobDescriptor {
5555

5656
std::vector<BuildNode*> inputs;
5757
std::vector<BuildNode*> outputs;
58-
bool excludeFromOwnershipAnalysis = false;
58+
bool repairViaOwnershipAnalysis = false;
5959

6060
StringRef getName() const { return name; }
6161

lib/BuildSystem/BuildFile.cpp

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ class OwnershipAnalysis {
109109
public:
110110
std::vector<std::pair<BuildNode*, Command*>> outputNodesAndCommands;
111111

112-
std::vector<BuildNode*> allDirectoryInputNodes;
112+
std::vector<std::pair<BuildNode*, Command*>> directoryInputNodesAndCommands;
113113

114114
OwnershipAnalysis(const BuildDescription::command_set& commands, BuildFileDelegate& fileDelegate): fileDelegate(fileDelegate) {
115115
// Extract outputs and directory inputs of all commands
@@ -123,7 +123,7 @@ class OwnershipAnalysis {
123123

124124
for (auto input: command->getInputs()) {
125125
if (input->isDirectory()) {
126-
allDirectoryInputNodes.push_back(input);
126+
directoryInputNodesAndCommands.push_back(std::pair<BuildNode*, Command*>(input, command));
127127
}
128128
}
129129
}
@@ -140,7 +140,7 @@ class OwnershipAnalysis {
140140
/// Establish ownerships
141141
bool establishOwnerships() {
142142
for (auto outputNodeAndCommand: outputNodesAndCommands) {
143-
if (outputNodeAndCommand.second->isExternalCommand() && outputNodeAndCommand.second->excludeFromOwnershipAnalysis == false) {
143+
if (outputNodeAndCommand.second->isExternalCommand() && outputNodeAndCommand.second->repairViaOwnershipAnalysis == true) {
144144
Command *owner = includedOwnerOf(outputNodeAndCommand.first->getName());
145145
if (owner == nullptr) {
146146
setOwner(outputNodeAndCommand.first, outputNodeAndCommand.second);
@@ -224,12 +224,14 @@ class OwnershipAnalysis {
224224
//
225225
// This ensures TaskC will wait until TaskB is finished.
226226
void amendOutputOfOwnersWithConsumedSubpaths() {
227-
for (auto inputNode: allDirectoryInputNodes) {
228-
Command *owner = includedOwnerOf(inputNode->getName());
227+
for (auto directoryInputNodeAndCommand: directoryInputNodesAndCommands) {
228+
Command *owner = includedOwnerOf(directoryInputNodeAndCommand.first->getName());
229229
if (owner != nullptr) {
230230
auto ownerOutputs = owner->getOutputs();
231-
if (std::find(ownerOutputs.begin(), ownerOutputs.end(), inputNode) == ownerOutputs.end()) {
232-
owner->addOutput(inputNode);
231+
if (std::find(ownerOutputs.begin(), ownerOutputs.end(), directoryInputNodeAndCommand.first) == ownerOutputs.end()) {
232+
if (owner->repairViaOwnershipAnalysis) {
233+
owner->addOutput(directoryInputNodeAndCommand.first);
234+
}
233235
}
234236
}
235237
}
@@ -245,25 +247,27 @@ class OwnershipAnalysis {
245247
// We should add "a.txt" and "b.txt" to mustScanAfterPaths of "unowned-directory/".
246248
// This ensures TaskC will wait until TaskA and TaskB are finished.
247249
void deferScanningUnownedInputsUntilSubpathsAvailable() {
248-
auto unownedDirectoryInputNodes = std::vector<BuildNode*>();
249-
std::copy_if(allDirectoryInputNodes.begin(),
250-
allDirectoryInputNodes.end(),
251-
std::back_inserter(unownedDirectoryInputNodes),
252-
[this](const BuildNode* node) -> bool {
253-
return isIncludedUnownedNode(node);
250+
auto unownedDirectoryInputNodesAndConsumingCommands = std::vector<std::pair<BuildNode*, Command*>>();
251+
std::copy_if(directoryInputNodesAndCommands.begin(),
252+
directoryInputNodesAndCommands.end(),
253+
std::back_inserter(unownedDirectoryInputNodesAndConsumingCommands),
254+
[this](const std::pair<BuildNode*, Command*> directoryInputNodeAndCommand) -> bool {
255+
return isIncludedUnownedNode(directoryInputNodeAndCommand.first) && directoryInputNodeAndCommand.second->repairViaOwnershipAnalysis;
254256
});
255257

258+
// For each output node and its producing command (e.g. "unowned-directory/a.txt" and "TaskA"),
259+
// check if there exists an unowned node (e.g. "unowned-directory/" used by "TaskC") that is a parent of the produced node.
260+
// Only add "a.txt" to mustScanAfterPaths of "unowned-directory/" if TaskC is marked as "repairViaOwnershipAnalysis".
256261
for (auto outputNodeAndCommand: outputNodesAndCommands) {
257-
auto unownedNode = std::find_if(unownedDirectoryInputNodes.begin(),
258-
unownedDirectoryInputNodes.end(),
259-
[=](BuildNode* unownedDirectory) -> bool {
260-
return outputNodeAndCommand.first->getName().startswith(unownedDirectory->getName()) && outputNodeAndCommand.second->excludeFromOwnershipAnalysis == false;
262+
auto repairableUnownedNode =
263+
std::find_if(unownedDirectoryInputNodesAndConsumingCommands.begin(),
264+
unownedDirectoryInputNodesAndConsumingCommands.end(),
265+
[=](std::pair<BuildNode*, Command*> unownedDirectoryAndCommand) -> bool {
266+
return outputNodeAndCommand.first->getName().startswith(unownedDirectoryAndCommand.first->getName()) && outputNodeAndCommand.second->repairViaOwnershipAnalysis == true;
261267
});
262268

263-
if (unownedNode != unownedDirectoryInputNodes.end()) {
264-
auto mustScanAfterPath = outputNodeAndCommand.first->getName();
265-
std::string filename = llvm::sys::path::filename(mustScanAfterPath);
266-
(*unownedNode)->mustScanAfterPaths.push_back(outputNodeAndCommand.first->getName());
269+
if (repairableUnownedNode != unownedDirectoryInputNodesAndConsumingCommands.end()) {
270+
(*repairableUnownedNode).first->mustScanAfterPaths.push_back(outputNodeAndCommand.first->getName());
267271
}
268272
}
269273
}

lib/BuildSystem/BuildNode.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,6 @@ bool BuildNode::configureAttribute(const ConfigureContext& ctx, StringRef name,
104104
} else if (name == "content-exclusion-patterns") {
105105
exclusionPatterns = basic::StringList(value);
106106
return true;
107-
} else if (name == "must-scan-after-paths") {
108-
mustScanAfterPaths = basic::StringList(value).getValues();
109-
return true;
110107
}
111108

112109
// We don't support any other custom attributes.

lib/BuildSystem/BuildSystem.cpp

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3097,28 +3097,14 @@ class MkdirCommand : public ExternalCommand {
30973097
};
30983098

30993099
class MkdirTool : public Tool {
3100-
bool excludeFromOwnershipAnalysis = false;
31013100

31023101
public:
31033102
using Tool::Tool;
31043103

31053104
virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name,
31063105
StringRef value) override {
3107-
if (name == "exclude-from-ownership-analysis") {
3108-
if (value == "true") {
3109-
excludeFromOwnershipAnalysis = true;
3110-
return true;
3111-
} else if (value == "false") {
3112-
excludeFromOwnershipAnalysis = false;
3113-
return true;
3114-
} else {
3115-
ctx.error("invalid value for attribute: '" + name + "'");
3116-
return false;
3117-
}
3118-
} else {
3119-
ctx.error("unexpected attribute: '" + name + "'");
3120-
return false;
3121-
}
3106+
ctx.error("unexpected attribute: '" + name + "'");
3107+
return false;
31223108
}
31233109

31243110
virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name,
@@ -3137,7 +3123,6 @@ class MkdirTool : public Tool {
31373123

31383124
virtual std::unique_ptr<Command> createCommand(StringRef name) override {
31393125
auto res = llvm::make_unique<MkdirCommand>(name);
3140-
res->excludeFromOwnershipAnalysis = excludeFromOwnershipAnalysis;
31413126
return res;
31423127
}
31433128
};
@@ -3229,12 +3214,12 @@ class SymlinkCommand : public Command {
32293214
} else if (name == "link-output-path") {
32303215
linkOutputPath = value;
32313216
return true;
3232-
} else if (name == "exclude-from-ownership-analysis") {
3217+
} else if (name == "repair-via-ownership-analysis") {
32333218
if (value == "true") {
3234-
excludeFromOwnershipAnalysis = true;
3219+
repairViaOwnershipAnalysis = true;
32353220
return true;
32363221
} else if (value == "false") {
3237-
excludeFromOwnershipAnalysis = false;
3222+
repairViaOwnershipAnalysis = false;
32383223
return true;
32393224
} else {
32403225
ctx.error("invalid value for attribute: '" + name + "'");
@@ -3381,18 +3366,18 @@ class SymlinkCommand : public Command {
33813366
};
33823367

33833368
class SymlinkTool : public Tool {
3384-
bool excludeFromOwnershipAnalysis = false;
3369+
bool repairViaOwnershipAnalysis = false;
33853370
public:
33863371
using Tool::Tool;
33873372

33883373
virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name,
33893374
StringRef value) override {
3390-
if (name == "exclude-from-ownership-analysis") {
3375+
if (name == "repair-via-ownership-analysis") {
33913376
if (value == "true") {
3392-
excludeFromOwnershipAnalysis = true;
3377+
repairViaOwnershipAnalysis = true;
33933378
return true;
33943379
} else if(value == "false") {
3395-
excludeFromOwnershipAnalysis = false;
3380+
repairViaOwnershipAnalysis = false;
33963381
return true;
33973382
} else {
33983383
ctx.error("invalid value for attribute: '" + name + "'");
@@ -3420,7 +3405,7 @@ class SymlinkTool : public Tool {
34203405

34213406
virtual std::unique_ptr<Command> createCommand(StringRef name) override {
34223407
auto res = llvm::make_unique<SymlinkCommand>(name);
3423-
res->excludeFromOwnershipAnalysis = excludeFromOwnershipAnalysis;
3408+
res->repairViaOwnershipAnalysis = repairViaOwnershipAnalysis;
34243409
return res;
34253410
}
34263411
};

lib/BuildSystem/ExternalCommand.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,12 @@ configureAttribute(const ConfigureContext& ctx, StringRef name,
9797
alwaysOutOfDate = value == "true";
9898
return true;
9999

100-
} else if (name == "exclude-from-ownership-analysis") {
100+
} else if (name == "repair-via-ownership-analysis") {
101101
if (value == "true") {
102-
excludeFromOwnershipAnalysis = true;
102+
repairViaOwnershipAnalysis = true;
103103
return true;
104104
} else if (value == "false") {
105-
excludeFromOwnershipAnalysis = false;
105+
repairViaOwnershipAnalysis = false;
106106
return true;
107107
} else {
108108
ctx.error("invalid value for attribute: '" + name + "'");

products/libllbuild/BuildSystem-C-API.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -848,12 +848,12 @@ class CAPIExternalCommand : public ExternalCommand {
848848
} else {
849849
return false;
850850
}
851-
} else if (name == "exclude-from-ownership-analysis") {
851+
} else if (name == "repair-via-ownership-analysis") {
852852
if (value == "true") {
853-
excludeFromOwnershipAnalysis = true;
853+
repairViaOwnershipAnalysis = true;
854854
return true;
855855
} else if (value == "false") {
856-
excludeFromOwnershipAnalysis = false;
856+
repairViaOwnershipAnalysis = false;
857857
return true;
858858
} else {
859859
return false;

tests/BuildSystem/Build/directory-input-and-output.llbuild

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
#
88
# raw/
99
# | libX.fake-h <-- written on disk (initial state)
10-
# | libX.fake-h <-- written on disk (initial state)
1110
# | libY.fake-h <-- written on disk (initial state)
11+
# | libZ.fake-h <-- written on disk (initial state)
1212
# v
1313
# [TaskA] (verbatim copy; mixed case)
1414
# |
@@ -115,6 +115,7 @@ commands:
115115
cat $outputFile
116116
done
117117
'
118+
repair-via-ownership-analysis: true
118119

119120
taskA:
120121
tool: shell
@@ -136,3 +137,4 @@ commands:
136137
ls .
137138
cat *
138139
'
140+
repair-via-ownership-analysis: true

tests/BuildSystem/Build/directory-input-must-scan-after-paths-error.llbuild

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,20 @@ commands:
3232
outputs: ["out/a.txt"]
3333
description: "TaskA"
3434
args: "cat raw.txt > out/a.txt; cat out/a.txt; false"
35+
repair-via-ownership-analysis: true
3536

3637
taskB:
3738
tool: shell
3839
inputs: []
3940
outputs: ["out/b.txt"]
4041
description: "TaskB"
4142
args: "echo 'Output from TaskB for b.txt' > out/b.txt; cat out/b.txt"
43+
repair-via-ownership-analysis: true
4244

4345
taskC:
4446
tool: shell
4547
inputs: ["out/"]
4648
outputs: ["final.txt"]
4749
description: "TaskC"
4850
args: "cat out/* | tr a-z A-Z > final.txt; cat final.txt"
51+
repair-via-ownership-analysis: true

tests/BuildSystem/Build/directory-input-must-scan-after-paths.llbuild

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,20 @@ commands:
6464
outputs: ["out/a.txt"]
6565
description: "TaskA"
6666
args: "cat raw.txt > out/a.txt; cat out/a.txt"
67+
repair-via-ownership-analysis: true
6768

6869
taskB:
6970
tool: shell
7071
inputs: []
7172
outputs: ["out/b.txt"]
7273
description: "TaskB"
7374
args: "echo 'Output from TaskB for b.txt' > out/b.txt; cat out/b.txt"
75+
repair-via-ownership-analysis: true
7476

7577
taskC:
7678
tool: shell
7779
inputs: ["out/"]
7880
outputs: ["final.txt"]
7981
description: "TaskC"
8082
args: "cat out/* | tr a-z A-Z > final.txt; cat final.txt"
83+
repair-via-ownership-analysis: true

0 commit comments

Comments
 (0)