Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
0ef91bc
Package level metadata that includes a mapping of build statements to…
Mar 27, 2026
63f1b0d
export using BuildFileMetadata logic
Mar 27, 2026
419bd56
register caller scope for callstack-like traversal
Apr 7, 2026
8e1bd00
bufio writer for build statements
Apr 7, 2026
258b170
rewrite export logic into explicit flow
Apr 20, 2026
4110735
export targets related to build statement
Apr 20, 2026
a4252c9
enrich target with subincludes by looping though all scopes
Apr 20, 2026
82f117f
separate buildstmt register from adding target
Apr 20, 2026
eb657de
select and write subincludes
Apr 20, 2026
6535794
skip statement for preloaded subincludes
Apr 21, 2026
8e6c9c0
test: trim subincludes
Apr 21, 2026
9f0b4fe
rename file
Apr 21, 2026
0e597c6
use slices.collect and sort interface
Apr 21, 2026
de76e2c
rewrite export with 2 concrete interfaces: default and notrim
Apr 22, 2026
03ed361
notrim: full copy BUILD file and visit sources
Apr 22, 2026
717aba1
double new lines between targets
Apr 22, 2026
94160bf
suppress diff output when enforcing repo differences
Apr 24, 2026
582319e
export by filtering the original BUILD file
Apr 24, 2026
e6a5293
subincludes use label short string
Apr 24, 2026
ea329c3
Simplify package filtering method into a more explicit "switch" case
Apr 24, 2026
1a47c22
skip subrepos and internal packages when writing package file
Apr 24, 2026
a35119a
fix reusing err var resulted in failed filtering
Apr 24, 2026
9c1522c
doc strings for package metadata
Apr 26, 2026
9395a59
export missing doc strings
Apr 26, 2026
3c3d3d0
test: named go_repo and change testify for slimmer UUID
Apr 29, 2026
13e95cb
export dependencies of subrepos - 13/14 tests passing
Apr 29, 2026
28b5441
test: internal repo test using temp directory to avoid stale data
Apr 29, 2026
781af3a
fix: 0 label subinclude
Apr 29, 2026
2f8355c
adjusting dependency lookup and adjacent target test to include secon…
Apr 29, 2026
3e89c85
test: add custom tool to native test
Apr 30, 2026
9c5af3e
test: go_test export with several deps
Apr 30, 2026
922da6f
optional metadata parsing
May 1, 2026
5aeb360
test: minimal subinclude statement
May 1, 2026
517486a
collect map keys on active subinclude labels
May 1, 2026
f8f8e3f
non-fatal warning for missing source while exporting
May 1, 2026
8aa98e3
skip internal package export
May 1, 2026
5fa64f4
move some fatal to error and continue
May 1, 2026
e60dbb6
missing docstrings
May 1, 2026
c7409ab
run go fmt and plz fmt
May 1, 2026
be87020
move to error and continue for target lookup
May 1, 2026
6f73f78
rename new parser method on test files
May 1, 2026
762c016
use pkg.Metadata directly and remove intermediate pkg methods
May 11, 2026
406f95a
mutex in packagemetadata
May 12, 2026
b86ff9f
update stmt provider to avoid dereference
May 12, 2026
c7cd118
NewPackage with variadic optional functions
May 12, 2026
faf8c33
infof to debugf
May 12, 2026
dd8cfca
package metadata doc comments improvements
May 12, 2026
084f233
improve doc comments and adjust method visibility for export.go
May 12, 2026
bf0f734
hide build output when testing export
May 12, 2026
33d2bc2
open and write of exported package file merged into the same method
May 12, 2026
54f577c
update export_test.go with suggestions
May 12, 2026
ae5f520
apply review suggestions to export.go
May 13, 2026
5f0e549
rename and doc fields for scope
May 13, 2026
e59ab5b
revert new line change of target
May 14, 2026
917fe61
set builtin code filename for scope for debugging
May 14, 2026
b012ab8
Rework packagemetadata to return empty slices or nil instead of error…
May 14, 2026
2edfee0
linter fix imports
May 14, 2026
f59b5d0
ensure subrepo target exists. Failing to export //... on this repo
May 14, 2026
790a437
go test for filtered package
May 15, 2026
f589998
Add doc comments for providers in asp.interpreter
May 15, 2026
75521e2
test: function def in package file
May 15, 2026
2e2edde
unit testing current statement and active subincludes
May 15, 2026
0e74e53
remove nested maps and pointers in favor of using build labels
May 18, 2026
ef76bca
unexport noTrim implementation
May 18, 2026
8607a7b
AST based trimming (if-else and for):
May 21, 2026
b5bca70
handle subinclude variables by tracking origin and used.
May 29, 2026
bf9851d
scope metadata interface for optional metadata processing
Jun 2, 2026
34f75f8
test: adjust interpreter tests with scope metadata and origin trackin…
Jun 3, 2026
f0d26ca
golint trimmer
Jun 3, 2026
f9b4b80
fix missing targets by keeping parser running and parsing inline duri…
Jun 4, 2026
06eccf0
split export implementations into different files
Jun 5, 2026
66eef42
fix: propagate cursor
Jun 5, 2026
45e6cd8
simplify calls to getOrParseTarget
Jun 5, 2026
6bf0051
remove use of formatter and trim newlines
Jun 5, 2026
3f36ad4
reuse parser between build files
Jun 5, 2026
b76c2e2
use of baseExporter directly and interface cleanup
Jun 8, 2026
51814bc
interpreter preloads info prevents secondary loading/subincludes
Jun 8, 2026
58711e9
fix: deadlocking on closed results thread
Jun 9, 2026
0e05f0f
test: use system cache for speeding up e2e tests
Jun 9, 2026
8de64e3
add explicit targetToStmt mapping to improve CPU performance on FindS…
Jun 9, 2026
5ca4401
use cmap in package metadata, removing explicit usage of a shared mut…
Jun 9, 2026
6b9f0c4
docs: interface implementation comment
Jun 9, 2026
299b259
rename exporter source files
Jun 10, 2026
21f3775
apply feedback from multiple comments
Jun 10, 2026
681a664
local subrepos: fixes (relative filenames) and test
Jun 11, 2026
1bea58f
export transitive subincludes, fixing unexported targets subincluded …
Jun 12, 2026
acb81e6
export gitignore
Jun 12, 2026
f1a0abe
test: glob for sources
Jun 15, 2026
5d3073b
Package parsing via WaitForPackage
Jun 15, 2026
c38eba6
test: move trim test files into data
Jun 15, 2026
c387e50
test: trim subinclude in third_party/go test
Jun 16, 2026
2446dad
export label set
Jun 16, 2026
7152109
track used objects as a stack
Jun 16, 2026
50a8240
scopeMetadata: private, rename and comments
Jun 17, 2026
51cbb35
rename active to required subincludes
Jun 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/BUILD.plz
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ go_binary(
"github.com/thought-machine/please/src/version.PleaseVersion": VERSION,
},
visibility = ["PUBLIC"],
strip = False,
deps = [
"///third_party/go/github.com_thought-machine_go-flags//:go-flags",
"///third_party/go/go.uber.org_automaxprocs//maxprocs",
"//src/audit",
"//src/assets",
"//src/audit",
"//src/build",
"//src/cache",
"//src/clean",
Expand All @@ -29,7 +30,6 @@ go_binary(
"//src/help",
"//src/metrics",
"//src/output",
"//src/parse",
"//src/plz",
"//src/plzinit",
"//src/process",
Expand Down
12 changes: 12 additions & 0 deletions src/core/build_label.go
Original file line number Diff line number Diff line change
Expand Up @@ -622,3 +622,15 @@ func (slice BuildLabels) String() string {
}
return strings.Join(s, ", ")
}

// LabelSet defines a set of labels implemented using a map.
type LabelSet map[BuildLabel]struct{}

func (ls LabelSet) Add(l BuildLabel) {
ls[l] = struct{}{}
}

func (ls LabelSet) Contains(l BuildLabel) bool {
_, ok := ls[l]
return ok
}
41 changes: 32 additions & 9 deletions src/core/build_target.go
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,11 @@ func (target *BuildTarget) String() string {
return target.Label.String()
}

// hashBuildTarget returns a mostly unique hash of a BuildTarget by relying on the BuildLabel hash.
func hashBuildTarget(target *BuildTarget) uint64 {
return hashBuildLabel(target.Label)
}

// TmpDir returns the temporary working directory for this target, eg.
// //mickey/donald:goofy -> plz-out/tmp/mickey/donald/goofy._build
// Note the extra subdirectory to keep rules separate from one another, and the .build suffix
Expand Down Expand Up @@ -1471,7 +1476,7 @@ func (target *BuildTarget) AllTestTools() []BuildInput {
if target.Test.namedTools == nil {
return target.Test.tools
}
return target.allBuildInputs(target.Test.tools, target.Test.namedTools)
return target.selectBuildInputs(target.Test.tools, target.Test.namedTools)
}

// NamedTestTools returns all named test tools
Expand All @@ -1487,7 +1492,7 @@ func (target *BuildTarget) AllDebugTools() []BuildInput {
if target.Debug.namedTools == nil {
return target.Debug.tools
}
return target.allBuildInputs(target.Debug.tools, target.Debug.namedTools)
return target.selectBuildInputs(target.Debug.tools, target.Debug.namedTools)
}

// AddDatum adds a new item of data to the target.
Expand Down Expand Up @@ -1642,21 +1647,39 @@ func (target *BuildTarget) getCommand(state *BuildState, commands map[string]str
return highestCommand
}

// AllBuildInputs returns all the inputs for this target.
func (target *BuildTarget) AllBuildInputs() []BuildInput {
srcs := target.AllSources()
data := target.AllData()
tools := target.AllTools()

size := len(srcs) + len(data) + len(tools)
inputs := make([]BuildInput, 0, size)
inputs = append(inputs, srcs...)
inputs = append(inputs, data...)
inputs = append(inputs, tools...)
return inputs
}

// AllSources returns all the sources of this rule.
func (target *BuildTarget) AllSources() []BuildInput {
if target.NamedSources == nil {
return target.Sources
}
return target.allBuildInputs(target.Sources, target.NamedSources)
return target.selectBuildInputs(target.Sources, target.NamedSources)
}

func (target *BuildTarget) allBuildInputs(unnamed []BuildInput, named map[string][]BuildInput) []BuildInput {
ret := unnamed
func (target *BuildTarget) selectBuildInputs(unnamed []BuildInput, named map[string][]BuildInput) []BuildInput {
keys := make([]string, 0, len(named))
for k := range named {
size := len(unnamed)
for k, vals := range named {
keys = append(keys, k)
size += len(vals)
}
sort.Strings(keys)

ret := make([]BuildInput, 0, size)
ret = append(ret, unnamed...)
for _, k := range keys {
ret = append(ret, named[k]...)
}
Expand Down Expand Up @@ -1708,7 +1731,7 @@ func (target *BuildTarget) AllData() []BuildInput {
return target.Data
}

return target.allBuildInputs(target.Data, target.NamedData)
return target.selectBuildInputs(target.Data, target.NamedData)
}

// AllDebugData returns all the data for debugging this rule.
Expand All @@ -1719,7 +1742,7 @@ func (target *BuildTarget) AllDebugData() []BuildInput {
if target.Debug.namedData == nil {
return target.Debug.data
}
return target.allBuildInputs(target.Debug.data, target.Debug.namedData)
return target.selectBuildInputs(target.Debug.data, target.Debug.namedData)
}

// DebugData returns unnamed data for debugging this rule.
Expand All @@ -1743,7 +1766,7 @@ func (target *BuildTarget) AllTools() []BuildInput {
if target.namedTools == nil {
return target.Tools
}
return target.allBuildInputs(target.Tools, target.namedTools)
return target.selectBuildInputs(target.Tools, target.namedTools)
}

// ToolNames returns an ordered list of tool names.
Expand Down
29 changes: 9 additions & 20 deletions src/core/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,6 @@ import (
"github.com/thought-machine/please/src/cmap"
)

type labelSet map[BuildLabel]struct{}

func (ls labelSet) add(l BuildLabel) {
ls[l] = struct{}{}
}

func (ls labelSet) contains(l BuildLabel) bool {
_, ok := ls[l]
return ok
}

// A BuildGraph contains all the loaded targets and packages and maintains their
// relationships, especially reverse dependencies which are calculated here.
type BuildGraph struct {
Expand All @@ -34,8 +23,8 @@ type BuildGraph struct {
// Registered subrepos, as a map of their name to their root.
subrepos *cmap.Map[string, *Subrepo]
// Subincludes that are subincluded by other subincludes
subincludeSubincludes map[BuildLabel]labelSet
// Use a mutex as a labelSet isn't atomic. We need to guard against inserting as well as mutating the value.
subincludeSubincludes map[BuildLabel]LabelSet
// Use a mutex as a LabelSet isn't atomic. We need to guard against inserting as well as mutating the value.
subincMux sync.Mutex
}

Expand Down Expand Up @@ -168,7 +157,7 @@ func NewGraph() *BuildGraph {
targets: cmap.New[BuildLabel, *BuildTarget](cmap.DefaultShardCount, hashBuildLabel),
packages: cmap.New[packageKey, *Package](cmap.DefaultShardCount, hashPackageKey),
subrepos: cmap.New[string, *Subrepo](cmap.SmallShardCount, cmap.XXHash),
subincludeSubincludes: map[BuildLabel]labelSet{},
subincludeSubincludes: map[BuildLabel]LabelSet{},
}
return g
}
Expand All @@ -188,19 +177,19 @@ func (graph *BuildGraph) TransitiveSubincludes(l BuildLabel) []BuildLabel {
graph.subincMux.Lock()
defer graph.subincMux.Unlock()

incs := labelSet{}
incs := LabelSet{}
graph.findTransitiveSubincludes(l, incs)

ls := slices.Collect(maps.Keys(incs))
sort.Sort(BuildLabels(ls))
return ls
}

func (graph *BuildGraph) findTransitiveSubincludes(label BuildLabel, includes labelSet) {
if includes.contains(label) {
func (graph *BuildGraph) findTransitiveSubincludes(label BuildLabel, includes LabelSet) {
if includes.Contains(label) {
return
}
includes.add(label)
includes.Add(label)
for l := range graph.subincludeSubincludes[label] {
graph.findTransitiveSubincludes(l, includes)
}
Expand All @@ -212,8 +201,8 @@ func (graph *BuildGraph) RegisterTransitiveSubinclude(from, to BuildLabel) {

incs, ok := graph.subincludeSubincludes[from]
if !ok {
incs = labelSet{}
incs = LabelSet{}
graph.subincludeSubincludes[from] = incs
}
incs.add(to)
incs.Add(to)
}
47 changes: 35 additions & 12 deletions src/core/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,46 @@ type Package struct {
targets map[string]*BuildTarget
// Set of output files from rules.
Outputs map[string]*BuildTarget
// Includes metadata from parsing the package BUILD file.
Metadata PackageMetadata
// Protects access to above
mutex sync.RWMutex
}

// NewPackage constructs a new package with the given name.
func NewPackage(name string) *Package {
return NewPackageSubrepo(name, "")
// PackageOptions is a functional option type for configuring a new Package.
type PackageOptions func(*Package)

// WithPackageSubrepo returns a PackageOptions that sets the subrepo name for a new Package.
func WithPackageSubrepo(name string) PackageOptions {
return func(p *Package) {
p.SubrepoName = name
}
}

// NewPackageSubrepo constructs a new package with the given name and subrepo.
func NewPackageSubrepo(name, subrepo string) *Package {
return &Package{
Name: name,
SubrepoName: subrepo,
targets: map[string]*BuildTarget{},
Outputs: map[string]*BuildTarget{},
// WithPackageMetadata returns a PackageOptions that enables tracking of
// metadata (like statement positions and subinclude mappings) for the Package.
// This is required for features like 'plz export'.
func WithPackageMetadata() PackageOptions {
return func(p *Package) {
p.Metadata = newPackageMetadata()
}
Comment thread
DuBento marked this conversation as resolved.
}

// NewPackage constructs a new package with the given name, and enables additional features
// given the PackageOptions provided.
func NewPackage(name string, options ...PackageOptions) *Package {
pkg := &Package{
Name: name,
targets: map[string]*BuildTarget{},
Outputs: map[string]*BuildTarget{},
// Defaults to noop to avoid storing metadata for most operations
Metadata: newNoopPackageMetadata(),
}

for _, option := range options {
option(pkg)
}
return pkg
}

// Target returns the target with the given name, or nil if this package doesn't have one.
Expand Down Expand Up @@ -105,11 +128,11 @@ func (pkg *Package) RegisterSubinclude(label BuildLabel) {

// AllSubincludes returns the full set of subincludes needed for this package, including transitive subincludes
func (pkg *Package) AllSubincludes(graph *BuildGraph) []BuildLabel {
includes := make(labelSet, len(pkg.Subincludes))
includes := make(LabelSet, len(pkg.Subincludes))

for _, s := range pkg.Subincludes {
for _, inc := range append(graph.TransitiveSubincludes(s), s) {
includes.add(inc)
includes.Add(inc)
}
}

Expand Down
Loading
Loading