github.phpd.cn/thought-machine/please@v12.2.0+incompatible/src/core/build_input.go (about) 1 // Implementation of the BuildInput interface for simple cases of files in the local package. 2 3 package core 4 5 import ( 6 "path" 7 "strings" 8 ) 9 10 // A BuildInput represents some kind of input to a build rule. They can be implemented 11 // as either a file (in the local package or on the system) or another build rule. 12 type BuildInput interface { 13 // Paths returns a slice of paths to the files of this input. 14 Paths(graph *BuildGraph) []string 15 // FullPaths is like Paths but includes the leading plz-out/gen directory. 16 FullPaths(graph *BuildGraph) []string 17 // LocalPaths returns paths within the local package 18 LocalPaths(graph *BuildGraph) []string 19 // Label returns the build label associated with this input, or nil if it doesn't have one (eg. it's just a file). 20 Label() *BuildLabel 21 // nonOutputLabel returns the build label associated with this input, or nil if it doesn't have 22 // one or is a specific output of a rule. 23 // This is fiddly enough that we don't want to expose it outside the package right now. 24 nonOutputLabel() *BuildLabel 25 // String returns a string representation of this input 26 String() string 27 } 28 29 // FileLabel represents a file in the current package which is directly used by a target. 30 type FileLabel struct { 31 // Name of the file 32 File string 33 // Name of the package 34 Package string 35 } 36 37 // Paths returns a slice of paths to the files of this input. 38 func (label FileLabel) Paths(graph *BuildGraph) []string { 39 return []string{path.Join(label.Package, label.File)} 40 } 41 42 // FullPaths is like Paths but includes the leading plz-out/gen directory. 43 func (label FileLabel) FullPaths(graph *BuildGraph) []string { 44 return label.Paths(graph) 45 } 46 47 // LocalPaths returns paths within the local package 48 func (label FileLabel) LocalPaths(graph *BuildGraph) []string { 49 return []string{label.File} 50 } 51 52 // Label returns the build rule associated with this input. For a FileLabel it's always nil. 53 func (label FileLabel) Label() *BuildLabel { 54 return nil 55 } 56 57 func (label FileLabel) nonOutputLabel() *BuildLabel { 58 return nil 59 } 60 61 // String returns a string representation of this input. 62 func (label FileLabel) String() string { 63 return label.File 64 } 65 66 // A SubrepoFileLabel represents a file in the current package within a subrepo. 67 type SubrepoFileLabel struct { 68 // Name of the file 69 File string 70 // Name of the package 71 Package string 72 // The full path, including the subrepo root. 73 FullPackage string 74 } 75 76 // Paths returns a slice of paths to the files of this input. 77 func (label SubrepoFileLabel) Paths(graph *BuildGraph) []string { 78 return []string{path.Join(label.Package, label.File)} 79 } 80 81 // FullPaths is like Paths but includes the leading plz-out/gen directory. 82 func (label SubrepoFileLabel) FullPaths(graph *BuildGraph) []string { 83 return []string{path.Join(label.FullPackage, label.File)} 84 } 85 86 // LocalPaths returns paths within the local package 87 func (label SubrepoFileLabel) LocalPaths(graph *BuildGraph) []string { 88 return []string{label.File} 89 } 90 91 // Label returns the build rule associated with this input. For a SubrepoFileLabel it's always nil. 92 func (label SubrepoFileLabel) Label() *BuildLabel { 93 return nil 94 } 95 96 func (label SubrepoFileLabel) nonOutputLabel() *BuildLabel { 97 return nil 98 } 99 100 // String returns a string representation of this input. 101 func (label SubrepoFileLabel) String() string { 102 return label.File 103 } 104 105 // SystemFileLabel represents an absolute system dependency, which is not managed by the build system. 106 type SystemFileLabel struct { 107 Path string 108 } 109 110 // Paths returns a slice of paths to the files of this input. 111 func (label SystemFileLabel) Paths(graph *BuildGraph) []string { 112 return label.FullPaths(graph) 113 } 114 115 // FullPaths is like Paths but includes the leading plz-out/gen directory. 116 func (label SystemFileLabel) FullPaths(graph *BuildGraph) []string { 117 return []string{ExpandHomePath(label.Path)} 118 } 119 120 // LocalPaths returns paths within the local package 121 func (label SystemFileLabel) LocalPaths(graph *BuildGraph) []string { 122 return label.FullPaths(graph) 123 } 124 125 // Label returns the build rule associated with this input. For a SystemFileLabel it's always nil. 126 func (label SystemFileLabel) Label() *BuildLabel { 127 return nil 128 } 129 130 func (label SystemFileLabel) nonOutputLabel() *BuildLabel { 131 return nil 132 } 133 134 // String returns a string representation of this input. 135 func (label SystemFileLabel) String() string { 136 return label.Path 137 } 138 139 // SystemPathLabel represents system dependency somewhere on PATH, which is not managed by the build system. 140 type SystemPathLabel struct { 141 Name string 142 Path []string 143 } 144 145 // Paths returns a slice of paths to the files of this input. 146 func (label SystemPathLabel) Paths(graph *BuildGraph) []string { 147 return label.FullPaths(graph) 148 } 149 150 // FullPaths is like Paths but includes the leading plz-out/gen directory. 151 func (label SystemPathLabel) FullPaths(graph *BuildGraph) []string { 152 // non-specified paths like "bash" are turned into absolute ones based on plz's PATH. 153 // awkwardly this means we can't use the builtin exec.LookPath because the current 154 // environment variable isn't necessarily the same as what's in our config. 155 tool, err := LookPath(label.Name, label.Path) 156 if err != nil { 157 // This is a bit awkward, we can't signal an error here sensibly. 158 panic(err) 159 } 160 return []string{tool} 161 } 162 163 // LocalPaths returns paths within the local package 164 func (label SystemPathLabel) LocalPaths(graph *BuildGraph) []string { 165 return label.FullPaths(graph) 166 } 167 168 // Label returns the build rule associated with this input. For a SystemPathLabel it's always nil. 169 func (label SystemPathLabel) Label() *BuildLabel { 170 return nil 171 } 172 173 func (label SystemPathLabel) nonOutputLabel() *BuildLabel { 174 return nil 175 } 176 177 // String returns a string representation of this input. 178 func (label SystemPathLabel) String() string { 179 return label.Name 180 } 181 182 // NamedOutputLabel represents a reference to a subset of named outputs from a rule. 183 // The rule must have declared those as a named group. 184 type NamedOutputLabel struct { 185 BuildLabel 186 Output string 187 } 188 189 // Paths returns a slice of paths to the files of this input. 190 func (label NamedOutputLabel) Paths(graph *BuildGraph) []string { 191 return addPathPrefix(graph.TargetOrDie(label.BuildLabel).NamedOutputs(label.Output), label.PackageName) 192 } 193 194 // FullPaths is like Paths but includes the leading plz-out/gen directory. 195 func (label NamedOutputLabel) FullPaths(graph *BuildGraph) []string { 196 target := graph.TargetOrDie(label.BuildLabel) 197 return addPathPrefix(target.NamedOutputs(label.Output), target.OutDir()) 198 } 199 200 // LocalPaths returns paths within the local package 201 func (label NamedOutputLabel) LocalPaths(graph *BuildGraph) []string { 202 return graph.TargetOrDie(label.BuildLabel).NamedOutputs(label.Output) 203 } 204 205 // Label returns the build rule associated with this input. For a NamedOutputLabel it's always non-nil. 206 func (label NamedOutputLabel) Label() *BuildLabel { 207 return &label.BuildLabel 208 } 209 210 func (label NamedOutputLabel) nonOutputLabel() *BuildLabel { 211 return nil 212 } 213 214 // String returns a string representation of this input. 215 func (label NamedOutputLabel) String() string { 216 return label.BuildLabel.String() + "|" + label.Output 217 } 218 219 // MustParseNamedOutputLabel attempts to parse a build output label. It's allowed to just be 220 // a normal build label as well. 221 // The syntax is an extension of normal build labels: //package:target|output 222 // If the label refers to a subrepo then that's returned separately. 223 func MustParseNamedOutputLabel(target string, pkg *Package) (BuildInput, string) { 224 if index := strings.IndexRune(target, '|'); index != -1 && index != len(target)-1 { 225 label, subrepo := ParseBuildLabelSubrepo(target[:index], pkg) 226 return NamedOutputLabel{BuildLabel: label.ForPackage(pkg), Output: target[index+1:]}, subrepo 227 } 228 label, subrepo := ParseBuildLabelSubrepo(target, pkg) 229 return label.ForPackage(pkg), subrepo 230 } 231 232 // A URLLabel represents a remote input that's defined by a URL. 233 type URLLabel string 234 235 // Paths returns an empty slice always (since there are no real source paths) 236 func (label URLLabel) Paths(graph *BuildGraph) []string { 237 return nil 238 } 239 240 // FullPaths returns an empty slice always (since there are no real source paths) 241 func (label URLLabel) FullPaths(graph *BuildGraph) []string { 242 return nil 243 } 244 245 // LocalPaths returns an empty slice always (since there are no real source paths) 246 func (label URLLabel) LocalPaths(graph *BuildGraph) []string { 247 return nil 248 } 249 250 // Label returns the build rule associated with this input. For a URLLabel it's always nil. 251 func (label URLLabel) Label() *BuildLabel { 252 return nil 253 } 254 255 func (label URLLabel) nonOutputLabel() *BuildLabel { 256 return nil 257 } 258 259 // String returns a string representation of this input. 260 func (label URLLabel) String() string { 261 return string(label) 262 }