1
0
forked from rosa/hakurei

13 Commits

Author SHA1 Message Date
kat
a451cc2dbf TODO: docs 2026-05-16 01:12:09 +10:00
kat
4065d96d38 TODO: consider writing tests for the test runner. 2026-05-16 01:12:09 +10:00
kat
92f2111aed TODO: actually write tests lol. 2026-05-16 01:12:09 +10:00
kat
48e5de9d86 TODO: auto-load test files based on name, just like go (see long desc)
squash this into the commit that first added all_tests.ts, we don't even
want to have a trace of it left

for the cli ones, we can simply iterate the filesystem relative our
location. for the web one, we determine it on launch and expose it as an
endpoint from the server which the client queries
2026-05-16 01:12:09 +10:00
kat
3a50868e12 TODO: limited selective execution from cli (see long desc)
well the problem with arbitrary selection is that... you need to do lots
of matching, which is confusing too when you need to encode nesting. so
what if just.. node cli.js index_test.js?

this isn't concerned with reporters or execution, this happens at the
cli level and it solely affects which modules are imported instead of
just all_tests.js.

alternatively, we could do suites instead of files. this is probably
better huh because you don't need to type out all those file paths, and
it doesn't punish large files (because a test file corresponds to
a source code file)

so we'd just import all_tests.js, then just filter out suites whose name
doesn't match <input>, before calling `run` on it. deleting and
filtering out suites should probably be methods on the registrar

i suspect the impl will be tiny excl argument parser nonsense, so imo
squash this into the commit that added registrars

add a comment describing the use-case as “just run the tests i'm editing
to save time”, rather than as skipping, then briefly mention why general
purpose skipping is still a tentative future feature
2026-05-16 01:12:09 +10:00
kat
beeba66efe TODO: display elapsed time (see long description)
both on a test level and for the whole thing. i think the reporter or
registrar abstractions should deal with all timeouts, and just feed
elapsed time through all the functions: update() gets time for the
specific test, and finalize passes you the total time. this way you
don't need to do the same logic in every reporter, and you also give
a suggestion to reporter writers (i.e.: you in the future) to expose
test durations. actually tbh per-test isn't possible anywhere but in the
executor, especially when taking potential future parallel execution
into account

on the topic of parallelism: per-test is wall clock for that test,
regardless of perceived time, because no other number is useful. whole
thing is wall clock too, not cpu time

remember:
  - use monotonic clocks!! we need elapsed time, not absolute time
  - format them to more readable strings like “15h 12m” instead of
    “54738 seconds”. once things get large we can be less precise

for the go reporter: ask ozy if the go one already measures it. if so
then don't even bother serializing it

for the stream reporter: the live feed should include per-test time in
brackets or something. the final tree should only include timeout for
outliers on the long side (just shove a box plot-esque algo on it), and
if a flag is given print it for all nodes, and if another flag is given
print the n longest tests. the total time should be in the summary line
at the end in brackets à la pytest

for the dom reporter, we do the same as with the stream reporter's
outlier detection, and have a checkbox or button to dynamically
show/hide all timeouts, and another button to toggle a widget of sorts
that shows up right above the result tree which includes the n longest
tests. all these buttons should be on the same line as the summary
(successes/failures/skips). the total time should be included in the
“execution finished” text form the previous commit, i.e. “execution
finished in 15s”
2026-05-16 01:12:09 +10:00
kat
81be70f921 TODO: display text execution progress (see long description)
since the test tree is statically known, we also statically know how
many tests are present. we should hence be using this to provide
a counter, say [1/48], to give a rough estimate as to when tests might
finish. not a time estimate of course, since we can't determine that

nota bene, we can't pass the current test count, and instead need to let
the reporter deal with that, since otherwise we can't easily parallelize
execution in the future. definitely mention this in a comment somewhere
to elaborate on the design

for the go reporter, ask ozy if go has any way to tell it this info.
i doubt it since they don't have a statically known test count. if it
does, then just send the count alongside the tree

for the stream reporter, ignore it entirely; we don't even display
successes by default so the number has nowhere to be attached to

for the dom reporter, put it somewhere in the header, i think alongside
the success/failure/skip count. something like “in progress (4/28)”.
then once finalize() is called change the whole thing to “execution
finished”
2026-05-16 01:12:09 +10:00
kat
7ede68293e cmd/mbf: jstest: implement skipping from within the DSL 2026-05-16 01:12:09 +10:00
kat
f28265062d cmd/mbf: jstest: add JSON reporter for go test integration 2026-05-16 00:46:43 +10:00
kat
178748dd75 cmd/mbf: jstest: implement DSL and runner 2026-05-16 00:46:43 +10:00
kat
4d6a30dba1 cmd/mbf: jstest: add DOM reporter 2026-05-16 00:46:43 +10:00
kat
4c9043cb0c cmd/mbf: jstest: add basic CLI reporter 2026-05-16 00:46:43 +10:00
kat
cb4b2706c0 cmd/mbf: bring back pkgserver's favicon!
It existed in mae's #33, but ozy seems to have lost it during her
changes pre-merge, so just add it back again.

This favicon image was grabbed from mae:
8a38b614c6/cmd/pkgserver/ui/static/favicon.ico
That commit is the latest one of the salvaged original #33 history; see
rosa/hakurei#33 (comment).
2026-05-15 21:05:26 +10:00
121 changed files with 2081 additions and 2481 deletions

View File

@@ -6,7 +6,6 @@ import (
"io"
"os"
"strings"
"unique"
"hakurei.app/internal/pkg"
"hakurei.app/internal/rosa"
@@ -36,20 +35,17 @@ func commandInfo(
}
}
t := rosa.Native().Std()
for i, name := range args {
handle := rosa.ArtifactH(unique.Make(name))
if meta := rosa.Native().Get(handle); meta == nil {
if p, ok := rosa.ResolveName(name); !ok {
return fmt.Errorf("unknown artifact %q", name)
} else {
var suffix string
a, version := t.MustLoad(handle)
if version != rosa.Unversioned {
if version := rosa.Std.Version(p); version != rosa.Unversioned {
suffix += "-" + version
}
mustPrintln("name : " + name + suffix)
meta := rosa.GetMetadata(p)
mustPrintln("description : " + meta.Description)
if meta.Website != "" {
mustPrintln("website : " +
@@ -58,9 +54,9 @@ func commandInfo(
if len(meta.Dependencies) > 0 {
mustPrint("depends on :")
for _, d := range meta.Dependencies {
s := rosa.Native().MustGet(d).Name
if _, _version := t.Load(d); _version != rosa.Unversioned {
s += "-" + _version
s := rosa.GetMetadata(d).Name
if version := rosa.Std.Version(d); version != rosa.Unversioned {
s += "-" + version
}
mustPrint(" " + s)
}
@@ -72,7 +68,7 @@ func commandInfo(
if r == nil {
var f io.ReadSeekCloser
err = cm.Do(func(cache *pkg.Cache) (err error) {
f, err = cache.OpenStatus(a)
f, err = cache.OpenStatus(rosa.Std.Load(p))
return
})
if err != nil {
@@ -91,7 +87,7 @@ func commandInfo(
}
}
} else if err = cm.Do(func(cache *pkg.Cache) (err error) {
status, n := r.ArtifactOf(cache.Ident(a))
status, n := r.ArtifactOf(cache.Ident(rosa.Std.Load(p)))
if status == nil {
mustPrintln(
statusPrefix + "not in report",

View File

@@ -10,7 +10,6 @@ import (
"strings"
"syscall"
"testing"
"unique"
"unsafe"
"hakurei.app/internal/pkg"
@@ -21,14 +20,6 @@ import (
func TestInfo(t *testing.T) {
t.Parallel()
_t := rosa.Native().Std()
_, qemuVersion := _t.Load(rosa.QEMU)
_, glibVersion := _t.Load(rosa.GLib)
zlib, zlibVersion := _t.Load(rosa.Zlib)
_, zstdVersion := _t.Load(rosa.Zstd)
_, hakureiVersion := _t.Load(rosa.Hakurei)
_, hakureiDistVersion := _t.Load(rosa.HakureiDist)
testCases := []struct {
name string
args []string
@@ -38,24 +29,24 @@ func TestInfo(t *testing.T) {
wantErr any
}{
{"qemu", []string{"qemu"}, nil, "", `
name : qemu-` + qemuVersion + `
name : qemu-` + rosa.Std.Version(rosa.QEMU) + `
description : a generic and open source machine emulator and virtualizer
website : https://www.qemu.org
depends on : glib-` + glibVersion + ` zstd-` + zstdVersion + `
depends on : glib-` + rosa.Std.Version(rosa.GLib) + ` zstd-` + rosa.Std.Version(rosa.Zstd) + `
`, nil},
{"multi", []string{"hakurei", "hakurei-dist"}, nil, "", `
name : hakurei-` + hakureiVersion + `
name : hakurei-` + rosa.Std.Version(rosa.Hakurei) + `
description : low-level userspace tooling for Rosa OS
website : https://hakurei.app
name : hakurei-dist-` + hakureiDistVersion + `
name : hakurei-dist-` + rosa.Std.Version(rosa.HakureiDist) + `
description : low-level userspace tooling for Rosa OS (distribution tarball)
website : https://hakurei.app
`, nil},
{"nonexistent", []string{"zlib", "\x00"}, nil, "", `
name : zlib-` + zlibVersion + `
name : zlib-` + rosa.Std.Version(rosa.Zlib) + `
description : lossless data-compression library
website : https://zlib.net
@@ -65,12 +56,12 @@ website : https://zlib.net
"zstd": "internal/pkg (amd64) on satori\n",
"hakurei": "internal/pkg (amd64) on satori\n\n",
}, "", `
name : zlib-` + zlibVersion + `
name : zlib-` + rosa.Std.Version(rosa.Zlib) + `
description : lossless data-compression library
website : https://zlib.net
status : not yet cured
name : zstd-` + zstdVersion + `
name : zstd-` + rosa.Std.Version(rosa.Zstd) + `
description : a fast compression algorithm
website : https://facebook.github.io/zstd
status : internal/pkg (amd64) on satori
@@ -79,19 +70,19 @@ status : internal/pkg (amd64) on satori
{"status cache perm", []string{"zlib"}, map[string]string{
"zlib": "\x00",
}, "", `
name : zlib-` + zlibVersion + `
name : zlib-` + rosa.Std.Version(rosa.Zlib) + `
description : lossless data-compression library
website : https://zlib.net
`, func(cm *cache) error {
return &os.PathError{
Op: "open",
Path: filepath.Join(cm.base, "status", pkg.Encode(cm.c.Ident(zlib).Value())),
Path: filepath.Join(cm.base, "status", pkg.Encode(cm.c.Ident(rosa.Std.Load(rosa.Zlib)).Value())),
Err: syscall.EACCES,
}
}},
{"status report", []string{"zlib"}, nil, strings.Repeat("\x00", len(pkg.Checksum{})+8), `
name : zlib-` + zlibVersion + `
name : zlib-` + rosa.Std.Version(rosa.Zlib) + `
description : lossless data-compression library
website : https://zlib.net
status : not in report
@@ -140,8 +131,8 @@ status : not in report
if tc.status != nil {
for name, status := range tc.status {
a, _ := _t.Load(rosa.ArtifactH(unique.Make(name)))
if a == nil {
p, ok := rosa.ResolveName(name)
if !ok {
t.Fatalf("invalid name %q", name)
}
perm := os.FileMode(0400)
@@ -152,7 +143,7 @@ status : not in report
return os.WriteFile(filepath.Join(
cm.base,
"status",
pkg.Encode(cache.Ident(a).Value()),
pkg.Encode(cache.Ident(rosa.Std.Load(p)).Value()),
), unsafe.Slice(unsafe.StringData(status), len(status)), perm)
}); err != nil {
t.Fatalf("Do: error = %v", err)

View File

@@ -30,7 +30,7 @@ var (
// handleInfo writes constant system information.
func handleInfo(w http.ResponseWriter, _ *http.Request) {
infoPayloadOnce.Do(func() {
infoPayload.Count = int(rosa.Native().Count())
infoPayload.Count = int(rosa.PresetUnexportedStart)
infoPayload.HakureiVersion = info.Version()
})
// TODO(mae): cache entire response if no additional fields are planned
@@ -91,7 +91,7 @@ func (index *packageIndex) handleGet(w http.ResponseWriter, r *http.Request) {
if err != nil || i >= len(index.sorts[0]) || i < 0 {
http.Error(
w, "index must be an integer between 0 and "+
strconv.Itoa(len(index.sorts[0])-1),
strconv.Itoa(int(rosa.PresetUnexportedStart-1)),
http.StatusBadRequest,
)
return
@@ -125,7 +125,7 @@ func (index *packageIndex) handleSearch(w http.ResponseWriter, r *http.Request)
if err != nil || i >= len(index.sorts[0]) || i < 0 {
http.Error(
w, "index must be an integer between 0 and "+
strconv.Itoa(len(index.sorts[0])-1),
strconv.Itoa(int(rosa.PresetUnexportedStart-1)),
http.StatusBadRequest,
)
return

View File

@@ -3,6 +3,7 @@ package pkgserver
import (
"net/http"
"net/http/httptest"
"slices"
"strconv"
"testing"
@@ -31,7 +32,7 @@ func TestAPIInfo(t *testing.T) {
checkPayload(t, resp, struct {
Count int `json:"count"`
HakureiVersion string `json:"hakurei_version"`
}{rosa.Native().Count(), info.Version()})
}{int(rosa.PresetUnexportedStart), info.Version()})
}
func TestAPIGet(t *testing.T) {
@@ -95,8 +96,8 @@ func TestAPIGet(t *testing.T) {
t.Run("index", func(t *testing.T) {
t.Parallel()
checkValidate(
t, "limit=1&sort=0&index", 0, rosa.Native().Count()-1,
"index must be an integer between 0 and "+strconv.Itoa(rosa.Native().Count()-1),
t, "limit=1&sort=0&index", 0, int(rosa.PresetUnexportedStart-1),
"index must be an integer between 0 and "+strconv.Itoa(int(rosa.PresetUnexportedStart-1)),
)
})
@@ -107,4 +108,74 @@ func TestAPIGet(t *testing.T) {
"sort must be an integer between 0 and "+strconv.Itoa(int(sortOrderEnd)),
)
})
checkWithSuffix := func(name, suffix string, want []*metadata) {
t.Run(name, func(t *testing.T) {
t.Parallel()
w := newRequest(suffix)
resp := w.Result()
checkStatus(t, resp, http.StatusOK)
checkAPIHeader(t, w.Header())
checkPayloadFunc(t, resp, func(got *struct {
Values []*metadata `json:"values"`
}) bool {
return slices.EqualFunc(got.Values, want, func(a, b *metadata) bool {
return (a.Version == b.Version ||
a.Version == rosa.Unversioned ||
b.Version == rosa.Unversioned) &&
a.HasReport == b.HasReport &&
a.Name == b.Name &&
a.Description == b.Description &&
a.Website == b.Website
})
})
})
}
checkWithSuffix("declarationAscending", "?limit=2&index=1&sort=0", []*metadata{
{
Metadata: rosa.GetMetadata(1),
Version: rosa.Std.Version(1),
},
{
Metadata: rosa.GetMetadata(2),
Version: rosa.Std.Version(2),
},
})
checkWithSuffix("declarationAscending offset", "?limit=3&index=5&sort=0", []*metadata{
{
Metadata: rosa.GetMetadata(5),
Version: rosa.Std.Version(5),
},
{
Metadata: rosa.GetMetadata(6),
Version: rosa.Std.Version(6),
},
{
Metadata: rosa.GetMetadata(7),
Version: rosa.Std.Version(7),
},
})
checkWithSuffix("declarationDescending", "?limit=3&index=0&sort=1", []*metadata{
{
Metadata: rosa.GetMetadata(rosa.PresetUnexportedStart - 1),
Version: rosa.Std.Version(rosa.PresetUnexportedStart - 1),
},
{
Metadata: rosa.GetMetadata(rosa.PresetUnexportedStart - 2),
Version: rosa.Std.Version(rosa.PresetUnexportedStart - 2),
},
{
Metadata: rosa.GetMetadata(rosa.PresetUnexportedStart - 3),
Version: rosa.Std.Version(rosa.PresetUnexportedStart - 3),
},
})
checkWithSuffix("declarationDescending offset", "?limit=1&index=37&sort=1", []*metadata{
{
Metadata: rosa.GetMetadata(rosa.PresetUnexportedStart - 38),
Version: rosa.Std.Version(rosa.PresetUnexportedStart - 38),
},
})
}

View File

@@ -23,7 +23,7 @@ const (
// packageIndex refers to metadata by name and various sort orders.
type packageIndex struct {
sorts [sortOrderEnd + 1][]*metadata
sorts [sortOrderEnd + 1][rosa.PresetUnexportedStart]*metadata
names map[string]*metadata
search searchCache
// Taken from [rosa.Report] if available.
@@ -32,8 +32,8 @@ type packageIndex struct {
// metadata holds [rosa.Metadata] extended with additional information.
type metadata struct {
handle rosa.ArtifactH
*rosa.Artifact
p rosa.PArtifact
*rosa.Metadata
// Populated via [rosa.Toolchain.Version], [rosa.Unversioned] is equivalent
// to the zero value. Otherwise, the zero value is invalid.
@@ -56,17 +56,15 @@ func (index *packageIndex) populate(report *rosa.Report) (err error) {
index.handleAccess = report.HandleAccess
}
handles := rosa.Native().Collect()
work := make([]*metadata, len(handles))
var work [rosa.PresetUnexportedStart]*metadata
index.names = make(map[string]*metadata)
ir := pkg.NewIR()
for i, handle := range handles {
a, version := rosa.Native().Std().MustLoad(handle)
for p := range rosa.PresetUnexportedStart {
m := metadata{
handle: handle,
p: p,
Artifact: rosa.Native().MustGet(handle),
Version: version,
Metadata: rosa.GetMetadata(p),
Version: rosa.Std.Version(p),
}
if m.Version == "" {
return errors.New("invalid version from " + m.Name)
@@ -76,32 +74,32 @@ func (index *packageIndex) populate(report *rosa.Report) (err error) {
}
if report != nil {
id := ir.Ident(a)
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
}
work[i] = &m
work[p] = &m
index.names[m.Name] = &m
}
index.sorts[declarationAscending] = work
index.sorts[declarationDescending] = slices.Clone(work)
index.sorts[declarationDescending] = work
slices.Reverse(index.sorts[declarationDescending][:])
index.sorts[nameAscending] = slices.Clone(work)
index.sorts[nameAscending] = work
slices.SortFunc(index.sorts[nameAscending][:], func(a, b *metadata) int {
return strings.Compare(a.Name, b.Name)
})
index.sorts[nameDescending] = slices.Clone(index.sorts[nameAscending])
index.sorts[nameDescending] = index.sorts[nameAscending]
slices.Reverse(index.sorts[nameDescending][:])
index.sorts[sizeAscending] = slices.Clone(work)
index.sorts[sizeAscending] = work
slices.SortFunc(index.sorts[sizeAscending][:], func(a, b *metadata) int {
return cmp.Compare(a.Size, b.Size)
})
index.sorts[sizeDescending] = slices.Clone(index.sorts[sizeAscending])
index.sorts[sizeDescending] = index.sorts[sizeAscending]
slices.Reverse(index.sorts[sizeDescending][:])
return

View File

@@ -0,0 +1,2 @@
// Import all test files to register their test suites.
import "./index_test.js";

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -4,12 +4,11 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<link rel="icon" href="https://hakurei.app/favicon.ico"/>
<title>Rosa OS Packages</title>
<title>Hakurei PkgServer</title>
<script src="index.js"></script>
</head>
<body>
<h1>Rosa OS Packages</h1>
<h1>Hakurei PkgServer</h1>
<div class="top-controls" id="top-controls-regular">
<p>Showing entries <span id="entry-counter"></span>.</p>
<span id="search-bar">
@@ -55,4 +54,4 @@
</footer>
<script>main();</script>
</body>
</html>
</html>

View File

@@ -0,0 +1,2 @@
import { suite, test } from "./jstest/jstest.js";
import "./index.js";

View File

@@ -0,0 +1,48 @@
#!/usr/bin/env node
// Many editors have terminal emulators built in, so running tests with NodeJS
// provides faster iteration, especially for those acclimated to test-driven
// development.
import "../all_tests.js";
import { StreamReporter, GLOBAL_REGISTRAR } from "./jstest.js";
// TypeScript doesn't like process and Deno as their type definitions aren't
// installed, but doesn't seem to complain if they're accessed through
// globalThis.
const process: any = (globalThis as any).process;
const Deno: any = (globalThis as any).Deno;
function getArgs(): string[] {
if (process) {
const [runtime, program, ...args] = process.argv;
return args;
}
if (Deno) return Deno.args;
return [];
}
function exit(code?: number): never {
if (Deno) Deno.exit(code);
if (process) process.exit(code);
throw `exited with code ${code ?? 0}`;
}
const args = getArgs();
let verbose = false;
if (args.length > 1) {
console.error("Too many arguments");
exit(1);
}
if (args.length === 1) {
if (args[0] === "-v" || args[0] === "--verbose" || args[0] === "-verbose") {
verbose = true;
} else if (args[0] !== "--") {
console.error(`Unknown argument '${args[0]}'`);
exit(1);
}
}
let reporter = new StreamReporter({ writeln: console.log }, verbose);
GLOBAL_REGISTRAR.run(reporter);
exit(reporter.succeeded() ? 0 : 1);

View File

@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<!-- See failure-open.svg for an explanation of the view box dimensions. -->
<svg xmlns="http://www.w3.org/2000/svg" width="20" viewBox="-20,-20 160 130">
<!-- This triangle should match success-closed.svg, fill and stroke color notwithstanding. -->
<polygon points="0,0 100,50 0,100" fill="red" stroke="red" stroke-width="15" stroke-linejoin="round"/>
<!--
! y-coordinates go before x-coordinates here to highlight the difference
! (or, lack thereof) between these numbers and the ones in failure-open.svg;
! try a textual diff. Make sure to keep the numbers in sync!
-->
<line y1="30" x1="10" y2="70" x2="50" stroke="white" stroke-width="16"/>
<line y1="30" x1="50" y2="70" x2="10" stroke="white" stroke-width="16"/>
</svg>

After

Width:  |  Height:  |  Size: 788 B

View File

@@ -0,0 +1,35 @@
<?xml version="1.0"?>
<!--
! This view box is a bit weird: the strokes assume they're working in a view
! box that spans from the (0,0) to (100,100), and indeed that is convenient
! conceptualizing the strokes, but the stroke itself has a considerable width
! that gets clipped by restrictive view box dimensions. Hence, the view is
! shifted from (0,0)(100,100) to (-20,-20)(120,120), to make room for the
! clipped stroke, while leaving behind an illusion of working in a view box
! spanning from (0,0) to (100,100).
!
! However, the resulting SVG is too close to the summary text, and CSS
! properties to add padding do not seem to work with `content:` (likely because
! they're anonymous replaced elements); thus, the width of the view is
! increased considerably to provide padding in the SVG itself, while leaving
! the strokes oblivious.
!
! It gets worse: the summary text isn't vertically aligned with the icon! As
! a flexbox cannot be used in a summary to align the marker with the text, the
! simplest and most effective solution is to reduce the height of the view box
! from 140 to 130, thereby removing some of the bottom padding present.
!
! All six SVGs use the same view box (and indeed, they refer to this comment)
! so that they all appear to be the same size and position relative to each
! other on the DOM—indeed, the view box dimensions, alongside the width,
! directly control their placement on the DOM.
!
! TL;DR: CSS is janky, overflow is weird, and SVG is awesome!
-->
<svg xmlns="http://www.w3.org/2000/svg" width="20" viewBox="-20,-20 160 130">
<!-- This triangle should match success-open.svg, fill and stroke color notwithstanding. -->
<polygon points="0,0 100,0 50,100" fill="red" stroke="red" stroke-width="15" stroke-linejoin="round"/>
<!-- See the comment in failure-closed.svg before modifying this. -->
<line x1="30" y1="10" x2="70" y2="50" stroke="white" stroke-width="16"/>
<line x1="30" y1="50" x2="70" y2="10" stroke="white" stroke-width="16"/>
</svg>

View File

@@ -0,0 +1,3 @@
import "../all_tests.js";
import { GoTestReporter, GLOBAL_REGISTRAR } from "./jstest.js";
GLOBAL_REGISTRAR.run(new GoTestReporter());

View File

@@ -0,0 +1,39 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./style.css">
<title>PkgServer Tests</title>
</head>
<body>
<noscript>
I hate JavaScript as much as you, but this page runs tests written in
JavaScript to test the functionality of code written in JavaScript, so it
wouldn't make sense for it to work without JavaScript. <strong>Please turn
JavaScript on!</strong>
</noscript>
<h1>PkgServer Tests</h1>
<main>
<p id="counters">
<span id="success-counter">0</span> succeeded, <span id="failure-counter">0</span>
failed<span id="skip-counter-text" hidden>, <span id="skip-counter">0</span> skipped</span>.
</p>
<p hidden id="success-description">Successful test</p>
<p hidden id="failure-description">Failed test</p>
<p hidden id="skip-description">Partially or fully skipped test</p>
<div id="root">
</div>
<script type="module">
import "../all_tests.js";
import { DOMReporter, GLOBAL_REGISTRAR } from "./jstest.js";
GLOBAL_REGISTRAR.run(new DOMReporter());
</script>
</main>
</body>
</html>

View File

@@ -0,0 +1,464 @@
// =============================================================================
// DSL
type TestTree = TestGroup | Test;
type TestGroup = { name: string; children: TestTree[] };
type Test = { name: string; test: (t: TestController) => void };
// A registrar provides a central location to register test suites.
export class TestRegistrar {
// Note that, while this is equivalent to a new tree node sans a name, the
// lack of a name provides the illusion of multiple “top-level” suites,
// while still allowing reporters to pick their favorite name—say, “JS
// tests”—were they to need to label all suites together.
#suites: TestGroup[];
constructor() {
this.#suites = [];
}
suite(name: string, children: TestTree[]) {
checkDuplicates(name, children);
this.#suites.push({ name, children });
}
run(reporter: Reporter) {
reporter.register(this.#suites);
for (const suite of this.#suites) {
for (const c of suite.children) runTests(reporter, [suite.name], c);
}
reporter.finalize();
}
}
export let GLOBAL_REGISTRAR = new TestRegistrar();
// Register a suite in the global registrar.
export function suite(name: string, children: TestTree[]) {
GLOBAL_REGISTRAR.suite(name, children);
}
export function group(name: string, children: TestTree[]): TestTree {
checkDuplicates(name, children);
return { name, children };
}
export const context = group;
export const describe = group;
export function test(name: string, test: (t: TestController) => void): TestTree {
return { name, test };
}
// While this function could certainly refine the type to a map instead of
// simply checking for duplicates and discarding that knowledge, these test
// trees are primarily for flooding—that is, iteration—for which an array is
// better suited.
function checkDuplicates(parent: string, names: { name: string }[]) {
let seen = new Set<string>();
for (const { name } of names) {
if (seen.has(name)) {
throw new RangeError(`duplicate name '${name}' in '${parent}'`);
}
seen.add(name);
}
}
export type TestState = "success" | "failure" | "skip";
class AbortSentinel {}
export class TestController {
#state: TestState;
logs: string[];
constructor() {
this.#state = "success";
this.logs = [];
}
getState(): TestState {
return this.#state;
}
fail() {
this.#state = "failure";
}
failed(): boolean {
return this.#state === "failure";
}
failNow(): never {
this.fail();
throw new AbortSentinel();
}
log(message: string) {
this.logs.push(message);
}
error(message: string) {
this.log(message);
this.fail();
}
fatal(message: string): never {
this.log(message);
this.failNow();
}
skip(message?: string): never {
if (message != null) this.log(message);
if (this.#state !== "failure") this.#state = "skip";
throw new AbortSentinel();
}
skipped(): boolean {
return this.#state === "skip";
}
}
// =============================================================================
// Execution
export interface TestResult {
state: TestState;
logs: string[];
}
function runTests(reporter: Reporter, parents: string[], node: TestTree) {
const path = [...parents, node.name];
if ("children" in node) {
for (const c of node.children) runTests(reporter, path, c);
return;
}
let controller = new TestController();
try {
node.test(controller);
} catch (e) {
if (!(e instanceof AbortSentinel)) {
controller.error(extractExceptionString(e));
}
}
reporter.update(path, { state: controller.getState(), logs: controller.logs });
}
function extractExceptionString(e: any): string {
// String() instead of .toString() as null and undefined don't have
// properties.
const s = String(e);
if (!(e instanceof Error && e.stack)) return s;
// v8 (Chromium, NodeJS) includes the error message, while Firefox and
// WebKit do not.
if (e.stack.startsWith(s)) return e.stack;
return `${s}\n${e.stack}`;
}
// =============================================================================
// Reporting
export interface Reporter {
// A notable feature—or flaw, to some—of the DSL is that the tree of tests
// is statically known, which might greatly aid in implementing a reporter.
register(suites: TestGroup[]): void;
// While we could simply call a function with a tree representing all
// results, which would indeed greatly simplify implementation of reporters,
// simply registering a path and allowing the reporter to—either implicitly
// or explicitly—construct a tree themselves allows for results to be
// *incrementally reported*, instead of a great deal of silence until all
// tests finish.
update(path: string[], result: TestResult): void;
// With just update(), the reporter never knows when all tests have
// completed. The simplest possible use for this is to notify the user, but
// its intent is actually more tailored to the StreamReporter scenario:
// while destructively updated report rendering (as with a tree of DOM nodes
// which are mutated) always displays the results in a structured manner
// matching that of the tests, “rerendering” or otherwise destructively
// updating the rendered output might be infeasible in some paradigms, such
// as command-line applications—all existing implementations of such
// rendering both mess up the scrollback position and necessarily crop out
// some of the data at the bottom (since the top of the tree is forced to be
// at the top of the screen, as one cannot unscroll portably). Explicitly
// signaling to the reporter that no more results will be received permits
// it to simply display live test progress linearly, while building up
// a tree and displaying it once it's known the tree is complete.
finalize(): void;
}
// A reporter that diligently reports absolutely nothing. This is essentially
// a way to “undo” the incremental reporting update() provides, getting back the
// underlying result tree; this makes it extremely convenient in some cases like
// testing ourself.
export class NoOpReporter implements Reporter {
suites: TestGroup[];
results: ({ path: string[] } & TestResult)[];
finalized: boolean;
constructor() {
this.suites = [];
this.results = [];
this.finalized = false;
}
register(suites: TestGroup[]) {
this.suites = suites;
}
update(path: string[], result: TestResult) {
this.results.push({ path, ...result });
}
finalize() {
this.finalized = true;
}
}
export interface Stream {
writeln(s: string): void;
}
const SEP = " ";
// A simple reporter that outputs to some stream; suitable for CLIs.
export class StreamReporter implements Reporter {
stream: Stream;
verbose: boolean;
#successes: ({ path: string[] } & TestResult)[];
#failures: ({ path: string[] } & TestResult)[];
#skips: ({ path: string[] } & TestResult)[];
constructor(stream: Stream, verbose: boolean = false) {
this.stream = stream;
this.verbose = verbose;
this.#successes = [];
this.#failures = [];
this.#skips = [];
}
succeeded(): boolean {
return this.#successes.length > 0 && this.#failures.length === 0;
}
// We don't need the structure for reporting.
register(suites: TestGroup[]) {}
update(path: string[], result: TestResult) {
if (path.length === 0) throw new RangeError("path is empty");
const pathStr = path.join(SEP);
switch (result.state) {
case "success":
this.#successes.push({ path, ...result });
// NOTE: emojis are used instead of colored Unicode symbols as
// coloring isn't possible through all streams, which would make
// this terminal-specific, and even in terminals and emulators
// thereof, it's very tedious to correctly detect whether one should
// use colors (https://no-color.org, https://bixense.com/clicolors,
// https://force-color.org), ensure reasonable contrast is retained
// on every possible theme (using reverse video is often the only
// way), and be immediately noticeable. Emojis have an upper hand in
// that they're more common than obscure Unicode characters—which
// also means you're more likely to have an emoji font but not
// a font with those symbols—and that they're double-width.
if (this.verbose) this.stream.writeln(`✅️ ${pathStr}`);
break;
case "failure":
this.#failures.push({ path, ...result });
this.stream.writeln(`⚠️ ${pathStr}`);
break;
case "skip":
this.#skips.push({ path, ...result });
this.stream.writeln(`⏭️ ${pathStr}`);
break;
}
}
finalize() {
if (this.verbose) this.#displaySection("successes", this.#successes, true);
this.#displaySection("failures", this.#failures);
this.#displaySection("skips", this.#skips);
this.stream.writeln("");
this.stream.writeln(
`${this.#successes.length} succeeded, ${this.#failures.length} failed` +
(this.#skips.length ? `, ${this.#skips.length} skipped` : ""),
);
}
#displaySection(name: string, data: ({ path: string[] } & TestResult)[], ignoreEmpty: boolean = false) {
if (!data.length) return;
// Transform [{ path: ["a", "b", "c"] }, { path: ["a", "b", "d"] }] into
// { "a b": ["c", "d"] }. NOTE: intermediate nodes are collapsed as
// excessive nesting is difficult to convey clearly in a text-only
// environment.
let pathMap = new Map<string, ({ name: string } & TestResult)[]>();
for (const t of data) {
if (t.path.length === 0) throw new RangeError("path is empty");
const key = t.path.slice(0, -1).join(SEP);
if (!pathMap.has(key)) pathMap.set(key, []);
pathMap.get(key)!.push({ name: t.path.at(-1)!, ...t });
}
this.stream.writeln("");
this.stream.writeln(name.toUpperCase());
this.stream.writeln("=".repeat(name.length));
for (let [path, tests] of pathMap) {
if (ignoreEmpty) tests = tests.filter((t) => t.logs.length);
if (tests.length === 0) continue;
if (tests.length === 1) {
this.#writeOutput(tests[0], path ? `${path}${SEP}` : "", false);
} else {
this.stream.writeln(path);
for (const t of tests) this.#writeOutput(t, " - ", true);
}
}
}
#writeOutput(test: { name: string } & TestResult, prefix: string, nested: boolean) {
let output = "";
if (test.logs.length) {
// Individual logs might span multiple lines, so join them together
// then split it again.
const logStr = test.logs.join("\n");
const lines = logStr.split("\n");
if (lines.length <= 1) {
output = `: ${logStr}`;
} else {
const padding = nested ? " " : " ";
output = ":\n" + lines.map((line) => padding + line).join("\n");
}
}
this.stream.writeln(`${prefix}${test.name}${output}`);
}
}
function assertGetElementById(id: string): HTMLElement {
let elem = document.getElementById(id);
if (elem == null) throw new ReferenceError(`element with ID '${id}' missing from DOM`);
return elem;
}
// A reporter that directly translates a tree of results into a tree of
// collapsible elements in the DOM.
export class DOMReporter implements Reporter {
// It is very difficult to implement this using the statically known tree,
// because Map doesn't handle array keys properly (to store the path), and
// it's unknown of there's any way to implement it without writing one's own
// data types. Oh well; using the DOM as a data structure might seem hacky
// but it does have its benefits, apart from encouraging a tagless final.
register(suites: TestGroup[]) {}
update(path: string[], result: TestResult) {
if (path.length === 0) throw new RangeError("path is empty");
if (result.state === "skip") {
assertGetElementById("skip-counter-text").hidden = false;
}
const counter = assertGetElementById(`${result.state}-counter`);
counter.innerText = (Number(counter.innerText) + 1).toString();
let parent = assertGetElementById("root");
for (const node of path) {
let child: HTMLDetailsElement | null = null;
let summary: HTMLElement | null = null;
let d: Element;
outer: for (d of parent.children) {
if (!(d instanceof HTMLDetailsElement)) continue;
for (const s of d.children) {
if (!(s instanceof HTMLElement)) continue;
if (!(s.tagName === "SUMMARY" && s.innerText === node)) continue;
child = d;
summary = s;
break outer;
}
}
if (!child) {
child = document.createElement("details");
child.className = "test-node";
child.ariaRoleDescription = "test";
summary = document.createElement("summary");
summary.appendChild(document.createTextNode(node));
summary.ariaRoleDescription = "test name";
child.appendChild(summary);
parent.appendChild(child);
}
if (!summary) throw new Error("unreachable as assigned above");
switch (result.state) {
case "failure":
// Only expand failures, to minimize successes and skips.
child.open = true;
child.classList.add("failure");
child.classList.remove("skip");
child.classList.remove("success");
// The summary marker does not appear in the AOM, so setting its
// alt text is fruitless; label the summary itself instead.
summary.setAttribute("aria-labelledby", "failure-description");
break;
case "skip":
if (child.classList.contains("failure")) break;
child.classList.add("skip");
child.classList.remove("success");
summary.setAttribute("aria-labelledby", "skip-description");
break;
case "success":
if (child.classList.contains("failure") || child.classList.contains("skip")) break;
child.classList.add("success");
summary.setAttribute("aria-labelledby", "success-description");
break;
}
parent = child;
}
const p = document.createElement("p");
p.classList.add("test-desc");
if (result.logs.length) {
const pre = document.createElement("pre");
pre.appendChild(document.createTextNode(result.logs.join("\n")));
p.appendChild(pre);
} else {
p.classList.add("italic");
p.appendChild(document.createTextNode("No output."));
}
parent.appendChild(p);
}
finalize() {}
}
interface GoNode {
name: string;
subtests?: GoNode[];
}
// Used to display results via `go test`, via some glue code from the Go side.
// TODO(Ophestra): said glue code has to be written.
export class GoTestReporter implements Reporter {
register(suites: TestGroup[]) {
console.log(JSON.stringify(suites.map(GoTestReporter.serialize)));
}
// Convert a test tree into the one expected by the Go code.
static serialize(node: TestTree): GoNode {
return {
name: node.name,
subtests: "children" in node ? node.children.map(GoTestReporter.serialize) : undefined,
};
}
update(path: string[], result: TestResult) {
let state: number;
switch (result.state) {
case "success": state = 0; break;
case "failure": state = 1; break;
case "skip": state = 2; break;
}
console.log(JSON.stringify({ path, state, logs: result.logs }));
}
// Unnecessary but convenient on the Go side, so that it doesn't have to
// infer this via process exit.
finalize() {
console.log("null");
}
}

View File

@@ -0,0 +1,21 @@
<?xml version="1.0"?>
<!-- See failure-open.svg for an explanation of the view box dimensions. -->
<svg xmlns="http://www.w3.org/2000/svg" width="20" viewBox="-20,-20 160 130">
<!-- This triangle should match success-closed.svg, fill and stroke color notwithstanding. -->
<polygon points="0,0 100,50 0,100" fill="blue" stroke="blue" stroke-width="15" stroke-linejoin="round"/>
<!--
! This path is extremely similar to the one in skip-open.svg; before
! making minor modifications, diff the two to understand how they should
! remain in sync.
-->
<path
d="M 50,50
A 23,23 270,1,1 30,30
l -10,20
m 10,-20
l -20,-10"
fill="none"
stroke="white"
stroke-width="12"
stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 812 B

View File

@@ -0,0 +1,21 @@
<?xml version="1.0"?>
<!-- See failure-open.svg for an explanation of the view box dimensions. -->
<svg xmlns="http://www.w3.org/2000/svg" width="20" viewBox="-20,-20 160 130">
<!-- This triangle should match success-open.svg, fill and stroke color notwithstanding. -->
<polygon points="0,0 100,0 50,100" fill="blue" stroke="blue" stroke-width="15" stroke-linejoin="round"/>
<!--
! This path is extremely similar to the one in skip-closed.svg; before
! making minor modifications, diff the two to understand how they should
! remain in sync.
-->
<path
d="M 50,50
A 23,23 270,1,1 70,30
l 10,-20
m -10,20
l -20,-10"
fill="none"
stroke="white"
stroke-width="12"
stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 812 B

View File

@@ -0,0 +1,87 @@
/*
* When updating the theme colors, also update them in success-closed.svg and
* success-open.svg!
*/
:root {
--bg: #d3d3d3;
--fg: black;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #2c2c2c;
--fg: ghostwhite;
}
}
html {
background-color: var(--bg);
color: var(--fg);
}
h1, p, summary, noscript {
font-family: sans-serif;
}
noscript {
font-size: 16pt;
}
.root {
margin: 1rem 0;
}
details.test-node {
margin-left: 1rem;
padding: 0.2rem 0.5rem;
border-left: 2px dashed var(--fg);
> summary {
cursor: pointer;
}
&.success > summary::marker {
/*
* WebKit only supports color and font-size properties in ::marker [1], and
* its ::-webkit-details-marker only supports hiding the marker entirely
* [2], contrary to mdn's example [3]; thus, set a color as a fallback:
* while it may not be accessible for colorblind individuals, it's better
* than no indication of a test's state for anyone, as that there's no other
* way to include an indication in the marker on WebKit.
*
* [1]: https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/::marker#browser_compatibility
* [2]: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/summary#default_style
* [3]: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/summary#changing_the_summarys_icon
*/
color: var(--fg);
content: url("./success-closed.svg") / "success";
}
&.success[open] > summary::marker {
content: url("./success-open.svg") / "success";
}
&.failure > summary::marker {
color: red;
content: url("./failure-closed.svg") / "failure";
}
&.failure[open] > summary::marker {
content: url("./failure-open.svg") / "failure";
}
&.skip > summary::marker {
color: blue;
content: url("./skip-closed.svg") / "skip";
}
&.skip[open] > summary::marker {
content: url("./skip-open.svg") / "skip";
}
}
p.test-desc {
margin: 0 0 0 1rem;
padding: 2px 0;
> pre {
margin: 0;
}
}
.italic {
font-style: italic;
}

View File

@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<!-- See failure-open.svg for an explanation of the view box dimensions. -->
<svg xmlns="http://www.w3.org/2000/svg" width="20" viewBox="-20,-20 160 130">
<style>
.adaptive-stroke {
stroke: black;
}
@media (prefers-color-scheme: dark) {
.adaptive-stroke {
stroke: ghostwhite;
}
}
</style>
<!-- When updating this triangle, also update the other five SVGs. -->
<polygon points="0,0 100,50 0,100" fill="none" class="adaptive-stroke" stroke-width="15" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 572 B

View File

@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<!-- See failure-open.svg for an explanation of the view box dimensions. -->
<svg xmlns="http://www.w3.org/2000/svg" width="20" viewBox="-20,-20 160 130">
<style>
.adaptive-stroke {
stroke: black;
}
@media (prefers-color-scheme: dark) {
.adaptive-stroke {
stroke: ghostwhite;
}
}
</style>
<!-- When updating this triangle, also update the other five SVGs. -->
<polygon points="0,0 100,0 50,100" fill="none" class="adaptive-stroke" stroke-width="15" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 572 B

View File

@@ -0,0 +1,13 @@
//go:build frontend && frontend_test
package ui
import "embed"
//go:generate tsc -p tsconfig.test.json
//go:generate cp index.html style.css favicon.ico static
//go:generate cp jstest/index.html jstest/style.css static/jstest
//go:generate sh -c "cp jstest/*.svg static/jstest"
//go:embed static
var _static embed.FS
var static = staticFS(_static)

View File

@@ -1,8 +1,11 @@
// This file defines the common options for all TypeScript here. This shouldn't
// be directly used as the project file in builds; see tsconfig.*.json instead,
// which inherit from this file and essentially define specific build targets.
{
"compilerOptions": {
"target": "ES2024",
"strict": true,
"alwaysStrict": true,
"outDir": "static"
}
}
"outDir": "static",
},
}

View File

@@ -0,0 +1,5 @@
// Project file for building pkgserver alongside its tests. test_ui.go uses this
// as its project file.
{
"extends": "./tsconfig.json",
}

View File

@@ -0,0 +1,6 @@
// Project file for building just the pkgserver UI, with none of the testing
// stuff attached. ui_full.go uses this as its project file.
{
"extends": "./tsconfig.json",
"exclude": ["jstest", "all_tests.ts", "*_test.ts"],
}

View File

@@ -1,7 +1,19 @@
// Package ui holds the static web UI.
package ui
import "net/http"
import (
"io/fs"
"net/http"
)
// staticFS is an internal helper to wrap around go:embed's filesystem.
func staticFS(static fs.FS) fs.FS {
if f, err := fs.Sub(static, "static"); err != nil {
panic(err)
} else {
return f
}
}
// Register arranges for mux to serve the embedded frontend.
func Register(mux *http.ServeMux) {

View File

@@ -1,21 +1,11 @@
//go:build frontend
//go:build frontend && !frontend_test
package ui
import (
"embed"
"io/fs"
)
import "embed"
//go:generate tsc
//go:generate cp index.html style.css static
//go:generate tsc -p tsconfig.ui.json
//go:generate cp index.html style.css favicon.ico 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
}
}()
var static = staticFS(_static)

View File

@@ -97,10 +97,10 @@ func main() {
if !flagLTO {
flags |= rosa.OptLLVMNoLTO
}
rosa.Native().DropCaches("", flags)
rosa.DropCaches("", flags)
cross := flagArch != "" && flagArch != runtime.GOARCH
if flagQEMU || cross {
cm.qemu, _ = rosa.Native().Std().Load(rosa.QEMU)
cm.qemu = rosa.Std.Load(rosa.QEMU)
}
if cross {
@@ -108,7 +108,7 @@ func main() {
flags = flagCrossOverride
}
rosa.Native().DropCaches(flagArch, flags)
rosa.DropCaches(flagArch, flags)
if !rosa.HasStage0() {
return pkg.UnsupportedArchError(flagArch)
}
@@ -331,12 +331,12 @@ func main() {
n atomic.Uint64
)
w := make(chan rosa.ArtifactH)
w := make(chan rosa.PArtifact)
var wg sync.WaitGroup
for range max(flagJobs, 1) {
wg.Go(func() {
for p := range w {
meta := rosa.Native().MustGet(p)
meta := rosa.GetMetadata(p)
if meta.ID == 0 {
continue
}
@@ -349,9 +349,8 @@ func main() {
continue
}
_, version := rosa.Native().Std().Load(p)
if current, latest :=
version,
rosa.Std.Version(p),
meta.GetLatest(v); current != latest {
n.Add(1)
@@ -365,9 +364,9 @@ func main() {
}
done:
for _, p := range rosa.Native().Collect() {
for i := range rosa.PresetEnd {
select {
case w <- p:
case w <- rosa.PArtifact(i):
break
case <-ctx.Done():
break done
@@ -412,9 +411,9 @@ func main() {
"stage3",
"Check for toolchain 3-stage non-determinism",
func(args []string) (err error) {
s := rosa.Std
t := rosa.Std
if flagGentoo != "" {
s -= 3 // magic number to discourage misuse
t -= 3 // magic number to discourage misuse
var checksum pkg.Checksum
if len(flagChecksum) != 0 {
@@ -422,7 +421,7 @@ func main() {
return
}
}
rosa.Native().SetGentooStage3(flagGentoo, checksum)
rosa.SetGentooStage3(flagGentoo, checksum)
}
var (
@@ -431,8 +430,9 @@ func main() {
)
if err = cm.Do(func(cache *pkg.Cache) (err error) {
llvm, _ := rosa.Native().New(s - 2).Load(rosa.LLVM)
pathname, _, err = cache.Cure(llvm)
pathname, _, err = cache.Cure(
(t - 2).Load(rosa.LLVM),
)
return
}); err != nil {
return
@@ -440,16 +440,18 @@ func main() {
log.Println("stage1:", pathname)
if err = cm.Do(func(cache *pkg.Cache) (err error) {
llvm, _ := rosa.Native().New(s - 1).Load(rosa.LLVM)
pathname, checksum[0], err = cache.Cure(llvm)
pathname, checksum[0], err = cache.Cure(
(t - 1).Load(rosa.LLVM),
)
return
}); err != nil {
return
}
log.Println("stage2:", pathname)
if err = cm.Do(func(cache *pkg.Cache) (err error) {
llvm, _ := rosa.Native().New(s).Load(rosa.LLVM)
pathname, checksum[1], err = cache.Cure(llvm)
pathname, checksum[1], err = cache.Cure(
t.Load(rosa.LLVM),
)
return
}); err != nil {
return
@@ -470,8 +472,9 @@ func main() {
if flagStage0 {
if err = cm.Do(func(cache *pkg.Cache) (err error) {
stage0, _ := rosa.Native().New(s).Load(rosa.Stage0)
pathname, _, err = cache.Cure(stage0)
pathname, _, err = cache.Cure(
t.Load(rosa.Stage0),
)
return
}); err != nil {
return
@@ -516,6 +519,10 @@ func main() {
if len(args) != 1 {
return errors.New("cure requires 1 argument")
}
p, ok := rosa.ResolveName(args[0])
if !ok {
return fmt.Errorf("unknown artifact %q", args[0])
}
t := rosa.Std
if flagBoot {
@@ -524,16 +531,11 @@ func main() {
t -= 1
}
a, _ := rosa.Native().New(t).Load(rosa.ArtifactH(unique.Make(args[0])))
if a == nil {
return fmt.Errorf("unknown artifact %q", args[0])
}
switch {
default:
var pathname *check.Absolute
err := cm.Do(func(cache *pkg.Cache) (err error) {
pathname, _, err = cache.Cure(a)
pathname, _, err = cache.Cure(t.Load(p))
return
})
if err != nil {
@@ -575,7 +577,7 @@ func main() {
return err
}
if err = pkg.NewIR().EncodeAll(f, a); err != nil {
if err = pkg.NewIR().EncodeAll(f, rosa.Std.Load(p)); err != nil {
_ = f.Close()
return err
}
@@ -586,7 +588,7 @@ func main() {
return cm.Do(func(cache *pkg.Cache) error {
return cache.EnterExec(
ctx,
a,
t.Load(p),
true, os.Stdin, os.Stdout, os.Stderr,
rosa.AbsSystem.Append("bin", "mksh"),
"sh",
@@ -598,6 +600,7 @@ func main() {
if flagNoReply {
flags |= remoteNoReply
}
a := t.Load(p)
pathname, err := cureRemote(ctx, &addr, a, flags)
if !flagNoReply && err == nil {
log.Println(pathname)
@@ -617,7 +620,7 @@ func main() {
case flagFaults:
var faults []pkg.Fault
if err := cm.Do(func(cache *pkg.Cache) (err error) {
faults, err = cache.ReadFaults(a)
faults, err = cache.ReadFaults(t.Load(p))
return
}); err != nil {
return err
@@ -631,7 +634,7 @@ func main() {
case flagPop:
var faults []pkg.Fault
if err := cm.Do(func(cache *pkg.Cache) (err error) {
faults, err = cache.ReadFaults(a)
faults, err = cache.ReadFaults(t.Load(p))
return
}); err != nil {
return err
@@ -737,26 +740,27 @@ func main() {
"shell",
"Interactive shell in the specified Rosa OS environment",
func(args []string) error {
handles := make([]rosa.ArtifactH, len(args)+3)
presets := make([]rosa.PArtifact, len(args)+3)
for i, arg := range args {
handles[i] = rosa.ArtifactH(unique.Make(arg))
if rosa.Native().Get(handles[i]) == nil {
p, ok := rosa.ResolveName(arg)
if !ok {
return fmt.Errorf("unknown artifact %q", arg)
}
presets[i] = p
}
base := rosa.LLVM
if !flagWithToolchain {
base = rosa.Musl
}
handles = append(handles,
presets = append(presets,
base,
rosa.Mksh,
rosa.Toybox,
)
root := make(pkg.Collect, 0, 6+len(args))
root = rosa.Native().Std().Append(root, handles...)
root = rosa.Std.AppendPresets(root, presets...)
if err := cm.Do(func(cache *pkg.Cache) error {
_, _, err := cache.Cure(&root)

View File

@@ -9,7 +9,7 @@ import (
)
func TestMain(m *testing.M) {
rosa.Native().DropCaches("", rosa.OptLLVMNoLTO)
rosa.DropCaches("", rosa.OptLLVMNoLTO)
os.Exit(m.Run())
}
@@ -35,10 +35,10 @@ func TestCureAll(t *testing.T) {
}
})
for _, handle := range rosa.Native().Collect() {
a, _ := rosa.Native().Std().MustLoad(handle)
t.Run(rosa.Native().MustGet(handle).Name, func(t *testing.T) {
_, err := cureRemote(t.Context(), &addr, a, 0)
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)
}

View File

@@ -65,7 +65,7 @@ ln -s ../../system/bin/perl /usr/bin
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Attr] = Metadata{
f: Toolchain.newAttr,
Name: "attr",
@@ -73,7 +73,7 @@ func init() {
Website: "https://savannah.nongnu.org/projects/attr/",
ID: 137,
})
}
}
func (t Toolchain) newACL() (pkg.Artifact, string) {
@@ -94,7 +94,7 @@ func (t Toolchain) newACL() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[ACL] = Metadata{
f: Toolchain.newACL,
Name: "acl",
@@ -106,5 +106,5 @@ func init() {
},
ID: 16,
})
}
}

447
internal/rosa/all.go Normal file
View File

@@ -0,0 +1,447 @@
package rosa
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"runtime"
"strconv"
"sync"
"hakurei.app/internal/pkg"
)
// PArtifact is a lazily-initialised [pkg.Artifact] preset.
type PArtifact int
const (
LLVM PArtifact = iota
// EarlyInit is the Rosa OS init program.
EarlyInit
// ImageSystem is the Rosa OS /system image.
ImageSystem
// ImageInitramfs is the Rosa OS initramfs archive.
ImageInitramfs
// Kernel is the generic Rosa OS Linux kernel.
Kernel
// KernelHeaders is an installation of kernel headers for [Kernel].
KernelHeaders
// KernelSource is a writable kernel source tree installed to [AbsUsrSrc].
KernelSource
// Firmware is firmware blobs for use with the Linux kernel.
Firmware
ACL
ArgpStandalone
Attr
Autoconf
Automake
BC
Bash
Binutils
Bison
Bzip2
CMake
Connman
Coreutils
Curl
DBus
DTC
Diffutils
Elfutils
Fakeroot
Findutils
Flex
FontUtil
Freetype
Fuse
GMP
GLib
Gawk
GenInitCPIO
Gettext
Git
Glslang
GnuTLS
Go
Gperf
Grep
Gzip
Hakurei
HakureiDist
Hwdata
IPTables
Kmod
LIT
LibX11
LibXau
LibXdmcp
LibXext
LibXfixes
LibXfont2
LibXrandr
LibXrender
LibXxf86vm
Libarchive
Libbsd
Libcap
Libconfig
LibdisplayInfo
Libdrm
Libepoxy
Libev
Libexpat
Libffi
Libfontenc
Libgd
Libglvnd
Libiconv
Libmd
Libmnl
Libnftnl
Libpciaccess
Libpng
Libpsl
Libseccomp
Libtasn1
Libtirpc
Libtool
Libucontext
Libunistring
Libva
LibxcbRenderUtil
LibxcbUtil
LibxcbUtilImage
LibxcbUtilKeysyms
LibxcbUtilWM
Libxcvt
Libxkbfile
Libxml2
Libxshmfence
Libxslt
Libxtrans
LMSensors
M4
MPC
MPFR
Make
Mesa
Meson
Mksh
MuslFts
MuslObstack
NSS
NSSCACert
Ncurses
Nettle
Ninja
OpenSSL
P11Kit
PCRE2
Parallel
Patch
Perl
PerlLocaleGettext
PerlMIMECharset
PerlModuleBuild
PerlPodParser
PerlSGMLS
PerlTermReadKey
PerlTestCmd
PerlTextCharWidth
PerlTextWrapI18N
PerlUnicodeLineBreak
PerlYAMLTiny
Pixman
PkgConfig
Procps
Python
PythonFlitCore
PythonHatchling
PythonIniConfig
PythonMako
PythonMarkupSafe
PythonPackaging
PythonPathspec
PythonPluggy
PythonPyTest
PythonPyYAML
PythonPycparser
PythonPygments
PythonSetuptools
PythonSetuptoolsSCM
PythonTroveClassifiers
PythonVCSVersioning
PythonWheel
QEMU
Rdfind
Readline
Rsync
Sed
SPIRVHeaders
SPIRVLLVMTranslator
SPIRVTools
SquashfsTools
Strace
TamaGo
Tar
Texinfo
Toybox
toyboxEarly
Unzip
UtilLinux
VIM
Wayland
WaylandProtocols
XCB
XCBProto
XDGDBusProxy
XZ
Xkbcomp
XkeyboardConfig
XorgProto
Xserver
Zlib
Zstd
// PresetUnexportedStart is the first unexported preset.
PresetUnexportedStart
stage0Dist = iota - 1
llvmSource
// earlyCompilerRT is an early, standalone compiler-rt installation for the
// standalone runtimes build.
//
// earlyCompilerRT must only be loaded by [LLVM].
earlyCompilerRT
// earlyRuntimes is an early, standalone installation of LLVM runtimes to
// work around the cmake build system leaking the system LLVM installation
// when invoking the newly built toolchain.
//
// earlyRuntimes must only be loaded by [LLVM].
earlyRuntimes
buildcatrust
utilMacros
// Musl is a standalone libc that does not depend on the toolchain.
Musl
// muslHeaders is a system installation of [Musl] headers.
muslHeaders
// gcc is a hacked-to-pieces GCC toolchain meant for use in intermediate
// stages only. This preset and its direct output must never be exposed.
gcc
// nettle3 is an older version of [Nettle].
nettle3
// Stage0 is a tarball containing all compile-time dependencies of artifacts
// part of the [Std] toolchain.
Stage0
// PresetEnd is the total number of presets and does not denote a preset.
PresetEnd
)
// P represents multiple [PArtifact] and is stable through JSON.
type P []PArtifact
// MarshalJSON represents [PArtifact] by their [Metadata.Name].
func (s P) MarshalJSON() ([]byte, error) {
names := make([]string, len(s))
for i, p := range s {
names[i] = GetMetadata(p).Name
}
return json.Marshal(names)
}
// UnmarshalJSON resolves the value created by MarshalJSON back to [P].
func (s *P) UnmarshalJSON(data []byte) error {
var names []string
if err := json.Unmarshal(data, &names); err != nil {
return err
}
*s = make(P, len(names))
for i, name := range names {
if p, ok := ResolveName(name); !ok {
return fmt.Errorf("unknown artifact %q", name)
} else {
(*s)[i] = p
}
}
return nil
}
// Metadata is stage-agnostic information of a [PArtifact] not directly
// representable in the resulting [pkg.Artifact].
type Metadata struct {
f func(t Toolchain) (a pkg.Artifact, version string)
// Unique package name.
Name string `json:"name"`
// Short user-facing description.
Description string `json:"description"`
// Project home page.
Website string `json:"website,omitempty"`
// Runtime dependencies.
Dependencies P `json:"dependencies"`
// Project identifier on [Anitya].
//
// [Anitya]: https://release-monitoring.org/
ID int `json:"-"`
// Optional custom version checking behaviour.
latest func(v *Versions) string
}
// GetLatest returns the latest version described by v.
func (meta *Metadata) GetLatest(v *Versions) string {
if meta.latest != nil {
return meta.latest(v)
}
return v.Latest
}
// Unversioned denotes an unversioned [PArtifact].
const Unversioned = "\x00"
// UnpopulatedIDError is returned by [Metadata.GetLatest] for an instance of
// [Metadata] where ID is not populated.
type UnpopulatedIDError struct{}
func (UnpopulatedIDError) Unwrap() error { return errors.ErrUnsupported }
func (UnpopulatedIDError) Error() string { return "Anitya ID is not populated" }
// Versions are package versions returned by Anitya.
type Versions struct {
// The latest version for the project, as determined by the version sorting algorithm.
Latest string `json:"latest_version"`
// List of all versions that arent flagged as pre-release.
Stable []string `json:"stable_versions"`
// List of all versions stored, sorted from newest to oldest.
All []string `json:"versions"`
}
// getStable returns the first Stable version, or Latest if that is unavailable.
func (v *Versions) getStable() string {
if len(v.Stable) == 0 {
return v.Latest
}
return v.Stable[0]
}
// GetVersions returns versions fetched from Anitya.
func (meta *Metadata) GetVersions(ctx context.Context) (*Versions, error) {
if meta.ID == 0 {
return nil, UnpopulatedIDError{}
}
var resp *http.Response
if req, err := http.NewRequestWithContext(
ctx,
http.MethodGet,
"https://release-monitoring.org/api/v2/versions/?project_id="+
strconv.Itoa(meta.ID),
nil,
); err != nil {
return nil, err
} else {
req.Header.Set("User-Agent", "Rosa/1.1")
if resp, err = http.DefaultClient.Do(req); err != nil {
return nil, err
}
}
var v Versions
err := json.NewDecoder(resp.Body).Decode(&v)
return &v, errors.Join(err, resp.Body.Close())
}
var (
// artifactsM is an array of [PArtifact] metadata.
artifactsM [PresetEnd]Metadata
// artifacts stores the result of Metadata.f.
artifacts [_toolchainEnd][len(artifactsM)]struct {
a pkg.Artifact
v string
}
// artifactsOnce is for lazy initialisation of artifacts.
artifactsOnce [_toolchainEnd][len(artifactsM)]sync.Once
// arch is the target architecture.
arch = runtime.GOARCH
// presetOpts globally modifies behaviour of presets.
presetOpts int
)
const (
// OptSkipCheck skips running all test suites.
OptSkipCheck = 1 << iota
// OptLLVMNoLTO disables LTO in all [LLVM] stages.
OptLLVMNoLTO
)
// Arch returns the target architecture.
func Arch() string { return arch }
// Flags returns the current preset flags
func Flags() int { return presetOpts }
// zero zeros the value pointed to by p.
func zero[T any](p *T) { var v T; *p = v }
// DropCaches arranges for all cached [pkg.Artifact] to be freed some time after
// it returns. Must not be used concurrently with any other function from this
// package.
func DropCaches(targetArch string, flags int) {
if targetArch == "" {
targetArch = runtime.GOARCH
}
arch = targetArch
presetOpts = flags
zero(&artifacts)
zero(&artifactsOnce)
}
// GetMetadata returns [Metadata] of a [PArtifact].
func GetMetadata(p PArtifact) *Metadata { return &artifactsM[p] }
// construct constructs a [pkg.Artifact] corresponding to a [PArtifact] once.
func (t Toolchain) construct(p PArtifact) {
artifactsOnce[t][p].Do(func() {
artifacts[t][p].a, artifacts[t][p].v = artifactsM[p].f(t)
})
}
// Load returns the resulting [pkg.Artifact] of [PArtifact].
func (t Toolchain) Load(p PArtifact) pkg.Artifact {
t.construct(p)
return artifacts[t][p].a
}
// Version returns the version string of [PArtifact].
func (t Toolchain) Version(p PArtifact) string {
t.construct(p)
return artifacts[t][p].v
}
// ResolveName returns a [PArtifact] by name.
func ResolveName(name string) (p PArtifact, ok bool) {
for i := range PresetUnexportedStart {
if name == artifactsM[i].Name {
return i, true
}
}
return 0, false
}

81
internal/rosa/all_test.go Normal file
View File

@@ -0,0 +1,81 @@
package rosa_test
import (
"testing"
"hakurei.app/internal/rosa"
)
func TestLoad(t *testing.T) {
t.Parallel()
for i := range rosa.PresetEnd {
p := rosa.PArtifact(i)
t.Run(rosa.GetMetadata(p).Name, func(t *testing.T) {
t.Parallel()
rosa.Std.Load(p)
})
}
}
func BenchmarkAll(b *testing.B) {
arch, flags := rosa.Arch(), rosa.Flags()
b.Cleanup(func() { rosa.DropCaches(arch, flags) })
for b.Loop() {
for i := range rosa.PresetEnd {
rosa.Std.Load(rosa.PArtifact(i))
}
b.StopTimer()
rosa.DropCaches("", 0)
b.StartTimer()
}
}
func TestResolveName(t *testing.T) {
t.Parallel()
for i := range rosa.PresetUnexportedStart {
p := i
name := rosa.GetMetadata(p).Name
t.Run(name, func(t *testing.T) {
t.Parallel()
if got, ok := rosa.ResolveName(name); !ok {
t.Fatal("ResolveName: ok = false")
} else if got != p {
t.Fatalf("ResolveName: %d, want %d", got, p)
}
})
}
}
func TestResolveNameUnexported(t *testing.T) {
t.Parallel()
for i := rosa.PresetUnexportedStart; i < rosa.PresetEnd; i++ {
p := i
name := rosa.GetMetadata(p).Name
t.Run(name, func(t *testing.T) {
t.Parallel()
if got, ok := rosa.ResolveName(name); ok {
t.Fatalf("ResolveName: resolved unexported preset %d", got)
}
})
}
}
func TestUnique(t *testing.T) {
t.Parallel()
names := make(map[string]struct{})
for i := range rosa.PresetEnd {
name := rosa.GetMetadata(rosa.PArtifact(i)).Name
if _, ok := names[name]; ok {
t.Fatalf("name %s is not unique", name)
}
names[name] = struct{}{}
}
}

View File

@@ -26,11 +26,11 @@ install -D -m755 libargp.a /work/system/lib/libargp.a
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[ArgpStandalone] = Metadata{
f: Toolchain.newArgpStandalone,
Name: "argp-standalone",
Description: "hierarchical argument parsing library broken out from glibc",
Website: "http://www.lysator.liu.se/~nisse/misc/",
})
}
}

View File

@@ -1,348 +0,0 @@
// Package azalea implements a proof-of-concept, domain-specific language for
// Rosa OS software packaging.
package azalea
import (
"errors"
"io"
"strconv"
"text/scanner"
)
// idents are runes accepted in an identifier.
var idents = [...]bool{
'0': true, '1': true, '2': true, '3': true, '4': true, '5': true, '6': true,
'7': true, '8': true, '9': true,
'A': true, 'B': true, 'C': true, 'D': true, 'E': true, 'F': true, 'G': true,
'H': true, 'I': true, 'J': true, 'K': true, 'L': true, 'M': true, 'N': true,
'O': true, 'P': true, 'Q': true, 'R': true, 'S': true, 'T': true, 'U': true,
'V': true, 'W': true, 'X': true, 'Y': true, 'Z': true,
'a': true, 'b': true, 'c': true, 'd': true, 'e': true, 'f': true, 'g': true,
'h': true, 'i': true, 'j': true, 'k': true, 'l': true, 'm': true, 'n': true,
'o': true, 'p': true, 'q': true, 'r': true, 's': true, 't': true, 'u': true,
'v': true, 'w': true, 'x': true, 'y': true, 'z': true,
'-': true, '_': true,
}
// TokenError describes an unexpected token.
type TokenError [2]rune
func (e TokenError) Error() string {
return "expected " + scanner.TokenString(e[0]) +
", found " + scanner.TokenString(e[1])
}
// ExprError is an unexpected token encountered while parsing an expression.
type ExprError rune
func (e ExprError) Error() string {
return "unexpected token " + scanner.TokenString(rune(e))
}
// must1 returns v, or panics if err is not nil.
func must1[T any](v T, err error) T {
if err != nil {
panic(err)
}
return v
}
// parser retains the current token.
type parser struct {
s scanner.Scanner
tok rune
}
// scan advances the underlying scanner to the next token, storing its result.
func (p *parser) scan() rune { p.tok = p.s.Scan(); return p.tok }
// expects panics with [TokenError] for an unexpected tok.
func (p *parser) expects(expects rune) {
if p.tok != expects {
panic(TokenError{expects, p.tok})
}
}
// scanAs advances the scanner for an expected token.
func (p *parser) scanAs(expects rune) { p.scan(); p.expects(expects) }
// An Int is the value represented by an integer literal.
type Int int64
func (v Int) GoString() string {
return "azalea.Int(" + strconv.FormatInt(int64(v), 10) + ")"
}
// parseInt parses the current token as a base 10 representation of a 64-bit
// signed integer.
func (p *parser) parseInt() Int {
v, err := strconv.ParseInt(p.s.TokenText(), 10, 64)
return must1(Int(v), err)
}
// A String holds the unquoted content of a string literal.
type String string
func (v String) GoString() string {
return "azalea.String(" + strconv.Quote(string(v)) + ")"
}
// parseString parses the current token as a string.
func (p *parser) parseString() String {
s, err := strconv.Unquote(p.s.TokenText())
return must1(String(s), err)
}
// An Ident holds the name of an identifier.
type Ident string
func (v Ident) GoString() string {
return "azalea.Ident(" + strconv.Quote(string(v)) + ")"
}
// A Val are statements joined by the '+' operator. Only the [String] type
// supports concatenation.
type Val []any
// parseVal parses until the end of the [Val].
func (p *parser) parseVal() (v Val) {
v = append(v, p.parseExpr())
for p.tok == '+' {
p.scan()
v = append(v, p.parseExpr())
}
return
}
// An Array holds statements in an array.
type Array []Val
// A KV holds a key/value pair.
type KV struct {
K String
V Val
}
// An Arg represents an argument of [Func].
type Arg struct {
K []Ident
V Val
R bool
}
// Func is a function call or package declaration.
type Func struct {
// Function or package identifier.
Ident Ident
// Whether this is a package declaration.
Package bool
// Key-value arguments.
Args []Arg
}
// parseExpr parses the current expression.
func (p *parser) parseExpr() any {
switch p.tok {
case scanner.Int:
v := p.parseInt()
p.scan()
return v
case scanner.String, scanner.RawString:
v := p.parseString()
p.scan()
return v
case scanner.Ident:
var v Func
v.Ident = Ident(p.s.TokenText())
if v.Package = v.Ident == "package"; v.Package {
p.scanAs(scanner.Ident)
v.Ident = Ident(p.s.TokenText())
}
p.scan()
switch p.tok {
case '{':
for {
p.scan()
switch p.tok {
case '}':
p.scan()
return v
case scanner.Ident:
break
default:
panic(TokenError{scanner.Ident, p.tok})
}
arg := Arg{K: []Ident{Ident(p.s.TokenText())}}
delim := true
arg:
for {
p.scan()
switch p.tok {
case ',':
if delim {
delim = false
continue
}
panic(ExprError(p.tok))
case scanner.Ident:
if delim {
panic(TokenError{',', p.tok})
}
delim = true
arg.K = append(arg.K, Ident(p.s.TokenText()))
default:
break arg
}
}
switch p.tok {
case '=':
break
case '*':
arg.R = true
p.scanAs('=')
default:
panic(TokenError{'=', p.tok})
}
p.scan()
arg.V = p.parseVal()
v.Args = append(v.Args, arg)
p.expects(';')
}
default:
return v.Ident
}
case '{':
var v []KV
for {
p.scan()
switch p.tok {
case '}':
p.scan()
return v
case scanner.String:
pair := KV{K: p.parseString()}
p.scan()
switch p.tok {
case ';':
break
case ':':
p.scan()
pair.V = p.parseVal()
p.expects(';')
break
default:
panic(ExprError(p.tok))
}
v = append(v, pair)
default:
panic(ExprError(p.tok))
}
}
case '[':
var (
v Array
delim bool
)
p.scan()
for {
switch p.tok {
case ',':
if delim {
p.scan()
delim = false
continue
}
panic(ExprError(','))
case ']':
p.scan()
return v
case scanner.EOF:
panic(ExprError(scanner.EOF))
default:
if delim {
panic(TokenError{',', p.tok})
}
delim = true
break
}
v = append(v, p.parseVal())
}
default:
panic(ExprError(p.tok))
}
}
// ScanError is the error count parsing all expressions.
type ScanError int
func (ScanError) Error() string {
return "aborting due to scanning errors"
}
// Parse parses expressions from r.
func Parse(r io.Reader) (e []any, err error) {
var p parser
p.s.Init(r)
p.s.Mode = scanner.ScanIdents |
scanner.ScanInts |
scanner.ScanStrings |
scanner.ScanRawStrings |
scanner.ScanComments |
scanner.SkipComments
p.s.IsIdentRune = func(ch rune, i int) bool {
if i == 0 && ch >= '0' && ch <= '9' {
return false
}
return ch > 0 && ch < rune(len(idents)) && idents[ch]
}
defer func() {
v := recover()
if v == nil {
return
}
_err, ok := v.(error)
if !ok {
panic(v)
}
if err == nil {
err = _err
return
}
err = errors.Join(err, _err)
}()
p.scan()
for p.tok != scanner.EOF {
e = append(e, p.parseExpr())
}
if p.s.ErrorCount != 0 {
err = ScanError(p.s.ErrorCount)
}
return
}

View File

@@ -1,169 +0,0 @@
package azalea_test
import (
_ "embed"
"reflect"
"strings"
"testing"
"text/scanner"
. "hakurei.app/internal/rosa/azalea"
)
//go:embed testdata/gcc.az
var sample string
func TestParse(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
data string
want []any
err error
}{
{"invalid", "}", nil, ExprError('}')},
{"bad sep", "f{v?}", nil, TokenError{'=', '?'}},
{"bad ident", "f{9}", nil, TokenError{scanner.Ident, scanner.Int}},
{"share bad sep", "f { v,,v = v; }", nil, ExprError(',')},
{"share missing sep", "f { v v }", nil, TokenError{',', scanner.Ident}},
{"ident", `v`, []any{Ident("v")}, nil},
{"concat", `f { v = v+"\xfd"+p{}+9; }`, []any{Func{
Ident: "f",
Args: []Arg{{K: []Ident{"v"}, V: Val{
Ident("v"),
String("\xfd"),
Func{Ident: "p"},
Int(9),
}}},
}}, nil},
{"truncated string concat", `f { v = v+; }`, nil,
ExprError(';')},
{"empty pairs", `{}`, []any{[]KV(nil)}, nil},
{"short kv", `{"\x00":v;}`, []any{[]KV{
{K: "\x00", V: Val{Ident("v")}},
}}, nil},
{"truncated kv", `{"\x00"`, nil, ExprError(scanner.EOF)},
{"ident kv", `{v="";}`, nil, ExprError(scanner.Ident)},
{"empty array", `[]`, []any{Array(nil)}, nil},
{"integer array", `[9]`, []any{Array{{Int(9)}}}, nil},
{"short array", `[ "\x00" ]`, []any{
Array{{String("\x00")}},
}, nil},
{"short array delim", `[ "\x00", ]`, []any{
Array{{String("\x00")}},
}, nil},
{"missing array value", `[ "\x00", , v ]`, nil, ExprError(',')},
{"missing array delimiter", `[ v0 v1 ]`, nil, TokenError{',', scanner.Ident}},
{"truncated array", `[ "\x00"`, nil,
ExprError(scanner.EOF)},
{"gcc", sample, []any{Func{
Ident: Ident("gcc"),
Package: true,
Args: []Arg{
{K: []Ident{Ident("description")}, V: Val{String("The GNU Compiler Collection")}},
{K: []Ident{Ident("website")}, V: Val{String("https://www.gnu.org/software/gcc")}},
{K: []Ident{Ident("anitya")}, V: Val{Int(6502)}},
{K: []Ident{Ident("version")}, V: Val{String("16.1.0")}, R: true},
{K: []Ident{Ident("source")}, V: Val{Func{
Ident: Ident("remoteTar"),
Args: []Arg{
{K: []Ident{Ident("url")}, V: Val{
String("https://ftp.tsukuba.wide.ad.jp/software/gcc/releases/"),
String("gcc-"),
Ident("version"),
String("/gcc-"),
Ident("version"),
String(".tar.gz"),
}},
{K: []Ident{Ident("checksum")}, V: Val{String("4ASoWbxaA2FW7PAB0zzHDPC5XnNhyaAyjtDPpGzceSLeYnEIXsNYZR3PA_Zu5P0K")}},
{K: []Ident{Ident("compress")}, V: Val{Ident("gzip")}},
},
}}},
{K: []Ident{Ident("patches")}, V: Val{Array{
{String("musl-off64_t-loff_t.patch")},
{String("musl-legacy-lfs.patch")},
}}},
{K: []Ident{Ident("exclusive")}, V: Val{Ident("true")}},
{K: []Ident{Ident("exec")}, V: Val{Func{
Ident: Ident("make"),
Args: []Arg{
{K: []Ident{Ident("configure")}, V: Val{[]KV{
{K: String("disable-multilib")},
{K: String("enable-default-pie")},
{K: String("disable-nls")},
{K: String("with-gnu-as")},
{K: String("with-gnu-ld")},
{K: String("with-system-zlib")},
{K: String("enable-languages"), V: Val{String("c,c++,go")}},
{K: String("with-native-system-header-dir"), V: Val{String("/system/include")}},
{K: String("with-multilib-list"), V: Val{Func{
Ident: Ident("arch"),
Args: []Arg{
{K: []Ident{Ident("amd64"), Ident("arm64")}, V: Val{String("''")}},
{K: []Ident{Ident("default")}, V: Val{Ident("unset")}},
},
}}},
}}},
{K: []Ident{Ident("make")}, V: Val{Array{
{String("BOOT_CFLAGS='-O2 -g'")},
{
Func{Ident: Ident("noop"), Args: []Arg{{K: []Ident{Ident("key")}, V: Val{Ident("value")}}}},
String("\x00"),
},
{String("bootstrap")},
}}},
{K: []Ident{Ident("skip-check")}, V: Val{Ident("true")}},
},
}}},
{K: []Ident{Ident("inputs")}, V: Val{Array{
{Ident("binutils")},
{Ident("mpc")},
{Ident("zlib")},
{Ident("libucontext")},
{Ident("kernel-headers")},
}}},
},
}}, nil},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
p, err := Parse(strings.NewReader(tc.data))
if !reflect.DeepEqual(p, tc.want) {
t.Errorf("Parse: %#v, want %#v", p, tc.want)
}
if !reflect.DeepEqual(err, tc.err) {
t.Errorf("Parse: error = %v, want %v", err, tc.err)
}
})
}
}
func BenchmarkParse(b *testing.B) {
r := strings.NewReader(sample)
for b.Loop() {
if _, err := Parse(r); err != nil {
b.Fatal(err)
}
b.StopTimer()
r.Reset(sample)
b.StartTimer()
}
}

View File

@@ -1,308 +0,0 @@
package azalea
import (
"errors"
"fmt"
"maps"
"reflect"
"unique"
)
// Value are types supported by the language.
type Value interface {
bool | int64 | string | []string | [][2]string
}
type (
// FArg is an argument passed to [F].
FArg struct {
K unique.Handle[Ident]
V any
R bool
}
// FArgs are arguments passed to [F].
FArgs []FArg
// F is the implementation of a [Func].
F struct {
F func(isPackage bool, args FArgs) (v any, set bool, err error)
V map[unique.Handle[Ident]]any
}
)
// Apply applies named arguments and rejects unused arguments.
func (args FArgs) Apply(v map[unique.Handle[Ident]]any) error {
for _, arg := range args {
if arg.V == nil {
// unset
continue
}
r, ok := v[arg.K]
if !ok {
if arg.R {
continue
}
return UndefinedError(arg.K.Value())
}
err := storeE(r, arg.V)
if err != nil {
return err
}
}
return nil
}
// A Frame refers to local variables and debugging information.
type Frame struct {
// Local constants.
Val map[unique.Handle[Ident]]any
// Functions.
Func map[unique.Handle[Ident]]F
}
// UnsupportedExprError is an expression with invalid concrete type.
type UnsupportedExprError struct{ E any }
func (e UnsupportedExprError) Error() string {
return fmt.Sprintf("unsupported expression %#v", e.E)
}
// UndefinedError is an identifier not defined in any stack frame visible to the
// expression containing it.
type UndefinedError Ident
func (e UndefinedError) Error() string {
return "undefined: " + string(e)
}
// evaluate is evaluateAny with a type parameter.
func evaluate[T Value](s []Frame, expr any, rp *T) bool {
return evaluateAny(s, expr, rp)
}
// TypeError is an unexpected type during evaluation.
type TypeError struct {
Concrete, Asserted reflect.Type
}
func (e TypeError) Error() string {
return "expected " + e.Asserted.String() + ", got " + e.Concrete.String()
}
func (e TypeError) Is(err error) bool {
var v TypeError
return errors.As(err, &v) &&
e.Asserted == v.Asserted &&
e.Concrete == v.Concrete
}
// storeE is a convenience function to set the value of a result pointer.
func storeE(rp any, r any) error {
pv := reflect.ValueOf(rp).Elem()
v := reflect.ValueOf(r)
pt, vt := pv.Type(), v.Type()
if !vt.AssignableTo(pt) {
return TypeError{vt, pt}
}
pv.Set(v)
return nil
}
// store is like storeE, but panics if error is non-nil.
func store[T Value](rp any, r T) {
err := storeE(rp, r)
if err != nil {
panic(err)
}
}
// EvaluationError is an error and the expression it occurred in.
type EvaluationError struct {
Expr any
Err error
}
// Unwrap returns the underlying error.
func (e EvaluationError) Unwrap() error { return e.Err }
// Error returns a very long error description that should not be presented
// to the user directly.
func (e EvaluationError) Error() string {
return fmt.Sprintf("expression %#v: %v", e.Expr, e.Err)
}
// evaluateAny implements [Evaluate].
func evaluateAny(s []Frame, expr, rp any) bool {
defer func() {
r := recover()
if r == nil {
return
}
err, ok := r.(error)
if !ok {
panic(r)
}
if _, ok = err.(EvaluationError); ok {
panic(err)
}
panic(EvaluationError{expr, err})
}()
switch e := expr.(type) {
case Int:
store(rp, int64(e))
return true
case String:
store(rp, string(e))
return true
case Ident:
var (
v any
ok bool
)
for i := range s {
v, ok = s[len(s)-1-i].Val[unique.Make(e)]
if ok {
break
}
}
if !ok {
panic(UndefinedError(e))
}
if err := storeE(rp, v); err != nil {
panic(err)
}
return true
case Val:
if len(e) == 1 {
switch v := e[0].(type) {
case Ident:
switch v {
case "unset":
return false
case "true":
store(rp, true)
return true
case "false":
store(rp, false)
return true
default:
return evaluateAny(s, v, rp)
}
default:
return evaluateAny(s, e[0], rp)
}
}
var v string
for i := range e {
var _r string
if evaluate(s, e[i], &_r) {
v += _r
}
}
store(rp, v)
return true
case Array:
r := make([]string, 0, len(e))
for i := range e {
var _r string
if evaluate(s, e[i], &_r) {
r = append(r, _r)
}
}
store(rp, r)
return true
case []KV:
r := make([][2]string, 0, len(e))
for i := range e {
var _r string
if e[i].V == nil || evaluate(s, e[i].V, &_r) {
r = append(r, [2]string{string(e[i].K), _r})
}
}
store(rp, r)
return true
case Func:
var (
f F
ok bool
)
for i := range s {
f, ok = s[len(s)-1-i].Func[unique.Make(e.Ident)]
if ok {
break
}
}
if !ok {
panic(UndefinedError(e.Ident))
}
argc := len(e.Args)
for _, arg := range e.Args {
argc += len(arg.K) - 1
}
fargs := make([]FArg, 0, len(e.Args))
s = append(s, Frame{Val: maps.Clone(f.V)})
fp := &s[len(s)-1]
for _, arg := range e.Args {
farg := FArg{R: arg.R}
if !evaluateAny(s, arg.V, &farg.V) {
farg.V = nil
}
for _, name := range arg.K {
h := unique.Make(name)
farg.K = h
fargs = append(fargs, farg)
if arg.R && farg.V != nil {
if fp.Val == nil {
fp.Val = make(map[unique.Handle[Ident]]any)
}
(*fp).Val[h] = farg.V
}
}
}
v, set, err := f.F(e.Package, fargs)
if err != nil {
panic(err)
} else if v != nil {
if err = storeE(rp, v); err != nil {
panic(err)
}
}
return set
default:
panic(UnsupportedExprError{expr})
}
}
// Evaluate evaluates a statement and returns its value.
func Evaluate[T Value](s []Frame, expr any) (v T, set bool, err error) {
defer func() {
r := recover()
if r == nil {
return
}
_err, ok := r.(error)
if !ok {
panic(r)
}
err = _err
}()
set = evaluate[T](s, expr, &v)
return
}

View File

@@ -1,358 +0,0 @@
package azalea_test
import (
"errors"
"fmt"
"reflect"
"strings"
"testing"
"unique"
. "hakurei.app/internal/rosa/azalea"
)
// makeStackCheck creates a stack with a single frame with a single function "f"
// which calls the check function internally.
func makeStackCheck(check func(args FArgs) (any, error)) []Frame {
return []Frame{{Func: map[unique.Handle[Ident]]F{
unique.Make(Ident("f")): {F: func(
isPackage bool,
args FArgs,
) (v any, set bool, err error) {
set = true
v, err = check(args)
if isPackage {
err = errors.New("unexpected package")
}
return
}},
}}}
}
func TestEvaluate(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
data string
s []Frame
want string
err error
}{
{"apply unset", `f { v = unset; }`, makeStackCheck(func(
args FArgs,
) (v any, err error) {
v = "\xfd"
err = args.Apply(map[unique.Handle[Ident]]any{
unique.Make(Ident("v")): &v,
})
return
}), "\xfd", nil},
{"apply bad type", `f { v = 9; }`, makeStackCheck(func(
args FArgs,
) (v any, err error) {
v = "\xfd"
err = args.Apply(map[unique.Handle[Ident]]any{
unique.Make(Ident("v")): &v,
})
return
}), "", TypeError{
Concrete: reflect.TypeFor[int64](),
Asserted: reflect.TypeFor[string](),
}},
{"apply undefined", `f { v = 9; }`, makeStackCheck(func(
args FArgs,
) (v any, err error) {
v = "\xfd"
err = args.Apply(map[unique.Handle[Ident]]any{})
return
}), "", EvaluationError{
Expr: Func{
Ident: Ident("f"),
Args: []Arg{
{K: []Ident{"v"}, V: Val{Int(9)}},
},
},
Err: UndefinedError("v"),
}},
{"apply bound undefined", `f { _v* = "\x00"; v = _v; }`, makeStackCheck(func(
args FArgs,
) (v any, err error) {
v = "\xfd"
err = args.Apply(map[unique.Handle[Ident]]any{
unique.Make(Ident("v")): &v,
})
return
}), "\x00", nil},
{"undefined function", `f {}`, nil, "", EvaluationError{
Expr: Func{Ident: "f"},
Err: UndefinedError("f"),
}},
{"error wrap deep", `f { v = nil; }`, makeStackCheck(func(
FArgs,
) (any, error) {
panic("unreachable")
}), "", EvaluationError{
Expr: Ident("nil"),
Err: UndefinedError("nil"),
}},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
var expr Func
if e, err := Parse(strings.NewReader(tc.data)); err != nil {
t.Fatal(err)
} else if len(e) != 1 {
t.Fatalf("got expression %#v", e)
} else {
expr = e[0].(Func)
}
r, set, err := Evaluate[string](tc.s, expr)
if set != (err == nil) {
t.Error("Evaluate: unexpected unset")
}
if r != tc.want {
t.Errorf("Evaluate: %q, want %q", r, tc.want)
}
var errEquals bool
if errors.As(err, new(TypeError)) {
errEquals = errors.Is(err, tc.err)
} else {
errEquals = reflect.DeepEqual(err, tc.err)
}
if !errEquals {
t.Errorf("Evaluate: error = %v, want %v", err, tc.err)
}
})
}
}
func TestEvaluateGCC(t *testing.T) {
t.Parallel()
var gcc Func
if e, err := Parse(strings.NewReader(sample)); err != nil {
t.Fatal(err)
} else {
gcc = e[0].(Func)
}
var got [3]FArgs
if r, set, err := Evaluate[string]([]Frame{{
Func: map[unique.Handle[Ident]]F{
unique.Make(Ident("gcc")): {F: func(
isPackage bool,
args FArgs,
) (v any, set bool, err error) {
v = "\x00"
if !isPackage {
err = errors.New("not a package")
}
set = true
got[0] = args
return
}, V: map[unique.Handle[Ident]]any{
unique.Make(Ident("binutils")): "binutils",
unique.Make(Ident("mpc")): "mpc",
unique.Make(Ident("zlib")): "zlib",
unique.Make(Ident("libucontext")): "libucontext",
unique.Make(Ident("kernel-headers")): "kernel-headers",
}},
unique.Make(Ident("remoteTar")): {F: func(
isPackage bool,
args FArgs,
) (v any, set bool, err error) {
if isPackage {
err = errors.New("unexpected package")
return
}
var url, checksum string
var compress int
if err = args.Apply(map[unique.Handle[Ident]]any{
unique.Make(Ident("url")): &url,
unique.Make(Ident("checksum")): &checksum,
unique.Make(Ident("compress")): &compress,
}); err != nil {
return
}
if compress != 0xcafe {
err = fmt.Errorf("unexpected compress %#v", compress)
}
set = true
v = url + "?checksum=" + checksum
return
}, V: map[unique.Handle[Ident]]any{
unique.Make(Ident("gzip")): 0xcafe,
}},
unique.Make(Ident("make")): {F: func(
isPackage bool,
args FArgs,
) (v any, set bool, err error) {
v = args
if isPackage {
err = errors.New("unexpected package")
}
set = true
return
}},
unique.Make(Ident("arch")): {F: func(
isPackage bool,
args FArgs,
) (v any, set bool, err error) {
set = false
if isPackage {
err = errors.New("unexpected package")
}
got[1] = args
return
}},
unique.Make(Ident("noop")): {F: func(
isPackage bool,
args FArgs,
) (v any, set bool, err error) {
set = false
if isPackage {
err = errors.New("unexpected package")
}
set = true
got[2] = args
return
}, V: map[unique.Handle[Ident]]any{
unique.Make(Ident("value")): "\xfd",
}},
},
}}, gcc); err != nil {
t.Fatal(err)
} else if r != "\x00" {
t.Fatalf("package: %q", r)
} else if !set {
t.Fatal("package: unset")
}
want := [...]FArgs{
{
{K: unique.Make(Ident("description")), V: "The GNU Compiler Collection"},
{K: unique.Make(Ident("website")), V: "https://www.gnu.org/software/gcc"},
{K: unique.Make(Ident("anitya")), V: int64(6502)},
{K: unique.Make(Ident("version")), V: "16.1.0", R: true},
{K: unique.Make(Ident("source")), V: "https://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-16.1.0/gcc-16.1.0.tar.gz?checksum=4ASoWbxaA2FW7PAB0zzHDPC5XnNhyaAyjtDPpGzceSLeYnEIXsNYZR3PA_Zu5P0K"},
{K: unique.Make(Ident("patches")), V: []string{"musl-off64_t-loff_t.patch", "musl-legacy-lfs.patch"}},
{K: unique.Make(Ident("exclusive")), V: true},
{K: unique.Make(Ident("exec")), V: FArgs{
{K: unique.Make(Ident("configure")), V: [][2]string{
{"disable-multilib", ""},
{"enable-default-pie", ""},
{"disable-nls", ""},
{"with-gnu-as", ""},
{"with-gnu-ld", ""},
{"with-system-zlib", ""},
{"enable-languages", "c,c++,go"},
{"with-native-system-header-dir", "/system/include"},
}},
{K: unique.Make(Ident("make")), V: []string{
"BOOT_CFLAGS='-O2 -g'",
"\x00",
"bootstrap",
}},
{K: unique.Make(Ident("skip-check")), V: true},
}},
{K: unique.Make(Ident("inputs")), V: []string{
"binutils",
"mpc",
"zlib",
"libucontext",
"kernel-headers",
}},
},
{
{K: unique.Make(Ident("amd64")), V: "''"},
{K: unique.Make(Ident("arm64")), V: "''"},
{K: unique.Make(Ident("default"))},
},
{{K: unique.Make(Ident("key")), V: "\xfd"}},
}
if !reflect.DeepEqual(got, want) {
t.Errorf("package: args = %#v, want %#v", got, want)
}
}
func BenchmarkEvaluate(b *testing.B) {
var gcc Func
if e, err := Parse(strings.NewReader(sample)); err != nil {
b.Fatal(err)
} else {
gcc = e[0].(Func)
}
s := []Frame{{
Func: map[unique.Handle[Ident]]F{
unique.Make(Ident("gcc")): {F: func(
bool,
FArgs,
) (v any, set bool, err error) {
return
}, V: map[unique.Handle[Ident]]any{
unique.Make(Ident("binutils")): "binutils",
unique.Make(Ident("mpc")): "mpc",
unique.Make(Ident("zlib")): "zlib",
unique.Make(Ident("libucontext")): "libucontext",
unique.Make(Ident("kernel-headers")): "kernel-headers",
}},
unique.Make(Ident("remoteTar")): {F: func(
bool,
FArgs,
) (v any, set bool, err error) {
return
}, V: map[unique.Handle[Ident]]any{
unique.Make(Ident("gzip")): 0xcafe,
}},
unique.Make(Ident("make")): {F: func(
bool,
FArgs,
) (v any, set bool, err error) {
return
}},
unique.Make(Ident("arch")): {F: func(
bool,
FArgs,
) (v any, set bool, err error) {
return
}},
unique.Make(Ident("noop")): {F: func(
bool,
FArgs,
) (v any, set bool, err error) {
return
}, V: map[unique.Handle[Ident]]any{
unique.Make(Ident("value")): "\xfd",
}},
},
}}
for b.Loop() {
if _, _, err := Evaluate[string](s, gcc); err != nil {
b.Fatal(err)
}
}
}

View File

@@ -1,57 +0,0 @@
package gcc {
description = "The GNU Compiler Collection";
website = "https://www.gnu.org/software/gcc";
anitya = 6502;
version* = "16.1.0";
source = remoteTar {
url = "https://ftp.tsukuba.wide.ad.jp/software/gcc/releases/"+
"gcc-"+version+"/gcc-"+version+".tar.gz";
checksum = "4ASoWbxaA2FW7PAB0zzHDPC5XnNhyaAyjtDPpGzceSLeYnEIXsNYZR3PA_Zu5P0K";
compress = gzip;
};
patches = [
"musl-off64_t-loff_t.patch",
"musl-legacy-lfs.patch",
];
// GCC spends most of its time in its many configure scripts, however
// it also saturates the CPU for a consequential amount of time.
exclusive = true;
exec = make {
configure = {
"disable-multilib";
"enable-default-pie";
"disable-nls";
"with-gnu-as";
"with-gnu-ld";
"with-system-zlib";
"enable-languages": "c,c++,go";
"with-native-system-header-dir": "/system/include";
"with-multilib-list": arch {
amd64, arm64 = "''";
default = unset;
};
};
make = [
"BOOT_CFLAGS='-O2 -g'",
noop { key = value; } + "\x00",
"bootstrap",
];
// This toolchain is hacked to pieces, it is not expected to ever work
// well in its current state. That does not matter as long as the
// toolchain it produces passes its own test suite.
skip-check = true;
};
inputs = [
binutils,
mpc,
zlib,
libucontext,
kernel-headers,
];
}

View File

@@ -85,13 +85,13 @@ func (a busyboxBin) Cure(t *pkg.TContext) (err error) {
// newBusyboxBin returns a [pkg.Artifact] containing a busybox installation from
// the https://busybox.net/downloads/binaries/ binary release.
func (s *S) newBusyboxBin() pkg.Artifact {
func newBusyboxBin() pkg.Artifact {
var version, url, checksum string
switch s.arch {
switch arch {
case "amd64":
version = "1.35.0"
url = "https://busybox.net/downloads/binaries/" +
version + "-" + s.linuxArch() + "-linux-musl/busybox"
version + "-" + linuxArch() + "-linux-musl/busybox"
checksum = "L7OBIsPu9enNHn7FqpBT1kOg_mCLNmetSeNMA3i4Y60Z5jTgnlX3qX3zcQtLx5AB"
case "arm64":
version = "1.31.0"
@@ -100,11 +100,11 @@ func (s *S) newBusyboxBin() pkg.Artifact {
checksum = "npJjBO7iwhjW6Kx2aXeSxf8kXhVgTCDChOZTTsI8ZfFfa3tbsklxRiidZQdrVERg"
default:
panic("unsupported target " + s.arch)
panic("unsupported target " + arch)
}
return pkg.NewExec(
"busybox-bin-"+version, s.arch, nil, pkg.ExecTimeoutMax, false, false,
"busybox-bin-"+version, arch, nil, pkg.ExecTimeoutMax, false, false,
fhs.AbsRoot, []string{
"PATH=/system/bin",
},

View File

@@ -26,7 +26,7 @@ func (t Toolchain) newBzip2() (pkg.Artifact, string) {
}), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Bzip2] = Metadata{
f: Toolchain.newBzip2,
Name: "bzip2",
@@ -34,5 +34,5 @@ func init() {
Website: "https://sourceware.org/bzip2/",
ID: 237,
})
}
}

View File

@@ -106,7 +106,7 @@ index 2ead810437..f85cbb8b1c 100644
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[CMake] = Metadata{
f: Toolchain.newCMake,
Name: "cmake",
@@ -114,7 +114,7 @@ func init() {
Website: "https://cmake.org/",
ID: 306,
})
}
}
// CMakeHelper is the [CMake] build system helper.
@@ -164,7 +164,7 @@ func (*CMakeHelper) createDir() bool { return true }
func (*CMakeHelper) wantsDir() string { return "/cure/" }
// script generates the cure script.
func (attr *CMakeHelper) script(s *S, name string) string {
func (attr *CMakeHelper) script(name string) string {
if attr == nil {
attr = new(CMakeHelper)
}
@@ -180,7 +180,7 @@ func (attr *CMakeHelper) script(s *S, name string) string {
}
script := attr.Script
if !attr.SkipTest && s.opts&OptSkipCheck == 0 {
if !attr.SkipTest && presetOpts&OptSkipCheck == 0 {
script += "\n" + test
}

View File

@@ -90,7 +90,7 @@ func (t Toolchain) newConnman() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Connman] = Metadata{
f: Toolchain.newConnman,
Name: "connman",
@@ -105,5 +105,5 @@ func init() {
},
ID: 337,
})
}
}

View File

@@ -39,7 +39,7 @@ chmod +w tests/data && rm -f tests/data/test459
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Curl] = Metadata{
f: Toolchain.newCurl,
Name: "curl",
@@ -52,5 +52,5 @@ func init() {
},
ID: 381,
})
}
}

View File

@@ -29,7 +29,7 @@ func (t Toolchain) newDBus() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[DBus] = Metadata{
f: Toolchain.newDBus,
Name: "dbus",
@@ -42,7 +42,7 @@ func init() {
},
ID: 5356,
})
}
}
func (t Toolchain) newXDGDBusProxy() (pkg.Artifact, string) {
@@ -65,7 +65,7 @@ func (t Toolchain) newXDGDBusProxy() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[XDGDBusProxy] = Metadata{
f: Toolchain.newXDGDBusProxy,
Name: "xdg-dbus-proxy",
@@ -77,5 +77,5 @@ func init() {
},
ID: 58434,
})
}
}

View File

@@ -31,7 +31,7 @@ func (t Toolchain) newDTC() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[DTC] = Metadata{
f: Toolchain.newDTC,
Name: "dtc",
@@ -39,5 +39,5 @@ func init() {
Website: "https://git.kernel.org/pub/scm/utils/dtc/dtc.git/",
ID: 16911,
})
}
}

View File

@@ -39,7 +39,7 @@ func (t Toolchain) newElfutils() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Elfutils] = Metadata{
f: Toolchain.newElfutils,
Name: "elfutils",
@@ -55,5 +55,5 @@ func init() {
},
ID: 5679,
})
}
}

View File

@@ -46,7 +46,7 @@ index f135ad9..85c784c 100644
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Fakeroot] = Metadata{
f: Toolchain.newFakeroot,
Name: "fakeroot",
@@ -54,5 +54,5 @@ func init() {
Website: "https://salsa.debian.org/clint/fakeroot",
ID: 12048,
})
}
}

View File

@@ -20,7 +20,7 @@ func (t Toolchain) newFlex() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Flex] = Metadata{
f: Toolchain.newFlex,
Name: "flex",
@@ -28,5 +28,5 @@ func init() {
Website: "https://github.com/westes/flex/",
ID: 819,
})
}
}

View File

@@ -15,7 +15,7 @@ func (t Toolchain) newFreetype() (pkg.Artifact, string) {
), nil, (*MakeHelper)(nil)), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Freetype] = Metadata{
f: Toolchain.newFreetype,
Name: "freetype",
@@ -23,5 +23,5 @@ func init() {
Website: "http://www.freetype.org/",
ID: 854,
})
}
}

View File

@@ -31,7 +31,7 @@ func (t Toolchain) newFuse() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Fuse] = Metadata{
f: Toolchain.newFuse,
Name: "fuse",
@@ -39,5 +39,5 @@ func init() {
Website: "https://github.com/libfuse/libfuse/",
ID: 861,
})
}
}

View File

@@ -88,7 +88,7 @@ disable_test t5515-fetch-merge-logic
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Git] = Metadata{
f: Toolchain.newGit,
Name: "git",
@@ -102,7 +102,7 @@ func init() {
},
ID: 5350,
})
}
}
// NewViaGit returns a [pkg.Artifact] for cloning a git repository.
@@ -113,7 +113,7 @@ func (t Toolchain) NewViaGit(
return t.New(strings.TrimSuffix(
path.Base(url),
".git",
)+"-src-"+path.Base(rev), THostNet, t.Append(nil,
)+"-src-"+path.Base(rev), THostNet, t.AppendPresets(nil,
NSSCACert,
Git,
), &checksum, nil, `

View File

@@ -22,7 +22,7 @@ func (t Toolchain) newSPIRVHeaders() (pkg.Artifact, string) {
}), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[SPIRVHeaders] = Metadata{
f: Toolchain.newSPIRVHeaders,
Name: "spirv-headers",
@@ -49,7 +49,7 @@ func init() {
}
return v.Latest
},
})
}
}
func (t Toolchain) newSPIRVTools() (pkg.Artifact, string) {
@@ -72,7 +72,7 @@ func (t Toolchain) newSPIRVTools() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[SPIRVTools] = Metadata{
f: Toolchain.newSPIRVTools,
Name: "spirv-tools",
@@ -86,7 +86,7 @@ func init() {
ID: 14894,
latest: (*Versions).getStable,
})
}
}
func (t Toolchain) newGlslang() (pkg.Artifact, string) {
@@ -116,7 +116,7 @@ func (t Toolchain) newGlslang() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Glslang] = Metadata{
f: Toolchain.newGlslang,
Name: "glslang",
@@ -124,7 +124,7 @@ func init() {
Website: "https://github.com/KhronosGroup/glslang",
ID: 205796,
})
}
}
func (t Toolchain) newSPIRVLLVMTranslator() (pkg.Artifact, string) {
@@ -137,7 +137,7 @@ func (t Toolchain) newSPIRVLLVMTranslator() (pkg.Artifact, string) {
"cooperative_matrix_constant_null.spvasm",
}
switch t.arch {
switch arch {
case "arm64":
skipChecks = append(skipChecks,
// LLVM ERROR: unsupported calling convention
@@ -232,7 +232,7 @@ export LIT_OPTS=` + litArgs(true, skipChecks...) + `
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[SPIRVLLVMTranslator] = Metadata{
f: Toolchain.newSPIRVLLVMTranslator,
Name: "spirv-llvm-translator",
@@ -244,5 +244,5 @@ func init() {
},
ID: 227273,
})
}
}

View File

@@ -63,7 +63,7 @@ chmod +w tests/test-c32ispunct.sh && echo '#!/bin/sh' > tests/test-c32ispunct.sh
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[M4] = Metadata{
f: Toolchain.newM4,
Name: "m4",
@@ -71,7 +71,7 @@ func init() {
Website: "https://www.gnu.org/software/m4/",
ID: 1871,
})
}
}
func (t Toolchain) newBison() (pkg.Artifact, string) {
@@ -98,7 +98,7 @@ func (t Toolchain) newBison() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Bison] = Metadata{
f: Toolchain.newBison,
Name: "bison",
@@ -106,7 +106,7 @@ func init() {
Website: "https://www.gnu.org/software/bison/",
ID: 193,
})
}
}
func (t Toolchain) newSed() (pkg.Artifact, string) {
@@ -125,7 +125,7 @@ func (t Toolchain) newSed() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Sed] = Metadata{
f: Toolchain.newSed,
Name: "sed",
@@ -133,7 +133,7 @@ func init() {
Website: "https://www.gnu.org/software/sed/",
ID: 4789,
})
}
}
func (t Toolchain) newAutoconf() (pkg.Artifact, string) {
@@ -160,7 +160,7 @@ func (t Toolchain) newAutoconf() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Autoconf] = Metadata{
f: Toolchain.newAutoconf,
Name: "autoconf",
@@ -173,7 +173,7 @@ func init() {
},
ID: 141,
})
}
}
func (t Toolchain) newAutomake() (pkg.Artifact, string) {
@@ -205,7 +205,7 @@ test_disable '#!/bin/sh' t/pr9.sh
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Automake] = Metadata{
f: Toolchain.newAutomake,
Name: "automake",
@@ -217,7 +217,7 @@ func init() {
},
ID: 144,
})
}
}
func (t Toolchain) newLibtool() (pkg.Artifact, string) {
@@ -231,7 +231,7 @@ func (t Toolchain) newLibtool() (pkg.Artifact, string) {
pkg.TarGzip,
), nil, &MakeHelper{
// _Z2a2c: symbol not found
SkipCheck: t.stage.isStage0(),
SkipCheck: t.isStage0(),
Check: []string{
"TESTSUITEFLAGS=" + jobsFlagE,
@@ -243,7 +243,7 @@ func (t Toolchain) newLibtool() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libtool] = Metadata{
f: Toolchain.newLibtool,
Name: "libtool",
@@ -251,7 +251,7 @@ func init() {
Website: "https://www.gnu.org/software/libtool/",
ID: 1741,
})
}
}
func (t Toolchain) newGzip() (pkg.Artifact, string) {
@@ -269,7 +269,7 @@ func (t Toolchain) newGzip() (pkg.Artifact, string) {
}), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Gzip] = Metadata{
f: Toolchain.newGzip,
Name: "gzip",
@@ -277,7 +277,7 @@ func init() {
Website: "https://www.gnu.org/software/gzip/",
ID: 1290,
})
}
}
func (t Toolchain) newGettext() (pkg.Artifact, string) {
@@ -315,7 +315,7 @@ touch gettext-tools/autotools/archive.dir.tar
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Gettext] = Metadata{
f: Toolchain.newGettext,
Name: "gettext",
@@ -323,7 +323,7 @@ func init() {
Website: "https://www.gnu.org/software/gettext/",
ID: 898,
})
}
}
func (t Toolchain) newDiffutils() (pkg.Artifact, string) {
@@ -348,7 +348,7 @@ test_disable '#!/bin/sh' tests/cmp
}, (*MakeHelper)(nil)), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Diffutils] = Metadata{
f: Toolchain.newDiffutils,
Name: "diffutils",
@@ -356,7 +356,7 @@ func init() {
Website: "https://www.gnu.org/software/diffutils/",
ID: 436,
})
}
}
func (t Toolchain) newPatch() (pkg.Artifact, string) {
@@ -380,7 +380,7 @@ test_disable '#!/bin/sh' tests/need-filename
}, (*MakeHelper)(nil)), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Patch] = Metadata{
f: Toolchain.newPatch,
Name: "patch",
@@ -388,7 +388,7 @@ func init() {
Website: "https://savannah.gnu.org/projects/patch/",
ID: 2597,
})
}
}
func (t Toolchain) newBash() (pkg.Artifact, string) {
@@ -410,7 +410,7 @@ func (t Toolchain) newBash() (pkg.Artifact, string) {
}), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Bash] = Metadata{
f: Toolchain.newBash,
Name: "bash",
@@ -418,7 +418,7 @@ func init() {
Website: "https://www.gnu.org/software/bash/",
ID: 166,
})
}
}
func (t Toolchain) newCoreutils() (pkg.Artifact, string) {
@@ -456,7 +456,7 @@ test_disable 'int main(){return 0;}' gnulib-tests/test-lchown.c
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Coreutils] = Metadata{
f: Toolchain.newCoreutils,
Name: "coreutils",
@@ -464,7 +464,7 @@ func init() {
Website: "https://www.gnu.org/software/coreutils/",
ID: 343,
})
}
}
func (t Toolchain) newTexinfo() (pkg.Artifact, string) {
@@ -484,7 +484,7 @@ func (t Toolchain) newTexinfo() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Texinfo] = Metadata{
f: Toolchain.newTexinfo,
Name: "texinfo",
@@ -497,7 +497,7 @@ func init() {
},
ID: 4958,
})
}
}
func (t Toolchain) newGperf() (pkg.Artifact, string) {
@@ -514,7 +514,7 @@ func (t Toolchain) newGperf() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Gperf] = Metadata{
f: Toolchain.newGperf,
Name: "gperf",
@@ -522,7 +522,7 @@ func init() {
Website: "https://www.gnu.org/software/gperf/",
ID: 1237,
})
}
}
func (t Toolchain) newGawk() (pkg.Artifact, string) {
@@ -542,7 +542,7 @@ func (t Toolchain) newGawk() (pkg.Artifact, string) {
}), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Gawk] = Metadata{
f: Toolchain.newGawk,
Name: "gawk",
@@ -550,7 +550,7 @@ func init() {
Website: "https://www.gnu.org/software/gawk/",
ID: 868,
})
}
}
func (t Toolchain) newGrep() (pkg.Artifact, string) {
@@ -575,7 +575,7 @@ test_disable 'int main(){return 0;}' gnulib-tests/test-c32ispunct.c
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Grep] = Metadata{
f: Toolchain.newGrep,
Name: "grep",
@@ -583,7 +583,7 @@ func init() {
Website: "https://www.gnu.org/software/grep/",
ID: 1251,
})
}
}
func (t Toolchain) newFindutils() (pkg.Artifact, string) {
@@ -606,7 +606,7 @@ echo 'int main(){return 0;}' > tests/xargs/test-sigusr.c
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Findutils] = Metadata{
f: Toolchain.newFindutils,
Name: "findutils",
@@ -614,7 +614,7 @@ func init() {
Website: "https://www.gnu.org/software/findutils/",
ID: 812,
})
}
}
func (t Toolchain) newBC() (pkg.Artifact, string) {
@@ -635,7 +635,7 @@ func (t Toolchain) newBC() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[BC] = Metadata{
f: Toolchain.newBC,
Name: "bc",
@@ -643,7 +643,7 @@ func init() {
Website: "https://www.gnu.org/software/bc/",
ID: 170,
})
}
}
func (t Toolchain) newLibiconv() (pkg.Artifact, string) {
@@ -658,7 +658,7 @@ func (t Toolchain) newLibiconv() (pkg.Artifact, string) {
), nil, (*MakeHelper)(nil)), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libiconv] = Metadata{
f: Toolchain.newLibiconv,
Name: "libiconv",
@@ -666,7 +666,7 @@ func init() {
Website: "https://www.gnu.org/software/libiconv/",
ID: 10656,
})
}
}
func (t Toolchain) newTar() (pkg.Artifact, string) {
@@ -700,7 +700,7 @@ func (t Toolchain) newTar() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Tar] = Metadata{
f: Toolchain.newTar,
Name: "tar",
@@ -708,7 +708,7 @@ func init() {
Website: "https://www.gnu.org/software/tar/",
ID: 4939,
})
}
}
func (t Toolchain) newParallel() (pkg.Artifact, string) {
@@ -730,7 +730,7 @@ ln -s ../system/bin/bash /bin/
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Parallel] = Metadata{
f: Toolchain.newParallel,
Name: "parallel",
@@ -742,7 +742,7 @@ func init() {
},
ID: 5448,
})
}
}
func (t Toolchain) newLibunistring() (pkg.Artifact, string) {
@@ -767,7 +767,7 @@ test_disable 'int main(){return 0;}' tests/test-c32ispunct.c
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libunistring] = Metadata{
f: Toolchain.newLibunistring,
Name: "libunistring",
@@ -775,7 +775,7 @@ func init() {
Website: "https://www.gnu.org/software/libunistring/",
ID: 1747,
})
}
}
func (t Toolchain) newLibtasn1() (pkg.Artifact, string) {
@@ -790,7 +790,7 @@ func (t Toolchain) newLibtasn1() (pkg.Artifact, string) {
), nil, (*MakeHelper)(nil)), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libtasn1] = Metadata{
f: Toolchain.newLibtasn1,
Name: "libtasn1",
@@ -798,7 +798,7 @@ func init() {
Website: "https://www.gnu.org/software/libtasn1/",
ID: 1734,
})
}
}
func (t Toolchain) newReadline() (pkg.Artifact, string) {
@@ -820,7 +820,7 @@ func (t Toolchain) newReadline() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Readline] = Metadata{
f: Toolchain.newReadline,
Name: "readline",
@@ -832,7 +832,7 @@ func init() {
},
ID: 4173,
})
}
}
func (t Toolchain) newGnuTLS() (pkg.Artifact, string) {
@@ -842,7 +842,7 @@ func (t Toolchain) newGnuTLS() (pkg.Artifact, string) {
)
var configureExtra []KV
switch t.arch {
switch arch {
case "arm64":
configureExtra = []KV{
{"disable-hardware-acceleration"},
@@ -997,7 +997,7 @@ index 1b78b8cf1..350156a86 100644
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[GnuTLS] = Metadata{
f: Toolchain.newGnuTLS,
Name: "gnutls",
@@ -1013,7 +1013,7 @@ func init() {
},
ID: 1221,
})
}
}
func (t Toolchain) newBinutils() (pkg.Artifact, string) {
@@ -1030,7 +1030,7 @@ func (t Toolchain) newBinutils() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Binutils] = Metadata{
f: Toolchain.newBinutils,
Name: "binutils",
@@ -1038,7 +1038,7 @@ func init() {
Website: "https://www.gnu.org/software/binutils/",
ID: 7981,
})
}
}
func (t Toolchain) newGMP() (pkg.Artifact, string) {
@@ -1060,7 +1060,7 @@ func (t Toolchain) newGMP() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[GMP] = Metadata{
f: Toolchain.newGMP,
Name: "gmp",
@@ -1068,7 +1068,7 @@ func init() {
Website: "https://gmplib.org/",
ID: 1186,
})
}
}
func (t Toolchain) newMPFR() (pkg.Artifact, string) {
@@ -1086,7 +1086,7 @@ func (t Toolchain) newMPFR() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[MPFR] = Metadata{
f: Toolchain.newMPFR,
Name: "mpfr",
@@ -1098,7 +1098,7 @@ func init() {
},
ID: 2019,
})
}
}
func (t Toolchain) newMPC() (pkg.Artifact, string) {
@@ -1125,7 +1125,7 @@ func (t Toolchain) newMPC() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[MPC] = Metadata{
f: Toolchain.newMPC,
Name: "mpc",
@@ -1137,7 +1137,7 @@ func init() {
},
ID: 1667,
})
}
}
func (t Toolchain) newGCC() (pkg.Artifact, string) {
@@ -1147,7 +1147,7 @@ func (t Toolchain) newGCC() (pkg.Artifact, string) {
)
var configureExtra []KV
switch t.arch {
switch arch {
case "amd64", "arm64":
configureExtra = append(configureExtra, KV{"with-multilib-list", "''"})
}
@@ -1346,7 +1346,7 @@ ln -s system/lib /work/
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[gcc] = Metadata{
f: Toolchain.newGCC,
Name: "gcc",
@@ -1362,5 +1362,5 @@ func init() {
},
ID: 6502,
})
}
}

View File

@@ -9,7 +9,7 @@ import (
// newGoBootstrap returns the Go bootstrap toolchain.
func (t Toolchain) newGoBootstrap() pkg.Artifact {
const checksum = "8o9JL_ToiQKadCTb04nvBDkp8O1xiWOolAxVEqaTGodieNe4lOFEjlOxN3bwwe23"
return t.New("go1.4-bootstrap", 0, t.Append(nil,
return t.New("go1.4-bootstrap", 0, t.AppendPresets(nil,
Bash,
), nil, []string{
"CGO_ENABLED=0",
@@ -35,10 +35,10 @@ func (t Toolchain) newGo(
extra ...pkg.Artifact,
) pkg.Artifact {
name := "all"
if t.opts&OptSkipCheck != 0 {
if presetOpts&OptSkipCheck != 0 {
name = "make"
}
return t.New("go"+version, 0, t.Append(extra,
return t.New("go"+version, 0, t.AppendPresets(extra,
Bash,
), nil, slices.Concat([]string{
"CC=cc",
@@ -72,17 +72,17 @@ func (t Toolchain) newGoLatest() (pkg.Artifact, string) {
finalEnv []string
)
switch t.arch {
switch arch {
case "amd64":
bootstrapExtra = append(bootstrapExtra, t.newGoBootstrap())
case "arm64", "riscv64":
bootstrapEnv = append(bootstrapEnv, "GOROOT_BOOTSTRAP=/system")
bootstrapExtra = t.Append(bootstrapExtra, gcc)
bootstrapExtra = t.AppendPresets(bootstrapExtra, gcc)
finalEnv = append(finalEnv, "CGO_ENABLED=0")
default:
panic("unsupported target " + t.arch)
panic("unsupported target " + arch)
}
go119 := t.newGo(
@@ -106,8 +106,8 @@ echo \
"YtrDka402BOAEwywx03Vz4QlVwoBiguJHzG7PuythMCPHXS8CVMLvzmvgEbu4Tzu",
[]string{"CGO_ENABLED=0"}, `
sed -i \
's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
cmd/link/internal/`+t.arch+`/obj.go
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
cmd/link/internal/`+arch+`/obj.go
rm \
crypto/tls/handshake_client_test.go \
@@ -124,8 +124,8 @@ echo \
"wcI32bl1tkqbgcelGtGWPI4RtlEddd-PTd76Eb-k7nXA5LbE9yTNdIL9QSOOxMOs",
[]string{"CGO_ENABLED=0"}, `
sed -i \
's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
cmd/link/internal/`+t.arch+`/obj.go
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
cmd/link/internal/`+arch+`/obj.go
`, go121,
)
@@ -134,8 +134,8 @@ sed -i \
"TwKwatkpwal-j9U2sDSRPEdM3YesI4Gm88YgGV59wtU-L85K9gA7UPy9SCxn6PMb",
[]string{"CGO_ENABLED=0"}, `
sed -i \
's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
cmd/link/internal/`+t.arch+`/obj.go
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
cmd/link/internal/`+arch+`/obj.go
rm \
os/root_unix_test.go \
@@ -152,8 +152,8 @@ rm \
checksum,
finalEnv, `
sed -i \
's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
cmd/link/internal/`+t.arch+`/obj.go
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
cmd/link/internal/`+arch+`/obj.go
sed -i \
's/cpu.X86.HasAVX512VBMI/& \&\& cpu.X86.HasPOPCNT/' \
internal/runtime/gc/scan/scan_amd64.go
@@ -166,7 +166,7 @@ rm \
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Go] = Metadata{
f: Toolchain.newGoLatest,
Name: "go",
@@ -174,5 +174,5 @@ func init() {
Website: "https://go.dev/",
ID: 1227,
})
}
}

View File

@@ -42,7 +42,7 @@ func (t Toolchain) newGLib() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[GLib] = Metadata{
f: Toolchain.newGLib,
Name: "glib",
@@ -56,5 +56,5 @@ func init() {
},
ID: 10024,
})
}
}

View File

@@ -14,7 +14,7 @@ go build -o /bin/hostname /usr/src/hostname/main.go
hostname = ""
}
return t.New("hakurei"+suffix+"-"+hakureiVersion, 0, t.Append(nil,
return t.New("hakurei"+suffix+"-"+hakureiVersion, 0, t.AppendPresets(nil,
Go,
PkgConfig,
@@ -58,7 +58,7 @@ func main() {
)))
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Hakurei] = Metadata{
f: func(t Toolchain) (pkg.Artifact, string) {
return t.newHakurei("", `
mkdir -p /work/system/libexec/hakurei/
@@ -93,11 +93,11 @@ mkdir -p /work/system/bin/
Website: "https://hakurei.app/",
ID: 388834,
})
native.MustRegister(&Artifact{
}
artifactsM[HakureiDist] = Metadata{
f: func(t Toolchain) (pkg.Artifact, string) {
name := "all"
if t.opts&OptSkipCheck != 0 {
if presetOpts&OptSkipCheck != 0 {
name = "make"
}
return t.newHakurei("-dist", `
@@ -109,5 +109,5 @@ DESTDIR=/work /usr/src/hakurei/`+name+`.sh
Name: "hakurei-dist",
Description: "low-level userspace tooling for Rosa OS (distribution tarball)",
Website: "https://hakurei.app/",
})
}
}

View File

@@ -22,7 +22,7 @@ func (t Toolchain) newHwdata() (pkg.Artifact, string) {
}), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Hwdata] = Metadata{
f: Toolchain.newHwdata,
Name: "hwdata",
@@ -30,5 +30,5 @@ func init() {
Website: "https://github.com/vcrhonek/hwdata",
ID: 5387,
})
}
}

View File

@@ -6,7 +6,7 @@ import (
)
func init() {
native.MustRegister(&Artifact{
artifactsM[EarlyInit] = Metadata{
Name: "earlyinit",
Description: "Rosa OS initramfs init program",
@@ -24,14 +24,15 @@ go build -trimpath -v -o /work/system/libexec/hakurei -ldflags="-s -w
echo
`, false), Unversioned
},
})
}
}
func (t Toolchain) newImageSystem() (pkg.Artifact, string) {
return t.New("system.img", TNoToolchain, t.Append(nil,
return t.New("system.img", TNoToolchain, t.AppendPresets(nil,
SquashfsTools,
), nil, nil, `
mksquashfs /mnt/system /work/system.img
`, pkg.Path(fhs.AbsRoot.Append("mnt"), false, t.Append(nil,
`, pkg.Path(fhs.AbsRoot.Append("mnt"), false, t.AppendPresets(nil,
Musl,
Mksh,
Toybox,
@@ -42,15 +43,16 @@ mksquashfs /mnt/system /work/system.img
)...)), Unversioned
}
func init() {
native.MustRegister(&Artifact{
artifactsM[ImageSystem] = Metadata{
Name: "system-image",
Description: "Rosa OS system image",
f: Toolchain.newImageSystem,
})
}
}
func (t Toolchain) newImageInitramfs() (pkg.Artifact, string) {
return t.New("initramfs", TNoToolchain, t.Append(nil,
return t.New("initramfs", TNoToolchain, t.AppendPresets(nil,
Zstd,
EarlyInit,
GenInitCPIO,
@@ -64,10 +66,10 @@ file /init /system/libexec/hakurei/earlyinit 0555 0 0
`)))), Unversioned
}
func init() {
native.MustRegister(&Artifact{
artifactsM[ImageInitramfs] = Metadata{
Name: "initramfs-image",
Description: "Rosa OS initramfs image",
f: Toolchain.newImageInitramfs,
})
}
}

View File

@@ -19,23 +19,20 @@ chmod -R +w /work/usr/src/linux/
`, pkg.Path(AbsUsrSrc.Append("linux"), false, kernelSource)), kernelVersion
}
func init() {
native.MustRegister(&Artifact{
artifactsM[KernelSource] = Metadata{
f: Toolchain.newKernelSource,
Name: "kernel-source",
Description: "a writable kernel source tree installed to /usr/src/linux",
Website: "https://kernel.org/",
})
}
}
func (t Toolchain) newKernelHeaders() (pkg.Artifact, string) {
checksum := perArch[string]{
"amd64": "lCmBNcMeUmXifg0vecKOPy3GAaFcJSmOPnf3wit9xYTDSTsFADPt1xxUFfmTn1fD",
"arm64": "PlRxp4JzZeMGx7CScRlT1NBzc2NVyJlb8Gm8sa3ofFght9ZT101ZJhcIXiCkHSHM",
}
const checksum = "lCmBNcMeUmXifg0vecKOPy3GAaFcJSmOPnf3wit9xYTDSTsFADPt1xxUFfmTn1fD"
return t.NewPackage("kernel-headers", kernelVersion, kernelSource, &PackageAttr{
Flag: TEarly,
KnownChecksum: new(mustDecode(checksum.unwrap(t.S))),
KnownChecksum: new(mustDecode(checksum)),
Paths: []pkg.ExecPath{
// updated manually for API changes
@@ -70,13 +67,13 @@ cat \
), kernelVersion
}
func init() {
native.MustRegister(&Artifact{
artifactsM[KernelHeaders] = Metadata{
f: Toolchain.newKernelHeaders,
Name: "kernel-headers",
Description: "an installation of kernel headers",
Website: "https://kernel.org/",
})
}
}
func (t Toolchain) newKernel() (pkg.Artifact, string) {
@@ -1275,7 +1272,7 @@ rm -v /work/system/lib/modules/` + kernelVersion + `/build
), kernelVersion
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Kernel] = Metadata{
f: Toolchain.newKernel,
Name: "kernel",
@@ -1283,7 +1280,7 @@ func init() {
Website: "https://kernel.org/",
ID: 375621,
})
}
}
func (t Toolchain) newGenInitCPIO() (pkg.Artifact, string) {
@@ -1293,12 +1290,12 @@ cc -o /work/system/bin/gen_init_cpio /usr/src/linux/usr/gen_init_cpio.c
`, pkg.Path(AbsUsrSrc.Append("linux"), false, kernelSource)), kernelVersion
}
func init() {
native.MustRegister(&Artifact{
artifactsM[GenInitCPIO] = Metadata{
f: Toolchain.newGenInitCPIO,
Name: "gen_init_cpio",
Description: "a program in the kernel source tree for creating initramfs archive",
})
}
}
func (t Toolchain) newFirmware() (pkg.Artifact, string) {
@@ -1340,7 +1337,7 @@ func (t Toolchain) newFirmware() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Firmware] = Metadata{
f: Toolchain.newFirmware,
Name: "firmware",
@@ -1348,5 +1345,5 @@ func init() {
Website: "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/",
ID: 141464,
})
}
}

View File

@@ -32,7 +32,7 @@ func (t Toolchain) newKmod() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Kmod] = Metadata{
f: Toolchain.newKmod,
Name: "kmod",
@@ -46,5 +46,5 @@ func init() {
},
ID: 1517,
})
}
}

View File

@@ -88,7 +88,7 @@ install -Dv /usr/src/CTestCustom.cmake /cure/
}, (*CMakeHelper)(nil)), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libarchive] = Metadata{
f: Toolchain.newLibarchive,
Name: "libarchive",
@@ -96,5 +96,5 @@ func init() {
Website: "https://www.libarchive.org/",
ID: 1558,
})
}
}

View File

@@ -21,7 +21,7 @@ install -D /usr/src/libmd/src/helper.c src/helper.c
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libmd] = Metadata{
f: Toolchain.newLibmd,
Name: "libmd",
@@ -29,7 +29,7 @@ func init() {
Website: "https://www.hadrons.org/software/libmd/",
ID: 15525,
})
}
}
func (t Toolchain) newLibbsd() (pkg.Artifact, string) {
@@ -50,7 +50,7 @@ func (t Toolchain) newLibbsd() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libbsd] = Metadata{
f: Toolchain.newLibbsd,
Name: "libbsd",
@@ -58,5 +58,5 @@ func init() {
Website: "https://libbsd.freedesktop.org/",
ID: 1567,
})
}
}

View File

@@ -42,7 +42,7 @@ ln -s ../system/bin/bash /bin/
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libcap] = Metadata{
f: Toolchain.newLibcap,
Name: "libcap",
@@ -50,5 +50,5 @@ func init() {
Website: "https://sites.google.com/site/fullycapable/",
ID: 1569,
})
}
}

View File

@@ -38,7 +38,7 @@ index eba7eae..f916d2e 100644
}, (*CMakeHelper)(nil)), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libconfig] = Metadata{
f: Toolchain.newLibconfig,
Name: "libconfig",
@@ -46,5 +46,5 @@ func init() {
Website: "https://hyperrealm.github.io/libconfig/",
ID: 1580,
})
}
}

View File

@@ -18,7 +18,7 @@ func (t Toolchain) newLibdisplayInfo() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[LibdisplayInfo] = Metadata{
f: Toolchain.newLibdisplayInfo,
Name: "libdisplay-info",
@@ -26,5 +26,5 @@ func init() {
Website: "https://gitlab.freedesktop.org/emersion/libdisplay-info",
ID: 326668,
})
}
}

View File

@@ -21,7 +21,7 @@ func (t Toolchain) newLibepoxy() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libepoxy] = Metadata{
f: Toolchain.newLibepoxy,
Name: "libepoxy",
@@ -29,5 +29,5 @@ func init() {
Website: "https://github.com/anholt/libepoxy",
ID: 6090,
})
}
}

View File

@@ -14,7 +14,7 @@ func (t Toolchain) newLibev() (pkg.Artifact, string) {
), nil, (*MakeHelper)(nil)), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libev] = Metadata{
f: Toolchain.newLibev,
Name: "libev",
@@ -22,5 +22,5 @@ func init() {
Website: "http://libev.schmorp.de/",
ID: 1605,
})
}
}

View File

@@ -22,7 +22,7 @@ func (t Toolchain) newLibexpat() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libexpat] = Metadata{
f: Toolchain.newLibexpat,
Name: "libexpat",
@@ -30,5 +30,5 @@ func init() {
Website: "https://libexpat.github.io/",
ID: 770,
})
}
}

View File

@@ -18,7 +18,7 @@ func (t Toolchain) newLibffi() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libffi] = Metadata{
f: Toolchain.newLibffi,
Name: "libffi",
@@ -26,5 +26,5 @@ func init() {
Website: "https://sourceware.org/libffi/",
ID: 1611,
})
}
}

View File

@@ -24,7 +24,7 @@ mkdir /dev/shm/gd
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libgd] = Metadata{
f: Toolchain.newLibgd,
Name: "libgd",
@@ -36,5 +36,5 @@ func init() {
},
ID: 880,
})
}
}

View File

@@ -22,7 +22,7 @@ func (t Toolchain) newLibpng() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libpng] = Metadata{
f: Toolchain.newLibpng,
Name: "libpng",
@@ -34,5 +34,5 @@ func init() {
},
ID: 1705,
})
}
}

View File

@@ -25,7 +25,7 @@ test_disable 'int main(){return 0;}' tests/test-is-public-builtin.c
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libpsl] = Metadata{
f: Toolchain.newLibpsl,
Name: "libpsl",
@@ -33,5 +33,5 @@ func init() {
Website: "https://rockdaboot.github.io/libpsl/",
ID: 7305,
})
}
}

View File

@@ -43,7 +43,7 @@ index adccef3..65a277a 100644
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libseccomp] = Metadata{
f: Toolchain.newLibseccomp,
Name: "libseccomp",
@@ -51,5 +51,5 @@ func init() {
Website: "https://github.com/seccomp/libseccomp/",
ID: 13823,
})
}
}

View File

@@ -32,7 +32,7 @@ func (t Toolchain) newLibtirpc() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libtirpc] = Metadata{
f: Toolchain.newLibtirpc,
Name: "libtirpc",
@@ -40,5 +40,5 @@ func init() {
Website: "https://sourceforge.net/projects/libtirpc/",
ID: 1740,
})
}
}

View File

@@ -21,13 +21,13 @@ func (t Toolchain) newLibucontext() (pkg.Artifact, string) {
SkipConfigure: true,
InPlace: true,
Make: []string{
"ARCH=" + t.linuxArch(),
"ARCH=" + linuxArch(),
},
Install: "make prefix=/system DESTDIR=/work install",
}), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libucontext] = Metadata{
f: Toolchain.newLibucontext,
Name: "libucontext",
@@ -35,5 +35,5 @@ func init() {
Website: "https://github.com/kaniini/libucontext/",
ID: 17085,
})
}
}

View File

@@ -20,7 +20,7 @@ func (t Toolchain) newLibxml2() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libxml2] = Metadata{
f: Toolchain.newLibxml2,
Name: "libxml2",
@@ -28,5 +28,5 @@ func init() {
Website: "https://gitlab.gnome.org/GNOME/libxml2/",
ID: 1783,
})
}
}

View File

@@ -26,7 +26,7 @@ func (t Toolchain) newLibxslt() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libxslt] = Metadata{
f: Toolchain.newLibxslt,
Name: "libxslt",
@@ -38,5 +38,5 @@ func init() {
},
ID: 13301,
})
}
}

View File

@@ -30,9 +30,9 @@ func litArgs(verbose bool, skipChecks ...string) string {
}
func (t Toolchain) newEarlyCompilerRT() (pkg.Artifact, string) {
source, version := t.Load(llvmSource)
version := t.Version(llvmSource)
major, _, _ := strings.Cut(version, ".")
return t.NewPackage("early-compiler-rt", version, source, &PackageAttr{
return t.NewPackage("early-compiler-rt", version, t.Load(llvmSource), &PackageAttr{
Flag: TExclusive,
}, &CMakeHelper{
Append: []string{"compiler-rt"},
@@ -71,10 +71,10 @@ ln -s \
"/work/system/lib/clang/` + major + `/lib/"
ln -s \
"clang_rt.crtbegin-` + t.linuxArch() + `.o" \
"clang_rt.crtbegin-` + linuxArch() + `.o" \
"/work/system/lib/${ROSA_TRIPLE}/crtbeginS.o"
ln -s \
"clang_rt.crtend-` + t.linuxArch() + `.o" \
"clang_rt.crtend-` + linuxArch() + `.o" \
"/work/system/lib/${ROSA_TRIPLE}/crtendS.o"
`,
},
@@ -85,7 +85,7 @@ ln -s \
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[earlyCompilerRT] = Metadata{
f: Toolchain.newEarlyCompilerRT,
Name: "early-compiler-rt",
@@ -94,12 +94,12 @@ func init() {
Dependencies: P{
Musl,
},
})
}
}
func (t Toolchain) newEarlyRuntimes() (pkg.Artifact, string) {
source, version := t.Load(llvmSource)
return t.NewPackage("early-runtimes", version, source, &PackageAttr{
version := t.Version(llvmSource)
return t.NewPackage("early-runtimes", version, t.Load(llvmSource), &PackageAttr{
Flag: TExclusive,
}, &CMakeHelper{
Append: []string{"runtimes"},
@@ -145,7 +145,7 @@ func (t Toolchain) newEarlyRuntimes() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[earlyRuntimes] = Metadata{
f: Toolchain.newEarlyRuntimes,
Name: "early-runtimes",
@@ -154,12 +154,12 @@ func init() {
Dependencies: P{
earlyCompilerRT,
},
})
}
}
func (t Toolchain) newLLVM() (pkg.Artifact, string) {
early := muslHeaders
if t.stage.isStage0() {
var early PArtifact = muslHeaders
if t.isStage0() {
// The LLVM build system uses the system installation when building with
// LLVM_LINK_LLVM_DYLIB, since it builds runtimes after the fact, using
// the just-built toolchain. This is unacceptable in stage0 due to the
@@ -217,7 +217,7 @@ func (t Toolchain) newLLVM() (pkg.Artifact, string) {
}, ";") + "'"},
}
if !t.stage.isStage0() {
if !t.isStage0() {
skipChecks := []string{
// expensive, pointless to run here
"benchmarks",
@@ -247,7 +247,7 @@ func (t Toolchain) newLLVM() (pkg.Artifact, string) {
// unwind: fails on musl
"eh_frame_fde_pc_range",
}
switch t.arch {
switch arch {
case "arm64":
skipChecks = append(skipChecks,
// LLVM: intermittently crashes
@@ -257,7 +257,7 @@ func (t Toolchain) newLLVM() (pkg.Artifact, string) {
)
}
if t.opts&OptLLVMNoLTO == 0 {
if presetOpts&OptLLVMNoLTO == 0 {
cache = append(cache, []KV{
// very expensive
{"LLVM_ENABLE_LTO", "Thin"},
@@ -273,8 +273,8 @@ func (t Toolchain) newLLVM() (pkg.Artifact, string) {
}...)
}
source, version := t.Load(llvmSource)
return t.NewPackage("llvm", version, source, &PackageAttr{
version := t.Version(llvmSource)
return t.NewPackage("llvm", version, t.Load(llvmSource), &PackageAttr{
Flag: TExclusive,
}, &CMakeHelper{
Append: []string{"llvm"},
@@ -291,7 +291,7 @@ ln -s clang++ /work/system/bin/c++
// installation into test environment, and the tests end up testing the
// system installation instead. Tests are disabled on stage0 and relies
// on 3-stage determinism to test later stages.
SkipTest: t.stage.isStage0(),
SkipTest: t.isStage0(),
Test: `
chmod +w /bin && ln -s \
@@ -324,7 +324,7 @@ func init() {
checksum = "32gOaLPHcUlo3hkdk5RbFumTE01XKeCAYZcpvn8IDHF95egXVfDFSl6eZL3ChMen"
)
native.MustRegister(&Artifact{
artifactsM[llvmSource] = Metadata{
f: func(t Toolchain) (pkg.Artifact, string) {
return t.NewPatchedSource("llvm", version, newFromGitHub(
"llvm/llvm-project",
@@ -337,9 +337,9 @@ func init() {
Description: "LLVM monorepo with Rosa OS patches",
ID: 1830,
})
}
native.MustRegister(&Artifact{
artifactsM[LLVM] = Metadata{
f: Toolchain.newLLVM,
Name: "llvm",
@@ -351,5 +351,5 @@ func init() {
Zstd,
Musl,
},
})
}
}

View File

@@ -47,7 +47,7 @@ ln -s \
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[LMSensors] = Metadata{
f: Toolchain.newLMSensors,
Name: "lm_sensors",
@@ -55,5 +55,5 @@ func init() {
Website: "https://hwmon.wiki.kernel.org/lm_sensors",
ID: 1831,
})
}
}

View File

@@ -27,7 +27,7 @@ cd "$(mktemp -d)"
))), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Make] = Metadata{
f: Toolchain.newMake,
Name: "make",
@@ -35,7 +35,7 @@ func init() {
Website: "https://www.gnu.org/software/make/",
ID: 1877,
})
}
}
// MakeHelper is the [Make] build system helper.
@@ -123,7 +123,7 @@ func (attr *MakeHelper) wantsDir() string {
}
// script generates the cure script.
func (attr *MakeHelper) script(s *S, name string) string {
func (attr *MakeHelper) script(name string) string {
if attr == nil {
attr = new(MakeHelper)
}
@@ -194,7 +194,7 @@ make \
}
scriptMake += "\n"
if !attr.SkipCheck && s.opts&OptSkipCheck == 0 {
if !attr.SkipCheck && presetOpts&OptSkipCheck == 0 {
scriptMake += attr.ScriptCheckEarly + `make \
` + jobsFlagE + ` \
`

View File

@@ -35,7 +35,7 @@ trap 'kill $XVFB_PID && wait $XVFB_PID' EXIT
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libglvnd] = Metadata{
f: Toolchain.newLibglvnd,
Name: "libglvnd",
@@ -47,7 +47,7 @@ func init() {
},
ID: 12098,
})
}
}
func (t Toolchain) newLibdrm() (pkg.Artifact, string) {
@@ -72,7 +72,7 @@ func (t Toolchain) newLibdrm() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libdrm] = Metadata{
f: Toolchain.newLibdrm,
Name: "libdrm",
@@ -84,7 +84,7 @@ func init() {
},
ID: 1596,
})
}
}
func (t Toolchain) newLibva() (pkg.Artifact, string) {
@@ -111,7 +111,7 @@ func (t Toolchain) newLibva() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libva] = Metadata{
f: Toolchain.newLibva,
Name: "libva",
@@ -126,7 +126,7 @@ func init() {
},
ID: 1752,
})
}
}
func (t Toolchain) newMesa() (pkg.Artifact, string) {
@@ -238,7 +238,7 @@ func (t Toolchain) newMesa() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Mesa] = Metadata{
f: Toolchain.newMesa,
Name: "mesa",
@@ -261,5 +261,5 @@ func init() {
ID: 1970,
latest: (*Versions).getStable,
})
}
}

View File

@@ -52,7 +52,7 @@ python3 ./run_project_tests.py \
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Meson] = Metadata{
f: Toolchain.newMeson,
Name: "meson",
@@ -67,7 +67,7 @@ func init() {
},
ID: 6472,
})
}
}
// MesonHelper is the [Meson] build system helper.
@@ -106,7 +106,7 @@ func (*MesonHelper) createDir() bool { return false }
func (*MesonHelper) wantsDir() string { return `"$(mktemp -d)"` }
// script generates the cure script.
func (attr *MesonHelper) script(s *S, name string) string {
func (attr *MesonHelper) script(name string) string {
if attr == nil {
attr = new(MesonHelper)
}
@@ -117,7 +117,7 @@ func (attr *MesonHelper) script(s *S, name string) string {
}
var scriptTest string
if !attr.SkipTest && s.opts&OptSkipCheck == 0 {
if !attr.SkipTest && presetOpts&OptSkipCheck == 0 {
scriptTest = `
meson test \
--print-errorlogs`

View File

@@ -8,10 +8,10 @@ func (t Toolchain) newMksh() (pkg.Artifact, string) {
checksum = "0Zj-k4nXEu3IuJY4lvwD2OrC2t27GdZj8SPy4DoaeuBRH1padWb7oREpYgwY8JNq"
)
scriptTest := "./test.sh -C regress:no-ctty\n"
if t.opts&OptSkipCheck != 0 {
if presetOpts&OptSkipCheck != 0 {
scriptTest = ""
}
return t.New("mksh-"+version, 0, t.Append(nil,
return t.New("mksh-"+version, 0, t.AppendPresets(nil,
Perl,
Coreutils,
), nil, []string{
@@ -36,7 +36,7 @@ ln -vs ../system/bin/sh /work/bin/
))), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Mksh] = Metadata{
f: Toolchain.newMksh,
Name: "mksh",
@@ -44,5 +44,5 @@ func init() {
Website: "https://www.mirbsd.org/mksh",
ID: 5590,
})
}
}

View File

@@ -24,7 +24,7 @@ func (t Toolchain) newMuslFts() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[MuslFts] = Metadata{
f: Toolchain.newMuslFts,
Name: "musl-fts",
@@ -32,5 +32,5 @@ func init() {
Website: "https://github.com/void-linux/musl-fts",
ID: 26980,
})
}
}

View File

@@ -24,7 +24,7 @@ func (t Toolchain) newMuslObstack() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[MuslObstack] = Metadata{
f: Toolchain.newMuslObstack,
Name: "musl-obstack",
@@ -32,5 +32,5 @@ func init() {
Website: "https://github.com/void-linux/musl-obstack",
ID: 146206,
})
}
}

View File

@@ -14,7 +14,7 @@ func (t Toolchain) newMusl(headers bool) (pkg.Artifact, string) {
SkipCheck: true,
Script: `
mkdir -p /work/system/bin
COMPAT_LINKER_NAME="ld-musl-` + t.linuxArch() + `.so.1"
COMPAT_LINKER_NAME="ld-musl-` + linuxArch() + `.so.1"
ln -vs ../lib/libc.so /work/system/bin/linker
ln -vs ../lib/libc.so /work/system/bin/ldd
ln -vs libc.so "/work/system/lib/${COMPAT_LINKER_NAME}"
@@ -34,9 +34,9 @@ rmdir -v /work/lib
}
env := []string{
"LDFLAGS=" + t.earlyLDFLAGS(false),
"LDFLAGS=" + earlyLDFLAGS(false),
}
if t.stage.isStage0() {
if t.isStage0() {
env = append(env,
"CC=clang",
"AR=ar",
@@ -75,7 +75,7 @@ index 715948f4..c2fece68 100644
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Musl] = Metadata{
f: func(t Toolchain) (pkg.Artifact, string) {
return t.newMusl(false)
},
@@ -85,14 +85,14 @@ func init() {
Website: "https://musl.libc.org/",
ID: 11688,
})
}
native.MustRegister(&Artifact{
artifactsM[muslHeaders] = Metadata{
f: func(t Toolchain) (pkg.Artifact, string) {
return t.newMusl(true)
},
Name: "musl-headers",
Description: "system installation of musl headers",
})
}
}

View File

@@ -26,7 +26,7 @@ func (t Toolchain) newNcurses() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Ncurses] = Metadata{
f: Toolchain.newNcurses,
Name: "ncurses",
@@ -34,5 +34,5 @@ func init() {
Website: "https://invisible-island.net/ncurses/",
ID: 373226,
})
}
}

View File

@@ -39,7 +39,7 @@ index d223ac2..a7878d0 100644
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libmnl] = Metadata{
f: Toolchain.newLibmnl,
Name: "libmnl",
@@ -47,7 +47,7 @@ func init() {
Website: "https://www.netfilter.org/projects/libmnl/",
ID: 1663,
})
}
}
func (t Toolchain) newLibnftnl() (pkg.Artifact, string) {
@@ -77,7 +77,7 @@ func (t Toolchain) newLibnftnl() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Libnftnl] = Metadata{
f: Toolchain.newLibnftnl,
Name: "libnftnl",
@@ -89,7 +89,7 @@ func init() {
},
ID: 1681,
})
}
}
func (t Toolchain) newIPTables() (pkg.Artifact, string) {
@@ -131,7 +131,7 @@ chmod +w /etc/ && ln -s ../usr/src/iptables/etc/ethertypes /etc/
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[IPTables] = Metadata{
f: Toolchain.newIPTables,
Name: "iptables",
@@ -143,5 +143,5 @@ func init() {
},
ID: 1394,
})
}
}

View File

@@ -19,7 +19,7 @@ func (t Toolchain) newNettle() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Nettle] = Metadata{
f: Toolchain.newNettle,
Name: "nettle",
@@ -31,5 +31,5 @@ func init() {
},
ID: 2073,
})
}
}

View File

@@ -19,7 +19,7 @@ func (t Toolchain) newNettle3() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[nettle3] = Metadata{
f: Toolchain.newNettle3,
Name: "nettle3",
@@ -29,5 +29,5 @@ func init() {
Dependencies: P{
GMP,
},
})
}
}

View File

@@ -7,11 +7,9 @@ func (t Toolchain) newNinja() (pkg.Artifact, string) {
version = "1.13.2"
checksum = "ygKWMa0YV2lWKiFro5hnL-vcKbc_-RACZuPu0Io8qDvgQlZ0dxv7hPNSFkt4214v"
)
python, _ := t.Load(Python)
bash, _ := t.Load(Bash)
return t.New("ninja-"+version, 0, []pkg.Artifact{
python,
bash,
t.Load(Python),
t.Load(Bash),
}, nil, nil, `
cd "$(mktemp -d)"
python3 /usr/src/ninja/configure.py \
@@ -39,7 +37,7 @@ cp ninja /work/system/bin/
))), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Ninja] = Metadata{
f: Toolchain.newNinja,
Name: "ninja",
@@ -47,5 +45,5 @@ func init() {
Website: "https://ninja-build.org/",
ID: 2089,
})
}
}

View File

@@ -67,7 +67,7 @@ cp -r \
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[NSS] = Metadata{
f: Toolchain.newNSS,
Name: "nss",
@@ -79,7 +79,7 @@ func init() {
},
ID: 2503,
})
}
}
func init() {
@@ -87,7 +87,7 @@ func init() {
version = "0.5.1"
checksum = "oxjnuIrPVMPvD6x8VFLqB7EdbfuhouGQdtPuHDpEHGzoyH5nkxqtYN9UthMY9noA"
)
native.newPythonPackage(
artifactsM[buildcatrust] = newPythonPackage(
"buildcatrust", 233988,
"transform certificate stores between formats",
"https://github.com/nix-community/buildcatrust",
@@ -103,7 +103,7 @@ rm buildcatrust/tests/test_nonhermetic.py
}
func (t Toolchain) newNSSCACert() (pkg.Artifact, string) {
return t.New("nss-cacert", 0, t.Append(nil,
return t.New("nss-cacert", 0, t.AppendPresets(nil,
Bash,
NSS,
@@ -120,11 +120,11 @@ buildcatrust \
`), Unversioned
}
func init() {
native.MustRegister(&Artifact{
artifactsM[NSSCACert] = Metadata{
f: Toolchain.newNSSCACert,
Name: "nss-cacert",
Description: "bundle of X.509 certificates of public Certificate Authorities",
Website: "https://curl.se/docs/caextract.html",
})
}
}

View File

@@ -40,7 +40,7 @@ func (t Toolchain) newOpenSSL() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[OpenSSL] = Metadata{
f: Toolchain.newOpenSSL,
Name: "openssl",
@@ -51,5 +51,5 @@ func init() {
// strange malformed tags treated as pre-releases in Anitya
latest: (*Versions).getStable,
})
}
}

View File

@@ -23,7 +23,7 @@ func (t Toolchain) newP11Kit() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[P11Kit] = Metadata{
f: Toolchain.newP11Kit,
Name: "p11-kit",
@@ -36,5 +36,5 @@ func init() {
},
ID: 2582,
})
}
}

View File

@@ -32,7 +32,7 @@ ln -s ../system/bin/toybox /bin/echo
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[PCRE2] = Metadata{
f: Toolchain.newPCRE2,
Name: "pcre2",
@@ -40,5 +40,5 @@ func init() {
Website: "https://pcre2project.github.io/pcre2/",
ID: 5832,
})
}
}

View File

@@ -50,7 +50,7 @@ chmod +w /system/bin && rm -f /system/bin/ps # perl does not like toybox ps
}), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Perl] = Metadata{
f: Toolchain.newPerl,
Name: "perl",
@@ -61,7 +61,7 @@ func init() {
// odd-even versioning
latest: (*Versions).getStable,
})
}
}
// newViaPerlModuleBuild installs a perl module via Build.PL.
@@ -69,12 +69,12 @@ func (t Toolchain) newViaPerlModuleBuild(
name, version string,
source pkg.Artifact,
patches []KV,
extra ...ArtifactH,
extra ...PArtifact,
) pkg.Artifact {
if name == "" || version == "" {
panic("names must be non-empty")
}
return t.New("perl-"+name, 0, t.Append(nil,
return t.New("perl-"+name, 0, t.AppendPresets(nil,
slices.Concat(P{Perl}, extra)...,
), nil, nil, `
cd /usr/src/`+name+`
@@ -100,7 +100,7 @@ func (t Toolchain) newPerlModuleBuild() (pkg.Artifact, string) {
), nil), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[PerlModuleBuild] = Metadata{
f: Toolchain.newPerlModuleBuild,
Name: "perl-Module::Build",
@@ -110,7 +110,7 @@ func init() {
Dependencies: P{
Perl,
},
})
}
}
// newViaPerlMakeMaker installs a perl module via Makefile.PL.
@@ -118,7 +118,7 @@ func (t Toolchain) newViaPerlMakeMaker(
name, version string,
source pkg.Artifact,
patches []KV,
extra ...ArtifactH,
extra ...PArtifact,
) pkg.Artifact {
return t.NewPackage("perl-"+name, version, source, &PackageAttr{
// uses source tree as scratch space
@@ -154,7 +154,7 @@ func (t Toolchain) newPerlLocaleGettext() (pkg.Artifact, string) {
), nil), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[PerlLocaleGettext] = Metadata{
f: Toolchain.newPerlLocaleGettext,
Name: "perl-Locale::gettext",
@@ -162,7 +162,7 @@ func init() {
Website: "https://metacpan.org/release/Locale-gettext",
ID: 7523,
})
}
}
func (t Toolchain) newPerlPodParser() (pkg.Artifact, string) {
@@ -178,7 +178,7 @@ func (t Toolchain) newPerlPodParser() (pkg.Artifact, string) {
), nil), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[PerlPodParser] = Metadata{
f: Toolchain.newPerlPodParser,
Name: "perl-Pod::Parser",
@@ -186,7 +186,7 @@ func init() {
Website: "https://metacpan.org/release/Pod-Parser",
ID: 3244,
})
}
}
func (t Toolchain) newPerlSGMLS() (pkg.Artifact, string) {
@@ -202,7 +202,7 @@ func (t Toolchain) newPerlSGMLS() (pkg.Artifact, string) {
), nil), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[PerlSGMLS] = Metadata{
f: Toolchain.newPerlSGMLS,
Name: "perl-SGMLS",
@@ -224,7 +224,7 @@ func init() {
}
return v.Latest
},
})
}
}
func (t Toolchain) newPerlTermReadKey() (pkg.Artifact, string) {
@@ -240,7 +240,7 @@ func (t Toolchain) newPerlTermReadKey() (pkg.Artifact, string) {
), nil), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[PerlTermReadKey] = Metadata{
f: Toolchain.newPerlTermReadKey,
Name: "perl-Term::ReadKey",
@@ -248,7 +248,7 @@ func init() {
Website: "https://metacpan.org/release/TermReadKey",
ID: 3372,
})
}
}
func (t Toolchain) newPerlTextCharWidth() (pkg.Artifact, string) {
@@ -264,7 +264,7 @@ func (t Toolchain) newPerlTextCharWidth() (pkg.Artifact, string) {
), nil), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[PerlTextCharWidth] = Metadata{
f: Toolchain.newPerlTextCharWidth,
Name: "perl-Text::CharWidth",
@@ -272,7 +272,7 @@ func init() {
Website: "https://metacpan.org/release/Text-CharWidth",
ID: 14380,
})
}
}
func (t Toolchain) newPerlTextWrapI18N() (pkg.Artifact, string) {
@@ -290,7 +290,7 @@ func (t Toolchain) newPerlTextWrapI18N() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[PerlTextWrapI18N] = Metadata{
f: Toolchain.newPerlTextWrapI18N,
Name: "perl-Text::WrapI18N",
@@ -302,7 +302,7 @@ func init() {
},
ID: 14385,
})
}
}
func (t Toolchain) newPerlMIMECharset() (pkg.Artifact, string) {
@@ -318,7 +318,7 @@ func (t Toolchain) newPerlMIMECharset() (pkg.Artifact, string) {
), nil), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[PerlMIMECharset] = Metadata{
f: Toolchain.newPerlMIMECharset,
Name: "perl-MIME::Charset",
@@ -326,7 +326,7 @@ func init() {
Website: "https://metacpan.org/release/MIME-Charset",
ID: 3070,
})
}
}
func (t Toolchain) newPerlUnicodeLineBreak() (pkg.Artifact, string) {
@@ -344,7 +344,7 @@ func (t Toolchain) newPerlUnicodeLineBreak() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[PerlUnicodeLineBreak] = Metadata{
f: Toolchain.newPerlUnicodeLineBreak,
Name: "perl-Unicode::LineBreak",
@@ -356,7 +356,7 @@ func init() {
},
ID: 6033,
})
}
}
func (t Toolchain) newPerlYAMLTiny() (pkg.Artifact, string) {
@@ -372,7 +372,7 @@ func (t Toolchain) newPerlYAMLTiny() (pkg.Artifact, string) {
), nil), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[PerlYAMLTiny] = Metadata{
f: Toolchain.newPerlYAMLTiny,
Name: "perl-YAML::Tiny",
@@ -380,7 +380,7 @@ func init() {
Website: "https://metacpan.org/release/YAML-Tiny",
ID: 3549,
})
}
}
func (t Toolchain) newPerlTestCmd() (pkg.Artifact, string) {
@@ -396,7 +396,7 @@ func (t Toolchain) newPerlTestCmd() (pkg.Artifact, string) {
), nil), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[PerlTestCmd] = Metadata{
f: Toolchain.newPerlTestCmd,
Name: "perl-Test::Cmd",
@@ -404,5 +404,5 @@ func init() {
Website: "https://metacpan.org/release/Test-Cmd",
ID: 6014,
})
}
}

View File

@@ -19,7 +19,7 @@ func (t Toolchain) newPixman() (pkg.Artifact, string) {
}), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Pixman] = Metadata{
f: Toolchain.newPixman,
Name: "pixman",
@@ -27,5 +27,5 @@ func init() {
Website: "https://pixman.org/",
ID: 3648,
})
}
}

View File

@@ -24,7 +24,7 @@ func (t Toolchain) newPkgConfig() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[PkgConfig] = Metadata{
f: Toolchain.newPkgConfig,
Name: "pkg-config",
@@ -32,5 +32,5 @@ func init() {
Website: "https://pkgconfig.freedesktop.org/",
ID: 3649,
})
}
}

View File

@@ -27,7 +27,7 @@ func (t Toolchain) newProcps() (pkg.Artifact, string) {
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Procps] = Metadata{
f: Toolchain.newProcps,
Name: "procps",
@@ -35,5 +35,5 @@ func init() {
Website: "https://gitlab.com/procps-ng/procps",
ID: 3708,
})
}
}

View File

@@ -73,7 +73,7 @@ index 19aea290b58..51603ba9510 100644
// _ctypes appears to infer something from the linker name
"LDFLAGS=-Wl,--dynamic-linker=/system/lib/" +
"ld-musl-" + t.linuxArch() + ".so.1",
"ld-musl-" + linuxArch() + ".so.1",
},
}, &MakeHelper{
Check: []string{"test"},
@@ -88,7 +88,7 @@ index 19aea290b58..51603ba9510 100644
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[Python] = Metadata{
f: Toolchain.newPython,
Name: "python",
@@ -103,7 +103,7 @@ func init() {
},
ID: 13254,
})
}
}
// PipHelper is the [Python] pip packaging helper.
@@ -150,7 +150,7 @@ func (*PipHelper) createDir() bool { return false }
func (*PipHelper) wantsDir() string { return `"$(mktemp -d)"` }
// script generates the pip3 install command.
func (attr *PipHelper) script(_ *S, name string) string {
func (attr *PipHelper) script(name string) string {
if attr == nil {
attr = new(PipHelper)
}
@@ -193,14 +193,14 @@ pip3 install \
` + script
}
// newPythonPackage registers a new [Python] package.
func (s *S) newPythonPackage(
// 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 ...ArtifactH,
) {
build P, extra ...PArtifact,
) Metadata {
name = "python-" + name
s.MustRegister(&Artifact{
return Metadata{
f: func(t Toolchain) (pkg.Artifact, string) {
return t.NewPackage(name, version, source, attrP, attr, slices.Concat(
P{Python},
@@ -216,7 +216,7 @@ func (s *S) newPythonPackage(
Dependencies: slices.Concat(P{Python}, extra),
ID: id,
})
}
}
func init() {
@@ -224,7 +224,7 @@ func init() {
version = "0.47.0"
checksum = "HZ-MvkUP8mbbx2YmsRNswj_bbOCIiXckuHqL5Qbvb5NxN5DYfWnqwkGNyS7OrId0"
)
native.newPythonPackage(
artifactsM[PythonWheel] = newPythonPackage(
"wheel", 11428,
"the official binary distribution format for Python",
"https://peps.python.org/pep-0427/",
@@ -242,7 +242,7 @@ func init() {
version = "82.0.1"
checksum = "nznP46Tj539yqswtOrIM4nQgwLA1h-ApKX7z7ghazROCpyF5swtQGwsZoI93wkhc"
)
native.newPythonPackage(
artifactsM[PythonSetuptools] = newPythonPackage(
"setuptools", 4021,
"the autotools of the Python ecosystem",
"https://pypi.org/project/setuptools/",
@@ -262,7 +262,7 @@ func init() {
version = "1.1.1"
checksum = "rXZixTsZcRcIoUC1LvWrjySsiXSv5uhW6ng2P-yXZrbdj7FrSrDeJLCfC2b-ladV"
)
native.newPythonPackage(
artifactsM[PythonVCSVersioning] = newPythonPackage(
"vcs-versioning", 389421,
"core VCS versioning functionality extracted as a standalone library",
"https://setuptools-scm.readthedocs.io/en/latest/",
@@ -289,7 +289,7 @@ func init() {
version = "10.0.5"
checksum = "vTN_TPd-b4Wbsw5WmAcsWjrs-FNXXznOeVTDnb54NtXve9Oy-eb2HPy-RG3FzNqp"
)
native.newPythonPackage(
artifactsM[PythonSetuptoolsSCM] = newPythonPackage(
"setuptools-scm", 7874,
"extracts Python package versions from Git or Mercurial metadata",
"https://setuptools-scm.readthedocs.io/en/latest/",
@@ -316,7 +316,7 @@ func init() {
version = "3.12.0"
checksum = "VcTsiGiDU1aPLbjSPe38f9OjJDCLcxFz9loObJqUI1ZxDHXAaQMxBpNyLz_G1Rff"
)
native.newPythonPackage(
artifactsM[PythonFlitCore] = newPythonPackage(
"flit-core", 44841,
"a PEP 517 build backend for packages using Flit",
"https://flit.pypa.io/",
@@ -337,7 +337,7 @@ func init() {
version = "26.2"
checksum = "rdpGa2EkPFbj1mFtLKLnSwIX9gPfELcuneiICjRVDNw6By49szTFVoW8gtMMZ6ZS"
)
native.newPythonPackage(
artifactsM[PythonPackaging] = newPythonPackage(
"packaging", 60461,
"reusable core utilities for various Python Packaging interoperability specifications",
"https://packaging.pypa.io/",
@@ -352,10 +352,10 @@ func init() {
}
func init() {
native.MustRegister(&Artifact{
artifactsM[LIT] = Metadata{
f: func(t Toolchain) (pkg.Artifact, string) {
source, version := t.Load(llvmSource)
return t.NewPackage("lit", version, source, nil, &PipHelper{
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,
@@ -371,7 +371,7 @@ func init() {
Dependencies: P{
Python,
},
})
}
}
func init() {
@@ -379,7 +379,7 @@ func init() {
version = "1.1.1"
checksum = "1fVwoal6FoKXczoG3qRUi87TxSWESSGcgvnbEZDYuaOgsO25o36iF3SbAhwkr4Va"
)
native.newPythonPackage(
artifactsM[PythonPathspec] = newPythonPackage(
"pathspec", 23424,
"utility library for gitignore style pattern matching of file paths",
"https://github.com/cpburnz/python-pathspec",
@@ -398,7 +398,7 @@ func init() {
version = "2026.5.7.17"
checksum = "1Fcps0gK9P4ofwGL8MISN9k1Q40-quxX7NDpIna50TmziBNrZy-0Vz0I9yIeHCoP"
)
native.newPythonPackage(
artifactsM[PythonTroveClassifiers] = newPythonPackage(
"trove-classifiers", 88298,
"canonical source for classifiers on PyPI",
"https://pypi.org/p/trove-classifiers/",
@@ -417,7 +417,7 @@ func init() {
version = "1.6.0"
checksum = "GiUgDkKjF8Xn1cmq6iMhTGXzcPIYeaJrvQpHBSAJapNVx4UyuiTXqd5eVlxSClJu"
)
native.newPythonPackage(
artifactsM[PythonPluggy] = newPythonPackage(
"pluggy", 7500,
"the core framework used by the pytest, tox, and devpi projects",
"https://pluggy.readthedocs.io/en/latest/",
@@ -440,7 +440,7 @@ func init() {
version = "1.16.5"
checksum = "V2eREtqZLZeV85yb4O-bfAJCUluHcQP76Qfs0QH5s7RF_Oc8xIP8jD0jl85qFyWk"
)
native.newPythonPackage(
artifactsM[PythonHatchling] = newPythonPackage(
"hatchling", 16137,
"the extensible, standards compliant build backend used by Hatch",
"https://hatch.pypa.io/latest/",
@@ -465,7 +465,7 @@ func init() {
version = "2.20.0"
checksum = "L-2P6vn7c_CNZYliE5CJAWLxO1ziDQVVkf8bnZbHj8aSCQ43oWv11wC9KzU9MeCa"
)
native.newPythonPackage(
artifactsM[PythonPygments] = newPythonPackage(
"pygments", 3986,
"a syntax highlighting package written in Python",
"https://pygments.org/",
@@ -484,7 +484,7 @@ func init() {
version = "2.3.0"
checksum = "mH7VBZaXcYatBPE3RQQZvSzz_Ay8IPPek60NpPHZulPq4ReAFUUsA4EPWfiyMknZ"
)
native.newPythonPackage(
artifactsM[PythonIniConfig] = newPythonPackage(
"iniconfig", 114778,
"a small and simple INI-file parser module",
"https://github.com/pytest-dev/iniconfig",
@@ -507,7 +507,7 @@ func init() {
version = "9.0.3"
checksum = "qfLL_znWhbJCDbNJvrx9H3-orJ86z4ifhaW0bIn21jl2sDP-FVoX_1yieOypArQe"
)
native.newPythonPackage(
artifactsM[PythonPyTest] = newPythonPackage(
"pytest", 3765,
"the pytest framework",
"https://pytest.org",
@@ -534,7 +534,7 @@ func init() {
version = "3.0.3"
checksum = "txRGYdWE3his1lHHRI-lZADw0-ILvUg2l5OGdFHtFXIb_QowGxwdxHCUSJIgmjQs"
)
native.newPythonPackage(
artifactsM[PythonMarkupSafe] = newPythonPackage(
"markupsafe", 3918,
"implements a text object that escapes characters so it is safe to use in HTML and XML",
"https://markupsafe.palletsprojects.com/",
@@ -553,7 +553,7 @@ func init() {
version = "1.3.12"
checksum = "OZbBsQe2MzRuAo5Mr4qRwWHGqU1EEZeBuSprDDIceAtMLIUJtO7SbERlxHIxNhLk"
)
native.newPythonPackage(
artifactsM[PythonMako] = newPythonPackage(
"mako", 3915,
"a template library written in Python",
"https://www.makotemplates.org/",
@@ -571,7 +571,7 @@ func init() {
version = "6.0.3"
checksum = "7wDv0RW9chBdu9l5Q4Hun5F2HHdo105ZSIixwdFPKbEYbftW9YxmsegfL-zafnbJ"
)
native.newPythonPackage(
artifactsM[PythonPyYAML] = newPythonPackage(
"pyyaml", 4123,
"a YAML parser and emitter for Python",
"https://pyyaml.org/",
@@ -590,7 +590,7 @@ func init() {
version = "3.00"
checksum = "4qfCMFKp0fLsRsloOAF780tXX_Ce_68RwinCmjNGObAX32WpF_iBafIKW1S1bYlA"
)
native.newPythonPackage(
artifactsM[PythonPycparser] = newPythonPackage(
"pycparser", 8175,
"complete C99 parser in pure Python",
"https://github.com/eliben/pycparser",

View File

@@ -94,7 +94,7 @@ EOF
), version
}
func init() {
native.MustRegister(&Artifact{
artifactsM[QEMU] = Metadata{
f: Toolchain.newQEMU,
Name: "qemu",
@@ -107,5 +107,5 @@ func init() {
},
ID: 13607,
})
}
}

Some files were not shown because too many files have changed in this diff Show More