Compare commits
97 Commits
94a3ea9e5c
...
staging
| Author | SHA1 | Date | |
|---|---|---|---|
|
a71a008f3c
|
|||
|
162265b47e
|
|||
|
3fa7ac04e4
|
|||
|
bf2867d653
|
|||
|
ec0f0f6507
|
|||
|
a77a802955
|
|||
|
4407e14dfc
|
|||
|
e024d3184a
|
|||
|
8e1bf00c2d
|
|||
|
b111e22050
|
|||
|
1fa458c0be
|
|||
|
2c7ae67a67
|
|||
|
3826621b21
|
|||
|
041b505c2e
|
|||
|
e6debce649
|
|||
|
aa26b86fce
|
|||
|
a57a8fd5d8
|
|||
|
1d5d063d6a
|
|||
|
e61628a34e
|
|||
|
5a18f14929
|
|||
|
f12880688d
|
|||
|
bb5bbfe16a
|
|||
|
427e1ca37c
|
|||
|
96fdd9ecc5
|
|||
|
02771b655b
|
|||
|
d1c8d2c39b
|
|||
|
0efd742e8a
|
|||
|
ae1fe638d5
|
|||
|
445d95023b
|
|||
|
fc66f0bb47
|
|||
|
2cd6b35bee
|
|||
|
09a216c6ec
|
|||
|
44d17325c2
|
|||
|
544ce77cbc
|
|||
|
63c3c30b23
|
|||
|
d23c4ecc7c
|
|||
|
a46656dff8
|
|||
|
77db153ff5
|
|||
|
520d95bc07
|
|||
|
451df3f4e7
|
|||
|
011fac15ed
|
|||
|
347682ad0b
|
|||
|
1a2b979add
|
|||
|
b1c90cc380
|
|||
|
3a66b8143a
|
|||
|
64bbd3aabd
|
|||
|
08799a13d0
|
|||
|
1aef9c3bbb
|
|||
|
1f38303747
|
|||
|
640777b00c
|
|||
|
1d657193cf
|
|||
|
bab5406295
|
|||
|
725ae7d64d
|
|||
|
37a0c3967e
|
|||
|
ea0692548f
|
|||
|
48ea23e648
|
|||
|
40320e4920
|
|||
|
3ca0f61632
|
|||
|
6ffaac96e3
|
|||
|
13c7713d0c
|
|||
|
42389f7ec5
|
|||
|
30f130c691
|
|||
|
ceb4d26087
|
|||
|
852f3a9b3d
|
|||
|
5e02dbdb0d
|
|||
|
6a3248d472
|
|||
|
67404c98d9
|
|||
|
b9bf69cfce
|
|||
|
4648f98272
|
|||
|
11d99439ac
|
|||
|
39e4c5b8ac
|
|||
|
e8f6db38b6
|
|||
|
20d5b71575
|
|||
|
e903e7f542
|
|||
|
1caa051f4d
|
|||
|
dcdc6f7f6d
|
|||
|
5ad6f26b46
|
|||
|
7ba75a79f4
|
|||
|
9ef84d3904
|
|||
|
3b7b6e51fb
|
|||
|
b1b4debb82
|
|||
|
021cbbc2a8
|
|||
|
a4a54a4a4d
|
|||
|
04a344aac6
|
|||
|
6b98156a3d
|
|||
|
753432cf09
|
|||
|
f8902e3679
|
|||
|
8ee53a5164
|
|||
|
3981d44757
|
|||
|
9fd67e47b4
|
|||
|
4dcec40156
|
|||
|
9a274c78a3
|
|||
|
5647c3a91f
|
|||
|
992139c75d
|
|||
|
57c69b533e
|
|||
|
6f0c2a80f2
|
|||
|
08dfefb28d
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -7,7 +7,7 @@
|
||||
|
||||
# go generate
|
||||
/cmd/hakurei/LICENSE
|
||||
/cmd/pkgserver/ui/static/*.js
|
||||
/cmd/mbf/internal/pkgserver/ui/static
|
||||
/internal/pkg/testdata/testtool
|
||||
/internal/rosa/hakurei_current.tar.gz
|
||||
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"hakurei.app/command"
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.SetFlags(0)
|
||||
log.SetPrefix("irdump: ")
|
||||
|
||||
var (
|
||||
flagOutput string
|
||||
flagReal bool
|
||||
flagHeader bool
|
||||
flagForce bool
|
||||
flagRaw bool
|
||||
)
|
||||
c := command.New(os.Stderr, log.Printf, "irdump", func(args []string) (err error) {
|
||||
var input *os.File
|
||||
if len(args) != 1 {
|
||||
return errors.New("irdump requires 1 argument")
|
||||
}
|
||||
if input, err = os.Open(args[0]); err != nil {
|
||||
return
|
||||
}
|
||||
defer input.Close()
|
||||
|
||||
var output *os.File
|
||||
if flagOutput == "" {
|
||||
output = os.Stdout
|
||||
} else {
|
||||
defer output.Close()
|
||||
if output, err = os.Create(flagOutput); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var out string
|
||||
if out, err = pkg.Disassemble(input, flagReal, flagHeader, flagForce, flagRaw); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = output.WriteString(out); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}).Flag(
|
||||
&flagOutput,
|
||||
"o", command.StringFlag(""),
|
||||
"Output file for asm (leave empty for stdout)",
|
||||
).Flag(
|
||||
&flagReal,
|
||||
"r", command.BoolFlag(false),
|
||||
"skip label generation; idents print real value",
|
||||
).Flag(
|
||||
&flagHeader,
|
||||
"H", command.BoolFlag(false),
|
||||
"display artifact headers",
|
||||
).Flag(
|
||||
&flagForce,
|
||||
"f", command.BoolFlag(false),
|
||||
"force display (skip validations)",
|
||||
).Flag(
|
||||
&flagRaw,
|
||||
"R", command.BoolFlag(false),
|
||||
"don't format output",
|
||||
)
|
||||
|
||||
c.MustParse(os.Args[1:], func(err error) {
|
||||
log.Fatal(err)
|
||||
})
|
||||
}
|
||||
@@ -31,9 +31,6 @@ func (cache *cache) open() (err error) {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
|
||||
if cache.base == "" {
|
||||
cache.base = "cache"
|
||||
}
|
||||
var base *check.Absolute
|
||||
if cache.base, err = filepath.Abs(cache.base); err != nil {
|
||||
return
|
||||
|
||||
@@ -99,10 +99,9 @@ func cancelIdent(
|
||||
var ident pkg.ID
|
||||
if _, err := io.ReadFull(conn, ident[:]); err != nil {
|
||||
return nil, false, errors.Join(err, conn.Close())
|
||||
} else if err = conn.Close(); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return &ident, cache.Cancel(unique.Make(ident)), nil
|
||||
ok := cache.Cancel(unique.Make(ident))
|
||||
return &ident, ok, conn.Close()
|
||||
}
|
||||
|
||||
// serve services connections from a [net.UnixListener].
|
||||
@@ -194,11 +193,11 @@ func serve(
|
||||
}
|
||||
|
||||
case specialAbort:
|
||||
log.Println("aborting all pending cures")
|
||||
cm.c.Abort()
|
||||
if _err := conn.Close(); _err != nil {
|
||||
log.Println(_err)
|
||||
}
|
||||
log.Println("aborting all pending cures")
|
||||
cm.c.Abort()
|
||||
}
|
||||
|
||||
return
|
||||
@@ -306,6 +305,7 @@ func cancelRemote(
|
||||
ctx context.Context,
|
||||
addr *net.UnixAddr,
|
||||
a pkg.Artifact,
|
||||
wait bool,
|
||||
) error {
|
||||
done, conn, err := dial(ctx, addr)
|
||||
if err != nil {
|
||||
@@ -324,13 +324,19 @@ func cancelRemote(
|
||||
} else if n != len(id) {
|
||||
return errors.Join(io.ErrShortWrite, conn.Close())
|
||||
}
|
||||
return conn.Close()
|
||||
if wait {
|
||||
if _, err = conn.Read(make([]byte, 1)); err == io.EOF {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
return errors.Join(err, conn.Close())
|
||||
}
|
||||
|
||||
// abortRemote aborts all [pkg.Artifact] curing on a daemon.
|
||||
func abortRemote(
|
||||
ctx context.Context,
|
||||
addr *net.UnixAddr,
|
||||
wait bool,
|
||||
) error {
|
||||
done, conn, err := dial(ctx, addr)
|
||||
if err != nil {
|
||||
@@ -339,5 +345,10 @@ func abortRemote(
|
||||
defer close(done)
|
||||
|
||||
err = writeSpecialHeader(conn, specialAbort)
|
||||
if wait && err == nil {
|
||||
if _, err = conn.Read(make([]byte, 1)); err == io.EOF {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
return errors.Join(err, conn.Close())
|
||||
}
|
||||
|
||||
@@ -106,11 +106,11 @@ func TestDaemon(t *testing.T) {
|
||||
}
|
||||
}()
|
||||
|
||||
if err = cancelRemote(ctx, &addr, pkg.NewFile("nonexistent", nil)); err != nil {
|
||||
if err = cancelRemote(ctx, &addr, pkg.NewFile("nonexistent", nil), true); err != nil {
|
||||
t.Fatalf("cancelRemote: error = %v", err)
|
||||
}
|
||||
|
||||
if err = abortRemote(ctx, &addr); err != nil {
|
||||
if err = abortRemote(ctx, &addr, true); err != nil {
|
||||
t.Fatalf("abortRemote: error = %v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,25 +17,12 @@ func commandInfo(
|
||||
args []string,
|
||||
w io.Writer,
|
||||
writeStatus bool,
|
||||
reportPath string,
|
||||
r *rosa.Report,
|
||||
) (err error) {
|
||||
if len(args) == 0 {
|
||||
return errors.New("info requires at least 1 argument")
|
||||
}
|
||||
|
||||
var r *rosa.Report
|
||||
if reportPath != "" {
|
||||
if r, err = rosa.OpenReport(reportPath); err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if closeErr := r.Close(); err == nil {
|
||||
err = closeErr
|
||||
}
|
||||
}()
|
||||
defer r.HandleAccess(&err)()
|
||||
}
|
||||
|
||||
// recovered by HandleAccess
|
||||
mustPrintln := func(a ...any) {
|
||||
if _, _err := fmt.Fprintln(w, a...); _err != nil {
|
||||
|
||||
@@ -95,7 +95,7 @@ status : not in report
|
||||
var (
|
||||
cm *cache
|
||||
buf strings.Builder
|
||||
rp string
|
||||
r *rosa.Report
|
||||
)
|
||||
|
||||
if tc.status != nil || tc.report != "" {
|
||||
@@ -108,14 +108,25 @@ status : not in report
|
||||
}
|
||||
|
||||
if tc.report != "" {
|
||||
rp = filepath.Join(t.TempDir(), "report")
|
||||
if err := os.WriteFile(
|
||||
rp,
|
||||
pathname := filepath.Join(t.TempDir(), "report")
|
||||
err := os.WriteFile(
|
||||
pathname,
|
||||
unsafe.Slice(unsafe.StringData(tc.report), len(tc.report)),
|
||||
0400,
|
||||
); err != nil {
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
r, err = rosa.OpenReport(pathname)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
if err = r.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
if tc.status != nil {
|
||||
@@ -157,7 +168,7 @@ status : not in report
|
||||
tc.args,
|
||||
&buf,
|
||||
cm != nil,
|
||||
rp,
|
||||
r,
|
||||
); !reflect.DeepEqual(err, wantErr) {
|
||||
t.Fatalf("commandInfo: error = %v, want %v", err, wantErr)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package main
|
||||
// Package pkgserver implements the package metadata service backend.
|
||||
package pkgserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
@@ -8,6 +10,7 @@ import (
|
||||
"path"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"hakurei.app/internal/info"
|
||||
"hakurei.app/internal/rosa"
|
||||
@@ -158,6 +161,29 @@ func (index *packageIndex) registerAPI(mux *http.ServeMux) {
|
||||
mux.HandleFunc("GET /status/", index.newStatusHandler(true))
|
||||
}
|
||||
|
||||
// Register arranges for mux to service API requests.
|
||||
func Register(ctx context.Context, mux *http.ServeMux, report *rosa.Report) error {
|
||||
var index packageIndex
|
||||
index.search = make(searchCache)
|
||||
if err := index.populate(report); err != nil {
|
||||
return err
|
||||
}
|
||||
ticker := time.NewTicker(1 * time.Minute)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
ticker.Stop()
|
||||
return
|
||||
case <-ticker.C:
|
||||
index.search.clean()
|
||||
}
|
||||
}
|
||||
}()
|
||||
index.registerAPI(mux)
|
||||
return nil
|
||||
}
|
||||
|
||||
// writeAPIPayload sets headers common to API responses and encodes payload as
|
||||
// JSON for the response body.
|
||||
func writeAPIPayload(w http.ResponseWriter, payload any) {
|
||||
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package pkgserver
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -118,33 +118,31 @@ func TestAPIGet(t *testing.T) {
|
||||
checkStatus(t, resp, http.StatusOK)
|
||||
checkAPIHeader(t, w.Header())
|
||||
checkPayloadFunc(t, resp, func(got *struct {
|
||||
Count int `json:"count"`
|
||||
Values []*metadata `json:"values"`
|
||||
}) bool {
|
||||
return got.Count == len(want) &&
|
||||
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
|
||||
})
|
||||
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=0&sort=0", []*metadata{
|
||||
{
|
||||
Metadata: rosa.GetMetadata(0),
|
||||
Version: rosa.Std.Version(0),
|
||||
},
|
||||
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{
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package pkgserver
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
@@ -50,7 +50,7 @@ type metadata struct {
|
||||
}
|
||||
|
||||
// populate deterministically populates packageIndex, optionally with a report.
|
||||
func (index *packageIndex) populate(cache *pkg.Cache, report *rosa.Report) (err error) {
|
||||
func (index *packageIndex) populate(report *rosa.Report) (err error) {
|
||||
if report != nil {
|
||||
defer report.HandleAccess(&err)()
|
||||
index.handleAccess = report.HandleAccess
|
||||
@@ -58,6 +58,7 @@ func (index *packageIndex) populate(cache *pkg.Cache, report *rosa.Report) (err
|
||||
|
||||
var work [rosa.PresetUnexportedStart]*metadata
|
||||
index.names = make(map[string]*metadata)
|
||||
ir := pkg.NewIR()
|
||||
for p := range rosa.PresetUnexportedStart {
|
||||
m := metadata{
|
||||
p: p,
|
||||
@@ -72,8 +73,8 @@ func (index *packageIndex) populate(cache *pkg.Cache, report *rosa.Report) (err
|
||||
m.Version = ""
|
||||
}
|
||||
|
||||
if cache != nil && report != nil {
|
||||
id := cache.Ident(rosa.Std.Load(p))
|
||||
if report != nil {
|
||||
id := ir.Ident(rosa.Std.Load(p))
|
||||
m.ids = pkg.Encode(id.Value())
|
||||
m.status, m.Size = report.ArtifactOf(id)
|
||||
m.HasReport = m.Size >= 0
|
||||
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package pkgserver
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -15,7 +15,7 @@ func newIndex(t *testing.T) *packageIndex {
|
||||
t.Helper()
|
||||
|
||||
var index packageIndex
|
||||
if err := index.populate(nil, nil); err != nil {
|
||||
if err := index.populate(nil); err != nil {
|
||||
t.Fatalf("populate: error = %v", err)
|
||||
}
|
||||
return &index
|
||||
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package pkgserver
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
@@ -3,9 +3,9 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="static/style.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<title>Hakurei PkgServer</title>
|
||||
<script src="static/index.js"></script>
|
||||
<script src="index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hakurei PkgServer</h1>
|
||||
9
cmd/mbf/internal/pkgserver/ui/ui.go
Normal file
9
cmd/mbf/internal/pkgserver/ui/ui.go
Normal file
@@ -0,0 +1,9 @@
|
||||
// Package ui holds the static web UI.
|
||||
package ui
|
||||
|
||||
import "net/http"
|
||||
|
||||
// Register arranges for mux to serve the embedded frontend.
|
||||
func Register(mux *http.ServeMux) {
|
||||
mux.Handle("GET /", http.FileServer(http.FS(static)))
|
||||
}
|
||||
21
cmd/mbf/internal/pkgserver/ui/ui_full.go
Normal file
21
cmd/mbf/internal/pkgserver/ui/ui_full.go
Normal file
@@ -0,0 +1,21 @@
|
||||
//go:build frontend
|
||||
|
||||
package ui
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"io/fs"
|
||||
)
|
||||
|
||||
//go:generate tsc
|
||||
//go:generate cp index.html style.css static
|
||||
//go:embed static
|
||||
var _static embed.FS
|
||||
|
||||
var static = func() fs.FS {
|
||||
if f, err := fs.Sub(_static, "static"); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
return f
|
||||
}
|
||||
}()
|
||||
@@ -1,7 +1,7 @@
|
||||
//go:build !frontend
|
||||
|
||||
package main
|
||||
package ui
|
||||
|
||||
import "testing/fstest"
|
||||
|
||||
var content fstest.MapFS
|
||||
var static fstest.MapFS
|
||||
132
cmd/mbf/main.go
132
cmd/mbf/main.go
@@ -20,6 +20,7 @@ import (
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
@@ -41,6 +42,9 @@ import (
|
||||
"hakurei.app/internal/pkg"
|
||||
"hakurei.app/internal/rosa"
|
||||
"hakurei.app/message"
|
||||
|
||||
"hakurei.app/cmd/mbf/internal/pkgserver"
|
||||
"hakurei.app/cmd/mbf/internal/pkgserver/ui"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -59,17 +63,12 @@ func main() {
|
||||
defer stop()
|
||||
|
||||
var cm cache
|
||||
defer func() {
|
||||
cm.Close()
|
||||
|
||||
if r := recover(); r != nil {
|
||||
fmt.Println(r)
|
||||
log.Fatal("consider scrubbing the on-disk cache")
|
||||
}
|
||||
}()
|
||||
defer func() { cm.Close() }()
|
||||
|
||||
var (
|
||||
flagQuiet bool
|
||||
flagCheck bool
|
||||
flagLTO bool
|
||||
|
||||
addr net.UnixAddr
|
||||
)
|
||||
@@ -77,18 +76,38 @@ func main() {
|
||||
msg.SwapVerbose(!flagQuiet)
|
||||
cm.ctx, cm.msg = ctx, msg
|
||||
cm.base = os.ExpandEnv(cm.base)
|
||||
if cm.base == "" {
|
||||
cm.base = "cache"
|
||||
}
|
||||
|
||||
addr.Net = "unix"
|
||||
addr.Name = os.ExpandEnv(addr.Name)
|
||||
if addr.Name == "" {
|
||||
addr.Name = "daemon"
|
||||
addr.Name = filepath.Join(cm.base, "daemon")
|
||||
}
|
||||
|
||||
var flags int
|
||||
if !flagCheck {
|
||||
flags |= rosa.OptSkipCheck
|
||||
}
|
||||
if !flagLTO {
|
||||
flags |= rosa.OptLLVMNoLTO
|
||||
}
|
||||
rosa.DropCaches(flags)
|
||||
|
||||
return nil
|
||||
}).Flag(
|
||||
&flagQuiet,
|
||||
"q", command.BoolFlag(false),
|
||||
"Do not print cure messages",
|
||||
).Flag(
|
||||
&flagLTO,
|
||||
"lto", command.BoolFlag(false),
|
||||
"Enable LTO in stage2 and stage3 LLVM toolchains",
|
||||
).Flag(
|
||||
&flagCheck,
|
||||
"check", command.BoolFlag(true),
|
||||
"Run test suites",
|
||||
).Flag(
|
||||
&cm.cures,
|
||||
"cures", command.IntFlag(0),
|
||||
@@ -121,7 +140,17 @@ func main() {
|
||||
c.NewCommand(
|
||||
"checksum", "Compute checksum of data read from standard input",
|
||||
func([]string) error {
|
||||
go func() { <-ctx.Done(); os.Exit(1) }()
|
||||
done := make(chan struct{})
|
||||
defer close(done)
|
||||
go func() {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
os.Exit(1)
|
||||
case <-done:
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
h := sha512.New384()
|
||||
if _, err := io.Copy(h, os.Stdin); err != nil {
|
||||
return err
|
||||
@@ -155,6 +184,7 @@ func main() {
|
||||
|
||||
{
|
||||
var (
|
||||
flagBind string
|
||||
flagStatus bool
|
||||
flagReport string
|
||||
)
|
||||
@@ -162,8 +192,52 @@ func main() {
|
||||
"info",
|
||||
"Display out-of-band metadata of an artifact",
|
||||
func(args []string) (err error) {
|
||||
return commandInfo(&cm, args, os.Stdout, flagStatus, flagReport)
|
||||
const shutdownTimeout = 15 * time.Second
|
||||
|
||||
var r *rosa.Report
|
||||
if flagReport != "" {
|
||||
if r, err = rosa.OpenReport(flagReport); err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if closeErr := r.Close(); err == nil {
|
||||
err = closeErr
|
||||
}
|
||||
}()
|
||||
defer r.HandleAccess(&err)()
|
||||
}
|
||||
|
||||
if flagBind == "" {
|
||||
return commandInfo(&cm, args, os.Stdout, flagStatus, r)
|
||||
}
|
||||
|
||||
var mux http.ServeMux
|
||||
ui.Register(&mux)
|
||||
if err = pkgserver.Register(ctx, &mux, r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
server := http.Server{Addr: flagBind, Handler: &mux}
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
cc, cancel := context.WithTimeout(context.Background(), shutdownTimeout)
|
||||
defer cancel()
|
||||
if _err := server.Shutdown(cc); _err != nil {
|
||||
log.Fatal(_err)
|
||||
}
|
||||
}()
|
||||
|
||||
msg.Verbosef("listening on %q", flagBind)
|
||||
err = server.ListenAndServe()
|
||||
if errors.Is(err, http.ErrServerClosed) {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
},
|
||||
).Flag(
|
||||
&flagBind,
|
||||
"bind", command.StringFlag(""),
|
||||
"TCP address for the server to listen on",
|
||||
).Flag(
|
||||
&flagStatus,
|
||||
"status", command.BoolFlag(false),
|
||||
@@ -322,7 +396,7 @@ func main() {
|
||||
|
||||
if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
||||
pathname, _, err = cache.Cure(
|
||||
(t - 2).Load(rosa.Clang),
|
||||
(t - 2).Load(rosa.LLVM),
|
||||
)
|
||||
return
|
||||
}); err != nil {
|
||||
@@ -332,7 +406,7 @@ func main() {
|
||||
|
||||
if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
||||
pathname, checksum[0], err = cache.Cure(
|
||||
(t - 1).Load(rosa.Clang),
|
||||
(t - 1).Load(rosa.LLVM),
|
||||
)
|
||||
return
|
||||
}); err != nil {
|
||||
@@ -341,7 +415,7 @@ func main() {
|
||||
log.Println("stage2:", pathname)
|
||||
if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
||||
pathname, checksum[1], err = cache.Cure(
|
||||
t.Load(rosa.Clang),
|
||||
t.Load(rosa.LLVM),
|
||||
)
|
||||
return
|
||||
}); err != nil {
|
||||
@@ -397,6 +471,9 @@ func main() {
|
||||
flagExport string
|
||||
flagRemote bool
|
||||
flagNoReply bool
|
||||
|
||||
flagBoot bool
|
||||
flagStd bool
|
||||
)
|
||||
c.NewCommand(
|
||||
"cure",
|
||||
@@ -410,11 +487,18 @@ func main() {
|
||||
return fmt.Errorf("unknown artifact %q", args[0])
|
||||
}
|
||||
|
||||
t := rosa.Std
|
||||
if flagBoot {
|
||||
t -= 2
|
||||
} else if flagStd {
|
||||
t -= 1
|
||||
}
|
||||
|
||||
switch {
|
||||
default:
|
||||
var pathname *check.Absolute
|
||||
err := cm.Do(func(cache *pkg.Cache) (err error) {
|
||||
pathname, _, err = cache.Cure(rosa.Std.Load(p))
|
||||
pathname, _, err = cache.Cure(t.Load(p))
|
||||
return
|
||||
})
|
||||
if err != nil {
|
||||
@@ -467,7 +551,7 @@ func main() {
|
||||
return cm.Do(func(cache *pkg.Cache) error {
|
||||
return cache.EnterExec(
|
||||
ctx,
|
||||
rosa.Std.Load(p),
|
||||
t.Load(p),
|
||||
true, os.Stdin, os.Stdout, os.Stderr,
|
||||
rosa.AbsSystem.Append("bin", "mksh"),
|
||||
"sh",
|
||||
@@ -479,7 +563,7 @@ func main() {
|
||||
if flagNoReply {
|
||||
flags |= remoteNoReply
|
||||
}
|
||||
a := rosa.Std.Load(p)
|
||||
a := t.Load(p)
|
||||
pathname, err := cureRemote(ctx, &addr, a, flags)
|
||||
if !flagNoReply && err == nil {
|
||||
log.Println(pathname)
|
||||
@@ -489,7 +573,7 @@ func main() {
|
||||
cc, cancel := context.WithDeadline(context.Background(), daemonDeadline())
|
||||
defer cancel()
|
||||
|
||||
if _err := cancelRemote(cc, &addr, a); _err != nil {
|
||||
if _err := cancelRemote(cc, &addr, a, false); _err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
@@ -517,13 +601,21 @@ func main() {
|
||||
&flagNoReply,
|
||||
"no-reply", command.BoolFlag(false),
|
||||
"Do not receive a reply from the daemon",
|
||||
).Flag(
|
||||
&flagBoot,
|
||||
"boot", command.BoolFlag(false),
|
||||
"Build on the stage0 toolchain",
|
||||
).Flag(
|
||||
&flagStd,
|
||||
"std", command.BoolFlag(false),
|
||||
"Build on the intermediate toolchain",
|
||||
)
|
||||
}
|
||||
|
||||
c.NewCommand(
|
||||
"abort",
|
||||
"Abort all pending cures on the daemon",
|
||||
func([]string) error { return abortRemote(ctx, &addr) },
|
||||
func([]string) error { return abortRemote(ctx, &addr, false) },
|
||||
)
|
||||
|
||||
{
|
||||
@@ -546,7 +638,7 @@ func main() {
|
||||
presets[i] = p
|
||||
}
|
||||
|
||||
base := rosa.Clang
|
||||
base := rosa.LLVM
|
||||
if !flagWithToolchain {
|
||||
base = rosa.Musl
|
||||
}
|
||||
|
||||
47
cmd/mbf/main_test.go
Normal file
47
cmd/mbf/main_test.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"hakurei.app/internal/rosa"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
rosa.DropCaches(rosa.OptLLVMNoLTO)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestCureAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
const env = "ROSA_TEST_DAEMON"
|
||||
|
||||
if !testing.Verbose() {
|
||||
t.Skip("verbose flag not set")
|
||||
}
|
||||
|
||||
pathname, ok := os.LookupEnv(env)
|
||||
if !ok {
|
||||
t.Skip(env + " not set")
|
||||
}
|
||||
|
||||
addr := net.UnixAddr{Net: "unix", Name: pathname}
|
||||
t.Cleanup(func() {
|
||||
if t.Failed() {
|
||||
if err := abortRemote(t.Context(), &addr, false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
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)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"hakurei.app/check"
|
||||
"hakurei.app/command"
|
||||
"hakurei.app/internal/pkg"
|
||||
"hakurei.app/internal/rosa"
|
||||
"hakurei.app/message"
|
||||
)
|
||||
|
||||
const shutdownTimeout = 15 * time.Second
|
||||
|
||||
func main() {
|
||||
log.SetFlags(0)
|
||||
log.SetPrefix("pkgserver: ")
|
||||
|
||||
var (
|
||||
flagBaseDir string
|
||||
flagAddr string
|
||||
)
|
||||
|
||||
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
|
||||
defer stop()
|
||||
msg := message.New(log.Default())
|
||||
|
||||
c := command.New(os.Stderr, log.Printf, "pkgserver", func(args []string) error {
|
||||
var (
|
||||
cache *pkg.Cache
|
||||
report *rosa.Report
|
||||
)
|
||||
switch len(args) {
|
||||
case 0:
|
||||
break
|
||||
|
||||
case 1:
|
||||
baseDir, err := check.NewAbs(flagBaseDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cache, err = pkg.Open(ctx, msg, 0, 0, baseDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cache.Close()
|
||||
|
||||
report, err = rosa.OpenReport(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
default:
|
||||
return errors.New("pkgserver requires 1 argument")
|
||||
|
||||
}
|
||||
|
||||
var index packageIndex
|
||||
index.search = make(searchCache)
|
||||
if err := index.populate(cache, report); err != nil {
|
||||
return err
|
||||
}
|
||||
ticker := time.NewTicker(1 * time.Minute)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
ticker.Stop()
|
||||
return
|
||||
case <-ticker.C:
|
||||
index.search.clean()
|
||||
}
|
||||
}
|
||||
}()
|
||||
var mux http.ServeMux
|
||||
uiRoutes(&mux)
|
||||
index.registerAPI(&mux)
|
||||
server := http.Server{
|
||||
Addr: flagAddr,
|
||||
Handler: &mux,
|
||||
}
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
c, cancel := context.WithTimeout(context.Background(), shutdownTimeout)
|
||||
defer cancel()
|
||||
if err := server.Shutdown(c); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
return server.ListenAndServe()
|
||||
}).Flag(
|
||||
&flagBaseDir,
|
||||
"b", command.StringFlag(""),
|
||||
"base directory for cache",
|
||||
).Flag(
|
||||
&flagAddr,
|
||||
"addr", command.StringFlag(":8067"),
|
||||
"TCP network address to listen on",
|
||||
)
|
||||
c.MustParse(os.Args[1:], func(err error) {
|
||||
if errors.Is(err, http.ErrServerClosed) {
|
||||
os.Exit(0)
|
||||
}
|
||||
log.Fatal(err)
|
||||
})
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package main
|
||||
|
||||
import "net/http"
|
||||
|
||||
func serveWebUI(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
|
||||
w.Header().Set("Pragma", "no-cache")
|
||||
w.Header().Set("Expires", "0")
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
w.Header().Set("X-XSS-Protection", "1")
|
||||
w.Header().Set("X-Frame-Options", "DENY")
|
||||
|
||||
http.ServeFileFS(w, r, content, "ui/index.html")
|
||||
}
|
||||
func serveStaticContent(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case "/static/style.css":
|
||||
http.ServeFileFS(w, r, content, "ui/static/style.css")
|
||||
case "/favicon.ico":
|
||||
http.ServeFileFS(w, r, content, "ui/static/favicon.ico")
|
||||
case "/static/index.js":
|
||||
http.ServeFileFS(w, r, content, "ui/static/index.js")
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func uiRoutes(mux *http.ServeMux) {
|
||||
mux.HandleFunc("GET /{$}", serveWebUI)
|
||||
mux.HandleFunc("GET /favicon.ico", serveStaticContent)
|
||||
mux.HandleFunc("GET /static/", serveStaticContent)
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB |
@@ -1,9 +0,0 @@
|
||||
//go:build frontend
|
||||
|
||||
package main
|
||||
|
||||
import "embed"
|
||||
|
||||
//go:generate tsc -p ui
|
||||
//go:embed ui/*
|
||||
var content embed.FS
|
||||
@@ -118,6 +118,10 @@ func errnoFallback(op, path string, err error) (syscall.Errno, *os.PathError) {
|
||||
|
||||
// mount wraps syscall.Mount for error handling.
|
||||
func mount(source, target, fstype string, flags uintptr, data string) error {
|
||||
if max(len(source), len(target), len(data))+1 > os.Getpagesize() {
|
||||
return &MountError{source, target, fstype, flags, data, syscall.ENOMEM}
|
||||
}
|
||||
|
||||
err := syscall.Mount(source, target, fstype, flags, data)
|
||||
if err == nil {
|
||||
return nil
|
||||
|
||||
@@ -1,216 +0,0 @@
|
||||
package pkg
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type asmOutLine struct {
|
||||
pos int
|
||||
word int
|
||||
kindData int64
|
||||
valueData []byte
|
||||
indent int
|
||||
kind string
|
||||
value string
|
||||
}
|
||||
|
||||
var spacingLine = asmOutLine{
|
||||
pos: -1,
|
||||
kindData: -1,
|
||||
valueData: nil,
|
||||
indent: 0,
|
||||
kind: "",
|
||||
value: "",
|
||||
}
|
||||
|
||||
func Disassemble(r io.Reader, real bool, showHeader bool, force bool, raw bool) (s string, err error) {
|
||||
var lines []asmOutLine
|
||||
sb := new(strings.Builder)
|
||||
header := true
|
||||
pos := new(int)
|
||||
|
||||
for err == nil {
|
||||
if header {
|
||||
var kind uint64
|
||||
var size uint64
|
||||
var bsize []byte
|
||||
p := *pos
|
||||
if _, kind, err = nextUint64(r, pos); err != nil {
|
||||
break
|
||||
}
|
||||
if bsize, size, err = nextUint64(r, pos); err != nil {
|
||||
break
|
||||
}
|
||||
if showHeader {
|
||||
lines = append(lines, asmOutLine{p, 8, int64(kind), bsize, 0, "head " + intToKind(kind), ""})
|
||||
}
|
||||
for i := 0; uint64(i) < size; i++ {
|
||||
var did Checksum
|
||||
var dkind uint64
|
||||
p := *pos
|
||||
if _, dkind, err = nextUint64(r, pos); err != nil {
|
||||
break
|
||||
}
|
||||
if _, did, err = nextIdent(r, pos); err != nil {
|
||||
break
|
||||
}
|
||||
if showHeader {
|
||||
lines = append(lines, asmOutLine{p, 8, int64(dkind), nil, 1, intToKind(dkind), Encode(did)})
|
||||
}
|
||||
}
|
||||
header = false
|
||||
}
|
||||
var k uint32
|
||||
p := *pos
|
||||
if _, k, err = nextUint32(r, pos); err != nil {
|
||||
break
|
||||
}
|
||||
kind := IRValueKind(k)
|
||||
switch kind {
|
||||
case IRKindEnd:
|
||||
var a uint32
|
||||
var ba []byte
|
||||
if ba, a, err = nextUint32(r, pos); err != nil {
|
||||
break
|
||||
}
|
||||
if a&1 != 0 {
|
||||
var sum Checksum
|
||||
if _, sum, err = nextIdent(r, pos); err != nil {
|
||||
break
|
||||
}
|
||||
lines = append(lines, asmOutLine{p, 4, int64(kind), ba, 1, "end ", Encode(sum)})
|
||||
} else {
|
||||
lines = append(lines, asmOutLine{p, 4, int64(kind), []byte{0, 0, 0, 0}, 1, "end ", ""})
|
||||
}
|
||||
lines = append(lines, spacingLine)
|
||||
header = true
|
||||
continue
|
||||
|
||||
case IRKindIdent:
|
||||
var a []byte
|
||||
// discard ancillary
|
||||
if a, _, err = nextUint32(r, pos); err != nil {
|
||||
break
|
||||
}
|
||||
var sum Checksum
|
||||
if _, sum, err = nextIdent(r, pos); err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
lines = append(lines, asmOutLine{p, 4, int64(kind), a, 1, "id ", Encode(sum)})
|
||||
continue
|
||||
case IRKindUint32:
|
||||
var i uint32
|
||||
var bi []byte
|
||||
if bi, i, err = nextUint32(r, pos); err != nil {
|
||||
break
|
||||
}
|
||||
lines = append(lines, asmOutLine{p, 4, int64(kind), bi, 1, "int ", strconv.FormatUint(uint64(i), 10)})
|
||||
case IRKindString:
|
||||
var l uint32
|
||||
var bl []byte
|
||||
if bl, l, err = nextUint32(r, pos); err != nil {
|
||||
break
|
||||
}
|
||||
s := make([]byte, l+(wordSize-(l)%wordSize)%wordSize)
|
||||
var n int
|
||||
if n, err = r.Read(s); err != nil {
|
||||
break
|
||||
}
|
||||
*pos = *pos + n
|
||||
|
||||
lines = append(lines, asmOutLine{p, 4, int64(kind), bl, 1, "str ", strconv.Quote(string(s[:l]))})
|
||||
continue
|
||||
default:
|
||||
var bi []byte
|
||||
if bi, _, err = nextUint32(r, pos); err != nil {
|
||||
break
|
||||
}
|
||||
lines = append(lines, asmOutLine{p, 4, int64(kind), bi, 1, "????", ""})
|
||||
}
|
||||
}
|
||||
if err != io.EOF {
|
||||
return
|
||||
}
|
||||
err = nil
|
||||
for _, line := range lines {
|
||||
if raw {
|
||||
if line.pos != -1 {
|
||||
sb.WriteString(fmt.Sprintf("%s\t%s\n", line.kind, line.value))
|
||||
}
|
||||
} else {
|
||||
if line.pos == -1 {
|
||||
sb.WriteString("\n")
|
||||
} else if line.word == 4 {
|
||||
sb.WriteString(fmt.Sprintf("%06x: %04x %04x%s %s %s\n", line.pos, binary.LittleEndian.AppendUint32(nil, uint32(line.kindData)), line.valueData, headerSpacing(showHeader), line.kind, line.value))
|
||||
} else {
|
||||
kind := binary.LittleEndian.AppendUint64(nil, uint64(line.kindData))
|
||||
value := line.valueData
|
||||
if len(value) == 8 {
|
||||
sb.WriteString(fmt.Sprintf("%06x: %04x %04x %04x %04x %s %s\n", line.pos, kind[:4], kind[4:], value[:4], value[4:], line.kind, line.value))
|
||||
} else {
|
||||
sb.WriteString(fmt.Sprintf("%06x: %04x %04x %s %s\n", line.pos, kind[:4], kind[4:], line.kind, line.value))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return sb.String(), err
|
||||
}
|
||||
func nextUint32(r io.Reader, pos *int) ([]byte, uint32, error) {
|
||||
i := make([]byte, 4)
|
||||
_, err := r.Read(i)
|
||||
if err != nil {
|
||||
return i, 0, err
|
||||
}
|
||||
p := *pos + 4
|
||||
*pos = p
|
||||
return i, binary.LittleEndian.Uint32(i), nil
|
||||
}
|
||||
func nextUint64(r io.Reader, pos *int) ([]byte, uint64, error) {
|
||||
i := make([]byte, 8)
|
||||
_, err := r.Read(i)
|
||||
if err != nil {
|
||||
return i, 0, err
|
||||
}
|
||||
p := *pos + 8
|
||||
*pos = p
|
||||
return i, binary.LittleEndian.Uint64(i), nil
|
||||
}
|
||||
func nextIdent(r io.Reader, pos *int) ([]byte, Checksum, error) {
|
||||
i := make([]byte, 48)
|
||||
if _, err := r.Read(i); err != nil {
|
||||
return i, Checksum{}, err
|
||||
}
|
||||
p := *pos + 48
|
||||
*pos = p
|
||||
return i, Checksum(i), nil
|
||||
}
|
||||
func intToKind(i uint64) string {
|
||||
switch Kind(i) {
|
||||
case KindHTTPGet:
|
||||
return "http"
|
||||
case KindTar:
|
||||
return "tar "
|
||||
case KindExec:
|
||||
return "exec"
|
||||
case KindExecNet:
|
||||
return "exen"
|
||||
case KindFile:
|
||||
return "file"
|
||||
default:
|
||||
return fmt.Sprintf("$%d ", i-KindCustomOffset)
|
||||
}
|
||||
}
|
||||
func headerSpacing(showHeader bool) string {
|
||||
if showHeader {
|
||||
return " "
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
@@ -432,6 +432,12 @@ func (e InvalidKindError) Error() string {
|
||||
// register is not safe for concurrent use. register must not be called after
|
||||
// the first instance of [Cache] has been opened.
|
||||
func register(k Kind, f IRReadFunc) {
|
||||
openMu.Lock()
|
||||
defer openMu.Unlock()
|
||||
|
||||
if opened {
|
||||
panic("attempting to register after open")
|
||||
}
|
||||
if _, ok := irArtifact[k]; ok {
|
||||
panic("attempting to register " + strconv.Itoa(int(k)) + " twice")
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@@ -70,6 +71,64 @@ func MustDecode(s string) (checksum Checksum) {
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
// extension is a string uniquely identifying a set of custom [Artifact]
|
||||
// implementations registered by calling [Register].
|
||||
extension string
|
||||
|
||||
// openMu synchronises access to global state for initialisation.
|
||||
openMu sync.Mutex
|
||||
// opened is false if [Open] was never called.
|
||||
opened bool
|
||||
)
|
||||
|
||||
// Extension returns a string uniquely identifying the currently registered set
|
||||
// of custom [Artifact], or the zero value if none was registered.
|
||||
func Extension() string { return extension }
|
||||
|
||||
// ValidExtension returns whether s is valid for use in a call to SetExtension.
|
||||
func ValidExtension(s string) bool {
|
||||
if l := len(s); l == 0 || l > 128 {
|
||||
return false
|
||||
}
|
||||
for _, v := range s {
|
||||
if v < 'a' || v > 'z' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ErrInvalidExtension is returned for a variant identification string for which
|
||||
// [ValidExtension] returns false.
|
||||
var ErrInvalidExtension = errors.New("invalid extension variant identification string")
|
||||
|
||||
// SetExtension sets the extension variant identification string. SetExtension
|
||||
// must be called before [Open] if custom [Artifact] implementations had been
|
||||
// recorded by calling [Register].
|
||||
//
|
||||
// The variant identification string must be between 1 and 128 bytes long and
|
||||
// consists of only bytes between 'a' and 'z'.
|
||||
//
|
||||
// SetExtension is not safe for concurrent use. SetExtension is called at most
|
||||
// once and must not be called after the first instance of Cache has been opened.
|
||||
func SetExtension(s string) {
|
||||
openMu.Lock()
|
||||
defer openMu.Unlock()
|
||||
|
||||
if opened {
|
||||
panic("attempting to set extension after open")
|
||||
}
|
||||
if extension != "" {
|
||||
panic("attempting to set extension twice")
|
||||
}
|
||||
if !ValidExtension(s) {
|
||||
panic(ErrInvalidExtension)
|
||||
}
|
||||
extension = s
|
||||
statusHeader = makeStatusHeader(s)
|
||||
}
|
||||
|
||||
// common holds elements and receives methods shared between different contexts.
|
||||
type common struct {
|
||||
// Context specific to this [Artifact]. The toplevel context in [Cache] must
|
||||
@@ -102,19 +161,27 @@ type TContext struct {
|
||||
common
|
||||
}
|
||||
|
||||
// statusHeader is the header written to all status files in dirStatus.
|
||||
var statusHeader = func() string {
|
||||
// makeStatusHeader creates the header written to every status file. This should
|
||||
// not be called directly, its result is stored in statusHeader and will not
|
||||
// change after the first [Cache] is opened.
|
||||
func makeStatusHeader(extension string) string {
|
||||
s := programName
|
||||
if v := info.Version(); v != info.FallbackVersion {
|
||||
s += " " + v
|
||||
}
|
||||
if extension != "" {
|
||||
s += " with " + extension + " extensions"
|
||||
}
|
||||
s += " (" + runtime.GOARCH + ")"
|
||||
if name, err := os.Hostname(); err == nil {
|
||||
s += " on " + name
|
||||
}
|
||||
s += "\n\n"
|
||||
return s
|
||||
}()
|
||||
}
|
||||
|
||||
// statusHeader is the header written to all status files in dirStatus.
|
||||
var statusHeader = makeStatusHeader("")
|
||||
|
||||
// prepareStatus initialises the status file once.
|
||||
func (t *TContext) prepareStatus() error {
|
||||
@@ -427,6 +494,9 @@ const (
|
||||
// KindFile is the kind of [Artifact] returned by [NewFile].
|
||||
KindFile
|
||||
|
||||
// _kindEnd is the total number of kinds and does not denote a kind.
|
||||
_kindEnd
|
||||
|
||||
// KindCustomOffset is the first [Kind] value reserved for implementations
|
||||
// not from this package.
|
||||
KindCustomOffset = 1 << 31
|
||||
@@ -441,6 +511,9 @@ const (
|
||||
// fileLock is the file name appended to Cache.base for guaranteeing
|
||||
// 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 = "variant"
|
||||
|
||||
// dirIdentifier is the directory name appended to Cache.base for storing
|
||||
// artifacts named after their [ID].
|
||||
@@ -540,6 +613,10 @@ const (
|
||||
// impurity due to [KindExecNet] being [KnownChecksum]. This flag exists
|
||||
// to support kernels without Landlock LSM enabled.
|
||||
CHostAbstract
|
||||
|
||||
// CPromoteVariant allows [pkg.Open] to promote an unextended on-disk cache
|
||||
// to the current extension variant. This is a one-way operation.
|
||||
CPromoteVariant
|
||||
)
|
||||
|
||||
// toplevel holds [context.WithCancel] over caller-supplied context, where all
|
||||
@@ -1930,6 +2007,20 @@ func (c *Cache) Close() {
|
||||
c.unlock()
|
||||
}
|
||||
|
||||
// UnsupportedVariantError describes an on-disk cache with an extension variant
|
||||
// identification string that differs from the value returned by [Extension].
|
||||
type UnsupportedVariantError string
|
||||
|
||||
func (e UnsupportedVariantError) Error() string {
|
||||
return "unsupported variant " + strconv.Quote(string(e))
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrWouldPromote is returned by [Open] if the [CPromoteVariant] bit is not
|
||||
// set and the on-disk cache requires variant promotion.
|
||||
ErrWouldPromote = errors.New("operation would promote unextended cache")
|
||||
)
|
||||
|
||||
// Open returns the address of a newly opened instance of [Cache].
|
||||
//
|
||||
// Concurrent cures of a [FloodArtifact] dependency graph is limited to the
|
||||
@@ -1961,6 +2052,14 @@ func open(
|
||||
base *check.Absolute,
|
||||
lock bool,
|
||||
) (*Cache, error) {
|
||||
openMu.Lock()
|
||||
defer openMu.Unlock()
|
||||
opened = true
|
||||
|
||||
if extension == "" && len(irArtifact) != int(_kindEnd) {
|
||||
panic("attempting to open cache with incomplete variant setup")
|
||||
}
|
||||
|
||||
if cures < 1 {
|
||||
cures = runtime.NumCPU()
|
||||
}
|
||||
@@ -1974,8 +2073,10 @@ func open(
|
||||
dirStatus,
|
||||
dirWork,
|
||||
} {
|
||||
if err := os.MkdirAll(base.Append(name).String(), 0700); err != nil &&
|
||||
!errors.Is(err, os.ErrExist) {
|
||||
if err := os.MkdirAll(
|
||||
base.Append(name).String(),
|
||||
0700,
|
||||
); err != nil && !errors.Is(err, os.ErrExist) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -2013,6 +2114,45 @@ func open(
|
||||
c.unlock = func() {}
|
||||
}
|
||||
|
||||
variantPath := base.Append(fileVariant).String()
|
||||
if p, err := os.ReadFile(variantPath); err != nil {
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
c.unlock()
|
||||
return nil, err
|
||||
}
|
||||
// nonexistence implies newly created cache, or a cache predating
|
||||
// variant identification strings, in which case it is silently promoted
|
||||
if err = os.WriteFile(
|
||||
variantPath,
|
||||
[]byte(extension),
|
||||
0400,
|
||||
); err != nil {
|
||||
c.unlock()
|
||||
return nil, err
|
||||
}
|
||||
} else if s := string(p); s == "" {
|
||||
if extension != "" {
|
||||
if flags&CPromoteVariant == 0 {
|
||||
c.unlock()
|
||||
return nil, ErrWouldPromote
|
||||
}
|
||||
if err = os.WriteFile(
|
||||
variantPath,
|
||||
[]byte(extension),
|
||||
0400,
|
||||
); err != nil {
|
||||
c.unlock()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
} else if !ValidExtension(s) {
|
||||
c.unlock()
|
||||
return nil, ErrInvalidExtension
|
||||
} else if s != extension {
|
||||
c.unlock()
|
||||
return nil, UnsupportedVariantError(s)
|
||||
}
|
||||
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,25 @@ func unsafeOpen(
|
||||
lock bool,
|
||||
) (*pkg.Cache, error)
|
||||
|
||||
var (
|
||||
// extension is a string uniquely identifying a set of custom [Artifact]
|
||||
// implementations registered by calling [Register].
|
||||
//
|
||||
//go:linkname extension hakurei.app/internal/pkg.extension
|
||||
extension string
|
||||
|
||||
// opened is false if [Open] was never called.
|
||||
//
|
||||
//go:linkname opened hakurei.app/internal/pkg.opened
|
||||
opened bool
|
||||
|
||||
// irArtifact refers to artifact IR interpretation functions and must not be
|
||||
// written to directly.
|
||||
//
|
||||
//go:linkname irArtifact hakurei.app/internal/pkg.irArtifact
|
||||
irArtifact map[pkg.Kind]pkg.IRReadFunc
|
||||
)
|
||||
|
||||
// newRContext returns the address of a new [pkg.RContext] unsafely created for
|
||||
// the specified [testing.TB].
|
||||
func newRContext(tb testing.TB, c *pkg.Cache) *pkg.RContext {
|
||||
@@ -342,9 +361,20 @@ func checkWithCache(t *testing.T, testCases []cacheTestCase) {
|
||||
restoreTemp = true
|
||||
}
|
||||
|
||||
// destroy lock file to avoid changing cache checksums
|
||||
if err := os.Remove(base.Append("lock").String()); err != nil {
|
||||
t.Fatal(err)
|
||||
// destroy lock and variant file to avoid changing cache checksums
|
||||
for _, s := range []string{
|
||||
"lock",
|
||||
"variant",
|
||||
} {
|
||||
pathname := base.Append(s)
|
||||
if p, err := os.ReadFile(pathname.String()); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if len(p) != 0 {
|
||||
t.Fatalf("file %q: %q", s, string(p))
|
||||
}
|
||||
if err := os.Remove(pathname.String()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// destroy non-deterministic status files
|
||||
@@ -1101,6 +1131,10 @@ func TestErrors(t *testing.T) {
|
||||
Want: pkg.IRKindIdent,
|
||||
Ancillary: 0xcafe,
|
||||
}, "got invalid kind 48879 IR value (0xcafe) instead of ident"},
|
||||
|
||||
{"UnsupportedVariantError", pkg.UnsupportedVariantError(
|
||||
"rosa",
|
||||
), `unsupported variant "rosa"`},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
@@ -1309,6 +1343,8 @@ func (a earlyFailureF) Cure(*pkg.FContext) error {
|
||||
}
|
||||
|
||||
func TestDependencyCureErrorEarly(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
checkWithCache(t, []cacheTestCase{
|
||||
{"early", 0, nil, func(t *testing.T, _ *check.Absolute, c *pkg.Cache) {
|
||||
_, _, err := c.Cure(earlyFailureF(8))
|
||||
@@ -1319,7 +1355,7 @@ func TestDependencyCureErrorEarly(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
func TestOpen(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("nonexistent", func(t *testing.T) {
|
||||
@@ -1367,3 +1403,219 @@ func TestNew(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestExtensionRegister(t *testing.T) {
|
||||
extensionOld := extension
|
||||
openedOld := opened
|
||||
t.Cleanup(func() { extension = extensionOld; opened = openedOld })
|
||||
extension = ""
|
||||
opened = false
|
||||
|
||||
t.Run("set", func(t *testing.T) {
|
||||
t.Cleanup(func() { extension = "" })
|
||||
|
||||
const want = "rosa"
|
||||
pkg.SetExtension(want)
|
||||
if got := pkg.Extension(); got != want {
|
||||
t.Fatalf("Extension: %q, want %q", got, want)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("twice", func(t *testing.T) {
|
||||
t.Cleanup(func() { extension = "" })
|
||||
|
||||
defer func() {
|
||||
const wantPanic = "attempting to set extension twice"
|
||||
if r := recover(); r != wantPanic {
|
||||
t.Errorf("panic: %#v, want %q", r, wantPanic)
|
||||
}
|
||||
}()
|
||||
pkg.SetExtension("rosa")
|
||||
pkg.SetExtension("rosa")
|
||||
})
|
||||
|
||||
t.Run("invalid", func(t *testing.T) {
|
||||
defer func() {
|
||||
var wantPanic = pkg.ErrInvalidExtension
|
||||
if r := recover(); r != wantPanic {
|
||||
t.Errorf("panic: %#v, want %#v", r, wantPanic)
|
||||
}
|
||||
}()
|
||||
pkg.SetExtension(" ")
|
||||
})
|
||||
|
||||
t.Run("opened", func(t *testing.T) {
|
||||
t.Cleanup(func() { opened = false })
|
||||
|
||||
if _, err := pkg.Open(
|
||||
t.Context(),
|
||||
message.New(log.Default()),
|
||||
0, 0, 0,
|
||||
check.MustAbs(container.Nonexistent),
|
||||
); !errors.Is(err, os.ErrNotExist) {
|
||||
t.Fatalf("Open: error = %v", err)
|
||||
}
|
||||
|
||||
t.Run("variant", func(t *testing.T) {
|
||||
defer func() {
|
||||
const wantPanic = "attempting to set extension after open"
|
||||
if r := recover(); r != wantPanic {
|
||||
t.Errorf("panic: %#v, want %q", r, wantPanic)
|
||||
}
|
||||
}()
|
||||
pkg.SetExtension("rosa")
|
||||
})
|
||||
|
||||
t.Run("register", func(t *testing.T) {
|
||||
defer func() {
|
||||
const wantPanic = "attempting to register after open"
|
||||
if r := recover(); r != wantPanic {
|
||||
t.Errorf("panic: %#v, want %q", r, wantPanic)
|
||||
}
|
||||
}()
|
||||
pkg.Register(pkg.KindCustomOffset, nil)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("incomplete", func(t *testing.T) {
|
||||
t.Cleanup(func() { delete(irArtifact, pkg.KindCustomOffset) })
|
||||
|
||||
defer func() {
|
||||
const wantPanic = "attempting to open cache with incomplete variant setup"
|
||||
if r := recover(); r != wantPanic {
|
||||
t.Errorf("panic: %#v, want %q", r, wantPanic)
|
||||
}
|
||||
}()
|
||||
pkg.Register(pkg.KindCustomOffset, nil)
|
||||
|
||||
t.Cleanup(func() { opened = false })
|
||||
_, _ = pkg.Open(nil, nil, 0, 0, 0, nil)
|
||||
panic("unreachable")
|
||||
})
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
t.Cleanup(func() { extension = "" })
|
||||
const want = "rosa"
|
||||
pkg.SetExtension(want)
|
||||
|
||||
base := check.MustAbs(t.TempDir())
|
||||
t.Cleanup(func() { opened = false })
|
||||
if c, err := pkg.Open(
|
||||
t.Context(), nil,
|
||||
0, 0, 0,
|
||||
base,
|
||||
); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
c.Close()
|
||||
}
|
||||
|
||||
if got, err := os.ReadFile(base.Append("variant").String()); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if string(got) != want {
|
||||
t.Fatalf("variant: %q", string(got))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("access", func(t *testing.T) {
|
||||
base := check.MustAbs(t.TempDir())
|
||||
t.Cleanup(func() { opened = false })
|
||||
|
||||
if err := os.WriteFile(base.Append("variant").String(), nil, 0); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
wantErr := &os.PathError{
|
||||
Op: "open",
|
||||
Path: base.Append("variant").String(),
|
||||
Err: syscall.EACCES,
|
||||
}
|
||||
if _, err := pkg.Open(
|
||||
t.Context(), nil,
|
||||
0, 0, 0,
|
||||
base,
|
||||
); !reflect.DeepEqual(err, wantErr) {
|
||||
t.Fatalf("Open: error = %v, want %v", err, wantErr)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("promote", func(t *testing.T) {
|
||||
t.Cleanup(func() { extension = "" })
|
||||
const want = "rosa"
|
||||
pkg.SetExtension(want)
|
||||
|
||||
base := check.MustAbs(t.TempDir())
|
||||
t.Cleanup(func() { opened = false })
|
||||
|
||||
variantPath := base.Append("variant")
|
||||
if err := os.WriteFile(variantPath.String(), nil, 0600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := pkg.Open(
|
||||
t.Context(), nil,
|
||||
0, 0, 0,
|
||||
base,
|
||||
); !reflect.DeepEqual(err, pkg.ErrWouldPromote) {
|
||||
t.Fatalf("Open: error = %v", err)
|
||||
}
|
||||
|
||||
if p, err := os.ReadFile(variantPath.String()); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if len(p) != 0 {
|
||||
t.Fatalf("variant: %q", string(p))
|
||||
}
|
||||
|
||||
if c, err := pkg.Open(
|
||||
t.Context(), nil,
|
||||
pkg.CPromoteVariant, 0, 0,
|
||||
base,
|
||||
); err != nil {
|
||||
t.Fatalf("Open: error = %v", err)
|
||||
} else {
|
||||
c.Close()
|
||||
}
|
||||
|
||||
if p, err := os.ReadFile(variantPath.String()); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if string(p) != want {
|
||||
t.Fatalf("variant: %q, want %q", string(p), want)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("open invalid", func(t *testing.T) {
|
||||
base := check.MustAbs(t.TempDir())
|
||||
t.Cleanup(func() { opened = false })
|
||||
|
||||
variantPath := base.Append("variant")
|
||||
if err := os.WriteFile(variantPath.String(), make([]byte, 129), 0400); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := pkg.Open(
|
||||
t.Context(), nil,
|
||||
0, 0, 0,
|
||||
base,
|
||||
); !reflect.DeepEqual(err, pkg.ErrInvalidExtension) {
|
||||
t.Fatalf("Open: error = %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("unsupported", func(t *testing.T) {
|
||||
base := check.MustAbs(t.TempDir())
|
||||
t.Cleanup(func() { opened = false })
|
||||
|
||||
variantPath := base.Append("variant")
|
||||
if err := os.WriteFile(variantPath.String(), []byte("rosa"), 0400); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := pkg.Open(
|
||||
t.Context(), nil,
|
||||
0, 0, 0,
|
||||
base,
|
||||
); !reflect.DeepEqual(err, pkg.UnsupportedVariantError("rosa")) {
|
||||
t.Fatalf("Open: error = %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -16,9 +16,7 @@ import (
|
||||
type PArtifact int
|
||||
|
||||
const (
|
||||
CompilerRT PArtifact = iota
|
||||
LLVMRuntimes
|
||||
Clang
|
||||
LLVM PArtifact = iota
|
||||
|
||||
// EarlyInit is the Rosa OS init program.
|
||||
EarlyInit
|
||||
@@ -74,10 +72,12 @@ const (
|
||||
HakureiDist
|
||||
IPTables
|
||||
Kmod
|
||||
LIT
|
||||
LibX11
|
||||
LibXau
|
||||
LibXext
|
||||
Libbsd
|
||||
Libcap
|
||||
Libclc
|
||||
Libdrm
|
||||
Libev
|
||||
Libexpat
|
||||
@@ -95,8 +95,10 @@ const (
|
||||
Libtool
|
||||
Libucontext
|
||||
Libunistring
|
||||
Libxshmfence
|
||||
Libxml2
|
||||
Libxslt
|
||||
Libxtrans
|
||||
M4
|
||||
MPC
|
||||
MPFR
|
||||
@@ -129,21 +131,29 @@ const (
|
||||
PkgConfig
|
||||
Procps
|
||||
Python
|
||||
PythonFlitCore
|
||||
PythonHatchling
|
||||
PythonIniConfig
|
||||
PythonMako
|
||||
PythonMarkupSafe
|
||||
PythonPackaging
|
||||
PythonPathspec
|
||||
PythonPluggy
|
||||
PythonPyTest
|
||||
PythonPyYAML
|
||||
PythonPygments
|
||||
PythonSetuptools
|
||||
PythonSetuptoolsSCM
|
||||
PythonTroveClassifiers
|
||||
PythonVCSVersioning
|
||||
PythonWheel
|
||||
QEMU
|
||||
Rdfind
|
||||
Readline
|
||||
Rsync
|
||||
Sed
|
||||
Setuptools
|
||||
SPIRVHeaders
|
||||
SPIRVLLVMTranslator
|
||||
SPIRVTools
|
||||
SquashfsTools
|
||||
Strace
|
||||
@@ -160,7 +170,7 @@ const (
|
||||
XCBProto
|
||||
XDGDBusProxy
|
||||
XZ
|
||||
Xproto
|
||||
XorgProto
|
||||
Zlib
|
||||
Zstd
|
||||
|
||||
@@ -173,6 +183,8 @@ const (
|
||||
|
||||
// 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.
|
||||
@@ -317,15 +329,29 @@ var (
|
||||
}
|
||||
// artifactsOnce is for lazy initialisation of artifacts.
|
||||
artifactsOnce [_toolchainEnd][len(artifactsM)]sync.Once
|
||||
|
||||
// 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
|
||||
)
|
||||
|
||||
// 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() {
|
||||
func DropCaches(flags int) {
|
||||
presetOpts = flags
|
||||
zero(&artifacts)
|
||||
zero(&artifactsOnce)
|
||||
}
|
||||
|
||||
@@ -20,13 +20,16 @@ func TestLoad(t *testing.T) {
|
||||
}
|
||||
|
||||
func BenchmarkAll(b *testing.B) {
|
||||
flags := rosa.Flags()
|
||||
b.Cleanup(func() { rosa.DropCaches(flags) })
|
||||
|
||||
for b.Loop() {
|
||||
for i := range rosa.PresetEnd {
|
||||
rosa.Std.Load(rosa.PArtifact(i))
|
||||
}
|
||||
|
||||
b.StopTimer()
|
||||
rosa.DropCaches()
|
||||
rosa.DropCaches(0)
|
||||
b.StartTimer()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
|
||||
func (t Toolchain) newCMake() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "4.3.1"
|
||||
checksum = "RHpzZiM1kJ5bwLjo9CpXSeHJJg3hTtV9QxBYpQoYwKFtRh5YhGWpShrqZCSOzQN6"
|
||||
version = "4.3.2"
|
||||
checksum = "6QylwRVKletndTSkZTV2YBRwgd_9rUVgav_QW23HpjUgV21AVYZOUOal8tdBDmO7"
|
||||
)
|
||||
return t.NewPackage("cmake", version, newFromGitHubRelease(
|
||||
"Kitware/CMake",
|
||||
@@ -122,11 +122,18 @@ type CMakeHelper struct {
|
||||
// Path elements joined with source.
|
||||
Append []string
|
||||
|
||||
// Value of CMAKE_BUILD_TYPE. The zero value is equivalent to "Release".
|
||||
BuildType string
|
||||
// CMake CACHE entries.
|
||||
Cache []KV
|
||||
// Runs after install.
|
||||
Script string
|
||||
|
||||
// Replaces the default test command.
|
||||
Test string
|
||||
// Whether to skip running tests.
|
||||
SkipTest bool
|
||||
|
||||
// Whether to generate Makefile instead.
|
||||
Make bool
|
||||
}
|
||||
@@ -159,20 +166,30 @@ func (*CMakeHelper) wantsDir() string { return "/cure/" }
|
||||
// script generates the cure script.
|
||||
func (attr *CMakeHelper) script(name string) string {
|
||||
if attr == nil {
|
||||
attr = &CMakeHelper{
|
||||
Cache: []KV{
|
||||
{"CMAKE_BUILD_TYPE", "Release"},
|
||||
},
|
||||
}
|
||||
}
|
||||
if len(attr.Cache) == 0 {
|
||||
panic("CACHE must be non-empty")
|
||||
attr = new(CMakeHelper)
|
||||
}
|
||||
|
||||
generate := "Ninja"
|
||||
test := "ninja " + jobsFlagE + " test"
|
||||
if attr.Make {
|
||||
generate = "'Unix Makefiles'"
|
||||
test = "make " + jobsFlagE + " test"
|
||||
}
|
||||
if attr.Test != "" {
|
||||
test = attr.Test
|
||||
}
|
||||
|
||||
script := attr.Script
|
||||
if !attr.SkipTest && presetOpts&OptSkipCheck == 0 {
|
||||
script += "\n" + test
|
||||
}
|
||||
|
||||
cache := make([]KV, 1, 1+len(attr.Cache))
|
||||
cache[0] = KV{"CMAKE_BUILD_TYPE", "Release"}
|
||||
if attr.BuildType != "" {
|
||||
cache[0][1] = attr.BuildType
|
||||
}
|
||||
cache = append(cache, attr.Cache...)
|
||||
|
||||
return `
|
||||
cmake -G ` + generate + ` \
|
||||
@@ -181,7 +198,7 @@ cmake -G ` + generate + ` \
|
||||
-DCMAKE_ASM_COMPILER_TARGET="${ROSA_TRIPLE}" \
|
||||
-DCMAKE_INSTALL_LIBDIR=lib \
|
||||
` + strings.Join(slices.Collect(func(yield func(string) bool) {
|
||||
for _, v := range attr.Cache {
|
||||
for _, v := range cache {
|
||||
if !yield("-D" + v[0] + "=" + v[1]) {
|
||||
return
|
||||
}
|
||||
@@ -191,5 +208,5 @@ cmake -G ` + generate + ` \
|
||||
'/usr/src/` + name + `/` + filepath.Join(attr.Append...) + `'
|
||||
cmake --build . --parallel=` + jobsE + `
|
||||
cmake --install . --prefix=/work/system
|
||||
` + attr.Script
|
||||
` + script
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
|
||||
func (t Toolchain) newGit() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.53.0"
|
||||
checksum = "rlqSTeNgSeVKJA7nvzGqddFH8q3eFEPB4qRZft-4zth8wTHnbTbm7J90kp_obHGm"
|
||||
version = "2.54.0"
|
||||
checksum = "7vGKtFOJGqY8DO4e8UMRax7dLgImXKQz5MMalec6MlgYrsarffSJjgOughwRFpSH"
|
||||
)
|
||||
return t.NewPackage("git", version, newTar(
|
||||
"https://www.kernel.org/pub/software/scm/git/"+
|
||||
@@ -20,6 +20,9 @@ func (t Toolchain) newGit() (pkg.Artifact, string) {
|
||||
), &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
|
||||
@@ -38,6 +41,7 @@ function disable_test {
|
||||
fi
|
||||
}
|
||||
|
||||
disable_test t1800-hook
|
||||
disable_test t5319-multi-pack-index
|
||||
disable_test t1305-config-include
|
||||
disable_test t3900-i18n-commit
|
||||
@@ -63,6 +67,9 @@ disable_test t2200-add-update
|
||||
NO_INSTALL_HARDLINKS=1 \
|
||||
install`,
|
||||
},
|
||||
// test suite hangs on mksh
|
||||
Bash,
|
||||
|
||||
Diffutils,
|
||||
Autoconf,
|
||||
Gettext,
|
||||
|
||||
@@ -17,9 +17,8 @@ func (t Toolchain) newSPIRVHeaders() (pkg.Artifact, string) {
|
||||
"vulkan-sdk-"+version,
|
||||
checksum,
|
||||
), nil, &CMakeHelper{
|
||||
Cache: []KV{
|
||||
{"CMAKE_BUILD_TYPE", "Release"},
|
||||
},
|
||||
// upstream has no tests
|
||||
SkipTest: true,
|
||||
}), version
|
||||
}
|
||||
func init() {
|
||||
@@ -64,7 +63,6 @@ func (t Toolchain) newSPIRVTools() (pkg.Artifact, string) {
|
||||
checksum,
|
||||
), nil, &CMakeHelper{
|
||||
Cache: []KV{
|
||||
{"CMAKE_BUILD_TYPE", "Release"},
|
||||
{"SPIRV-Headers_SOURCE_DIR", "/system"},
|
||||
},
|
||||
},
|
||||
@@ -86,6 +84,8 @@ func init() {
|
||||
},
|
||||
|
||||
ID: 14894,
|
||||
|
||||
latest: (*Versions).getStable,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,11 +104,9 @@ func (t Toolchain) newGlslang() (pkg.Artifact, string) {
|
||||
Chmod: true,
|
||||
}, &CMakeHelper{
|
||||
Cache: []KV{
|
||||
{"CMAKE_BUILD_TYPE", "Release"},
|
||||
{"BUILD_SHARED_LIBS", "ON"},
|
||||
{"ALLOW_EXTERNAL_SPIRV_TOOLS", "ON"},
|
||||
},
|
||||
Script: "ctest",
|
||||
},
|
||||
Python,
|
||||
Bash,
|
||||
@@ -128,3 +126,65 @@ func init() {
|
||||
ID: 205796,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newSPIRVLLVMTranslator() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "22.1.2"
|
||||
checksum = "JZAaV5ewYcm-35YA_U2BM2IcsQouZtX1BLZR0zh2vSlfEXMsT5OCtY4Gh5RJkcGy"
|
||||
)
|
||||
return t.NewPackage("spirv-llvm-translator", version, newFromGitHub(
|
||||
"KhronosGroup/SPIRV-LLVM-Translator",
|
||||
"v"+version, checksum,
|
||||
), &PackageAttr{
|
||||
Patches: []KV{
|
||||
{"remove-early-prefix", `diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index c000a77e..86f79b03 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -172,5 +172,5 @@ install(
|
||||
FILES
|
||||
${CMAKE_BINARY_DIR}/LLVMSPIRVLib.pc
|
||||
DESTINATION
|
||||
- ${CMAKE_INSTALL_PREFIX}/lib${LLVM_LIBDIR_SUFFIX}/pkgconfig
|
||||
+ lib${LLVM_LIBDIR_SUFFIX}/pkgconfig
|
||||
)
|
||||
`},
|
||||
},
|
||||
|
||||
// litArgs emits shell syntax
|
||||
ScriptEarly: `
|
||||
export LIT_OPTS=` + litArgs(true,
|
||||
// error: line 13: OpTypeCooperativeMatrixKHR Scope is limited to Workgroup and Subgroup
|
||||
"cooperative_matrix_constant_null.spvasm") + `
|
||||
`,
|
||||
}, &CMakeHelper{
|
||||
Cache: []KV{
|
||||
{"CMAKE_SKIP_BUILD_RPATH", "ON"},
|
||||
{"BUILD_SHARED_LIBS", "ON"},
|
||||
{"LLVM_SPIRV_ENABLE_LIBSPIRV_DIS", "ON"},
|
||||
{"LLVM_EXTERNAL_SPIRV_HEADERS_SOURCE_DIR", "/system"},
|
||||
{"LLVM_EXTERNAL_LIT", "/system/bin/lit"},
|
||||
{"LLVM_INCLUDE_TESTS", "ON"},
|
||||
},
|
||||
},
|
||||
Bash,
|
||||
LIT,
|
||||
|
||||
SPIRVTools,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[SPIRVLLVMTranslator] = Metadata{
|
||||
f: Toolchain.newSPIRVLLVMTranslator,
|
||||
|
||||
Name: "spirv-llvm-translator",
|
||||
Description: "bi-directional translation between SPIR-V and LLVM IR",
|
||||
Website: "https://github.com/KhronosGroup/SPIRV-LLVM-Translator",
|
||||
|
||||
Dependencies: P{
|
||||
SPIRVTools,
|
||||
},
|
||||
|
||||
ID: 227273,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,47 @@ package rosa
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"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) newM4() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.4.21"
|
||||
@@ -47,7 +84,15 @@ func (t Toolchain) newBison() (pkg.Artifact, string) {
|
||||
"https://ftpmirror.gnu.org/gnu/bison/bison-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, (*MakeHelper)(nil),
|
||||
), nil, &MakeHelper{
|
||||
Check: []string{
|
||||
"TESTSUITEFLAGS=" + jobsFlagE + "' " + skipGNUTests(
|
||||
// clang miscompiles (SIGILL)
|
||||
764,
|
||||
) + "'",
|
||||
"check",
|
||||
},
|
||||
},
|
||||
M4,
|
||||
Diffutils,
|
||||
Sed,
|
||||
@@ -67,8 +112,8 @@ func init() {
|
||||
|
||||
func (t Toolchain) newSed() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "4.9"
|
||||
checksum = "pe7HWH4PHNYrazOTlUoE1fXmhn2GOPFN_xE62i0llOr3kYGrH1g2_orDz0UtZ9Nt"
|
||||
version = "4.10"
|
||||
checksum = "TXTRFQJCyflb-bpBRI2S5Y1DpplwvT7-KfXtpqN4AdZgZ5OtI6yStn1-bkhDKx51"
|
||||
)
|
||||
return t.NewPackage("sed", version, newTar(
|
||||
"https://ftpmirror.gnu.org/gnu/sed/sed-"+version+".tar.gz",
|
||||
@@ -76,6 +121,8 @@ func (t Toolchain) newSed() (pkg.Artifact, string) {
|
||||
pkg.TarGzip,
|
||||
), nil, (*MakeHelper)(nil),
|
||||
Diffutils,
|
||||
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
@@ -184,6 +231,9 @@ func (t Toolchain) newLibtool() (pkg.Artifact, string) {
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, &MakeHelper{
|
||||
// _Z2a2c: symbol not found
|
||||
SkipCheck: t.isStage0(),
|
||||
|
||||
Check: []string{
|
||||
"TESTSUITEFLAGS=" + jobsFlagE,
|
||||
"check",
|
||||
@@ -374,8 +424,8 @@ func init() {
|
||||
|
||||
func (t Toolchain) newCoreutils() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "9.10"
|
||||
checksum = "o-B9wssRnZySzJUI1ZJAgw-bZtj1RC67R9po2AcM2OjjS8FQIl16IRHpC6IwO30i"
|
||||
version = "9.11"
|
||||
checksum = "t8UMed5wpFEoC56aa42_yidfOAaRGzOfj7MRtQkkqgGbpXiskNA8bd-EmVSQkZie"
|
||||
)
|
||||
return t.NewPackage("coreutils", version, newTar(
|
||||
"https://ftpmirror.gnu.org/gnu/coreutils/coreutils-"+version+".tar.gz",
|
||||
@@ -387,106 +437,13 @@ func (t Toolchain) newCoreutils() (pkg.Artifact, string) {
|
||||
test_disable() { chmod +w "$2" && echo "$1" > "$2"; }
|
||||
|
||||
test_disable '#!/bin/sh' gnulib-tests/test-c32ispunct.sh
|
||||
test_disable '#!/bin/sh' tests/split/line-bytes.sh
|
||||
test_disable '#!/bin/sh' tests/ls/hyperlink.sh
|
||||
test_disable '#!/bin/sh' tests/misc/user.sh
|
||||
test_disable 'int main(){return 0;}' gnulib-tests/test-chown.c
|
||||
test_disable 'int main(){return 0;}' gnulib-tests/test-fchownat.c
|
||||
test_disable 'int main(){return 0;}' gnulib-tests/test-lchown.c
|
||||
`,
|
||||
|
||||
Patches: []KV{
|
||||
{"tests-fix-job-control", `From 21d287324aa43aa3a31f39619ade0deac7fd6013 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <P@draigBrady.com>
|
||||
Date: Tue, 24 Feb 2026 15:44:41 +0000
|
||||
Subject: [PATCH] tests: fix job control triggering test termination
|
||||
|
||||
This avoids the test harness being terminated like:
|
||||
make[1]: *** [Makefile:24419: check-recursive] Hangup
|
||||
make[3]: *** [Makefile:24668: check-TESTS] Hangup
|
||||
make: *** [Makefile:24922: check] Hangup
|
||||
make[2]: *** [Makefile:24920: check-am] Hangup
|
||||
make[4]: *** [Makefile:24685: tests/misc/usage_vs_refs.log] Error 129
|
||||
...
|
||||
|
||||
This happened sometimes when the tests were being run non interactively.
|
||||
For example when run like:
|
||||
|
||||
setsid make TESTS="tests/timeout/timeout.sh \
|
||||
tests/tail/overlay-headers.sh" SUBDIRS=. -j2 check
|
||||
|
||||
Note the race window can be made bigger by adding a sleep
|
||||
after tail is stopped in overlay-headers.sh
|
||||
|
||||
The race can trigger the kernel to induce its job control
|
||||
mechanism to prevent stuck processes.
|
||||
I.e. where it sends SIGHUP + SIGCONT to a process group
|
||||
when it determines that group may become orphaned,
|
||||
and there are stopped processes in that group.
|
||||
|
||||
* tests/tail/overlay-headers.sh: Use setsid(1) to keep the stopped
|
||||
tail process in a separate process group, thus avoiding any kernel
|
||||
job control protection mechanism.
|
||||
* tests/timeout/timeout.sh: Use setsid(1) to avoid the kernel
|
||||
checking the main process group when sleep(1) is reparented.
|
||||
Fixes https://bugs.gnu.org/80477
|
||||
---
|
||||
tests/tail/overlay-headers.sh | 8 +++++++-
|
||||
tests/timeout/timeout.sh | 11 ++++++++---
|
||||
2 files changed, 15 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/tests/tail/overlay-headers.sh b/tests/tail/overlay-headers.sh
|
||||
index be9b6a7df..1e6da0a3f 100755
|
||||
--- a/tests/tail/overlay-headers.sh
|
||||
+++ b/tests/tail/overlay-headers.sh
|
||||
@@ -20,6 +20,8 @@
|
||||
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
|
||||
print_ver_ tail sleep
|
||||
|
||||
+setsid true || skip_ 'setsid required to control groups'
|
||||
+
|
||||
# Function to count number of lines from tail
|
||||
# while ignoring transient errors due to resource limits
|
||||
countlines_ ()
|
||||
@@ -54,7 +56,11 @@ echo start > file2 || framework_failure_
|
||||
env sleep 60 & sleep=$!
|
||||
|
||||
# Note don't use timeout(1) here as it currently
|
||||
-# does not propagate SIGCONT
|
||||
+# does not propagate SIGCONT.
|
||||
+# Note use setsid here to ensure we're in a separate process group
|
||||
+# as we're going to STOP this tail process, and this can trigger
|
||||
+# the kernel to send SIGHUP to a group if other tests have
|
||||
+# processes that are reparented. (See tests/timeout/timeout.sh).
|
||||
tail $fastpoll --pid=$sleep -f file1 file2 > out & pid=$!
|
||||
|
||||
# Ensure tail is running
|
||||
diff --git a/tests/timeout/timeout.sh b/tests/timeout/timeout.sh
|
||||
index 9a395416b..fbb043312 100755
|
||||
--- a/tests/timeout/timeout.sh
|
||||
+++ b/tests/timeout/timeout.sh
|
||||
@@ -56,9 +56,14 @@ returns_ 124 timeout --foreground -s0 -k1 .1 sleep 10 && fail=1
|
||||
) || fail=1
|
||||
|
||||
# Don't be confused when starting off with a child (Bug#9098).
|
||||
-out=$(sleep .1 & exec timeout .5 sh -c 'sleep 2; echo foo')
|
||||
-status=$?
|
||||
-test "$out" = "" && test $status = 124 || fail=1
|
||||
+# Use setsid to avoid sleep being in the test's process group, as
|
||||
+# upon reparenting it can trigger an orphaned process group SIGHUP
|
||||
+# (if there were stopped processes in other tests).
|
||||
+if setsid true; then
|
||||
+ out=$(setsid sleep .1 & exec timeout .5 sh -c 'sleep 2; echo foo')
|
||||
+ status=$?
|
||||
+ test "$out" = "" && test $status = 124 || fail=1
|
||||
+fi
|
||||
|
||||
# Verify --verbose output
|
||||
cat > exp <<\EOF
|
||||
--
|
||||
2.53.0
|
||||
`},
|
||||
},
|
||||
|
||||
Flag: TEarly,
|
||||
}, &MakeHelper{
|
||||
Configure: []KV{
|
||||
@@ -757,15 +714,20 @@ func init() {
|
||||
|
||||
func (t Toolchain) newParallel() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "20260322"
|
||||
checksum = "gHoPmFkOO62ev4xW59HqyMlodhjp8LvTsBOwsVKHUUdfrt7KwB8koXmSVqQ4VOrB"
|
||||
version = "20260422"
|
||||
checksum = "eTsepxgqhXpMEhPd55qh-W5y4vjKn0x9TD2mzbJCNZYtFf4lT4Wzoqr74HGJYBEH"
|
||||
)
|
||||
return t.NewPackage("parallel", version, newTar(
|
||||
"https://ftpmirror.gnu.org/gnu/parallel/parallel-"+version+".tar.bz2",
|
||||
checksum,
|
||||
pkg.TarBzip2,
|
||||
), nil, (*MakeHelper)(nil),
|
||||
), &PackageAttr{
|
||||
ScriptEarly: `
|
||||
ln -s ../system/bin/bash /bin/
|
||||
`,
|
||||
}, (*MakeHelper)(nil),
|
||||
Perl,
|
||||
Bash,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
@@ -1143,10 +1105,11 @@ func init() {
|
||||
func (t Toolchain) newMPC() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.4.1"
|
||||
checksum = "wdXAhplnS89FjVp20m2nC2CmLFQeyQqLpQAfViTy4vPxFdv2WYOTtfBKeIk5_Rec"
|
||||
checksum = "ZffaZyWkvIw0iPvRe5EJ7O-VvHtSkbbb3K_7SgPtK810NvGan7nbF0T5-6tozjQN"
|
||||
)
|
||||
return t.NewPackage("mpc", version, t.newTagRemote(
|
||||
"https://gitlab.inria.fr/mpc/mpc.git",
|
||||
return t.NewPackage("mpc", version, newFromGitLab(
|
||||
"gitlab.inria.fr",
|
||||
"mpc/mpc",
|
||||
version, checksum,
|
||||
), &PackageAttr{
|
||||
// does not find mpc-impl.h otherwise
|
||||
|
||||
35
internal/rosa/gnu_test.go
Normal file
35
internal/rosa/gnu_test.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package rosa
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSkipGNUTests(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := []struct {
|
||||
tests []int
|
||||
want string
|
||||
}{
|
||||
{[]int{764}, "1-763 765-"},
|
||||
{[]int{764, 0xcafe, 37, 9}, "1-8 10-36 38-763 765-51965 51967-"},
|
||||
{[]int{1, 2, 0xbed}, "3-3052 3054-"},
|
||||
{[]int{3, 4}, "1-2 5-"},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(strings.Join(slices.Collect(func(yield func(string) bool) {
|
||||
for _, n := range tc.tests {
|
||||
yield(strconv.Itoa(n))
|
||||
}
|
||||
}), ","), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if got := skipGNUTests(tc.tests...); got != tc.want {
|
||||
t.Errorf("skipGNUTests: %q, want %q", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
// newGoBootstrap returns the Go bootstrap toolchain.
|
||||
func (t Toolchain) newGoBootstrap() pkg.Artifact {
|
||||
const checksum = "8o9JL_ToiQKadCTb04nvBDkp8O1xiWOolAxVEqaTGodieNe4lOFEjlOxN3bwwe23"
|
||||
return t.New("go1.4-bootstrap", 0, []pkg.Artifact{
|
||||
t.Load(Bash),
|
||||
}, nil, []string{
|
||||
return t.New("go1.4-bootstrap", 0, t.AppendPresets(nil,
|
||||
Bash,
|
||||
), nil, []string{
|
||||
"CGO_ENABLED=0",
|
||||
}, `
|
||||
mkdir -p /var/tmp/ /work/system/
|
||||
@@ -35,9 +35,9 @@ func (t Toolchain) newGo(
|
||||
script string,
|
||||
extra ...pkg.Artifact,
|
||||
) pkg.Artifact {
|
||||
return t.New("go"+version, 0, slices.Concat([]pkg.Artifact{
|
||||
t.Load(Bash),
|
||||
}, extra), nil, slices.Concat([]string{
|
||||
return t.New("go"+version, 0, t.AppendPresets(extra,
|
||||
Bash,
|
||||
), nil, slices.Concat([]string{
|
||||
"CC=cc",
|
||||
"GOCACHE=/tmp/gocache",
|
||||
"GOROOT_BOOTSTRAP=/system/go",
|
||||
@@ -127,8 +127,8 @@ sed -i \
|
||||
)
|
||||
|
||||
go125 := t.newGo(
|
||||
"1.25.7",
|
||||
"fyylHdBVRUobnBjYj3NKBaYPUw3kGmo2mEELiZonOYurPfbarNU1x77B99Fjut7Q",
|
||||
"1.25.9",
|
||||
"gShJb9uOMk5AxqPSwvn53ZO56S6PyP6nfojzrHUiJ3krAvrgjJpYa6-DPA-jxbpN",
|
||||
[]string{"CGO_ENABLED=0"}, `
|
||||
sed -i \
|
||||
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
@@ -151,9 +151,14 @@ rm \
|
||||
sed -i \
|
||||
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
cmd/link/internal/`+runtime.GOARCH+`/obj.go
|
||||
sed -i \
|
||||
's/cpu.X86.HasAVX512VBMI/& \&\& cpu.X86.HasPOPCNT/' \
|
||||
internal/runtime/gc/scan/scan_amd64.go
|
||||
|
||||
rm \
|
||||
os/root_unix_test.go
|
||||
os/root_unix_test.go \
|
||||
cmd/cgo/internal/testsanitizers/tsan_test.go \
|
||||
cmd/cgo/internal/testsanitizers/cshared_test.go
|
||||
`, go125,
|
||||
), version
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@ package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
const kernelVersion = "6.12.81"
|
||||
const kernelVersion = "6.12.84"
|
||||
|
||||
var kernelSource = newTar(
|
||||
"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/"+
|
||||
"snapshot/linux-"+kernelVersion+".tar.gz",
|
||||
"fBkNwf82DQXh74in6gaF2Jot7Vg-Vlcp9BUtCEipL9mvcM1EXLVFdV7FcrO20Eve",
|
||||
"GJLUEu68r3DpLYoTcMl4wA_ThMBs_Zwc0gZsp82ii_3AOfcVxpI639IKfq2jAAY2",
|
||||
pkg.TarGzip,
|
||||
)
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# Linux/x86 6.12.80 Kernel Configuration
|
||||
# Linux/x86 6.12.84 Kernel Configuration
|
||||
#
|
||||
CONFIG_CC_VERSION_TEXT="clang version 22.1.2"
|
||||
CONFIG_CC_VERSION_TEXT="clang version 22.1.4"
|
||||
CONFIG_GCC_VERSION=0
|
||||
CONFIG_CC_IS_CLANG=y
|
||||
CONFIG_CLANG_VERSION=220102
|
||||
CONFIG_CLANG_VERSION=220104
|
||||
CONFIG_AS_IS_LLVM=y
|
||||
CONFIG_AS_VERSION=220102
|
||||
CONFIG_AS_VERSION=220104
|
||||
CONFIG_LD_VERSION=0
|
||||
CONFIG_LD_IS_LLD=y
|
||||
CONFIG_LLD_VERSION=220102
|
||||
CONFIG_LLD_VERSION=220104
|
||||
CONFIG_RUSTC_VERSION=0
|
||||
CONFIG_RUSTC_LLVM_VERSION=0
|
||||
CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y
|
||||
@@ -3175,14 +3175,8 @@ CONFIG_PATA_ACPI=y
|
||||
CONFIG_ATA_GENERIC=y
|
||||
CONFIG_PATA_LEGACY=m
|
||||
CONFIG_MD=y
|
||||
CONFIG_BLK_DEV_MD=m
|
||||
# CONFIG_BLK_DEV_MD is not set
|
||||
CONFIG_MD_BITMAP_FILE=y
|
||||
CONFIG_MD_LINEAR=m
|
||||
CONFIG_MD_RAID0=m
|
||||
CONFIG_MD_RAID1=m
|
||||
CONFIG_MD_RAID10=m
|
||||
CONFIG_MD_RAID456=m
|
||||
CONFIG_MD_CLUSTER=m
|
||||
CONFIG_BCACHE=m
|
||||
# CONFIG_BCACHE_DEBUG is not set
|
||||
# CONFIG_BCACHE_ASYNC_REGISTRATION is not set
|
||||
@@ -3205,7 +3199,7 @@ CONFIG_DM_ERA=m
|
||||
CONFIG_DM_CLONE=m
|
||||
CONFIG_DM_MIRROR=m
|
||||
CONFIG_DM_LOG_USERSPACE=m
|
||||
CONFIG_DM_RAID=m
|
||||
# CONFIG_DM_RAID is not set
|
||||
CONFIG_DM_ZERO=m
|
||||
CONFIG_DM_MULTIPATH=m
|
||||
CONFIG_DM_MULTIPATH_QL=m
|
||||
@@ -11636,10 +11630,7 @@ CONFIG_RANDSTRUCT_NONE=y
|
||||
|
||||
CONFIG_XOR_BLOCKS=m
|
||||
CONFIG_ASYNC_CORE=m
|
||||
CONFIG_ASYNC_MEMCPY=m
|
||||
CONFIG_ASYNC_XOR=m
|
||||
CONFIG_ASYNC_PQ=m
|
||||
CONFIG_ASYNC_RAID6_RECOV=m
|
||||
CONFIG_CRYPTO=y
|
||||
|
||||
#
|
||||
@@ -11925,8 +11916,6 @@ CONFIG_BINARY_PRINTF=y
|
||||
#
|
||||
# Library routines
|
||||
#
|
||||
CONFIG_RAID6_PQ=m
|
||||
CONFIG_RAID6_PQ_BENCHMARK=y
|
||||
CONFIG_LINEAR_RANGES=y
|
||||
CONFIG_PACKING=y
|
||||
CONFIG_BITREVERSE=y
|
||||
@@ -12471,7 +12460,6 @@ CONFIG_RUNTIME_TESTING_MENU=y
|
||||
# CONFIG_INTERVAL_TREE_TEST is not set
|
||||
# CONFIG_PERCPU_TEST is not set
|
||||
# CONFIG_ATOMIC64_SELFTEST is not set
|
||||
# CONFIG_ASYNC_RAID6_TEST is not set
|
||||
# CONFIG_TEST_HEXDUMP is not set
|
||||
# CONFIG_TEST_KSTRTOX is not set
|
||||
# CONFIG_TEST_PRINTF is not set
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# Linux/arm64 6.12.80 Kernel Configuration
|
||||
# Linux/arm64 6.12.83 Kernel Configuration
|
||||
#
|
||||
CONFIG_CC_VERSION_TEXT="clang version 21.1.8"
|
||||
CONFIG_CC_VERSION_TEXT="clang version 22.1.4"
|
||||
CONFIG_GCC_VERSION=0
|
||||
CONFIG_CC_IS_CLANG=y
|
||||
CONFIG_CLANG_VERSION=210108
|
||||
CONFIG_CLANG_VERSION=220104
|
||||
CONFIG_AS_IS_LLVM=y
|
||||
CONFIG_AS_VERSION=210108
|
||||
CONFIG_AS_VERSION=220104
|
||||
CONFIG_LD_VERSION=0
|
||||
CONFIG_LD_IS_LLD=y
|
||||
CONFIG_LLD_VERSION=210108
|
||||
CONFIG_LLD_VERSION=220104
|
||||
CONFIG_RUSTC_VERSION=0
|
||||
CONFIG_RUSTC_LLVM_VERSION=0
|
||||
CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y
|
||||
@@ -3253,14 +3253,8 @@ CONFIG_PATA_ACPI=y
|
||||
CONFIG_ATA_GENERIC=y
|
||||
CONFIG_PATA_LEGACY=m
|
||||
CONFIG_MD=y
|
||||
CONFIG_BLK_DEV_MD=m
|
||||
# CONFIG_BLK_DEV_MD is not set
|
||||
CONFIG_MD_BITMAP_FILE=y
|
||||
CONFIG_MD_LINEAR=m
|
||||
CONFIG_MD_RAID0=m
|
||||
CONFIG_MD_RAID1=m
|
||||
CONFIG_MD_RAID10=m
|
||||
CONFIG_MD_RAID456=m
|
||||
CONFIG_MD_CLUSTER=m
|
||||
CONFIG_BCACHE=m
|
||||
# CONFIG_BCACHE_DEBUG is not set
|
||||
# CONFIG_BCACHE_ASYNC_REGISTRATION is not set
|
||||
@@ -3283,7 +3277,7 @@ CONFIG_DM_ERA=m
|
||||
CONFIG_DM_CLONE=m
|
||||
CONFIG_DM_MIRROR=m
|
||||
CONFIG_DM_LOG_USERSPACE=m
|
||||
CONFIG_DM_RAID=m
|
||||
# CONFIG_DM_RAID is not set
|
||||
CONFIG_DM_ZERO=m
|
||||
CONFIG_DM_MULTIPATH=m
|
||||
CONFIG_DM_MULTIPATH_QL=m
|
||||
@@ -10300,7 +10294,6 @@ CONFIG_ALTERA_MSGDMA=m
|
||||
# CONFIG_AMBA_PL08X is not set
|
||||
CONFIG_APPLE_ADMAC=m
|
||||
CONFIG_AXI_DMAC=m
|
||||
CONFIG_BCM_SBA_RAID=m
|
||||
CONFIG_DMA_BCM2835=m
|
||||
CONFIG_DMA_SUN6I=m
|
||||
CONFIG_DW_AXI_DMAC=m
|
||||
@@ -13292,12 +13285,7 @@ CONFIG_RANDSTRUCT_NONE=y
|
||||
|
||||
CONFIG_XOR_BLOCKS=m
|
||||
CONFIG_ASYNC_CORE=m
|
||||
CONFIG_ASYNC_MEMCPY=m
|
||||
CONFIG_ASYNC_XOR=m
|
||||
CONFIG_ASYNC_PQ=m
|
||||
CONFIG_ASYNC_RAID6_RECOV=m
|
||||
CONFIG_ASYNC_TX_DISABLE_PQ_VAL_DMA=y
|
||||
CONFIG_ASYNC_TX_DISABLE_XOR_VAL_DMA=y
|
||||
CONFIG_CRYPTO=y
|
||||
|
||||
#
|
||||
@@ -13640,8 +13628,6 @@ CONFIG_BINARY_PRINTF=y
|
||||
#
|
||||
# Library routines
|
||||
#
|
||||
CONFIG_RAID6_PQ=m
|
||||
CONFIG_RAID6_PQ_BENCHMARK=y
|
||||
CONFIG_LINEAR_RANGES=y
|
||||
CONFIG_PACKING=y
|
||||
CONFIG_BITREVERSE=y
|
||||
@@ -14172,7 +14158,6 @@ CONFIG_RUNTIME_TESTING_MENU=y
|
||||
# CONFIG_INTERVAL_TREE_TEST is not set
|
||||
# CONFIG_PERCPU_TEST is not set
|
||||
# CONFIG_ATOMIC64_SELFTEST is not set
|
||||
# CONFIG_ASYNC_RAID6_TEST is not set
|
||||
# CONFIG_TEST_HEXDUMP is not set
|
||||
# CONFIG_TEST_KSTRTOX is not set
|
||||
# CONFIG_TEST_PRINTF is not set
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# Linux/riscv 6.12.77 Kernel Configuration
|
||||
# Linux/riscv 6.12.80 Kernel Configuration
|
||||
#
|
||||
CONFIG_CC_VERSION_TEXT="clang version 22.1.2"
|
||||
CONFIG_GCC_VERSION=0
|
||||
@@ -37,11 +37,6 @@ CONFIG_BUILD_SALT=""
|
||||
CONFIG_HAVE_KERNEL_GZIP=y
|
||||
CONFIG_HAVE_KERNEL_ZSTD=y
|
||||
# CONFIG_KERNEL_GZIP is not set
|
||||
# CONFIG_KERNEL_BZIP2 is not set
|
||||
# CONFIG_KERNEL_LZMA is not set
|
||||
# CONFIG_KERNEL_XZ is not set
|
||||
# CONFIG_KERNEL_LZO is not set
|
||||
# CONFIG_KERNEL_LZ4 is not set
|
||||
CONFIG_KERNEL_ZSTD=y
|
||||
CONFIG_DEFAULT_INIT=""
|
||||
CONFIG_DEFAULT_HOSTNAME="rosa-early"
|
||||
@@ -2848,14 +2843,8 @@ CONFIG_PATA_ACPI=y
|
||||
CONFIG_ATA_GENERIC=y
|
||||
CONFIG_PATA_LEGACY=m
|
||||
CONFIG_MD=y
|
||||
CONFIG_BLK_DEV_MD=m
|
||||
# CONFIG_BLK_DEV_MD is not set
|
||||
CONFIG_MD_BITMAP_FILE=y
|
||||
CONFIG_MD_LINEAR=m
|
||||
CONFIG_MD_RAID0=m
|
||||
CONFIG_MD_RAID1=m
|
||||
CONFIG_MD_RAID10=m
|
||||
CONFIG_MD_RAID456=m
|
||||
CONFIG_MD_CLUSTER=m
|
||||
CONFIG_BCACHE=m
|
||||
# CONFIG_BCACHE_DEBUG is not set
|
||||
# CONFIG_BCACHE_ASYNC_REGISTRATION is not set
|
||||
@@ -2878,7 +2867,7 @@ CONFIG_DM_ERA=m
|
||||
CONFIG_DM_CLONE=m
|
||||
CONFIG_DM_MIRROR=m
|
||||
CONFIG_DM_LOG_USERSPACE=m
|
||||
CONFIG_DM_RAID=m
|
||||
# CONFIG_DM_RAID is not set
|
||||
CONFIG_DM_ZERO=m
|
||||
CONFIG_DM_MULTIPATH=m
|
||||
CONFIG_DM_MULTIPATH_QL=m
|
||||
@@ -10655,10 +10644,7 @@ CONFIG_RANDSTRUCT_NONE=y
|
||||
|
||||
CONFIG_XOR_BLOCKS=m
|
||||
CONFIG_ASYNC_CORE=m
|
||||
CONFIG_ASYNC_MEMCPY=m
|
||||
CONFIG_ASYNC_XOR=m
|
||||
CONFIG_ASYNC_PQ=m
|
||||
CONFIG_ASYNC_RAID6_RECOV=m
|
||||
CONFIG_CRYPTO=y
|
||||
|
||||
#
|
||||
@@ -10918,8 +10904,6 @@ CONFIG_BINARY_PRINTF=y
|
||||
#
|
||||
# Library routines
|
||||
#
|
||||
CONFIG_RAID6_PQ=m
|
||||
CONFIG_RAID6_PQ_BENCHMARK=y
|
||||
CONFIG_LINEAR_RANGES=y
|
||||
CONFIG_PACKING=y
|
||||
CONFIG_BITREVERSE=y
|
||||
@@ -11408,7 +11392,6 @@ CONFIG_RUNTIME_TESTING_MENU=y
|
||||
# CONFIG_INTERVAL_TREE_TEST is not set
|
||||
# CONFIG_PERCPU_TEST is not set
|
||||
# CONFIG_ATOMIC64_SELFTEST is not set
|
||||
# CONFIG_ASYNC_RAID6_TEST is not set
|
||||
# CONFIG_TEST_HEXDUMP is not set
|
||||
# CONFIG_TEST_KSTRTOX is not set
|
||||
# CONFIG_TEST_PRINTF is not set
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
|
||||
func (t Toolchain) newLibexpat() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.7.5"
|
||||
checksum = "vTRUjjg-qbHSXUBYKXgzVHkUO7UNyuhrkSYrE7ikApQm0g-OvQ8tspw4w55M-1Tp"
|
||||
version = "2.8.0"
|
||||
checksum = "pnwZ_JSif-OfoWIwk2JYXWHagOWMA3Sh-Ea0p-4Rz9U9mDEeAebhyvnfD7OYOMCk"
|
||||
)
|
||||
return t.NewPackage("libexpat", version, newFromGitHubRelease(
|
||||
"libexpat/libexpat",
|
||||
|
||||
@@ -5,10 +5,11 @@ import "hakurei.app/internal/pkg"
|
||||
func (t Toolchain) newLibxml2() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.15.3"
|
||||
checksum = "oWkNe53c3d4Lt4OzrXPHBcOLHJ3TWqpa0x7B7bh_DyZ-uIMiplpdZjQRgRWVal2h"
|
||||
checksum = "oJy74htGlEpf70KPvpW18fYJo0RQQkCXZRwqUz6NoXborS3HCq3Nm4gsyaSeNmUH"
|
||||
)
|
||||
return t.NewPackage("libxml2", version, t.newTagRemote(
|
||||
"https://gitlab.gnome.org/GNOME/libxml2.git",
|
||||
return t.NewPackage("libxml2", version, newFromGitLab(
|
||||
"gitlab.gnome.org",
|
||||
"GNOME/libxml2",
|
||||
"v"+version, checksum,
|
||||
), &PackageAttr{
|
||||
// can't create shell.out: Read-only file system
|
||||
|
||||
@@ -5,10 +5,11 @@ import "hakurei.app/internal/pkg"
|
||||
func (t Toolchain) newLibxslt() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.1.45"
|
||||
checksum = "MZc_dyUWpHChkWDKa5iycrECxBsRd4ZMbYfL4VojTbung593mlH2tHGmxYB6NFYT"
|
||||
checksum = "67ks7v8od2oWaEGf23Sst_Xbn_8brQyolQjqxPoO-lK35k_WJhi2Px5JJgbk-nfn"
|
||||
)
|
||||
return t.NewPackage("libxslt", version, t.newTagRemote(
|
||||
"https://gitlab.gnome.org/GNOME/libxslt.git",
|
||||
return t.NewPackage("libxslt", version, newFromGitLab(
|
||||
"gitlab.gnome.org",
|
||||
"GNOME/libxslt",
|
||||
"v"+version, checksum,
|
||||
), nil, &MakeHelper{
|
||||
Generate: "NOCONFIGURE=1 ./autogen.sh",
|
||||
|
||||
@@ -1,195 +1,165 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
import (
|
||||
"regexp"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
func init() {
|
||||
artifactsM[llvmSource] = Metadata{
|
||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||
return t.NewPatchedSource("llvm", llvmVersion, newFromGitHub(
|
||||
"llvm/llvm-project",
|
||||
"llvmorg-"+llvmVersion,
|
||||
llvmChecksum,
|
||||
), true, llvmPatches...), llvmVersion
|
||||
},
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
Name: "llvm-project",
|
||||
Description: "LLVM monorepo with Rosa OS patches",
|
||||
|
||||
ID: 1830,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newCompilerRT() (pkg.Artifact, string) {
|
||||
muslHeaders, _ := t.newMusl(true)
|
||||
return t.NewPackage("compiler-rt", llvmVersion, t.Load(llvmSource), &PackageAttr{
|
||||
NonStage0: []pkg.Artifact{
|
||||
muslHeaders,
|
||||
},
|
||||
Env: stage0ExclConcat(t, []string{},
|
||||
"LDFLAGS="+earlyLDFLAGS(false),
|
||||
),
|
||||
Flag: TExclusive,
|
||||
}, &CMakeHelper{
|
||||
Append: []string{"compiler-rt"},
|
||||
|
||||
Cache: []KV{
|
||||
{"CMAKE_BUILD_TYPE", "Release"},
|
||||
|
||||
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
|
||||
// libc++ not yet available
|
||||
{"CMAKE_CXX_COMPILER_TARGET", ""},
|
||||
|
||||
{"COMPILER_RT_BUILD_BUILTINS", "ON"},
|
||||
{"COMPILER_RT_DEFAULT_TARGET_ONLY", "OFF"},
|
||||
{"COMPILER_RT_SANITIZERS_TO_BUILD", "asan"},
|
||||
{"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"},
|
||||
},
|
||||
Script: `
|
||||
mkdir -p "/work/system/lib/clang/` + llvmVersionMajor + `/lib/"
|
||||
ln -s \
|
||||
"../../../${ROSA_TRIPLE}" \
|
||||
"/work/system/lib/clang/` + llvmVersionMajor + `/lib/"
|
||||
|
||||
ln -s \
|
||||
"clang_rt.crtbegin-` + linuxArch() + `.o" \
|
||||
"/work/system/lib/${ROSA_TRIPLE}/crtbeginS.o"
|
||||
ln -s \
|
||||
"clang_rt.crtend-` + linuxArch() + `.o" \
|
||||
"/work/system/lib/${ROSA_TRIPLE}/crtendS.o"
|
||||
`,
|
||||
},
|
||||
Python,
|
||||
|
||||
KernelHeaders,
|
||||
), llvmVersion
|
||||
}
|
||||
func init() {
|
||||
artifactsM[CompilerRT] = Metadata{
|
||||
f: Toolchain.newCompilerRT,
|
||||
|
||||
Name: "compiler-rt",
|
||||
Description: "LLVM runtime: compiler-rt",
|
||||
Website: "https://llvm.org/",
|
||||
|
||||
Dependencies: P{
|
||||
Musl,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newLLVMRuntimes() (pkg.Artifact, string) {
|
||||
return t.NewPackage("llvm-runtimes", llvmVersion, t.Load(llvmSource), &PackageAttr{
|
||||
NonStage0: t.AppendPresets(nil, CompilerRT),
|
||||
Env: stage0ExclConcat(t, []string{},
|
||||
"LDFLAGS="+earlyLDFLAGS(false),
|
||||
),
|
||||
Flag: TExclusive,
|
||||
}, &CMakeHelper{
|
||||
Append: []string{"runtimes"},
|
||||
|
||||
Cache: []KV{
|
||||
{"CMAKE_BUILD_TYPE", "Release"},
|
||||
|
||||
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_ENABLE_RUNTIMES", "'libunwind;libcxx;libcxxabi'"},
|
||||
|
||||
{"LIBUNWIND_USE_COMPILER_RT", "ON"},
|
||||
{"LIBCXX_HAS_MUSL_LIBC", "ON"},
|
||||
{"LIBCXX_USE_COMPILER_RT", "ON"},
|
||||
{"LIBCXXABI_USE_COMPILER_RT", "ON"},
|
||||
{"LIBCXXABI_USE_LLVM_UNWINDER", "ON"},
|
||||
|
||||
// libc++ not yet available
|
||||
{"CMAKE_CXX_COMPILER_WORKS", "ON"},
|
||||
|
||||
{"LIBCXX_HAS_ATOMIC_LIB", "OFF"},
|
||||
{"LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL", "OFF"},
|
||||
|
||||
{"LLVM_ENABLE_ZLIB", "OFF"},
|
||||
{"LLVM_ENABLE_ZSTD", "OFF"},
|
||||
{"LLVM_ENABLE_LIBXML2", "OFF"},
|
||||
},
|
||||
},
|
||||
Python,
|
||||
|
||||
KernelHeaders,
|
||||
), llvmVersion
|
||||
}
|
||||
func init() {
|
||||
artifactsM[LLVMRuntimes] = Metadata{
|
||||
f: Toolchain.newLLVMRuntimes,
|
||||
|
||||
Name: "llvm-runtimes",
|
||||
Description: "LLVM runtimes: libunwind, libcxx, libcxxabi",
|
||||
Website: "https://llvm.org/",
|
||||
|
||||
Dependencies: P{
|
||||
CompilerRT,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newClang() (pkg.Artifact, string) {
|
||||
target := "'AArch64;RISCV;X86'"
|
||||
if t.isStage0() {
|
||||
target = "Native"
|
||||
// litArgs returns [LIT] arguments for optional verbosity and check skipping.
|
||||
func litArgs(verbose bool, skipChecks ...string) string {
|
||||
args := []string{"-sv"}
|
||||
if verbose {
|
||||
args[0] = "--verbose"
|
||||
}
|
||||
|
||||
return t.NewPackage("clang", llvmVersion, t.Load(llvmSource), &PackageAttr{
|
||||
NonStage0: t.AppendPresets(nil, LLVMRuntimes),
|
||||
Env: stage0ExclConcat(t, []string{},
|
||||
"CFLAGS="+earlyCFLAGS,
|
||||
"CXXFLAGS="+earlyCXXFLAGS(),
|
||||
"LDFLAGS="+earlyLDFLAGS(false),
|
||||
),
|
||||
Flag: TExclusive,
|
||||
}, &CMakeHelper{
|
||||
if len(skipChecks) > 0 {
|
||||
skipChecks = slices.Clone(skipChecks)
|
||||
for i, s := range skipChecks {
|
||||
s = regexp.QuoteMeta(s)
|
||||
s = strings.ReplaceAll(s, "/", "\\/")
|
||||
skipChecks[i] = s
|
||||
}
|
||||
args = append(args,
|
||||
"--filter-out='\\''"+strings.Join(skipChecks, "|")+"'\\''")
|
||||
}
|
||||
|
||||
return "'" + strings.Join(args, " ") + "'"
|
||||
}
|
||||
|
||||
func (t Toolchain) newLLVM() (pkg.Artifact, string) {
|
||||
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"},
|
||||
{"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 runtime.GOARCH {
|
||||
case "arm64":
|
||||
skipChecks = append(skipChecks,
|
||||
// LLVM: intermittently crashes
|
||||
"ExecutionEngine/OrcLazy/multiple-compile-threads-basic.ll",
|
||||
// unwind: unexpectedly passes
|
||||
"unwind_leaffunction",
|
||||
)
|
||||
}
|
||||
|
||||
if presetOpts&OptLLVMNoLTO == 0 {
|
||||
cache = append(cache, []KV{
|
||||
// very expensive
|
||||
{"LLVM_ENABLE_LTO", "Thin"},
|
||||
}...)
|
||||
}
|
||||
|
||||
cache = append(cache, []KV{
|
||||
// symbols: clock_gettime, mallopt
|
||||
{"COMPILER_RT_INCLUDE_TESTS", "OFF"},
|
||||
|
||||
{"LLVM_LIT_ARGS", litArgs(true, skipChecks...)},
|
||||
}...)
|
||||
}
|
||||
|
||||
version := t.Version(llvmSource)
|
||||
return t.NewPackage("llvm", version, t.Load(llvmSource), nil, &CMakeHelper{
|
||||
Append: []string{"llvm"},
|
||||
|
||||
Cache: []KV{
|
||||
{"CMAKE_BUILD_TYPE", "Release"},
|
||||
|
||||
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_ENABLE_PROJECTS", "'clang;lld'"},
|
||||
|
||||
{"LLVM_ENABLE_LIBCXX", "ON"},
|
||||
{"LLVM_USE_LINKER", "lld"},
|
||||
|
||||
{"LLVM_INSTALL_BINUTILS_SYMLINKS", "ON"},
|
||||
{"LLVM_INSTALL_CCTOOLS_SYMLINKS", "ON"},
|
||||
|
||||
{"LLVM_LIT_ARGS", "'--verbose'"},
|
||||
|
||||
{"CLANG_DEFAULT_LINKER", "lld"},
|
||||
{"CLANG_DEFAULT_CXX_STDLIB", "libc++"},
|
||||
{"CLANG_DEFAULT_RTLIB", "compiler-rt"},
|
||||
{"CLANG_DEFAULT_UNWINDLIB", "libunwind"},
|
||||
|
||||
{"LLVM_TARGETS_TO_BUILD", target},
|
||||
{"CMAKE_CROSSCOMPILING", "OFF"},
|
||||
{"CXX_SUPPORTS_CUSTOM_LINKER", "ON"},
|
||||
|
||||
{"LLVM_ENABLE_ZLIB", "OFF"},
|
||||
{"LLVM_ENABLE_ZSTD", "OFF"},
|
||||
{"LLVM_ENABLE_LIBXML2", "OFF"},
|
||||
},
|
||||
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(),
|
||||
|
||||
Test: `
|
||||
chmod +w /bin && ln -s \
|
||||
../system/bin/chmod \
|
||||
../system/bin/mkdir \
|
||||
../system/bin/rm \
|
||||
../system/bin/tr \
|
||||
../system/bin/awk \
|
||||
/bin
|
||||
ninja ` + jobsFlagE + ` check-all
|
||||
`,
|
||||
},
|
||||
@@ -201,44 +171,44 @@ ninja ` + jobsFlagE + ` check-all
|
||||
Coreutils,
|
||||
Findutils,
|
||||
|
||||
Zlib,
|
||||
Zstd,
|
||||
muslHeaders,
|
||||
KernelHeaders,
|
||||
), llvmVersion
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Clang] = Metadata{
|
||||
f: Toolchain.newClang,
|
||||
const (
|
||||
version = "22.1.4"
|
||||
checksum = "Bk3t-tV5sD5T0bqefFMcLeFuAwXnhFipywZmqst5hAZs97QQWGKB_5XyAFjj5tDB"
|
||||
)
|
||||
|
||||
Name: "clang",
|
||||
Description: `an "LLVM native" C/C++/Objective-C compiler`,
|
||||
Website: "https://llvm.org/",
|
||||
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
|
||||
},
|
||||
|
||||
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{
|
||||
LLVMRuntimes,
|
||||
Zlib,
|
||||
Zstd,
|
||||
Musl,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newLibclc() (pkg.Artifact, string) {
|
||||
return t.NewPackage("libclc", llvmVersion, t.Load(llvmSource), nil, &CMakeHelper{
|
||||
Append: []string{"libclc"},
|
||||
|
||||
Cache: []KV{
|
||||
{"CMAKE_BUILD_TYPE", "Release"},
|
||||
|
||||
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
|
||||
{"LIBCLC_TARGETS_TO_BUILD", "all"},
|
||||
},
|
||||
Script: "ninja " + jobsFlagE + " test",
|
||||
}), llvmVersion
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libclc] = Metadata{
|
||||
f: Toolchain.newLibclc,
|
||||
|
||||
Name: "libclc",
|
||||
Description: "an open source, BSD/MIT dual licensed implementation of the library requirements of the OpenCL C programming language",
|
||||
Website: "https://libclc.llvm.org/",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package rosa
|
||||
|
||||
// latest version of LLVM, conditional to temporarily avoid broken new releases
|
||||
const (
|
||||
llvmVersionMajor = "22"
|
||||
llvmVersion = llvmVersionMajor + ".1.3"
|
||||
|
||||
llvmChecksum = "CUwnpzua_y28HZ9oI0NmcKL2wClsSjFpgY9do5-7cCZJHI5KNF64vfwGvY0TYyR3"
|
||||
)
|
||||
@@ -91,10 +91,10 @@ index 8ac8d4eb9181..e46b04a898ca 100644
|
||||
`},
|
||||
|
||||
{"path-system-libraries", `diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
|
||||
index 8ac8d4eb9181..f4d1347ab64d 100644
|
||||
index d525b417b4ea..fdc411f2239c 100644
|
||||
--- a/clang/lib/Driver/ToolChains/Linux.cpp
|
||||
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
|
||||
@@ -282,6 +282,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
||||
@@ -302,6 +302,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
||||
const bool IsHexagon = Arch == llvm::Triple::hexagon;
|
||||
const bool IsRISCV = Triple.isRISCV();
|
||||
const bool IsCSKY = Triple.isCSKY();
|
||||
@@ -102,7 +102,7 @@ index 8ac8d4eb9181..f4d1347ab64d 100644
|
||||
|
||||
if (IsCSKY && !SelectedMultilibs.empty())
|
||||
SysRoot = SysRoot + SelectedMultilibs.back().osSuffix();
|
||||
@@ -318,12 +319,23 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
||||
@@ -337,12 +338,23 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
||||
const std::string OSLibDir = std::string(getOSLibDir(Triple, Args));
|
||||
const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot);
|
||||
|
||||
@@ -110,7 +110,7 @@ index 8ac8d4eb9181..f4d1347ab64d 100644
|
||||
+ ExtraOpts.push_back("-rpath");
|
||||
+ ExtraOpts.push_back("/system/lib");
|
||||
+ ExtraOpts.push_back("-rpath");
|
||||
+ ExtraOpts.push_back(concat("/system/lib", MultiarchTriple));
|
||||
+ ExtraOpts.push_back(concat("/system/lib", Triple.str()));
|
||||
+ }
|
||||
+
|
||||
// mips32: Debian multilib, we use /libo32, while in other case, /lib is
|
||||
@@ -128,7 +128,7 @@ index 8ac8d4eb9181..f4d1347ab64d 100644
|
||||
}
|
||||
Generic_GCC::AddMultilibPaths(D, SysRoot, OSLibDir, MultiarchTriple, Paths);
|
||||
|
||||
@@ -341,18 +353,30 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
||||
@@ -360,18 +372,30 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
||||
Paths);
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ index 8ac8d4eb9181..f4d1347ab64d 100644
|
||||
}
|
||||
|
||||
ToolChain::RuntimeLibType Linux::GetDefaultRuntimeLibType() const {
|
||||
@@ -457,6 +481,9 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
|
||||
@@ -572,6 +596,9 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
|
||||
return Triple.isArch64Bit() ? "/system/bin/linker64" : "/system/bin/linker";
|
||||
}
|
||||
if (Triple.isMusl()) {
|
||||
@@ -175,10 +175,10 @@ index 8ac8d4eb9181..f4d1347ab64d 100644
|
||||
bool IsArm = false;
|
||||
|
||||
diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp
|
||||
index 64324a3f8b01..15ce70b68217 100644
|
||||
index f484d6f33ad8..dca55e72d67e 100644
|
||||
--- a/clang/tools/clang-installapi/Options.cpp
|
||||
+++ b/clang/tools/clang-installapi/Options.cpp
|
||||
@@ -515,7 +515,7 @@ bool Options::processFrontendOptions(InputArgList &Args) {
|
||||
@@ -514,7 +514,7 @@ bool Options::processFrontendOptions(InputArgList &Args) {
|
||||
FEOpts.FwkPaths = std::move(FrameworkPaths);
|
||||
|
||||
// Add default framework/library paths.
|
||||
@@ -19,7 +19,7 @@ cd "$(mktemp -d)"
|
||||
--build="${ROSA_TRIPLE}" \
|
||||
--disable-dependency-tracking
|
||||
./build.sh
|
||||
./make DESTDIR=/work install check
|
||||
./make DESTDIR=/work install
|
||||
`, pkg.Path(AbsUsrSrc.Append("make"), false, newTar(
|
||||
"https://ftpmirror.gnu.org/gnu/make/make-"+version+".tar.gz",
|
||||
checksum,
|
||||
@@ -194,7 +194,7 @@ make \
|
||||
}
|
||||
scriptMake += "\n"
|
||||
|
||||
if !attr.SkipCheck {
|
||||
if !attr.SkipCheck && presetOpts&OptSkipCheck == 0 {
|
||||
scriptMake += attr.ScriptCheckEarly + `make \
|
||||
` + jobsFlagE + ` \
|
||||
`
|
||||
|
||||
@@ -30,8 +30,8 @@ func init() {
|
||||
|
||||
func (t Toolchain) newLibdrm() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.4.131"
|
||||
checksum = "riHPSpvTnvCPbR-iT4jt7_X-z4rpwm6oNh9ZN2zP6RBFkFVxBRKmedG4eEXSADIh"
|
||||
version = "2.4.133"
|
||||
checksum = "bfj296NcR9DndO11hqDbSRFPqaweSLMqRk3dlCPZpM6FONX1WZ9J4JdbTDMUd1rU"
|
||||
)
|
||||
return t.NewPackage("libdrm", version, newFromGitLab(
|
||||
"gitlab.freedesktop.org",
|
||||
|
||||
@@ -9,27 +9,47 @@ import (
|
||||
|
||||
func (t Toolchain) newMeson() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.11.0"
|
||||
checksum = "b7oo3U_cklhzsTfsyYsjPGyeEufiS-Pm06JPLzodseS125Ach62ZBly7R6dSDiAc"
|
||||
version = "1.11.1"
|
||||
checksum = "uvILRxdopwc6Dy17UbIeClcQr0qHqyTaqyk1M9OqWKN9PwB9N6UVAiyN8kSSz3r2"
|
||||
)
|
||||
return t.New("meson-"+version, 0, []pkg.Artifact{
|
||||
t.Load(Zlib),
|
||||
t.Load(Python),
|
||||
t.Load(Setuptools),
|
||||
}, nil, nil, `
|
||||
cd /usr/src/meson
|
||||
chmod -R +w meson.egg-info
|
||||
python3 setup.py \
|
||||
install \
|
||||
--prefix=/system \
|
||||
--root=/work
|
||||
`, pkg.Path(AbsUsrSrc.Append("meson"), true, newFromGitHubRelease(
|
||||
return t.NewPackage("meson", version, newFromGitHub(
|
||||
"mesonbuild/meson",
|
||||
version,
|
||||
"meson-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
))), version
|
||||
), &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{
|
||||
@@ -97,7 +117,7 @@ func (attr *MesonHelper) script(name string) string {
|
||||
}
|
||||
|
||||
var scriptTest string
|
||||
if !attr.SkipTest {
|
||||
if !attr.SkipTest && presetOpts&OptSkipCheck == 0 {
|
||||
scriptTest = `
|
||||
meson test \
|
||||
--print-errorlogs`
|
||||
|
||||
@@ -7,9 +7,9 @@ func (t Toolchain) newMksh() (pkg.Artifact, string) {
|
||||
version = "59c"
|
||||
checksum = "0Zj-k4nXEu3IuJY4lvwD2OrC2t27GdZj8SPy4DoaeuBRH1padWb7oREpYgwY8JNq"
|
||||
)
|
||||
return t.New("mksh-"+version, 0, stage0Concat(t, []pkg.Artifact{},
|
||||
t.Load(Perl),
|
||||
t.Load(Coreutils),
|
||||
return t.New("mksh-"+version, 0, t.AppendPresets(nil,
|
||||
Perl,
|
||||
Coreutils,
|
||||
), nil, []string{
|
||||
"LDSTATIC=-static",
|
||||
"CPPFLAGS=-DMKSH_DEFAULT_PROFILEDIR=\\\"/system/etc\\\"",
|
||||
|
||||
@@ -2,10 +2,7 @@ package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newMusl(
|
||||
headers bool,
|
||||
extra ...pkg.Artifact,
|
||||
) (pkg.Artifact, string) {
|
||||
func (t Toolchain) newMusl(headers bool) (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.2.6"
|
||||
checksum = "WtWb_OV_XxLDAB5NerOL9loLlHVadV00MmGk65PPBU1evaolagoMHfvpZp_vxEzS"
|
||||
@@ -36,25 +33,26 @@ rmdir -v /work/lib
|
||||
helper.Script = ""
|
||||
}
|
||||
|
||||
env := []string{
|
||||
"LDFLAGS=" + earlyLDFLAGS(false),
|
||||
}
|
||||
if t.isStage0() {
|
||||
env = append(env,
|
||||
"CC=clang",
|
||||
"AR=ar",
|
||||
"RANLIB=ranlib",
|
||||
)
|
||||
}
|
||||
|
||||
return t.NewPackage(name, version, newTar(
|
||||
"https://musl.libc.org/releases/musl-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), &PackageAttr{
|
||||
NonStage0: extra,
|
||||
|
||||
// expected to be writable in copies
|
||||
Chmod: true,
|
||||
|
||||
Env: stage0ExclConcat(t, []string{
|
||||
"CC=clang",
|
||||
"LIBCC=/system/lib/clang/" + llvmVersionMajor + "/lib/" +
|
||||
triplet() + "/libclang_rt.builtins.a",
|
||||
"AR=ar",
|
||||
"RANLIB=ranlib",
|
||||
},
|
||||
"LDFLAGS="+earlyLDFLAGS(false),
|
||||
),
|
||||
Env: env,
|
||||
}, &helper,
|
||||
Coreutils,
|
||||
), version
|
||||
@@ -62,7 +60,7 @@ rmdir -v /work/lib
|
||||
func init() {
|
||||
artifactsM[Musl] = Metadata{
|
||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||
return t.newMusl(false, t.Load(CompilerRT))
|
||||
return t.newMusl(false)
|
||||
},
|
||||
|
||||
Name: "musl",
|
||||
@@ -71,4 +69,13 @@ func init() {
|
||||
|
||||
ID: 11688,
|
||||
}
|
||||
|
||||
artifactsM[muslHeaders] = Metadata{
|
||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||
return t.newMusl(true)
|
||||
},
|
||||
|
||||
Name: "musl-headers",
|
||||
Description: "system installation of musl headers",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
|
||||
func (t Toolchain) newNSS() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "3.123"
|
||||
checksum = "pwBz0FO8jmhejPblfzNQLGsqBBGT0DwAw-z9yBJH3V3hVJBMKSc1l0R8GC0_BnzF"
|
||||
version = "3.123.1"
|
||||
checksum = "g811Z_fc74ssg-s6BeXRG-ipSfJggD6hrxjVJxrOBIz98CE7piv0OLwzIRLMQpwR"
|
||||
|
||||
version0 = "4_38_2"
|
||||
checksum0 = "25x2uJeQnOHIiq_zj17b4sYqKgeoU8-IsySUptoPcdHZ52PohFZfGuIisBreWzx0"
|
||||
@@ -82,30 +82,24 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newBuildCATrust() (pkg.Artifact, string) {
|
||||
func init() {
|
||||
const (
|
||||
version = "0.5.1"
|
||||
checksum = "g9AqIksz-hvCUceSR7ZKwfqf8Y_UsJU_3_zLUIdc4IkxFVkgdv9kKVvhFjE4s1-7"
|
||||
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},
|
||||
)
|
||||
return t.newViaPip("buildcatrust", version,
|
||||
"https://github.com/nix-community/buildcatrust/releases/"+
|
||||
"download/v"+version+"/buildcatrust-"+version+"-py3-none-any.whl",
|
||||
checksum), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[buildcatrust] = Metadata{
|
||||
f: Toolchain.newBuildCATrust,
|
||||
|
||||
Name: "buildcatrust",
|
||||
Description: "transform certificate stores between formats",
|
||||
Website: "https://github.com/nix-community/buildcatrust",
|
||||
|
||||
Dependencies: P{
|
||||
Python,
|
||||
},
|
||||
|
||||
ID: 233988,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newNSSCACert() (pkg.Artifact, string) {
|
||||
|
||||
@@ -23,7 +23,7 @@ func (t Toolchain) newPerl() (pkg.Artifact, string) {
|
||||
|
||||
ScriptEarly: `
|
||||
echo 'print STDOUT "1..0 # Skip broken test\n";' > ext/Pod-Html/t/htmldir3.t
|
||||
rm -f /system/bin/ps # perl does not like toybox ps
|
||||
chmod +w /system/bin && rm -f /system/bin/ps # perl does not like toybox ps
|
||||
`,
|
||||
|
||||
Flag: TEarly,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package rosa
|
||||
|
||||
import (
|
||||
"path"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
@@ -23,6 +22,32 @@ func (t Toolchain) newPython() (pkg.Artifact, string) {
|
||||
Writable: true,
|
||||
Chmod: true,
|
||||
|
||||
Patches: []KV{
|
||||
{"zipfile-no-default-strict_timestamps", `diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py
|
||||
index 19aea290b58..51603ba9510 100644
|
||||
--- a/Lib/zipfile/__init__.py
|
||||
+++ b/Lib/zipfile/__init__.py
|
||||
@@ -617,7 +617,7 @@ def _decodeExtra(self, filename_crc):
|
||||
extra = extra[ln+4:]
|
||||
|
||||
@classmethod
|
||||
- def from_file(cls, filename, arcname=None, *, strict_timestamps=True):
|
||||
+ def from_file(cls, filename, arcname=None, *, strict_timestamps=False):
|
||||
"""Construct an appropriate ZipInfo for a file on the filesystem.
|
||||
|
||||
filename should be the path to a file or directory on the filesystem.
|
||||
@@ -1412,7 +1412,7 @@ class ZipFile:
|
||||
_windows_illegal_name_trans_table = None
|
||||
|
||||
def __init__(self, file, mode="r", compression=ZIP_STORED, allowZip64=True,
|
||||
- compresslevel=None, *, strict_timestamps=True, metadata_encoding=None):
|
||||
+ compresslevel=None, *, strict_timestamps=False, metadata_encoding=None):
|
||||
"""Open the ZIP file with mode read 'r', write 'w', exclusive create 'x',
|
||||
or append 'a'."""
|
||||
if mode not in ('r', 'w', 'x', 'a'):
|
||||
`},
|
||||
},
|
||||
|
||||
Env: []string{
|
||||
"EXTRATESTOPTS=-j0 -x " + strings.Join([]string{
|
||||
// requires internet access (http://www.pythontest.net/)
|
||||
@@ -36,7 +61,7 @@ func (t Toolchain) newPython() (pkg.Artifact, string) {
|
||||
"test_os",
|
||||
"test_subprocess",
|
||||
|
||||
// somehow picks up mtime of source code
|
||||
// patched out insane strict_timestamps default
|
||||
"test_zipfile",
|
||||
|
||||
// requires gcc
|
||||
@@ -81,47 +106,112 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
// newViaPip installs a pip wheel from a url.
|
||||
func (t Toolchain) newViaPip(
|
||||
name, version, url, checksum string,
|
||||
extra ...PArtifact,
|
||||
) pkg.Artifact {
|
||||
return t.New(name+"-"+version, 0, t.AppendPresets(nil,
|
||||
slices.Concat(P{Python}, extra)...,
|
||||
), nil, nil, `
|
||||
// PipHelper is the [Python] pip packaging helper.
|
||||
type PipHelper struct {
|
||||
// Path elements joined with source.
|
||||
Append []string
|
||||
// Whether to omit --no-build-isolation.
|
||||
BuildIsolation bool
|
||||
// Whether to enter source after install.
|
||||
EnterSource bool
|
||||
// Whether to install to build environment after install.
|
||||
Install bool
|
||||
// Whether to skip running tests.
|
||||
SkipCheck bool
|
||||
// Replaces pytest if non-empty.
|
||||
Check string
|
||||
// Runs after install.
|
||||
Script string
|
||||
}
|
||||
|
||||
var _ Helper = new(PipHelper)
|
||||
|
||||
// extra returns python, or pytest if defaults are assumed.
|
||||
func (attr *PipHelper) extra(int) P {
|
||||
if attr == nil || (!attr.SkipCheck && attr.Check == "") {
|
||||
return P{PythonPyTest}
|
||||
}
|
||||
return P{Python}
|
||||
}
|
||||
|
||||
// wantsChmod returns true.
|
||||
func (*PipHelper) wantsChmod() bool { return true }
|
||||
|
||||
// wantsWrite is equivalent to wantsChmod.
|
||||
func (attr *PipHelper) wantsWrite() bool { return attr.wantsChmod() }
|
||||
|
||||
// scriptEarly is a noop.
|
||||
func (*PipHelper) scriptEarly() string { return "" }
|
||||
|
||||
// createDir returns false.
|
||||
func (*PipHelper) createDir() bool { return false }
|
||||
|
||||
// wantsDir requests a new directory in TMPDIR.
|
||||
func (*PipHelper) wantsDir() string { return `"$(mktemp -d)"` }
|
||||
|
||||
// script generates the pip3 install command.
|
||||
func (attr *PipHelper) script(name string) string {
|
||||
if attr == nil {
|
||||
attr = new(PipHelper)
|
||||
}
|
||||
sourcePath := AbsUsrSrc.Append(name).Append(attr.Append...)
|
||||
|
||||
var extra string
|
||||
if !attr.BuildIsolation {
|
||||
extra += `
|
||||
--no-build-isolation \`
|
||||
}
|
||||
|
||||
var script string
|
||||
if attr.Install {
|
||||
script += `pip3 install \
|
||||
--no-index \
|
||||
--prefix=/system \
|
||||
--no-build-isolation \
|
||||
'` + sourcePath.String() + `'
|
||||
`
|
||||
}
|
||||
if attr.EnterSource {
|
||||
script += "cd '/usr/src/" + name + "'\n"
|
||||
}
|
||||
if !attr.SkipCheck {
|
||||
if attr.Check == "" {
|
||||
// some test suites fall apart when ran out-of-tree
|
||||
script += "(cd '" + sourcePath.String() + "' && pytest)\n"
|
||||
} else {
|
||||
script += attr.Check
|
||||
}
|
||||
}
|
||||
script += attr.Script
|
||||
|
||||
return `
|
||||
pip3 install \
|
||||
--no-index \
|
||||
--prefix=/system \
|
||||
--root=/work \
|
||||
'/usr/src/`+path.Base(url)+`'
|
||||
`, pkg.Path(AbsUsrSrc.Append(path.Base(url)), false, pkg.NewHTTPGet(
|
||||
nil, url,
|
||||
mustDecode(checksum),
|
||||
)))
|
||||
--root=/work \` + extra + `
|
||||
'` + sourcePath.String() + `'
|
||||
` + script
|
||||
}
|
||||
|
||||
// newPypi creates [Metadata] for a [pypi] package.
|
||||
//
|
||||
// [pypi]: https://pypi.org/
|
||||
func newPypi(
|
||||
name string, id int,
|
||||
description, version, interpreter, abi, platform, checksum string,
|
||||
extra ...PArtifact,
|
||||
// newPythonPackage creates [Metadata] for a [Python] package.
|
||||
func newPythonPackage(
|
||||
name string, id int, description, website, version string,
|
||||
source pkg.Artifact, attrP *PackageAttr, attr *PipHelper,
|
||||
build P, extra ...PArtifact,
|
||||
) Metadata {
|
||||
name = "python-" + name
|
||||
return Metadata{
|
||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||
return t.newViaPip(name, version, "https://files.pythonhosted.org/"+path.Join(
|
||||
"packages",
|
||||
interpreter,
|
||||
string(name[0]),
|
||||
name,
|
||||
name+"-"+version+"-"+interpreter+"-"+abi+"-"+platform+".whl",
|
||||
), checksum, extra...), version
|
||||
return t.NewPackage(name, version, source, attrP, attr, slices.Concat(
|
||||
P{Python},
|
||||
extra,
|
||||
build,
|
||||
)...), version
|
||||
},
|
||||
|
||||
Name: "python-" + name,
|
||||
Name: name,
|
||||
Description: description,
|
||||
Website: "https://pypi.org/project/" + name + "/",
|
||||
Website: website,
|
||||
|
||||
Dependencies: slices.Concat(P{Python}, extra),
|
||||
|
||||
@@ -129,106 +219,368 @@ func newPypi(
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newSetuptools() (pkg.Artifact, string) {
|
||||
func init() {
|
||||
const (
|
||||
version = "0.47.0"
|
||||
checksum = "HZ-MvkUP8mbbx2YmsRNswj_bbOCIiXckuHqL5Qbvb5NxN5DYfWnqwkGNyS7OrId0"
|
||||
)
|
||||
artifactsM[PythonWheel] = newPythonPackage(
|
||||
"wheel", 11428,
|
||||
"the official binary distribution format for Python",
|
||||
"https://peps.python.org/pep-0427/",
|
||||
version, newFromGitHub(
|
||||
"pypa/wheel",
|
||||
version, checksum,
|
||||
), nil, &PipHelper{
|
||||
Install: true,
|
||||
}, P{PythonFlitCore, PythonSetuptools},
|
||||
)
|
||||
}
|
||||
|
||||
func init() {
|
||||
const (
|
||||
version = "82.0.1"
|
||||
checksum = "nznP46Tj539yqswtOrIM4nQgwLA1h-ApKX7z7ghazROCpyF5swtQGwsZoI93wkhc"
|
||||
)
|
||||
return t.New("setuptools-"+version, 0, t.AppendPresets(nil,
|
||||
Python,
|
||||
), nil, nil, `
|
||||
pip3 install \
|
||||
--no-index \
|
||||
--prefix=/system \
|
||||
--root=/work \
|
||||
/usr/src/setuptools
|
||||
`, pkg.Path(AbsUsrSrc.Append("setuptools"), true, newFromGitHub(
|
||||
"pypa/setuptools",
|
||||
"v"+version, checksum,
|
||||
))), version
|
||||
artifactsM[PythonSetuptools] = newPythonPackage(
|
||||
"setuptools", 4021,
|
||||
"the autotools of the Python ecosystem",
|
||||
"https://pypi.org/project/setuptools/",
|
||||
version, newFromGitHub(
|
||||
"pypa/setuptools",
|
||||
"v"+version, checksum,
|
||||
), nil, &PipHelper{
|
||||
// error: invalid command 'dist_info'
|
||||
BuildIsolation: true,
|
||||
// pytest circular dependency
|
||||
SkipCheck: true,
|
||||
}, nil)
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Setuptools] = Metadata{
|
||||
f: Toolchain.newSetuptools,
|
||||
|
||||
Name: "python-setuptools",
|
||||
Description: "the autotools of the Python ecosystem",
|
||||
Website: "https://pypi.org/project/setuptools/",
|
||||
func init() {
|
||||
const (
|
||||
version = "1.1.1"
|
||||
checksum = "rXZixTsZcRcIoUC1LvWrjySsiXSv5uhW6ng2P-yXZrbdj7FrSrDeJLCfC2b-ladV"
|
||||
)
|
||||
artifactsM[PythonVCSVersioning] = newPythonPackage(
|
||||
"vcs-versioning", 389421,
|
||||
"core VCS versioning functionality extracted as a standalone library",
|
||||
"https://setuptools-scm.readthedocs.io/en/latest/",
|
||||
version, newFromGitHub(
|
||||
"pypa/setuptools-scm",
|
||||
"vcs-versioning-v"+version, checksum,
|
||||
), &PackageAttr{
|
||||
Env: []string{
|
||||
"SETUPTOOLS_SCM_PRETEND_VERSION=" + version,
|
||||
},
|
||||
}, &PipHelper{
|
||||
// upstream is monorepo of two packages (setuptools-scm)
|
||||
Append: []string{"vcs-versioning"},
|
||||
// pytest circular dependency
|
||||
SkipCheck: true,
|
||||
}, nil,
|
||||
PythonSetuptools,
|
||||
PythonPackaging,
|
||||
)
|
||||
}
|
||||
|
||||
func init() {
|
||||
const (
|
||||
version = "10.0.5"
|
||||
checksum = "vTN_TPd-b4Wbsw5WmAcsWjrs-FNXXznOeVTDnb54NtXve9Oy-eb2HPy-RG3FzNqp"
|
||||
)
|
||||
artifactsM[PythonSetuptoolsSCM] = newPythonPackage(
|
||||
"setuptools-scm", 7874,
|
||||
"extracts Python package versions from Git or Mercurial metadata",
|
||||
"https://setuptools-scm.readthedocs.io/en/latest/",
|
||||
version, newFromGitHub(
|
||||
"pypa/setuptools-scm",
|
||||
"setuptools-scm-v"+version, checksum,
|
||||
), &PackageAttr{
|
||||
Env: []string{
|
||||
"SETUPTOOLS_SCM_PRETEND_VERSION=" + version,
|
||||
},
|
||||
}, &PipHelper{
|
||||
// upstream is monorepo of two packages
|
||||
Append: []string{"setuptools-scm"},
|
||||
// pytest circular dependency
|
||||
SkipCheck: true,
|
||||
}, nil,
|
||||
PythonSetuptools,
|
||||
PythonVCSVersioning,
|
||||
)
|
||||
}
|
||||
|
||||
func init() {
|
||||
const (
|
||||
version = "3.12.0"
|
||||
checksum = "VcTsiGiDU1aPLbjSPe38f9OjJDCLcxFz9loObJqUI1ZxDHXAaQMxBpNyLz_G1Rff"
|
||||
)
|
||||
artifactsM[PythonFlitCore] = newPythonPackage(
|
||||
"flit-core", 44841,
|
||||
"a PEP 517 build backend for packages using Flit",
|
||||
"https://flit.pypa.io/",
|
||||
version, newFromGitHub(
|
||||
"pypa/flit",
|
||||
version, checksum,
|
||||
), nil, &PipHelper{
|
||||
// upstream has other unused packages with many dependencies
|
||||
Append: []string{"flit_core"},
|
||||
// pytest circular dependency
|
||||
SkipCheck: true,
|
||||
}, nil,
|
||||
)
|
||||
}
|
||||
|
||||
func init() {
|
||||
const (
|
||||
version = "26.2"
|
||||
checksum = "rdpGa2EkPFbj1mFtLKLnSwIX9gPfELcuneiICjRVDNw6By49szTFVoW8gtMMZ6ZS"
|
||||
)
|
||||
artifactsM[PythonPackaging] = newPythonPackage(
|
||||
"packaging", 60461,
|
||||
"reusable core utilities for various Python Packaging interoperability specifications",
|
||||
"https://packaging.pypa.io/",
|
||||
version, newFromGitHub(
|
||||
"pypa/packaging",
|
||||
version, checksum,
|
||||
), nil, &PipHelper{
|
||||
// pytest circular dependency
|
||||
SkipCheck: true,
|
||||
}, P{PythonFlitCore},
|
||||
)
|
||||
}
|
||||
|
||||
func init() {
|
||||
artifactsM[LIT] = Metadata{
|
||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||
version := t.Version(LLVM)
|
||||
return t.NewPackage("lit", version, t.Load(llvmSource), nil, &PipHelper{
|
||||
Append: []string{"llvm", "utils", "lit"},
|
||||
// already checked during llvm
|
||||
SkipCheck: true,
|
||||
},
|
||||
PythonSetuptools,
|
||||
), version
|
||||
},
|
||||
|
||||
Name: "lit",
|
||||
Description: "a portable tool for executing LLVM and Clang style test suites",
|
||||
Website: "https://llvm.org/docs/CommandGuide/lit.html",
|
||||
|
||||
Dependencies: P{
|
||||
Python,
|
||||
},
|
||||
|
||||
ID: 4021,
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
artifactsM[PythonPygments] = newPypi(
|
||||
"pygments", 3986,
|
||||
" a syntax highlighting package written in Python",
|
||||
"2.20.0", "py3", "none", "any",
|
||||
"qlyqX2YSXcV0Z8XgGaPttc_gkq-xsu_nYs6NFOcYnk-CX7qmcj45gG-h6DpwPIcO",
|
||||
const (
|
||||
version = "1.1.1"
|
||||
checksum = "1fVwoal6FoKXczoG3qRUi87TxSWESSGcgvnbEZDYuaOgsO25o36iF3SbAhwkr4Va"
|
||||
)
|
||||
artifactsM[PythonPathspec] = newPythonPackage(
|
||||
"pathspec", 23424,
|
||||
"utility library for gitignore style pattern matching of file paths",
|
||||
"https://github.com/cpburnz/python-pathspec",
|
||||
version, newFromGitHub(
|
||||
"cpburnz/python-pathspec",
|
||||
"v"+version, checksum,
|
||||
), nil, &PipHelper{
|
||||
// pytest circular dependency
|
||||
SkipCheck: true,
|
||||
}, P{PythonFlitCore},
|
||||
)
|
||||
}
|
||||
|
||||
artifactsM[PythonPluggy] = newPypi(
|
||||
func init() {
|
||||
const (
|
||||
version = "2026.4.28.13"
|
||||
checksum = "Z3MbmMXtmWHCM3-EvJehb9MzDqX7Ce_Xg86D5g5nxFRWMKqwHwnQ8R-AlKf-32HU"
|
||||
)
|
||||
artifactsM[PythonTroveClassifiers] = newPythonPackage(
|
||||
"trove-classifiers", 88298,
|
||||
"canonical source for classifiers on PyPI",
|
||||
"https://pypi.org/p/trove-classifiers/",
|
||||
version, newFromGitHub(
|
||||
"pypa/trove-classifiers",
|
||||
version, checksum,
|
||||
), nil, &PipHelper{
|
||||
// pytest circular dependency
|
||||
SkipCheck: true,
|
||||
}, P{PythonSetuptools},
|
||||
)
|
||||
}
|
||||
|
||||
func init() {
|
||||
const (
|
||||
version = "1.6.0"
|
||||
checksum = "GiUgDkKjF8Xn1cmq6iMhTGXzcPIYeaJrvQpHBSAJapNVx4UyuiTXqd5eVlxSClJu"
|
||||
)
|
||||
artifactsM[PythonPluggy] = newPythonPackage(
|
||||
"pluggy", 7500,
|
||||
"the core framework used by the pytest, tox, and devpi projects",
|
||||
"1.6.0", "py3", "none", "any",
|
||||
"2HWYBaEwM66-y1hSUcWI1MyE7dVVuNNRW24XD6iJBey4YaUdAK8WeXdtFMQGC-4J",
|
||||
"https://pluggy.readthedocs.io/en/latest/",
|
||||
version, newFromGitHub(
|
||||
"pytest-dev/pluggy",
|
||||
version, checksum,
|
||||
), &PackageAttr{
|
||||
Env: []string{
|
||||
"SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PLUGGY=" + version,
|
||||
},
|
||||
}, &PipHelper{
|
||||
// pytest circular dependency
|
||||
SkipCheck: true,
|
||||
}, P{PythonSetuptoolsSCM},
|
||||
)
|
||||
}
|
||||
|
||||
artifactsM[PythonPackaging] = newPypi(
|
||||
"packaging", 60461,
|
||||
"reusable core utilities for various Python Packaging interoperability specifications",
|
||||
"26.1", "py3", "none", "any",
|
||||
"6WZjBJeRb0eZZavxM8cLPcgD-ch-1FblsHoCFKC_9VUC5XAmd397LwliVhsnQcSN",
|
||||
func init() {
|
||||
const (
|
||||
version = "1.16.5"
|
||||
checksum = "V2eREtqZLZeV85yb4O-bfAJCUluHcQP76Qfs0QH5s7RF_Oc8xIP8jD0jl85qFyWk"
|
||||
)
|
||||
artifactsM[PythonHatchling] = newPythonPackage(
|
||||
"hatchling", 16137,
|
||||
"the extensible, standards compliant build backend used by Hatch",
|
||||
"https://hatch.pypa.io/latest/",
|
||||
version, newFromGitHub(
|
||||
"pypa/hatch",
|
||||
"hatch-v"+version, checksum,
|
||||
), nil, &PipHelper{
|
||||
// upstream has other unused packages with many dependencies
|
||||
Append: []string{"backend"},
|
||||
// pytest circular dependency
|
||||
SkipCheck: true,
|
||||
}, nil,
|
||||
PythonPackaging,
|
||||
PythonPathspec,
|
||||
PythonTroveClassifiers,
|
||||
PythonPluggy,
|
||||
)
|
||||
}
|
||||
|
||||
artifactsM[PythonIniConfig] = newPypi(
|
||||
func init() {
|
||||
const (
|
||||
version = "2.20.0"
|
||||
checksum = "L-2P6vn7c_CNZYliE5CJAWLxO1ziDQVVkf8bnZbHj8aSCQ43oWv11wC9KzU9MeCa"
|
||||
)
|
||||
artifactsM[PythonPygments] = newPythonPackage(
|
||||
"pygments", 3986,
|
||||
"a syntax highlighting package written in Python",
|
||||
"https://pygments.org/",
|
||||
version, newFromGitHub(
|
||||
"pygments/pygments",
|
||||
version, checksum,
|
||||
), nil, &PipHelper{
|
||||
// pytest circular dependency
|
||||
SkipCheck: true,
|
||||
}, P{PythonHatchling},
|
||||
)
|
||||
}
|
||||
|
||||
func init() {
|
||||
const (
|
||||
version = "2.3.0"
|
||||
checksum = "mH7VBZaXcYatBPE3RQQZvSzz_Ay8IPPek60NpPHZulPq4ReAFUUsA4EPWfiyMknZ"
|
||||
)
|
||||
artifactsM[PythonIniConfig] = newPythonPackage(
|
||||
"iniconfig", 114778,
|
||||
"a small and simple INI-file parser module",
|
||||
"2.3.0", "py3", "none", "any",
|
||||
"SDgs4S5bXi77aVOeKTPv2TUrS3M9rduiK4DpU0hCmDsSBWqnZcWInq9lsx6INxut",
|
||||
"https://github.com/pytest-dev/iniconfig",
|
||||
version, newFromGitHub(
|
||||
"pytest-dev/iniconfig",
|
||||
"v"+version, checksum,
|
||||
), &PackageAttr{
|
||||
Env: []string{
|
||||
"SETUPTOOLS_SCM_PRETEND_VERSION_FOR_INICONFIG=" + version,
|
||||
},
|
||||
}, &PipHelper{
|
||||
// pytest circular dependency
|
||||
SkipCheck: true,
|
||||
}, P{PythonSetuptoolsSCM},
|
||||
)
|
||||
}
|
||||
|
||||
artifactsM[PythonPyTest] = newPypi(
|
||||
func init() {
|
||||
const (
|
||||
version = "9.0.3"
|
||||
checksum = "qfLL_znWhbJCDbNJvrx9H3-orJ86z4ifhaW0bIn21jl2sDP-FVoX_1yieOypArQe"
|
||||
)
|
||||
artifactsM[PythonPyTest] = newPythonPackage(
|
||||
"pytest", 3765,
|
||||
"the pytest framework",
|
||||
"9.0.3", "py3", "none", "any",
|
||||
"57WLrIVOfyoRDjt5qD6LGOaDcDCtzQnKDSTUb7GzHyJDtry_nGHHs4-0tW0tiIJr",
|
||||
"https://pytest.org",
|
||||
version, newFromGitHub(
|
||||
"pytest-dev/pytest",
|
||||
version, checksum,
|
||||
), &PackageAttr{
|
||||
Env: []string{
|
||||
"SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PYTEST=" + version,
|
||||
},
|
||||
}, &PipHelper{
|
||||
// many dependencies
|
||||
SkipCheck: true,
|
||||
}, P{PythonSetuptoolsSCM},
|
||||
PythonIniConfig,
|
||||
PythonPackaging,
|
||||
PythonPluggy,
|
||||
PythonPygments,
|
||||
)
|
||||
}
|
||||
|
||||
artifactsM[PythonMarkupSafe] = newPypi(
|
||||
func init() {
|
||||
const (
|
||||
version = "3.0.3"
|
||||
checksum = "txRGYdWE3his1lHHRI-lZADw0-ILvUg2l5OGdFHtFXIb_QowGxwdxHCUSJIgmjQs"
|
||||
)
|
||||
artifactsM[PythonMarkupSafe] = newPythonPackage(
|
||||
"markupsafe", 3918,
|
||||
"implements a text object that escapes characters so it is safe to use in HTML and XML",
|
||||
"3.0.3", "cp314", "cp314", "musllinux_1_2_"+linuxArch(),
|
||||
perArch[string]{
|
||||
"amd64": "E2mo9ig_FKgTpGon_8qqviSEULwhnmxTIqd9vfyNxNpK4yofVYM7eLW_VE-LKbtO",
|
||||
"arm64": "iG_hqsncOs8fA7bCaAg0x9XenXWlo9sqblyPcSG7yA9sfGLvM9KZznCpwWfOCwFC",
|
||||
"riscv64": "7DI7U0M3jvr7U4uZml25GLw3m3EvMubCtNukZmss1gkVJ_DVkhV5DgX3Wt_sztbv",
|
||||
}.unwrap(),
|
||||
)
|
||||
|
||||
artifactsM[PythonMako] = newPypi(
|
||||
"mako", 3915,
|
||||
"a template library written in Python",
|
||||
"1.3.11", "py3", "none", "any",
|
||||
"WJ_hxYI-nNiuDiM6QhfAG84uO5U-M2aneB0JS9AQ2J2Oi6YXAbBxIdOeOEng6CoS",
|
||||
PythonMarkupSafe,
|
||||
)
|
||||
|
||||
artifactsM[PythonPyYAML] = newPypi(
|
||||
"pyyaml", 4123,
|
||||
"a YAML parser and emitter for Python",
|
||||
"6.0.3", "cp314", "cp314", "musllinux_1_2_"+linuxArch(),
|
||||
perArch[string]{
|
||||
"amd64": "4_jhCFpUNtyrFp2HOMqUisR005u90MHId53eS7rkUbcGXkoaJ7JRsY21dREHEfGN",
|
||||
"arm64": "sQ818ZYSmC7Vj9prIPx3sEYqSDhZlWvLbgHV9w4GjxsfQ63ZSzappctKM7Lb0Whw",
|
||||
}.unwrap(),
|
||||
"https://markupsafe.palletsprojects.com/",
|
||||
version, newFromGitHub(
|
||||
"pallets/markupsafe",
|
||||
version, checksum,
|
||||
), nil, &PipHelper{
|
||||
// ModuleNotFoundError: No module named 'markupsafe'
|
||||
Install: true,
|
||||
}, P{PythonSetuptools},
|
||||
)
|
||||
}
|
||||
|
||||
func init() {
|
||||
const (
|
||||
version = "1.3.12"
|
||||
checksum = "OZbBsQe2MzRuAo5Mr4qRwWHGqU1EEZeBuSprDDIceAtMLIUJtO7SbERlxHIxNhLk"
|
||||
)
|
||||
artifactsM[PythonMako] = newPythonPackage(
|
||||
"mako", 3915,
|
||||
"a template library written in Python",
|
||||
"https://www.makotemplates.org/",
|
||||
version, newFromGitHub(
|
||||
"sqlalchemy/mako",
|
||||
"rel_"+strings.Join(strings.SplitN(version, ".", 3), "_"),
|
||||
checksum,
|
||||
), nil, nil, P{PythonSetuptools},
|
||||
PythonMarkupSafe,
|
||||
)
|
||||
}
|
||||
|
||||
func init() {
|
||||
const (
|
||||
version = "6.0.3"
|
||||
checksum = "7wDv0RW9chBdu9l5Q4Hun5F2HHdo105ZSIixwdFPKbEYbftW9YxmsegfL-zafnbJ"
|
||||
)
|
||||
artifactsM[PythonPyYAML] = newPythonPackage(
|
||||
"pyyaml", 4123,
|
||||
"a YAML parser and emitter for Python",
|
||||
"https://pyyaml.org/",
|
||||
version, newFromGitHub(
|
||||
"yaml/pyyaml",
|
||||
version, checksum,
|
||||
), nil, &PipHelper{
|
||||
// ModuleNotFoundError: No module named 'yaml'
|
||||
Install: true,
|
||||
}, P{PythonSetuptools},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newQEMU() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "10.2.2"
|
||||
checksum = "uNzRxlrVoLWe-EmZmBp75SezymgE512iE5XN90Bl7wi6CjE_oQGQB-9ocs7E16QG"
|
||||
version = "11.0.0"
|
||||
checksum = "C64gdi_Tkdg2fTwD9ERxtWGcf8vNn_6UvczW0c-x0KW1NZtd3NbEOIrlDhYGn15n"
|
||||
)
|
||||
return t.NewPackage("qemu", version, newTar(
|
||||
"https://download.qemu.org/qemu-"+version+".tar.bz2",
|
||||
@@ -73,6 +73,8 @@ EOF
|
||||
},
|
||||
Bash,
|
||||
Python,
|
||||
PythonSetuptools,
|
||||
PythonWheel,
|
||||
Ninja,
|
||||
PkgConfig,
|
||||
Diffutils,
|
||||
|
||||
@@ -3,7 +3,6 @@ package rosa
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"path"
|
||||
"runtime"
|
||||
"slices"
|
||||
@@ -15,6 +14,12 @@ import (
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
// Extension is the variant identification string of custom artifact
|
||||
// implementations registered by package rosa.
|
||||
const Extension = "rosa"
|
||||
|
||||
func init() { pkg.SetExtension(Extension) }
|
||||
|
||||
const (
|
||||
// kindEtc is the kind of [pkg.Artifact] of cureEtc.
|
||||
kindEtc = iota + pkg.KindCustomOffset
|
||||
@@ -28,7 +33,7 @@ const (
|
||||
func mustDecode(s string) pkg.Checksum {
|
||||
var fallback = pkg.Checksum{}
|
||||
if s == "" {
|
||||
log.Println(
|
||||
println(
|
||||
"falling back to",
|
||||
pkg.Encode(fallback),
|
||||
"for unpopulated checksum",
|
||||
@@ -102,21 +107,6 @@ func earlyLDFLAGS(static bool) string {
|
||||
return s
|
||||
}
|
||||
|
||||
// earlyCFLAGS is reference CFLAGS for the stage0 toolchain.
|
||||
const earlyCFLAGS = "-Qunused-arguments " +
|
||||
"-isystem/system/include"
|
||||
|
||||
// earlyCXXFLAGS returns reference CXXFLAGS for the stage0 toolchain
|
||||
// corresponding to [runtime.GOARCH].
|
||||
func earlyCXXFLAGS() string {
|
||||
return "--start-no-unused-arguments " +
|
||||
"-stdlib=libc++ " +
|
||||
"--end-no-unused-arguments " +
|
||||
"-isystem/system/include/c++/v1 " +
|
||||
"-isystem/system/include/" + triplet() + "/c++/v1 " +
|
||||
"-isystem/system/include "
|
||||
}
|
||||
|
||||
// Toolchain denotes the infrastructure to compile a [pkg.Artifact] on.
|
||||
type Toolchain uint32
|
||||
|
||||
@@ -186,24 +176,6 @@ func (t Toolchain) isStd() bool {
|
||||
}
|
||||
}
|
||||
|
||||
// stage0Concat concatenates s and values. If the current toolchain is
|
||||
// toolchainStage0, stage0Concat returns s as is.
|
||||
func stage0Concat[S ~[]E, E any](t Toolchain, s S, values ...E) S {
|
||||
if t.isStage0() {
|
||||
return s
|
||||
}
|
||||
return slices.Concat(s, values)
|
||||
}
|
||||
|
||||
// stage0ExclConcat concatenates s and values. If the current toolchain is not
|
||||
// toolchainStage0, stage0ExclConcat returns s as is.
|
||||
func stage0ExclConcat[S ~[]E, E any](t Toolchain, s S, values ...E) S {
|
||||
if t.isStage0() {
|
||||
return slices.Concat(s, values)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// lastIndexFunc is like [strings.LastIndexFunc] but for [slices].
|
||||
func lastIndexFunc[S ~[]E, E any](s S, f func(E) bool) (i int) {
|
||||
if i = slices.IndexFunc(s, f); i < 0 {
|
||||
@@ -293,6 +265,7 @@ func (t Toolchain) New(
|
||||
|
||||
case toolchainGentoo, toolchainStage0:
|
||||
name += "-boot"
|
||||
support = append(support, extra...)
|
||||
support = append(support, cureEtc{})
|
||||
if t == toolchainStage0 {
|
||||
support = append(support, NewStage0())
|
||||
@@ -313,7 +286,6 @@ mkdir -vp /work/system/bin
|
||||
),
|
||||
)))
|
||||
}
|
||||
support = slices.Concat(support, extra)
|
||||
env = fixupEnviron(env, []string{
|
||||
EnvTriplet + "=" + triplet(),
|
||||
lcMessages,
|
||||
@@ -333,7 +305,7 @@ mkdir -vp /work/system/bin
|
||||
toybox = toyboxEarly
|
||||
}
|
||||
|
||||
base := Clang
|
||||
base := LLVM
|
||||
if flag&TNoToolchain != 0 {
|
||||
base = Musl
|
||||
}
|
||||
@@ -348,11 +320,6 @@ mkdir -vp /work/system/bin
|
||||
env = fixupEnviron(env, []string{
|
||||
EnvTriplet + "=" + triplet(),
|
||||
lcMessages,
|
||||
|
||||
"AR=ar",
|
||||
"RANLIB=ranlib",
|
||||
"LIBCC=/system/lib/clang/" + llvmVersionMajor + "/lib/" + triplet() +
|
||||
"/libclang_rt.builtins.a",
|
||||
}, "/system/bin", "/bin")
|
||||
|
||||
default:
|
||||
@@ -410,8 +377,8 @@ cat /usr/src/` + name + `-patches/* | \
|
||||
`
|
||||
aname += "-patched"
|
||||
}
|
||||
return t.New(aname, 0, stage0Concat(t, []pkg.Artifact{},
|
||||
t.Load(Patch),
|
||||
return t.New(aname, 0, t.AppendPresets(nil,
|
||||
Patch,
|
||||
), nil, nil, script, paths...)
|
||||
}
|
||||
|
||||
@@ -458,9 +425,6 @@ type PackageAttr struct {
|
||||
// Passed to [Toolchain.NewPatchedSource].
|
||||
Patches []KV
|
||||
|
||||
// Dependencies not provided by stage0.
|
||||
NonStage0 []pkg.Artifact
|
||||
|
||||
// Passed through to [Toolchain.New], before source.
|
||||
Paths []pkg.ExecPath
|
||||
// Passed through to [Toolchain.New].
|
||||
@@ -528,14 +492,8 @@ func (t Toolchain) NewPackage(
|
||||
panic("source must be non-nil")
|
||||
}
|
||||
wantsChmod, wantsWrite := helper.wantsChmod(), helper.wantsWrite()
|
||||
dc := len(attr.NonStage0)
|
||||
if !t.isStage0() {
|
||||
dc += 1<<3 + len(extra)
|
||||
}
|
||||
|
||||
extraRes := make([]pkg.Artifact, 0, dc)
|
||||
extraRes = append(extraRes, attr.NonStage0...)
|
||||
if !t.isStage0() {
|
||||
extraRes := make([]pkg.Artifact, 0, 1<<3+len(extra))
|
||||
{
|
||||
pv := paGet()
|
||||
for _, p := range helper.extra(attr.Flag) {
|
||||
extraRes = t.appendPreset(extraRes, pv, p)
|
||||
|
||||
@@ -28,6 +28,7 @@ var (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
rosa.DropCaches(rosa.OptLLVMNoLTO)
|
||||
container.TryArgv0(nil)
|
||||
|
||||
code := m.Run()
|
||||
@@ -93,11 +94,14 @@ func TestCureAll(t *testing.T) {
|
||||
}
|
||||
|
||||
func BenchmarkStage3(b *testing.B) {
|
||||
flags := rosa.Flags()
|
||||
b.Cleanup(func() { rosa.DropCaches(flags) })
|
||||
|
||||
for b.Loop() {
|
||||
rosa.Std.Load(rosa.Clang)
|
||||
rosa.Std.Load(rosa.LLVM)
|
||||
|
||||
b.StopTimer()
|
||||
rosa.DropCaches()
|
||||
rosa.DropCaches(0)
|
||||
b.StartTimer()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newRsync() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "3.4.1"
|
||||
checksum = "VBlTsBWd9z3r2-ex7GkWeWxkUc5OrlgDzikAC0pK7ufTjAJ0MbmC_N04oSVTGPiv"
|
||||
version = "3.4.2"
|
||||
checksum = "t7PxS4WHXzefLMKKc_3hJgxUmlGG6KgHMZ8i4DZvCQAUAizxbclNKwfLyOHyq5BX"
|
||||
)
|
||||
return t.NewPackage("rsync", version, newTar(
|
||||
"https://download.samba.org/pub/rsync/src/"+
|
||||
|
||||
@@ -3,42 +3,25 @@ package rosa
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"hakurei.app/fhs"
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
func (t Toolchain) newStage0() (pkg.Artifact, string) {
|
||||
return t.New("rosa-stage0", 0, []pkg.Artifact{
|
||||
t.Load(Musl),
|
||||
t.Load(CompilerRT),
|
||||
t.Load(LLVMRuntimes),
|
||||
t.Load(Clang),
|
||||
|
||||
t.Load(Zlib),
|
||||
t.Load(Bzip2),
|
||||
|
||||
t.Load(Patch),
|
||||
t.Load(Make),
|
||||
t.Load(CMake),
|
||||
t.Load(Ninja),
|
||||
|
||||
t.Load(Libffi),
|
||||
t.Load(Python),
|
||||
t.Load(Perl),
|
||||
t.Load(Diffutils),
|
||||
t.Load(Bash),
|
||||
t.Load(Gawk),
|
||||
t.Load(Coreutils),
|
||||
t.Load(Findutils),
|
||||
|
||||
t.Load(KernelHeaders),
|
||||
}, nil, nil, `
|
||||
return t.New("rosa-stage0", 0, t.AppendPresets(nil,
|
||||
Bzip2,
|
||||
), nil, nil, `
|
||||
umask 377
|
||||
tar \
|
||||
-vjc \
|
||||
-C / \
|
||||
-C /stage0 \
|
||||
-f /work/stage0-`+triplet()+`.tar.bz2 \
|
||||
system bin usr/bin/env
|
||||
`), Unversioned
|
||||
.
|
||||
`, pkg.Path(fhs.AbsRoot.Append("stage0"), false, t.AppendPresets(nil,
|
||||
LLVM,
|
||||
Mksh,
|
||||
toyboxEarly,
|
||||
)...)), Unversioned
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Stage0] = Metadata{
|
||||
@@ -60,12 +43,11 @@ var (
|
||||
func NewStage0() pkg.Artifact {
|
||||
stage0Once.Do(func() {
|
||||
stage0 = newTar(
|
||||
"https://hakurei.app/seed/20260210/"+
|
||||
"https://hakurei.app/seed/20260429/"+
|
||||
"stage0-"+triplet()+".tar.bz2",
|
||||
perArch[string]{
|
||||
"amd64": "tqM1Li15BJ-uFG8zU-XjgFxoN_kuzh1VxrSDVUVa0vGmo-NeWapSftH739sY8EAg",
|
||||
"arm64": "CJj3ZSnRyLmFHlWIQtTPQD9oikOZY4cD_mI3v_-LIYc2hhg-cq_CZFBLzQBAkFIn",
|
||||
"riscv64": "FcszJjcVWdKAnn-bt8qmUn5GUUTjv_xQjXOWkUpOplRkG3Ckob3StUoAi5KQ5-QF",
|
||||
"amd64": "ldz-WkSx2wxUK4ndi-tlaaU8ykOowbpGRcBsciAcIDdnX6-QfzQg_se3lsZYuzuK",
|
||||
"arm64": "_mo39S_sgzPYaIQ_Wi13O46KPQuWqCCiZdildpz6a8MTh2khIt68tNIulyUGBV2z",
|
||||
}.unwrap(),
|
||||
pkg.TarBzip2,
|
||||
)
|
||||
|
||||
@@ -27,8 +27,14 @@ chmod -R +w ..
|
||||
sed -i \
|
||||
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
cmd/link/internal/`+runtime.GOARCH+`/obj.go
|
||||
sed -i \
|
||||
's/cpu.X86.HasAVX512VBMI/& \&\& cpu.X86.HasPOPCNT/' \
|
||||
internal/runtime/gc/scan/scan_amd64.go
|
||||
|
||||
rm \
|
||||
os/root_unix_test.go
|
||||
os/root_unix_test.go \
|
||||
cmd/cgo/internal/testsanitizers/tsan_test.go \
|
||||
cmd/cgo/internal/testsanitizers/cshared_test.go
|
||||
|
||||
./all.bash
|
||||
`, pkg.Path(AbsUsrSrc.Append("tamago"), false, newFromGitHub(
|
||||
|
||||
@@ -26,19 +26,50 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newXproto() (pkg.Artifact, string) {
|
||||
func (t Toolchain) newLibxtrans() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "7.0.31"
|
||||
checksum = "Cm69urWY5RctKpR78eGzuwrjDEfXGkvHRdodj6sjypOGy5FF4-lmnUttVHYV1ydg"
|
||||
version = "1.6.0"
|
||||
checksum = "1cxDCF59fLf1HyGDMcjR1L50ZbjD0RTTEDUpOJYcHXu6HUK_Ds0x-KREY7rLNxu9"
|
||||
)
|
||||
return t.NewPackage("xproto", version, newTar(
|
||||
"https://www.x.org/releases/individual/proto/"+
|
||||
"xproto-"+version+".tar.bz2",
|
||||
return t.NewPackage("libxtrans", version, newFromGitLab(
|
||||
"gitlab.freedesktop.org",
|
||||
"xorg/lib/libxtrans",
|
||||
"xtrans-"+version,
|
||||
checksum,
|
||||
pkg.TarBzip2,
|
||||
), nil, &MakeHelper{
|
||||
// ancient configure script
|
||||
Generate: "autoreconf -if",
|
||||
Generate: "NOCONFIGURE=1 ./autogen.sh",
|
||||
},
|
||||
Automake,
|
||||
Libtool,
|
||||
PkgConfig,
|
||||
|
||||
utilMacros,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libxtrans] = Metadata{
|
||||
f: Toolchain.newLibxtrans,
|
||||
|
||||
Name: "libxtrans",
|
||||
Description: "X Window System Protocols Transport layer shared code",
|
||||
Website: "https://gitlab.freedesktop.org/xorg/lib/libxtrans",
|
||||
|
||||
ID: 13441,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newXorgProto() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2025.1"
|
||||
checksum = "pTwJiBJHKA6Rgm3cVDXy1lyvXNIUzTRaukvvYdk1xWoJ_1G-Dfjm9MyewuyIjoHz"
|
||||
)
|
||||
return t.NewPackage("xorgproto", version, newFromGitLab(
|
||||
"gitlab.freedesktop.org",
|
||||
"xorg/proto/xorgproto",
|
||||
"xorgproto-"+version,
|
||||
checksum,
|
||||
), nil, &MakeHelper{
|
||||
Generate: "NOCONFIGURE=1 ./autogen.sh",
|
||||
},
|
||||
Automake,
|
||||
PkgConfig,
|
||||
@@ -47,14 +78,14 @@ func (t Toolchain) newXproto() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Xproto] = Metadata{
|
||||
f: Toolchain.newXproto,
|
||||
artifactsM[XorgProto] = Metadata{
|
||||
f: Toolchain.newXorgProto,
|
||||
|
||||
Name: "xproto",
|
||||
Name: "xorgproto",
|
||||
Description: "X Window System unified protocol definitions",
|
||||
Website: "https://gitlab.freedesktop.org/xorg/proto/xorgproto",
|
||||
|
||||
ID: 13650,
|
||||
ID: 17190,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +108,7 @@ func (t Toolchain) newLibXau() (pkg.Artifact, string) {
|
||||
PkgConfig,
|
||||
|
||||
utilMacros,
|
||||
Xproto,
|
||||
XorgProto,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
@@ -89,13 +120,186 @@ func init() {
|
||||
Website: "https://gitlab.freedesktop.org/xorg/lib/libxau",
|
||||
|
||||
Dependencies: P{
|
||||
Xproto,
|
||||
XorgProto,
|
||||
},
|
||||
|
||||
ID: 1765,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newXCBProto() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.17.0"
|
||||
checksum = "_NtbKaJ_iyT7XiJz25mXQ7y-niTzE8sHPvLXZPcqtNoV_-vTzqkezJ8Hp2U1enCv"
|
||||
)
|
||||
return t.NewPackage("xcb-proto", version, newTar(
|
||||
"https://xcb.freedesktop.org/dist/xcb-proto-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, (*MakeHelper)(nil),
|
||||
Python,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[XCBProto] = Metadata{
|
||||
f: Toolchain.newXCBProto,
|
||||
|
||||
Name: "xcb-proto",
|
||||
Description: "XML-XCB protocol descriptions used by libxcb for the X11 protocol & extensions",
|
||||
Website: "https://gitlab.freedesktop.org/xorg/proto/xcbproto",
|
||||
|
||||
ID: 13646,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newXCB() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.17.0"
|
||||
checksum = "hjjsc79LpWM_hZjNWbDDS6qRQUXREjjekS6UbUsDq-RR1_AjgNDxhRvZf-1_kzDd"
|
||||
)
|
||||
return t.NewPackage("xcb", version, newTar(
|
||||
"https://xcb.freedesktop.org/dist/libxcb-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, (*MakeHelper)(nil),
|
||||
Python,
|
||||
PkgConfig,
|
||||
|
||||
XCBProto,
|
||||
LibXau,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[XCB] = Metadata{
|
||||
f: Toolchain.newXCB,
|
||||
|
||||
Name: "xcb",
|
||||
Description: "The X protocol C-language Binding",
|
||||
Website: "https://xcb.freedesktop.org/",
|
||||
|
||||
Dependencies: P{
|
||||
XCBProto,
|
||||
LibXau,
|
||||
},
|
||||
|
||||
ID: 1767,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newLibX11() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.8.13"
|
||||
checksum = "ARh-cuZY_U2v3DbPS1byc7ybh9NInZc-yav7SJiusk_C7408s058qWV83ocMd2pT"
|
||||
)
|
||||
return t.NewPackage("libX11", version, newFromGitLab(
|
||||
"gitlab.freedesktop.org",
|
||||
"xorg/lib/libx11",
|
||||
"libX11-"+version,
|
||||
checksum,
|
||||
), nil, &MakeHelper{
|
||||
Generate: "NOCONFIGURE=1 ./autogen.sh",
|
||||
|
||||
Configure: []KV{
|
||||
{"enable-static"},
|
||||
{"without-xmlto"},
|
||||
},
|
||||
},
|
||||
Automake,
|
||||
Libtool,
|
||||
PkgConfig,
|
||||
|
||||
utilMacros,
|
||||
Libxtrans,
|
||||
XorgProto,
|
||||
XCB,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[LibX11] = Metadata{
|
||||
f: Toolchain.newLibX11,
|
||||
|
||||
Name: "libX11",
|
||||
Description: `Core X11 protocol client library (aka "Xlib")`,
|
||||
Website: "https://gitlab.freedesktop.org/xorg/lib/libx11",
|
||||
|
||||
Dependencies: P{
|
||||
XCB,
|
||||
},
|
||||
|
||||
ID: 1764,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newLibXext() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.3.7"
|
||||
checksum = "-0wvUDaucLPLNOrK1pcKhHNoO-5nUqQyyw6JAbhx65gRjuMiNKKaF2_tcrbC_KNq"
|
||||
)
|
||||
return t.NewPackage("libXext", version, newFromGitLab(
|
||||
"gitlab.freedesktop.org",
|
||||
"xorg/lib/libxext",
|
||||
"libXext-"+version,
|
||||
checksum,
|
||||
), nil, &MakeHelper{
|
||||
Generate: "NOCONFIGURE=1 ./autogen.sh",
|
||||
},
|
||||
Automake,
|
||||
Libtool,
|
||||
PkgConfig,
|
||||
|
||||
utilMacros,
|
||||
LibX11,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[LibXext] = Metadata{
|
||||
f: Toolchain.newLibXext,
|
||||
|
||||
Name: "libXext",
|
||||
Description: "Xlib-based library for common extensions to the X11 protocol",
|
||||
Website: "https://gitlab.freedesktop.org/xorg/lib/libxext",
|
||||
|
||||
Dependencies: P{
|
||||
LibX11,
|
||||
},
|
||||
|
||||
ID: 1774,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newLibxshmfence() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.3.3"
|
||||
checksum = "JamExTPg81By2fs3vWdeo_dzlpBQeAwXr2sDXeHJqm9XBoLW5pamiD6FgAWtAKyA"
|
||||
)
|
||||
return t.NewPackage("libxshmfence", version, newFromGitLab(
|
||||
"gitlab.freedesktop.org",
|
||||
"xorg/lib/libxshmfence",
|
||||
"libxshmfence-"+version,
|
||||
checksum,
|
||||
), nil, &MakeHelper{
|
||||
Generate: "NOCONFIGURE=1 ./autogen.sh",
|
||||
},
|
||||
Automake,
|
||||
Libtool,
|
||||
PkgConfig,
|
||||
|
||||
utilMacros,
|
||||
XorgProto,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libxshmfence] = Metadata{
|
||||
f: Toolchain.newLibxshmfence,
|
||||
|
||||
Name: "libxshmfence",
|
||||
Description: "shared memory 'SyncFence' synchronization primitive",
|
||||
Website: "https://gitlab.freedesktop.org/xorg/lib/libxshmfence",
|
||||
|
||||
ID: 1792,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newLibpciaccess() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "0.19"
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newXCBProto() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.17.0"
|
||||
checksum = "_NtbKaJ_iyT7XiJz25mXQ7y-niTzE8sHPvLXZPcqtNoV_-vTzqkezJ8Hp2U1enCv"
|
||||
)
|
||||
return t.NewPackage("xcb-proto", version, newTar(
|
||||
"https://xcb.freedesktop.org/dist/xcb-proto-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, (*MakeHelper)(nil),
|
||||
Python,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[XCBProto] = Metadata{
|
||||
f: Toolchain.newXCBProto,
|
||||
|
||||
Name: "xcb-proto",
|
||||
Description: "XML-XCB protocol descriptions used by libxcb for the X11 protocol & extensions",
|
||||
Website: "https://gitlab.freedesktop.org/xorg/proto/xcbproto",
|
||||
|
||||
ID: 13646,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newXCB() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.17.0"
|
||||
checksum = "hjjsc79LpWM_hZjNWbDDS6qRQUXREjjekS6UbUsDq-RR1_AjgNDxhRvZf-1_kzDd"
|
||||
)
|
||||
return t.NewPackage("xcb", version, newTar(
|
||||
"https://xcb.freedesktop.org/dist/libxcb-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, (*MakeHelper)(nil),
|
||||
Python,
|
||||
PkgConfig,
|
||||
|
||||
XCBProto,
|
||||
LibXau,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[XCB] = Metadata{
|
||||
f: Toolchain.newXCB,
|
||||
|
||||
Name: "xcb",
|
||||
Description: "The X protocol C-language Binding",
|
||||
Website: "https://xcb.freedesktop.org/",
|
||||
|
||||
Dependencies: P{
|
||||
XCBProto,
|
||||
LibXau,
|
||||
},
|
||||
|
||||
ID: 1767,
|
||||
}
|
||||
}
|
||||
@@ -13,9 +13,8 @@ func (t Toolchain) newZlib() (pkg.Artifact, string) {
|
||||
pkg.TarGzip,
|
||||
), nil, &CMakeHelper{
|
||||
Cache: []KV{
|
||||
{"CMAKE_BUILD_TYPE", "Release"},
|
||||
|
||||
{"ZLIB_BUILD_TESTING", "OFF"},
|
||||
{"CMAKE_C_FLAGS", "-fPIC"},
|
||||
{"ZLIB_BUILD_TESTING", "ON"},
|
||||
{"ZLIB_BUILD_SHARED", "ON"},
|
||||
{"ZLIB_BUILD_STATIC", "ON"},
|
||||
{"ZLIB_BUILD_MINIZIP", "OFF"},
|
||||
|
||||
@@ -13,12 +13,20 @@ func (t Toolchain) newZstd() (pkg.Artifact, string) {
|
||||
"zstd-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, &CMakeHelper{
|
||||
), &PackageAttr{
|
||||
// tests Makefile assumes writable source
|
||||
Writable: true,
|
||||
Chmod: true,
|
||||
}, &CMakeHelper{
|
||||
Append: []string{"build", "cmake"},
|
||||
Cache: []KV{
|
||||
{"CMAKE_BUILD_TYPE", "Release"},
|
||||
},
|
||||
}), version
|
||||
Test: `
|
||||
make -C /usr/src/zstd/tests datagen
|
||||
ZSTD_BIN=/cure/programs/zstd /usr/src/zstd/tests/playTests.sh
|
||||
`,
|
||||
},
|
||||
Make,
|
||||
Diffutils,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Zstd] = Metadata{
|
||||
|
||||
@@ -26,7 +26,7 @@ def swaymsg(command: str = "", succeed=True, type="command"):
|
||||
|
||||
|
||||
def check_filter(check_offset, name, pname):
|
||||
pid = int(machine.wait_until_succeeds(f"pgrep -U {10000+check_offset} -x {pname}", timeout=60))
|
||||
pid = int(machine.wait_until_succeeds(f"pgrep -U {10000+check_offset} -x {pname}"))
|
||||
hash = machine.succeed(f"sudo -u alice -i XDG_RUNTIME_DIR=/run/user/1000 WAYLAND_DISPLAY=wayland-1 check-sandbox-{name} hash")
|
||||
print(machine.succeed(f"hakurei-test -s {hash} filter {pid}"))
|
||||
|
||||
@@ -47,7 +47,7 @@ check_filter(0, "pdlike", "cat")
|
||||
|
||||
# Check fd leak:
|
||||
swaymsg("exec exec 127</proc/cmdline && hakurei -v exec sleep infinity")
|
||||
pd_identity0_sleep_pid = int(machine.wait_until_succeeds("pgrep -U 10000 -x sleep", timeout=60))
|
||||
pd_identity0_sleep_pid = int(machine.wait_until_succeeds("pgrep -U 10000 -x sleep"))
|
||||
print(machine.succeed(f"hakurei-test fd {pd_identity0_sleep_pid}"))
|
||||
machine.succeed(f"kill -INT {pd_identity0_sleep_pid}")
|
||||
|
||||
@@ -66,7 +66,7 @@ check_offset = 0
|
||||
def check_sandbox(name):
|
||||
global check_offset
|
||||
swaymsg(f"exec script /dev/null -E always -qec check-sandbox-{name}")
|
||||
machine.wait_for_file(f"/var/tmp/.hakurei-check-ok.{check_offset}", timeout=60)
|
||||
machine.wait_for_file(f"/var/tmp/.hakurei-check-ok.{check_offset}")
|
||||
check_filter(check_offset, name, "hakurei-test")
|
||||
check_offset += 1
|
||||
|
||||
@@ -79,7 +79,7 @@ check_sandbox("device")
|
||||
check_sandbox("pdlike")
|
||||
|
||||
# Exit Sway and verify process exit status 0:
|
||||
machine.wait_until_fails("pgrep -x hakurei", timeout=5)
|
||||
machine.wait_until_fails("pgrep -x hakurei")
|
||||
swaymsg("exit", succeed=False)
|
||||
machine.wait_for_file("/tmp/sway-exit-ok")
|
||||
|
||||
|
||||
52
test/test.py
52
test/test.py
@@ -119,7 +119,7 @@ def hakurei_identity(offset):
|
||||
|
||||
# Start hakurei permissive defaults outside Wayland session:
|
||||
print(machine.succeed("sudo -u alice -i hakurei -v exec -a 0 touch /tmp/pd-bare-ok"))
|
||||
machine.wait_for_file("/tmp/hakurei.0/tmpdir/0/pd-bare-ok", timeout=5)
|
||||
machine.wait_for_file("/tmp/hakurei.0/tmpdir/0/pd-bare-ok")
|
||||
|
||||
# Verify silent output permissive defaults:
|
||||
output = machine.succeed("sudo -u alice -i hakurei exec -a 0 true &>/dev/stdout")
|
||||
@@ -132,11 +132,11 @@ def silent_output_interrupt(flags):
|
||||
wait_for_window("alice@machine")
|
||||
# identity 0 does not have home-manager
|
||||
machine.send_chars(f"exec hakurei exec {flags}-a 0 sh -c 'export PATH=/run/current-system/sw/bin:$PATH && touch /tmp/pd-silent-ready && sleep infinity' &>/tmp/pd-silent\n")
|
||||
machine.wait_for_file("/tmp/hakurei.0/tmpdir/0/pd-silent-ready", timeout=15)
|
||||
machine.wait_for_file("/tmp/hakurei.0/tmpdir/0/pd-silent-ready")
|
||||
machine.succeed("rm /tmp/hakurei.0/tmpdir/0/pd-silent-ready")
|
||||
machine.send_key("ctrl-c")
|
||||
machine.wait_until_fails("pgrep foot", timeout=5)
|
||||
machine.wait_until_fails(f"pgrep -u alice -f 'hakurei exec {flags}-a 0 '", timeout=5)
|
||||
machine.wait_until_fails("pgrep foot")
|
||||
machine.wait_until_fails(f"pgrep -u alice -f 'hakurei exec {flags}-a 0 '")
|
||||
output = machine.succeed("cat /tmp/pd-silent && rm /tmp/pd-silent")
|
||||
if output != "":
|
||||
raise Exception(f"unexpected output\n{output}")
|
||||
@@ -151,7 +151,7 @@ print(machine.fail("sudo -u alice -i hakurei -v exec --wayland true"))
|
||||
|
||||
# Start hakurei permissive defaults within Wayland session:
|
||||
hakurei('-v exec --wayland --dbus --dbus-log notify-send -a "NixOS Tests" "Test notification" "Notification from within sandbox." && touch /tmp/dbus-ok')
|
||||
machine.wait_for_file("/tmp/dbus-ok", timeout=15)
|
||||
machine.wait_for_file("/tmp/dbus-ok")
|
||||
collect_state_ui("dbus_notify_exited")
|
||||
# not in pid namespace, verify termination
|
||||
machine.wait_until_fails("pgrep xdg-dbus-proxy")
|
||||
@@ -165,11 +165,11 @@ hakurei("-v exec --wayland -X --dbus --pulse -u p1 foot && touch /tmp/p1-exit-ok
|
||||
wait_for_window("p1@machine")
|
||||
print(machine.succeed("getfacl --absolute-names --omit-header --numeric /tmp/hakurei.0/runtime | grep 10000"))
|
||||
machine.send_chars("exit\n")
|
||||
machine.wait_for_file("/tmp/p1-exit-ok", timeout=15)
|
||||
machine.wait_for_file("/tmp/p1-exit-ok")
|
||||
# Verify acl is kept alive:
|
||||
print(machine.succeed("getfacl --absolute-names --omit-header --numeric /tmp/hakurei.0/runtime | grep 10000"))
|
||||
machine.send_chars("exit\n")
|
||||
machine.wait_for_file("/tmp/p0-exit-ok", timeout=15)
|
||||
machine.wait_for_file("/tmp/p0-exit-ok")
|
||||
machine.fail("getfacl --absolute-names --omit-header --numeric /tmp/hakurei.0/runtime | grep 10000")
|
||||
|
||||
# Check invalid identifier fd behaviour:
|
||||
@@ -181,7 +181,7 @@ print(machine.succeed('grep "^hakurei: cannot write identifier: bad file descrip
|
||||
swaymsg("exec sh -c 'ne-foot; echo -n $? > /tmp/monitor-exit-code'")
|
||||
wait_for_window(f"u0_a{hakurei_identity(0)}@machine")
|
||||
machine.succeed("pkill -INT -f 'hakurei -v run '")
|
||||
machine.wait_until_fails("pgrep foot", timeout=5)
|
||||
machine.wait_until_fails("pgrep foot")
|
||||
machine.wait_for_file("/tmp/monitor-exit-code")
|
||||
interrupt_exit_code = int(machine.succeed("cat /tmp/monitor-exit-code"))
|
||||
if interrupt_exit_code != 230:
|
||||
@@ -191,7 +191,7 @@ if interrupt_exit_code != 230:
|
||||
swaymsg("exec sh -c 'ne-foot-immediate; echo -n $? > /tmp/monitor-exit-code'")
|
||||
wait_for_window(f"u0_a{hakurei_identity(0)}@machine")
|
||||
machine.succeed("pkill -INT -f 'hakurei -v run '")
|
||||
machine.wait_until_fails("pgrep foot", timeout=5)
|
||||
machine.wait_until_fails("pgrep foot")
|
||||
machine.wait_for_file("/tmp/monitor-exit-code")
|
||||
interrupt_exit_code = int(machine.succeed("cat /tmp/monitor-exit-code"))
|
||||
if interrupt_exit_code != 254:
|
||||
@@ -202,7 +202,7 @@ swaymsg("exec sh -c 'ne-foot &> /tmp/shim-cont-unexpected-pid'")
|
||||
wait_for_window(f"u0_a{hakurei_identity(0)}@machine")
|
||||
machine.succeed("pkill -CONT -f 'hakurei shim'")
|
||||
machine.succeed("pkill -INT -f 'hakurei -v run '")
|
||||
machine.wait_until_fails("pgrep foot", timeout=5)
|
||||
machine.wait_until_fails("pgrep foot")
|
||||
machine.wait_for_file("/tmp/shim-cont-unexpected-pid")
|
||||
print(machine.succeed('grep "shim: got SIGCONT from unexpected process$" /tmp/shim-cont-unexpected-pid'))
|
||||
|
||||
@@ -221,26 +221,26 @@ if sched_rr != 2:
|
||||
swaymsg("exec ne-foot")
|
||||
wait_for_window(f"u0_a{hakurei_identity(0)}@machine")
|
||||
machine.send_chars("clear; wayland-info && touch /var/tmp/client-ok\n")
|
||||
machine.wait_for_file("/var/tmp/client-ok", timeout=15)
|
||||
machine.wait_for_file("/var/tmp/client-ok")
|
||||
collect_state_ui("foot_wayland")
|
||||
check_state("ne-foot", {"wayland": True})
|
||||
# Verify lack of acl on XDG_RUNTIME_DIR:
|
||||
machine.fail(f"getfacl --absolute-names --omit-header --numeric /run/user/1000 | grep {hakurei_identity(0) + 10000}")
|
||||
machine.send_chars("exit\n")
|
||||
machine.wait_until_fails("pgrep foot", timeout=5)
|
||||
machine.fail(f"getfacl --absolute-names --omit-header --numeric /run/user/1000 | grep {hakurei_identity(0) + 10000}", timeout=5)
|
||||
machine.wait_until_fails("pgrep foot")
|
||||
machine.fail(f"getfacl --absolute-names --omit-header --numeric /run/user/1000 | grep {hakurei_identity(0) + 10000}")
|
||||
|
||||
# Test pipewire-pulse:
|
||||
swaymsg("exec pa-foot")
|
||||
wait_for_window(f"u0_a{hakurei_identity(1)}@machine")
|
||||
machine.send_chars("clear; pactl info && touch /var/tmp/pulse-ok\n")
|
||||
machine.wait_for_file("/var/tmp/pulse-ok", timeout=15)
|
||||
machine.wait_for_file("/var/tmp/pulse-ok")
|
||||
collect_state_ui("pulse_wayland")
|
||||
check_state("pa-foot", {"wayland": True, "pipewire": True})
|
||||
machine.fail("find /tmp -maxdepth 1 -type d -name '.hakurei-shim-*' -print -exec false '{}' +")
|
||||
machine.send_chars("exit\n")
|
||||
machine.wait_until_fails("pgrep foot", timeout=5)
|
||||
machine.wait_until_fails("pgrep -x hakurei", timeout=5)
|
||||
machine.wait_until_fails("pgrep foot")
|
||||
machine.wait_until_fails("pgrep -x hakurei")
|
||||
machine.succeed("find /tmp -maxdepth 1 -type d -name '.hakurei-shim-*' -print -exec false '{}' +")
|
||||
# Test PipeWire SecurityContext:
|
||||
machine.succeed("sudo -u alice -i XDG_RUNTIME_DIR=/run/user/1000 hakurei -v exec --pulse pactl info")
|
||||
@@ -253,25 +253,25 @@ machine.fail("sudo -u alice -i XDG_RUNTIME_DIR=/run/user/1000 hakurei -v exec --
|
||||
swaymsg("exec x11-alacritty")
|
||||
wait_for_window(f"u0_a{hakurei_identity(0)}@machine")
|
||||
machine.send_chars("clear; glinfo && touch /var/tmp/x11-ok\n")
|
||||
machine.wait_for_file("/var/tmp/x11-ok", timeout=15)
|
||||
machine.wait_for_file("/var/tmp/x11-ok")
|
||||
collect_state_ui("alacritty_x11")
|
||||
check_state("x11-alacritty", {"x11": True})
|
||||
machine.send_chars("exit\n")
|
||||
machine.wait_until_fails("pgrep alacritty", timeout=5)
|
||||
machine.wait_until_fails("pgrep alacritty")
|
||||
|
||||
# Start app (foot) with direct Wayland access:
|
||||
swaymsg("exec da-foot")
|
||||
wait_for_window(f"u0_a{hakurei_identity(3)}@machine")
|
||||
machine.send_chars("clear; wayland-info && touch /var/tmp/direct-ok\n")
|
||||
collect_state_ui("foot_direct")
|
||||
machine.wait_for_file("/var/tmp/direct-ok", timeout=15)
|
||||
machine.wait_for_file("/var/tmp/direct-ok")
|
||||
check_state("da-foot", {"wayland": True})
|
||||
# Verify acl on XDG_RUNTIME_DIR:
|
||||
print(machine.succeed(f"getfacl --absolute-names --omit-header --numeric /run/user/1000 | grep {hakurei_identity(3) + 10000}"))
|
||||
machine.send_chars("exit\n")
|
||||
machine.wait_until_fails("pgrep foot", timeout=5)
|
||||
machine.wait_until_fails("pgrep foot")
|
||||
# Verify acl cleanup on XDG_RUNTIME_DIR:
|
||||
machine.wait_until_fails(f"getfacl --absolute-names --omit-header --numeric /run/user/1000 | grep {hakurei_identity(3) + 10000}", timeout=5)
|
||||
machine.wait_until_fails(f"getfacl --absolute-names --omit-header --numeric /run/user/1000 | grep {hakurei_identity(3) + 10000}")
|
||||
|
||||
# Test syscall filter:
|
||||
print(machine.fail("sudo -u alice -i XDG_RUNTIME_DIR=/run/user/1000 strace-failure"))
|
||||
@@ -280,20 +280,20 @@ print(machine.fail("sudo -u alice -i XDG_RUNTIME_DIR=/run/user/1000 strace-failu
|
||||
swaymsg("exec foot $SHELL -c '(ne-foot) & disown && exec $SHELL'")
|
||||
wait_for_window(f"u0_a{hakurei_identity(0)}@machine")
|
||||
machine.send_chars("clear; wayland-info && touch /var/tmp/term-ok\n")
|
||||
machine.wait_for_file("/var/tmp/term-ok", timeout=15)
|
||||
machine.wait_for_file("/var/tmp/term-ok")
|
||||
machine.send_key("alt-h")
|
||||
machine.send_chars("clear; hakurei show $(hakurei ps --short) && touch /tmp/ps-show-ok && exec cat\n")
|
||||
machine.wait_for_file("/tmp/ps-show-ok", timeout=5)
|
||||
machine.wait_for_file("/tmp/ps-show-ok")
|
||||
collect_state_ui("foot_wayland_term")
|
||||
check_state("ne-foot", {"wayland": True})
|
||||
machine.send_key("alt-l")
|
||||
machine.send_chars("exit\n")
|
||||
wait_for_window("alice@machine")
|
||||
machine.send_key("ctrl-c")
|
||||
machine.wait_until_fails("pgrep foot", timeout=5)
|
||||
machine.wait_until_fails("pgrep foot")
|
||||
|
||||
# Exit Sway and verify process exit status 0:
|
||||
machine.wait_until_fails("pgrep -x hakurei", timeout=5)
|
||||
machine.wait_until_fails("pgrep -x hakurei")
|
||||
swaymsg("exit", succeed=False)
|
||||
machine.wait_for_file("/tmp/sway-exit-ok")
|
||||
|
||||
@@ -308,4 +308,4 @@ machine.succeed("find /tmp -maxdepth 1 -type d -name '.hakurei-shim-*' -print -e
|
||||
# Verify go test status:
|
||||
machine.wait_for_file("/tmp/hakurei-test-done")
|
||||
print(machine.succeed("cat /tmp/hakurei-test.log"))
|
||||
machine.wait_for_file("/tmp/hakurei-test-ok", timeout=2)
|
||||
machine.wait_for_file("/tmp/hakurei-test-ok")
|
||||
|
||||
Reference in New Issue
Block a user