1 //===- ExternalCommand.h ----------------------------------------*- C++ -*-===//
2 //
3 // This source file is part of the Swift.org open source project
4 //
5 // Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
6 // Licensed under Apache License v2.0 with Runtime Library Exception
7 //
8 // See http://swift.org/LICENSE.txt for license information
9 // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLBUILD_BUILDSYSTEM_EXTERNALCOMMAND_H
14 #define LLBUILD_BUILDSYSTEM_EXTERNALCOMMAND_H
15 
16 #include "llbuild/BuildSystem/BuildDescription.h"
17 #include "llbuild/BuildSystem/BuildSystem.h"
18 #include "llbuild/BuildSystem/BuildValue.h"
19 #include "llbuild/BuildSystem/CommandResult.h"
20 
21 #include "llvm/ADT/Optional.h"
22 #include "llvm/ADT/StringRef.h"
23 
24 #include <string>
25 #include <vector>
26 
27 namespace llbuild {
28 namespace core {
29 
30 class Task;
31 
32 }
33 
34 namespace buildsystem {
35 
36 class BuildNode;
37 class BuildSystem;
38 struct QueueJobContext;
39 
40 /// This is a base class for defining commands which are run externally to the
41 /// build system and interact using files. It defines common base behaviors
42 /// which make sense for all such tools.
43 class ExternalCommand : public Command {
44   std::vector<BuildNode*> inputs;
45   std::vector<BuildNode*> outputs;
46   std::string description;
47 
48   /// Whether to allow missing inputs.
49   bool allowMissingInputs = false;
50 
51   /// Whether to allow modified outputs.
52   //
53   // FIXME: This is currently useful as a mechanism for defining builds in which
54   // an output is intentionally modified by another command. However, this isn't
55   // a very robust mechanism, and we should ultimately move to a model whereby
56   // we can reconstruct exactly the state of each individual command (by having
57   // a durable storage for the outputs outside of the file system).
58   bool allowModifiedOutputs = false;
59 
60   /// Whether to treat the command as always being out-of-date.
61   bool alwaysOutOfDate = false;
62 
63   // Build specific data.
64   //
65   // FIXME: We should probably factor this out somewhere else, so we can enforce
66   // it is never used when initialized incorrectly.
67 
68   /// The previous build result command signature, if available.
69   uint64_t priorResultCommandSignature;
70 
71   /// If not None, the command should be skipped with the provided BuildValue.
72   llvm::Optional<BuildValue> skipValue;
73 
74   /// If true, the command had a missing input (this implies ShouldSkip is
75   /// true).
76   bool hasMissingInput = false;
77 
78   /// If true, the command can legally be updated if the output state allows it.
79   bool canUpdateIfNewer = true;
80 
81   /// Whether a prior result has been found.
82   bool hasPriorResult = false;
83 
84   /// Compute the output result for the command.
85   BuildValue computeCommandResult(BuildSystemCommandInterface& bsci);
86 
87   /// Check if it is legal to only update the result (versus rerunning)
88   /// because the outputs are newer than all of the inputs.
89   bool canUpdateIfNewerWithResult(const BuildValue& result);
90 
91 protected:
getInputs()92   const std::vector<BuildNode*>& getInputs() { return inputs; }
93 
getOutputs()94   const std::vector<BuildNode*>& getOutputs() { return outputs; }
95 
getDescription()96   StringRef getDescription() { return description; }
97 
98   /// This function must be overriden by subclasses for any additional keys.
99   virtual uint64_t getSignature();
100 
101   /// Extension point for subclasses, to actually execute the command.
102   virtual CommandResult executeExternalCommand(BuildSystemCommandInterface& bsci,
103                                                core::Task* task,
104                                                QueueJobContext* context) = 0;
105 
106 public:
107   using Command::Command;
108 
109   virtual void configureDescription(const ConfigureContext&,
110                                     StringRef value) override;
111 
112   virtual void configureInputs(const ConfigureContext&,
113                                const std::vector<Node*>& value) override;
114 
115   virtual void configureOutputs(const ConfigureContext&,
116                                 const std::vector<Node*>& value) override;
117 
118   virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name,
119                                   StringRef value) override;
120   virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name,
121                                   ArrayRef<StringRef> values) override;
122   virtual bool configureAttribute(
123       const ConfigureContext&, StringRef name,
124       ArrayRef<std::pair<StringRef, StringRef>> values) override;
125 
126   virtual BuildValue getResultForOutput(Node* node,
127                                         const BuildValue& value) override;
128 
129   virtual bool isResultValid(BuildSystem&, const BuildValue& value) override;
130 
131   virtual void start(BuildSystemCommandInterface& bsci,
132                      core::Task* task) override;
133 
134   virtual void providePriorValue(BuildSystemCommandInterface&, core::Task*,
135                                  const BuildValue&) override;
136 
137   virtual void provideValue(BuildSystemCommandInterface& bsci, core::Task*,
138                             uintptr_t inputID,
139                             const BuildValue& value) override;
140 
141   virtual BuildValue execute(BuildSystemCommandInterface& bsci,
142                              core::Task* task,
143                              QueueJobContext* context) override;
144 };
145 
146 }
147 }
148 
149 #endif
150