forked from rosa/hakurei
internal/rosa: read-only access to built-ins
This removes potential footguns caused by mutable builtins without requiring unnecessary clones. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -25,7 +25,7 @@ const (
|
||||
loadFlagE = `"-l$` + pkg.EnvLoad + `"`
|
||||
)
|
||||
|
||||
// newTar wraps [pkg.NewHTTPGetTar] with a simpler function signature.
|
||||
// newTar is a helper for downloading compressed tarballs.
|
||||
func newTar(url, checksum string, compress uint32) pkg.Artifact {
|
||||
return pkg.NewTar(
|
||||
pkg.NewDecompress(
|
||||
@@ -114,3 +114,43 @@ func skipGNUTests(tests ...int64) string {
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// builtin contains native and embedded [Artifact] registrations.
|
||||
var builtin S
|
||||
|
||||
// New returns the address of a newly populated [S] derived from built-ins.
|
||||
func New() *S { return builtin.Clone() }
|
||||
|
||||
// Collect returns all built-in non-excluded [ArtifactH].
|
||||
func Collect() (handles P) { return builtin.Collect() }
|
||||
|
||||
// CollectAll returns all built-in [ArtifactH].
|
||||
func CollectAll() (handles P) { return builtin.CollectAll() }
|
||||
|
||||
// builtinStd is the [Std] toolchain stage on builtin.
|
||||
var builtinStd = builtin.Std()
|
||||
|
||||
// Load satisfies an [Artifact] referred to by an [ArtifactH].
|
||||
func Load(handle ArtifactH) (*Metadata, pkg.Artifact) {
|
||||
return builtinStd.Load(handle)
|
||||
}
|
||||
|
||||
// LoadAt satisfies an [Artifact] referred to by an [ArtifactH] at the
|
||||
// specified stage.
|
||||
func LoadAt(stage Stage, handle ArtifactH) (*Metadata, pkg.Artifact) {
|
||||
return builtin.New(stage).Load(handle)
|
||||
}
|
||||
|
||||
// MustLoad is like Load, but panics if the named [Artifact] is not registered.
|
||||
func MustLoad(handle ArtifactH) (*Metadata, pkg.Artifact) {
|
||||
return builtinStd.MustLoad(handle)
|
||||
}
|
||||
|
||||
// MustLoadAt is like LoadAt, but panics if the named [Artifact] is not
|
||||
// registered.
|
||||
func MustLoadAt(stage Stage, handle ArtifactH) (*Metadata, pkg.Artifact) {
|
||||
return builtin.New(stage).MustLoad(handle)
|
||||
}
|
||||
|
||||
// HasStageEarly returns whether a stage0 distribution is available.
|
||||
func HasStageEarly() (ok bool) { return builtin.HasStageEarly() }
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ func init() {
|
||||
Version: version,
|
||||
Exclude: true,
|
||||
}
|
||||
native.MustRegister(meta.Name, func(t Toolchain) (*Metadata, pkg.Artifact) {
|
||||
builtin.MustRegister(meta.Name, func(t Toolchain) (*Metadata, pkg.Artifact) {
|
||||
var (
|
||||
bootstrapEnv []string
|
||||
bootstrapEarly []pkg.Artifact
|
||||
|
||||
@@ -48,7 +48,7 @@ func litArgs(verbose bool, skipChecks ...string) string {
|
||||
}
|
||||
|
||||
func init() {
|
||||
native.MustRegister("llvm", func(t Toolchain) (*Metadata, pkg.Artifact) {
|
||||
builtin.MustRegister("llvm", func(t Toolchain) (*Metadata, pkg.Artifact) {
|
||||
meta := Metadata{
|
||||
Name: "llvm",
|
||||
Description: "a collection of modular and reusable compiler and toolchain technologies",
|
||||
@@ -168,7 +168,7 @@ func init() {
|
||||
)
|
||||
}
|
||||
|
||||
if t.opts&OptLLVMNoLTO == 0 {
|
||||
if t.opts&OptToolchainLTO != 0 {
|
||||
cache = append(cache, []KV{
|
||||
// very expensive
|
||||
{"LLVM_ENABLE_LTO", "Thin"},
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
func TestLLVMInputs(t *testing.T) {
|
||||
const wantInputCount = 470
|
||||
|
||||
_, llvm := rosa.Native().Std().MustLoad(rosa.H("llvm"))
|
||||
_, llvm := rosa.MustLoad(rosa.H("llvm"))
|
||||
var n int
|
||||
for range pkg.Inputs(llvm) {
|
||||
n++
|
||||
|
||||
@@ -42,8 +42,8 @@ func WriteReport(msg message.Msg, w io.Writer, c *pkg.Cache) error {
|
||||
zero [wordSize]byte
|
||||
buf [len(pkg.ID{}) + wordSize]byte
|
||||
)
|
||||
t := native.Std()
|
||||
for _, p := range native.Collect() {
|
||||
t := builtin.Std()
|
||||
for _, p := range builtin.Collect() {
|
||||
meta, a := t.MustLoad(p)
|
||||
if meta == nil {
|
||||
return errors.New("artifact " + p.String() + " in inconsistent state")
|
||||
|
||||
+4
-12
@@ -624,33 +624,25 @@ func (attr *GenericHelper) script(t Toolchain, _ string) string {
|
||||
return script
|
||||
}
|
||||
|
||||
// native contains natively-implemented and built-in azalea-based [Artifact].
|
||||
// It is generally recommended to clone this instance for custom [Artifact]
|
||||
// registrations.
|
||||
var native S
|
||||
|
||||
// Native returns the global [S].
|
||||
func Native() *S { return &native }
|
||||
|
||||
// parseTime is the duration of early parsing of built-in azalea expressions.
|
||||
var parseTime time.Duration
|
||||
|
||||
// ParseTime returns the time taken by early parsing of built-in azalea expressions.
|
||||
func ParseTime() time.Duration { return parseTime }
|
||||
|
||||
// nativeB is the backing directory of built-in azalea-based [Artifact]
|
||||
// builtinAzalea is the backing directory of built-in azalea-based [Artifact]
|
||||
// implementations.
|
||||
//
|
||||
//go:embed package
|
||||
var nativeB embed.FS
|
||||
var builtinAzalea embed.FS
|
||||
|
||||
func init() {
|
||||
sub, err := fs.Sub(nativeB, "package")
|
||||
sub, err := fs.Sub(builtinAzalea, "package")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
t := time.Now()
|
||||
if err = native.RegisterFS(sub); err != nil {
|
||||
if err = builtin.RegisterFS(sub); err != nil {
|
||||
println(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ var (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
rosa.Native().DropCaches("", rosa.OptLLVMNoLTO)
|
||||
container.TryArgv0(nil)
|
||||
|
||||
code := m.Run()
|
||||
@@ -79,8 +78,8 @@ func TestCureAll(t *testing.T) {
|
||||
cache := getCache(t)
|
||||
t.Parallel()
|
||||
|
||||
for _, p := range rosa.Native().CollectAll() {
|
||||
_, a := rosa.Native().Std().MustLoad(p)
|
||||
for _, p := range rosa.CollectAll() {
|
||||
_, a := rosa.MustLoad(p)
|
||||
t.Run(p.String(), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -94,7 +93,7 @@ func TestCureAll(t *testing.T) {
|
||||
}
|
||||
|
||||
func BenchmarkStage3(b *testing.B) {
|
||||
t := rosa.Native().Clone().Std()
|
||||
t := rosa.New().Std()
|
||||
|
||||
llvm := rosa.H("llvm")
|
||||
for b.Loop() {
|
||||
|
||||
+17
-17
@@ -184,16 +184,16 @@ type cachedArtifact struct {
|
||||
const (
|
||||
// OptSkipCheck skips running all test suites.
|
||||
OptSkipCheck = 1 << iota
|
||||
// OptLLVMNoLTO disables LTO in all [LLVM] stages.
|
||||
OptLLVMNoLTO
|
||||
// OptToolchainLTO enables LTO in all LLVM stages.
|
||||
OptToolchainLTO
|
||||
)
|
||||
|
||||
// S holds a set of [Artifact].
|
||||
type S struct {
|
||||
// [ArtifactH] to [Artifact].
|
||||
artifacts sync.Map
|
||||
// Size of artifacts.
|
||||
artifactCount atomic.Uint64
|
||||
p sync.Map
|
||||
// Size of p.
|
||||
len atomic.Uint64
|
||||
|
||||
// Target architecture.
|
||||
arch string
|
||||
@@ -220,9 +220,9 @@ type S struct {
|
||||
// Clone returns a copy of s.
|
||||
func (s *S) Clone() *S {
|
||||
v := S{arch: s.arch, opts: s.opts}
|
||||
s.artifacts.Range(func(key, value any) bool {
|
||||
v.artifacts.Store(key, value)
|
||||
v.artifactCount.Add(1)
|
||||
s.p.Range(func(key, value any) bool {
|
||||
v.p.Store(key, value)
|
||||
v.len.Add(1)
|
||||
return true
|
||||
})
|
||||
return &v
|
||||
@@ -304,7 +304,7 @@ func (s *S) DropCaches(targetArch string, flags int) {
|
||||
// get returns the named [Artifact].
|
||||
func (s *S) get(handle ArtifactH) (f Artifact) {
|
||||
s.wantsArch()
|
||||
v, ok := s.artifacts.Load(handle)
|
||||
v, ok := s.p.Load(handle)
|
||||
if ok {
|
||||
f = v.(Artifact)
|
||||
}
|
||||
@@ -393,9 +393,9 @@ func (s *S) Register(name string, f Artifact) bool {
|
||||
return false
|
||||
}
|
||||
p := ArtifactH(unique.Make(name))
|
||||
_, ok := s.artifacts.LoadOrStore(p, f)
|
||||
_, ok := s.p.LoadOrStore(p, f)
|
||||
if !ok {
|
||||
s.artifactCount.Add(1)
|
||||
s.len.Add(1)
|
||||
}
|
||||
return !ok
|
||||
}
|
||||
@@ -418,15 +418,15 @@ func (s *S) MustRegister(name string, f Artifact) {
|
||||
}
|
||||
}
|
||||
|
||||
// count returns the number of [Artifact] registered to s.
|
||||
// count returns the number of [Artifact] registered to r.
|
||||
func (s *S) count() int {
|
||||
return int(s.artifactCount.Load())
|
||||
return int(s.len.Load())
|
||||
}
|
||||
|
||||
// CollectAll returns all [ArtifactH] registered to s.
|
||||
func (s *S) CollectAll() (handles P) {
|
||||
handles = make(P, 0, s.count())
|
||||
s.artifacts.Range(func(key, _ any) bool {
|
||||
s.p.Range(func(key, _ any) bool {
|
||||
handles = append(handles, key.(ArtifactH))
|
||||
return true
|
||||
})
|
||||
@@ -439,7 +439,7 @@ func (s *S) CollectAll() (handles P) {
|
||||
// Collect returns all non-excluded [ArtifactH] registered to s.
|
||||
func (s *S) Collect() (handles P) {
|
||||
handles = make(P, 0, s.count())
|
||||
s.artifacts.Range(func(key, _ any) bool {
|
||||
s.p.Range(func(key, _ any) bool {
|
||||
h := key.(ArtifactH)
|
||||
meta, _ := s.Std().MustLoad(h)
|
||||
if !meta.Exclude {
|
||||
@@ -453,7 +453,7 @@ func (s *S) Collect() (handles P) {
|
||||
return
|
||||
}
|
||||
|
||||
// deferredGit is a call to Toolchain.newTagRemote from azalea.
|
||||
// deferredGit is a call to [Toolchain.NewViaGit] from azalea.
|
||||
type deferredGit struct {
|
||||
url string
|
||||
tag string
|
||||
@@ -1375,7 +1375,7 @@ func (s *S) SetSource(fsys fs.FS) error {
|
||||
|
||||
const name = "hakurei-source"
|
||||
a := pkg.NewFile("hakurei-src-current.tar.gz", buf.Bytes())
|
||||
s.artifacts.Store(
|
||||
s.p.Store(
|
||||
H(name),
|
||||
Artifact(func(t Toolchain) (*Metadata, pkg.Artifact) {
|
||||
return &Metadata{
|
||||
|
||||
@@ -9,17 +9,17 @@ import (
|
||||
func TestLoad(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, p := range rosa.Native().Collect() {
|
||||
for _, p := range rosa.Collect() {
|
||||
t.Run(p.String(), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
rosa.Native().Std().MustLoad(p)
|
||||
rosa.MustLoad(p)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAll(b *testing.B) {
|
||||
t := rosa.Native().Clone().Std()
|
||||
t := rosa.New().Std()
|
||||
|
||||
for b.Loop() {
|
||||
for _, p := range t.Collect() {
|
||||
|
||||
Reference in New Issue
Block a user