Compare commits
99 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
608d8303ec
|
|||
|
1c6f30379e
|
|||
|
009a4e0d58
|
|||
|
e7c8656691
|
|||
|
d6be116ff8
|
|||
|
962b02cf25
|
|||
|
6fd6d971ed
|
|||
|
548c96c7ec
|
|||
|
6e8bfa6c4c
|
|||
|
a770d62b9b
|
|||
|
ff44060763
|
|||
|
3010a209b5
|
|||
|
e65a3b435c
|
|||
|
23515f67c8
|
|||
|
4389df60ae
|
|||
|
8092492018
|
|||
|
a7877844bf
|
|||
|
1ed027846d
|
|||
|
2f376d4813
|
|||
|
dc3810b530
|
|||
|
6e9e8c74f3
|
|||
|
4d60fa5632
|
|||
|
8807cbc730
|
|||
|
0e95573f18
|
|||
|
eb2b53307a
|
|||
|
682b3a2ce5
|
|||
|
594221eb78
|
|||
|
34822925e1
|
|||
|
37df040d85
|
|||
|
0360e779f3
|
|||
|
3e236333a7
|
|||
|
f24ae21af1
|
|||
|
99b324fb17
|
|||
|
6f50811dc9
|
|||
|
6b87bac401
|
|||
|
a967aa3b6e
|
|||
|
38bc2c7508
|
|||
|
30eb0d6a61
|
|||
|
c2ff9c9fa5
|
|||
|
d38d306147
|
|||
|
c32c06b2e8
|
|||
|
61199f734c
|
|||
|
87cf0d4e6b
|
|||
|
cf0dffa0f5
|
|||
|
686d7ec63a
|
|||
|
4c653b1151
|
|||
|
0b0a63d151
|
|||
|
6231cfe2aa
|
|||
|
712e80890b
|
|||
|
3fe7d48014
|
|||
|
16f9d39427
|
|||
|
c1cd5ba07b
|
|||
|
7b0cd2e472
|
|||
|
e580307528
|
|||
|
ee1dffb676
|
|||
|
f095fcf181
|
|||
|
ca8a130130
|
|||
|
0ad6b00e41
|
|||
|
ad0f1cf36b
|
|||
|
b12d924fa2
|
|||
|
c31d8ae41a
|
|||
|
6dbbf15c0e
|
|||
|
be7de68a42
|
|||
|
a759cf3666
|
|||
|
8c2dd3e984
|
|||
|
67038d5af4
|
|||
|
53d8d12e7f
|
|||
|
7997d79e56
|
|||
|
f2f1726190
|
|||
|
f63203cb0a
|
|||
|
19555c7670
|
|||
|
a3beab8959
|
|||
|
2ea786d6a9
|
|||
|
747d4ec4b0
|
|||
|
b76e6f6519
|
|||
|
840d8f68bf
|
|||
|
4bede7ecdd
|
|||
|
487a03b5a3
|
|||
|
8f3c22896a
|
|||
|
a167c1aba5
|
|||
|
a6008ef68b
|
|||
|
5228b27362
|
|||
|
f00d3a07ad
|
|||
|
f9538bc21b
|
|||
|
6ae5efec56
|
|||
|
14f4c59c8c
|
|||
|
688d43417b
|
|||
|
9f8fafa39b
|
|||
|
6643cfbeee
|
|||
|
dcde38f2e9
|
|||
|
deebbf6b1a
|
|||
|
0c557798bc
|
|||
|
327e6ed5a2
|
|||
|
76c7a423a9
|
|||
|
6e113b8836
|
|||
|
ce9f4b5f71
|
|||
|
8f727273ef
|
|||
|
d0a63b942e
|
|||
|
7f2126df32
|
@@ -6,6 +6,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"unique"
|
||||
|
||||
"hakurei.app/internal/pkg"
|
||||
"hakurei.app/internal/rosa"
|
||||
@@ -35,17 +36,19 @@ func commandInfo(
|
||||
}
|
||||
}
|
||||
|
||||
t := rosa.Native().Std()
|
||||
for i, name := range args {
|
||||
if p, ok := rosa.ResolveName(name); !ok {
|
||||
handle := rosa.ArtifactH(unique.Make(name))
|
||||
if meta, a := t.Load(handle); meta == nil {
|
||||
return fmt.Errorf("unknown artifact %q", name)
|
||||
} else {
|
||||
var suffix string
|
||||
if version := rosa.Std.Version(p); version != rosa.Unversioned {
|
||||
suffix += "-" + version
|
||||
|
||||
if meta.Version != rosa.Unversioned {
|
||||
suffix += "-" + meta.Version
|
||||
}
|
||||
mustPrintln("name : " + name + suffix)
|
||||
|
||||
meta := rosa.GetMetadata(p)
|
||||
mustPrintln("description : " + meta.Description)
|
||||
if meta.Website != "" {
|
||||
mustPrintln("website : " +
|
||||
@@ -54,9 +57,10 @@ func commandInfo(
|
||||
if len(meta.Dependencies) > 0 {
|
||||
mustPrint("depends on :")
|
||||
for _, d := range meta.Dependencies {
|
||||
s := rosa.GetMetadata(d).Name
|
||||
if version := rosa.Std.Version(d); version != rosa.Unversioned {
|
||||
s += "-" + version
|
||||
_meta, _ := rosa.Native().Std().MustLoad(d)
|
||||
s := _meta.Name
|
||||
if _meta.Version != rosa.Unversioned {
|
||||
s += "-" + _meta.Version
|
||||
}
|
||||
mustPrint(" " + s)
|
||||
}
|
||||
@@ -68,7 +72,7 @@ func commandInfo(
|
||||
if r == nil {
|
||||
var f io.ReadSeekCloser
|
||||
err = cm.Do(func(cache *pkg.Cache) (err error) {
|
||||
f, err = cache.OpenStatus(rosa.Std.Load(p))
|
||||
f, err = cache.OpenStatus(a)
|
||||
return
|
||||
})
|
||||
if err != nil {
|
||||
@@ -87,7 +91,7 @@ func commandInfo(
|
||||
}
|
||||
}
|
||||
} else if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
||||
status, n := r.ArtifactOf(cache.Ident(rosa.Std.Load(p)))
|
||||
status, n := r.ArtifactOf(cache.Ident(a))
|
||||
if status == nil {
|
||||
mustPrintln(
|
||||
statusPrefix + "not in report",
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
"unique"
|
||||
"unsafe"
|
||||
|
||||
"hakurei.app/internal/pkg"
|
||||
@@ -20,6 +21,14 @@ import (
|
||||
func TestInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_t := rosa.Native().Std()
|
||||
qemuMeta, _ := _t.Load(rosa.QEMU)
|
||||
glibMeta, _ := _t.Load(rosa.GLib)
|
||||
zlibMeta, zlib := _t.Load(rosa.Zlib)
|
||||
zstdMeta, _ := _t.Load(rosa.Zstd)
|
||||
hakureiMeta, _ := _t.Load(rosa.Hakurei)
|
||||
hakureiDistMeta, _ := _t.Load(rosa.HakureiDist)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
@@ -29,24 +38,24 @@ func TestInfo(t *testing.T) {
|
||||
wantErr any
|
||||
}{
|
||||
{"qemu", []string{"qemu"}, nil, "", `
|
||||
name : qemu-` + rosa.Std.Version(rosa.QEMU) + `
|
||||
name : qemu-` + qemuMeta.Version + `
|
||||
description : a generic and open source machine emulator and virtualizer
|
||||
website : https://www.qemu.org
|
||||
depends on : glib-` + rosa.Std.Version(rosa.GLib) + ` zstd-` + rosa.Std.Version(rosa.Zstd) + `
|
||||
depends on : glib-` + glibMeta.Version + ` zstd-` + zstdMeta.Version + `
|
||||
`, nil},
|
||||
|
||||
{"multi", []string{"hakurei", "hakurei-dist"}, nil, "", `
|
||||
name : hakurei-` + rosa.Std.Version(rosa.Hakurei) + `
|
||||
name : hakurei-` + hakureiMeta.Version + `
|
||||
description : low-level userspace tooling for Rosa OS
|
||||
website : https://hakurei.app
|
||||
|
||||
name : hakurei-dist-` + rosa.Std.Version(rosa.HakureiDist) + `
|
||||
name : hakurei-dist-` + hakureiDistMeta.Version + `
|
||||
description : low-level userspace tooling for Rosa OS (distribution tarball)
|
||||
website : https://hakurei.app
|
||||
`, nil},
|
||||
|
||||
{"nonexistent", []string{"zlib", "\x00"}, nil, "", `
|
||||
name : zlib-` + rosa.Std.Version(rosa.Zlib) + `
|
||||
name : zlib-` + zlibMeta.Version + `
|
||||
description : lossless data-compression library
|
||||
website : https://zlib.net
|
||||
|
||||
@@ -56,12 +65,12 @@ website : https://zlib.net
|
||||
"zstd": "internal/pkg (amd64) on satori\n",
|
||||
"hakurei": "internal/pkg (amd64) on satori\n\n",
|
||||
}, "", `
|
||||
name : zlib-` + rosa.Std.Version(rosa.Zlib) + `
|
||||
name : zlib-` + zlibMeta.Version + `
|
||||
description : lossless data-compression library
|
||||
website : https://zlib.net
|
||||
status : not yet cured
|
||||
|
||||
name : zstd-` + rosa.Std.Version(rosa.Zstd) + `
|
||||
name : zstd-` + zstdMeta.Version + `
|
||||
description : a fast compression algorithm
|
||||
website : https://facebook.github.io/zstd
|
||||
status : internal/pkg (amd64) on satori
|
||||
@@ -70,19 +79,19 @@ status : internal/pkg (amd64) on satori
|
||||
{"status cache perm", []string{"zlib"}, map[string]string{
|
||||
"zlib": "\x00",
|
||||
}, "", `
|
||||
name : zlib-` + rosa.Std.Version(rosa.Zlib) + `
|
||||
name : zlib-` + zlibMeta.Version + `
|
||||
description : lossless data-compression library
|
||||
website : https://zlib.net
|
||||
`, func(cm *cache) error {
|
||||
return &os.PathError{
|
||||
Op: "open",
|
||||
Path: filepath.Join(cm.base, "status", pkg.Encode(cm.c.Ident(rosa.Std.Load(rosa.Zlib)).Value())),
|
||||
Path: filepath.Join(cm.base, "status", pkg.Encode(cm.c.Ident(zlib).Value())),
|
||||
Err: syscall.EACCES,
|
||||
}
|
||||
}},
|
||||
|
||||
{"status report", []string{"zlib"}, nil, strings.Repeat("\x00", len(pkg.Checksum{})+8), `
|
||||
name : zlib-` + rosa.Std.Version(rosa.Zlib) + `
|
||||
name : zlib-` + zlibMeta.Version + `
|
||||
description : lossless data-compression library
|
||||
website : https://zlib.net
|
||||
status : not in report
|
||||
@@ -131,8 +140,8 @@ status : not in report
|
||||
|
||||
if tc.status != nil {
|
||||
for name, status := range tc.status {
|
||||
p, ok := rosa.ResolveName(name)
|
||||
if !ok {
|
||||
_, a := _t.Load(rosa.ArtifactH(unique.Make(name)))
|
||||
if a == nil {
|
||||
t.Fatalf("invalid name %q", name)
|
||||
}
|
||||
perm := os.FileMode(0400)
|
||||
@@ -143,7 +152,7 @@ status : not in report
|
||||
return os.WriteFile(filepath.Join(
|
||||
cm.base,
|
||||
"status",
|
||||
pkg.Encode(cache.Ident(rosa.Std.Load(p)).Value()),
|
||||
pkg.Encode(cache.Ident(a).Value()),
|
||||
), unsafe.Slice(unsafe.StringData(status), len(status)), perm)
|
||||
}); err != nil {
|
||||
t.Fatalf("Do: error = %v", err)
|
||||
|
||||
@@ -30,7 +30,7 @@ var (
|
||||
// handleInfo writes constant system information.
|
||||
func handleInfo(w http.ResponseWriter, _ *http.Request) {
|
||||
infoPayloadOnce.Do(func() {
|
||||
infoPayload.Count = int(rosa.PresetUnexportedStart)
|
||||
infoPayload.Count = int(rosa.Native().Count())
|
||||
infoPayload.HakureiVersion = info.Version()
|
||||
})
|
||||
// TODO(mae): cache entire response if no additional fields are planned
|
||||
@@ -91,7 +91,7 @@ func (index *packageIndex) handleGet(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil || i >= len(index.sorts[0]) || i < 0 {
|
||||
http.Error(
|
||||
w, "index must be an integer between 0 and "+
|
||||
strconv.Itoa(int(rosa.PresetUnexportedStart-1)),
|
||||
strconv.Itoa(len(index.sorts[0])-1),
|
||||
http.StatusBadRequest,
|
||||
)
|
||||
return
|
||||
@@ -125,7 +125,7 @@ func (index *packageIndex) handleSearch(w http.ResponseWriter, r *http.Request)
|
||||
if err != nil || i >= len(index.sorts[0]) || i < 0 {
|
||||
http.Error(
|
||||
w, "index must be an integer between 0 and "+
|
||||
strconv.Itoa(int(rosa.PresetUnexportedStart-1)),
|
||||
strconv.Itoa(len(index.sorts[0])-1),
|
||||
http.StatusBadRequest,
|
||||
)
|
||||
return
|
||||
|
||||
@@ -3,7 +3,6 @@ package pkgserver
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"slices"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
@@ -32,7 +31,7 @@ func TestAPIInfo(t *testing.T) {
|
||||
checkPayload(t, resp, struct {
|
||||
Count int `json:"count"`
|
||||
HakureiVersion string `json:"hakurei_version"`
|
||||
}{int(rosa.PresetUnexportedStart), info.Version()})
|
||||
}{rosa.Native().Count(), info.Version()})
|
||||
}
|
||||
|
||||
func TestAPIGet(t *testing.T) {
|
||||
@@ -96,8 +95,8 @@ func TestAPIGet(t *testing.T) {
|
||||
t.Run("index", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
checkValidate(
|
||||
t, "limit=1&sort=0&index", 0, int(rosa.PresetUnexportedStart-1),
|
||||
"index must be an integer between 0 and "+strconv.Itoa(int(rosa.PresetUnexportedStart-1)),
|
||||
t, "limit=1&sort=0&index", 0, rosa.Native().Count()-1,
|
||||
"index must be an integer between 0 and "+strconv.Itoa(rosa.Native().Count()-1),
|
||||
)
|
||||
})
|
||||
|
||||
@@ -108,74 +107,4 @@ func TestAPIGet(t *testing.T) {
|
||||
"sort must be an integer between 0 and "+strconv.Itoa(int(sortOrderEnd)),
|
||||
)
|
||||
})
|
||||
|
||||
checkWithSuffix := func(name, suffix string, want []*metadata) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
w := newRequest(suffix)
|
||||
resp := w.Result()
|
||||
checkStatus(t, resp, http.StatusOK)
|
||||
checkAPIHeader(t, w.Header())
|
||||
checkPayloadFunc(t, resp, func(got *struct {
|
||||
Values []*metadata `json:"values"`
|
||||
}) bool {
|
||||
return slices.EqualFunc(got.Values, want, func(a, b *metadata) bool {
|
||||
return (a.Version == b.Version ||
|
||||
a.Version == rosa.Unversioned ||
|
||||
b.Version == rosa.Unversioned) &&
|
||||
a.HasReport == b.HasReport &&
|
||||
a.Name == b.Name &&
|
||||
a.Description == b.Description &&
|
||||
a.Website == b.Website
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
checkWithSuffix("declarationAscending", "?limit=2&index=1&sort=0", []*metadata{
|
||||
{
|
||||
Metadata: rosa.GetMetadata(1),
|
||||
Version: rosa.Std.Version(1),
|
||||
},
|
||||
{
|
||||
Metadata: rosa.GetMetadata(2),
|
||||
Version: rosa.Std.Version(2),
|
||||
},
|
||||
})
|
||||
checkWithSuffix("declarationAscending offset", "?limit=3&index=5&sort=0", []*metadata{
|
||||
{
|
||||
Metadata: rosa.GetMetadata(5),
|
||||
Version: rosa.Std.Version(5),
|
||||
},
|
||||
{
|
||||
Metadata: rosa.GetMetadata(6),
|
||||
Version: rosa.Std.Version(6),
|
||||
},
|
||||
{
|
||||
Metadata: rosa.GetMetadata(7),
|
||||
Version: rosa.Std.Version(7),
|
||||
},
|
||||
})
|
||||
checkWithSuffix("declarationDescending", "?limit=3&index=0&sort=1", []*metadata{
|
||||
{
|
||||
Metadata: rosa.GetMetadata(rosa.PresetUnexportedStart - 1),
|
||||
Version: rosa.Std.Version(rosa.PresetUnexportedStart - 1),
|
||||
},
|
||||
{
|
||||
Metadata: rosa.GetMetadata(rosa.PresetUnexportedStart - 2),
|
||||
Version: rosa.Std.Version(rosa.PresetUnexportedStart - 2),
|
||||
},
|
||||
{
|
||||
Metadata: rosa.GetMetadata(rosa.PresetUnexportedStart - 3),
|
||||
Version: rosa.Std.Version(rosa.PresetUnexportedStart - 3),
|
||||
},
|
||||
})
|
||||
checkWithSuffix("declarationDescending offset", "?limit=1&index=37&sort=1", []*metadata{
|
||||
{
|
||||
Metadata: rosa.GetMetadata(rosa.PresetUnexportedStart - 38),
|
||||
Version: rosa.Std.Version(rosa.PresetUnexportedStart - 38),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ const (
|
||||
|
||||
// packageIndex refers to metadata by name and various sort orders.
|
||||
type packageIndex struct {
|
||||
sorts [sortOrderEnd + 1][rosa.PresetUnexportedStart]*metadata
|
||||
sorts [sortOrderEnd + 1][]*metadata
|
||||
names map[string]*metadata
|
||||
search searchCache
|
||||
// Taken from [rosa.Report] if available.
|
||||
@@ -32,11 +32,11 @@ type packageIndex struct {
|
||||
|
||||
// metadata holds [rosa.Metadata] extended with additional information.
|
||||
type metadata struct {
|
||||
p rosa.PArtifact
|
||||
handle rosa.ArtifactH
|
||||
*rosa.Metadata
|
||||
|
||||
// Populated via [rosa.Toolchain.Version], [rosa.Unversioned] is equivalent
|
||||
// to the zero value. Otherwise, the zero value is invalid.
|
||||
// Copied from [rosa.Metadata], [rosa.Unversioned] is equivalent to the zero
|
||||
// value. Otherwise, the zero value is invalid.
|
||||
Version string `json:"version,omitempty"`
|
||||
// Output data size, available if present in report.
|
||||
Size int64 `json:"size,omitempty"`
|
||||
@@ -56,15 +56,17 @@ func (index *packageIndex) populate(report *rosa.Report) (err error) {
|
||||
index.handleAccess = report.HandleAccess
|
||||
}
|
||||
|
||||
var work [rosa.PresetUnexportedStart]*metadata
|
||||
handles := rosa.Native().Collect()
|
||||
work := make([]*metadata, len(handles))
|
||||
index.names = make(map[string]*metadata)
|
||||
ir := pkg.NewIR()
|
||||
for p := range rosa.PresetUnexportedStart {
|
||||
for i, handle := range handles {
|
||||
meta, a := rosa.Native().Std().MustLoad(handle)
|
||||
m := metadata{
|
||||
p: p,
|
||||
handle: handle,
|
||||
|
||||
Metadata: rosa.GetMetadata(p),
|
||||
Version: rosa.Std.Version(p),
|
||||
Metadata: meta,
|
||||
Version: meta.Version,
|
||||
}
|
||||
if m.Version == "" {
|
||||
return errors.New("invalid version from " + m.Name)
|
||||
@@ -74,32 +76,32 @@ func (index *packageIndex) populate(report *rosa.Report) (err error) {
|
||||
}
|
||||
|
||||
if report != nil {
|
||||
id := ir.Ident(rosa.Std.Load(p))
|
||||
id := ir.Ident(a)
|
||||
m.ids = pkg.Encode(id.Value())
|
||||
m.status, m.Size = report.ArtifactOf(id)
|
||||
m.HasReport = m.Size >= 0
|
||||
}
|
||||
|
||||
work[p] = &m
|
||||
work[i] = &m
|
||||
index.names[m.Name] = &m
|
||||
}
|
||||
|
||||
index.sorts[declarationAscending] = work
|
||||
index.sorts[declarationDescending] = work
|
||||
index.sorts[declarationDescending] = slices.Clone(work)
|
||||
slices.Reverse(index.sorts[declarationDescending][:])
|
||||
|
||||
index.sorts[nameAscending] = work
|
||||
index.sorts[nameAscending] = slices.Clone(work)
|
||||
slices.SortFunc(index.sorts[nameAscending][:], func(a, b *metadata) int {
|
||||
return strings.Compare(a.Name, b.Name)
|
||||
})
|
||||
index.sorts[nameDescending] = index.sorts[nameAscending]
|
||||
index.sorts[nameDescending] = slices.Clone(index.sorts[nameAscending])
|
||||
slices.Reverse(index.sorts[nameDescending][:])
|
||||
|
||||
index.sorts[sizeAscending] = work
|
||||
index.sorts[sizeAscending] = slices.Clone(work)
|
||||
slices.SortFunc(index.sorts[sizeAscending][:], func(a, b *metadata) int {
|
||||
return cmp.Compare(a.Size, b.Size)
|
||||
})
|
||||
index.sorts[sizeDescending] = index.sorts[sizeAscending]
|
||||
index.sorts[sizeDescending] = slices.Clone(index.sorts[sizeAscending])
|
||||
slices.Reverse(index.sorts[sizeDescending][:])
|
||||
|
||||
return
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<title>Hakurei PkgServer</title>
|
||||
<link rel="icon" href="https://hakurei.app/favicon.ico"/>
|
||||
<title>Rosa OS Packages</title>
|
||||
<script src="index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hakurei PkgServer</h1>
|
||||
<h1>Rosa OS Packages</h1>
|
||||
<div class="top-controls" id="top-controls-regular">
|
||||
<p>Showing entries <span id="entry-counter"></span>.</p>
|
||||
<span id="search-bar">
|
||||
@@ -54,4 +55,4 @@
|
||||
</footer>
|
||||
<script>main();</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
172
cmd/mbf/main.go
172
cmd/mbf/main.go
@@ -58,6 +58,19 @@ func main() {
|
||||
log.Fatal("this program must not run as root")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r == nil {
|
||||
return
|
||||
}
|
||||
|
||||
e, ok := r.(rosa.LoadError)
|
||||
if !ok {
|
||||
panic(r)
|
||||
}
|
||||
log.Fatal(e)
|
||||
}()
|
||||
|
||||
ctx, stop := signal.NotifyContext(context.Background(),
|
||||
syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
|
||||
defer stop()
|
||||
@@ -71,12 +84,17 @@ func main() {
|
||||
flagArch string
|
||||
flagCheck bool
|
||||
flagLTO bool
|
||||
flagPT bool
|
||||
|
||||
flagCrossOverride int
|
||||
|
||||
addr net.UnixAddr
|
||||
)
|
||||
c := command.New(os.Stderr, log.Printf, "mbf", func([]string) error {
|
||||
if flagPT {
|
||||
log.Println("parsed in", rosa.ParseTime())
|
||||
}
|
||||
|
||||
msg.SwapVerbose(!flagQuiet)
|
||||
cm.ctx, cm.msg = ctx, msg
|
||||
cm.base = os.ExpandEnv(cm.base)
|
||||
@@ -97,10 +115,10 @@ func main() {
|
||||
if !flagLTO {
|
||||
flags |= rosa.OptLLVMNoLTO
|
||||
}
|
||||
rosa.DropCaches("", flags)
|
||||
rosa.Native().DropCaches("", flags)
|
||||
cross := flagArch != "" && flagArch != runtime.GOARCH
|
||||
if flagQEMU || cross {
|
||||
cm.qemu = rosa.Std.Load(rosa.QEMU)
|
||||
_, cm.qemu = rosa.Native().Std().MustLoad(rosa.QEMU)
|
||||
}
|
||||
|
||||
if cross {
|
||||
@@ -108,7 +126,7 @@ func main() {
|
||||
flags = flagCrossOverride
|
||||
}
|
||||
|
||||
rosa.DropCaches(flagArch, flags)
|
||||
rosa.Native().DropCaches(flagArch, flags)
|
||||
if !rosa.HasStage0() {
|
||||
return pkg.UnsupportedArchError(flagArch)
|
||||
}
|
||||
@@ -170,6 +188,10 @@ func main() {
|
||||
&addr.Name,
|
||||
"socket", command.StringFlag("$MBF_DAEMON_SOCKET"),
|
||||
"Pathname of socket to bind to",
|
||||
).Flag(
|
||||
&flagPT,
|
||||
"parse-time", command.BoolFlag(false),
|
||||
"Print duration of the initial azalea parse",
|
||||
)
|
||||
|
||||
c.NewCommand(
|
||||
@@ -331,12 +353,12 @@ func main() {
|
||||
n atomic.Uint64
|
||||
)
|
||||
|
||||
w := make(chan rosa.PArtifact)
|
||||
w := make(chan rosa.ArtifactH)
|
||||
var wg sync.WaitGroup
|
||||
for range max(flagJobs, 1) {
|
||||
wg.Go(func() {
|
||||
for p := range w {
|
||||
meta := rosa.GetMetadata(p)
|
||||
meta, _ := rosa.Native().Std().MustLoad(p)
|
||||
if meta.ID == 0 {
|
||||
continue
|
||||
}
|
||||
@@ -349,12 +371,9 @@ func main() {
|
||||
continue
|
||||
}
|
||||
|
||||
if current, latest :=
|
||||
rosa.Std.Version(p),
|
||||
meta.GetLatest(v); current != latest {
|
||||
|
||||
if latest := meta.GetLatest(v); meta.Version != latest {
|
||||
n.Add(1)
|
||||
log.Printf("%s %s < %s", meta.Name, current, latest)
|
||||
log.Printf("%s %s < %s", meta.Name, meta.Version, latest)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -364,9 +383,9 @@ func main() {
|
||||
}
|
||||
|
||||
done:
|
||||
for i := range rosa.PresetEnd {
|
||||
for _, p := range rosa.Native().Collect() {
|
||||
select {
|
||||
case w <- rosa.PArtifact(i):
|
||||
case w <- p:
|
||||
break
|
||||
case <-ctx.Done():
|
||||
break done
|
||||
@@ -411,9 +430,9 @@ func main() {
|
||||
"stage3",
|
||||
"Check for toolchain 3-stage non-determinism",
|
||||
func(args []string) (err error) {
|
||||
t := rosa.Std
|
||||
s := rosa.Std
|
||||
if flagGentoo != "" {
|
||||
t -= 3 // magic number to discourage misuse
|
||||
s -= 3 // magic number to discourage misuse
|
||||
|
||||
var checksum pkg.Checksum
|
||||
if len(flagChecksum) != 0 {
|
||||
@@ -421,7 +440,7 @@ func main() {
|
||||
return
|
||||
}
|
||||
}
|
||||
rosa.SetGentooStage3(flagGentoo, checksum)
|
||||
rosa.Native().SetGentooStage3(flagGentoo, checksum)
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -430,9 +449,8 @@ func main() {
|
||||
)
|
||||
|
||||
if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
||||
pathname, _, err = cache.Cure(
|
||||
(t - 2).Load(rosa.LLVM),
|
||||
)
|
||||
_, llvm := rosa.Native().New(s - 2).Load(rosa.LLVM)
|
||||
pathname, _, err = cache.Cure(llvm)
|
||||
return
|
||||
}); err != nil {
|
||||
return
|
||||
@@ -440,18 +458,16 @@ func main() {
|
||||
log.Println("stage1:", pathname)
|
||||
|
||||
if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
||||
pathname, checksum[0], err = cache.Cure(
|
||||
(t - 1).Load(rosa.LLVM),
|
||||
)
|
||||
_, llvm := rosa.Native().New(s - 1).Load(rosa.LLVM)
|
||||
pathname, checksum[0], err = cache.Cure(llvm)
|
||||
return
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
log.Println("stage2:", pathname)
|
||||
if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
||||
pathname, checksum[1], err = cache.Cure(
|
||||
t.Load(rosa.LLVM),
|
||||
)
|
||||
_, llvm := rosa.Native().New(s).Load(rosa.LLVM)
|
||||
pathname, checksum[1], err = cache.Cure(llvm)
|
||||
return
|
||||
}); err != nil {
|
||||
return
|
||||
@@ -472,9 +488,8 @@ func main() {
|
||||
|
||||
if flagStage0 {
|
||||
if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
||||
pathname, _, err = cache.Cure(
|
||||
t.Load(rosa.Stage0),
|
||||
)
|
||||
_, stage0 := rosa.Native().New(s).Load(rosa.Stage0)
|
||||
pathname, _, err = cache.Cure(stage0)
|
||||
return
|
||||
}); err != nil {
|
||||
return
|
||||
@@ -506,6 +521,8 @@ func main() {
|
||||
flagExport string
|
||||
flagRemote bool
|
||||
flagNoReply bool
|
||||
flagFaults bool
|
||||
flagPop bool
|
||||
|
||||
flagBoot bool
|
||||
flagStd bool
|
||||
@@ -517,10 +534,6 @@ func main() {
|
||||
if len(args) != 1 {
|
||||
return errors.New("cure requires 1 argument")
|
||||
}
|
||||
p, ok := rosa.ResolveName(args[0])
|
||||
if !ok {
|
||||
return fmt.Errorf("unknown artifact %q", args[0])
|
||||
}
|
||||
|
||||
t := rosa.Std
|
||||
if flagBoot {
|
||||
@@ -529,11 +542,16 @@ func main() {
|
||||
t -= 1
|
||||
}
|
||||
|
||||
_, a := rosa.Native().New(t).Load(rosa.ArtifactH(unique.Make(args[0])))
|
||||
if a == nil {
|
||||
return fmt.Errorf("unknown artifact %q", args[0])
|
||||
}
|
||||
|
||||
switch {
|
||||
default:
|
||||
var pathname *check.Absolute
|
||||
err := cm.Do(func(cache *pkg.Cache) (err error) {
|
||||
pathname, _, err = cache.Cure(t.Load(p))
|
||||
pathname, _, err = cache.Cure(a)
|
||||
return
|
||||
})
|
||||
if err != nil {
|
||||
@@ -575,7 +593,7 @@ func main() {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = pkg.NewIR().EncodeAll(f, rosa.Std.Load(p)); err != nil {
|
||||
if err = pkg.NewIR().EncodeAll(f, a); err != nil {
|
||||
_ = f.Close()
|
||||
return err
|
||||
}
|
||||
@@ -586,7 +604,7 @@ func main() {
|
||||
return cm.Do(func(cache *pkg.Cache) error {
|
||||
return cache.EnterExec(
|
||||
ctx,
|
||||
t.Load(p),
|
||||
a,
|
||||
true, os.Stdin, os.Stdout, os.Stderr,
|
||||
rosa.AbsSystem.Append("bin", "mksh"),
|
||||
"sh",
|
||||
@@ -598,7 +616,6 @@ func main() {
|
||||
if flagNoReply {
|
||||
flags |= remoteNoReply
|
||||
}
|
||||
a := t.Load(p)
|
||||
pathname, err := cureRemote(ctx, &addr, a, flags)
|
||||
if !flagNoReply && err == nil {
|
||||
log.Println(pathname)
|
||||
@@ -614,6 +631,49 @@ func main() {
|
||||
}
|
||||
|
||||
return err
|
||||
|
||||
case flagFaults:
|
||||
var faults []pkg.Fault
|
||||
if err := cm.Do(func(cache *pkg.Cache) (err error) {
|
||||
faults, err = cache.ReadFaults(a)
|
||||
return
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, fault := range faults {
|
||||
log.Printf("%s: %s ago", fault.String(), time.Since(fault.Time()))
|
||||
}
|
||||
return nil
|
||||
|
||||
case flagPop:
|
||||
var faults []pkg.Fault
|
||||
if err := cm.Do(func(cache *pkg.Cache) (err error) {
|
||||
faults, err = cache.ReadFaults(a)
|
||||
return
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(faults) == 0 {
|
||||
return errors.New("no fault entries found")
|
||||
}
|
||||
fault := faults[len(faults)-1]
|
||||
r, err := fault.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = io.Copy(os.Stdout, r); err != nil {
|
||||
_ = r.Close()
|
||||
return err
|
||||
}
|
||||
fmt.Println()
|
||||
if err = r.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("faulting cure terminated %s ago", time.Since(fault.Time()))
|
||||
return fault.Destroy()
|
||||
}
|
||||
},
|
||||
).Flag(
|
||||
@@ -644,9 +704,40 @@ func main() {
|
||||
&flagStd,
|
||||
"std", command.BoolFlag(false),
|
||||
"Build on the intermediate toolchain",
|
||||
).Flag(
|
||||
&flagFaults,
|
||||
"faults", command.BoolFlag(false),
|
||||
"Display fault entries of the specified artifact",
|
||||
).Flag(
|
||||
&flagPop,
|
||||
"pop", command.BoolFlag(false),
|
||||
"Display and destroy the most recent fault entry",
|
||||
)
|
||||
}
|
||||
|
||||
c.NewCommand(
|
||||
"clear",
|
||||
"Remove all fault entries from the cache",
|
||||
func([]string) error {
|
||||
return cm.Do(func(*pkg.Cache) error {
|
||||
pathname := filepath.Join(cm.base, "fault")
|
||||
dents, err := os.ReadDir(pathname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, dent := range dents {
|
||||
msg.Verbosef("destroying entry %s", dent.Name())
|
||||
if err = os.Remove(filepath.Join(pathname, dent.Name())); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
log.Printf("destroyed %d fault entries", len(dents))
|
||||
return nil
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
c.NewCommand(
|
||||
"abort",
|
||||
"Abort all pending cures on the daemon",
|
||||
@@ -664,27 +755,26 @@ func main() {
|
||||
"shell",
|
||||
"Interactive shell in the specified Rosa OS environment",
|
||||
func(args []string) error {
|
||||
presets := make([]rosa.PArtifact, len(args)+3)
|
||||
handles := make([]rosa.ArtifactH, len(args), len(args)+3)
|
||||
for i, arg := range args {
|
||||
p, ok := rosa.ResolveName(arg)
|
||||
if !ok {
|
||||
handles[i] = rosa.ArtifactH(unique.Make(arg))
|
||||
if meta, _ := rosa.Native().Std().Load(handles[i]); meta == nil {
|
||||
return fmt.Errorf("unknown artifact %q", arg)
|
||||
}
|
||||
presets[i] = p
|
||||
}
|
||||
|
||||
base := rosa.LLVM
|
||||
if !flagWithToolchain {
|
||||
base = rosa.Musl
|
||||
}
|
||||
presets = append(presets,
|
||||
handles = append(handles,
|
||||
base,
|
||||
rosa.Mksh,
|
||||
rosa.Toybox,
|
||||
)
|
||||
|
||||
root := make(pkg.Collect, 0, 6+len(args))
|
||||
root = rosa.Std.AppendPresets(root, presets...)
|
||||
root = rosa.Native().Std().Append(root, handles...)
|
||||
|
||||
if err := cm.Do(func(cache *pkg.Cache) error {
|
||||
_, _, err := cache.Cure(&root)
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
rosa.DropCaches("", rosa.OptLLVMNoLTO)
|
||||
rosa.Native().DropCaches("", rosa.OptLLVMNoLTO)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
@@ -35,10 +35,10 @@ func TestCureAll(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
for i := range rosa.PresetEnd {
|
||||
p := rosa.PArtifact(i)
|
||||
t.Run(rosa.GetMetadata(p).Name, func(t *testing.T) {
|
||||
_, err := cureRemote(t.Context(), &addr, rosa.Std.Load(p), 0)
|
||||
for _, handle := range rosa.Native().Collect() {
|
||||
_, a := rosa.Native().Std().MustLoad(handle)
|
||||
t.Run(handle.String(), func(t *testing.T) {
|
||||
_, err := cureRemote(t.Context(), &addr, a, 0)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -162,28 +162,40 @@ type execArtifact struct {
|
||||
|
||||
var _ fmt.Stringer = new(execArtifact)
|
||||
|
||||
// execNetArtifact is like execArtifact but implements [KnownChecksum] and has
|
||||
// its resulting container keep the host net namespace.
|
||||
type execNetArtifact struct {
|
||||
// execMeasuredArtifact is like execArtifact but implements [KnownChecksum] and
|
||||
// has its resulting container optionally keep the host net namespace.
|
||||
type execMeasuredArtifact struct {
|
||||
checksum Checksum
|
||||
|
||||
// Whether to keep host net namespace.
|
||||
hostNet bool
|
||||
|
||||
execArtifact
|
||||
}
|
||||
|
||||
var _ KnownChecksum = new(execNetArtifact)
|
||||
var _ KnownChecksum = new(execMeasuredArtifact)
|
||||
|
||||
// Checksum returns the caller-supplied checksum.
|
||||
func (a *execNetArtifact) Checksum() Checksum { return a.checksum }
|
||||
func (a *execMeasuredArtifact) Checksum() Checksum { return a.checksum }
|
||||
|
||||
// Kind returns the hardcoded [Kind] constant.
|
||||
func (*execNetArtifact) Kind() Kind { return KindExecNet }
|
||||
// Kind returns [KindExecNet], or [KindExec] if hostNet is false.
|
||||
func (a *execMeasuredArtifact) Kind() Kind {
|
||||
if a == nil || a.hostNet {
|
||||
return KindExecNet
|
||||
}
|
||||
return KindExec
|
||||
}
|
||||
|
||||
// Cure cures the [Artifact] in the container described by the caller. The
|
||||
// container retains host networking.
|
||||
func (a *execNetArtifact) Cure(f *FContext) error {
|
||||
return a.cure(f, true)
|
||||
// container optionally retains host networking.
|
||||
func (a *execMeasuredArtifact) Cure(f *FContext) error {
|
||||
return a.cure(f, a.hostNet)
|
||||
}
|
||||
|
||||
// ErrNetChecksum is panicked by [NewExec] if host net namespace is requested
|
||||
// with a nil checksum.
|
||||
var ErrNetChecksum = errors.New("attempting to keep net namespace without checksum")
|
||||
|
||||
// NewExec returns a new [Artifact] that executes the program path in a
|
||||
// container with specified paths bind mounted read-only in order. A private
|
||||
// instance of /proc and /dev is made available to the container.
|
||||
@@ -197,7 +209,7 @@ func (a *execNetArtifact) Cure(f *FContext) error {
|
||||
// regular or symlink.
|
||||
//
|
||||
// If checksum is non-nil, the resulting [Artifact] implements [KnownChecksum]
|
||||
// and its container runs in the host net namespace.
|
||||
// and its container optionally runs in the host net namespace.
|
||||
//
|
||||
// The container is allowed to run for the specified duration before the initial
|
||||
// process and all processes originating from it is terminated. A zero or
|
||||
@@ -211,7 +223,7 @@ func NewExec(
|
||||
name, arch string,
|
||||
checksum *Checksum,
|
||||
timeout time.Duration,
|
||||
exclusive bool,
|
||||
hostNet, exclusive bool,
|
||||
|
||||
dir *check.Absolute,
|
||||
env []string,
|
||||
@@ -234,9 +246,12 @@ func NewExec(
|
||||
}
|
||||
a := execArtifact{name, arch, paths, dir, env, pathname, args, timeout, exclusive}
|
||||
if checksum == nil {
|
||||
if hostNet {
|
||||
panic(ErrNetChecksum)
|
||||
}
|
||||
return &a
|
||||
}
|
||||
return &execNetArtifact{*checksum, a}
|
||||
return &execMeasuredArtifact{*checksum, hostNet, a}
|
||||
}
|
||||
|
||||
// Kind returns the hardcoded [Kind] constant.
|
||||
@@ -361,22 +376,17 @@ func readExecArtifact(r *IRReader, net bool) Artifact {
|
||||
exclusive := r.ReadUint32() != 0
|
||||
|
||||
checksum, ok := r.Finalise()
|
||||
|
||||
var checksumP *Checksum
|
||||
if net {
|
||||
if !ok {
|
||||
panic(ErrExpectedChecksum)
|
||||
}
|
||||
checksumVal := checksum.Value()
|
||||
checksumP = &checksumVal
|
||||
} else {
|
||||
if ok {
|
||||
panic(ErrUnexpectedChecksum)
|
||||
}
|
||||
if ok {
|
||||
checksumP = new(checksum.Value())
|
||||
}
|
||||
|
||||
if net && !ok {
|
||||
panic(ErrExpectedChecksum)
|
||||
}
|
||||
|
||||
return NewExec(
|
||||
name, arch, checksumP, timeout, exclusive, dir, env, pathname, args, paths...,
|
||||
name, arch, checksumP, timeout, net, exclusive, dir, env, pathname, args, paths...,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -588,9 +598,9 @@ func (c *Cache) EnterExec(
|
||||
case *execArtifact:
|
||||
e = f
|
||||
|
||||
case *execNetArtifact:
|
||||
case *execMeasuredArtifact:
|
||||
e = &f.execArtifact
|
||||
hostNet = true
|
||||
hostNet = f.hostNet
|
||||
|
||||
default:
|
||||
return ErrNotExec
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package pkg_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"encoding/gob"
|
||||
"errors"
|
||||
@@ -11,7 +12,6 @@ import (
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"testing"
|
||||
"unique"
|
||||
|
||||
"hakurei.app/check"
|
||||
"hakurei.app/container"
|
||||
@@ -50,14 +50,21 @@ func TestExec(t *testing.T) {
|
||||
"check": {Mode: 0400, Data: []byte{0}},
|
||||
}
|
||||
wantOfflineEncode := pkg.Encode(wantOffline.hash())
|
||||
failingArtifact := &stubArtifact{
|
||||
kind: pkg.KindTar,
|
||||
params: []byte("doomed artifact"),
|
||||
cure: func(t *pkg.TContext) error {
|
||||
return stub.UniqueError(0xcafe)
|
||||
},
|
||||
}
|
||||
|
||||
checkWithCache(t, []cacheTestCase{
|
||||
{"offline", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
{"offline", pkg.CValidateKnown | checkDestroySubstitutes, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
testtool, testtoolDestroy := newTesttool()
|
||||
|
||||
cureMany(t, c, []cureStep{
|
||||
{"container", pkg.NewExec(
|
||||
"exec-offline", "", nil, 0, false,
|
||||
"exec-offline", "", new(wantOffline.hash()), 0, false, false,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1"},
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
@@ -79,31 +86,47 @@ func TestExec(t *testing.T) {
|
||||
pkg.MustPath("/opt", false, testtool),
|
||||
), ignorePathname, wantOffline, nil},
|
||||
|
||||
{"error passthrough", pkg.NewExec(
|
||||
"", "", nil, 0, true,
|
||||
{"substitution", pkg.NewExec(
|
||||
"exec-offline", "", new(wantOffline.hash()), 0, false, false,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1"},
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
[]string{"testtool"},
|
||||
|
||||
pkg.MustPath("/proc/nonexistent", false, &stubArtifact{
|
||||
pkg.MustPath("/file", false, newStubFile(
|
||||
pkg.KindHTTPGet,
|
||||
pkg.ID{0xfe, 0},
|
||||
nil,
|
||||
nil, nil,
|
||||
)),
|
||||
// substitution miss fails in testtool due to differing idents
|
||||
pkg.MustPath("/.hakurei", false, &stubArtifact{
|
||||
kind: pkg.KindTar,
|
||||
params: []byte("doomed artifact"),
|
||||
params: []byte("empty directory (substituted)"),
|
||||
cure: func(t *pkg.TContext) error {
|
||||
return stub.UniqueError(0xcafe)
|
||||
return os.MkdirAll(t.GetWorkDir().String(), 0700)
|
||||
},
|
||||
}),
|
||||
pkg.MustPath("/opt", false, testtool),
|
||||
), ignorePathname, wantOffline, nil},
|
||||
|
||||
{"error passthrough", pkg.NewExec(
|
||||
"", "", nil, 0, false, true,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1"},
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
[]string{"testtool"},
|
||||
|
||||
pkg.MustPath("/proc/nonexistent", false, failingArtifact),
|
||||
), nil, nil, &pkg.DependencyCureError{
|
||||
{
|
||||
Ident: unique.Make(pkg.ID(pkg.MustDecode(
|
||||
"Sowo6oZRmG6xVtUaxB6bDWZhVsqAJsIJWUp0OPKlE103cY0lodx7dem8J-qQF0Z1",
|
||||
))),
|
||||
A: failingArtifact,
|
||||
Err: stub.UniqueError(0xcafe),
|
||||
},
|
||||
}},
|
||||
|
||||
{"invalid paths", pkg.NewExec(
|
||||
"", "", nil, 0, false,
|
||||
"", "", nil, 0, false, false,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1"},
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
@@ -114,18 +137,41 @@ func TestExec(t *testing.T) {
|
||||
})
|
||||
|
||||
// check init failure passthrough
|
||||
var exitError *exec.ExitError
|
||||
if _, _, err := c.Cure(pkg.NewExec(
|
||||
"", "", nil, 0, false,
|
||||
initFailureArtifact := pkg.NewExec(
|
||||
"", "", nil, 0, false, false,
|
||||
pkg.AbsWork,
|
||||
nil,
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
[]string{"testtool"},
|
||||
)); !errors.As(err, &exitError) ||
|
||||
)
|
||||
var exitError *exec.ExitError
|
||||
if _, _, err := c.Cure(initFailureArtifact); !errors.As(err, &exitError) ||
|
||||
exitError.ExitCode() != hst.ExitFailure {
|
||||
t.Fatalf("Cure: error = %v, want init exit status 1", err)
|
||||
}
|
||||
|
||||
var faultStatus []byte
|
||||
if faults, err := c.ReadFaults(initFailureArtifact); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if len(faults) != 1 {
|
||||
t.Fatalf("ReadFaults: %v", faults)
|
||||
} else if faultStatus, err = os.ReadFile(faults[0].String()); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if err = faults[0].Destroy(); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
t.Logf("destroyed expected fault at %s", faults[0].Time().UTC())
|
||||
}
|
||||
|
||||
if !bytes.HasPrefix(faultStatus, []byte(
|
||||
"internal/pkg ",
|
||||
)) || !bytes.Contains(faultStatus, []byte(
|
||||
"\ninit: fork/exec /opt/bin/testtool: no such file or directory\n",
|
||||
)) {
|
||||
t.Errorf("unexpected status:\n%s", string(faultStatus))
|
||||
}
|
||||
|
||||
destroyStatus(t, base, 2, 1)
|
||||
testtoolDestroy(t, base, c)
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
@@ -137,15 +183,19 @@ func TestExec(t *testing.T) {
|
||||
"checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400, Data: []byte{}},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/IY91PCtOpCYy21AaIK0c9f8-Z6fb2_2ewoHWkt4dxoLf0GOrWqS8yAGFLV84b1Dw": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||
"identifier/QwS7SmiatdqryQYgESdGw7Yw2PcpNf0vNfpvUA0t92BTlKiUjfCrXyMW17G2X77X": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
||||
"identifier/" + expected.Offline: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
{"net", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
{"net", pkg.CValidateKnown | checkDestroySubstitutes, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
testtool, testtoolDestroy := newTesttool()
|
||||
|
||||
wantNet := expectsFS{
|
||||
@@ -155,7 +205,7 @@ func TestExec(t *testing.T) {
|
||||
}
|
||||
cureMany(t, c, []cureStep{
|
||||
{"container", pkg.NewExec(
|
||||
"exec-net", "", new(wantNet.hash()), 0, false,
|
||||
"exec-net", "", new(wantNet.hash()), 0, true, false,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1"},
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
@@ -178,6 +228,7 @@ func TestExec(t *testing.T) {
|
||||
), ignorePathname, wantNet, nil},
|
||||
})
|
||||
|
||||
destroyStatus(t, base, 2, 0)
|
||||
testtoolDestroy(t, base, c)
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
@@ -193,16 +244,18 @@ func TestExec(t *testing.T) {
|
||||
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
{"overlay root", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
{"overlay root", pkg.CValidateKnown | checkDestroySubstitutes, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
testtool, testtoolDestroy := newTesttool()
|
||||
|
||||
cureMany(t, c, []cureStep{
|
||||
{"container", pkg.NewExec(
|
||||
"exec-overlay-root", "", nil, 0, false,
|
||||
"exec-overlay-root", "", nil, 0, false, false,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
@@ -219,6 +272,7 @@ func TestExec(t *testing.T) {
|
||||
), ignorePathname, wantOffline, nil},
|
||||
})
|
||||
|
||||
destroyStatus(t, base, 2, 0)
|
||||
testtoolDestroy(t, base, c)
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
@@ -232,16 +286,18 @@ func TestExec(t *testing.T) {
|
||||
"identifier/" + expected.OvlRoot: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
{"overlay work", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
{"overlay work", pkg.CValidateKnown | checkDestroySubstitutes, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
testtool, testtoolDestroy := newTesttool()
|
||||
|
||||
cureMany(t, c, []cureStep{
|
||||
{"container", pkg.NewExec(
|
||||
"exec-overlay-work", "", nil, 0, false,
|
||||
"exec-overlay-work", "", nil, 0, false, false,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
|
||||
check.MustAbs("/work/bin/testtool"),
|
||||
@@ -263,6 +319,7 @@ func TestExec(t *testing.T) {
|
||||
), ignorePathname, wantOffline, nil},
|
||||
})
|
||||
|
||||
destroyStatus(t, base, 2, 0)
|
||||
testtoolDestroy(t, base, c)
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
@@ -276,16 +333,18 @@ func TestExec(t *testing.T) {
|
||||
"identifier/" + expected.Work: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
{"multiple layers", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
{"multiple layers", pkg.CValidateKnown | checkDestroySubstitutes, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
testtool, testtoolDestroy := newTesttool()
|
||||
|
||||
cureMany(t, c, []cureStep{
|
||||
{"container", pkg.NewExec(
|
||||
"exec-multiple-layers", "", nil, 0, false,
|
||||
"exec-multiple-layers", "", nil, 0, false, false,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
@@ -329,6 +388,7 @@ func TestExec(t *testing.T) {
|
||||
), ignorePathname, wantOffline, nil},
|
||||
})
|
||||
|
||||
destroyStatus(t, base, 2, 0)
|
||||
testtoolDestroy(t, base, c)
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
@@ -347,16 +407,18 @@ func TestExec(t *testing.T) {
|
||||
"identifier/" + expected.Layers: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
{"overlay layer promotion", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
{"overlay layer promotion", pkg.CValidateKnown | checkDestroySubstitutes, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
testtool, testtoolDestroy := newTesttool()
|
||||
|
||||
cureMany(t, c, []cureStep{
|
||||
{"container", pkg.NewExec(
|
||||
"exec-layer-promotion", "", nil, 0, true,
|
||||
"exec-layer-promotion", "", nil, 0, false, true,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
@@ -379,6 +441,7 @@ func TestExec(t *testing.T) {
|
||||
), ignorePathname, wantOffline, nil},
|
||||
})
|
||||
|
||||
destroyStatus(t, base, 2, 0)
|
||||
testtoolDestroy(t, base, c)
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
@@ -393,18 +456,20 @@ func TestExec(t *testing.T) {
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
"identifier/" + expected.Promote: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
{"binfmt", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
{"binfmt", pkg.CValidateKnown | checkDestroySubstitutes, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
if info.CanDegrade && os.Getenv("ROSA_SKIP_BINFMT") != "" {
|
||||
t.Skip("binfmt_misc test explicitly skipped")
|
||||
}
|
||||
|
||||
cureMany(t, c, []cureStep{
|
||||
{"container", pkg.NewExec(
|
||||
"exec-binfmt", "cafe", nil, 0, true,
|
||||
"exec-binfmt", "cafe", nil, 0, false, true,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1", "HAKUREI_BINFMT=1"},
|
||||
check.MustAbs("/opt/bin/sample"),
|
||||
@@ -440,6 +505,8 @@ func TestExec(t *testing.T) {
|
||||
"check": {Mode: 0400, Data: []byte("binfmt")},
|
||||
}, nil},
|
||||
})
|
||||
|
||||
destroyStatus(t, base, 2, 0)
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
@@ -456,6 +523,8 @@ func TestExec(t *testing.T) {
|
||||
"identifier/_v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/5aevg3YpDxjqQZ-pdvXK7YqgkL5JKqcoStYQxeD96kuYar6K2mRQWMHib6NQRnpV")},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
@@ -29,6 +29,8 @@ func TestFile(t *testing.T) {
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/3376ALA7hIUm2LbzH2fDvRezgzod1eTK_G6XjyOgbM2u-6swvkFaF0BOwSl_juBi": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX")},
|
||||
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package expected
|
||||
|
||||
const (
|
||||
Offline = "oe7Uv1u5BwxcuX3HLQzZRg1Q5oetJo6jWiKGMOeqLiqBkaVgyKzvx82N81_IzUAz"
|
||||
Offline = "q5ktDTq0miP-VvB2blxqXQeaRXCUWgP_KbC18KNtUDtyoaI_h5mHmGuPMArVEBDs"
|
||||
OvlRoot = "NacZGXwuRkTvcHaG08a22ujJ8qCWN0RSoFlRSR5FSt0ZcBbJ28FRvkYsHEtX7G8i"
|
||||
Layers = "WBJDrATtX6rIE5yAu8ePX3WmDF0Tt9kFiue0m3cRnyRoVx1my8a67fh3CAW486oP"
|
||||
Net = "CmYtj2sNB3LHtqiDuck_Lz3MjLLIiwyP8N4NDitQ1Icvv__LVP9p8tm-sHeQaKKp"
|
||||
|
||||
10
internal/pkg/internal/testtool/expected/sum_arm64.go
Normal file
10
internal/pkg/internal/testtool/expected/sum_arm64.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package expected
|
||||
|
||||
const (
|
||||
Offline = "WapqyoPxbWSnq07dWHt71mHaJXq99pAjJfFlELlJljSiZMhTFqqlzU1_mN86shSj"
|
||||
OvlRoot = "V9anFOiRvjGfAeBhLl14AL8TKdWZyD0WTPYe4fS9mOBw8iW5Lmarvt6TG6MV8uWm"
|
||||
Layers = "tKx7JNRoSBdK_7MdzI-nwTNV2wmiPzwYdcd17oLmXKL_iLmUzUiA79qTqdrTasrv"
|
||||
Net = "aXyDLzBCJ9XltXZIfetEVsEkrqHfcXuD5XE_FcUnYbN3emwL55N6P8LlHzNfGnM5"
|
||||
Promote = "3k4V16n96Lq04gjFSKmm4sFjyQ883FFBNXgTy9s_DjeTwxT3pg_iacEh8yMb_S4m"
|
||||
Work = "6Q49MhFWRE3Ne6MycwAotgl1GtoU5WCHqJNWG2byYZCY-zX-IxPrWiKk7bKkNzhE"
|
||||
)
|
||||
10
internal/pkg/internal/testtool/expected/sum_riscv64.go
Normal file
10
internal/pkg/internal/testtool/expected/sum_riscv64.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package expected
|
||||
|
||||
const (
|
||||
Offline = "Z6yXE5gOJScL3srmnVMWgCXccDiUNZ5snSrf6RkXuU1_U0rX_kGVwsfHUgNG_awd"
|
||||
OvlRoot = "zYXJHFRLuxvUhuisZEXgGgVvdQd6piMfp5jmtT6jdVjvC2gICXquOq-UTwlrSD5I"
|
||||
Layers = "_F8EDazHbcLeT0sVSQXRN_kn9IjduqJcDYgzXpsT-hpKU4EBcZ0PISN2zchpqMbm"
|
||||
Net = "CA_FAaSIYJgapBEHV40doxpH23PdUEy_6s1TZc7wfSPN0XYqwGpMceXXDSabGveO"
|
||||
Promote = "_3LPrLp--4h9k4GsNNApu9hHtAafq-GUhfU6d4hJKBDKT3bz_szOsvkXxc5sK53d"
|
||||
Work = "FEgHeiCD_WT4wsfB-9kDH5n6cRWCEYtJmXdKZgmUUukAOoXumH_hLlosXREC-tqq"
|
||||
)
|
||||
@@ -76,6 +76,9 @@ type IContext struct {
|
||||
// Written to by various methods, should be zeroed after [Artifact.Params]
|
||||
// returns and must not be exposed directly.
|
||||
w io.Writer
|
||||
// Optional [Artifact] to cureRes cache, replaces [IRKindIdent] with
|
||||
// checksum values if non-nil.
|
||||
inputs map[Artifact]cureRes
|
||||
}
|
||||
|
||||
// irZero is a zero IR word.
|
||||
@@ -163,7 +166,15 @@ func (i *IContext) WriteIdent(a Artifact) {
|
||||
defer i.ic.putIdentBuf(buf)
|
||||
|
||||
IRKindIdent.encodeHeader(0).put(buf[:])
|
||||
*(*ID)(buf[wordSize:]) = i.ic.Ident(a).Value()
|
||||
if i.inputs != nil {
|
||||
res, ok := i.inputs[a]
|
||||
if !ok {
|
||||
panic(InvalidLookupError(i.ic.Ident(a).Value()))
|
||||
}
|
||||
*(*ID)(buf[wordSize:]) = res.checksum.Value()
|
||||
} else {
|
||||
*(*ID)(buf[wordSize:]) = i.ic.Ident(a).Value()
|
||||
}
|
||||
i.mustWrite(buf[:])
|
||||
}
|
||||
|
||||
@@ -207,19 +218,44 @@ func (i *IContext) WriteString(s string) {
|
||||
// Encode writes a deterministic, efficient representation of a to w and returns
|
||||
// the first non-nil error encountered while writing to w.
|
||||
func (ic *irCache) Encode(w io.Writer, a Artifact) (err error) {
|
||||
return ic.encode(w, a, nil)
|
||||
}
|
||||
|
||||
// encode implements Encode but replaces identifiers with their cured checksums
|
||||
// for a non-nil ident. Caller must acquire Cache.identMu.
|
||||
func (ic *irCache) encode(
|
||||
w io.Writer,
|
||||
a Artifact,
|
||||
inputs map[Artifact]cureRes,
|
||||
) (err error) {
|
||||
deps := a.Dependencies()
|
||||
idents := make([]*extIdent, len(deps))
|
||||
for i, d := range deps {
|
||||
dbuf, did := ic.unsafeIdent(d, true)
|
||||
if dbuf == nil {
|
||||
dbuf = ic.getIdentBuf()
|
||||
binary.LittleEndian.PutUint64(dbuf[:], uint64(d.Kind()))
|
||||
*(*ID)(dbuf[wordSize:]) = did.Value()
|
||||
} else {
|
||||
ic.storeIdent(d, dbuf)
|
||||
if inputs == nil {
|
||||
for i, d := range deps {
|
||||
dbuf, did := ic.unsafeIdent(d, true)
|
||||
if dbuf == nil {
|
||||
dbuf = ic.getIdentBuf()
|
||||
binary.LittleEndian.PutUint64(dbuf[:], uint64(d.Kind()))
|
||||
*(*ID)(dbuf[wordSize:]) = did.Value()
|
||||
} else {
|
||||
ic.storeIdent(d, dbuf)
|
||||
}
|
||||
defer ic.putIdentBuf(dbuf)
|
||||
idents[i] = dbuf
|
||||
}
|
||||
} else {
|
||||
for i, d := range deps {
|
||||
res, ok := inputs[d]
|
||||
if !ok {
|
||||
return InvalidLookupError(ic.Ident(d).Value())
|
||||
}
|
||||
|
||||
dbuf := ic.getIdentBuf()
|
||||
binary.LittleEndian.PutUint64(dbuf[:], uint64(d.Kind()))
|
||||
*(*ID)(dbuf[wordSize:]) = res.checksum.Value()
|
||||
defer ic.putIdentBuf(dbuf)
|
||||
idents[i] = dbuf
|
||||
}
|
||||
defer ic.putIdentBuf(dbuf)
|
||||
idents[i] = dbuf
|
||||
}
|
||||
slices.SortFunc(idents, func(a, b *extIdent) int {
|
||||
return bytes.Compare(a[:], b[:])
|
||||
@@ -244,7 +280,7 @@ func (ic *irCache) Encode(w io.Writer, a Artifact) (err error) {
|
||||
}
|
||||
|
||||
func() {
|
||||
i := IContext{ic, w}
|
||||
i := IContext{ic, w, inputs}
|
||||
|
||||
defer panicToError(&err)
|
||||
defer func() { i.ic, i.w = nil, nil }()
|
||||
|
||||
@@ -39,7 +39,7 @@ func TestIRRoundtrip(t *testing.T) {
|
||||
)},
|
||||
|
||||
{"exec offline", pkg.NewExec(
|
||||
"exec-offline", "", nil, 0, false,
|
||||
"exec-offline", "", nil, 0, false, false,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1"},
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
@@ -61,7 +61,7 @@ func TestIRRoundtrip(t *testing.T) {
|
||||
{"exec net", pkg.NewExec(
|
||||
"exec-net", "",
|
||||
(*pkg.Checksum)(bytes.Repeat([]byte{0xfc}, len(pkg.Checksum{}))),
|
||||
0, false,
|
||||
0, false, false,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1"},
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
@@ -80,6 +80,28 @@ func TestIRRoundtrip(t *testing.T) {
|
||||
)),
|
||||
)},
|
||||
|
||||
{"exec measured", pkg.NewExec(
|
||||
"exec-measured", "",
|
||||
(*pkg.Checksum)(bytes.Repeat([]byte{0xfd}, len(pkg.Checksum{}))),
|
||||
0, false, false,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1"},
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
[]string{"testtool", "measured"},
|
||||
|
||||
pkg.MustPath("/file", false, pkg.NewFile("file", []byte(
|
||||
"stub file",
|
||||
))), pkg.MustPath("/.hakurei", false, pkg.NewHTTPGetTar(
|
||||
nil, "file:///hakurei.tar",
|
||||
pkg.Checksum(bytes.Repeat([]byte{0xfd}, len(pkg.Checksum{}))),
|
||||
pkg.TarUncompressed,
|
||||
)), pkg.MustPath("/opt", false, pkg.NewHTTPGetTar(
|
||||
nil, "file:///testtool.tar.gz",
|
||||
pkg.Checksum(bytes.Repeat([]byte{0xfd}, len(pkg.Checksum{}))),
|
||||
pkg.TarGzip,
|
||||
)),
|
||||
)},
|
||||
|
||||
{"file anonymous", pkg.NewFile("", []byte{0})},
|
||||
{"file", pkg.NewFile("stub", []byte("stub"))},
|
||||
}
|
||||
@@ -110,6 +132,7 @@ func TestIRRoundtrip(t *testing.T) {
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -90,6 +90,7 @@ func TestHTTPGet(t *testing.T) {
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
@@ -159,6 +160,8 @@ func TestHTTPGet(t *testing.T) {
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/oM-2pUlk-mOxK1t3aMWZer69UdOQlAXiAgMrpZ1476VoOqpYVP1aGFS9_HYy-D8_": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU")},
|
||||
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
})
|
||||
|
||||
@@ -4,6 +4,7 @@ package pkg
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"cmp"
|
||||
"context"
|
||||
"crypto/sha512"
|
||||
"encoding/base64"
|
||||
@@ -15,6 +16,7 @@ import (
|
||||
"io/fs"
|
||||
"maps"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"slices"
|
||||
@@ -24,6 +26,7 @@ import (
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
"unique"
|
||||
"unsafe"
|
||||
|
||||
@@ -247,7 +250,14 @@ func (t *TContext) destroy(errP *error) {
|
||||
*errP = errors.Join(*errP, err)
|
||||
}
|
||||
if *errP != nil {
|
||||
*errP = errors.Join(*errP, os.Remove(t.statusPath.String()))
|
||||
*errP = errors.Join(*errP, os.Rename(
|
||||
t.statusPath.String(), t.cache.base.Append(
|
||||
dirFault,
|
||||
t.ids+"."+strconv.FormatUint(uint64(
|
||||
time.Now().UnixNano(),
|
||||
), 10),
|
||||
).String(),
|
||||
))
|
||||
}
|
||||
t.status = nil
|
||||
}
|
||||
@@ -508,33 +518,34 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
// fileLock is the file name appended to Cache.base for guaranteeing
|
||||
// exclusive access to the cache directory.
|
||||
// fileLock is the lock file for exclusive access to the cache directory.
|
||||
fileLock = "lock"
|
||||
// fileVariant is the file name appended to Cache.base holding the variant
|
||||
// identification string set by a prior call to [SetExtension].
|
||||
// fileVariant is a file holding the variant identification string set by a
|
||||
// prior call to [SetExtension].
|
||||
fileVariant = "variant"
|
||||
|
||||
// dirIdentifier is the directory name appended to Cache.base for storing
|
||||
// artifacts named after their [ID].
|
||||
// dirSubstitute holds symlinks to artifacts by checksum, named after their
|
||||
// substitute identifier.
|
||||
dirSubstitute = "substitute"
|
||||
// dirIdentifier holds symlinks to artifacts by checksum, named after their
|
||||
// IR-based identifier.
|
||||
dirIdentifier = "identifier"
|
||||
// dirChecksum is the directory name appended to Cache.base for storing
|
||||
// artifacts named after their [Checksum].
|
||||
// dirChecksum holds artifacts named after their [Checksum].
|
||||
dirChecksum = "checksum"
|
||||
// dirStatus is the directory name appended to Cache.base for storing
|
||||
// artifact metadata and logs named after their [ID].
|
||||
// dirStatus holds artifact metadata and logs named after their IR-based
|
||||
// identifier. For [FloodArtifact], the same file is also available under
|
||||
// its substitute identifier.
|
||||
dirStatus = "status"
|
||||
// dirFault holds status files of faulted cures.
|
||||
dirFault = "fault"
|
||||
|
||||
// dirWork is the directory name appended to Cache.base for working
|
||||
// pathnames set up during [Cache.Cure].
|
||||
// dirWork holds working pathnames set up during [Cache.Cure].
|
||||
dirWork = "work"
|
||||
// dirTemp is the directory name appended to Cache.base for scratch space
|
||||
// pathnames allocated during [Cache.Cure].
|
||||
// dirTemp holds scratch space allocated during [Cache.Cure].
|
||||
dirTemp = "temp"
|
||||
|
||||
// dirExecScratch is the directory name appended to Cache.base for scratch
|
||||
// space setting up the container started by [Cache.EnterExec]. Exclusivity
|
||||
// via Cache.inExec.
|
||||
// dirExecScratch is scratch space set up for the container started by
|
||||
// [Cache.EnterExec]. Exclusivity via Cache.inExec.
|
||||
dirExecScratch = "scratch"
|
||||
|
||||
// checksumLinknamePrefix is prepended to the encoded [Checksum] value
|
||||
@@ -621,6 +632,9 @@ const (
|
||||
// CSuppressInit arranges for verbose output of the container init to be
|
||||
// suppressed regardless of [message.Msg] state.
|
||||
CSuppressInit
|
||||
|
||||
// CIgnoreSubstitutes disables content-based dependency substitution.
|
||||
CIgnoreSubstitutes
|
||||
)
|
||||
|
||||
// toplevel holds [context.WithCancel] over caller-supplied context, where all
|
||||
@@ -676,6 +690,11 @@ type Cache struct {
|
||||
// Synchronises access to dirChecksum.
|
||||
checksumMu sync.RWMutex
|
||||
|
||||
// Presence of an alternative in the cache. Keys are not valid identifiers
|
||||
// and must not be used as such.
|
||||
substitute map[unique.Handle[ID]]unique.Handle[Checksum]
|
||||
// Synchronises access to substitute and corresponding filesystem entries.
|
||||
substituteMu sync.RWMutex
|
||||
// Identifier to content pair cache.
|
||||
ident map[unique.Handle[ID]]unique.Handle[Checksum]
|
||||
// Identifier to error pair for unrecoverably faulted [Artifact].
|
||||
@@ -886,11 +905,14 @@ func (c *Cache) Scrub(checks int) error {
|
||||
checks = runtime.NumCPU()
|
||||
}
|
||||
|
||||
c.substituteMu.Lock()
|
||||
defer c.substituteMu.Unlock()
|
||||
c.identMu.Lock()
|
||||
defer c.identMu.Unlock()
|
||||
c.checksumMu.Lock()
|
||||
defer c.checksumMu.Unlock()
|
||||
|
||||
c.substitute = make(map[unique.Handle[ID]]unique.Handle[Checksum])
|
||||
c.ident = make(map[unique.Handle[ID]]unique.Handle[Checksum])
|
||||
c.identErr = make(map[unique.Handle[ID]]error)
|
||||
c.artifact.Clear()
|
||||
@@ -998,47 +1020,52 @@ func (c *Cache) Scrub(checks int) error {
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
dir = c.base.Append(dirIdentifier)
|
||||
if entries, readdirErr := os.ReadDir(dir.String()); readdirErr != nil {
|
||||
addErr(dir, readdirErr)
|
||||
} else {
|
||||
wg.Add(len(entries))
|
||||
for _, ent := range entries {
|
||||
w <- checkEntry{ent, func(ent os.DirEntry, want *Checksum) bool {
|
||||
got := p.Get().(*Checksum)
|
||||
defer p.Put(got)
|
||||
for _, suffix := range []string{
|
||||
dirSubstitute,
|
||||
dirIdentifier,
|
||||
} {
|
||||
dir = c.base.Append(suffix)
|
||||
if entries, readdirErr := os.ReadDir(dir.String()); readdirErr != nil {
|
||||
addErr(dir, readdirErr)
|
||||
} else {
|
||||
wg.Add(len(entries))
|
||||
for _, ent := range entries {
|
||||
w <- checkEntry{ent, func(ent os.DirEntry, want *Checksum) bool {
|
||||
got := p.Get().(*Checksum)
|
||||
defer p.Put(got)
|
||||
|
||||
pathname := dir.Append(ent.Name())
|
||||
if linkname, err := os.Readlink(
|
||||
pathname.String(),
|
||||
); err != nil {
|
||||
seMu.Lock()
|
||||
se.Errs[pathname.Handle()] = append(se.Errs[pathname.Handle()], err)
|
||||
se.DanglingIdentifiers = append(se.DanglingIdentifiers, *want)
|
||||
seMu.Unlock()
|
||||
return false
|
||||
} else if err = Decode(got, filepath.Base(linkname)); err != nil {
|
||||
seMu.Lock()
|
||||
lnp := dir.Append(linkname)
|
||||
se.Errs[lnp.Handle()] = append(se.Errs[lnp.Handle()], err)
|
||||
se.DanglingIdentifiers = append(se.DanglingIdentifiers, *want)
|
||||
seMu.Unlock()
|
||||
return false
|
||||
}
|
||||
|
||||
if _, err := os.Stat(pathname.String()); err != nil {
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
addErr(pathname, err)
|
||||
pathname := dir.Append(ent.Name())
|
||||
if linkname, err := os.Readlink(
|
||||
pathname.String(),
|
||||
); err != nil {
|
||||
seMu.Lock()
|
||||
se.Errs[pathname.Handle()] = append(se.Errs[pathname.Handle()], err)
|
||||
se.DanglingIdentifiers = append(se.DanglingIdentifiers, *want)
|
||||
seMu.Unlock()
|
||||
return false
|
||||
} else if err = Decode(got, filepath.Base(linkname)); err != nil {
|
||||
seMu.Lock()
|
||||
lnp := dir.Append(linkname)
|
||||
se.Errs[lnp.Handle()] = append(se.Errs[lnp.Handle()], err)
|
||||
se.DanglingIdentifiers = append(se.DanglingIdentifiers, *want)
|
||||
seMu.Unlock()
|
||||
return false
|
||||
}
|
||||
seMu.Lock()
|
||||
se.DanglingIdentifiers = append(se.DanglingIdentifiers, *want)
|
||||
seMu.Unlock()
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}}
|
||||
|
||||
if _, err := os.Stat(pathname.String()); err != nil {
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
addErr(pathname, err)
|
||||
}
|
||||
seMu.Lock()
|
||||
se.DanglingIdentifiers = append(se.DanglingIdentifiers, *want)
|
||||
seMu.Unlock()
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}}
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
dir = c.base.Append(dirStatus)
|
||||
@@ -1186,6 +1213,52 @@ func (c *Cache) finaliseIdent(
|
||||
close(done)
|
||||
}
|
||||
|
||||
// zeroChecksum is a zero [Checksum] handle, used for comparison only.
|
||||
var zeroChecksum unique.Handle[Checksum]
|
||||
|
||||
// loadSubstitute returns a checksum corresponding to a substitute identifier,
|
||||
// or zeroChecksum if an alternative is not available.
|
||||
func (c *Cache) loadSubstitute(
|
||||
substitute unique.Handle[ID],
|
||||
) (unique.Handle[Checksum], error) {
|
||||
c.substituteMu.RLock()
|
||||
if checksum, ok := c.substitute[substitute]; ok {
|
||||
c.substituteMu.RUnlock()
|
||||
return checksum, nil
|
||||
}
|
||||
|
||||
linkname, err := os.Readlink(c.base.Append(
|
||||
dirSubstitute,
|
||||
Encode(substitute.Value()),
|
||||
).String())
|
||||
c.substituteMu.RUnlock()
|
||||
|
||||
if err != nil {
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
return zeroChecksum, err
|
||||
}
|
||||
|
||||
c.substituteMu.Lock()
|
||||
c.substitute[substitute] = zeroChecksum
|
||||
c.substituteMu.Unlock()
|
||||
return zeroChecksum, nil
|
||||
}
|
||||
|
||||
var checksum unique.Handle[Checksum]
|
||||
buf := c.getIdentBuf()
|
||||
err = Decode((*Checksum)(buf[:]), filepath.Base(linkname))
|
||||
if err == nil {
|
||||
checksum = unique.Make(Checksum(buf[:]))
|
||||
|
||||
c.substituteMu.Lock()
|
||||
c.substitute[substitute] = checksum
|
||||
c.substituteMu.Unlock()
|
||||
}
|
||||
c.putIdentBuf(buf)
|
||||
|
||||
return checksum, err
|
||||
}
|
||||
|
||||
// Done returns a channel that is closed when the ongoing cure of an [Artifact]
|
||||
// referred to by the specified identifier completes. Done may return nil if
|
||||
// no ongoing cure of the specified identifier exists.
|
||||
@@ -1420,8 +1493,8 @@ func (c *Cache) Cure(a Artifact) (
|
||||
|
||||
// CureError wraps a non-nil error returned attempting to cure an [Artifact].
|
||||
type CureError struct {
|
||||
Ident unique.Handle[ID]
|
||||
Err error
|
||||
A Artifact
|
||||
Err error
|
||||
}
|
||||
|
||||
// Unwrap returns the underlying error.
|
||||
@@ -1434,40 +1507,63 @@ func (e *CureError) Error() string { return e.Err.Error() }
|
||||
type DependencyCureError []*CureError
|
||||
|
||||
// unwrapM recursively expands underlying errors into a caller-supplied map.
|
||||
func (e *DependencyCureError) unwrapM(me map[unique.Handle[ID]]*CureError) {
|
||||
func (e *DependencyCureError) unwrapM(
|
||||
ctx context.Context,
|
||||
ir *IRCache,
|
||||
me map[unique.Handle[ID]]*CureError,
|
||||
) {
|
||||
for _, err := range *e {
|
||||
if _, ok := me[err.Ident]; ok {
|
||||
if ctx.Err() != nil {
|
||||
break
|
||||
}
|
||||
|
||||
id := ir.Ident(err.A)
|
||||
if _, ok := me[id]; ok {
|
||||
continue
|
||||
}
|
||||
if _e, ok := err.Err.(*DependencyCureError); ok {
|
||||
_e.unwrapM(me)
|
||||
_e.unwrapM(ctx, ir, me)
|
||||
continue
|
||||
}
|
||||
me[err.Ident] = err
|
||||
me[id] = err
|
||||
}
|
||||
}
|
||||
|
||||
// unwrap recursively expands and deduplicates underlying errors.
|
||||
func (e *DependencyCureError) unwrap() DependencyCureError {
|
||||
func (e *DependencyCureError) unwrap(
|
||||
ctx context.Context,
|
||||
ir *IRCache,
|
||||
) DependencyCureError {
|
||||
me := make(map[unique.Handle[ID]]*CureError)
|
||||
e.unwrapM(me)
|
||||
errs := slices.AppendSeq(
|
||||
make(DependencyCureError, 0, len(me)),
|
||||
maps.Values(me),
|
||||
)
|
||||
e.unwrapM(ctx, ir, me)
|
||||
type ent struct {
|
||||
id unique.Handle[ID]
|
||||
err *CureError
|
||||
}
|
||||
errs := make([]*ent, 0, len(me))
|
||||
for id, err := range me {
|
||||
errs = append(errs, &ent{id, err})
|
||||
}
|
||||
|
||||
var identBuf [2]ID
|
||||
slices.SortFunc(errs, func(a, b *CureError) int {
|
||||
identBuf[0], identBuf[1] = a.Ident.Value(), b.Ident.Value()
|
||||
slices.SortFunc(errs, func(a, b *ent) int {
|
||||
identBuf[0], identBuf[1] = a.id.Value(), b.id.Value()
|
||||
return slices.Compare(identBuf[0][:], identBuf[1][:])
|
||||
})
|
||||
|
||||
return errs
|
||||
_errs := make(DependencyCureError, len(errs))
|
||||
for i, v := range errs {
|
||||
_errs[i] = v.err
|
||||
}
|
||||
return _errs
|
||||
}
|
||||
|
||||
// Unwrap returns a deduplicated slice of underlying errors.
|
||||
func (e *DependencyCureError) Unwrap() []error {
|
||||
errs := e.unwrap()
|
||||
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
|
||||
defer cancel()
|
||||
|
||||
errs := e.unwrap(ctx, NewIR())
|
||||
_errs := make([]error, len(errs))
|
||||
for i, err := range errs {
|
||||
_errs[i] = err
|
||||
@@ -1477,14 +1573,23 @@ func (e *DependencyCureError) Unwrap() []error {
|
||||
|
||||
// Error returns a user-facing multiline error message.
|
||||
func (e *DependencyCureError) Error() string {
|
||||
errs := e.unwrap()
|
||||
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
|
||||
defer cancel()
|
||||
|
||||
ir := NewIR()
|
||||
errs := e.unwrap(ctx, ir)
|
||||
if len(errs) == 0 {
|
||||
return "invalid dependency cure outcome"
|
||||
}
|
||||
var buf strings.Builder
|
||||
buf.WriteString("errors curing dependencies:")
|
||||
for _, err := range errs {
|
||||
buf.WriteString("\n\t" + Encode(err.Ident.Value()) + ": " + err.Error())
|
||||
buf.WriteString("\n\t" +
|
||||
reportName(err.A, ir.Ident(err.A)) + ": " +
|
||||
err.Error())
|
||||
}
|
||||
if ctx.Err() != nil {
|
||||
buf.WriteString("\nerror resolution cancelled")
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
@@ -1654,16 +1759,44 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
|
||||
return
|
||||
}
|
||||
|
||||
var checksums string
|
||||
var (
|
||||
checksums string
|
||||
substitute unique.Handle[ID]
|
||||
alternative *check.Absolute
|
||||
)
|
||||
defer func() {
|
||||
if err == nil && checksums != "" {
|
||||
linkname := checksumLinknamePrefix + checksums
|
||||
|
||||
err = os.Symlink(
|
||||
checksumLinknamePrefix+checksums,
|
||||
linkname,
|
||||
pathname.String(),
|
||||
)
|
||||
if err == nil {
|
||||
err = zeroTimes(pathname.String())
|
||||
}
|
||||
|
||||
if err == nil && alternative != nil {
|
||||
c.substituteMu.Lock()
|
||||
err = os.Symlink(
|
||||
linkname,
|
||||
alternative.String(),
|
||||
)
|
||||
if errors.Is(err, os.ErrExist) {
|
||||
c.msg.Verbosef(
|
||||
"creating alternative over %s for artifact %s",
|
||||
Encode(substitute.Value()), ids,
|
||||
)
|
||||
err = nil
|
||||
}
|
||||
if err == nil {
|
||||
err = zeroTimes(alternative.String())
|
||||
}
|
||||
if err == nil && checksum != zeroChecksum {
|
||||
c.substitute[substitute] = checksum
|
||||
}
|
||||
c.substituteMu.Unlock()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -1860,11 +1993,64 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
|
||||
f.deps[deps[i]] = p
|
||||
}
|
||||
|
||||
sh := sha512.New384()
|
||||
err = c.encode(sh, a, f.deps)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf := c.getIdentBuf()
|
||||
sh.Sum(buf[wordSize:wordSize])
|
||||
substitute = unique.Make(ID(buf[wordSize:]))
|
||||
substitutes := Encode(substitute.Value())
|
||||
c.putIdentBuf(buf)
|
||||
alternative = c.base.Append(
|
||||
dirSubstitute,
|
||||
substitutes,
|
||||
)
|
||||
|
||||
if c.flags&CIgnoreSubstitutes == 0 {
|
||||
var substituteChecksum unique.Handle[Checksum]
|
||||
substituteChecksum, err = c.loadSubstitute(substitute)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if substituteChecksum != zeroChecksum {
|
||||
checksum = substituteChecksum
|
||||
checksums = Encode(checksum.Value())
|
||||
checksumPathname = c.base.Append(
|
||||
dirChecksum,
|
||||
checksums,
|
||||
)
|
||||
if _, err = os.Lstat(c.base.Append(
|
||||
dirStatus,
|
||||
substitutes,
|
||||
).String()); err == nil {
|
||||
err = os.Symlink(substitutes, c.base.Append(
|
||||
dirStatus,
|
||||
ids,
|
||||
).String())
|
||||
} else if errors.Is(err, os.ErrNotExist) {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
defer f.destroy(&err)
|
||||
if err = c.enterCure(a, curesExempt); err != nil {
|
||||
return
|
||||
}
|
||||
err = ca.Cure(&f)
|
||||
if err == nil && f.status != nil {
|
||||
err = os.Link(c.base.Append(
|
||||
dirStatus,
|
||||
ids,
|
||||
).String(), c.base.Append(
|
||||
dirStatus,
|
||||
substitutes,
|
||||
).String())
|
||||
}
|
||||
c.exitCure(a, curesExempt)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -1957,7 +2143,7 @@ func (pending *pendingArtifactDep) cure(c *Cache) {
|
||||
}
|
||||
|
||||
pending.errsMu.Lock()
|
||||
*pending.errs = append(*pending.errs, &CureError{c.Ident(pending.a), err})
|
||||
*pending.errs = append(*pending.errs, &CureError{pending.a, err})
|
||||
pending.errsMu.Unlock()
|
||||
}
|
||||
|
||||
@@ -1973,6 +2159,52 @@ func (c *Cache) OpenStatus(a Artifact) (r io.ReadSeekCloser, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Fault holds the pathname and termination time of an [Artifact] fault entry.
|
||||
type Fault struct {
|
||||
*check.Absolute
|
||||
t uint64
|
||||
}
|
||||
|
||||
// Time returns the instant in time where the fault occurred.
|
||||
func (f Fault) Time() time.Time { return time.Unix(0, int64(f.t)) }
|
||||
|
||||
// Open opens the underlying entry for reading.
|
||||
func (f Fault) Open() (io.ReadCloser, error) { return os.Open(f.Absolute.String()) }
|
||||
|
||||
// Destroy removes the underlying fault entry.
|
||||
func (f Fault) Destroy() error { return os.Remove(f.Absolute.String()) }
|
||||
|
||||
// ReadFaults returns fault entries for an [Artifact].
|
||||
func (c *Cache) ReadFaults(a Artifact) (faults []Fault, err error) {
|
||||
prefix := Encode(c.Ident(a).Value()) + "."
|
||||
var dents []os.DirEntry
|
||||
if dents, err = os.ReadDir(c.base.Append(dirFault).String()); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, dent := range dents {
|
||||
name := dent.Name()
|
||||
if !strings.HasPrefix(name, prefix) {
|
||||
continue
|
||||
}
|
||||
var t uint64
|
||||
t, err = strconv.ParseUint(name[len(prefix):], 10, 64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
faults = append(faults, Fault{c.base.Append(
|
||||
dirFault,
|
||||
name,
|
||||
), t})
|
||||
}
|
||||
|
||||
slices.SortFunc(faults, func(a, b Fault) int {
|
||||
return cmp.Compare(a.t, b.t)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Abort cancels all pending cures and waits for them to clean up, but does not
|
||||
// close the cache.
|
||||
func (c *Cache) Abort() {
|
||||
@@ -2072,9 +2304,11 @@ func open(
|
||||
}
|
||||
|
||||
for _, name := range []string{
|
||||
dirSubstitute,
|
||||
dirIdentifier,
|
||||
dirChecksum,
|
||||
dirStatus,
|
||||
dirFault,
|
||||
dirWork,
|
||||
} {
|
||||
if err := os.MkdirAll(
|
||||
@@ -2097,6 +2331,7 @@ func open(
|
||||
|
||||
irCache: zeroIRCache(),
|
||||
|
||||
substitute: make(map[unique.Handle[ID]]unique.Handle[Checksum]),
|
||||
ident: make(map[unique.Handle[ID]]unique.Handle[Checksum]),
|
||||
identErr: make(map[unique.Handle[ID]]error),
|
||||
identPending: make(map[unique.Handle[ID]]*pendingCure),
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"syscall"
|
||||
"testing"
|
||||
"testing/fstest"
|
||||
"time"
|
||||
"unique"
|
||||
"unsafe"
|
||||
|
||||
@@ -244,6 +245,41 @@ func newDestroyArtifactFunc(a pkg.Artifact) func(
|
||||
}
|
||||
}
|
||||
|
||||
// destroyStatus counts non-substitution status entries and destroys them.
|
||||
func destroyStatus(t *testing.T, base *check.Absolute, c, s int) {
|
||||
dents, err := os.ReadDir(base.Append("status").String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var gotC, gotS int
|
||||
for _, dent := range dents {
|
||||
if err = os.Remove(base.Append(
|
||||
"status",
|
||||
dent.Name(),
|
||||
).String()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if dent.Type().IsRegular() {
|
||||
gotC++
|
||||
continue
|
||||
}
|
||||
if dent.Type()&fs.ModeSymlink == fs.ModeSymlink {
|
||||
gotS++
|
||||
continue
|
||||
}
|
||||
t.Errorf("%s: %s", dent.Name(), dent.Type())
|
||||
}
|
||||
|
||||
if gotC != c {
|
||||
t.Errorf("status: c = %d, want %d", gotC, c)
|
||||
}
|
||||
if gotS != s {
|
||||
t.Errorf("status: s = %d, want %d", gotS, s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIdent(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -392,6 +428,12 @@ type cacheTestCase struct {
|
||||
want expectsFS
|
||||
}
|
||||
|
||||
const (
|
||||
// checkDestroySubstitutes arranges for substitutes to be destroyed before
|
||||
// measurement during checkWithCache.
|
||||
checkDestroySubstitutes = 1 << (iota + 32)
|
||||
)
|
||||
|
||||
// checkWithCache runs a slice of cacheTestCase.
|
||||
func checkWithCache(t *testing.T, testCases []cacheTestCase) {
|
||||
t.Helper()
|
||||
@@ -472,10 +514,27 @@ func checkWithCache(t *testing.T, testCases []cacheTestCase) {
|
||||
}
|
||||
}
|
||||
|
||||
// destroy non-deterministic status files
|
||||
if err := os.RemoveAll(base.Append("status").String()); err != nil {
|
||||
// destroy non-deterministic substitutes
|
||||
if tc.flags&checkDestroySubstitutes != 0 {
|
||||
substitute := base.Append("substitute")
|
||||
if err := os.RemoveAll(substitute.String()); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if err = os.Mkdir(substitute.String(), 0700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// destroy empty status directory
|
||||
if err := syscall.Rmdir(base.Append("status").String()); err != nil {
|
||||
t.Error(expectsFrom(base.Append("status").String()))
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// destroy empty fault directory
|
||||
if err := os.Remove(base.Append("fault").String()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
want := tc.want.hash()
|
||||
|
||||
var checksum pkg.Checksum
|
||||
@@ -539,6 +598,21 @@ func cureMany(t *testing.T, c *pkg.Cache, steps []cureStep) {
|
||||
for _, step := range steps {
|
||||
t.Log("cure step:", step.name)
|
||||
if pathname, checksum, err := c.Cure(step.a); !reflect.DeepEqual(err, step.err) {
|
||||
faults, _err := c.ReadFaults(step.a)
|
||||
if _err != nil {
|
||||
t.Errorf("ReadFaults: error = %v", _err)
|
||||
}
|
||||
|
||||
var p []byte
|
||||
for _, fault := range faults {
|
||||
p, _err = os.ReadFile(fault.String())
|
||||
if _err != nil {
|
||||
t.Error(_err)
|
||||
continue
|
||||
}
|
||||
t.Log(string(p))
|
||||
t.Logf("faulting cure terminated %s ago", time.Since(faults[0].Time()))
|
||||
}
|
||||
t.Fatalf("Cure: error = %v, want %v", err, step.err)
|
||||
} else if step.pathname != ignorePathname && !pathname.Is(step.pathname) {
|
||||
t.Fatalf("Cure: pathname = %q, want %q", pathname, step.pathname)
|
||||
@@ -635,6 +709,15 @@ func TestCache(t *testing.T) {
|
||||
"identifier",
|
||||
"cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe",
|
||||
)
|
||||
failingFile := newStubFile(
|
||||
pkg.KindHTTPGet,
|
||||
pkg.ID{0xff, 3},
|
||||
nil,
|
||||
nil, struct {
|
||||
_ []byte
|
||||
stub.UniqueError
|
||||
}{UniqueError: 0xbad},
|
||||
)
|
||||
|
||||
cureMany(t, c, []cureStep{
|
||||
{"initial file", newStubFile(
|
||||
@@ -716,22 +799,14 @@ func TestCache(t *testing.T) {
|
||||
{"noncomparable error", &stubArtifactF{
|
||||
kind: pkg.KindExec,
|
||||
params: []byte("artifact with dependency returning noncomparable error"),
|
||||
deps: []pkg.Artifact{newStubFile(
|
||||
pkg.KindHTTPGet,
|
||||
pkg.ID{0xff, 3},
|
||||
nil,
|
||||
nil, struct {
|
||||
_ []byte
|
||||
stub.UniqueError
|
||||
}{UniqueError: 0xbad},
|
||||
)},
|
||||
deps: []pkg.Artifact{failingFile},
|
||||
|
||||
cure: func(f *pkg.FContext) error {
|
||||
panic("attempting to cure impossible artifact")
|
||||
},
|
||||
}, nil, nil, &pkg.DependencyCureError{
|
||||
{
|
||||
Ident: unique.Make(pkg.ID{0xff, 3}),
|
||||
A: failingFile,
|
||||
Err: struct {
|
||||
_ []byte
|
||||
stub.UniqueError
|
||||
@@ -788,6 +863,8 @@ func TestCache(t *testing.T) {
|
||||
"identifier/cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
||||
"identifier/deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
||||
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
@@ -972,11 +1049,87 @@ func TestCache(t *testing.T) {
|
||||
}}, nil, nil, pkg.InvalidFileModeError(
|
||||
fs.ModeSymlink | 0777,
|
||||
)},
|
||||
|
||||
{"alternative", &stubArtifactF{
|
||||
kind: pkg.KindExec,
|
||||
params: []byte("substitutable artifact"),
|
||||
deps: []pkg.Artifact{newStubFile(
|
||||
pkg.KindHTTPGet,
|
||||
pkg.ID{0xff, 8},
|
||||
nil,
|
||||
[]byte("substitutable dependency"),
|
||||
nil,
|
||||
)},
|
||||
|
||||
cure: func(f *pkg.FContext) error {
|
||||
return makeSample(&f.TContext)
|
||||
},
|
||||
}, base.Append(
|
||||
"identifier",
|
||||
"xMDWovje7OfyIaDy_2VnjpKxRqSOQ_LoeD946t-3WsS2V2SeMJ7nDGrNfpa4Pbc-",
|
||||
), want, nil},
|
||||
|
||||
{"substitutable", &stubArtifactF{
|
||||
kind: pkg.KindExec,
|
||||
params: []byte("substitutable artifact"),
|
||||
deps: []pkg.Artifact{newStubFile(
|
||||
pkg.KindHTTPGet,
|
||||
pkg.ID{0xff, 10},
|
||||
nil,
|
||||
[]byte("substitutable dependency"),
|
||||
nil,
|
||||
)},
|
||||
|
||||
cure: func(f *pkg.FContext) error {
|
||||
panic("substitution missed")
|
||||
},
|
||||
}, base.Append(
|
||||
"identifier",
|
||||
"k2ilgG5KQ9NXnMoT2oB6NdwOnSPRn_H24oXQc4l6qOYIxIG9XfuEczeyrR8UEv_f",
|
||||
), want, nil},
|
||||
})
|
||||
|
||||
if c0, err := unsafeOpen(
|
||||
t.Context(),
|
||||
message.New(nil),
|
||||
0, 0, 0, base, false,
|
||||
); err != nil {
|
||||
t.Fatalf("open: error = %v", err)
|
||||
} else {
|
||||
t.Cleanup(c.Close)
|
||||
cureMany(t, c0, []cureStep{
|
||||
{"substitutable", &stubArtifactF{
|
||||
kind: pkg.KindExec,
|
||||
params: []byte("substitutable artifact"),
|
||||
deps: []pkg.Artifact{newStubFile(
|
||||
pkg.KindHTTPGet,
|
||||
pkg.ID{0xff, 0xff, 0xfd, 0xfd},
|
||||
nil,
|
||||
[]byte("substitutable dependency"),
|
||||
nil,
|
||||
)},
|
||||
|
||||
cure: func(f *pkg.FContext) error {
|
||||
panic("substitution missed")
|
||||
},
|
||||
}, base.Append(
|
||||
"identifier",
|
||||
"_EmV5nsYZ2UWHgRmLDMU8i-rJWDx-kv5_1pFrzQI7vMMCM5mAXivO8UZtVfOqMR_",
|
||||
), want, nil},
|
||||
})
|
||||
}
|
||||
|
||||
if dents, err := os.ReadDir(base.Append("status").String()); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if len(dents) > 0 {
|
||||
t.Errorf("ReadDir: %v", dents)
|
||||
}
|
||||
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/7lfQ4QwSpV8nw7IDh0JiQ_jqUPrPv3_Vfie034RxsSy-cy4vO8DVvxgpx2LW08oO": {Mode: 0400, Data: []byte("substitutable dependency")},
|
||||
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/check": {Mode: 0400, Data: []byte{0, 0}},
|
||||
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib": {Mode: fs.ModeDir | 0700},
|
||||
@@ -986,6 +1139,15 @@ func TestCache(t *testing.T) {
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
||||
"identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
||||
"identifier/_EmV5nsYZ2UWHgRmLDMU8i-rJWDx-kv5_1pFrzQI7vMMCM5mAXivO8UZtVfOqMR_": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
||||
"identifier/___9_QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/7lfQ4QwSpV8nw7IDh0JiQ_jqUPrPv3_Vfie034RxsSy-cy4vO8DVvxgpx2LW08oO")},
|
||||
"identifier/_wgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/7lfQ4QwSpV8nw7IDh0JiQ_jqUPrPv3_Vfie034RxsSy-cy4vO8DVvxgpx2LW08oO")},
|
||||
"identifier/_woAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/7lfQ4QwSpV8nw7IDh0JiQ_jqUPrPv3_Vfie034RxsSy-cy4vO8DVvxgpx2LW08oO")},
|
||||
"identifier/k2ilgG5KQ9NXnMoT2oB6NdwOnSPRn_H24oXQc4l6qOYIxIG9XfuEczeyrR8UEv_f": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
||||
"identifier/xMDWovje7OfyIaDy_2VnjpKxRqSOQ_LoeD946t-3WsS2V2SeMJ7nDGrNfpa4Pbc-": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
||||
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
"substitute/OyBGorh72Z9kVw35JUa8FbqDbpR4DqT-MX1jic0uKN5PdYmUBiAF38BRsIRnBigf": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
||||
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
@@ -1061,6 +1223,7 @@ func TestCache(t *testing.T) {
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
@@ -1119,6 +1282,7 @@ func TestCache(t *testing.T) {
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
@@ -1180,6 +1344,8 @@ func TestCache(t *testing.T) {
|
||||
"identifier/_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M")},
|
||||
"identifier/_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M")},
|
||||
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
@@ -1230,6 +1396,7 @@ func TestCache(t *testing.T) {
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
}
|
||||
@@ -1409,6 +1576,14 @@ errors during scrub:
|
||||
func TestDependencyCureError(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
makeIdent := func(ident ...byte) pkg.Artifact {
|
||||
var a overrideIdent
|
||||
copy(a.id[:], ident)
|
||||
// does not compare equal
|
||||
a.TrivialArtifact = new(stubArtifact)
|
||||
return a
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
err pkg.DependencyCureError
|
||||
@@ -1416,51 +1591,51 @@ func TestDependencyCureError(t *testing.T) {
|
||||
unwrap []error
|
||||
}{
|
||||
{"simple", pkg.DependencyCureError{
|
||||
{Ident: unique.Make(pkg.ID{0xff, 9}), Err: stub.UniqueError(0xbad09)},
|
||||
{Ident: unique.Make(pkg.ID{0xff, 0}), Err: stub.UniqueError(0xbad00)},
|
||||
{Ident: unique.Make(pkg.ID{0xff, 0xf}), Err: stub.UniqueError(0xbad0f)},
|
||||
{Ident: unique.Make(pkg.ID{0xff, 1}), Err: stub.UniqueError(0xbad01)},
|
||||
{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
|
||||
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
|
||||
{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)},
|
||||
{A: makeIdent(0xff, 1), Err: stub.UniqueError(0xbad01)},
|
||||
}, `errors curing dependencies:
|
||||
_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765184 injected by the test suite
|
||||
_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765185 injected by the test suite
|
||||
_wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765193 injected by the test suite
|
||||
_w8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765199 injected by the test suite`, []error{
|
||||
&pkg.CureError{Ident: unique.Make(pkg.ID{0xff, 0}), Err: stub.UniqueError(0xbad00)},
|
||||
&pkg.CureError{Ident: unique.Make(pkg.ID{0xff, 1}), Err: stub.UniqueError(0xbad01)},
|
||||
&pkg.CureError{Ident: unique.Make(pkg.ID{0xff, 9}), Err: stub.UniqueError(0xbad09)},
|
||||
&pkg.CureError{Ident: unique.Make(pkg.ID{0xff, 0xf}), Err: stub.UniqueError(0xbad0f)},
|
||||
&pkg.CureError{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
|
||||
&pkg.CureError{A: makeIdent(0xff, 1), Err: stub.UniqueError(0xbad01)},
|
||||
&pkg.CureError{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
|
||||
&pkg.CureError{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)},
|
||||
}},
|
||||
|
||||
{"dedup", pkg.DependencyCureError{
|
||||
{Ident: unique.Make(pkg.ID{0xff, 9}), Err: stub.UniqueError(0xbad09)},
|
||||
{Ident: unique.Make(pkg.ID{0xff, 0}), Err: stub.UniqueError(0xbad00)},
|
||||
{Ident: unique.Make(pkg.ID{0xff, 0xfd}), Err: &pkg.DependencyCureError{
|
||||
{Ident: unique.Make(pkg.ID{0xff, 9}), Err: stub.UniqueError(0xbad09)},
|
||||
{Ident: unique.Make(pkg.ID{0xff, 0xc}), Err: &pkg.DependencyCureError{
|
||||
{Ident: unique.Make(pkg.ID{0xff, 0xf}), Err: stub.UniqueError(0xbad0f)},
|
||||
{Ident: unique.Make(pkg.ID{0xff, 0}), Err: stub.UniqueError(0xbad00)},
|
||||
{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
|
||||
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
|
||||
{A: makeIdent(0xff, 0xfd), Err: &pkg.DependencyCureError{
|
||||
{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
|
||||
{A: makeIdent(0xff, 0xc), Err: &pkg.DependencyCureError{
|
||||
{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)},
|
||||
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
|
||||
}},
|
||||
{Ident: unique.Make(pkg.ID{0xff, 0}), Err: stub.UniqueError(0xbad00)},
|
||||
{Ident: unique.Make(pkg.ID{0xff, 0}), Err: stub.UniqueError(0xbad00)},
|
||||
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
|
||||
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
|
||||
}},
|
||||
{Ident: unique.Make(pkg.ID{0xff, 0xff}), Err: &pkg.DependencyCureError{
|
||||
{Ident: unique.Make(pkg.ID{0xff, 9}), Err: stub.UniqueError(0xbad09)},
|
||||
{Ident: unique.Make(pkg.ID{0xff, 0xc}), Err: &pkg.DependencyCureError{
|
||||
{Ident: unique.Make(pkg.ID{0xff, 0}), Err: stub.UniqueError(0xbad00)},
|
||||
{A: makeIdent(0xff, 0xff), Err: &pkg.DependencyCureError{
|
||||
{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
|
||||
{A: makeIdent(0xff, 0xc), Err: &pkg.DependencyCureError{
|
||||
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
|
||||
}},
|
||||
{Ident: unique.Make(pkg.ID{0xff, 0}), Err: stub.UniqueError(0xbad00)},
|
||||
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
|
||||
}},
|
||||
{Ident: unique.Make(pkg.ID{0xff, 0xf}), Err: stub.UniqueError(0xbad0f)},
|
||||
{Ident: unique.Make(pkg.ID{0xff, 1}), Err: stub.UniqueError(0xbad01)},
|
||||
{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)},
|
||||
{A: makeIdent(0xff, 1), Err: stub.UniqueError(0xbad01)},
|
||||
}, `errors curing dependencies:
|
||||
_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765184 injected by the test suite
|
||||
_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765185 injected by the test suite
|
||||
_wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765193 injected by the test suite
|
||||
_w8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765199 injected by the test suite`, []error{
|
||||
&pkg.CureError{Ident: unique.Make(pkg.ID{0xff, 0}), Err: stub.UniqueError(0xbad00)},
|
||||
&pkg.CureError{Ident: unique.Make(pkg.ID{0xff, 1}), Err: stub.UniqueError(0xbad01)},
|
||||
&pkg.CureError{Ident: unique.Make(pkg.ID{0xff, 9}), Err: stub.UniqueError(0xbad09)},
|
||||
&pkg.CureError{Ident: unique.Make(pkg.ID{0xff, 0xf}), Err: stub.UniqueError(0xbad0f)},
|
||||
&pkg.CureError{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
|
||||
&pkg.CureError{A: makeIdent(0xff, 1), Err: stub.UniqueError(0xbad01)},
|
||||
&pkg.CureError{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
|
||||
&pkg.CureError{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)},
|
||||
}},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
@@ -1501,6 +1676,25 @@ func (a earlyFailureF) Cure(*pkg.FContext) error {
|
||||
return stub.UniqueError(0xcafe)
|
||||
}
|
||||
|
||||
func BenchmarkEarlyDCE(b *testing.B) {
|
||||
msg := message.New(log.New(os.Stderr, "dce: ", 0))
|
||||
msg.SwapVerbose(testing.Verbose())
|
||||
c, err := pkg.Open(b.Context(), msg, 0, 0, 0, check.MustAbs(b.TempDir()))
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
_, _, err = c.Cure(earlyFailureF(8))
|
||||
if !errors.Is(err, stub.UniqueError(0xcafe)) {
|
||||
b.Fatalf("Cure: error = %v", err)
|
||||
}
|
||||
c.Close()
|
||||
dce := err.(*pkg.DependencyCureError)
|
||||
|
||||
for b.Loop() {
|
||||
dce.Unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
func TestDependencyCureErrorEarly(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -1514,6 +1708,7 @@ func TestDependencyCureErrorEarly(t *testing.T) {
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
})
|
||||
|
||||
@@ -83,6 +83,8 @@ func TestTar(t *testing.T) {
|
||||
"identifier/W5S65DEhawz_WKaok5NjUKLmnD9dNl5RPauNJjcOVcB3VM4eGhSaLGmXbL8vZpiw": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantEncode)},
|
||||
"identifier/rg7F1D5hwv6o4xctjD5zDq4i5MD0mArTsUIWfhUbik8xC6Bsyt3mjXXOm3goojTz": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantEncode)},
|
||||
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
@@ -105,6 +107,8 @@ func TestTar(t *testing.T) {
|
||||
"identifier/W5S65DEhawz_WKaok5NjUKLmnD9dNl5RPauNJjcOVcB3VM4eGhSaLGmXbL8vZpiw": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantExpandEncode)},
|
||||
"identifier/_v1blm2h-_KA-dVaawdpLas6MjHc6rbhhFS8JWwx8iJxZGUu8EBbRrhr5AaZ9PJL": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantExpandEncode)},
|
||||
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newAttr() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.5.2"
|
||||
checksum = "YWEphrz6vg1sUMmHHVr1CRo53pFXRhq_pjN-AlG8UgwZK1y6m7zuDhxqJhD0SV0l"
|
||||
)
|
||||
return t.NewPackage("attr", version, newTar(
|
||||
"https://download.savannah.nongnu.org/releases/attr/"+
|
||||
"attr-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), &PackageAttr{
|
||||
Patches: []KV{
|
||||
{"libgen-basename", `From 8a80d895dfd779373363c3a4b62ecce5a549efb2 Mon Sep 17 00:00:00 2001
|
||||
From: "Haelwenn (lanodan) Monnier" <contact@hacktivis.me>
|
||||
Date: Sat, 30 Mar 2024 10:17:10 +0100
|
||||
Subject: tools/attr.c: Add missing libgen.h include for basename(3)
|
||||
|
||||
Fixes compilation issue with musl and modern C99 compilers.
|
||||
|
||||
See: https://bugs.gentoo.org/926294
|
||||
---
|
||||
tools/attr.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/tools/attr.c b/tools/attr.c
|
||||
index f12e4af..6a3c1e9 100644
|
||||
--- a/tools/attr.c
|
||||
+++ b/tools/attr.c
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
+#include <libgen.h>
|
||||
|
||||
#include <attr/attributes.h>
|
||||
|
||||
--
|
||||
cgit v1.1`},
|
||||
|
||||
{"musl-errno", `diff --git a/test/attr.test b/test/attr.test
|
||||
index 6ce2f9b..e9bde92 100644
|
||||
--- a/test/attr.test
|
||||
+++ b/test/attr.test
|
||||
@@ -11,7 +11,7 @@ Try various valid and invalid names
|
||||
|
||||
$ touch f
|
||||
$ setfattr -n user -v value f
|
||||
- > setfattr: f: Operation not supported
|
||||
+ > setfattr: f: Not supported
|
||||
|
||||
$ setfattr -n user. -v value f
|
||||
> setfattr: f: Invalid argument
|
||||
`},
|
||||
},
|
||||
|
||||
ScriptEarly: `
|
||||
ln -s ../../system/bin/perl /usr/bin
|
||||
`,
|
||||
}, (*MakeHelper)(nil),
|
||||
Perl,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Attr] = Metadata{
|
||||
f: Toolchain.newAttr,
|
||||
|
||||
Name: "attr",
|
||||
Description: "Commands for Manipulating Filesystem Extended Attributes",
|
||||
Website: "https://savannah.nongnu.org/projects/attr/",
|
||||
|
||||
ID: 137,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newACL() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.3.2"
|
||||
checksum = "-fY5nwH4K8ZHBCRXrzLdguPkqjKI6WIiGu4dBtrZ1o0t6AIU73w8wwJz_UyjIS0P"
|
||||
)
|
||||
return t.NewPackage("acl", version, newTar(
|
||||
"https://download.savannah.nongnu.org/releases/acl/"+
|
||||
"acl-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, &MakeHelper{
|
||||
// makes assumptions about uid_map/gid_map
|
||||
SkipCheck: true,
|
||||
},
|
||||
Attr,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[ACL] = Metadata{
|
||||
f: Toolchain.newACL,
|
||||
|
||||
Name: "acl",
|
||||
Description: "Commands for Manipulating POSIX Access Control Lists",
|
||||
Website: "https://savannah.nongnu.org/projects/acl/",
|
||||
|
||||
Dependencies: P{
|
||||
Attr,
|
||||
},
|
||||
|
||||
ID: 16,
|
||||
}
|
||||
}
|
||||
@@ -1,424 +0,0 @@
|
||||
package rosa
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
// PArtifact is a lazily-initialised [pkg.Artifact] preset.
|
||||
type PArtifact int
|
||||
|
||||
const (
|
||||
LLVM PArtifact = iota
|
||||
|
||||
// EarlyInit is the Rosa OS init program.
|
||||
EarlyInit
|
||||
// ImageSystem is the Rosa OS /system image.
|
||||
ImageSystem
|
||||
// ImageInitramfs is the Rosa OS initramfs archive.
|
||||
ImageInitramfs
|
||||
|
||||
// Kernel is the generic Rosa OS Linux kernel.
|
||||
Kernel
|
||||
// KernelHeaders is an installation of kernel headers for [Kernel].
|
||||
KernelHeaders
|
||||
// KernelSource is a writable kernel source tree installed to [AbsUsrSrc].
|
||||
KernelSource
|
||||
// Firmware is firmware blobs for use with the Linux kernel.
|
||||
Firmware
|
||||
|
||||
ACL
|
||||
ArgpStandalone
|
||||
Attr
|
||||
Autoconf
|
||||
Automake
|
||||
BC
|
||||
Bash
|
||||
Binutils
|
||||
Bison
|
||||
Bzip2
|
||||
CMake
|
||||
Connman
|
||||
Coreutils
|
||||
Curl
|
||||
DBus
|
||||
DTC
|
||||
Diffutils
|
||||
Elfutils
|
||||
Fakeroot
|
||||
Findutils
|
||||
Flex
|
||||
Fuse
|
||||
GMP
|
||||
GLib
|
||||
Gawk
|
||||
GenInitCPIO
|
||||
Gettext
|
||||
Git
|
||||
Glslang
|
||||
GnuTLS
|
||||
Go
|
||||
Gperf
|
||||
Grep
|
||||
Gzip
|
||||
Hakurei
|
||||
HakureiDist
|
||||
Hwdata
|
||||
IPTables
|
||||
Kmod
|
||||
LIT
|
||||
LibX11
|
||||
LibXau
|
||||
LibXext
|
||||
LibXrandr
|
||||
LibXrender
|
||||
LibXxf86vm
|
||||
Libarchive
|
||||
Libbsd
|
||||
Libcap
|
||||
Libconfig
|
||||
LibdisplayInfo
|
||||
Libdrm
|
||||
Libev
|
||||
Libexpat
|
||||
Libffi
|
||||
Libgd
|
||||
Libglvnd
|
||||
Libiconv
|
||||
Libmd
|
||||
Libmnl
|
||||
Libnftnl
|
||||
Libpciaccess
|
||||
Libpng
|
||||
Libpsl
|
||||
Libseccomp
|
||||
Libtasn1
|
||||
Libtool
|
||||
Libucontext
|
||||
Libunistring
|
||||
Libxshmfence
|
||||
Libxml2
|
||||
Libxslt
|
||||
Libxtrans
|
||||
M4
|
||||
MPC
|
||||
MPFR
|
||||
Make
|
||||
Meson
|
||||
Mksh
|
||||
MuslFts
|
||||
MuslObstack
|
||||
NSS
|
||||
NSSCACert
|
||||
Ncurses
|
||||
Nettle
|
||||
Ninja
|
||||
OpenSSL
|
||||
P11Kit
|
||||
PCRE2
|
||||
Parallel
|
||||
Patch
|
||||
Perl
|
||||
PerlLocaleGettext
|
||||
PerlMIMECharset
|
||||
PerlModuleBuild
|
||||
PerlPodParser
|
||||
PerlSGMLS
|
||||
PerlTermReadKey
|
||||
PerlTextCharWidth
|
||||
PerlTextWrapI18N
|
||||
PerlUnicodeLineBreak
|
||||
PerlYAMLTiny
|
||||
PkgConfig
|
||||
Procps
|
||||
Python
|
||||
PythonFlitCore
|
||||
PythonHatchling
|
||||
PythonIniConfig
|
||||
PythonMako
|
||||
PythonMarkupSafe
|
||||
PythonPackaging
|
||||
PythonPathspec
|
||||
PythonPluggy
|
||||
PythonPyTest
|
||||
PythonPyYAML
|
||||
PythonPycparser
|
||||
PythonPygments
|
||||
PythonSetuptools
|
||||
PythonSetuptoolsSCM
|
||||
PythonTroveClassifiers
|
||||
PythonVCSVersioning
|
||||
PythonWheel
|
||||
QEMU
|
||||
Rdfind
|
||||
Readline
|
||||
Rsync
|
||||
Sed
|
||||
SPIRVHeaders
|
||||
SPIRVLLVMTranslator
|
||||
SPIRVTools
|
||||
SquashfsTools
|
||||
Strace
|
||||
TamaGo
|
||||
Tar
|
||||
Texinfo
|
||||
Toybox
|
||||
toyboxEarly
|
||||
Unzip
|
||||
UtilLinux
|
||||
Wayland
|
||||
WaylandProtocols
|
||||
XCB
|
||||
XCBProto
|
||||
XCBUtilKeysyms
|
||||
XDGDBusProxy
|
||||
XZ
|
||||
XorgProto
|
||||
Zlib
|
||||
Zstd
|
||||
|
||||
// PresetUnexportedStart is the first unexported preset.
|
||||
PresetUnexportedStart
|
||||
|
||||
stage0Dist = iota - 1
|
||||
llvmSource
|
||||
// earlyCompilerRT is an early, standalone compiler-rt installation for the
|
||||
// standalone runtimes build.
|
||||
//
|
||||
// earlyCompilerRT must only be loaded by [LLVM].
|
||||
earlyCompilerRT
|
||||
// earlyRuntimes is an early, standalone installation of LLVM runtimes to
|
||||
// work around the cmake build system leaking the system LLVM installation
|
||||
// when invoking the newly built toolchain.
|
||||
//
|
||||
// earlyRuntimes must only be loaded by [LLVM].
|
||||
earlyRuntimes
|
||||
|
||||
buildcatrust
|
||||
utilMacros
|
||||
|
||||
// Musl is a standalone libc that does not depend on the toolchain.
|
||||
Musl
|
||||
// muslHeaders is a system installation of [Musl] headers.
|
||||
muslHeaders
|
||||
|
||||
// gcc is a hacked-to-pieces GCC toolchain meant for use in intermediate
|
||||
// stages only. This preset and its direct output must never be exposed.
|
||||
gcc
|
||||
|
||||
// nettle3 is an older version of [Nettle].
|
||||
nettle3
|
||||
|
||||
// Stage0 is a tarball containing all compile-time dependencies of artifacts
|
||||
// part of the [Std] toolchain.
|
||||
Stage0
|
||||
|
||||
// PresetEnd is the total number of presets and does not denote a preset.
|
||||
PresetEnd
|
||||
)
|
||||
|
||||
// P represents multiple [PArtifact] and is stable through JSON.
|
||||
type P []PArtifact
|
||||
|
||||
// MarshalJSON represents [PArtifact] by their [Metadata.Name].
|
||||
func (s P) MarshalJSON() ([]byte, error) {
|
||||
names := make([]string, len(s))
|
||||
for i, p := range s {
|
||||
names[i] = GetMetadata(p).Name
|
||||
}
|
||||
return json.Marshal(names)
|
||||
}
|
||||
|
||||
// UnmarshalJSON resolves the value created by MarshalJSON back to [P].
|
||||
func (s *P) UnmarshalJSON(data []byte) error {
|
||||
var names []string
|
||||
if err := json.Unmarshal(data, &names); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*s = make(P, len(names))
|
||||
for i, name := range names {
|
||||
if p, ok := ResolveName(name); !ok {
|
||||
return fmt.Errorf("unknown artifact %q", name)
|
||||
} else {
|
||||
(*s)[i] = p
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Metadata is stage-agnostic information of a [PArtifact] not directly
|
||||
// representable in the resulting [pkg.Artifact].
|
||||
type Metadata struct {
|
||||
f func(t Toolchain) (a pkg.Artifact, version string)
|
||||
|
||||
// Unique package name.
|
||||
Name string `json:"name"`
|
||||
// Short user-facing description.
|
||||
Description string `json:"description"`
|
||||
// Project home page.
|
||||
Website string `json:"website,omitempty"`
|
||||
|
||||
// Runtime dependencies.
|
||||
Dependencies P `json:"dependencies"`
|
||||
|
||||
// Project identifier on [Anitya].
|
||||
//
|
||||
// [Anitya]: https://release-monitoring.org/
|
||||
ID int `json:"-"`
|
||||
|
||||
// Optional custom version checking behaviour.
|
||||
latest func(v *Versions) string
|
||||
}
|
||||
|
||||
// GetLatest returns the latest version described by v.
|
||||
func (meta *Metadata) GetLatest(v *Versions) string {
|
||||
if meta.latest != nil {
|
||||
return meta.latest(v)
|
||||
}
|
||||
return v.Latest
|
||||
}
|
||||
|
||||
// Unversioned denotes an unversioned [PArtifact].
|
||||
const Unversioned = "\x00"
|
||||
|
||||
// UnpopulatedIDError is returned by [Metadata.GetLatest] for an instance of
|
||||
// [Metadata] where ID is not populated.
|
||||
type UnpopulatedIDError struct{}
|
||||
|
||||
func (UnpopulatedIDError) Unwrap() error { return errors.ErrUnsupported }
|
||||
func (UnpopulatedIDError) Error() string { return "Anitya ID is not populated" }
|
||||
|
||||
// Versions are package versions returned by Anitya.
|
||||
type Versions struct {
|
||||
// The latest version for the project, as determined by the version sorting algorithm.
|
||||
Latest string `json:"latest_version"`
|
||||
// List of all versions that aren’t flagged as pre-release.
|
||||
Stable []string `json:"stable_versions"`
|
||||
// List of all versions stored, sorted from newest to oldest.
|
||||
All []string `json:"versions"`
|
||||
}
|
||||
|
||||
// getStable returns the first Stable version, or Latest if that is unavailable.
|
||||
func (v *Versions) getStable() string {
|
||||
if len(v.Stable) == 0 {
|
||||
return v.Latest
|
||||
}
|
||||
return v.Stable[0]
|
||||
}
|
||||
|
||||
// GetVersions returns versions fetched from Anitya.
|
||||
func (meta *Metadata) GetVersions(ctx context.Context) (*Versions, error) {
|
||||
if meta.ID == 0 {
|
||||
return nil, UnpopulatedIDError{}
|
||||
}
|
||||
|
||||
var resp *http.Response
|
||||
if req, err := http.NewRequestWithContext(
|
||||
ctx,
|
||||
http.MethodGet,
|
||||
"https://release-monitoring.org/api/v2/versions/?project_id="+
|
||||
strconv.Itoa(meta.ID),
|
||||
nil,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
req.Header.Set("User-Agent", "Rosa/1.1")
|
||||
if resp, err = http.DefaultClient.Do(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var v Versions
|
||||
err := json.NewDecoder(resp.Body).Decode(&v)
|
||||
return &v, errors.Join(err, resp.Body.Close())
|
||||
}
|
||||
|
||||
var (
|
||||
// artifactsM is an array of [PArtifact] metadata.
|
||||
artifactsM [PresetEnd]Metadata
|
||||
|
||||
// artifacts stores the result of Metadata.f.
|
||||
artifacts [_toolchainEnd][len(artifactsM)]struct {
|
||||
a pkg.Artifact
|
||||
v string
|
||||
}
|
||||
// artifactsOnce is for lazy initialisation of artifacts.
|
||||
artifactsOnce [_toolchainEnd][len(artifactsM)]sync.Once
|
||||
|
||||
// arch is the target architecture.
|
||||
arch = runtime.GOARCH
|
||||
|
||||
// presetOpts globally modifies behaviour of presets.
|
||||
presetOpts int
|
||||
)
|
||||
|
||||
const (
|
||||
// OptSkipCheck skips running all test suites.
|
||||
OptSkipCheck = 1 << iota
|
||||
// OptLLVMNoLTO disables LTO in all [LLVM] stages.
|
||||
OptLLVMNoLTO
|
||||
)
|
||||
|
||||
// Arch returns the target architecture.
|
||||
func Arch() string { return arch }
|
||||
|
||||
// Flags returns the current preset flags
|
||||
func Flags() int { return presetOpts }
|
||||
|
||||
// zero zeros the value pointed to by p.
|
||||
func zero[T any](p *T) { var v T; *p = v }
|
||||
|
||||
// DropCaches arranges for all cached [pkg.Artifact] to be freed some time after
|
||||
// it returns. Must not be used concurrently with any other function from this
|
||||
// package.
|
||||
func DropCaches(targetArch string, flags int) {
|
||||
if targetArch == "" {
|
||||
targetArch = runtime.GOARCH
|
||||
}
|
||||
|
||||
arch = targetArch
|
||||
presetOpts = flags
|
||||
zero(&artifacts)
|
||||
zero(&artifactsOnce)
|
||||
}
|
||||
|
||||
// GetMetadata returns [Metadata] of a [PArtifact].
|
||||
func GetMetadata(p PArtifact) *Metadata { return &artifactsM[p] }
|
||||
|
||||
// construct constructs a [pkg.Artifact] corresponding to a [PArtifact] once.
|
||||
func (t Toolchain) construct(p PArtifact) {
|
||||
artifactsOnce[t][p].Do(func() {
|
||||
artifacts[t][p].a, artifacts[t][p].v = artifactsM[p].f(t)
|
||||
})
|
||||
}
|
||||
|
||||
// Load returns the resulting [pkg.Artifact] of [PArtifact].
|
||||
func (t Toolchain) Load(p PArtifact) pkg.Artifact {
|
||||
t.construct(p)
|
||||
return artifacts[t][p].a
|
||||
}
|
||||
|
||||
// Version returns the version string of [PArtifact].
|
||||
func (t Toolchain) Version(p PArtifact) string {
|
||||
t.construct(p)
|
||||
return artifacts[t][p].v
|
||||
}
|
||||
|
||||
// ResolveName returns a [PArtifact] by name.
|
||||
func ResolveName(name string) (p PArtifact, ok bool) {
|
||||
for i := range PresetUnexportedStart {
|
||||
if name == artifactsM[i].Name {
|
||||
return i, true
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package rosa_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"hakurei.app/internal/rosa"
|
||||
)
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for i := range rosa.PresetEnd {
|
||||
p := rosa.PArtifact(i)
|
||||
t.Run(rosa.GetMetadata(p).Name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
rosa.Std.Load(p)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAll(b *testing.B) {
|
||||
arch, flags := rosa.Arch(), rosa.Flags()
|
||||
b.Cleanup(func() { rosa.DropCaches(arch, flags) })
|
||||
|
||||
for b.Loop() {
|
||||
for i := range rosa.PresetEnd {
|
||||
rosa.Std.Load(rosa.PArtifact(i))
|
||||
}
|
||||
|
||||
b.StopTimer()
|
||||
rosa.DropCaches("", 0)
|
||||
b.StartTimer()
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveName(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for i := range rosa.PresetUnexportedStart {
|
||||
p := i
|
||||
name := rosa.GetMetadata(p).Name
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if got, ok := rosa.ResolveName(name); !ok {
|
||||
t.Fatal("ResolveName: ok = false")
|
||||
} else if got != p {
|
||||
t.Fatalf("ResolveName: %d, want %d", got, p)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
func TestResolveNameUnexported(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for i := rosa.PresetUnexportedStart; i < rosa.PresetEnd; i++ {
|
||||
p := i
|
||||
name := rosa.GetMetadata(p).Name
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if got, ok := rosa.ResolveName(name); ok {
|
||||
t.Fatalf("ResolveName: resolved unexported preset %d", got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnique(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
names := make(map[string]struct{})
|
||||
for i := range rosa.PresetEnd {
|
||||
name := rosa.GetMetadata(rosa.PArtifact(i)).Name
|
||||
if _, ok := names[name]; ok {
|
||||
t.Fatalf("name %s is not unique", name)
|
||||
}
|
||||
names[name] = struct{}{}
|
||||
}
|
||||
}
|
||||
@@ -26,11 +26,9 @@ install -D -m755 libargp.a /work/system/lib/libargp.a
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[ArgpStandalone] = Metadata{
|
||||
f: Toolchain.newArgpStandalone,
|
||||
|
||||
native.mustRegister(Toolchain.newArgpStandalone, &Metadata{
|
||||
Name: "argp-standalone",
|
||||
Description: "hierarchical argument parsing library broken out from glibc",
|
||||
Website: "http://www.lysator.liu.se/~nisse/misc/",
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
348
internal/rosa/azalea/azalea.go
Normal file
348
internal/rosa/azalea/azalea.go
Normal file
@@ -0,0 +1,348 @@
|
||||
// Package azalea implements a proof-of-concept, domain-specific language for
|
||||
// Rosa OS software packaging.
|
||||
package azalea
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"strconv"
|
||||
"text/scanner"
|
||||
)
|
||||
|
||||
// idents are runes accepted in an identifier.
|
||||
var idents = [...]bool{
|
||||
'0': true, '1': true, '2': true, '3': true, '4': true, '5': true, '6': true,
|
||||
'7': true, '8': true, '9': true,
|
||||
|
||||
'A': true, 'B': true, 'C': true, 'D': true, 'E': true, 'F': true, 'G': true,
|
||||
'H': true, 'I': true, 'J': true, 'K': true, 'L': true, 'M': true, 'N': true,
|
||||
'O': true, 'P': true, 'Q': true, 'R': true, 'S': true, 'T': true, 'U': true,
|
||||
'V': true, 'W': true, 'X': true, 'Y': true, 'Z': true,
|
||||
|
||||
'a': true, 'b': true, 'c': true, 'd': true, 'e': true, 'f': true, 'g': true,
|
||||
'h': true, 'i': true, 'j': true, 'k': true, 'l': true, 'm': true, 'n': true,
|
||||
'o': true, 'p': true, 'q': true, 'r': true, 's': true, 't': true, 'u': true,
|
||||
'v': true, 'w': true, 'x': true, 'y': true, 'z': true,
|
||||
|
||||
'-': true, '_': true,
|
||||
}
|
||||
|
||||
// TokenError describes an unexpected token.
|
||||
type TokenError [2]rune
|
||||
|
||||
func (e TokenError) Error() string {
|
||||
return "expected " + scanner.TokenString(e[0]) +
|
||||
", found " + scanner.TokenString(e[1])
|
||||
}
|
||||
|
||||
// ExprError is an unexpected token encountered while parsing an expression.
|
||||
type ExprError rune
|
||||
|
||||
func (e ExprError) Error() string {
|
||||
return "unexpected token " + scanner.TokenString(rune(e))
|
||||
}
|
||||
|
||||
// must1 returns v, or panics if err is not nil.
|
||||
func must1[T any](v T, err error) T {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// parser retains the current token.
|
||||
type parser struct {
|
||||
s scanner.Scanner
|
||||
tok rune
|
||||
}
|
||||
|
||||
// scan advances the underlying scanner to the next token, storing its result.
|
||||
func (p *parser) scan() rune { p.tok = p.s.Scan(); return p.tok }
|
||||
|
||||
// expects panics with [TokenError] for an unexpected tok.
|
||||
func (p *parser) expects(expects rune) {
|
||||
if p.tok != expects {
|
||||
panic(TokenError{expects, p.tok})
|
||||
}
|
||||
}
|
||||
|
||||
// scanAs advances the scanner for an expected token.
|
||||
func (p *parser) scanAs(expects rune) { p.scan(); p.expects(expects) }
|
||||
|
||||
// An Int is the value represented by an integer literal.
|
||||
type Int int64
|
||||
|
||||
func (v Int) GoString() string {
|
||||
return "azalea.Int(" + strconv.FormatInt(int64(v), 10) + ")"
|
||||
}
|
||||
|
||||
// parseInt parses the current token as a base 10 representation of a 64-bit
|
||||
// signed integer.
|
||||
func (p *parser) parseInt() Int {
|
||||
v, err := strconv.ParseInt(p.s.TokenText(), 10, 64)
|
||||
return must1(Int(v), err)
|
||||
}
|
||||
|
||||
// A String holds the unquoted content of a string literal.
|
||||
type String string
|
||||
|
||||
func (v String) GoString() string {
|
||||
return "azalea.String(" + strconv.Quote(string(v)) + ")"
|
||||
}
|
||||
|
||||
// parseString parses the current token as a string.
|
||||
func (p *parser) parseString() String {
|
||||
s, err := strconv.Unquote(p.s.TokenText())
|
||||
return must1(String(s), err)
|
||||
}
|
||||
|
||||
// An Ident holds the name of an identifier.
|
||||
type Ident string
|
||||
|
||||
func (v Ident) GoString() string {
|
||||
return "azalea.Ident(" + strconv.Quote(string(v)) + ")"
|
||||
}
|
||||
|
||||
// A Val are statements joined by the '+' operator. Only the [String] type
|
||||
// supports concatenation.
|
||||
type Val []any
|
||||
|
||||
// parseVal parses until the end of the [Val].
|
||||
func (p *parser) parseVal() (v Val) {
|
||||
v = append(v, p.parseExpr())
|
||||
for p.tok == '+' {
|
||||
p.scan()
|
||||
v = append(v, p.parseExpr())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// An Array holds statements in an array.
|
||||
type Array []Val
|
||||
|
||||
// A KV holds a key/value pair.
|
||||
type KV struct {
|
||||
K String
|
||||
V Val
|
||||
}
|
||||
|
||||
// An Arg represents an argument of [Func].
|
||||
type Arg struct {
|
||||
K []Ident
|
||||
V Val
|
||||
R bool
|
||||
}
|
||||
|
||||
// Func is a function call or package declaration.
|
||||
type Func struct {
|
||||
// Function or package identifier.
|
||||
Ident Ident
|
||||
// Whether this is a package declaration.
|
||||
Package bool
|
||||
// Key-value arguments.
|
||||
Args []Arg
|
||||
}
|
||||
|
||||
// parseExpr parses the current expression.
|
||||
func (p *parser) parseExpr() any {
|
||||
switch p.tok {
|
||||
case scanner.Int:
|
||||
v := p.parseInt()
|
||||
p.scan()
|
||||
return v
|
||||
|
||||
case scanner.String, scanner.RawString:
|
||||
v := p.parseString()
|
||||
p.scan()
|
||||
return v
|
||||
|
||||
case scanner.Ident:
|
||||
var v Func
|
||||
v.Ident = Ident(p.s.TokenText())
|
||||
if v.Package = v.Ident == "package"; v.Package {
|
||||
p.scanAs(scanner.Ident)
|
||||
v.Ident = Ident(p.s.TokenText())
|
||||
}
|
||||
|
||||
p.scan()
|
||||
switch p.tok {
|
||||
case '{':
|
||||
for {
|
||||
p.scan()
|
||||
switch p.tok {
|
||||
case '}':
|
||||
p.scan()
|
||||
return v
|
||||
|
||||
case scanner.Ident:
|
||||
break
|
||||
|
||||
default:
|
||||
panic(TokenError{scanner.Ident, p.tok})
|
||||
}
|
||||
|
||||
arg := Arg{K: []Ident{Ident(p.s.TokenText())}}
|
||||
delim := true
|
||||
arg:
|
||||
for {
|
||||
p.scan()
|
||||
switch p.tok {
|
||||
case ',':
|
||||
if delim {
|
||||
delim = false
|
||||
continue
|
||||
}
|
||||
panic(ExprError(p.tok))
|
||||
|
||||
case scanner.Ident:
|
||||
if delim {
|
||||
panic(TokenError{',', p.tok})
|
||||
}
|
||||
delim = true
|
||||
arg.K = append(arg.K, Ident(p.s.TokenText()))
|
||||
|
||||
default:
|
||||
break arg
|
||||
}
|
||||
}
|
||||
switch p.tok {
|
||||
case '=':
|
||||
break
|
||||
|
||||
case '*':
|
||||
arg.R = true
|
||||
p.scanAs('=')
|
||||
|
||||
default:
|
||||
panic(TokenError{'=', p.tok})
|
||||
}
|
||||
p.scan()
|
||||
arg.V = p.parseVal()
|
||||
v.Args = append(v.Args, arg)
|
||||
p.expects(';')
|
||||
}
|
||||
|
||||
default:
|
||||
return v.Ident
|
||||
}
|
||||
|
||||
case '{':
|
||||
var v []KV
|
||||
for {
|
||||
p.scan()
|
||||
switch p.tok {
|
||||
case '}':
|
||||
p.scan()
|
||||
return v
|
||||
|
||||
case scanner.String:
|
||||
pair := KV{K: p.parseString()}
|
||||
p.scan()
|
||||
switch p.tok {
|
||||
case ';':
|
||||
break
|
||||
|
||||
case ':':
|
||||
p.scan()
|
||||
pair.V = p.parseVal()
|
||||
p.expects(';')
|
||||
break
|
||||
|
||||
default:
|
||||
panic(ExprError(p.tok))
|
||||
}
|
||||
v = append(v, pair)
|
||||
|
||||
default:
|
||||
panic(ExprError(p.tok))
|
||||
}
|
||||
}
|
||||
|
||||
case '[':
|
||||
var (
|
||||
v Array
|
||||
delim bool
|
||||
)
|
||||
p.scan()
|
||||
for {
|
||||
switch p.tok {
|
||||
case ',':
|
||||
if delim {
|
||||
p.scan()
|
||||
delim = false
|
||||
continue
|
||||
}
|
||||
panic(ExprError(','))
|
||||
case ']':
|
||||
p.scan()
|
||||
return v
|
||||
case scanner.EOF:
|
||||
panic(ExprError(scanner.EOF))
|
||||
default:
|
||||
if delim {
|
||||
panic(TokenError{',', p.tok})
|
||||
}
|
||||
delim = true
|
||||
break
|
||||
}
|
||||
v = append(v, p.parseVal())
|
||||
}
|
||||
|
||||
default:
|
||||
panic(ExprError(p.tok))
|
||||
}
|
||||
}
|
||||
|
||||
// ScanError is the error count parsing all expressions.
|
||||
type ScanError int
|
||||
|
||||
func (ScanError) Error() string {
|
||||
return "aborting due to scanning errors"
|
||||
}
|
||||
|
||||
// Parse parses expressions from r.
|
||||
func Parse(r io.Reader) (e []any, err error) {
|
||||
var p parser
|
||||
p.s.Init(r)
|
||||
|
||||
p.s.Mode = scanner.ScanIdents |
|
||||
scanner.ScanInts |
|
||||
scanner.ScanStrings |
|
||||
scanner.ScanRawStrings |
|
||||
scanner.ScanComments |
|
||||
scanner.SkipComments
|
||||
p.s.IsIdentRune = func(ch rune, i int) bool {
|
||||
if i == 0 && ch >= '0' && ch <= '9' {
|
||||
return false
|
||||
}
|
||||
return ch > 0 && ch < rune(len(idents)) && idents[ch]
|
||||
}
|
||||
|
||||
defer func() {
|
||||
v := recover()
|
||||
if v == nil {
|
||||
return
|
||||
}
|
||||
|
||||
_err, ok := v.(error)
|
||||
if !ok {
|
||||
panic(v)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
err = _err
|
||||
return
|
||||
}
|
||||
err = errors.Join(err, _err)
|
||||
}()
|
||||
|
||||
p.scan()
|
||||
for p.tok != scanner.EOF {
|
||||
e = append(e, p.parseExpr())
|
||||
}
|
||||
|
||||
if p.s.ErrorCount != 0 {
|
||||
err = ScanError(p.s.ErrorCount)
|
||||
}
|
||||
return
|
||||
}
|
||||
169
internal/rosa/azalea/azalea_test.go
Normal file
169
internal/rosa/azalea/azalea_test.go
Normal file
@@ -0,0 +1,169 @@
|
||||
package azalea_test
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"text/scanner"
|
||||
|
||||
. "hakurei.app/internal/rosa/azalea"
|
||||
)
|
||||
|
||||
//go:embed testdata/gcc.az
|
||||
var sample string
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
data string
|
||||
want []any
|
||||
err error
|
||||
}{
|
||||
{"invalid", "}", nil, ExprError('}')},
|
||||
{"bad sep", "f{v?}", nil, TokenError{'=', '?'}},
|
||||
{"bad ident", "f{9}", nil, TokenError{scanner.Ident, scanner.Int}},
|
||||
{"share bad sep", "f { v,,v = v; }", nil, ExprError(',')},
|
||||
{"share missing sep", "f { v v }", nil, TokenError{',', scanner.Ident}},
|
||||
|
||||
{"ident", `v`, []any{Ident("v")}, nil},
|
||||
{"concat", `f { v = v+"\xfd"+p{}+9; }`, []any{Func{
|
||||
Ident: "f",
|
||||
|
||||
Args: []Arg{{K: []Ident{"v"}, V: Val{
|
||||
Ident("v"),
|
||||
String("\xfd"),
|
||||
Func{Ident: "p"},
|
||||
Int(9),
|
||||
}}},
|
||||
}}, nil},
|
||||
{"truncated string concat", `f { v = v+; }`, nil,
|
||||
ExprError(';')},
|
||||
|
||||
{"empty pairs", `{}`, []any{[]KV(nil)}, nil},
|
||||
{"short kv", `{"\x00":v;}`, []any{[]KV{
|
||||
{K: "\x00", V: Val{Ident("v")}},
|
||||
}}, nil},
|
||||
{"truncated kv", `{"\x00"`, nil, ExprError(scanner.EOF)},
|
||||
{"ident kv", `{v="";}`, nil, ExprError(scanner.Ident)},
|
||||
|
||||
{"empty array", `[]`, []any{Array(nil)}, nil},
|
||||
{"integer array", `[9]`, []any{Array{{Int(9)}}}, nil},
|
||||
{"short array", `[ "\x00" ]`, []any{
|
||||
Array{{String("\x00")}},
|
||||
}, nil},
|
||||
{"short array delim", `[ "\x00", ]`, []any{
|
||||
Array{{String("\x00")}},
|
||||
}, nil},
|
||||
{"missing array value", `[ "\x00", , v ]`, nil, ExprError(',')},
|
||||
{"missing array delimiter", `[ v0 v1 ]`, nil, TokenError{',', scanner.Ident}},
|
||||
{"truncated array", `[ "\x00"`, nil,
|
||||
ExprError(scanner.EOF)},
|
||||
|
||||
{"gcc", sample, []any{Func{
|
||||
Ident: Ident("gcc"),
|
||||
Package: true,
|
||||
|
||||
Args: []Arg{
|
||||
{K: []Ident{Ident("description")}, V: Val{String("The GNU Compiler Collection")}},
|
||||
{K: []Ident{Ident("website")}, V: Val{String("https://www.gnu.org/software/gcc")}},
|
||||
{K: []Ident{Ident("anitya")}, V: Val{Int(6502)}},
|
||||
|
||||
{K: []Ident{Ident("version")}, V: Val{String("16.1.0")}, R: true},
|
||||
{K: []Ident{Ident("source")}, V: Val{Func{
|
||||
Ident: Ident("remoteTar"),
|
||||
|
||||
Args: []Arg{
|
||||
{K: []Ident{Ident("url")}, V: Val{
|
||||
String("https://ftp.tsukuba.wide.ad.jp/software/gcc/releases/"),
|
||||
String("gcc-"),
|
||||
Ident("version"),
|
||||
String("/gcc-"),
|
||||
Ident("version"),
|
||||
String(".tar.gz"),
|
||||
}},
|
||||
{K: []Ident{Ident("checksum")}, V: Val{String("4ASoWbxaA2FW7PAB0zzHDPC5XnNhyaAyjtDPpGzceSLeYnEIXsNYZR3PA_Zu5P0K")}},
|
||||
{K: []Ident{Ident("compress")}, V: Val{Ident("gzip")}},
|
||||
},
|
||||
}}},
|
||||
{K: []Ident{Ident("patches")}, V: Val{Array{
|
||||
{String("musl-off64_t-loff_t.patch")},
|
||||
{String("musl-legacy-lfs.patch")},
|
||||
}}},
|
||||
|
||||
{K: []Ident{Ident("exclusive")}, V: Val{Ident("true")}},
|
||||
|
||||
{K: []Ident{Ident("exec")}, V: Val{Func{
|
||||
Ident: Ident("make"),
|
||||
|
||||
Args: []Arg{
|
||||
{K: []Ident{Ident("configure")}, V: Val{[]KV{
|
||||
{K: String("disable-multilib")},
|
||||
{K: String("enable-default-pie")},
|
||||
{K: String("disable-nls")},
|
||||
{K: String("with-gnu-as")},
|
||||
{K: String("with-gnu-ld")},
|
||||
{K: String("with-system-zlib")},
|
||||
{K: String("enable-languages"), V: Val{String("c,c++,go")}},
|
||||
{K: String("with-native-system-header-dir"), V: Val{String("/system/include")}},
|
||||
{K: String("with-multilib-list"), V: Val{Func{
|
||||
Ident: Ident("arch"),
|
||||
|
||||
Args: []Arg{
|
||||
{K: []Ident{Ident("amd64"), Ident("arm64")}, V: Val{String("''")}},
|
||||
{K: []Ident{Ident("default")}, V: Val{Ident("unset")}},
|
||||
},
|
||||
}}},
|
||||
}}},
|
||||
{K: []Ident{Ident("make")}, V: Val{Array{
|
||||
{String("BOOT_CFLAGS='-O2 -g'")},
|
||||
{
|
||||
Func{Ident: Ident("noop"), Args: []Arg{{K: []Ident{Ident("key")}, V: Val{Ident("value")}}}},
|
||||
String("\x00"),
|
||||
},
|
||||
{String("bootstrap")},
|
||||
}}},
|
||||
|
||||
{K: []Ident{Ident("skip-check")}, V: Val{Ident("true")}},
|
||||
},
|
||||
}}},
|
||||
|
||||
{K: []Ident{Ident("inputs")}, V: Val{Array{
|
||||
{Ident("binutils")},
|
||||
{Ident("mpc")},
|
||||
{Ident("zlib")},
|
||||
{Ident("libucontext")},
|
||||
{Ident("kernel-headers")},
|
||||
}}},
|
||||
},
|
||||
}}, nil},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
p, err := Parse(strings.NewReader(tc.data))
|
||||
if !reflect.DeepEqual(p, tc.want) {
|
||||
t.Errorf("Parse: %#v, want %#v", p, tc.want)
|
||||
}
|
||||
if !reflect.DeepEqual(err, tc.err) {
|
||||
t.Errorf("Parse: error = %v, want %v", err, tc.err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkParse(b *testing.B) {
|
||||
r := strings.NewReader(sample)
|
||||
for b.Loop() {
|
||||
if _, err := Parse(r); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
b.StopTimer()
|
||||
r.Reset(sample)
|
||||
b.StartTimer()
|
||||
}
|
||||
}
|
||||
378
internal/rosa/azalea/evaluate.go
Normal file
378
internal/rosa/azalea/evaluate.go
Normal file
@@ -0,0 +1,378 @@
|
||||
package azalea
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"reflect"
|
||||
"slices"
|
||||
"unique"
|
||||
)
|
||||
|
||||
// Value are types supported by the language.
|
||||
type Value interface {
|
||||
bool | int64 | string | []string | [][2]string
|
||||
}
|
||||
|
||||
type (
|
||||
// FArg is an argument passed to [F].
|
||||
FArg struct {
|
||||
K unique.Handle[Ident]
|
||||
V any
|
||||
R bool
|
||||
}
|
||||
// FArgs are arguments passed to [F].
|
||||
FArgs []FArg
|
||||
|
||||
// PF implements the package declaration function.
|
||||
PF func(name Ident, args FArgs) (v any, set bool, err error)
|
||||
|
||||
// F is the implementation of a [Func].
|
||||
F struct {
|
||||
F func(args FArgs) (v any, set bool, err error)
|
||||
V map[unique.Handle[Ident]]any
|
||||
}
|
||||
)
|
||||
|
||||
// Apply applies named arguments and rejects unused arguments.
|
||||
func (args FArgs) Apply(v map[unique.Handle[Ident]]any) error {
|
||||
for _, arg := range args {
|
||||
if arg.V == nil {
|
||||
// unset
|
||||
continue
|
||||
}
|
||||
|
||||
r, ok := v[arg.K]
|
||||
if !ok {
|
||||
if arg.R {
|
||||
continue
|
||||
}
|
||||
return UndefinedError(arg.K.Value())
|
||||
}
|
||||
err := storeE(r, arg.V)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// A Frame refers to local variables and debugging information.
|
||||
type Frame struct {
|
||||
// Local constants.
|
||||
Val map[unique.Handle[Ident]]any
|
||||
// Functions.
|
||||
Func map[unique.Handle[Ident]]F
|
||||
}
|
||||
|
||||
// UnsupportedExprError is an expression with invalid concrete type.
|
||||
type UnsupportedExprError struct{ E any }
|
||||
|
||||
func (e UnsupportedExprError) Error() string {
|
||||
return fmt.Sprintf("unsupported expression %#v", e.E)
|
||||
}
|
||||
|
||||
// UndefinedError is an identifier not defined in any stack frame visible to the
|
||||
// expression containing it.
|
||||
type UndefinedError Ident
|
||||
|
||||
func (e UndefinedError) Error() string {
|
||||
return "undefined: " + string(e)
|
||||
}
|
||||
|
||||
// evaluate is evaluateAny with a type parameter.
|
||||
func evaluate[T Value](d PF, s []Frame, expr any, rp *T) bool {
|
||||
return evaluateAny(d, s, expr, rp)
|
||||
}
|
||||
|
||||
// TypeError is an unexpected type during evaluation.
|
||||
type TypeError struct {
|
||||
Concrete, Asserted reflect.Type
|
||||
}
|
||||
|
||||
func (e TypeError) Error() string {
|
||||
return "expected " + e.Asserted.String() + ", got " + e.Concrete.String()
|
||||
}
|
||||
|
||||
func (e TypeError) Is(err error) bool {
|
||||
var v TypeError
|
||||
return errors.As(err, &v) &&
|
||||
e.Asserted == v.Asserted &&
|
||||
e.Concrete == v.Concrete
|
||||
}
|
||||
|
||||
// storeE is a convenience function to set the value of a result pointer.
|
||||
func storeE(rp any, r any) error {
|
||||
pv := reflect.ValueOf(rp).Elem()
|
||||
v := reflect.ValueOf(r)
|
||||
pt, vt := pv.Type(), v.Type()
|
||||
if !vt.AssignableTo(pt) {
|
||||
return TypeError{vt, pt}
|
||||
}
|
||||
pv.Set(v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// store is like storeE, but panics if error is non-nil.
|
||||
func store[T Value](rp any, r T) {
|
||||
err := storeE(rp, r)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// EvaluationError is an error and the expression it occurred in.
|
||||
type EvaluationError struct {
|
||||
Expr any
|
||||
Err error
|
||||
}
|
||||
|
||||
// Unwrap returns the underlying error.
|
||||
func (e EvaluationError) Unwrap() error { return e.Err }
|
||||
|
||||
// Error returns a very long error description that should not be presented
|
||||
// to the user directly.
|
||||
func (e EvaluationError) Error() string {
|
||||
return fmt.Sprintf("expression %#v: %v", e.Expr, e.Err)
|
||||
}
|
||||
|
||||
var (
|
||||
// IdentInputs is a special array argument in a package declaration whose
|
||||
// values of [Ident] are kept as is when passed to a [PF].
|
||||
IdentInputs = unique.Make(Ident("inputs"))
|
||||
// IdentRuntime has the same semantics as [IdentInputs].
|
||||
IdentRuntime = unique.Make(Ident("runtime"))
|
||||
// IdentSource is a special argument in a package declaration where an
|
||||
// assignment of a [Val] with a single [Ident] passes through the evaluator.
|
||||
IdentSource = unique.Make(Ident("source"))
|
||||
|
||||
// ErrInvalidSpecial is panicked for a special [PF] argument sharing its
|
||||
// value or set for R.
|
||||
ErrInvalidSpecial = errors.New("special must not be common or bound to scope")
|
||||
)
|
||||
|
||||
// evaluateAny implements [Evaluate].
|
||||
func evaluateAny(d PF, s []Frame, expr, rp any) bool {
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r == nil {
|
||||
return
|
||||
}
|
||||
|
||||
err, ok := r.(error)
|
||||
if !ok {
|
||||
panic(r)
|
||||
}
|
||||
|
||||
if _, ok = err.(EvaluationError); ok {
|
||||
panic(err)
|
||||
}
|
||||
panic(EvaluationError{expr, err})
|
||||
}()
|
||||
|
||||
switch e := expr.(type) {
|
||||
case Int:
|
||||
store(rp, int64(e))
|
||||
return true
|
||||
|
||||
case String:
|
||||
store(rp, string(e))
|
||||
return true
|
||||
|
||||
case Ident:
|
||||
var (
|
||||
v any
|
||||
ok bool
|
||||
)
|
||||
for i := range s {
|
||||
v, ok = s[len(s)-1-i].Val[unique.Make(e)]
|
||||
if ok {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
panic(UndefinedError(e))
|
||||
}
|
||||
if err := storeE(rp, v); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return true
|
||||
|
||||
case Val:
|
||||
if len(e) == 1 {
|
||||
switch v := e[0].(type) {
|
||||
case Ident:
|
||||
switch v {
|
||||
case "unset":
|
||||
return false
|
||||
case "true":
|
||||
store(rp, true)
|
||||
return true
|
||||
case "false":
|
||||
store(rp, false)
|
||||
return true
|
||||
default:
|
||||
return evaluateAny(d, s, v, rp)
|
||||
}
|
||||
|
||||
default:
|
||||
return evaluateAny(d, s, e[0], rp)
|
||||
}
|
||||
}
|
||||
var v string
|
||||
for i := range e {
|
||||
var _r string
|
||||
if evaluate(d, s, e[i], &_r) {
|
||||
v += _r
|
||||
}
|
||||
}
|
||||
store(rp, v)
|
||||
return true
|
||||
|
||||
case Array:
|
||||
r := make([]string, 0, len(e))
|
||||
for i := range e {
|
||||
var _r string
|
||||
if evaluate(d, s, e[i], &_r) {
|
||||
r = append(r, _r)
|
||||
}
|
||||
}
|
||||
store(rp, r)
|
||||
return true
|
||||
|
||||
case []KV:
|
||||
r := make([][2]string, 0, len(e))
|
||||
for i := range e {
|
||||
var _r string
|
||||
if e[i].V == nil || evaluate(d, s, e[i].V, &_r) {
|
||||
r = append(r, [2]string{string(e[i].K), _r})
|
||||
}
|
||||
}
|
||||
store(rp, r)
|
||||
return true
|
||||
|
||||
case Func:
|
||||
var (
|
||||
f F
|
||||
ok bool
|
||||
)
|
||||
if !e.Package {
|
||||
for i := range s {
|
||||
f, ok = s[len(s)-1-i].Func[unique.Make(e.Ident)]
|
||||
if ok {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
panic(UndefinedError(e.Ident))
|
||||
}
|
||||
}
|
||||
|
||||
argc := len(e.Args)
|
||||
for _, arg := range e.Args {
|
||||
argc += len(arg.K) - 1
|
||||
}
|
||||
fargs := make([]FArg, 0, len(e.Args))
|
||||
s = append(s, Frame{})
|
||||
fp := &s[len(s)-1]
|
||||
if !e.Package {
|
||||
fp.Val = maps.Clone(f.V)
|
||||
}
|
||||
|
||||
args:
|
||||
for _, arg := range e.Args {
|
||||
names := make([]unique.Handle[Ident], len(arg.K))
|
||||
for i, name := range arg.K {
|
||||
names[i] = unique.Make(name)
|
||||
}
|
||||
|
||||
farg := FArg{R: arg.R}
|
||||
if e.Package {
|
||||
for _, special := range [...]unique.Handle[Ident]{
|
||||
IdentInputs,
|
||||
IdentRuntime,
|
||||
} {
|
||||
if slices.Contains(names, special) {
|
||||
if len(names) != 1 || len(arg.V) != 1 || arg.R {
|
||||
panic(ErrInvalidSpecial)
|
||||
}
|
||||
farg.K = names[0]
|
||||
if err := storeE(&farg.V, arg.V[0]); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fargs = append(fargs, farg)
|
||||
continue args
|
||||
}
|
||||
}
|
||||
|
||||
if slices.Contains(names, IdentSource) {
|
||||
if len(names) != 1 || len(arg.V) != 1 || arg.R {
|
||||
panic(ErrInvalidSpecial)
|
||||
}
|
||||
if _, ok = arg.V[0].(Ident); ok {
|
||||
farg.K = names[0]
|
||||
if err := storeE(&farg.V, arg.V[0]); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fargs = append(fargs, farg)
|
||||
continue args
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !evaluateAny(d, s, arg.V, &farg.V) {
|
||||
farg.V = nil
|
||||
}
|
||||
for _, name := range names {
|
||||
farg.K = name
|
||||
fargs = append(fargs, farg)
|
||||
|
||||
if arg.R && farg.V != nil {
|
||||
if fp.Val == nil {
|
||||
fp.Val = make(map[unique.Handle[Ident]]any)
|
||||
}
|
||||
(*fp).Val[name] = farg.V
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
v any
|
||||
err error
|
||||
)
|
||||
if !e.Package {
|
||||
v, ok, err = f.F(fargs)
|
||||
} else {
|
||||
v, ok, err = d(e.Ident, fargs)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
} else if v != nil {
|
||||
if err = storeE(rp, v); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return ok
|
||||
|
||||
default:
|
||||
panic(UnsupportedExprError{expr})
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate evaluates a statement and returns its value.
|
||||
func Evaluate[T any](d PF, s []Frame, expr any) (v T, set bool, err error) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r == nil {
|
||||
return
|
||||
}
|
||||
|
||||
_err, ok := r.(error)
|
||||
if !ok {
|
||||
panic(r)
|
||||
}
|
||||
err = _err
|
||||
}()
|
||||
set = evaluateAny(d, s, expr, &v)
|
||||
return
|
||||
}
|
||||
391
internal/rosa/azalea/evaluate_test.go
Normal file
391
internal/rosa/azalea/evaluate_test.go
Normal file
@@ -0,0 +1,391 @@
|
||||
package azalea_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"unique"
|
||||
|
||||
. "hakurei.app/internal/rosa/azalea"
|
||||
)
|
||||
|
||||
// makeStackCheck creates a stack with a single frame with a single function "f"
|
||||
// which calls the check function internally.
|
||||
func makeStackCheck(check func(args FArgs) (any, error)) []Frame {
|
||||
return []Frame{{Func: map[unique.Handle[Ident]]F{
|
||||
unique.Make(Ident("f")): {F: func(
|
||||
args FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
set = true
|
||||
v, err = check(args)
|
||||
return
|
||||
}},
|
||||
}}}
|
||||
}
|
||||
|
||||
func TestEvaluate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
data string
|
||||
s []Frame
|
||||
want any
|
||||
err error
|
||||
}{
|
||||
{"apply unset", `f { v = unset; }`, makeStackCheck(func(
|
||||
args FArgs,
|
||||
) (v any, err error) {
|
||||
v = "\xfd"
|
||||
err = args.Apply(map[unique.Handle[Ident]]any{
|
||||
unique.Make(Ident("v")): &v,
|
||||
})
|
||||
return
|
||||
}), "\xfd", nil},
|
||||
|
||||
{"apply bad type", `f { v = 9; }`, makeStackCheck(func(
|
||||
args FArgs,
|
||||
) (v any, err error) {
|
||||
v = "\xfd"
|
||||
err = args.Apply(map[unique.Handle[Ident]]any{
|
||||
unique.Make(Ident("v")): &v,
|
||||
})
|
||||
return
|
||||
}), "", TypeError{
|
||||
Concrete: reflect.TypeFor[int64](),
|
||||
Asserted: reflect.TypeFor[string](),
|
||||
}},
|
||||
|
||||
{"apply undefined", `f { v = 9; }`, makeStackCheck(func(
|
||||
args FArgs,
|
||||
) (v any, err error) {
|
||||
v = "\xfd"
|
||||
err = args.Apply(map[unique.Handle[Ident]]any{})
|
||||
return
|
||||
}), "", EvaluationError{
|
||||
Expr: Func{
|
||||
Ident: Ident("f"),
|
||||
Args: []Arg{
|
||||
{K: []Ident{"v"}, V: Val{Int(9)}},
|
||||
},
|
||||
},
|
||||
Err: UndefinedError("v"),
|
||||
}},
|
||||
|
||||
{"apply bound undefined", `f { _v* = "\x00"; v = _v; }`, makeStackCheck(func(
|
||||
args FArgs,
|
||||
) (v any, err error) {
|
||||
v = "\xfd"
|
||||
err = args.Apply(map[unique.Handle[Ident]]any{
|
||||
unique.Make(Ident("v")): &v,
|
||||
})
|
||||
return
|
||||
}), "\x00", nil},
|
||||
|
||||
{"undefined function", `f {}`, nil, "", EvaluationError{
|
||||
Expr: Func{Ident: "f"},
|
||||
Err: UndefinedError("f"),
|
||||
}},
|
||||
|
||||
{"error wrap deep", `f { v = nil; }`, makeStackCheck(func(
|
||||
FArgs,
|
||||
) (any, error) {
|
||||
panic("unreachable")
|
||||
}), "", EvaluationError{
|
||||
Expr: Ident("nil"),
|
||||
Err: UndefinedError("nil"),
|
||||
}},
|
||||
|
||||
{"common inputs", `package name { inputs, v = []; }`, nil, "", EvaluationError{
|
||||
Expr: Func{
|
||||
Ident: Ident("name"),
|
||||
Package: true,
|
||||
|
||||
Args: []Arg{
|
||||
{K: []Ident{
|
||||
"inputs",
|
||||
"v",
|
||||
}, V: Val{Array(nil)}},
|
||||
},
|
||||
},
|
||||
Err: ErrInvalidSpecial,
|
||||
}},
|
||||
|
||||
{"bound inputs", `package name { inputs* = []; }`, nil, "", EvaluationError{
|
||||
Expr: Func{
|
||||
Ident: Ident("name"),
|
||||
Package: true,
|
||||
|
||||
Args: []Arg{
|
||||
{K: []Ident{"inputs"}, V: Val{Array(nil)}, R: true},
|
||||
},
|
||||
},
|
||||
Err: ErrInvalidSpecial,
|
||||
}},
|
||||
|
||||
{"bound runtime", `package name { runtime* = []; }`, nil, "", EvaluationError{
|
||||
Expr: Func{
|
||||
Ident: Ident("name"),
|
||||
Package: true,
|
||||
|
||||
Args: []Arg{
|
||||
{K: []Ident{"runtime"}, V: Val{Array(nil)}, R: true},
|
||||
},
|
||||
},
|
||||
Err: ErrInvalidSpecial,
|
||||
}},
|
||||
|
||||
{"concat inputs", `package name { inputs = ""+""; }`, nil, "", EvaluationError{
|
||||
Expr: Func{
|
||||
Ident: Ident("name"),
|
||||
Package: true,
|
||||
|
||||
Args: []Arg{
|
||||
{K: []Ident{"inputs"}, V: Val{String(""), String("")}},
|
||||
},
|
||||
},
|
||||
Err: ErrInvalidSpecial,
|
||||
}},
|
||||
|
||||
{"concat source", `package name { source = ""+""; }`, nil, "", EvaluationError{
|
||||
Expr: Func{
|
||||
Ident: Ident("name"),
|
||||
Package: true,
|
||||
|
||||
Args: []Arg{
|
||||
{K: []Ident{"source"}, V: Val{String(""), String("")}},
|
||||
},
|
||||
},
|
||||
Err: ErrInvalidSpecial,
|
||||
}},
|
||||
|
||||
{"source handle", `package name { source = name; }`, nil, FArgs{
|
||||
{K: unique.Make(Ident("source")), V: Ident("name")},
|
||||
}, nil},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var expr Func
|
||||
if e, err := Parse(strings.NewReader(tc.data)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if len(e) != 1 {
|
||||
t.Fatalf("got expression %#v", e)
|
||||
} else {
|
||||
expr = e[0].(Func)
|
||||
}
|
||||
const rPackage = "\xff\xff\xff\xff"
|
||||
r, set, err := Evaluate[string](func(
|
||||
name Ident,
|
||||
args FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
v = rPackage
|
||||
if !reflect.DeepEqual(args, tc.want) {
|
||||
err = fmt.Errorf("%#v, want %#v", args, tc.want)
|
||||
}
|
||||
set = true
|
||||
return
|
||||
}, tc.s, expr)
|
||||
if set != (err == nil) {
|
||||
t.Error("Evaluate: unexpected unset")
|
||||
}
|
||||
|
||||
if r != rPackage && r != tc.want {
|
||||
t.Errorf("Evaluate: %q, want %q", r, tc.want)
|
||||
}
|
||||
|
||||
var errEquals bool
|
||||
if errors.As(err, new(TypeError)) {
|
||||
errEquals = errors.Is(err, tc.err)
|
||||
} else {
|
||||
errEquals = reflect.DeepEqual(err, tc.err)
|
||||
}
|
||||
if !errEquals {
|
||||
t.Errorf("Evaluate: error = %v, want %v", err, tc.err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvaluateGCC(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var gcc Func
|
||||
if e, err := Parse(strings.NewReader(sample)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
gcc = e[0].(Func)
|
||||
}
|
||||
|
||||
var got [3]FArgs
|
||||
if r, set, err := Evaluate[string](func(
|
||||
name Ident,
|
||||
args FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
v = "\x00"
|
||||
set = true
|
||||
got[0] = args
|
||||
return
|
||||
}, []Frame{{
|
||||
Func: map[unique.Handle[Ident]]F{
|
||||
unique.Make(Ident("remoteTar")): {F: func(
|
||||
args FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
var url, checksum string
|
||||
var compress int
|
||||
if err = args.Apply(map[unique.Handle[Ident]]any{
|
||||
unique.Make(Ident("url")): &url,
|
||||
unique.Make(Ident("checksum")): &checksum,
|
||||
unique.Make(Ident("compress")): &compress,
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if compress != 0xcafe {
|
||||
err = fmt.Errorf("unexpected compress %#v", compress)
|
||||
}
|
||||
set = true
|
||||
v = url + "?checksum=" + checksum
|
||||
return
|
||||
}, V: map[unique.Handle[Ident]]any{
|
||||
unique.Make(Ident("gzip")): 0xcafe,
|
||||
}},
|
||||
|
||||
unique.Make(Ident("make")): {F: func(
|
||||
args FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
v = args
|
||||
set = true
|
||||
return
|
||||
}},
|
||||
|
||||
unique.Make(Ident("arch")): {F: func(
|
||||
args FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
set = false
|
||||
got[1] = args
|
||||
return
|
||||
}},
|
||||
|
||||
unique.Make(Ident("noop")): {F: func(
|
||||
args FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
set = false
|
||||
set = true
|
||||
got[2] = args
|
||||
return
|
||||
}, V: map[unique.Handle[Ident]]any{
|
||||
unique.Make(Ident("value")): "\xfd",
|
||||
}},
|
||||
},
|
||||
}}, gcc); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if r != "\x00" {
|
||||
t.Fatalf("package: %q", r)
|
||||
} else if !set {
|
||||
t.Fatal("package: unset")
|
||||
}
|
||||
|
||||
want := [...]FArgs{
|
||||
{
|
||||
{K: unique.Make(Ident("description")), V: "The GNU Compiler Collection"},
|
||||
{K: unique.Make(Ident("website")), V: "https://www.gnu.org/software/gcc"},
|
||||
{K: unique.Make(Ident("anitya")), V: int64(6502)},
|
||||
|
||||
{K: unique.Make(Ident("version")), V: "16.1.0", R: true},
|
||||
{K: unique.Make(Ident("source")), V: "https://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-16.1.0/gcc-16.1.0.tar.gz?checksum=4ASoWbxaA2FW7PAB0zzHDPC5XnNhyaAyjtDPpGzceSLeYnEIXsNYZR3PA_Zu5P0K"},
|
||||
{K: unique.Make(Ident("patches")), V: []string{"musl-off64_t-loff_t.patch", "musl-legacy-lfs.patch"}},
|
||||
|
||||
{K: unique.Make(Ident("exclusive")), V: true},
|
||||
{K: unique.Make(Ident("exec")), V: FArgs{
|
||||
{K: unique.Make(Ident("configure")), V: [][2]string{
|
||||
{"disable-multilib", ""},
|
||||
{"enable-default-pie", ""},
|
||||
{"disable-nls", ""},
|
||||
{"with-gnu-as", ""},
|
||||
{"with-gnu-ld", ""},
|
||||
{"with-system-zlib", ""},
|
||||
{"enable-languages", "c,c++,go"},
|
||||
{"with-native-system-header-dir", "/system/include"},
|
||||
}},
|
||||
{K: unique.Make(Ident("make")), V: []string{
|
||||
"BOOT_CFLAGS='-O2 -g'",
|
||||
"\x00",
|
||||
"bootstrap",
|
||||
}},
|
||||
{K: unique.Make(Ident("skip-check")), V: true},
|
||||
}},
|
||||
|
||||
{K: unique.Make(Ident("inputs")), V: Array{
|
||||
{Ident("binutils")},
|
||||
{Ident("mpc")},
|
||||
{Ident("zlib")},
|
||||
{Ident("libucontext")},
|
||||
{Ident("kernel-headers")},
|
||||
}},
|
||||
},
|
||||
{
|
||||
{K: unique.Make(Ident("amd64")), V: "''"},
|
||||
{K: unique.Make(Ident("arm64")), V: "''"},
|
||||
{K: unique.Make(Ident("default"))},
|
||||
},
|
||||
{{K: unique.Make(Ident("key")), V: "\xfd"}},
|
||||
}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("package: args = %#v, want %#v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEvaluate(b *testing.B) {
|
||||
var gcc Func
|
||||
if e, err := Parse(strings.NewReader(sample)); err != nil {
|
||||
b.Fatal(err)
|
||||
} else {
|
||||
gcc = e[0].(Func)
|
||||
}
|
||||
|
||||
s := []Frame{{
|
||||
Func: map[unique.Handle[Ident]]F{
|
||||
unique.Make(Ident("remoteTar")): {F: func(
|
||||
FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
return
|
||||
}, V: map[unique.Handle[Ident]]any{
|
||||
unique.Make(Ident("gzip")): 0xcafe,
|
||||
}},
|
||||
|
||||
unique.Make(Ident("make")): {F: func(
|
||||
FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
return
|
||||
}},
|
||||
|
||||
unique.Make(Ident("arch")): {F: func(
|
||||
FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
return
|
||||
}},
|
||||
|
||||
unique.Make(Ident("noop")): {F: func(
|
||||
FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
return
|
||||
}, V: map[unique.Handle[Ident]]any{
|
||||
unique.Make(Ident("value")): "\xfd",
|
||||
}},
|
||||
},
|
||||
}}
|
||||
for b.Loop() {
|
||||
if _, _, err := Evaluate[string](func(
|
||||
Ident,
|
||||
FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
return
|
||||
}, s, gcc); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
57
internal/rosa/azalea/testdata/gcc.az
vendored
Normal file
57
internal/rosa/azalea/testdata/gcc.az
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
package gcc {
|
||||
description = "The GNU Compiler Collection";
|
||||
website = "https://www.gnu.org/software/gcc";
|
||||
anitya = 6502;
|
||||
|
||||
version* = "16.1.0";
|
||||
source = remoteTar {
|
||||
url = "https://ftp.tsukuba.wide.ad.jp/software/gcc/releases/"+
|
||||
"gcc-"+version+"/gcc-"+version+".tar.gz";
|
||||
checksum = "4ASoWbxaA2FW7PAB0zzHDPC5XnNhyaAyjtDPpGzceSLeYnEIXsNYZR3PA_Zu5P0K";
|
||||
compress = gzip;
|
||||
};
|
||||
patches = [
|
||||
"musl-off64_t-loff_t.patch",
|
||||
"musl-legacy-lfs.patch",
|
||||
];
|
||||
|
||||
// GCC spends most of its time in its many configure scripts, however
|
||||
// it also saturates the CPU for a consequential amount of time.
|
||||
exclusive = true;
|
||||
|
||||
exec = make {
|
||||
configure = {
|
||||
"disable-multilib";
|
||||
"enable-default-pie";
|
||||
"disable-nls";
|
||||
"with-gnu-as";
|
||||
"with-gnu-ld";
|
||||
"with-system-zlib";
|
||||
"enable-languages": "c,c++,go";
|
||||
"with-native-system-header-dir": "/system/include";
|
||||
"with-multilib-list": arch {
|
||||
amd64, arm64 = "''";
|
||||
default = unset;
|
||||
};
|
||||
};
|
||||
make = [
|
||||
"BOOT_CFLAGS='-O2 -g'",
|
||||
noop { key = value; } + "\x00",
|
||||
"bootstrap",
|
||||
];
|
||||
|
||||
// This toolchain is hacked to pieces, it is not expected to ever work
|
||||
// well in its current state. That does not matter as long as the
|
||||
// toolchain it produces passes its own test suite.
|
||||
skip-check = true;
|
||||
};
|
||||
|
||||
inputs = [
|
||||
binutils,
|
||||
|
||||
mpc,
|
||||
zlib,
|
||||
libucontext,
|
||||
kernel-headers,
|
||||
];
|
||||
}
|
||||
76
internal/rosa/bison.go
Normal file
76
internal/rosa/bison.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package rosa
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
// skipGNUTests generates a string for skipping specific tests by number in a
|
||||
// GNU test suite. This is nontrivial because the test suite does not support
|
||||
// excluding tests in any way, so ranges for all but the skipped tests have to
|
||||
// be specified instead.
|
||||
//
|
||||
// For example, to skip test 764, ranges around the skipped test must be
|
||||
// specified:
|
||||
//
|
||||
// 1-763 765-
|
||||
//
|
||||
// Tests are numbered starting from 1. The resulting string is unquoted.
|
||||
func skipGNUTests(tests ...int) string {
|
||||
tests = slices.Clone(tests)
|
||||
slices.Sort(tests)
|
||||
|
||||
var buf strings.Builder
|
||||
|
||||
if tests[0] != 1 {
|
||||
buf.WriteString("1-")
|
||||
}
|
||||
|
||||
for i, n := range tests {
|
||||
if n != 1 && (i == 0 || tests[i-1] != n-1) {
|
||||
buf.WriteString(strconv.Itoa(n - 1))
|
||||
buf.WriteString(" ")
|
||||
}
|
||||
if i == len(tests)-1 || tests[i+1] != n+1 {
|
||||
buf.WriteString(strconv.Itoa(n + 1))
|
||||
buf.WriteString("-")
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (t Toolchain) newBison() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "3.8.2"
|
||||
checksum = "BhRM6K7URj1LNOkIDCFDctSErLS-Xo5d9ba9seg10o6ACrgC1uNhED7CQPgIY29Y"
|
||||
)
|
||||
return t.NewPackage("bison", version, newTar(
|
||||
"https://ftpmirror.gnu.org/gnu/bison/bison-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, &MakeHelper{
|
||||
Check: []string{
|
||||
"TESTSUITEFLAGS=" + jobsFlagE + "' " + skipGNUTests(
|
||||
// clang miscompiles (SIGILL)
|
||||
764,
|
||||
) + "'",
|
||||
"check",
|
||||
},
|
||||
},
|
||||
M4,
|
||||
Diffutils,
|
||||
Sed,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.mustRegister(Toolchain.newBison, &Metadata{
|
||||
Name: "bison",
|
||||
Description: "a general-purpose parser generator",
|
||||
Website: "https://www.gnu.org/software/bison/",
|
||||
|
||||
ID: 193,
|
||||
})
|
||||
}
|
||||
@@ -85,13 +85,13 @@ func (a busyboxBin) Cure(t *pkg.TContext) (err error) {
|
||||
|
||||
// newBusyboxBin returns a [pkg.Artifact] containing a busybox installation from
|
||||
// the https://busybox.net/downloads/binaries/ binary release.
|
||||
func newBusyboxBin() pkg.Artifact {
|
||||
func (s *S) newBusyboxBin() pkg.Artifact {
|
||||
var version, url, checksum string
|
||||
switch arch {
|
||||
switch s.arch {
|
||||
case "amd64":
|
||||
version = "1.35.0"
|
||||
url = "https://busybox.net/downloads/binaries/" +
|
||||
version + "-" + linuxArch() + "-linux-musl/busybox"
|
||||
version + "-" + s.linuxArch() + "-linux-musl/busybox"
|
||||
checksum = "L7OBIsPu9enNHn7FqpBT1kOg_mCLNmetSeNMA3i4Y60Z5jTgnlX3qX3zcQtLx5AB"
|
||||
case "arm64":
|
||||
version = "1.31.0"
|
||||
@@ -100,11 +100,11 @@ func newBusyboxBin() pkg.Artifact {
|
||||
checksum = "npJjBO7iwhjW6Kx2aXeSxf8kXhVgTCDChOZTTsI8ZfFfa3tbsklxRiidZQdrVERg"
|
||||
|
||||
default:
|
||||
panic("unsupported target " + arch)
|
||||
panic("unsupported target " + s.arch)
|
||||
}
|
||||
|
||||
return pkg.NewExec(
|
||||
"busybox-bin-"+version, arch, nil, pkg.ExecTimeoutMax, false,
|
||||
"busybox-bin-"+version, s.arch, nil, pkg.ExecTimeoutMax, false, false,
|
||||
fhs.AbsRoot, []string{
|
||||
"PATH=/system/bin",
|
||||
},
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newBzip2() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.0.8"
|
||||
checksum = "cTLykcco7boom-s05H1JVsQi1AtChYL84nXkg_92Dm1Xt94Ob_qlMg_-NSguIK-c"
|
||||
)
|
||||
return t.NewPackage("bzip2", version, newTar(
|
||||
"https://sourceware.org/pub/bzip2/bzip2-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), &PackageAttr{
|
||||
Writable: true,
|
||||
EnterSource: true,
|
||||
}, &MakeHelper{
|
||||
// uses source tree as scratch space
|
||||
SkipConfigure: true,
|
||||
SkipCheck: true,
|
||||
InPlace: true,
|
||||
Make: []string{
|
||||
"CC=cc",
|
||||
},
|
||||
Install: "make PREFIX=/work/system install",
|
||||
}), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Bzip2] = Metadata{
|
||||
f: Toolchain.newBzip2,
|
||||
|
||||
Name: "bzip2",
|
||||
Description: "a freely available, patent free, high-quality data compressor",
|
||||
Website: "https://sourceware.org/bzip2/",
|
||||
|
||||
ID: 237,
|
||||
}
|
||||
}
|
||||
@@ -4,118 +4,10 @@ import (
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
func (t Toolchain) newCMake() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "4.3.2"
|
||||
checksum = "6QylwRVKletndTSkZTV2YBRwgd_9rUVgav_QW23HpjUgV21AVYZOUOal8tdBDmO7"
|
||||
)
|
||||
return t.NewPackage("cmake", version, newFromGitHubRelease(
|
||||
"Kitware/CMake",
|
||||
"v"+version,
|
||||
"cmake-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), &PackageAttr{
|
||||
// test suite expects writable source tree
|
||||
Writable: true,
|
||||
|
||||
// expected to be writable in the copy made during bootstrap
|
||||
Chmod: true,
|
||||
|
||||
Patches: []KV{
|
||||
{"bootstrap-test-no-openssl", `diff --git a/Tests/BootstrapTest.cmake b/Tests/BootstrapTest.cmake
|
||||
index 137de78bc1..b4da52e664 100644
|
||||
--- a/Tests/BootstrapTest.cmake
|
||||
+++ b/Tests/BootstrapTest.cmake
|
||||
@@ -9,7 +9,7 @@ if(NOT nproc EQUAL 0)
|
||||
endif()
|
||||
message(STATUS "running bootstrap: ${bootstrap} ${ninja_arg} ${parallel_arg}")
|
||||
execute_process(
|
||||
- COMMAND ${bootstrap} ${ninja_arg} ${parallel_arg}
|
||||
+ COMMAND ${bootstrap} ${ninja_arg} ${parallel_arg} -- -DCMAKE_USE_OPENSSL=OFF
|
||||
WORKING_DIRECTORY "${bin_dir}"
|
||||
RESULT_VARIABLE result
|
||||
)
|
||||
`},
|
||||
|
||||
{"disable-broken-tests-musl", `diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
|
||||
index 2ead810437..f85cbb8b1c 100644
|
||||
--- a/Tests/CMakeLists.txt
|
||||
+++ b/Tests/CMakeLists.txt
|
||||
@@ -384,7 +384,6 @@ if(BUILD_TESTING)
|
||||
add_subdirectory(CMakeLib)
|
||||
endif()
|
||||
add_subdirectory(CMakeOnly)
|
||||
- add_subdirectory(RunCMake)
|
||||
|
||||
add_subdirectory(FindPackageModeMakefileTest)
|
||||
|
||||
@@ -528,9 +527,6 @@ if(BUILD_TESTING)
|
||||
-DCMake_TEST_CUDA:BOOL=${CMake_TEST_CUDA}
|
||||
-DCMake_INSTALL_NAME_TOOL_BUG:BOOL=${CMake_INSTALL_NAME_TOOL_BUG}
|
||||
)
|
||||
- ADD_TEST_MACRO(ExportImport ExportImport)
|
||||
- set_property(TEST ExportImport APPEND
|
||||
- PROPERTY LABELS "CUDA")
|
||||
ADD_TEST_MACRO(Unset Unset)
|
||||
ADD_TEST_MACRO(PolicyScope PolicyScope)
|
||||
ADD_TEST_MACRO(EmptyLibrary EmptyLibrary)
|
||||
@@ -624,7 +620,6 @@ if(BUILD_TESTING)
|
||||
# run test for BundleUtilities on supported platforms/compilers
|
||||
if((MSVC OR
|
||||
MINGW OR
|
||||
- CMAKE_SYSTEM_NAME MATCHES "Linux" OR
|
||||
CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
AND NOT CMAKE_GENERATOR STREQUAL "Watcom WMake")
|
||||
|
||||
@@ -3095,10 +3090,6 @@ if(BUILD_TESTING)
|
||||
"${CMake_SOURCE_DIR}/Tests/CTestTestFdSetSize/test.cmake.in"
|
||||
"${CMake_BINARY_DIR}/Tests/CTestTestFdSetSize/test.cmake"
|
||||
@ONLY ESCAPE_QUOTES)
|
||||
- add_test(CTestTestFdSetSize ${CMAKE_CTEST_COMMAND}
|
||||
- -S "${CMake_BINARY_DIR}/Tests/CTestTestFdSetSize/test.cmake" -j20 -V --timeout 120
|
||||
- --output-log "${CMake_BINARY_DIR}/Tests/CTestTestFdSetSize/testOutput.log"
|
||||
- )
|
||||
|
||||
if(CMAKE_TESTS_CDASH_SERVER)
|
||||
set(regex "^([^:]+)://([^/]+)(.*)$")
|
||||
`},
|
||||
},
|
||||
}, &MakeHelper{
|
||||
OmitDefaults: true,
|
||||
|
||||
ConfigureName: "/usr/src/cmake/bootstrap",
|
||||
Configure: []KV{
|
||||
{"prefix", "/system"},
|
||||
{"parallel", jobsE},
|
||||
{"--"},
|
||||
{"-DCMAKE_USE_OPENSSL", "OFF"},
|
||||
{"-DCMake_TEST_NO_NETWORK", "ON"},
|
||||
},
|
||||
Check: []string{
|
||||
"CTEST_OUTPUT_ON_FAILURE=1",
|
||||
"CTEST_PARALLEL_LEVEL=128",
|
||||
"test",
|
||||
},
|
||||
},
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[CMake] = Metadata{
|
||||
f: Toolchain.newCMake,
|
||||
|
||||
Name: "cmake",
|
||||
Description: "cross-platform, open-source build system",
|
||||
Website: "https://cmake.org/",
|
||||
|
||||
ID: 306,
|
||||
}
|
||||
}
|
||||
// CMake is the package used by [CMakeHelper].
|
||||
var CMake = H("cmake")
|
||||
|
||||
// CMakeHelper is the [CMake] build system helper.
|
||||
type CMakeHelper struct {
|
||||
@@ -164,7 +56,7 @@ func (*CMakeHelper) createDir() bool { return true }
|
||||
func (*CMakeHelper) wantsDir() string { return "/cure/" }
|
||||
|
||||
// script generates the cure script.
|
||||
func (attr *CMakeHelper) script(name string) string {
|
||||
func (attr *CMakeHelper) script(t Toolchain, name string) string {
|
||||
if attr == nil {
|
||||
attr = new(CMakeHelper)
|
||||
}
|
||||
@@ -180,7 +72,7 @@ func (attr *CMakeHelper) script(name string) string {
|
||||
}
|
||||
|
||||
script := attr.Script
|
||||
if !attr.SkipTest && presetOpts&OptSkipCheck == 0 {
|
||||
if !attr.SkipTest && t.opts&OptSkipCheck == 0 {
|
||||
script += "\n" + test
|
||||
}
|
||||
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newCurl() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "8.19.0"
|
||||
checksum = "YHuVLVVp8q_Y7-JWpID5ReNjq2Zk6t7ArHB6ngQXilp_R5l3cubdxu3UKo-xDByv"
|
||||
)
|
||||
return t.NewPackage("curl", version, newTar(
|
||||
"https://curl.se/download/curl-"+version+".tar.bz2",
|
||||
checksum,
|
||||
pkg.TarBzip2,
|
||||
), &PackageAttr{
|
||||
// remove broken test
|
||||
Writable: true,
|
||||
ScriptEarly: `
|
||||
chmod +w tests/data && rm -f tests/data/test459
|
||||
`,
|
||||
}, &MakeHelper{
|
||||
Configure: []KV{
|
||||
{"with-openssl"},
|
||||
{"with-ca-bundle", "/system/etc/ssl/certs/ca-bundle.crt"},
|
||||
|
||||
{"disable-smb"},
|
||||
},
|
||||
Check: []string{
|
||||
"TFLAGS=" + jobsLFlagE,
|
||||
"test-nonflaky",
|
||||
},
|
||||
},
|
||||
Perl,
|
||||
Python,
|
||||
PkgConfig,
|
||||
Diffutils,
|
||||
|
||||
Libpsl,
|
||||
OpenSSL,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Curl] = Metadata{
|
||||
f: Toolchain.newCurl,
|
||||
|
||||
Name: "curl",
|
||||
Description: "command line tool and library for transferring data with URLs",
|
||||
Website: "https://curl.se/",
|
||||
|
||||
Dependencies: P{
|
||||
Libpsl,
|
||||
OpenSSL,
|
||||
},
|
||||
|
||||
ID: 381,
|
||||
}
|
||||
}
|
||||
@@ -29,9 +29,7 @@ func (t Toolchain) newDBus() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[DBus] = Metadata{
|
||||
f: Toolchain.newDBus,
|
||||
|
||||
native.mustRegister(Toolchain.newDBus, &Metadata{
|
||||
Name: "dbus",
|
||||
Description: "a message bus system",
|
||||
Website: "https://www.freedesktop.org/wiki/Software/dbus/",
|
||||
@@ -42,7 +40,7 @@ func init() {
|
||||
},
|
||||
|
||||
ID: 5356,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newXDGDBusProxy() (pkg.Artifact, string) {
|
||||
@@ -65,9 +63,7 @@ func (t Toolchain) newXDGDBusProxy() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[XDGDBusProxy] = Metadata{
|
||||
f: Toolchain.newXDGDBusProxy,
|
||||
|
||||
native.mustRegister(Toolchain.newXDGDBusProxy, &Metadata{
|
||||
Name: "xdg-dbus-proxy",
|
||||
Description: "a filtering proxy for D-Bus connections",
|
||||
Website: "https://github.com/flatpak/xdg-dbus-proxy",
|
||||
@@ -77,5 +73,5 @@ func init() {
|
||||
},
|
||||
|
||||
ID: 58434,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -31,13 +31,11 @@ func (t Toolchain) newDTC() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[DTC] = Metadata{
|
||||
f: Toolchain.newDTC,
|
||||
|
||||
native.mustRegister(Toolchain.newDTC, &Metadata{
|
||||
Name: "dtc",
|
||||
Description: "The Device Tree Compiler",
|
||||
Website: "https://git.kernel.org/pub/scm/utils/dtc/dtc.git/",
|
||||
|
||||
ID: 16911,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -39,9 +39,7 @@ func (t Toolchain) newElfutils() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Elfutils] = Metadata{
|
||||
f: Toolchain.newElfutils,
|
||||
|
||||
native.mustRegister(Toolchain.newElfutils, &Metadata{
|
||||
Name: "elfutils",
|
||||
Description: "utilities and libraries to handle ELF files and DWARF data",
|
||||
Website: "https://sourceware.org/elfutils/",
|
||||
@@ -55,5 +53,5 @@ func init() {
|
||||
},
|
||||
|
||||
ID: 5679,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newFakeroot() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.37.2"
|
||||
checksum = "4ve-eDqVspzQ6VWDhPS0NjW3aSenBJcPAJq_BFT7OOFgUdrQzoTBxZWipDAGWxF8"
|
||||
)
|
||||
return t.NewPackage("fakeroot", version, newFromGitLab(
|
||||
"salsa.debian.org",
|
||||
"clint/fakeroot",
|
||||
"upstream/"+version,
|
||||
checksum,
|
||||
), &PackageAttr{
|
||||
Patches: []KV{
|
||||
{"remove-broken-docs", `diff --git a/doc/Makefile.am b/doc/Makefile.am
|
||||
index f135ad9..85c784c 100644
|
||||
--- a/doc/Makefile.am
|
||||
+++ b/doc/Makefile.am
|
||||
@@ -1,5 +1,4 @@
|
||||
AUTOMAKE_OPTIONS=foreign
|
||||
-SUBDIRS = de es fr nl pt ro sv
|
||||
|
||||
man_MANS = faked.1 fakeroot.1
|
||||
|
||||
`},
|
||||
},
|
||||
|
||||
Env: []string{
|
||||
"CONFIG_SHELL=/bin/sh",
|
||||
},
|
||||
}, &MakeHelper{
|
||||
Generate: "./bootstrap",
|
||||
|
||||
// makes assumptions about /etc/passwd
|
||||
SkipCheck: true,
|
||||
},
|
||||
Automake,
|
||||
Libtool,
|
||||
PkgConfig,
|
||||
|
||||
Attr,
|
||||
Libcap,
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Fakeroot] = Metadata{
|
||||
f: Toolchain.newFakeroot,
|
||||
|
||||
Name: "fakeroot",
|
||||
Description: "tool for simulating superuser privileges",
|
||||
Website: "https://salsa.debian.org/clint/fakeroot",
|
||||
|
||||
ID: 12048,
|
||||
}
|
||||
}
|
||||
@@ -20,13 +20,11 @@ func (t Toolchain) newFlex() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Flex] = Metadata{
|
||||
f: Toolchain.newFlex,
|
||||
|
||||
native.mustRegister(Toolchain.newFlex, &Metadata{
|
||||
Name: "flex",
|
||||
Description: "scanner generator for lexing in C and C++",
|
||||
Website: "https://github.com/westes/flex/",
|
||||
|
||||
ID: 819,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
25
internal/rosa/freetype.go
Normal file
25
internal/rosa/freetype.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newFreetype() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.14.3"
|
||||
checksum = "-WfLv8fVJNyCHpP_lriiDzOcVbBL9ajdQ3tl8AzIIUa9-8sVpU9irxOmSMgRHWYz"
|
||||
)
|
||||
return t.NewPackage("freetype", version, newTar(
|
||||
"https://download.savannah.gnu.org/releases/freetype/"+
|
||||
"freetype-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, (*MakeHelper)(nil)), version
|
||||
}
|
||||
func init() {
|
||||
native.mustRegister(Toolchain.newFreetype, &Metadata{
|
||||
Name: "freetype",
|
||||
Description: "a freely available software library to render fonts",
|
||||
Website: "http://www.freetype.org/",
|
||||
|
||||
ID: 854,
|
||||
})
|
||||
}
|
||||
@@ -31,13 +31,11 @@ func (t Toolchain) newFuse() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Fuse] = Metadata{
|
||||
f: Toolchain.newFuse,
|
||||
|
||||
native.mustRegister(Toolchain.newFuse, &Metadata{
|
||||
Name: "fuse",
|
||||
Description: "the reference implementation of the Linux FUSE interface",
|
||||
Website: "https://github.com/libfuse/libfuse/",
|
||||
|
||||
ID: 861,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -7,98 +7,8 @@ import (
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
func (t Toolchain) newGit() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.54.0"
|
||||
checksum = "7vGKtFOJGqY8DO4e8UMRax7dLgImXKQz5MMalec6MlgYrsarffSJjgOughwRFpSH"
|
||||
)
|
||||
return t.NewPackage("git", version, newTar(
|
||||
"https://www.kernel.org/pub/software/scm/git/"+
|
||||
"git-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), &PackageAttr{
|
||||
ScriptEarly: `
|
||||
ln -s ../../system/bin/perl /usr/bin/ || true
|
||||
|
||||
# test suite assumes apache
|
||||
rm -f /system/bin/httpd
|
||||
`,
|
||||
|
||||
// uses source tree as scratch space
|
||||
EnterSource: true,
|
||||
}, &MakeHelper{
|
||||
InPlace: true,
|
||||
Generate: "make configure",
|
||||
ScriptMakeEarly: `
|
||||
function disable_test {
|
||||
local test=$1 pattern=${2:-''}
|
||||
if [ $# -eq 1 ]; then
|
||||
rm "t/${test}.sh"
|
||||
else
|
||||
sed -i "t/${test}.sh" \
|
||||
-e "/^\s*test_expect_.*$pattern/,/^\s*' *\$/{s/^/: #/}"
|
||||
fi
|
||||
}
|
||||
|
||||
disable_test t1800-hook
|
||||
disable_test t5319-multi-pack-index
|
||||
disable_test t1305-config-include
|
||||
disable_test t3900-i18n-commit
|
||||
disable_test t3507-cherry-pick-conflict
|
||||
disable_test t4201-shortlog
|
||||
disable_test t5303-pack-corruption-resilience
|
||||
disable_test t4301-merge-tree-write-tree
|
||||
disable_test t8005-blame-i18n
|
||||
disable_test t9350-fast-export
|
||||
disable_test t9300-fast-import
|
||||
disable_test t0211-trace2-perf
|
||||
disable_test t1517-outside-repo
|
||||
disable_test t2200-add-update
|
||||
disable_test t0027-auto-crlf
|
||||
disable_test t7513-interpret-trailers
|
||||
disable_test t7703-repack-geometric
|
||||
`,
|
||||
Check: []string{
|
||||
"-C t",
|
||||
`GIT_PROVE_OPTS="--jobs 32 --failures"`,
|
||||
"prove",
|
||||
},
|
||||
Install: `make \
|
||||
` + jobsFlagE + ` \
|
||||
DESTDIR=/work \
|
||||
NO_INSTALL_HARDLINKS=1 \
|
||||
install`,
|
||||
},
|
||||
// test suite hangs on mksh
|
||||
Bash,
|
||||
|
||||
Diffutils,
|
||||
Autoconf,
|
||||
Gettext,
|
||||
|
||||
Zlib,
|
||||
Curl,
|
||||
Libexpat,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Git] = Metadata{
|
||||
f: Toolchain.newGit,
|
||||
|
||||
Name: "git",
|
||||
Description: "distributed version control system",
|
||||
Website: "https://www.git-scm.com/",
|
||||
|
||||
Dependencies: P{
|
||||
Zlib,
|
||||
Curl,
|
||||
Libexpat,
|
||||
},
|
||||
|
||||
ID: 5350,
|
||||
}
|
||||
}
|
||||
// Git is the package used by [Toolchain.NewViaGit].
|
||||
var Git = H("git")
|
||||
|
||||
// NewViaGit returns a [pkg.Artifact] for cloning a git repository.
|
||||
func (t Toolchain) NewViaGit(
|
||||
@@ -108,7 +18,7 @@ func (t Toolchain) NewViaGit(
|
||||
return t.New(strings.TrimSuffix(
|
||||
path.Base(url),
|
||||
".git",
|
||||
)+"-src-"+path.Base(rev), 0, t.AppendPresets(nil,
|
||||
)+"-src-"+path.Base(rev), THostNet, t.Append(nil,
|
||||
NSSCACert,
|
||||
Git,
|
||||
), &checksum, nil, `
|
||||
|
||||
@@ -22,9 +22,7 @@ func (t Toolchain) newSPIRVHeaders() (pkg.Artifact, string) {
|
||||
}), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[SPIRVHeaders] = Metadata{
|
||||
f: Toolchain.newSPIRVHeaders,
|
||||
|
||||
native.mustRegister(Toolchain.newSPIRVHeaders, &Metadata{
|
||||
Name: "spirv-headers",
|
||||
Description: "machine-readable files for the SPIR-V Registry",
|
||||
Website: "https://github.com/KhronosGroup/SPIRV-Headers",
|
||||
@@ -49,7 +47,7 @@ func init() {
|
||||
}
|
||||
return v.Latest
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newSPIRVTools() (pkg.Artifact, string) {
|
||||
@@ -72,9 +70,7 @@ func (t Toolchain) newSPIRVTools() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[SPIRVTools] = Metadata{
|
||||
f: Toolchain.newSPIRVTools,
|
||||
|
||||
native.mustRegister(Toolchain.newSPIRVTools, &Metadata{
|
||||
Name: "spirv-tools",
|
||||
Description: "an API and commands for processing SPIR-V modules",
|
||||
Website: "https://github.com/KhronosGroup/SPIRV-Tools",
|
||||
@@ -86,13 +82,13 @@ func init() {
|
||||
ID: 14894,
|
||||
|
||||
latest: (*Versions).getStable,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newGlslang() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "16.2.0"
|
||||
checksum = "6_UuF9reLRDaVkgO-9IfB3kMwme3lQZM8LL8YsJwPdUFkrjzxJtf2A9X3w9nFxj2"
|
||||
version = "16.3.0"
|
||||
checksum = "xyqDf8k3-D0_BXHGi0uLgMglnJ05Rf3j73QgbDs3sGtKNdBIQhY8JfqX1NcNoJQN"
|
||||
)
|
||||
return t.NewPackage("glslang", version, newFromGitHub(
|
||||
"KhronosGroup/glslang",
|
||||
@@ -116,15 +112,13 @@ func (t Toolchain) newGlslang() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Glslang] = Metadata{
|
||||
f: Toolchain.newGlslang,
|
||||
|
||||
native.mustRegister(Toolchain.newGlslang, &Metadata{
|
||||
Name: "glslang",
|
||||
Description: "reference front end for GLSL/ESSL",
|
||||
Website: "https://github.com/KhronosGroup/glslang",
|
||||
|
||||
ID: 205796,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newSPIRVLLVMTranslator() (pkg.Artifact, string) {
|
||||
@@ -137,7 +131,7 @@ func (t Toolchain) newSPIRVLLVMTranslator() (pkg.Artifact, string) {
|
||||
"cooperative_matrix_constant_null.spvasm",
|
||||
}
|
||||
|
||||
switch arch {
|
||||
switch t.arch {
|
||||
case "arm64":
|
||||
skipChecks = append(skipChecks,
|
||||
// LLVM ERROR: unsupported calling convention
|
||||
@@ -189,9 +183,18 @@ func (t Toolchain) newSPIRVLLVMTranslator() (pkg.Artifact, string) {
|
||||
), &PackageAttr{
|
||||
Patches: []KV{
|
||||
{"remove-early-prefix", `diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index c000a77e..86f79b03 100644
|
||||
index c000a77e..f18f3fde 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -164,7 +164,7 @@ install(
|
||||
${LLVM_SPIRV_INCLUDE_DIRS}/LLVMSPIRVOpts.h
|
||||
${LLVM_SPIRV_INCLUDE_DIRS}/LLVMSPIRVExtensions.inc
|
||||
DESTINATION
|
||||
- ${CMAKE_INSTALL_PREFIX}/include/LLVMSPIRVLib
|
||||
+ include/LLVMSPIRVLib
|
||||
)
|
||||
|
||||
configure_file(LLVMSPIRVLib.pc.in ${CMAKE_BINARY_DIR}/LLVMSPIRVLib.pc @ONLY)
|
||||
@@ -172,5 +172,5 @@ install(
|
||||
FILES
|
||||
${CMAKE_BINARY_DIR}/LLVMSPIRVLib.pc
|
||||
@@ -199,7 +202,7 @@ index c000a77e..86f79b03 100644
|
||||
- ${CMAKE_INSTALL_PREFIX}/lib${LLVM_LIBDIR_SUFFIX}/pkgconfig
|
||||
+ lib${LLVM_LIBDIR_SUFFIX}/pkgconfig
|
||||
)
|
||||
`},
|
||||
;`},
|
||||
},
|
||||
|
||||
// litArgs emits shell syntax
|
||||
@@ -223,9 +226,7 @@ export LIT_OPTS=` + litArgs(true, skipChecks...) + `
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[SPIRVLLVMTranslator] = Metadata{
|
||||
f: Toolchain.newSPIRVLLVMTranslator,
|
||||
|
||||
native.mustRegister(Toolchain.newSPIRVLLVMTranslator, &Metadata{
|
||||
Name: "spirv-llvm-translator",
|
||||
Description: "bi-directional translation between SPIR-V and LLVM IR",
|
||||
Website: "https://github.com/KhronosGroup/SPIRV-LLVM-Translator",
|
||||
@@ -235,5 +236,5 @@ func init() {
|
||||
},
|
||||
|
||||
ID: 227273,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
1366
internal/rosa/gnu.go
1366
internal/rosa/gnu.go
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@ import (
|
||||
// newGoBootstrap returns the Go bootstrap toolchain.
|
||||
func (t Toolchain) newGoBootstrap() pkg.Artifact {
|
||||
const checksum = "8o9JL_ToiQKadCTb04nvBDkp8O1xiWOolAxVEqaTGodieNe4lOFEjlOxN3bwwe23"
|
||||
return t.New("go1.4-bootstrap", 0, t.AppendPresets(nil,
|
||||
return t.New("go1.4-bootstrap", 0, t.Append(nil,
|
||||
Bash,
|
||||
), nil, []string{
|
||||
"CGO_ENABLED=0",
|
||||
@@ -35,10 +35,10 @@ func (t Toolchain) newGo(
|
||||
extra ...pkg.Artifact,
|
||||
) pkg.Artifact {
|
||||
name := "all"
|
||||
if presetOpts&OptSkipCheck != 0 {
|
||||
if t.opts&OptSkipCheck != 0 {
|
||||
name = "make"
|
||||
}
|
||||
return t.New("go"+version, 0, t.AppendPresets(extra,
|
||||
return t.New("go"+version, 0, t.Append(extra,
|
||||
Bash,
|
||||
), nil, slices.Concat([]string{
|
||||
"CC=cc",
|
||||
@@ -72,17 +72,17 @@ func (t Toolchain) newGoLatest() (pkg.Artifact, string) {
|
||||
|
||||
finalEnv []string
|
||||
)
|
||||
switch arch {
|
||||
switch t.arch {
|
||||
case "amd64":
|
||||
bootstrapExtra = append(bootstrapExtra, t.newGoBootstrap())
|
||||
|
||||
case "arm64", "riscv64":
|
||||
bootstrapEnv = append(bootstrapEnv, "GOROOT_BOOTSTRAP=/system")
|
||||
bootstrapExtra = t.AppendPresets(bootstrapExtra, gcc)
|
||||
bootstrapExtra = t.Append(bootstrapExtra, gcc)
|
||||
finalEnv = append(finalEnv, "CGO_ENABLED=0")
|
||||
|
||||
default:
|
||||
panic("unsupported target " + arch)
|
||||
panic("unsupported target " + t.arch)
|
||||
}
|
||||
|
||||
go119 := t.newGo(
|
||||
@@ -106,8 +106,8 @@ echo \
|
||||
"YtrDka402BOAEwywx03Vz4QlVwoBiguJHzG7PuythMCPHXS8CVMLvzmvgEbu4Tzu",
|
||||
[]string{"CGO_ENABLED=0"}, `
|
||||
sed -i \
|
||||
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
cmd/link/internal/`+arch+`/obj.go
|
||||
's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
cmd/link/internal/`+t.arch+`/obj.go
|
||||
|
||||
rm \
|
||||
crypto/tls/handshake_client_test.go \
|
||||
@@ -124,8 +124,8 @@ echo \
|
||||
"wcI32bl1tkqbgcelGtGWPI4RtlEddd-PTd76Eb-k7nXA5LbE9yTNdIL9QSOOxMOs",
|
||||
[]string{"CGO_ENABLED=0"}, `
|
||||
sed -i \
|
||||
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
cmd/link/internal/`+arch+`/obj.go
|
||||
's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
cmd/link/internal/`+t.arch+`/obj.go
|
||||
`, go121,
|
||||
)
|
||||
|
||||
@@ -134,8 +134,8 @@ sed -i \
|
||||
"TwKwatkpwal-j9U2sDSRPEdM3YesI4Gm88YgGV59wtU-L85K9gA7UPy9SCxn6PMb",
|
||||
[]string{"CGO_ENABLED=0"}, `
|
||||
sed -i \
|
||||
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
cmd/link/internal/`+arch+`/obj.go
|
||||
's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
cmd/link/internal/`+t.arch+`/obj.go
|
||||
|
||||
rm \
|
||||
os/root_unix_test.go \
|
||||
@@ -152,8 +152,8 @@ rm \
|
||||
checksum,
|
||||
finalEnv, `
|
||||
sed -i \
|
||||
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
cmd/link/internal/`+arch+`/obj.go
|
||||
's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
cmd/link/internal/`+t.arch+`/obj.go
|
||||
sed -i \
|
||||
's/cpu.X86.HasAVX512VBMI/& \&\& cpu.X86.HasPOPCNT/' \
|
||||
internal/runtime/gc/scan/scan_amd64.go
|
||||
@@ -166,13 +166,11 @@ rm \
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Go] = Metadata{
|
||||
f: Toolchain.newGoLatest,
|
||||
|
||||
native.mustRegister(Toolchain.newGoLatest, &Metadata{
|
||||
Name: "go",
|
||||
Description: "the Go programming language toolchain",
|
||||
Website: "https://go.dev/",
|
||||
|
||||
ID: 1227,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
|
||||
func (t Toolchain) newGLib() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.88.0"
|
||||
checksum = "T79Cg4z6j-sDZ2yIwvbY4ccRv2-fbwbqgcw59F5NQ6qJT6z4v261vbYp3dHO6Ma3"
|
||||
version = "2.88.1"
|
||||
checksum = "Rkszn6W4RHjyspyqfXdVAVawdwDJCuS0Zu0f7qot7tbJhnw2fUDoUUJB40m-1MCX"
|
||||
)
|
||||
return t.NewPackage("glib", version, t.newTagRemote(
|
||||
"https://gitlab.gnome.org/GNOME/glib.git",
|
||||
@@ -42,9 +42,7 @@ func (t Toolchain) newGLib() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[GLib] = Metadata{
|
||||
f: Toolchain.newGLib,
|
||||
|
||||
native.mustRegister(Toolchain.newGLib, &Metadata{
|
||||
Name: "glib",
|
||||
Description: "the GNU library of miscellaneous stuff",
|
||||
Website: "https://developer.gnome.org/glib/",
|
||||
@@ -56,5 +54,5 @@ func init() {
|
||||
},
|
||||
|
||||
ID: 10024,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package rosa
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newHakurei(
|
||||
suffix, script string,
|
||||
suffix, build, check, install string,
|
||||
withHostname bool,
|
||||
) pkg.Artifact {
|
||||
hostname := `
|
||||
@@ -14,7 +14,40 @@ go build -o /bin/hostname /usr/src/hostname/main.go
|
||||
hostname = ""
|
||||
}
|
||||
|
||||
return t.New("hakurei"+suffix+"-"+hakureiVersion, 0, t.AppendPresets(nil,
|
||||
name := "hakurei" + suffix
|
||||
return t.NewPackage(name, hakureiVersion, t.NewPatchedSource(
|
||||
"hakurei", hakureiVersion, hakureiSource, false, hakureiPatches...,
|
||||
), &PackageAttr{
|
||||
Writable: true,
|
||||
Env: []string{
|
||||
"CGO_ENABLED=1",
|
||||
"GOCACHE=/tmp/gocache",
|
||||
"CC=clang -O3 -Werror",
|
||||
},
|
||||
|
||||
Paths: []pkg.ExecPath{pkg.Path(AbsUsrSrc.Append("hostname", "main.go"), false, pkg.NewFile(
|
||||
"hostname.go",
|
||||
[]byte(`
|
||||
package main
|
||||
|
||||
import "os"
|
||||
|
||||
func main() {
|
||||
if name, err := os.Hostname(); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
os.Stdout.WriteString(name)
|
||||
}
|
||||
}
|
||||
`),
|
||||
))},
|
||||
}, &GenericHelper{
|
||||
Build: hostname + `
|
||||
HAKUREI_VERSION='v` + hakureiVersion + `'
|
||||
` + build,
|
||||
Check: check,
|
||||
Install: install,
|
||||
},
|
||||
Go,
|
||||
PkgConfig,
|
||||
|
||||
@@ -30,37 +63,19 @@ go build -o /bin/hostname /usr/src/hostname/main.go
|
||||
WaylandProtocols,
|
||||
|
||||
KernelHeaders,
|
||||
), nil, []string{
|
||||
"CGO_ENABLED=1",
|
||||
"GOCACHE=/tmp/gocache",
|
||||
"CC=clang -O3 -Werror",
|
||||
}, hostname+`
|
||||
cd /usr/src/hakurei
|
||||
|
||||
HAKUREI_VERSION='v`+hakureiVersion+`'
|
||||
`+script, pkg.Path(AbsUsrSrc.Append("hakurei"), true, t.NewPatchedSource(
|
||||
"hakurei", hakureiVersion, hakureiSource, false, hakureiPatches...,
|
||||
)), pkg.Path(AbsUsrSrc.Append("hostname", "main.go"), false, pkg.NewFile(
|
||||
"hostname.go",
|
||||
[]byte(`
|
||||
package main
|
||||
|
||||
import "os"
|
||||
|
||||
func main() {
|
||||
if name, err := os.Hostname(); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
os.Stdout.WriteString(name)
|
||||
}
|
||||
}
|
||||
`),
|
||||
)))
|
||||
)
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Hakurei] = Metadata{
|
||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||
return t.newHakurei("", `
|
||||
meta := Metadata{
|
||||
Name: "hakurei",
|
||||
Description: "low-level userspace tooling for Rosa OS",
|
||||
Website: "https://hakurei.app",
|
||||
Version: hakureiVersion,
|
||||
|
||||
ID: 388834,
|
||||
}
|
||||
native.MustRegister(meta.Name, func(t Toolchain) (*Metadata, pkg.Artifact) {
|
||||
return &meta, t.newHakurei("", `
|
||||
mkdir -p /work/system/libexec/hakurei/
|
||||
|
||||
echo "Building hakurei for $(go env GOOS)/$(go env GOARCH)."
|
||||
@@ -75,35 +90,34 @@ go build -trimpath -tags=rosa -o /work/system/libexec/hakurei -ldflags="-s -w
|
||||
-X main.hakureiPath=/system/bin/hakurei
|
||||
" ./...
|
||||
echo
|
||||
|
||||
`, `
|
||||
echo '##### Testing hakurei.'
|
||||
go test -ldflags='-buildid= -linkmode external -extldflags=-static' ./...
|
||||
echo
|
||||
|
||||
`, `
|
||||
mkdir -p /work/system/bin/
|
||||
(cd /work/system/libexec/hakurei && mv \
|
||||
hakurei \
|
||||
sharefs \
|
||||
../../bin/)
|
||||
`, true), hakureiVersion
|
||||
},
|
||||
|
||||
Name: "hakurei",
|
||||
Description: "low-level userspace tooling for Rosa OS",
|
||||
Website: "https://hakurei.app/",
|
||||
|
||||
ID: 388834,
|
||||
}
|
||||
artifactsM[HakureiDist] = Metadata{
|
||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||
return t.newHakurei("-dist", `
|
||||
export HAKUREI_VERSION
|
||||
DESTDIR=/work /usr/src/hakurei/all.sh
|
||||
`, true), hakureiVersion
|
||||
},
|
||||
|
||||
`, true)
|
||||
})
|
||||
}
|
||||
func init() {
|
||||
meta := Metadata{
|
||||
Name: "hakurei-dist",
|
||||
Description: "low-level userspace tooling for Rosa OS (distribution tarball)",
|
||||
Website: "https://hakurei.app/",
|
||||
Website: "https://hakurei.app",
|
||||
Version: hakureiVersion,
|
||||
}
|
||||
native.MustRegister(meta.Name, func(t Toolchain) (*Metadata, pkg.Artifact) {
|
||||
name := "all"
|
||||
if t.opts&OptSkipCheck != 0 {
|
||||
name = "make"
|
||||
}
|
||||
return &meta, t.newHakurei("-dist", `
|
||||
export HAKUREI_VERSION
|
||||
DESTDIR=/work ./`+name+`.sh
|
||||
`, "", "", true)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@ package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
const hakureiVersion = "0.4.1"
|
||||
const hakureiVersion = "0.4.2"
|
||||
|
||||
// hakureiSource is the source code of a hakurei release.
|
||||
var hakureiSource = newTar(
|
||||
"https://git.gensokyo.uk/rosa/hakurei/archive/"+
|
||||
"v"+hakureiVersion+".tar.gz",
|
||||
"8bHvZcjUQOXUPbKL-qq99pHFTPnn-h7j1fkJudbGs8waLm3OmkI6eHfQev5bug2y",
|
||||
"jadgaOrxv5ABGvzQ_Rk0aPGz7U8K-427TbMhQNQ32scSizEnlR44Pu7NoWYWVZWq",
|
||||
pkg.TarGzip,
|
||||
)
|
||||
|
||||
|
||||
@@ -22,13 +22,11 @@ func (t Toolchain) newHwdata() (pkg.Artifact, string) {
|
||||
}), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Hwdata] = Metadata{
|
||||
f: Toolchain.newHwdata,
|
||||
|
||||
native.mustRegister(Toolchain.newHwdata, &Metadata{
|
||||
Name: "hwdata",
|
||||
Description: "contains various hardware identification and configuration data",
|
||||
Website: "https://github.com/vcrhonek/hwdata",
|
||||
|
||||
ID: 5387,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,12 +6,13 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
artifactsM[EarlyInit] = Metadata{
|
||||
meta := Metadata{
|
||||
Name: "earlyinit",
|
||||
Description: "Rosa OS initramfs init program",
|
||||
|
||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||
return t.newHakurei("-early-init", `
|
||||
Version: Unversioned,
|
||||
}
|
||||
native.MustRegister(meta.Name, func(t Toolchain) (*Metadata, pkg.Artifact) {
|
||||
return &meta, t.newHakurei("-early-init", `
|
||||
mkdir -p /work/system/libexec/hakurei/
|
||||
|
||||
echo '# Building earlyinit.'
|
||||
@@ -22,54 +23,51 @@ go build -trimpath -v -o /work/system/libexec/hakurei -ldflags="-s -w
|
||||
-X hakurei.app/internal/info.buildVersion=${HAKUREI_VERSION}
|
||||
" ./cmd/earlyinit
|
||||
echo
|
||||
`, false), Unversioned
|
||||
},
|
||||
}
|
||||
`, "", "", false)
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newImageSystem() (pkg.Artifact, string) {
|
||||
return t.New("system.img", TNoToolchain, t.AppendPresets(nil,
|
||||
SquashfsTools,
|
||||
), nil, nil, `
|
||||
mksquashfs /mnt/system /work/system.img
|
||||
`, pkg.Path(fhs.AbsRoot.Append("mnt"), false, t.AppendPresets(nil,
|
||||
Musl,
|
||||
Mksh,
|
||||
Toybox,
|
||||
|
||||
Kmod,
|
||||
Kernel,
|
||||
Firmware,
|
||||
)...)), Unversioned
|
||||
}
|
||||
func init() {
|
||||
artifactsM[ImageSystem] = Metadata{
|
||||
meta := Metadata{
|
||||
Name: "system-image",
|
||||
Description: "Rosa OS system image",
|
||||
|
||||
f: Toolchain.newImageSystem,
|
||||
Version: Unversioned,
|
||||
}
|
||||
native.MustRegister(meta.Name, func(t Toolchain) (*Metadata, pkg.Artifact) {
|
||||
return &meta, t.New("system.img", TNoToolchain, t.Append(nil,
|
||||
SquashfsTools,
|
||||
), nil, nil, `
|
||||
mksquashfs /mnt/system /work/system.img
|
||||
`, pkg.Path(fhs.AbsRoot.Append("mnt"), false, t.Append(nil,
|
||||
Musl,
|
||||
Mksh,
|
||||
Toybox,
|
||||
|
||||
Kmod,
|
||||
Kernel,
|
||||
Firmware,
|
||||
)...))
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newImageInitramfs() (pkg.Artifact, string) {
|
||||
return t.New("initramfs", TNoToolchain, t.AppendPresets(nil,
|
||||
Zstd,
|
||||
EarlyInit,
|
||||
GenInitCPIO,
|
||||
), nil, nil, `
|
||||
func init() {
|
||||
meta := Metadata{
|
||||
Name: "initramfs-image",
|
||||
Description: "Rosa OS initramfs image",
|
||||
Version: Unversioned,
|
||||
}
|
||||
native.MustRegister(meta.Name, func(t Toolchain) (*Metadata, pkg.Artifact) {
|
||||
return &meta, t.New("initramfs", TNoToolchain, t.Append(nil,
|
||||
Zstd,
|
||||
EarlyInit,
|
||||
GenInitCPIO,
|
||||
), nil, nil, `
|
||||
gen_init_cpio -t 4294967295 -c /usr/src/initramfs | zstd > /work/initramfs.zst
|
||||
`, pkg.Path(AbsUsrSrc.Append("initramfs"), false, pkg.NewFile("initramfs", []byte(`
|
||||
dir /dev 0755 0 0
|
||||
nod /dev/null 0666 0 0 c 1 3
|
||||
nod /dev/console 0600 0 0 c 5 1
|
||||
file /init /system/libexec/hakurei/earlyinit 0555 0 0
|
||||
`)))), Unversioned
|
||||
}
|
||||
func init() {
|
||||
artifactsM[ImageInitramfs] = Metadata{
|
||||
Name: "initramfs-image",
|
||||
Description: "Rosa OS initramfs image",
|
||||
|
||||
f: Toolchain.newImageInitramfs,
|
||||
}
|
||||
`))))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
package rosa
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed kernel_amd64.config
|
||||
var kernelConfig []byte
|
||||
|
||||
const kernelName = "bzImage"
|
||||
@@ -1,8 +0,0 @@
|
||||
package rosa
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed kernel_arm64.config
|
||||
var kernelConfig []byte
|
||||
|
||||
const kernelName = "vmlinuz.efi"
|
||||
@@ -1,8 +0,0 @@
|
||||
package rosa
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed kernel_riscv64.config
|
||||
var kernelConfig []byte
|
||||
|
||||
const kernelName = "bzImage"
|
||||
@@ -32,9 +32,7 @@ func (t Toolchain) newKmod() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Kmod] = Metadata{
|
||||
f: Toolchain.newKmod,
|
||||
|
||||
native.mustRegister(Toolchain.newKmod, &Metadata{
|
||||
Name: "kmod",
|
||||
Description: "a set of tools to handle common tasks with Linux kernel modules",
|
||||
Website: "https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git",
|
||||
@@ -46,5 +44,5 @@ func init() {
|
||||
},
|
||||
|
||||
ID: 1517,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -88,13 +88,11 @@ install -Dv /usr/src/CTestCustom.cmake /cure/
|
||||
}, (*CMakeHelper)(nil)), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libarchive] = Metadata{
|
||||
f: Toolchain.newLibarchive,
|
||||
|
||||
native.mustRegister(Toolchain.newLibarchive, &Metadata{
|
||||
Name: "libarchive",
|
||||
Description: "multi-format archive and compression library",
|
||||
Website: "https://www.libarchive.org/",
|
||||
|
||||
ID: 1558,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newLibmd() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.1.0"
|
||||
checksum = "9apYqPPZm0j5HQT8sCsVIhnVIqRD7XgN7kPIaTwTqnTuUq5waUAMq4M7ev8CODJ1"
|
||||
version = "1.2.0"
|
||||
checksum = "1rJ6joAO0wwMZvSfnRNkc1MOhywyAq7SM8VmF92NvDtv7Qdl1LRbjm5fg_DFFtGj"
|
||||
)
|
||||
return t.NewPackage("libmd", version, t.newTagRemote(
|
||||
"https://git.hadrons.org/git/libmd.git",
|
||||
@@ -21,15 +21,13 @@ install -D /usr/src/libmd/src/helper.c src/helper.c
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libmd] = Metadata{
|
||||
f: Toolchain.newLibmd,
|
||||
|
||||
native.mustRegister(Toolchain.newLibmd, &Metadata{
|
||||
Name: "libmd",
|
||||
Description: "Message Digest functions from BSD systems",
|
||||
Website: "https://www.hadrons.org/software/libmd/",
|
||||
|
||||
ID: 15525,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newLibbsd() (pkg.Artifact, string) {
|
||||
@@ -50,13 +48,11 @@ func (t Toolchain) newLibbsd() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libbsd] = Metadata{
|
||||
f: Toolchain.newLibbsd,
|
||||
|
||||
native.mustRegister(Toolchain.newLibbsd, &Metadata{
|
||||
Name: "libbsd",
|
||||
Description: "provides useful functions commonly found on BSD systems",
|
||||
Website: "https://libbsd.freedesktop.org/",
|
||||
|
||||
ID: 1567,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -42,13 +42,11 @@ ln -s ../system/bin/bash /bin/
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libcap] = Metadata{
|
||||
f: Toolchain.newLibcap,
|
||||
|
||||
native.mustRegister(Toolchain.newLibcap, &Metadata{
|
||||
Name: "libcap",
|
||||
Description: "a library for getting and setting POSIX.1e draft 15 capabilities",
|
||||
Website: "https://sites.google.com/site/fullycapable/",
|
||||
|
||||
ID: 1569,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -38,13 +38,11 @@ index eba7eae..f916d2e 100644
|
||||
}, (*CMakeHelper)(nil)), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libconfig] = Metadata{
|
||||
f: Toolchain.newLibconfig,
|
||||
|
||||
native.mustRegister(Toolchain.newLibconfig, &Metadata{
|
||||
Name: "libconfig",
|
||||
Description: "a simple library for processing structured configuration files",
|
||||
Website: "https://hyperrealm.github.io/libconfig/",
|
||||
|
||||
ID: 1580,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -18,13 +18,11 @@ func (t Toolchain) newLibdisplayInfo() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[LibdisplayInfo] = Metadata{
|
||||
f: Toolchain.newLibdisplayInfo,
|
||||
|
||||
native.mustRegister(Toolchain.newLibdisplayInfo, &Metadata{
|
||||
Name: "libdisplay-info",
|
||||
Description: "EDID and DisplayID library",
|
||||
Website: "https://gitlab.freedesktop.org/emersion/libdisplay-info",
|
||||
|
||||
ID: 326668,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
31
internal/rosa/libepoxy.go
Normal file
31
internal/rosa/libepoxy.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newLibepoxy() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.5.10"
|
||||
checksum = "OHI8wshrlGw6BMGrmSyejJtwzM2gPhyFJrTsKxULyKMmYrfgcOe7Iw2ibVoUND_Q"
|
||||
)
|
||||
return t.NewPackage("libepoxy", version, newFromGitHub(
|
||||
"anholt/libepoxy",
|
||||
version,
|
||||
checksum,
|
||||
), nil, &MesonHelper{
|
||||
Setup: []KV{
|
||||
{"Dglx", "no"},
|
||||
{"Degl", "no"},
|
||||
},
|
||||
},
|
||||
LibX11,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.mustRegister(Toolchain.newLibepoxy, &Metadata{
|
||||
Name: "libepoxy",
|
||||
Description: "a library for handling OpenGL function pointer management",
|
||||
Website: "https://github.com/anholt/libepoxy",
|
||||
|
||||
ID: 6090,
|
||||
})
|
||||
}
|
||||
@@ -14,13 +14,11 @@ func (t Toolchain) newLibev() (pkg.Artifact, string) {
|
||||
), nil, (*MakeHelper)(nil)), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libev] = Metadata{
|
||||
f: Toolchain.newLibev,
|
||||
|
||||
native.mustRegister(Toolchain.newLibev, &Metadata{
|
||||
Name: "libev",
|
||||
Description: "a full-featured and high-performance event loop",
|
||||
Website: "http://libev.schmorp.de/",
|
||||
|
||||
ID: 1605,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
|
||||
func (t Toolchain) newLibexpat() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.8.0"
|
||||
checksum = "pnwZ_JSif-OfoWIwk2JYXWHagOWMA3Sh-Ea0p-4Rz9U9mDEeAebhyvnfD7OYOMCk"
|
||||
version = "2.8.1"
|
||||
checksum = "iMEtbOJhQfGof2GxSlxffQSI1va_NDDQ9VIuqcPbNZ0291Dr8wttD5QecYyjIQap"
|
||||
)
|
||||
return t.NewPackage("libexpat", version, newFromGitHubRelease(
|
||||
"libexpat/libexpat",
|
||||
@@ -22,13 +22,11 @@ func (t Toolchain) newLibexpat() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libexpat] = Metadata{
|
||||
f: Toolchain.newLibexpat,
|
||||
|
||||
native.mustRegister(Toolchain.newLibexpat, &Metadata{
|
||||
Name: "libexpat",
|
||||
Description: "a stream-oriented XML parser library",
|
||||
Website: "https://libexpat.github.io/",
|
||||
|
||||
ID: 770,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -18,13 +18,11 @@ func (t Toolchain) newLibffi() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libffi] = Metadata{
|
||||
f: Toolchain.newLibffi,
|
||||
|
||||
native.mustRegister(Toolchain.newLibffi, &Metadata{
|
||||
Name: "libffi",
|
||||
Description: "a portable, high level programming interface to various calling conventions",
|
||||
Website: "https://sourceware.org/libffi/",
|
||||
|
||||
ID: 1611,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -24,9 +24,7 @@ mkdir /dev/shm/gd
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libgd] = Metadata{
|
||||
f: Toolchain.newLibgd,
|
||||
|
||||
native.mustRegister(Toolchain.newLibgd, &Metadata{
|
||||
Name: "libgd",
|
||||
Description: "an open source code library for the dynamic creation of images",
|
||||
Website: "https://libgd.github.io/",
|
||||
@@ -36,5 +34,5 @@ func init() {
|
||||
},
|
||||
|
||||
ID: 880,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -22,9 +22,7 @@ func (t Toolchain) newLibpng() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libpng] = Metadata{
|
||||
f: Toolchain.newLibpng,
|
||||
|
||||
native.mustRegister(Toolchain.newLibpng, &Metadata{
|
||||
Name: "libpng",
|
||||
Description: "the official PNG reference library",
|
||||
Website: "https://www.libpng.org/pub/png/libpng.html",
|
||||
@@ -34,5 +32,5 @@ func init() {
|
||||
},
|
||||
|
||||
ID: 1705,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -25,13 +25,11 @@ test_disable 'int main(){return 0;}' tests/test-is-public-builtin.c
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libpsl] = Metadata{
|
||||
f: Toolchain.newLibpsl,
|
||||
|
||||
native.mustRegister(Toolchain.newLibpsl, &Metadata{
|
||||
Name: "libpsl",
|
||||
Description: "provides functions to work with the Mozilla Public Suffix List",
|
||||
Website: "https://rockdaboot.github.io/libpsl/",
|
||||
|
||||
ID: 7305,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -43,13 +43,11 @@ index adccef3..65a277a 100644
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libseccomp] = Metadata{
|
||||
f: Toolchain.newLibseccomp,
|
||||
|
||||
native.mustRegister(Toolchain.newLibseccomp, &Metadata{
|
||||
Name: "libseccomp",
|
||||
Description: "an interface to the Linux Kernel's syscall filtering mechanism",
|
||||
Website: "https://github.com/seccomp/libseccomp/",
|
||||
|
||||
ID: 13823,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
42
internal/rosa/libtirpc.go
Normal file
42
internal/rosa/libtirpc.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package rosa
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
func (t Toolchain) newLibtirpc() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.3.7"
|
||||
checksum = "nzFfu7LNvnSNiNAryD1vtnNWnU-Xqee8KqfXUKoBf5yjb5-dkeRkYuRijdCoYLof"
|
||||
)
|
||||
return t.NewPackage("libtirpc", version, t.newTagRemote(
|
||||
"git://linux-nfs.org/~steved/libtirpc",
|
||||
"libtirpc-"+
|
||||
strings.Join(strings.SplitN(version, ".", 3), "-"),
|
||||
checksum,
|
||||
), nil, &MakeHelper{
|
||||
Generate: "sh -e ./bootstrap",
|
||||
Configure: []KV{
|
||||
{"CFLAGS", `"$(pkg-config --cflags libbsd-overlay) ${CFLAGS:-}"`},
|
||||
{"disable-gssapi"},
|
||||
},
|
||||
},
|
||||
Automake,
|
||||
Libtool,
|
||||
PkgConfig,
|
||||
|
||||
Libbsd,
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.mustRegister(Toolchain.newLibtirpc, &Metadata{
|
||||
Name: "libtirpc",
|
||||
Description: "a port of Suns Transport-Independent RPC library to Linux",
|
||||
Website: "https://sourceforge.net/projects/libtirpc/",
|
||||
|
||||
ID: 1740,
|
||||
})
|
||||
}
|
||||
@@ -4,8 +4,8 @@ import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newLibucontext() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.5"
|
||||
checksum = "Ggk7FMmDNBdCx1Z9PcNWWW6LSpjGYssn2vU0GK5BLXJYw7ZxZbA2m_eSgT9TFnIG"
|
||||
version = "1.5.1"
|
||||
checksum = "mUgeyJknjMxT-5fORzz-rqhZfP3Y7EZGBhOwvhuX7MsF4Pk9wkuwtrLf5IML-jWu"
|
||||
)
|
||||
return t.NewPackage("libucontext", version, newFromGitHub(
|
||||
"kaniini/libucontext",
|
||||
@@ -21,19 +21,17 @@ func (t Toolchain) newLibucontext() (pkg.Artifact, string) {
|
||||
SkipConfigure: true,
|
||||
InPlace: true,
|
||||
Make: []string{
|
||||
"ARCH=" + linuxArch(),
|
||||
"ARCH=" + t.linuxArch(),
|
||||
},
|
||||
Install: "make prefix=/system DESTDIR=/work install",
|
||||
}), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libucontext] = Metadata{
|
||||
f: Toolchain.newLibucontext,
|
||||
|
||||
native.mustRegister(Toolchain.newLibucontext, &Metadata{
|
||||
Name: "libucontext",
|
||||
Description: "ucontext implementation featuring glibc-compatible ABI",
|
||||
Website: "https://github.com/kaniini/libucontext/",
|
||||
|
||||
ID: 17085,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -20,13 +20,11 @@ func (t Toolchain) newLibxml2() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libxml2] = Metadata{
|
||||
f: Toolchain.newLibxml2,
|
||||
|
||||
native.mustRegister(Toolchain.newLibxml2, &Metadata{
|
||||
Name: "libxml2",
|
||||
Description: "an XML toolkit implemented in C",
|
||||
Website: "https://gitlab.gnome.org/GNOME/libxml2/",
|
||||
|
||||
ID: 1783,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -26,9 +26,7 @@ func (t Toolchain) newLibxslt() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libxslt] = Metadata{
|
||||
f: Toolchain.newLibxslt,
|
||||
|
||||
native.mustRegister(Toolchain.newLibxslt, &Metadata{
|
||||
Name: "libxslt",
|
||||
Description: "an XSLT processor based on libxml2",
|
||||
Website: "https://gitlab.gnome.org/GNOME/libxslt/",
|
||||
@@ -38,5 +36,5 @@ func init() {
|
||||
},
|
||||
|
||||
ID: 13301,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -29,269 +29,300 @@ func litArgs(verbose bool, skipChecks ...string) string {
|
||||
return "'" + strings.Join(args, " ") + "'"
|
||||
}
|
||||
|
||||
func (t Toolchain) newEarlyCompilerRT() (pkg.Artifact, string) {
|
||||
version := t.Version(llvmSource)
|
||||
major, _, _ := strings.Cut(version, ".")
|
||||
return t.NewPackage("early-compiler-rt", version, t.Load(llvmSource), &PackageAttr{
|
||||
Flag: TExclusive,
|
||||
}, &CMakeHelper{
|
||||
Append: []string{"compiler-rt"},
|
||||
func init() {
|
||||
native.MustRegister("early-compiler-rt", func(t Toolchain) (*Metadata, pkg.Artifact) {
|
||||
meta := Metadata{
|
||||
Name: "early-compiler-rt",
|
||||
Description: "early LLVM runtime: compiler-rt",
|
||||
|
||||
Cache: []KV{
|
||||
{"ENABLE_LINKER_BUILD_ID", "ON"},
|
||||
Dependencies: P{
|
||||
Musl,
|
||||
},
|
||||
}
|
||||
_meta, source := t.MustLoad(llvmSource)
|
||||
meta.Version = _meta.Version
|
||||
major, _, _ := strings.Cut(meta.Version, ".")
|
||||
return &meta, t.NewPackage("early-compiler-rt", meta.Version, source, &PackageAttr{
|
||||
Flag: TExclusive,
|
||||
}, &CMakeHelper{
|
||||
Append: []string{"compiler-rt"},
|
||||
|
||||
// libc++ not yet available
|
||||
{"CMAKE_CXX_COMPILER_TARGET", ""},
|
||||
Cache: []KV{
|
||||
{"ENABLE_LINKER_BUILD_ID", "ON"},
|
||||
|
||||
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_ENABLE_RTTI", "ON"},
|
||||
{"LLVM_BUILD_LLVM_DYLIB", "ON"},
|
||||
{"LLVM_LINK_LLVM_DYLIB", "ON"},
|
||||
{"LLVM_ENABLE_PER_TARGET_RUNTIME_DIR", "ON"},
|
||||
// libc++ not yet available
|
||||
{"CMAKE_CXX_COMPILER_TARGET", ""},
|
||||
|
||||
{"COMPILER_RT_BUILD_BUILTINS", "ON"},
|
||||
{"COMPILER_RT_DEFAULT_TARGET_ONLY", "ON"},
|
||||
{"COMPILER_RT_USE_BUILTINS_LIBRARY", "ON"},
|
||||
{"COMPILER_RT_SANITIZERS_TO_BUILD", "asan"},
|
||||
{"COMPILER_RT_BUILD_GWP_ASAN", "OFF"},
|
||||
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_ENABLE_RTTI", "ON"},
|
||||
{"LLVM_BUILD_LLVM_DYLIB", "ON"},
|
||||
{"LLVM_LINK_LLVM_DYLIB", "ON"},
|
||||
{"LLVM_ENABLE_PER_TARGET_RUNTIME_DIR", "ON"},
|
||||
|
||||
// does not work without libunwind
|
||||
{"COMPILER_RT_BUILD_CTX_PROFILE", "OFF"},
|
||||
{"COMPILER_RT_BUILD_LIBFUZZER", "OFF"},
|
||||
{"COMPILER_RT_BUILD_MEMPROF", "OFF"},
|
||||
{"COMPILER_RT_BUILD_PROFILE", "OFF"},
|
||||
{"COMPILER_RT_BUILD_XRAY", "OFF"},
|
||||
},
|
||||
SkipTest: true,
|
||||
Script: `
|
||||
{"COMPILER_RT_BUILD_BUILTINS", "ON"},
|
||||
{"COMPILER_RT_DEFAULT_TARGET_ONLY", "ON"},
|
||||
{"COMPILER_RT_USE_BUILTINS_LIBRARY", "ON"},
|
||||
{"COMPILER_RT_SANITIZERS_TO_BUILD", "asan"},
|
||||
{"COMPILER_RT_BUILD_GWP_ASAN", "OFF"},
|
||||
|
||||
// does not work without libunwind
|
||||
{"COMPILER_RT_BUILD_CTX_PROFILE", "OFF"},
|
||||
{"COMPILER_RT_BUILD_LIBFUZZER", "OFF"},
|
||||
{"COMPILER_RT_BUILD_MEMPROF", "OFF"},
|
||||
{"COMPILER_RT_BUILD_PROFILE", "OFF"},
|
||||
{"COMPILER_RT_BUILD_XRAY", "OFF"},
|
||||
},
|
||||
SkipTest: true,
|
||||
Script: `
|
||||
mkdir -p "/work/system/lib/clang/` + major + `/lib/"
|
||||
ln -s \
|
||||
"../../../${ROSA_TRIPLE}" \
|
||||
"/work/system/lib/clang/` + major + `/lib/"
|
||||
|
||||
ln -s \
|
||||
"clang_rt.crtbegin-` + linuxArch() + `.o" \
|
||||
"clang_rt.crtbegin-` + t.linuxArch() + `.o" \
|
||||
"/work/system/lib/${ROSA_TRIPLE}/crtbeginS.o"
|
||||
ln -s \
|
||||
"clang_rt.crtend-` + linuxArch() + `.o" \
|
||||
"clang_rt.crtend-` + t.linuxArch() + `.o" \
|
||||
"/work/system/lib/${ROSA_TRIPLE}/crtendS.o"
|
||||
`,
|
||||
},
|
||||
Python,
|
||||
|
||||
muslHeaders,
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[earlyCompilerRT] = Metadata{
|
||||
f: Toolchain.newEarlyCompilerRT,
|
||||
|
||||
Name: "early-compiler-rt",
|
||||
Description: "early LLVM runtime: compiler-rt",
|
||||
|
||||
Dependencies: P{
|
||||
Musl,
|
||||
},
|
||||
}
|
||||
}
|
||||
Python,
|
||||
|
||||
func (t Toolchain) newEarlyRuntimes() (pkg.Artifact, string) {
|
||||
version := t.Version(llvmSource)
|
||||
return t.NewPackage("early-runtimes", version, t.Load(llvmSource), &PackageAttr{
|
||||
Flag: TExclusive,
|
||||
}, &CMakeHelper{
|
||||
Append: []string{"runtimes"},
|
||||
muslHeaders,
|
||||
KernelHeaders,
|
||||
)
|
||||
})
|
||||
|
||||
Cache: []KV{
|
||||
native.MustRegister("early-runtimes", func(t Toolchain) (*Metadata, pkg.Artifact) {
|
||||
meta := Metadata{
|
||||
Name: "early-runtimes",
|
||||
Description: "early LLVM runtimes: libunwind, libcxx, libcxxabi",
|
||||
|
||||
Dependencies: P{
|
||||
earlyCompilerRT,
|
||||
},
|
||||
}
|
||||
_meta, source := t.MustLoad(llvmSource)
|
||||
meta.Version = _meta.Version
|
||||
|
||||
return &meta, t.NewPackage("early-runtimes", meta.Version, source, &PackageAttr{
|
||||
Flag: TExclusive,
|
||||
}, &CMakeHelper{
|
||||
Append: []string{"runtimes"},
|
||||
|
||||
Cache: []KV{
|
||||
{"ENABLE_LINKER_BUILD_ID", "ON"},
|
||||
|
||||
// libc++ not yet available
|
||||
{"CMAKE_CXX_COMPILER_WORKS", "ON"},
|
||||
|
||||
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_ENABLE_RTTI", "ON"},
|
||||
{"LLVM_BUILD_LLVM_DYLIB", "ON"},
|
||||
{"LLVM_LINK_LLVM_DYLIB", "ON"},
|
||||
{"LLVM_ENABLE_RUNTIMES", "'libunwind;libcxx;libcxxabi'"},
|
||||
|
||||
{"LIBUNWIND_ENABLE_ASSERTIONS", "OFF"},
|
||||
{"LIBUNWIND_USE_COMPILER_RT", "ON"},
|
||||
{"LIBCXX_HAS_MUSL_LIBC", "ON"},
|
||||
{"LIBCXX_USE_COMPILER_RT", "ON"},
|
||||
{"LIBCXX_CXX_ABI", "libcxxabi"},
|
||||
{"LIBCXX_ENABLE_STATIC_ABI_LIBRARY", "OFF"},
|
||||
{"LIBCXX_HARDENING_MODE", "fast"},
|
||||
{"LIBCXX_HAS_ATOMIC_LIB", "OFF"},
|
||||
{"LIBCXXABI_USE_COMPILER_RT", "ON"},
|
||||
{"LIBCXXABI_USE_LLVM_UNWINDER", "ON"},
|
||||
{"LIBCXXABI_ENABLE_STATIC_UNWINDER", "OFF"},
|
||||
{"LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL", "OFF"},
|
||||
|
||||
{"LLVM_ENABLE_ZLIB", "FORCE_ON"},
|
||||
{"LLVM_ENABLE_ZSTD", "FORCE_ON"},
|
||||
{"LLVM_ENABLE_LIBXML2", "OFF"},
|
||||
},
|
||||
SkipTest: true,
|
||||
},
|
||||
Python,
|
||||
|
||||
Zlib,
|
||||
Zstd,
|
||||
earlyCompilerRT,
|
||||
KernelHeaders,
|
||||
)
|
||||
})
|
||||
|
||||
const (
|
||||
version = "22.1.5"
|
||||
checksum = "32gOaLPHcUlo3hkdk5RbFumTE01XKeCAYZcpvn8IDHF95egXVfDFSl6eZL3ChMen"
|
||||
)
|
||||
|
||||
native.MustRegister("llvm-project", func(t Toolchain) (*Metadata, pkg.Artifact) {
|
||||
meta := Metadata{
|
||||
Name: "llvm-project",
|
||||
Description: "LLVM monorepo with Rosa OS patches",
|
||||
Version: version,
|
||||
|
||||
ID: 1830,
|
||||
}
|
||||
return &meta, t.NewPatchedSource("llvm", version, newFromGitHub(
|
||||
"llvm/llvm-project",
|
||||
"llvmorg-"+version,
|
||||
checksum,
|
||||
), true, llvmPatches...)
|
||||
})
|
||||
|
||||
native.MustRegister("llvm", func(t Toolchain) (*Metadata, pkg.Artifact) {
|
||||
meta := Metadata{
|
||||
Name: "llvm",
|
||||
Description: "a collection of modular and reusable compiler and toolchain technologies",
|
||||
Website: "https://llvm.org",
|
||||
|
||||
Dependencies: P{
|
||||
Zlib,
|
||||
Zstd,
|
||||
Musl,
|
||||
},
|
||||
}
|
||||
_meta, source := t.MustLoad(llvmSource)
|
||||
meta.Version = _meta.Version
|
||||
|
||||
early := muslHeaders
|
||||
if t.stage.isStage0() {
|
||||
// The LLVM build system uses the system installation when building with
|
||||
// LLVM_LINK_LLVM_DYLIB, since it builds runtimes after the fact, using
|
||||
// the just-built toolchain. This is unacceptable in stage0 due to the
|
||||
// potential version difference. Later stages bootstrap off of runtimes
|
||||
// of its previous stage via 3-stage determinism.
|
||||
early = earlyRuntimes
|
||||
}
|
||||
|
||||
cache := []KV{
|
||||
{"ENABLE_LINKER_BUILD_ID", "ON"},
|
||||
|
||||
// libc++ not yet available
|
||||
{"CMAKE_CXX_COMPILER_WORKS", "ON"},
|
||||
{"COMPILER_RT_USE_BUILTINS_LIBRARY", "ON"},
|
||||
{"COMPILER_RT_DEFAULT_TARGET_ONLY", "ON"},
|
||||
{"COMPILER_RT_BUILD_GWP_ASAN", "OFF"},
|
||||
{"LIBCXX_CXX_ABI", "libcxxabi"},
|
||||
{"LIBCXX_USE_COMPILER_RT", "ON"},
|
||||
{"LIBCXX_ENABLE_STATIC_ABI_LIBRARY", "OFF"},
|
||||
{"LIBCXX_HAS_MUSL_LIBC", "ON"},
|
||||
{"LIBCXX_HARDENING_MODE", "fast"},
|
||||
{"LIBCXXABI_USE_LLVM_UNWINDER", "ON"},
|
||||
{"LIBCXXABI_ENABLE_STATIC_UNWINDER", "OFF"},
|
||||
{"LIBCXXABI_USE_COMPILER_RT", "ON"},
|
||||
{"LLVM_INSTALL_BINUTILS_SYMLINKS", "ON"},
|
||||
{"LLVM_INSTALL_UTILS", "ON"},
|
||||
{"LLVM_BUILD_LLVM_DYLIB", "ON"},
|
||||
{"LLVM_LINK_LLVM_DYLIB", "ON"},
|
||||
{"LLVM_APPEND_VC_REV", "OFF"},
|
||||
{"LLVM_ENABLE_RTTI", "ON"},
|
||||
{"LLVM_ENABLE_ZLIB", "FORCE_ON"},
|
||||
{"LLVM_ENABLE_ZSTD", "FORCE_ON"},
|
||||
{"LLVM_ENABLE_PER_TARGET_RUNTIME_DIR", "ON"},
|
||||
{"LLVM_INCLUDE_BENCHMARKS", "OFF"},
|
||||
{"CLANG_DEFAULT_RTLIB", "compiler-rt"},
|
||||
{"CLANG_DEFAULT_UNWINDLIB", "libunwind"},
|
||||
{"CLANG_DEFAULT_CXX_STDLIB", "libc++"},
|
||||
{"CLANG_CONFIG_FILE_SYSTEM_DIR", "/system/etc/clang"},
|
||||
{"LLVM_ENABLE_FFI", "OFF"},
|
||||
{"LLVM_ENABLE_LIBXML2", "OFF"},
|
||||
{"LLVM_ENABLE_LIBCXX", "ON"},
|
||||
{"LLVM_ENABLE_LLD", "ON"},
|
||||
{"LIBUNWIND_ENABLE_ASSERTIONS", "OFF"},
|
||||
{"LIBUNWIND_USE_COMPILER_RT", "ON"},
|
||||
|
||||
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_ENABLE_RTTI", "ON"},
|
||||
{"LLVM_BUILD_LLVM_DYLIB", "ON"},
|
||||
{"LLVM_LINK_LLVM_DYLIB", "ON"},
|
||||
{"LLVM_ENABLE_RUNTIMES", "'libunwind;libcxx;libcxxabi'"},
|
||||
|
||||
{"LIBUNWIND_ENABLE_ASSERTIONS", "OFF"},
|
||||
{"LIBUNWIND_USE_COMPILER_RT", "ON"},
|
||||
{"LIBCXX_HAS_MUSL_LIBC", "ON"},
|
||||
{"LIBCXX_USE_COMPILER_RT", "ON"},
|
||||
{"LIBCXX_CXX_ABI", "libcxxabi"},
|
||||
{"LIBCXX_ENABLE_STATIC_ABI_LIBRARY", "OFF"},
|
||||
{"LIBCXX_HARDENING_MODE", "fast"},
|
||||
{"LIBCXX_HAS_ATOMIC_LIB", "OFF"},
|
||||
{"LIBCXXABI_USE_COMPILER_RT", "ON"},
|
||||
{"LIBCXXABI_USE_LLVM_UNWINDER", "ON"},
|
||||
{"LIBCXXABI_ENABLE_STATIC_UNWINDER", "OFF"},
|
||||
{"LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL", "OFF"},
|
||||
|
||||
{"LLVM_ENABLE_ZLIB", "FORCE_ON"},
|
||||
{"LLVM_ENABLE_ZSTD", "FORCE_ON"},
|
||||
{"LLVM_ENABLE_LIBXML2", "OFF"},
|
||||
},
|
||||
SkipTest: true,
|
||||
},
|
||||
Python,
|
||||
|
||||
Zlib,
|
||||
Zstd,
|
||||
earlyCompilerRT,
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[earlyRuntimes] = Metadata{
|
||||
f: Toolchain.newEarlyRuntimes,
|
||||
|
||||
Name: "early-runtimes",
|
||||
Description: "early LLVM runtimes: libunwind, libcxx, libcxxabi",
|
||||
|
||||
Dependencies: P{
|
||||
earlyCompilerRT,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newLLVM() (pkg.Artifact, string) {
|
||||
var early PArtifact = muslHeaders
|
||||
if t.isStage0() {
|
||||
// The LLVM build system uses the system installation when building with
|
||||
// LLVM_LINK_LLVM_DYLIB, since it builds runtimes after the fact, using
|
||||
// the just-built toolchain. This is unacceptable in stage0 due to the
|
||||
// potential version difference. Later stages bootstrap off of runtimes
|
||||
// of its previous stage via 3-stage determinism.
|
||||
early = earlyRuntimes
|
||||
}
|
||||
|
||||
cache := []KV{
|
||||
{"ENABLE_LINKER_BUILD_ID", "ON"},
|
||||
{"COMPILER_RT_USE_BUILTINS_LIBRARY", "ON"},
|
||||
{"COMPILER_RT_DEFAULT_TARGET_ONLY", "ON"},
|
||||
{"COMPILER_RT_BUILD_GWP_ASAN", "OFF"},
|
||||
{"LIBCXX_CXX_ABI", "libcxxabi"},
|
||||
{"LIBCXX_USE_COMPILER_RT", "ON"},
|
||||
{"LIBCXX_ENABLE_STATIC_ABI_LIBRARY", "OFF"},
|
||||
{"LIBCXX_HAS_MUSL_LIBC", "ON"},
|
||||
{"LIBCXX_HARDENING_MODE", "fast"},
|
||||
{"LIBCXXABI_USE_LLVM_UNWINDER", "ON"},
|
||||
{"LIBCXXABI_ENABLE_STATIC_UNWINDER", "OFF"},
|
||||
{"LIBCXXABI_USE_COMPILER_RT", "ON"},
|
||||
{"LLVM_INSTALL_BINUTILS_SYMLINKS", "ON"},
|
||||
{"LLVM_INSTALL_UTILS", "ON"},
|
||||
{"LLVM_BUILD_LLVM_DYLIB", "ON"},
|
||||
{"LLVM_LINK_LLVM_DYLIB", "ON"},
|
||||
{"LLVM_APPEND_VC_REV", "OFF"},
|
||||
{"LLVM_ENABLE_RTTI", "ON"},
|
||||
{"LLVM_ENABLE_ZLIB", "FORCE_ON"},
|
||||
{"LLVM_ENABLE_ZSTD", "FORCE_ON"},
|
||||
{"LLVM_ENABLE_PER_TARGET_RUNTIME_DIR", "ON"},
|
||||
{"LLVM_INCLUDE_BENCHMARKS", "OFF"},
|
||||
{"CLANG_DEFAULT_RTLIB", "compiler-rt"},
|
||||
{"CLANG_DEFAULT_UNWINDLIB", "libunwind"},
|
||||
{"CLANG_DEFAULT_CXX_STDLIB", "libc++"},
|
||||
{"CLANG_CONFIG_FILE_SYSTEM_DIR", "/system/etc/clang"},
|
||||
{"LLVM_ENABLE_FFI", "OFF"},
|
||||
{"LLVM_ENABLE_LIBXML2", "OFF"},
|
||||
{"LLVM_ENABLE_LIBCXX", "ON"},
|
||||
{"LLVM_ENABLE_LLD", "ON"},
|
||||
{"LIBUNWIND_ENABLE_ASSERTIONS", "OFF"},
|
||||
{"LIBUNWIND_USE_COMPILER_RT", "ON"},
|
||||
|
||||
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_ENABLE_PROJECTS", "'" + strings.Join([]string{
|
||||
"clang",
|
||||
"lld",
|
||||
}, ";") + "'"},
|
||||
{"LLVM_ENABLE_RUNTIMES", "'" + strings.Join([]string{
|
||||
"compiler-rt",
|
||||
"libcxx",
|
||||
"libcxxabi",
|
||||
"libunwind",
|
||||
"libclc",
|
||||
}, ";") + "'"},
|
||||
}
|
||||
|
||||
if !t.isStage0() {
|
||||
skipChecks := []string{
|
||||
// expensive, pointless to run here
|
||||
"benchmarks",
|
||||
// LLVM ERROR: Tried to execute an unknown external function: roundevenf
|
||||
"ExecutionEngine/Interpreter/intrinsics.ll",
|
||||
// clang: deadlocks with LLVM_BUILD_LLVM_DYLIB
|
||||
"crash-recovery-modules",
|
||||
// clang: fatal error: '__config_site' file not found
|
||||
"CodeGen/PowerPC/ppc-xmmintrin.c",
|
||||
"CodeGen/PowerPC/ppc-mmintrin.c",
|
||||
"CodeGen/PowerPC/ppc-emmintrin.c",
|
||||
"CodeGen/PowerPC/ppc-pmmintrin.c",
|
||||
"CodeGen/PowerPC/ppc-tmmintrin.c",
|
||||
"CodeGen/PowerPC/ppc-smmintrin.c",
|
||||
"CodeGenCUDA/amdgpu-alias-undef-symbols.cu",
|
||||
// cxx: fails on musl
|
||||
"close.dont-get-rid-of-buffer",
|
||||
"re/re.traits",
|
||||
"std/time",
|
||||
"localization/locales",
|
||||
"localization/locale.categories",
|
||||
"selftest/dsl/dsl.sh.py",
|
||||
"input.output/iostream.format",
|
||||
"locale-specific_form",
|
||||
// cxx: deadlocks
|
||||
"std/thread/thread.jthread",
|
||||
// unwind: fails on musl
|
||||
"eh_frame_fde_pc_range",
|
||||
}
|
||||
switch arch {
|
||||
case "arm64":
|
||||
skipChecks = append(skipChecks,
|
||||
// LLVM: intermittently crashes
|
||||
"ExecutionEngine/OrcLazy/multiple-compile-threads-basic.ll",
|
||||
// unwind: unexpectedly passes
|
||||
"unwind_leaffunction",
|
||||
)
|
||||
{"LLVM_ENABLE_PROJECTS", "'" + strings.Join([]string{
|
||||
"clang",
|
||||
"lld",
|
||||
}, ";") + "'"},
|
||||
{"LLVM_ENABLE_RUNTIMES", "'" + strings.Join([]string{
|
||||
"compiler-rt",
|
||||
"libcxx",
|
||||
"libcxxabi",
|
||||
"libunwind",
|
||||
"libclc",
|
||||
}, ";") + "'"},
|
||||
}
|
||||
|
||||
if presetOpts&OptLLVMNoLTO == 0 {
|
||||
if !t.stage.isStage0() {
|
||||
skipChecks := []string{
|
||||
// expensive, pointless to run here
|
||||
"benchmarks",
|
||||
// LLVM ERROR: Tried to execute an unknown external function: roundevenf
|
||||
"ExecutionEngine/Interpreter/intrinsics.ll",
|
||||
// clang: deadlocks with LLVM_BUILD_LLVM_DYLIB
|
||||
"crash-recovery-modules",
|
||||
// clang: fatal error: '__config_site' file not found
|
||||
"CodeGen/PowerPC/ppc-xmmintrin.c",
|
||||
"CodeGen/PowerPC/ppc-mmintrin.c",
|
||||
"CodeGen/PowerPC/ppc-emmintrin.c",
|
||||
"CodeGen/PowerPC/ppc-pmmintrin.c",
|
||||
"CodeGen/PowerPC/ppc-tmmintrin.c",
|
||||
"CodeGen/PowerPC/ppc-smmintrin.c",
|
||||
"CodeGenCUDA/amdgpu-alias-undef-symbols.cu",
|
||||
// cxx: fails on musl
|
||||
"close.dont-get-rid-of-buffer",
|
||||
"re/re.traits",
|
||||
"std/time",
|
||||
"localization/locales",
|
||||
"localization/locale.categories",
|
||||
"selftest/dsl/dsl.sh.py",
|
||||
"input.output/iostream.format",
|
||||
"locale-specific_form",
|
||||
// cxx: deadlocks
|
||||
"std/thread/thread.jthread",
|
||||
// unwind: fails on musl
|
||||
"eh_frame_fde_pc_range",
|
||||
}
|
||||
switch t.arch {
|
||||
case "arm64":
|
||||
skipChecks = append(skipChecks,
|
||||
// LLVM: intermittently crashes
|
||||
"ExecutionEngine/OrcLazy/multiple-compile-threads-basic.ll",
|
||||
// unwind: unexpectedly passes
|
||||
"unwind_leaffunction",
|
||||
)
|
||||
}
|
||||
|
||||
if t.opts&OptLLVMNoLTO == 0 {
|
||||
cache = append(cache, []KV{
|
||||
// very expensive
|
||||
{"LLVM_ENABLE_LTO", "Thin"},
|
||||
}...)
|
||||
}
|
||||
|
||||
cache = append(cache, []KV{
|
||||
// very expensive
|
||||
{"LLVM_ENABLE_LTO", "Thin"},
|
||||
// symbols: clock_gettime, mallopt
|
||||
{"COMPILER_RT_INCLUDE_TESTS", "OFF"},
|
||||
|
||||
{"LLVM_BUILD_TESTS", "ON"},
|
||||
{"LLVM_LIT_ARGS", litArgs(true, skipChecks...)},
|
||||
}...)
|
||||
}
|
||||
|
||||
cache = append(cache, []KV{
|
||||
// symbols: clock_gettime, mallopt
|
||||
{"COMPILER_RT_INCLUDE_TESTS", "OFF"},
|
||||
return &meta, t.NewPackage("llvm", meta.Version, source, &PackageAttr{
|
||||
Flag: TExclusive,
|
||||
}, &CMakeHelper{
|
||||
Append: []string{"llvm"},
|
||||
|
||||
{"LLVM_BUILD_TESTS", "ON"},
|
||||
{"LLVM_LIT_ARGS", litArgs(true, skipChecks...)},
|
||||
}...)
|
||||
}
|
||||
|
||||
version := t.Version(llvmSource)
|
||||
return t.NewPackage("llvm", version, t.Load(llvmSource), nil, &CMakeHelper{
|
||||
Append: []string{"llvm"},
|
||||
|
||||
Cache: cache,
|
||||
Script: `
|
||||
Cache: cache,
|
||||
Script: `
|
||||
ln -s ld.lld /work/system/bin/ld
|
||||
ln -s clang /work/system/bin/cc
|
||||
ln -s clang /work/system/bin/cpp
|
||||
ln -s clang++ /work/system/bin/c++
|
||||
`,
|
||||
|
||||
// LLVM_LINK_LLVM_DYLIB causes llvm test suite to leak system
|
||||
// installation into test environment, and the tests end up testing the
|
||||
// system installation instead. Tests are disabled on stage0 and relies
|
||||
// on 3-stage determinism to test later stages.
|
||||
SkipTest: t.isStage0(),
|
||||
// LLVM_LINK_LLVM_DYLIB causes llvm test suite to leak system
|
||||
// installation into test environment, and the tests end up testing the
|
||||
// system installation instead. Tests are disabled on stage0 and relies
|
||||
// on 3-stage determinism to test later stages.
|
||||
SkipTest: t.stage.isStage0(),
|
||||
|
||||
Test: `
|
||||
Test: `
|
||||
chmod +w /bin && ln -s \
|
||||
../system/bin/chmod \
|
||||
../system/bin/mkdir \
|
||||
@@ -301,53 +332,20 @@ chmod +w /bin && ln -s \
|
||||
/bin
|
||||
ninja ` + jobsFlagE + ` check-all
|
||||
`,
|
||||
},
|
||||
Python,
|
||||
Perl,
|
||||
Diffutils,
|
||||
Bash,
|
||||
Gawk,
|
||||
Coreutils,
|
||||
Findutils,
|
||||
|
||||
Zlib,
|
||||
Zstd,
|
||||
early,
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
const (
|
||||
version = "22.1.4"
|
||||
checksum = "Bk3t-tV5sD5T0bqefFMcLeFuAwXnhFipywZmqst5hAZs97QQWGKB_5XyAFjj5tDB"
|
||||
)
|
||||
|
||||
artifactsM[llvmSource] = Metadata{
|
||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||
return t.NewPatchedSource("llvm", version, newFromGitHub(
|
||||
"llvm/llvm-project",
|
||||
"llvmorg-"+version,
|
||||
checksum,
|
||||
), true, llvmPatches...), version
|
||||
},
|
||||
Python,
|
||||
Perl,
|
||||
Diffutils,
|
||||
Bash,
|
||||
Gawk,
|
||||
Coreutils,
|
||||
Findutils,
|
||||
|
||||
Name: "llvm-project",
|
||||
Description: "LLVM monorepo with Rosa OS patches",
|
||||
|
||||
ID: 1830,
|
||||
}
|
||||
|
||||
artifactsM[LLVM] = Metadata{
|
||||
f: Toolchain.newLLVM,
|
||||
|
||||
Name: "llvm",
|
||||
Description: "a collection of modular and reusable compiler and toolchain technologies",
|
||||
Website: "https://llvm.org",
|
||||
|
||||
Dependencies: P{
|
||||
Zlib,
|
||||
Zstd,
|
||||
Musl,
|
||||
},
|
||||
}
|
||||
early,
|
||||
KernelHeaders,
|
||||
)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
57
internal/rosa/lm-sensors.go
Normal file
57
internal/rosa/lm-sensors.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newLMSensors() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "3-6-2"
|
||||
checksum = "7JYNutrihe-FP6r3ftf96uFZJJWPfxnBHL0ALSMA-vovaXVRr-sAjlLitw7WWpCI"
|
||||
)
|
||||
return t.NewPackage("lm_sensors", version, newFromGitHub(
|
||||
"lm-sensors/lm-sensors",
|
||||
"V"+version,
|
||||
checksum,
|
||||
), &PackageAttr{
|
||||
Writable: true,
|
||||
Chmod: true,
|
||||
EnterSource: true,
|
||||
|
||||
ScriptEarly: `
|
||||
ln -s \
|
||||
../../system/bin/perl \
|
||||
/usr/bin/
|
||||
`,
|
||||
}, &MakeHelper{
|
||||
InPlace: true,
|
||||
SkipConfigure: true,
|
||||
|
||||
Make: []string{
|
||||
"CC=cc",
|
||||
"ETCDIR=/system/etc",
|
||||
"PREFIX=/system",
|
||||
},
|
||||
|
||||
Check: []string{
|
||||
"CC=cc",
|
||||
"check",
|
||||
},
|
||||
|
||||
Install: "make DESTDIR=/work PREFIX=/system install",
|
||||
},
|
||||
Perl,
|
||||
PerlTestCmd,
|
||||
|
||||
M4,
|
||||
Bison,
|
||||
Flex,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.mustRegister(Toolchain.newLMSensors, &Metadata{
|
||||
Name: "lm_sensors",
|
||||
Description: "user-space support for hardware monitoring drivers",
|
||||
Website: "https://hwmon.wiki.kernel.org/lm_sensors",
|
||||
|
||||
ID: 1831,
|
||||
})
|
||||
}
|
||||
@@ -3,40 +3,10 @@ package rosa
|
||||
import (
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
func (t Toolchain) newMake() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "4.4.1"
|
||||
checksum = "YS_B07ZcAy9PbaK5_vKGj64SrxO2VMpnMKfc9I0Q9IC1rn0RwOH7802pJoj2Mq4a"
|
||||
)
|
||||
return t.New("make-"+version, TEarly, nil, nil, nil, `
|
||||
cd "$(mktemp -d)"
|
||||
/usr/src/make/configure \
|
||||
--prefix=/system \
|
||||
--build="${ROSA_TRIPLE}" \
|
||||
--disable-dependency-tracking
|
||||
./build.sh
|
||||
./make DESTDIR=/work install
|
||||
`, pkg.Path(AbsUsrSrc.Append("make"), false, newTar(
|
||||
"https://ftpmirror.gnu.org/gnu/make/make-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
))), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Make] = Metadata{
|
||||
f: Toolchain.newMake,
|
||||
|
||||
Name: "make",
|
||||
Description: "a tool which controls the generation of executables and other non-source files",
|
||||
Website: "https://www.gnu.org/software/make/",
|
||||
|
||||
ID: 1877,
|
||||
}
|
||||
}
|
||||
// Make is the build system used by [MakeHelper].
|
||||
var Make = H("make")
|
||||
|
||||
// MakeHelper is the [Make] build system helper.
|
||||
type MakeHelper struct {
|
||||
@@ -70,6 +40,8 @@ type MakeHelper struct {
|
||||
Make []string
|
||||
// Whether to skip the check target.
|
||||
SkipCheck bool
|
||||
// Whether to skip the check target during stage0.
|
||||
SkipCheckEarly bool
|
||||
// Name of the check target, zero value is equivalent to "check".
|
||||
Check []string
|
||||
// Replaces the default install command.
|
||||
@@ -123,7 +95,7 @@ func (attr *MakeHelper) wantsDir() string {
|
||||
}
|
||||
|
||||
// script generates the cure script.
|
||||
func (attr *MakeHelper) script(name string) string {
|
||||
func (attr *MakeHelper) script(t Toolchain, name string) string {
|
||||
if attr == nil {
|
||||
attr = new(MakeHelper)
|
||||
}
|
||||
@@ -194,7 +166,8 @@ make \
|
||||
}
|
||||
scriptMake += "\n"
|
||||
|
||||
if !attr.SkipCheck && presetOpts&OptSkipCheck == 0 {
|
||||
if !attr.SkipCheck && t.opts&OptSkipCheck == 0 &&
|
||||
(!attr.SkipCheckEarly || !t.stage.isStage0()) {
|
||||
scriptMake += attr.ScriptCheckEarly + `make \
|
||||
` + jobsFlagE + ` \
|
||||
`
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
func (t Toolchain) newLibglvnd() (pkg.Artifact, string) {
|
||||
const (
|
||||
@@ -12,20 +16,36 @@ func (t Toolchain) newLibglvnd() (pkg.Artifact, string) {
|
||||
"glvnd/libglvnd",
|
||||
"v"+version,
|
||||
checksum,
|
||||
), nil, (*MesonHelper)(nil),
|
||||
), nil, &MesonHelper{
|
||||
Setup: []KV{
|
||||
{"Dx11", "enabled"},
|
||||
{"Dglx", "enabled"},
|
||||
},
|
||||
ScriptCompiled: `
|
||||
export DISPLAY=':0'
|
||||
Xvfb &
|
||||
XVFB_PID="$!"
|
||||
trap 'kill $XVFB_PID && wait $XVFB_PID' EXIT
|
||||
`,
|
||||
},
|
||||
Binutils, // symbols check fail with llvm nm
|
||||
Xserver, // test suite wants X server
|
||||
|
||||
LibXext,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libglvnd] = Metadata{
|
||||
f: Toolchain.newLibglvnd,
|
||||
|
||||
native.mustRegister(Toolchain.newLibglvnd, &Metadata{
|
||||
Name: "libglvnd",
|
||||
Description: "The GL Vendor-Neutral Dispatch library",
|
||||
Website: "https://gitlab.freedesktop.org/glvnd/libglvnd",
|
||||
|
||||
Dependencies: P{
|
||||
LibXext,
|
||||
},
|
||||
|
||||
ID: 12098,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newLibdrm() (pkg.Artifact, string) {
|
||||
@@ -50,9 +70,7 @@ func (t Toolchain) newLibdrm() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libdrm] = Metadata{
|
||||
f: Toolchain.newLibdrm,
|
||||
|
||||
native.mustRegister(Toolchain.newLibdrm, &Metadata{
|
||||
Name: "libdrm",
|
||||
Description: "a userspace library for accessing the DRM",
|
||||
Website: "https://dri.freedesktop.org/",
|
||||
@@ -62,5 +80,178 @@ func init() {
|
||||
},
|
||||
|
||||
ID: 1596,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newLibva() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.23.0"
|
||||
checksum = "UmF5tPyWIG_w5kiR3KFpoYbF7UUcaak5tyc-RhOheNTwQlLkPlifreFYCM9FQxbq"
|
||||
)
|
||||
return t.NewPackage("libva", version, newFromGitHub(
|
||||
"intel/libva",
|
||||
version,
|
||||
checksum,
|
||||
), nil, &MesonHelper{
|
||||
Setup: []KV{
|
||||
{"Dwith_x11", "yes"},
|
||||
{"Dwith_glx", "yes"},
|
||||
{"Dwith_wayland", "yes"},
|
||||
},
|
||||
},
|
||||
Libdrm,
|
||||
LibXfixes,
|
||||
Libglvnd,
|
||||
Wayland,
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.mustRegister(Toolchain.newLibva, &Metadata{
|
||||
Name: "libva",
|
||||
Description: "an implementation for VA-API (Video Acceleration API)",
|
||||
Website: "https://01.org/vaapi",
|
||||
|
||||
Dependencies: P{
|
||||
Libdrm,
|
||||
LibXfixes,
|
||||
Libglvnd,
|
||||
Wayland,
|
||||
},
|
||||
|
||||
ID: 1752,
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newMesa() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "26.1.0"
|
||||
checksum = "zU0fjqevySBaoi_5SLW3e2UffmGeBdxOuHmAHTH68n2hV-sjYoqg30koLqFXuk5y"
|
||||
)
|
||||
return t.NewPackage("mesa", version, newFromGitLab(
|
||||
"gitlab.freedesktop.org",
|
||||
"mesa/mesa",
|
||||
"mesa-"+version,
|
||||
checksum,
|
||||
), nil, &MesonHelper{
|
||||
Setup: []KV{
|
||||
{"Dplatforms", "x11,wayland"},
|
||||
{"Dvideo-codecs", "all"},
|
||||
|
||||
{"Dglvnd", "enabled"},
|
||||
{"Dgbm", "enabled"},
|
||||
|
||||
{"Dgallium-drivers", strings.Join([]string{
|
||||
"asahi", // Apple AGX
|
||||
"crocus", // Intel legacy
|
||||
"etnaviv", // Vivante GPU designs (mostly NXP/Marvell SoCs)
|
||||
"freedreno", // Qualcomm Adreno (all Qualcomm SoCs)
|
||||
"i915", // Intel extra legacy
|
||||
"iris", // new Intel (Broadwell+)
|
||||
"lima", // ARM Mali 4xx
|
||||
"llvmpipe", // software renderer
|
||||
"nouveau", // Nvidia
|
||||
"panfrost", // ARM Mali Midgard and up (T/G series)
|
||||
"r300", // very old AMD
|
||||
"r600", // less old AMD
|
||||
"radeonsi", // new AMD (GCN+)
|
||||
"softpipe", // older software renderer
|
||||
"svga", // VMWare virtualized GPU
|
||||
"tegra", // Nvidia Tegra SoCs
|
||||
"v3d", // Broadcom VC5 (Raspberry Pi 4)
|
||||
"vc4", // Broadcom VC4 (Raspberry Pi 0-3)
|
||||
"virgl", // QEMU virtualized GPU (aka VirGL)
|
||||
"zink", // generic OpenGL over Vulkan, experimental
|
||||
|
||||
// d3d12: WSL emulated GPU (aka Dozen)
|
||||
// ethosu: accelerator
|
||||
// rocket: accelerator
|
||||
}, ",")},
|
||||
|
||||
{"Dvulkan-drivers", strings.Join([]string{
|
||||
"amd", // AMD (aka RADV)
|
||||
"broadcom", // Broadcom VC5 (Raspberry Pi 4, aka V3D)
|
||||
"freedreno", // Qualcomm Adreno (all Qualcomm SoCs)
|
||||
"intel", // new Intel (aka ANV)
|
||||
"intel_hasvk", // Intel Haswell/Broadwell, "legacy" Vulkan driver (https://www.phoronix.com/news/Intel-HasVK-Drop-Dead-Code)
|
||||
"panfrost", // ARM Mali Midgard and up (T/G series)
|
||||
"swrast", // software renderer (aka Lavapipe)
|
||||
"virtio", // QEMU virtualized GPU (aka VirGL)
|
||||
"imagination", // PowerVR Rogue
|
||||
"asahi", // Apple AGX
|
||||
"gfxstream", // Android virtualized GPU
|
||||
|
||||
// nouveau: Nouveau (aka NVK), requires rust
|
||||
// microsoft-experimental: WSL virtualized GPU (aka DZN/Dozen)
|
||||
// kosmickrisp: macOS-specific
|
||||
}, ",")},
|
||||
{"Dvulkan-layers", strings.Join([]string{
|
||||
"device-select",
|
||||
"intel-nullhw",
|
||||
"overlay",
|
||||
"screenshot",
|
||||
"anti-lag",
|
||||
"vram-report-limit",
|
||||
}, ",")},
|
||||
|
||||
{"Dfreedreno-kmds", "msm,virtio"},
|
||||
{"Damdgpu-virtio", "true"},
|
||||
},
|
||||
},
|
||||
M4,
|
||||
PythonPackaging,
|
||||
PythonMako,
|
||||
PythonPyYAML,
|
||||
PythonPycparser,
|
||||
Glslang,
|
||||
SPIRVLLVMTranslator,
|
||||
|
||||
Zlib,
|
||||
Zstd,
|
||||
Gzip,
|
||||
Ncurses,
|
||||
Libglvnd,
|
||||
Libexpat,
|
||||
Libva,
|
||||
Libdrm,
|
||||
Elfutils,
|
||||
Bison,
|
||||
Flex,
|
||||
LMSensors,
|
||||
Libconfig,
|
||||
LibdisplayInfo,
|
||||
Wayland,
|
||||
WaylandProtocols,
|
||||
Libxshmfence,
|
||||
LibXxf86vm,
|
||||
LibXrandr,
|
||||
LibxcbUtilKeysyms,
|
||||
Libpng,
|
||||
Libarchive,
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.mustRegister(Toolchain.newMesa, &Metadata{
|
||||
Name: "mesa",
|
||||
Description: "open source implementations of OpenGL, OpenGL ES, Vulkan, OpenCL, and more",
|
||||
Website: "https://mesa3d.org",
|
||||
|
||||
Dependencies: P{
|
||||
Libdrm,
|
||||
Elfutils,
|
||||
LMSensors,
|
||||
LibdisplayInfo,
|
||||
Wayland,
|
||||
Libxshmfence,
|
||||
LibXxf86vm,
|
||||
LibXrandr,
|
||||
LibxcbUtilKeysyms,
|
||||
Libpng,
|
||||
},
|
||||
|
||||
ID: 1970,
|
||||
|
||||
latest: (*Versions).getStable,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,72 +3,10 @@ package rosa
|
||||
import (
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
func (t Toolchain) newMeson() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.11.1"
|
||||
checksum = "uvILRxdopwc6Dy17UbIeClcQr0qHqyTaqyk1M9OqWKN9PwB9N6UVAiyN8kSSz3r2"
|
||||
)
|
||||
return t.NewPackage("meson", version, newFromGitHub(
|
||||
"mesonbuild/meson",
|
||||
version,
|
||||
checksum,
|
||||
), &PackageAttr{
|
||||
Env: []string{
|
||||
"CMAKE_MAKE_PROGRAM=ninja",
|
||||
},
|
||||
}, &PipHelper{
|
||||
EnterSource: true,
|
||||
Check: `
|
||||
cd 'test cases'
|
||||
rm -rf \
|
||||
'common/32 has header' \
|
||||
'common/66 vcstag' \
|
||||
'common/153 wrap file should not failed' \
|
||||
'common/184 openmp' \
|
||||
'common/189 check header' \
|
||||
'linuxlike/6 subdir include order' \
|
||||
'linuxlike/9 compiler checks with dependencies' \
|
||||
'linuxlike/13 cmake dependency' \
|
||||
'frameworks/15 llvm' \
|
||||
'frameworks/29 blocks'
|
||||
cd ..
|
||||
|
||||
python3 ./run_project_tests.py \
|
||||
-v \
|
||||
` + jobsFlagE + ` \
|
||||
--failfast \
|
||||
--backend=ninja
|
||||
`,
|
||||
},
|
||||
PythonSetuptools,
|
||||
PkgConfig,
|
||||
CMake,
|
||||
Ninja,
|
||||
PythonPyTest,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Meson] = Metadata{
|
||||
f: Toolchain.newMeson,
|
||||
|
||||
Name: "meson",
|
||||
Description: "an open source build system",
|
||||
Website: "https://mesonbuild.com/",
|
||||
|
||||
Dependencies: P{
|
||||
Python,
|
||||
PkgConfig,
|
||||
CMake,
|
||||
Ninja,
|
||||
},
|
||||
|
||||
ID: 6472,
|
||||
}
|
||||
}
|
||||
// Meson is the meson package used by [MesonHelper].
|
||||
var Meson = H("meson")
|
||||
|
||||
// MesonHelper is the [Meson] build system helper.
|
||||
type MesonHelper struct {
|
||||
@@ -106,7 +44,7 @@ func (*MesonHelper) createDir() bool { return false }
|
||||
func (*MesonHelper) wantsDir() string { return `"$(mktemp -d)"` }
|
||||
|
||||
// script generates the cure script.
|
||||
func (attr *MesonHelper) script(name string) string {
|
||||
func (attr *MesonHelper) script(t Toolchain, name string) string {
|
||||
if attr == nil {
|
||||
attr = new(MesonHelper)
|
||||
}
|
||||
@@ -117,7 +55,7 @@ func (attr *MesonHelper) script(name string) string {
|
||||
}
|
||||
|
||||
var scriptTest string
|
||||
if !attr.SkipTest && presetOpts&OptSkipCheck == 0 {
|
||||
if !attr.SkipTest && t.opts&OptSkipCheck == 0 {
|
||||
scriptTest = `
|
||||
meson test \
|
||||
--print-errorlogs`
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newMksh() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "59c"
|
||||
checksum = "0Zj-k4nXEu3IuJY4lvwD2OrC2t27GdZj8SPy4DoaeuBRH1padWb7oREpYgwY8JNq"
|
||||
)
|
||||
scriptTest := "./test.sh -C regress:no-ctty\n"
|
||||
if presetOpts&OptSkipCheck != 0 {
|
||||
scriptTest = ""
|
||||
}
|
||||
return t.New("mksh-"+version, 0, t.AppendPresets(nil,
|
||||
Perl,
|
||||
Coreutils,
|
||||
), nil, []string{
|
||||
"LDSTATIC=-static",
|
||||
"CPPFLAGS=-DMKSH_DEFAULT_PROFILEDIR=\\\"/system/etc\\\"",
|
||||
}, `
|
||||
cd "$(mktemp -d)"
|
||||
sh /usr/src/mksh/Build.sh -r
|
||||
CPPFLAGS="${CPPFLAGS} -DMKSH_BINSHPOSIX -DMKSH_BINSHREDUCED" \
|
||||
sh /usr/src/mksh/Build.sh -r -L
|
||||
`+scriptTest+`
|
||||
mkdir -p /work/system/bin/
|
||||
cp -v mksh /work/system/bin/
|
||||
cp -v lksh /work/system/bin/sh
|
||||
|
||||
mkdir -p /work/bin/
|
||||
ln -vs ../system/bin/sh /work/bin/
|
||||
`, pkg.Path(AbsUsrSrc.Append("mksh"), false, newTar(
|
||||
"https://mbsd.evolvis.org/MirOS/dist/mir/mksh/mksh-R"+version+".tgz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
))), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Mksh] = Metadata{
|
||||
f: Toolchain.newMksh,
|
||||
|
||||
Name: "mksh",
|
||||
Description: "MirBSD Korn Shell",
|
||||
Website: "https://www.mirbsd.org/mksh",
|
||||
|
||||
ID: 5590,
|
||||
}
|
||||
}
|
||||
@@ -24,13 +24,11 @@ func (t Toolchain) newMuslFts() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[MuslFts] = Metadata{
|
||||
f: Toolchain.newMuslFts,
|
||||
|
||||
native.mustRegister(Toolchain.newMuslFts, &Metadata{
|
||||
Name: "musl-fts",
|
||||
Description: "implementation of fts(3) functions which are missing in musl libc",
|
||||
Website: "https://github.com/void-linux/musl-fts",
|
||||
|
||||
ID: 26980,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -24,13 +24,11 @@ func (t Toolchain) newMuslObstack() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[MuslObstack] = Metadata{
|
||||
f: Toolchain.newMuslObstack,
|
||||
|
||||
native.mustRegister(Toolchain.newMuslObstack, &Metadata{
|
||||
Name: "musl-obstack",
|
||||
Description: "obstack functions and macros separated from glibc",
|
||||
Website: "https://github.com/void-linux/musl-obstack",
|
||||
|
||||
ID: 146206,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ func (t Toolchain) newMusl(headers bool) (pkg.Artifact, string) {
|
||||
SkipCheck: true,
|
||||
Script: `
|
||||
mkdir -p /work/system/bin
|
||||
COMPAT_LINKER_NAME="ld-musl-` + linuxArch() + `.so.1"
|
||||
COMPAT_LINKER_NAME="ld-musl-` + t.linuxArch() + `.so.1"
|
||||
ln -vs ../lib/libc.so /work/system/bin/linker
|
||||
ln -vs ../lib/libc.so /work/system/bin/ldd
|
||||
ln -vs libc.so "/work/system/lib/${COMPAT_LINKER_NAME}"
|
||||
@@ -34,9 +34,9 @@ rmdir -v /work/lib
|
||||
}
|
||||
|
||||
env := []string{
|
||||
"LDFLAGS=" + earlyLDFLAGS(false),
|
||||
"LDFLAGS=" + t.earlyLDFLAGS(false),
|
||||
}
|
||||
if t.isStage0() {
|
||||
if t.stage.isStage0() {
|
||||
env = append(env,
|
||||
"CC=clang",
|
||||
"AR=ar",
|
||||
@@ -75,24 +75,20 @@ index 715948f4..c2fece68 100644
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Musl] = Metadata{
|
||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||
return t.newMusl(false)
|
||||
},
|
||||
|
||||
native.mustRegister(func(t Toolchain) (pkg.Artifact, string) {
|
||||
return t.newMusl(false)
|
||||
}, &Metadata{
|
||||
Name: "musl",
|
||||
Description: "an implementation of the C standard library",
|
||||
Website: "https://musl.libc.org/",
|
||||
|
||||
ID: 11688,
|
||||
}
|
||||
|
||||
artifactsM[muslHeaders] = Metadata{
|
||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||
return t.newMusl(true)
|
||||
},
|
||||
})
|
||||
|
||||
native.mustRegister(func(t Toolchain) (pkg.Artifact, string) {
|
||||
return t.newMusl(true)
|
||||
}, &Metadata{
|
||||
Name: "musl-headers",
|
||||
Description: "system installation of musl headers",
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -26,13 +26,11 @@ func (t Toolchain) newNcurses() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Ncurses] = Metadata{
|
||||
f: Toolchain.newNcurses,
|
||||
|
||||
native.mustRegister(Toolchain.newNcurses, &Metadata{
|
||||
Name: "ncurses",
|
||||
Description: "a free software emulation of curses in System V Release 4.0 (SVr4)",
|
||||
Website: "https://invisible-island.net/ncurses/",
|
||||
|
||||
ID: 373226,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -39,15 +39,13 @@ index d223ac2..a7878d0 100644
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libmnl] = Metadata{
|
||||
f: Toolchain.newLibmnl,
|
||||
|
||||
native.mustRegister(Toolchain.newLibmnl, &Metadata{
|
||||
Name: "libmnl",
|
||||
Description: "a minimalistic user-space library oriented to Netlink developers",
|
||||
Website: "https://www.netfilter.org/projects/libmnl/",
|
||||
|
||||
ID: 1663,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newLibnftnl() (pkg.Artifact, string) {
|
||||
@@ -77,9 +75,7 @@ func (t Toolchain) newLibnftnl() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libnftnl] = Metadata{
|
||||
f: Toolchain.newLibnftnl,
|
||||
|
||||
native.mustRegister(Toolchain.newLibnftnl, &Metadata{
|
||||
Name: "libnftnl",
|
||||
Description: "a userspace library providing a low-level netlink API to the in-kernel nf_tables subsystem",
|
||||
Website: "https://www.netfilter.org/projects/libnftnl/",
|
||||
@@ -89,7 +85,7 @@ func init() {
|
||||
},
|
||||
|
||||
ID: 1681,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newIPTables() (pkg.Artifact, string) {
|
||||
@@ -131,9 +127,7 @@ chmod +w /etc/ && ln -s ../usr/src/iptables/etc/ethertypes /etc/
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[IPTables] = Metadata{
|
||||
f: Toolchain.newIPTables,
|
||||
|
||||
native.mustRegister(Toolchain.newIPTables, &Metadata{
|
||||
Name: "iptables",
|
||||
Description: "the userspace command line program used to configure the Linux 2.4.x and later packet filtering ruleset",
|
||||
Website: "https://www.netfilter.org/projects/iptables/",
|
||||
@@ -143,5 +137,5 @@ func init() {
|
||||
},
|
||||
|
||||
ID: 1394,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -19,9 +19,7 @@ func (t Toolchain) newNettle() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Nettle] = Metadata{
|
||||
f: Toolchain.newNettle,
|
||||
|
||||
native.mustRegister(Toolchain.newNettle, &Metadata{
|
||||
Name: "nettle",
|
||||
Description: "a low-level cryptographic library",
|
||||
Website: "https://www.lysator.liu.se/~nisse/nettle/",
|
||||
@@ -31,5 +29,5 @@ func init() {
|
||||
},
|
||||
|
||||
ID: 2073,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newNettle3() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "3.10.2"
|
||||
checksum = "07aXlj10X5llf67jIqRQAA1pgLSgb0w_JYggZVPuKNoc-B-_usb5Kr8FrfBe7g1S"
|
||||
)
|
||||
return t.NewPackage("nettle", version, newTar(
|
||||
"https://ftpmirror.gnu.org/gnu/nettle/nettle-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, (*MakeHelper)(nil),
|
||||
M4,
|
||||
Diffutils,
|
||||
|
||||
GMP,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[nettle3] = Metadata{
|
||||
f: Toolchain.newNettle3,
|
||||
|
||||
Name: "nettle3",
|
||||
Description: "a low-level cryptographic library",
|
||||
Website: "https://www.lysator.liu.se/~nisse/nettle/",
|
||||
|
||||
Dependencies: P{
|
||||
GMP,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,29 @@ package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newNinja() (pkg.Artifact, string) {
|
||||
// Ninja is the build system used by [CMakeHelper] and [MesonHelper].
|
||||
var Ninja = H("ninja")
|
||||
|
||||
func init() {
|
||||
const (
|
||||
version = "1.13.2"
|
||||
checksum = "ygKWMa0YV2lWKiFro5hnL-vcKbc_-RACZuPu0Io8qDvgQlZ0dxv7hPNSFkt4214v"
|
||||
)
|
||||
return t.New("ninja-"+version, 0, []pkg.Artifact{
|
||||
t.Load(Python),
|
||||
t.Load(Bash),
|
||||
}, nil, nil, `
|
||||
meta := Metadata{
|
||||
Name: "ninja",
|
||||
Description: "a small build system with a focus on speed",
|
||||
Website: "https://ninja-build.org",
|
||||
Version: version,
|
||||
|
||||
ID: 2089,
|
||||
}
|
||||
native.MustRegister(meta.Name, func(t Toolchain) (*Metadata, pkg.Artifact) {
|
||||
_, python := t.Load(Python)
|
||||
_, bash := t.Load(Bash)
|
||||
return &meta, t.New(meta.Name+"-"+version, 0, []pkg.Artifact{
|
||||
python,
|
||||
bash,
|
||||
}, nil, nil, `
|
||||
cd "$(mktemp -d)"
|
||||
python3 /usr/src/ninja/configure.py \
|
||||
--verbose \
|
||||
@@ -22,28 +36,18 @@ python3 /usr/src/ninja/configure.py \
|
||||
mkdir -p /work/system/bin/
|
||||
cp ninja /work/system/bin/
|
||||
`, pkg.Path(AbsUsrSrc.Append("googletest"), false,
|
||||
newFromGitHubRelease(
|
||||
"google/googletest",
|
||||
"v1.16.0",
|
||||
"googletest-1.16.0.tar.gz",
|
||||
"NjLGvSbgPy_B-y-o1hdanlzEzaYeStFcvFGxpYV3KYlhrWWFRcugYhM3ZMzOA9B_",
|
||||
pkg.TarGzip,
|
||||
)), pkg.Path(AbsUsrSrc.Append("ninja"), true, t.NewPatchedSource(
|
||||
"ninja", version, newFromGitHub(
|
||||
"ninja-build/ninja",
|
||||
"v"+version,
|
||||
checksum,
|
||||
), false,
|
||||
))), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Ninja] = Metadata{
|
||||
f: Toolchain.newNinja,
|
||||
|
||||
Name: "ninja",
|
||||
Description: "a small build system with a focus on speed",
|
||||
Website: "https://ninja-build.org/",
|
||||
|
||||
ID: 2089,
|
||||
}
|
||||
newFromGitHubRelease(
|
||||
"google/googletest",
|
||||
"v1.16.0",
|
||||
"googletest-1.16.0.tar.gz",
|
||||
"NjLGvSbgPy_B-y-o1hdanlzEzaYeStFcvFGxpYV3KYlhrWWFRcugYhM3ZMzOA9B_",
|
||||
pkg.TarGzip,
|
||||
)), pkg.Path(AbsUsrSrc.Append("ninja"), true, t.NewPatchedSource(
|
||||
meta.Name, version, newFromGitHub(
|
||||
"ninja-build/ninja",
|
||||
"v"+version,
|
||||
checksum,
|
||||
), false,
|
||||
)))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -67,9 +67,7 @@ cp -r \
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[NSS] = Metadata{
|
||||
f: Toolchain.newNSS,
|
||||
|
||||
native.mustRegister(Toolchain.newNSS, &Metadata{
|
||||
Name: "nss",
|
||||
Description: "Network Security Services",
|
||||
Website: "https://firefox-source-docs.mozilla.org/security/nss/index.html",
|
||||
@@ -79,35 +77,15 @@ func init() {
|
||||
},
|
||||
|
||||
ID: 2503,
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
const (
|
||||
version = "0.5.1"
|
||||
checksum = "oxjnuIrPVMPvD6x8VFLqB7EdbfuhouGQdtPuHDpEHGzoyH5nkxqtYN9UthMY9noA"
|
||||
)
|
||||
artifactsM[buildcatrust] = newPythonPackage(
|
||||
"buildcatrust", 233988,
|
||||
"transform certificate stores between formats",
|
||||
"https://github.com/nix-community/buildcatrust",
|
||||
version, newFromGitHub(
|
||||
"nix-community/buildcatrust",
|
||||
"v"+version, checksum,
|
||||
), &PackageAttr{
|
||||
ScriptEarly: `
|
||||
rm buildcatrust/tests/test_nonhermetic.py
|
||||
`,
|
||||
}, nil, P{PythonFlitCore},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newNSSCACert() (pkg.Artifact, string) {
|
||||
return t.New("nss-cacert", 0, t.AppendPresets(nil,
|
||||
return t.New("nss-cacert", 0, t.Append(nil,
|
||||
Bash,
|
||||
|
||||
NSS,
|
||||
buildcatrust,
|
||||
H("buildcatrust"),
|
||||
), nil, nil, `
|
||||
mkdir -p /work/system/etc/ssl/{certs/unbundled,certs/hashed,trust-source}
|
||||
buildcatrust \
|
||||
@@ -120,11 +98,9 @@ buildcatrust \
|
||||
`), Unversioned
|
||||
}
|
||||
func init() {
|
||||
artifactsM[NSSCACert] = Metadata{
|
||||
f: Toolchain.newNSSCACert,
|
||||
|
||||
native.mustRegister(Toolchain.newNSSCACert, &Metadata{
|
||||
Name: "nss-cacert",
|
||||
Description: "bundle of X.509 certificates of public Certificate Authorities",
|
||||
Website: "https://curl.se/docs/caextract.html",
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -40,9 +40,7 @@ func (t Toolchain) newOpenSSL() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[OpenSSL] = Metadata{
|
||||
f: Toolchain.newOpenSSL,
|
||||
|
||||
native.mustRegister(Toolchain.newOpenSSL, &Metadata{
|
||||
Name: "openssl",
|
||||
Description: "TLS/SSL and crypto library",
|
||||
Website: "https://www.openssl.org/",
|
||||
@@ -51,5 +49,5 @@ func init() {
|
||||
|
||||
// strange malformed tags treated as pre-releases in Anitya
|
||||
latest: (*Versions).getStable,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -23,9 +23,7 @@ func (t Toolchain) newP11Kit() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[P11Kit] = Metadata{
|
||||
f: Toolchain.newP11Kit,
|
||||
|
||||
native.mustRegister(Toolchain.newP11Kit, &Metadata{
|
||||
Name: "p11-kit",
|
||||
Description: "provides a way to load and enumerate PKCS#11 modules",
|
||||
Website: "https://p11-glue.freedesktop.org/p11-kit.html",
|
||||
@@ -36,5 +34,5 @@ func init() {
|
||||
},
|
||||
|
||||
ID: 2582,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
26
internal/rosa/package/acl/libgen-basename.patch
Normal file
26
internal/rosa/package/acl/libgen-basename.patch
Normal file
@@ -0,0 +1,26 @@
|
||||
From 8a80d895dfd779373363c3a4b62ecce5a549efb2 Mon Sep 17 00:00:00 2001
|
||||
From: "Haelwenn (lanodan) Monnier" <contact@hacktivis.me>
|
||||
Date: Sat, 30 Mar 2024 10:17:10 +0100
|
||||
Subject: tools/attr.c: Add missing libgen.h include for basename(3)
|
||||
|
||||
Fixes compilation issue with musl and modern C99 compilers.
|
||||
|
||||
See: https://bugs.gentoo.org/926294
|
||||
---
|
||||
tools/attr.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/tools/attr.c b/tools/attr.c
|
||||
index f12e4af..6a3c1e9 100644
|
||||
--- a/tools/attr.c
|
||||
+++ b/tools/attr.c
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
+#include <libgen.h>
|
||||
|
||||
#include <attr/attributes.h>
|
||||
|
||||
--
|
||||
cgit v1.1
|
||||
13
internal/rosa/package/acl/musl-errno.patch
Normal file
13
internal/rosa/package/acl/musl-errno.patch
Normal file
@@ -0,0 +1,13 @@
|
||||
diff --git a/test/attr.test b/test/attr.test
|
||||
index 6ce2f9b..e9bde92 100644
|
||||
--- a/test/attr.test
|
||||
+++ b/test/attr.test
|
||||
@@ -11,7 +11,7 @@ Try various valid and invalid names
|
||||
|
||||
$ touch f
|
||||
$ setfattr -n user -v value f
|
||||
- > setfattr: f: Operation not supported
|
||||
+ > setfattr: f: Not supported
|
||||
|
||||
$ setfattr -n user. -v value f
|
||||
> setfattr: f: Invalid argument
|
||||
47
internal/rosa/package/acl/package.az
Normal file
47
internal/rosa/package/acl/package.az
Normal file
@@ -0,0 +1,47 @@
|
||||
package attr {
|
||||
description = "Commands for Manipulating Filesystem Extended Attributes";
|
||||
website = "https://savannah.nongnu.org/projects/attr";
|
||||
anitya = 137;
|
||||
|
||||
version* = "2.5.2";
|
||||
source = remoteTar {
|
||||
url = "https://download.savannah.nongnu.org/releases/attr/"+
|
||||
"attr-"+version+".tar.gz";
|
||||
checksum = "YWEphrz6vg1sUMmHHVr1CRo53pFXRhq_pjN-AlG8UgwZK1y6m7zuDhxqJhD0SV0l";
|
||||
compress = gzip;
|
||||
};
|
||||
patches = [
|
||||
"libgen-basename.patch",
|
||||
"musl-errno.patch",
|
||||
];
|
||||
|
||||
early = `
|
||||
ln -s ../../system/bin/perl /usr/bin
|
||||
`;
|
||||
|
||||
exec = make {};
|
||||
|
||||
inputs = [ perl ];
|
||||
}
|
||||
|
||||
package acl {
|
||||
description = "Commands for Manipulating POSIX Access Control Lists";
|
||||
website = "https://savannah.nongnu.org/projects/acl";
|
||||
anitya = 16;
|
||||
|
||||
version* = "2.3.2";
|
||||
source = remoteTar {
|
||||
url = "https://download.savannah.nongnu.org/releases/acl/"+
|
||||
"acl-"+version+".tar.gz";
|
||||
checksum = "-fY5nwH4K8ZHBCRXrzLdguPkqjKI6WIiGu4dBtrZ1o0t6AIU73w8wwJz_UyjIS0P";
|
||||
compress = gzip;
|
||||
};
|
||||
|
||||
exec = make {
|
||||
// makes assumptions about uid_map/gid_map
|
||||
skipCheck = true;
|
||||
};
|
||||
|
||||
inputs = [ attr ];
|
||||
runtime = [ attr ];
|
||||
}
|
||||
19
internal/rosa/package/buildcatrust.az
Normal file
19
internal/rosa/package/buildcatrust.az
Normal file
@@ -0,0 +1,19 @@
|
||||
package buildcatrust {
|
||||
description = "transform certificate stores between formats";
|
||||
website = "https://github.com/nix-community/buildcatrust";
|
||||
anitya = 233988;
|
||||
|
||||
version* = "0.5.1";
|
||||
source = remoteGitHub {
|
||||
suffix = "nix-community/buildcatrust";
|
||||
tag = "v"+version;
|
||||
checksum = "oxjnuIrPVMPvD6x8VFLqB7EdbfuhouGQdtPuHDpEHGzoyH5nkxqtYN9UthMY9noA";
|
||||
};
|
||||
|
||||
early = "\nrm buildcatrust/tests/test_nonhermetic.py\n";
|
||||
|
||||
exec = pip {};
|
||||
|
||||
inputs = [ python-flit-core ];
|
||||
runtime = [ python ];
|
||||
}
|
||||
27
internal/rosa/package/bzip2.az
Normal file
27
internal/rosa/package/bzip2.az
Normal file
@@ -0,0 +1,27 @@
|
||||
package bzip2 {
|
||||
description = "a freely available, patent free, high-quality data compressor";
|
||||
website = "https://sourceware.org/bzip2";
|
||||
anitya = 237;
|
||||
|
||||
version* = "1.0.8";
|
||||
source = remoteTar {
|
||||
url = "https://sourceware.org/pub/bzip2/bzip2-"+version+".tar.gz";
|
||||
checksum = "cTLykcco7boom-s05H1JVsQi1AtChYL84nXkg_92Dm1Xt94Ob_qlMg_-NSguIK-c";
|
||||
compress = gzip;
|
||||
};
|
||||
|
||||
// uses source tree as scratch space
|
||||
writable = true;
|
||||
enterSource = true;
|
||||
|
||||
exec = make {
|
||||
skipConfigure = true;
|
||||
skipCheck = true;
|
||||
inPlace = true;
|
||||
|
||||
make = [
|
||||
"CC=cc",
|
||||
];
|
||||
install = "make PREFIX=/work/system install";
|
||||
};
|
||||
}
|
||||
13
internal/rosa/package/cmake/bootstrap-test-no-openssl.patch
Normal file
13
internal/rosa/package/cmake/bootstrap-test-no-openssl.patch
Normal file
@@ -0,0 +1,13 @@
|
||||
diff --git a/Tests/BootstrapTest.cmake b/Tests/BootstrapTest.cmake
|
||||
index 137de78bc1..b4da52e664 100644
|
||||
--- a/Tests/BootstrapTest.cmake
|
||||
+++ b/Tests/BootstrapTest.cmake
|
||||
@@ -9,7 +9,7 @@ if(NOT nproc EQUAL 0)
|
||||
endif()
|
||||
message(STATUS "running bootstrap: ${bootstrap} ${ninja_arg} ${parallel_arg}")
|
||||
execute_process(
|
||||
- COMMAND ${bootstrap} ${ninja_arg} ${parallel_arg}
|
||||
+ COMMAND ${bootstrap} ${ninja_arg} ${parallel_arg} -- -DCMAKE_USE_OPENSSL=OFF
|
||||
WORKING_DIRECTORY "${bin_dir}"
|
||||
RESULT_VARIABLE result
|
||||
)
|
||||
41
internal/rosa/package/cmake/disable-broken-tests-musl.patch
Normal file
41
internal/rosa/package/cmake/disable-broken-tests-musl.patch
Normal file
@@ -0,0 +1,41 @@
|
||||
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
|
||||
index 2ead810437..f85cbb8b1c 100644
|
||||
--- a/Tests/CMakeLists.txt
|
||||
+++ b/Tests/CMakeLists.txt
|
||||
@@ -384,7 +384,6 @@ if(BUILD_TESTING)
|
||||
add_subdirectory(CMakeLib)
|
||||
endif()
|
||||
add_subdirectory(CMakeOnly)
|
||||
- add_subdirectory(RunCMake)
|
||||
|
||||
add_subdirectory(FindPackageModeMakefileTest)
|
||||
|
||||
@@ -528,9 +527,6 @@ if(BUILD_TESTING)
|
||||
-DCMake_TEST_CUDA:BOOL=${CMake_TEST_CUDA}
|
||||
-DCMake_INSTALL_NAME_TOOL_BUG:BOOL=${CMake_INSTALL_NAME_TOOL_BUG}
|
||||
)
|
||||
- ADD_TEST_MACRO(ExportImport ExportImport)
|
||||
- set_property(TEST ExportImport APPEND
|
||||
- PROPERTY LABELS "CUDA")
|
||||
ADD_TEST_MACRO(Unset Unset)
|
||||
ADD_TEST_MACRO(PolicyScope PolicyScope)
|
||||
ADD_TEST_MACRO(EmptyLibrary EmptyLibrary)
|
||||
@@ -624,7 +620,6 @@ if(BUILD_TESTING)
|
||||
# run test for BundleUtilities on supported platforms/compilers
|
||||
if((MSVC OR
|
||||
MINGW OR
|
||||
- CMAKE_SYSTEM_NAME MATCHES "Linux" OR
|
||||
CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
AND NOT CMAKE_GENERATOR STREQUAL "Watcom WMake")
|
||||
|
||||
@@ -3095,10 +3090,6 @@ if(BUILD_TESTING)
|
||||
"${CMake_SOURCE_DIR}/Tests/CTestTestFdSetSize/test.cmake.in"
|
||||
"${CMake_BINARY_DIR}/Tests/CTestTestFdSetSize/test.cmake"
|
||||
@ONLY ESCAPE_QUOTES)
|
||||
- add_test(CTestTestFdSetSize ${CMAKE_CTEST_COMMAND}
|
||||
- -S "${CMake_BINARY_DIR}/Tests/CTestTestFdSetSize/test.cmake" -j20 -V --timeout 120
|
||||
- --output-log "${CMake_BINARY_DIR}/Tests/CTestTestFdSetSize/testOutput.log"
|
||||
- )
|
||||
|
||||
if(CMAKE_TESTS_CDASH_SERVER)
|
||||
set(regex "^([^:]+)://([^/]+)(.*)$")
|
||||
45
internal/rosa/package/cmake/package.az
Normal file
45
internal/rosa/package/cmake/package.az
Normal file
@@ -0,0 +1,45 @@
|
||||
package cmake {
|
||||
description = "cross-platform, open-source build system";
|
||||
website = "https://cmake.org";
|
||||
anitya = 306;
|
||||
|
||||
version* = "4.3.2";
|
||||
source = remoteGitHubRelease {
|
||||
suffix = "Kitware/CMake";
|
||||
tag = "v"+version;
|
||||
name = "cmake-"+version+".tar.gz";
|
||||
checksum = "6QylwRVKletndTSkZTV2YBRwgd_9rUVgav_QW23HpjUgV21AVYZOUOal8tdBDmO7";
|
||||
compress = gzip;
|
||||
};
|
||||
patches = [
|
||||
"bootstrap-test-no-openssl.patch",
|
||||
"disable-broken-tests-musl.patch",
|
||||
];
|
||||
|
||||
// test suite expects writable source tree
|
||||
writable = true;
|
||||
|
||||
// expected to be writable in the copy made during bootstrap
|
||||
chmod = true;
|
||||
|
||||
exec = make {
|
||||
omitDefaults = true;
|
||||
|
||||
configureName = "/usr/src/cmake/bootstrap";
|
||||
configure = {
|
||||
"prefix": "/system";
|
||||
"parallel": jobsE;
|
||||
"--";
|
||||
"-DCMAKE_USE_OPENSSL": "OFF";
|
||||
"-DCMake_TEST_NO_NETWORK": "ON";
|
||||
};
|
||||
|
||||
check = [
|
||||
"CTEST_OUTPUT_ON_FAILURE=1",
|
||||
"CTEST_PARALLEL_LEVEL=128",
|
||||
"test",
|
||||
];
|
||||
};
|
||||
|
||||
inputs = [ kernel-headers ];
|
||||
}
|
||||
@@ -1,20 +1,4 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newConnman() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.0"
|
||||
checksum = "MhVTdJOhndnZn2SWd8URKo_Pj7Zvc14tntEbrVOf9L3yVWJvpb3v3Q6104tWJgtW"
|
||||
)
|
||||
return t.NewPackage("connman", version, newTar(
|
||||
"https://git.kernel.org/pub/scm/network/connman/connman.git/"+
|
||||
"snapshot/connman-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), &PackageAttr{
|
||||
Patches: []KV{
|
||||
{"alpine-musl-res", `musl does not implement res_ninit
|
||||
musl does not implement res_ninit
|
||||
|
||||
--- a/gweb/gresolv.c
|
||||
+++ b/gweb/gresolv.c
|
||||
@@ -73,37 +57,3 @@ func (t Toolchain) newConnman() (pkg.Artifact, string) {
|
||||
}
|
||||
|
||||
if (!resolv->nameserver_list)
|
||||
`},
|
||||
},
|
||||
}, &MakeHelper{
|
||||
Generate: "./bootstrap",
|
||||
},
|
||||
Automake,
|
||||
Libtool,
|
||||
PkgConfig,
|
||||
|
||||
DBus,
|
||||
IPTables,
|
||||
GnuTLS,
|
||||
Readline,
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Connman] = Metadata{
|
||||
f: Toolchain.newConnman,
|
||||
|
||||
Name: "connman",
|
||||
Description: "a daemon for managing Internet connections",
|
||||
Website: "https://git.kernel.org/pub/scm/network/connman/connman.git/",
|
||||
|
||||
Dependencies: P{
|
||||
DBus,
|
||||
IPTables,
|
||||
GnuTLS,
|
||||
Readline,
|
||||
},
|
||||
|
||||
ID: 337,
|
||||
}
|
||||
}
|
||||
37
internal/rosa/package/connman/package.az
Normal file
37
internal/rosa/package/connman/package.az
Normal file
@@ -0,0 +1,37 @@
|
||||
package connman {
|
||||
description = "a daemon for managing Internet connections";
|
||||
website = "https://git.kernel.org/pub/scm/network/connman/connman.git";
|
||||
anitya = 337;
|
||||
|
||||
version* = "2.0";
|
||||
source = remoteTar {
|
||||
url = "https://git.kernel.org/pub/scm/network/connman/connman.git/"+
|
||||
"snapshot/connman-"+version+".tar.gz";
|
||||
checksum = "MhVTdJOhndnZn2SWd8URKo_Pj7Zvc14tntEbrVOf9L3yVWJvpb3v3Q6104tWJgtW";
|
||||
compress = gzip;
|
||||
};
|
||||
patches = [ "alpine-musl-res.patch" ];
|
||||
|
||||
exec = make {
|
||||
generate = "./bootstrap";
|
||||
};
|
||||
|
||||
inputs = [
|
||||
automake,
|
||||
libtool,
|
||||
pkg-config,
|
||||
|
||||
dbus,
|
||||
iptables,
|
||||
gnutls,
|
||||
readline,
|
||||
kernel-headers,
|
||||
];
|
||||
|
||||
runtime = [
|
||||
dbus,
|
||||
iptables,
|
||||
gnutls,
|
||||
readline,
|
||||
];
|
||||
}
|
||||
47
internal/rosa/package/curl.az
Normal file
47
internal/rosa/package/curl.az
Normal file
@@ -0,0 +1,47 @@
|
||||
package curl {
|
||||
description = "command line tool and library for transferring data with URLs";
|
||||
website = "https://curl.se";
|
||||
anitya = 381;
|
||||
|
||||
version* = "8.20.0";
|
||||
source = remoteTar {
|
||||
url = "https://curl.se/download/curl-"+version+".tar.bz2";
|
||||
checksum = "xyHXwrngIRGMasuzhn-I5MSCOhktwINbsWt1f_LuR-5jRVvyx_g6U1EQfDLEbr9r";
|
||||
compress = bzip2;
|
||||
};
|
||||
|
||||
// remove broken test
|
||||
writable = true;
|
||||
early = "\nchmod +w tests/data && rm -f tests/data/test459\n";
|
||||
|
||||
exec = make {
|
||||
configure = {
|
||||
"with-openssl";
|
||||
"with-ca-bundle": "/system/etc/ssl/certs/ca-bundle.crt";
|
||||
|
||||
"disable-smb";
|
||||
};
|
||||
|
||||
check = [
|
||||
"TFLAGS=" + jobsLFlagE,
|
||||
"test-nonflaky",
|
||||
];
|
||||
};
|
||||
|
||||
inputs = [
|
||||
perl,
|
||||
python,
|
||||
pkg-config,
|
||||
diffutils,
|
||||
|
||||
libpsl,
|
||||
openssl,
|
||||
];
|
||||
|
||||
runtime = [
|
||||
zlib,
|
||||
zstd,
|
||||
libpsl,
|
||||
openssl,
|
||||
];
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user