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  }