Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
152 commits
Select commit Hold shift + click to select a range
8d0ecc4
Package level metadata that includes a mapping of build statements to…
Mar 27, 2026
c91668c
export using BuildFileMetadata logic
Mar 27, 2026
1276403
register caller scope for callstack-like traversal
Apr 7, 2026
836fff5
bufio writer for build statements
Apr 7, 2026
a505981
rewrite export logic into explicit flow
Apr 20, 2026
d3e67bc
export targets related to build statement
Apr 20, 2026
d09e7d0
enrich target with subincludes by looping though all scopes
Apr 20, 2026
1fb4f18
separate buildstmt register from adding target
Apr 20, 2026
b0c3c1e
select and write subincludes
Apr 20, 2026
3abc3cd
skip statement for preloaded subincludes
Apr 21, 2026
68b61e0
test: trim subincludes
Apr 21, 2026
aeb2e4a
rename file
Apr 21, 2026
1966979
use slices.collect and sort interface
Apr 21, 2026
50110d3
rewrite export with 2 concrete interfaces: default and notrim
Apr 22, 2026
65fd873
notrim: full copy BUILD file and visit sources
Apr 22, 2026
82f9587
double new lines between targets
Apr 22, 2026
00f617f
suppress diff output when enforcing repo differences
Apr 24, 2026
47ab394
export by filtering the original BUILD file
Apr 24, 2026
a2aa6a0
subincludes use label short string
Apr 24, 2026
28f61c6
Simplify package filtering method into a more explicit "switch" case
Apr 24, 2026
6616b6e
skip subrepos and internal packages when writing package file
Apr 24, 2026
f849a78
fix reusing err var resulted in failed filtering
Apr 24, 2026
7fffc39
doc strings for package metadata
Apr 26, 2026
b1fc186
export missing doc strings
Apr 26, 2026
6d572c7
test: named go_repo and change testify for slimmer UUID
Apr 29, 2026
ec888c5
export dependencies of subrepos - 13/14 tests passing
Apr 29, 2026
a4da492
test: internal repo test using temp directory to avoid stale data
Apr 29, 2026
e0fcfe2
fix: 0 label subinclude
Apr 29, 2026
7eda2cb
adjusting dependency lookup and adjacent target test to include secon…
Apr 29, 2026
9736002
test: add custom tool to native test
Apr 30, 2026
2f0a275
test: go_test export with several deps
Apr 30, 2026
88b5205
optional metadata parsing
May 1, 2026
4633d4f
test: minimal subinclude statement
May 1, 2026
2b2af8f
collect map keys on active subinclude labels
May 1, 2026
e0f2b61
non-fatal warning for missing source while exporting
May 1, 2026
4b984b6
skip internal package export
May 1, 2026
5faf4c1
move some fatal to error and continue
May 1, 2026
942c4b2
missing docstrings
May 1, 2026
215adc0
run go fmt and plz fmt
May 1, 2026
4746de6
move to error and continue for target lookup
May 1, 2026
1a758d0
rename new parser method on test files
May 1, 2026
e5ba148
use pkg.Metadata directly and remove intermediate pkg methods
May 11, 2026
31d4afe
mutex in packagemetadata
May 12, 2026
92c2e17
update stmt provider to avoid dereference
May 12, 2026
8733b00
NewPackage with variadic optional functions
May 12, 2026
488f951
infof to debugf
May 12, 2026
26d9a46
package metadata doc comments improvements
May 12, 2026
38ffa62
improve doc comments and adjust method visibility for export.go
May 12, 2026
8da1e96
hide build output when testing export
May 12, 2026
21e23c6
open and write of exported package file merged into the same method
May 12, 2026
2377776
update export_test.go with suggestions
May 12, 2026
d05a9c3
apply review suggestions to export.go
May 13, 2026
6bc28b5
rename and doc fields for scope
May 13, 2026
c1a04df
revert new line change of target
May 14, 2026
a95784c
set builtin code filename for scope for debugging
May 14, 2026
1d749b7
Rework packagemetadata to return empty slices or nil instead of error…
May 14, 2026
58e6532
linter fix imports
May 14, 2026
db93587
ensure subrepo target exists. Failing to export //... on this repo
May 14, 2026
bea7e98
go test for filtered package
May 15, 2026
2d608dd
Add doc comments for providers in asp.interpreter
May 15, 2026
4c81a60
test: function def in package file
May 15, 2026
165045d
unit testing current statement and active subincludes
May 15, 2026
beee484
remove nested maps and pointers in favor of using build labels
May 18, 2026
5ee2bcd
unexport noTrim implementation
May 18, 2026
3370418
AST based trimming (if-else and for):
May 21, 2026
029de6a
handle subinclude variables by tracking origin and used.
May 29, 2026
ac76bdd
scope metadata interface for optional metadata processing
Jun 2, 2026
fa25ce2
test: adjust interpreter tests with scope metadata and origin trackin…
Jun 3, 2026
69e310b
golint trimmer
Jun 3, 2026
0fe5d00
fix missing targets by keeping parser running and parsing inline duri…
Jun 4, 2026
6cdcebc
split export implementations into different files
Jun 5, 2026
1651a3e
fix: propagate cursor
Jun 5, 2026
fda8cd9
simplify calls to getOrParseTarget
Jun 5, 2026
fd68740
remove use of formatter and trim newlines
Jun 5, 2026
58d8936
reuse parser between build files
Jun 5, 2026
74d290a
use of baseExporter directly and interface cleanup
Jun 8, 2026
e2ef287
interpreter preloads info prevents secondary loading/subincludes
Jun 8, 2026
def5006
fix: deadlocking on closed results thread
Jun 9, 2026
8d95ab5
test: use system cache for speeding up e2e tests
Jun 9, 2026
6857d4d
add explicit targetToStmt mapping to improve CPU performance on FindS…
Jun 9, 2026
3f2427e
use cmap in package metadata, removing explicit usage of a shared mut…
Jun 9, 2026
a44e729
docs: interface implementation comment
Jun 9, 2026
56bc568
rename exporter source files
Jun 10, 2026
d11e014
apply feedback from multiple comments
Jun 10, 2026
ebe361d
local subrepos: fixes (relative filenames) and test
Jun 11, 2026
0500a75
export transitive subincludes, fixing unexported targets subincluded …
Jun 12, 2026
bb6b0e5
export gitignore
Jun 12, 2026
ee374ce
test: glob for sources
Jun 15, 2026
d87189e
Package parsing via WaitForPackage
Jun 15, 2026
97e90d7
test: move trim test files into data
Jun 15, 2026
89aca5c
test: trim subinclude in third_party/go test
Jun 16, 2026
94fd517
export label set
Jun 16, 2026
add2812
track used objects as a stack
Jun 16, 2026
a087c75
scopeMetadata: private, rename and comments
Jun 17, 2026
c459832
rename active to required subincludes
Jun 17, 2026
24035dc
imp: skip scope and package metadata tracking for external subrepos
Jun 18, 2026
41c72f9
remove doc reference to required target naming for successful export
Jun 22, 2026
d819246
Only pop symbols from stack in package scope + rework newScopeMetadat…
Jun 22, 2026
348cdc7
lazy initialize symbol origins
Jun 23, 2026
d75b5ea
Close package wait channels on error. Introduced a deadlock when Keep…
Jun 24, 2026
137f012
Support method calls as arguments by popping the symbol stack only at…
Jun 24, 2026
efcaabb
refactor: record all statements and respective origins for all statem…
Jun 24, 2026
8332c5f
Package level scope metadata; Tracking done at package level only.
Jun 25, 2026
46d8b29
Package metadata lookup table in interpreter to avoid recursive calle…
Jun 25, 2026
99f5b29
Trimmer: always keep for expression but trim stmts inside
Jun 25, 2026
fa7847f
glob statement: register files required by statements
Jun 26, 2026
3ea8dec
Checkpoint and restore symbol and file stack to support different cal…
Jun 26, 2026
54b70c6
move to BuildLabels in export and metadata to avoid pressure on GC
Jun 26, 2026
b38e018
track interpreted statements (mark as 0 targets) to correctly identif…
Jun 26, 2026
a39676f
subinclude tracking for dynamic subincludes
Jun 29, 2026
6e40952
track inner level globs.
Jun 29, 2026
beff770
feat(cmd): query print metadata - print package metadata
Jun 29, 2026
4db88e3
track inner statements (e.g. if clauses) and trim clauses based on if…
Jun 30, 2026
a935994
lint suggestions: remove hashBuildTarget and initialise labels slice …
Jun 30, 2026
376d14b
feat(cmd): metadata json formatting
Jun 30, 2026
08b8e94
progress monitor for export
Jul 1, 2026
ee07ae8
metadata: drop json printing and optional hidden targets
Jul 3, 2026
3ced65d
maintain subinclude label order
Jul 3, 2026
433333e
combined build inputs
Aug 5, 2026
4253c25
Pseudo uniform distribution
Aug 5, 2026
b7ad615
Package metadata renaming and doc comment fixes
Aug 6, 2026
e924bf4
Justify subsequent calls to RegisterStatement
Aug 6, 2026
397ed51
Address package metadata review comments: docs, zero value and sort
Aug 6, 2026
31361d7
Refactor: consolidate maps into single statement map with statement m…
Aug 6, 2026
9f5ad5e
Refactor: remove subinclude statement mapping and use isSubincludeSta…
Aug 6, 2026
2c1644c
State: test for logBuildError
Aug 7, 2026
beef2ac
export test formatting
Aug 11, 2026
30a5ee5
Fix if trim test: declared interpreted statements.
Aug 11, 2026
777b1f1
getOrParse safety timeout
Aug 11, 2026
5632e13
fix infinite counter
Aug 26, 2026
3bf3179
address query.metadata comments
Aug 26, 2026
0931003
strip symbols
Aug 26, 2026
1cbfd18
s/CleanUp/Cleanup
Aug 26, 2026
e6ff712
s/unneded/unneeded
Aug 26, 2026
ab48c30
standardise use of "unused" in tests
Aug 26, 2026
7f0bdfc
comments for interpreter.go
Aug 27, 2026
a081324
test: target variable trimming
Aug 28, 2026
229ea4f
revert: track preloaded in interpreter
Aug 28, 2026
10b3f05
fix: add new lines at the end of files
Aug 28, 2026
23b4f99
revert one time variable
Aug 28, 2026
7ba7f18
test: move complex go test to e2e
Aug 28, 2026
585d95a
lint: plz fmt
Aug 28, 2026
d32f1e6
fix: wrong reference to unused lib in e2e test
Aug 28, 2026
90e7436
refactor/revert: resolve package targets upfront instead of keeping p…
Aug 28, 2026
7552be7
refactor: decouple buildStatement from core by implementing interface…
Aug 28, 2026
ef3bd43
go lint
Aug 28, 2026
9b8ca27
unexport labelset
Sep 2, 2026
4f7c136
refactor: use RWmutex instead of cmaps for package metadata
Sep 2, 2026
0f073e4
refactor: introduce struct TrackedStatement instead of sorted slices …
Sep 2, 2026
0ae4949
test: trimming of variables that include targets
Sep 3, 2026
2c4ae9f
test: refactor build error test for better consistency
Sep 3, 2026
ff407e4
refactor: subincludeArgs as iterator
Sep 3, 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
14 changes: 5 additions & 9 deletions docs/commands.html
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,11 @@ <h2 id="query" class="title-2">
<code class="code">whatoutputs</code>: Prints out target(s) responsible for outputting provided file(s)
</span>
</li>
<li>
<span>
<code class="code">metadata</code>: Prints out a structured, tree-like visualization of parsed build statement metadata (required subincludes, files, and generated targets) of a package.
</span>
</li>
</ul>

<p>
Expand Down Expand Up @@ -1032,15 +1037,6 @@ <h3 class="mt1 f6 lh-title">
</h3>
<p>Disables trimming unnecessary targets from exported packages. Normally targets in exported packages that
aren't dependencies of the originally exported targets are removed.</p>
<p>
This trimming syntax based, so doesn't always work depending on how the build definition is authored. Passing
this flag will disable this feature, avoiding cases where these rules will be erroneously trimmed.
</p>
<p>
To make sure a rule works without this flag, the rule must follow the naming convention, whereby children of
<code class="code">:name</code> follow the format <code class="code">:_name#{some-tag}</code>. This is the
format <code class="code">tag(name, tag)</code> would produce.
</p>
</div>
</li>
</ul>
Expand Down
15 changes: 11 additions & 4 deletions src/cli/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"sync"

cli "github.com/peterebden/go-cli-init/v5/logging"
"github.com/peterebden/go-deferred-regex"
deferredregex "github.com/peterebden/go-deferred-regex"
"golang.org/x/term"
"gopkg.in/op/go-logging.v1"

Expand Down Expand Up @@ -184,9 +184,6 @@ func (backend *LogBackend) calcOutput() []string {
ret = append(ret, new...)
}
}
if len(ret) > 0 {
ret = append(ret, "Messages:")
}
return reverse(ret)
}

Expand Down Expand Up @@ -248,6 +245,16 @@ func (backend *LogBackend) Output() []string {
return backend.output[:]
}

// FlushOutput returns the current set of preformatted log messages and clears them.
func (backend *LogBackend) FlushOutput() []string {
backend.mutex.Lock()
defer backend.mutex.Unlock()
ret := backend.output[:]
backend.output = nil
backend.logMessages.Init()
return ret
}

// Wraps a string across multiple lines. Returned slice is reversed.
func (backend *LogBackend) lineWrap(msg string) []string {
lines := strings.Split(msg, "\n")
Expand Down
15 changes: 14 additions & 1 deletion src/core/build_label.go
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,8 @@ func subrepoLabel(subrepoName, arch string) BuildLabel {
return BuildLabel{Name: subrepoName, Subrepo: arch}
}

func hashBuildLabel(l BuildLabel) uint64 {
// HashBuildLabel calculates an hash of Build Label, suitable to use for map indexing.
func HashBuildLabel(l BuildLabel) uint64 {
return cmap.XXHashes(l.Subrepo, l.PackageName, l.Name)
}

Expand Down Expand Up @@ -622,3 +623,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
}
38 changes: 29 additions & 9 deletions src/core/build_target.go
Original file line number Diff line number Diff line change
Expand Up @@ -1473,7 +1473,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 combinedBuildInputs(target.Test.tools, target.Test.namedTools)
}

// NamedTestTools returns all named test tools
Expand All @@ -1489,7 +1489,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 combinedBuildInputs(target.Debug.tools, target.Debug.namedTools)
}

// AddDatum adds a new item of data to the target.
Expand Down Expand Up @@ -1644,21 +1644,41 @@ 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 combinedBuildInputs(target.Sources, target.NamedSources)
}

func (target *BuildTarget) allBuildInputs(unnamed []BuildInput, named map[string][]BuildInput) []BuildInput {
ret := unnamed
// combinedBuildInputs combines the unnamed inputs and the values of named inputs into one slice.
func combinedBuildInputs(unnamed []BuildInput, named map[string][]BuildInput) []BuildInput {
keys := make([]string, 0, len(named))
for k := range named {
size := 0
for k, vals := range named {
keys = append(keys, k)
size += len(vals)
}
sort.Strings(keys)
Comment thread
DuBento marked this conversation as resolved.

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

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

// AllDebugData returns all the data for debugging this rule.
Expand All @@ -1721,7 +1741,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 combinedBuildInputs(target.Debug.data, target.Debug.namedData)
}

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

// ToolNames returns an ordered list of tool names.
Expand Down
21 changes: 5 additions & 16 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 @@ -35,7 +24,7 @@ type BuildGraph struct {
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.
// 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 @@ -165,7 +154,7 @@ func (graph *BuildGraph) PackageMap() map[string]*Package {
// NewGraph constructs and returns a new BuildGraph.
func NewGraph() *BuildGraph {
g := &BuildGraph{
targets: cmap.New[BuildLabel, *BuildTarget](cmap.DefaultShardCount, hashBuildLabel),
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{},
Expand Down Expand Up @@ -197,10 +186,10 @@ func (graph *BuildGraph) TransitiveSubincludes(l BuildLabel) []BuildLabel {
}

func (graph *BuildGraph) findTransitiveSubincludes(label BuildLabel, includes labelSet) {
if includes.contains(label) {
if includes.Contains(label) {
return
}
includes.add(label)
includes.Add(label)
for l := range graph.subincludeSubincludes[label] {
graph.findTransitiveSubincludes(l, includes)
}
Expand All @@ -215,5 +204,5 @@ func (graph *BuildGraph) RegisterTransitiveSubinclude(from, to BuildLabel) {
incs = labelSet{}
graph.subincludeSubincludes[from] = incs
}
incs.add(to)
incs.Add(to)
}
45 changes: 34 additions & 11 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 @@ -109,7 +132,7 @@ func (pkg *Package) AllSubincludes(graph *BuildGraph) []BuildLabel {

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

Expand Down
Loading
Loading