Pregenerate: add a concept of tasks that can be waited upon. Not yet 100% sure if all tasks should be made waitable or not - we're only gonna need it on the Perlasm tasks (and there only for the Linux ones). The goal is to use this for symbol prefixing the asm symbols: one task depends on all the Perlasm outputs, and will then read those as well as any non-Perlasm asm files, and generate the list of asm symbols for prefixing. By making this a task, it can run in parallel with other things, including the upcoming Clang AST based public symbol extraction. Bug: 42220000 Change-Id: I8ce81394822f38dd3b3114ba99626f616a6a6964 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/87027 Reviewed-by: Xiangfei Ding <xfding@google.com> Commit-Queue: Rudolf Polzer <rpolzer@google.com>
diff --git a/util/pregenerate/build.go b/util/pregenerate/build.go index 743b84b..6bae080 100644 --- a/util/pregenerate/build.go +++ b/util/pregenerate/build.go
@@ -105,7 +105,7 @@ } dst = path.Join("gen", name, dst+fileSuffix) args = append(slices.Clone(args), p.Args...) - addTask(list, &PerlasmTask{Src: p.Src, Dst: dst, Args: args}) + addTask(list, WrapWaitable(&PerlasmTask{Src: p.Src, Dst: dst, Args: args})) } for _, p := range in.PerlasmAarch64 {
diff --git a/util/pregenerate/task.go b/util/pregenerate/task.go index 4d170a0..3a565e4 100644 --- a/util/pregenerate/task.go +++ b/util/pregenerate/task.go
@@ -16,6 +16,7 @@ import ( "bytes" + "fmt" "os" "os/exec" "path" @@ -33,14 +34,54 @@ Run() ([]byte, error) } +type WaitableTask interface { + Task + + // Wait waits for the task to finish, and returns its status. + Wait() error +} + +// WaitableTaskImpl is an implementation of a waitable task. +type WaitableTaskImpl struct { + Task + FinishedC chan struct{} + Err error +} + +func WrapWaitable(t Task) WaitableTask { + return &WaitableTaskImpl{Task: t, FinishedC: make(chan struct{})} +} + +// Run performs the task, taking care of infrastructure so it can be waited on. +func (t *WaitableTaskImpl) Run() (out []byte, err error) { + defer func() { + if p := recover(); p != nil { + err = fmt.Errorf("panic caught: %v", p) + } + t.Err = err + close(t.FinishedC) + }() + return t.Task.Run() +} + +// Wait waits for the task to finish, and returns its status. +func (t *WaitableTaskImpl) Wait() error { + <-t.FinishedC + return t.Err +} + type SimpleTask struct { Dst string RunFunc func() ([]byte, error) } -func (t *SimpleTask) Destination() string { return t.Dst } +// Destination returns where this task will write to. +func (t *SimpleTask) Destination() string { return t.Dst } + +// Run performs the task. func (t *SimpleTask) Run() ([]byte, error) { return t.RunFunc() } +// NewSimpleTask creates a new task based on a lambda for what it does. func NewSimpleTask(dst string, runFunc func() ([]byte, error)) *SimpleTask { return &SimpleTask{Dst: dst, RunFunc: runFunc} }