1
0
forked from rosa/hakurei

67 Commits

Author SHA1 Message Date
823575acac cmd/mbf: move info command
This is cleaner with less shared state.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-16 17:43:52 +09:00
136bc0917b cmd/mbf: optionally open cache
Some commands do not require the cache. This change also makes acquisition of locked cache cancelable.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-16 15:59:34 +09:00
d6b082dd0b internal/rosa/ninja: bootstrap with verbose output
This otherwise outputs nothing, and appears to hang until the (fully single-threaded) bootstrap completes.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-15 22:19:05 +09:00
89d6d9576b internal/rosa/make: optionally format value as is
This enables correct formatting for awkward configure scripts.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-15 22:17:58 +09:00
fafce04a5d internal/rosa/kernel: firmware 20260309 to 20260410
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-15 22:16:47 +09:00
5d760a1db9 internal/rosa/kernel: 6.12.80 to 6.12.81
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-15 22:16:30 +09:00
d197e40b2a internal/rosa/python: mako 1.3.10 to 1.3.11
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-15 22:21:54 +09:00
2008902247 internal/rosa/python: packaging 26.0 to 26.1
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-15 22:15:18 +09:00
30ac985fd2 internal/rosa/meson: 1.10.2 to 1.11.0
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-15 22:14:52 +09:00
e9fec368f8 internal/rosa/nss: 3.122 to 3.122.1
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-15 22:13:45 +09:00
46add42f58 internal/rosa/openssl: disable building docs
These take very long and are never used in the Rosa OS environment.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-15 22:13:18 +09:00
377b61e342 internal/rosa/openssl: do not double test job count
The test suite is racy, this reduces flakiness.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-15 22:12:36 +09:00
520c36db6d internal/rosa: respect preferred job count
This discontinues use of nproc, and also overrides detection behaviour in ninja.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-15 18:49:36 +09:00
3352bb975b internal/pkg: job count in container environment
This exposes preferred job count to the container initial process.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-15 15:49:21 +09:00
f7f48d57e9 internal/pkg: pass impure job count
This is cleaner than checking cpu count during cure, it is impossible to avoid impurity in both situations but this is configurable.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-15 15:36:44 +09:00
5c2345128e internal/rosa/llvm: autodetect stage0 target
This is fine, now that stages beyond stage0 have explicit target.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-14 03:10:26 +09:00
78f9676b1f internal/rosa/llvm: centralise llvm source
This avoids having to sidestep the NewPackage name formatting machinery to take the cache fast path.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-14 03:03:06 +09:00
5b5b676132 internal/rosa/cmake: remove variant
This has no effect outside formatting of name and is a remnant of the old llvm helpers.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-14 02:57:47 +09:00
78383fb6e8 internal/rosa/llvm: migrate libclc
This eliminates newLLVMVariant.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-14 02:40:13 +09:00
e97f6a393f internal/rosa/llvm: migrate runtimes and clang
This eliminates most newLLVM family of functions.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-14 02:07:13 +09:00
eeffefd22b internal/rosa/llvm: migrate compiler-rt helper
This also removes unused dependencies.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-14 01:12:56 +09:00
ac825640ab internal/rosa/llvm: migrate musl
This removes the pointless special treatment given to musl.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-14 00:35:42 +09:00
a7f7ce1795 internal/rosa/llvm: migrate compiler-rt
The newLLVM family of functions predate the package system. This change migrates compiler-rt without changing any resulting artifacts.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-14 00:19:33 +09:00
38c639e35c internal/rosa/llvm: remove project/runtime helper
More remnants from early days, these are not reusable at all but that was not known at the time.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-14 00:03:23 +09:00
b2cb13e94c internal/rosa/llvm: centralise patches
This enables easier reuse of the patchset.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-13 23:52:44 +09:00
46f98d12d6 internal/rosa/llvm: remove conditional flags in helper
The llvm helper is a remnant from very early days, and ended up not being very useful, but was never removed. This change begins its removal, without changing the resulting artifacts for now.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-13 23:38:11 +09:00
503c7f953c internal/rosa/x: libpciaccess artifact
Required by userspace gpu drivers.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-13 19:04:38 +09:00
15c9f6545d internal/rosa/perl: populate anitya identifiers
These are also tracked by Anitya.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-13 18:44:43 +09:00
83b0e32c55 internal/rosa: helpers for common url formats
This cleans up call site of NewPackage.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-13 18:02:57 +09:00
eeaf26e7a2 internal/rosa: wrapper around git helper
This results in much cleaner call site for the majority of use cases.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-13 15:20:51 +09:00
b587caf2e8 internal/rosa: assume file source is xz-compressed
XZ happens to be the only widely-used format that is awful to deal with, everything else is natively supported.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-13 15:07:30 +09:00
f1c2ca4928 internal/rosa/mesa: libdrm artifact
Required by mesa.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-13 03:27:09 +09:00
0ca301219f internal/rosa/python: pyyaml artifact
Mesa unfortunately requires this horrible format.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-13 03:18:47 +09:00
e2199e1276 internal/rosa/python: mako artifact
This unfortunately pulls in platform-specific package.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-13 03:11:38 +09:00
86eacb3208 cmd/mbf: checksum command
This computes and encodes sha384 checksum of data streamed from standard input.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-13 03:09:21 +09:00
8541bdd858 internal/rosa: wrap per-arch values
This is cleaner syntax in some specific cases.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-13 02:59:55 +09:00
46be0b0dc8 internal/rosa/nss: buildcatrust 0.4.0 to 0.5.1
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-13 02:18:21 +09:00
cbe37e87e7 internal/rosa/python: pytest 9.0.2 to 9.0.3
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-13 02:18:02 +09:00
66d741fb07 internal/rosa/python: pygments 2.19.2 to 2.20.0
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-13 02:13:04 +09:00
0d449011f6 internal/rosa/python: use predictable URLs
This is much cleaner and more maintainable than specifying URL prefix manually. This change also populates Anitya project identifiers.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-13 02:08:22 +09:00
46428ed85d internal/rosa/python: url pip wheel helper
This enables a cleaner higher-level helper.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-13 01:59:28 +09:00
081d6b463c internal/rosa/llvm: libclc artifact
This is built independently of llvm build system to avoid having to build llvm again.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-12 22:57:04 +09:00
11b3171180 internal/rosa/glslang: glslang artifact
Required by mesa.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-12 22:34:17 +09:00
adbb84c3dd internal/rosa/glslang: spirv-tools artifact
Required by glslang.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-12 22:27:49 +09:00
1084e31d95 internal/rosa/glslang: spirv-headers artifact
Required by spirv-tools.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-12 22:16:29 +09:00
27a1b8fe0a internal/rosa/mesa: libglvnd artifact
Required by mesa.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-12 21:27:30 +09:00
b2141a41d7 internal/rosa/dbus: xdg-dbus-proxy artifact
This is currently a hakurei runtime dependency, but will eventually be removed.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-12 19:41:49 +09:00
c0dff5bc87 internal/rosa/gnu: gcc set with-multilib-list as needed
This breaks riscv64.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-12 18:03:45 +09:00
04513c0510 internal/rosa/gnu: gmp explicit CC
The configure script is hard coded to use gcc without fallback on riscv64.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-12 17:25:15 +09:00
28ebf973d6 nix: add sharefs supplementary group
This works around vfs inode file attribute race.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-11 23:28:18 +09:00
41aeb404ec internal/rosa/hakurei: 0.3.7 to 0.4.0
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-11 10:53:29 +09:00
0b1009786f release: 0.4.0
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-11 10:49:43 +09:00
b390640376 internal/landlock: relocate from package container
This is not possible to use directly, so remove it from the public API.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-10 23:56:45 +09:00
ad2c9f36cd container: unexport PR_SET_NO_NEW_PRIVS wrapper
This is subtle to use correctly. It also does not make sense as part of the container API.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-10 23:45:51 +09:00
67db3fbb8d check: use encoding interfaces
This turned out not to require specific treatment, so the shared interfaces are cleaner.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-10 22:11:53 +09:00
560cb626a1 hst: remove enablement json adapter
The go116 behaviour of built-in new function makes this cleaner.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-10 20:47:30 +09:00
c33a6a5b7e hst: optionally reject insecure options
This prevents inadvertent use of insecure compatibility features.

Closes #30.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-10 19:34:02 +09:00
952082bd9b internal/rosa/python: 3.14.3 to 3.14.4
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-10 02:38:22 +09:00
24a9b24823 internal/rosa/openssl: 3.6.1 to 3.6.2
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-10 02:38:02 +09:00
c2e61e7987 internal/rosa/libcap: 2.77 to 2.78
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-10 02:37:04 +09:00
86787b3bc5 internal/rosa/tamago: 1.26.1 to 1.26.2
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-10 02:31:57 +09:00
cdfcfe6ce0 internal/rosa/go: 1.26.1 to 1.26.2
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-10 02:18:27 +09:00
68a2f0c240 internal/rosa/llvm: remove unused field
This change also renames confusingly named flags field and corrects its doc comment.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-10 02:13:26 +09:00
7319c7adf9 internal/rosa/llvm: use latest version on arm64
This also removes arch-specific patches because they were not useful.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-10 01:07:25 +09:00
e9c890cbb2 internal/rosa/llvm: enable cross compilation
This now passes the test suite.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-10 00:59:14 +09:00
6f924336fc internal/rosa/llvm: increase stack size
Some aarch64 regression tests fail intermittently on the default size.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-10 00:56:51 +09:00
bd88f10524 internal/rosa/llvm: 22.1.2 to 22.1.3
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-09 17:36:23 +09:00
132 changed files with 2423 additions and 1622 deletions

View File

@@ -2,7 +2,7 @@
package check
import (
"encoding/json"
"encoding"
"errors"
"fmt"
"path/filepath"
@@ -30,6 +30,16 @@ func (e AbsoluteError) Is(target error) bool {
// Absolute holds a pathname checked to be absolute.
type Absolute struct{ pathname unique.Handle[string] }
var (
_ encoding.TextAppender = new(Absolute)
_ encoding.TextMarshaler = new(Absolute)
_ encoding.TextUnmarshaler = new(Absolute)
_ encoding.BinaryAppender = new(Absolute)
_ encoding.BinaryMarshaler = new(Absolute)
_ encoding.BinaryUnmarshaler = new(Absolute)
)
// ok returns whether [Absolute] is not the zero value.
func (a *Absolute) ok() bool { return a != nil && *a != (Absolute{}) }
@@ -84,13 +94,16 @@ func (a *Absolute) Append(elem ...string) *Absolute {
// Dir calls [filepath.Dir] with [Absolute] as its argument.
func (a *Absolute) Dir() *Absolute { return unsafeAbs(filepath.Dir(a.String())) }
// GobEncode returns the checked pathname.
func (a *Absolute) GobEncode() ([]byte, error) {
return []byte(a.String()), nil
// AppendText appends the checked pathname.
func (a *Absolute) AppendText(data []byte) ([]byte, error) {
return append(data, a.String()...), nil
}
// GobDecode stores data if it represents an absolute pathname.
func (a *Absolute) GobDecode(data []byte) error {
// MarshalText returns the checked pathname.
func (a *Absolute) MarshalText() ([]byte, error) { return a.AppendText(nil) }
// UnmarshalText stores data if it represents an absolute pathname.
func (a *Absolute) UnmarshalText(data []byte) error {
pathname := string(data)
if !filepath.IsAbs(pathname) {
return AbsoluteError(pathname)
@@ -99,23 +112,9 @@ func (a *Absolute) GobDecode(data []byte) error {
return nil
}
// MarshalJSON returns a JSON representation of the checked pathname.
func (a *Absolute) MarshalJSON() ([]byte, error) {
return json.Marshal(a.String())
}
// UnmarshalJSON stores data if it represents an absolute pathname.
func (a *Absolute) UnmarshalJSON(data []byte) error {
var pathname string
if err := json.Unmarshal(data, &pathname); err != nil {
return err
}
if !filepath.IsAbs(pathname) {
return AbsoluteError(pathname)
}
a.pathname = unique.Make(pathname)
return nil
}
func (a *Absolute) AppendBinary(data []byte) ([]byte, error) { return a.AppendText(data) }
func (a *Absolute) MarshalBinary() ([]byte, error) { return a.MarshalText() }
func (a *Absolute) UnmarshalBinary(data []byte) error { return a.UnmarshalText(data) }
// SortAbs calls [slices.SortFunc] for a slice of [Absolute].
func SortAbs(x []*Absolute) {

View File

@@ -170,20 +170,20 @@ func TestCodecAbsolute(t *testing.T) {
{"good", MustAbs("/etc"),
nil,
"\t\x7f\x05\x01\x02\xff\x82\x00\x00\x00\b\xff\x80\x00\x04/etc",
",\xff\x83\x03\x01\x01\x06sCheck\x01\xff\x84\x00\x01\x02\x01\bPathname\x01\xff\x80\x00\x01\x05Magic\x01\x06\x00\x00\x00\t\x7f\x05\x01\x02\xff\x82\x00\x00\x00\x0f\xff\x84\x01\x04/etc\x01\xfc\xc0\xed\x00\x00\x00",
"\t\x7f\x06\x01\x02\xff\x82\x00\x00\x00\b\xff\x80\x00\x04/etc",
",\xff\x83\x03\x01\x01\x06sCheck\x01\xff\x84\x00\x01\x02\x01\bPathname\x01\xff\x80\x00\x01\x05Magic\x01\x06\x00\x00\x00\t\x7f\x06\x01\x02\xff\x82\x00\x00\x00\x0f\xff\x84\x01\x04/etc\x01\xfc\xc0\xed\x00\x00\x00",
`"/etc"`, `{"val":"/etc","magic":3236757504}`},
{"not absolute", nil,
AbsoluteError("etc"),
"\t\x7f\x05\x01\x02\xff\x82\x00\x00\x00\a\xff\x80\x00\x03etc",
",\xff\x83\x03\x01\x01\x06sCheck\x01\xff\x84\x00\x01\x02\x01\bPathname\x01\xff\x80\x00\x01\x05Magic\x01\x06\x00\x00\x00\t\x7f\x05\x01\x02\xff\x82\x00\x00\x00\x0f\xff\x84\x01\x03etc\x01\xfb\x01\x81\xda\x00\x00\x00",
"\t\x7f\x06\x01\x02\xff\x82\x00\x00\x00\a\xff\x80\x00\x03etc",
",\xff\x83\x03\x01\x01\x06sCheck\x01\xff\x84\x00\x01\x02\x01\bPathname\x01\xff\x80\x00\x01\x05Magic\x01\x06\x00\x00\x00\t\x7f\x06\x01\x02\xff\x82\x00\x00\x00\x0f\xff\x84\x01\x03etc\x01\xfb\x01\x81\xda\x00\x00\x00",
`"etc"`, `{"val":"etc","magic":3236757504}`},
{"zero", nil,
new(AbsoluteError),
"\t\x7f\x05\x01\x02\xff\x82\x00\x00\x00\x04\xff\x80\x00\x00",
",\xff\x83\x03\x01\x01\x06sCheck\x01\xff\x84\x00\x01\x02\x01\bPathname\x01\xff\x80\x00\x01\x05Magic\x01\x06\x00\x00\x00\t\x7f\x05\x01\x02\xff\x82\x00\x00\x00\f\xff\x84\x01\x00\x01\xfb\x01\x81\xda\x00\x00\x00",
"\t\x7f\x06\x01\x02\xff\x82\x00\x00\x00\x04\xff\x80\x00\x00",
",\xff\x83\x03\x01\x01\x06sCheck\x01\xff\x84\x00\x01\x02\x01\bPathname\x01\xff\x80\x00\x01\x05Magic\x01\x06\x00\x00\x00\t\x7f\x06\x01\x02\xff\x82\x00\x00\x00\f\xff\x84\x01\x00\x01\xfb\x01\x81\xda\x00\x00\x00",
`""`, `{"val":"","magic":3236757504}`},
}
@@ -347,15 +347,6 @@ func TestCodecAbsolute(t *testing.T) {
})
})
}
t.Run("json passthrough", func(t *testing.T) {
t.Parallel()
wantErr := "invalid character ':' looking for beginning of value"
if err := new(Absolute).UnmarshalJSON([]byte(":3")); err == nil || err.Error() != wantErr {
t.Errorf("UnmarshalJSON: error = %v, want %s", err, wantErr)
}
})
}
func TestAbsoluteWrap(t *testing.T) {

View File

@@ -38,8 +38,9 @@ var errSuccess = errors.New("success")
func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErrs, out io.Writer) command.Command {
var (
flagVerbose bool
flagJSON bool
flagVerbose bool
flagInsecure bool
flagJSON bool
)
c := command.New(out, log.Printf, "hakurei", func([]string) error {
msg.SwapVerbose(flagVerbose)
@@ -57,6 +58,7 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
return nil
}).
Flag(&flagVerbose, "v", command.BoolFlag(false), "Increase log verbosity").
Flag(&flagInsecure, "insecure", command.BoolFlag(false), "Allow use of insecure compatibility options").
Flag(&flagJSON, "json", command.BoolFlag(false), "Serialise output in JSON when applicable")
c.Command("shim", command.UsageInternal, func([]string) error { outcome.Shim(msg); return errSuccess })
@@ -75,7 +77,12 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
config.Container.Args = append(config.Container.Args, args[1:]...)
}
outcome.Main(ctx, msg, config, flagIdentifierFile)
var flags int
if flagInsecure {
flags |= hst.VAllowInsecure
}
outcome.Main(ctx, msg, config, flags, flagIdentifierFile)
panic("unreachable")
}).
Flag(&flagIdentifierFile, "identifier-fd", command.IntFlag(-1),
@@ -145,7 +152,7 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
}
}
var et hst.Enablement
var et hst.Enablements
if flagWayland {
et |= hst.EWayland
}
@@ -163,7 +170,7 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
ID: flagID,
Identity: flagIdentity,
Groups: flagGroups,
Enablements: hst.NewEnablements(et),
Enablements: &et,
Container: &hst.ContainerConfig{
Filesystem: []hst.FilesystemConfigJSON{
@@ -282,7 +289,7 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
}
}
outcome.Main(ctx, msg, &config, -1)
outcome.Main(ctx, msg, &config, 0, -1)
panic("unreachable")
}).
Flag(&flagDBusConfigSession, "dbus-config", command.StringFlag("builtin"),

View File

@@ -20,7 +20,7 @@ func TestHelp(t *testing.T) {
}{
{
"main", []string{}, `
Usage: hakurei [-h | --help] [-v] [--json] COMMAND [OPTIONS]
Usage: hakurei [-h | --help] [-v] [--insecure] [--json] COMMAND [OPTIONS]
Commands:
run Load and start container from configuration file

View File

@@ -56,7 +56,7 @@ func printShowInstance(
t := newPrinter(output)
defer t.MustFlush()
if err := config.Validate(); err != nil {
if err := config.Validate(hst.VAllowInsecure); err != nil {
valid = false
if m, ok := message.GetMessage(err); ok {
mustPrint(output, "Error: "+m+"!\n\n")

View File

@@ -32,7 +32,7 @@ var (
PID: 0xbeef,
ShimPID: 0xcafe,
Config: &hst.Config{
Enablements: hst.NewEnablements(hst.EWayland | hst.EPipeWire),
Enablements: new(hst.EWayland | hst.EPipeWire),
Identity: 1,
Container: &hst.ContainerConfig{
Shell: check.MustAbs("/bin/sh"),

90
cmd/mbf/cache.go Normal file
View File

@@ -0,0 +1,90 @@
package main
import (
"context"
"os"
"path/filepath"
"hakurei.app/check"
"hakurei.app/internal/pkg"
"hakurei.app/message"
)
// cache refers to an instance of [pkg.Cache] that might be open.
type cache struct {
ctx context.Context
msg message.Msg
// Should generally not be used directly.
c *pkg.Cache
cures, jobs int
hostAbstract, idle bool
base string
}
// open opens the underlying [pkg.Cache].
func (cache *cache) open() (err error) {
if cache.c != nil {
return os.ErrInvalid
}
if cache.base == "" {
cache.base = "cache"
}
var base *check.Absolute
if cache.base, err = filepath.Abs(cache.base); err != nil {
return
} else if base, err = check.NewAbs(cache.base); err != nil {
return
}
var flags int
if cache.idle {
flags |= pkg.CSchedIdle
}
if cache.hostAbstract {
flags |= pkg.CHostAbstract
}
done := make(chan struct{})
defer close(done)
go func() {
select {
case <-cache.ctx.Done():
os.Exit(2)
case <-done:
return
}
}()
cache.msg.Verbosef("opening cache at %s", base)
cache.c, err = pkg.Open(
cache.ctx,
cache.msg,
flags,
cache.cures,
cache.jobs,
base,
)
return
}
// Close closes the underlying [pkg.Cache] if it is open.
func (cache *cache) Close() {
if cache.c != nil {
cache.c.Close()
}
}
// Do calls f on the underlying cache and returns its error value.
func (cache *cache) Do(f func(cache *pkg.Cache) error) error {
if cache.c == nil {
if err := cache.open(); err != nil {
return err
}
}
return f(cache.c)
}

38
cmd/mbf/cache_test.go Normal file
View File

@@ -0,0 +1,38 @@
package main
import (
"context"
"log"
"os"
"testing"
"hakurei.app/internal/pkg"
"hakurei.app/message"
)
func TestCache(t *testing.T) {
t.Parallel()
cm := cache{
ctx: context.Background(),
msg: message.New(log.New(os.Stderr, "check: ", 0)),
base: t.TempDir(),
hostAbstract: true, idle: true,
}
defer cm.Close()
cm.Close()
if err := cm.open(); err != nil {
t.Fatalf("open: error = %v", err)
}
if err := cm.open(); err != os.ErrInvalid {
t.Errorf("(duplicate) open: error = %v", err)
}
if err := cm.Do(func(cache *pkg.Cache) error {
return cache.Scrub(0)
}); err != nil {
t.Errorf("Scrub: error = %v", err)
}
}

127
cmd/mbf/info.go Normal file
View File

@@ -0,0 +1,127 @@
package main
import (
"errors"
"fmt"
"io"
"os"
"strings"
"hakurei.app/internal/pkg"
"hakurei.app/internal/rosa"
)
// commandInfo implements the info subcommand.
func commandInfo(
cm *cache,
args []string,
w io.Writer,
writeStatus bool,
reportPath string,
) (err error) {
if len(args) == 0 {
return errors.New("info requires at least 1 argument")
}
var r *rosa.Report
if reportPath != "" {
if r, err = rosa.OpenReport(reportPath); err != nil {
return err
}
defer func() {
if closeErr := r.Close(); err == nil {
err = closeErr
}
}()
defer r.HandleAccess(&err)()
}
// recovered by HandleAccess
mustPrintln := func(a ...any) {
if _, _err := fmt.Fprintln(w, a...); _err != nil {
panic(_err)
}
}
mustPrint := func(a ...any) {
if _, _err := fmt.Fprint(w, a...); _err != nil {
panic(_err)
}
}
for i, name := range args {
if p, ok := rosa.ResolveName(name); !ok {
return fmt.Errorf("unknown artifact %q", name)
} else {
var suffix string
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 : " +
strings.TrimSuffix(meta.Website, "/"))
}
if len(meta.Dependencies) > 0 {
mustPrint("depends on :")
for _, d := range meta.Dependencies {
s := rosa.GetMetadata(d).Name
if version := rosa.Std.Version(d); version != rosa.Unversioned {
s += "-" + version
}
mustPrint(" " + s)
}
mustPrintln()
}
const statusPrefix = "status : "
if writeStatus {
if r == nil {
var f io.ReadSeekCloser
err = cm.Do(func(cache *pkg.Cache) (err error) {
f, err = cache.OpenStatus(rosa.Std.Load(p))
return
})
if err != nil {
if errors.Is(err, os.ErrNotExist) {
mustPrintln(
statusPrefix + "not yet cured",
)
} else {
return
}
} else {
mustPrint(statusPrefix)
_, err = io.Copy(w, f)
if err = errors.Join(err, f.Close()); err != nil {
return
}
}
} else if err = cm.Do(func(cache *pkg.Cache) (err error) {
status, n := r.ArtifactOf(cache.Ident(rosa.Std.Load(p)))
if status == nil {
mustPrintln(
statusPrefix + "not in report",
)
} else {
mustPrintln("size :", n)
mustPrint(statusPrefix)
if _, err = w.Write(status); err != nil {
return
}
}
return
}); err != nil {
return
}
}
if i != len(args)-1 {
mustPrintln()
}
}
}
return nil
}

170
cmd/mbf/info_test.go Normal file
View File

@@ -0,0 +1,170 @@
package main
import (
"context"
"fmt"
"log"
"os"
"path/filepath"
"reflect"
"strings"
"syscall"
"testing"
"unsafe"
"hakurei.app/internal/pkg"
"hakurei.app/internal/rosa"
"hakurei.app/message"
)
func TestInfo(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
args []string
status map[string]string
report string
want string
wantErr any
}{
{"qemu", []string{"qemu"}, nil, "", `
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-` + rosa.Std.Version(rosa.GLib) + ` zstd-` + rosa.Std.Version(rosa.Zstd) + `
`, nil},
{"multi", []string{"hakurei", "hakurei-dist"}, nil, "", `
name : hakurei-` + rosa.Std.Version(rosa.Hakurei) + `
description : low-level userspace tooling for Rosa OS
website : https://hakurei.app
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-` + rosa.Std.Version(rosa.Zlib) + `
description : lossless data-compression library
website : https://zlib.net
`, fmt.Errorf("unknown artifact %q", "\x00")},
{"status cache", []string{"zlib", "zstd"}, map[string]string{
"zstd": "internal/pkg (amd64) on satori\n",
"hakurei": "internal/pkg (amd64) on satori\n\n",
}, "", `
name : zlib-` + rosa.Std.Version(rosa.Zlib) + `
description : lossless data-compression library
website : https://zlib.net
status : not yet cured
name : zstd-` + rosa.Std.Version(rosa.Zstd) + `
description : a fast compression algorithm
website : https://facebook.github.io/zstd
status : internal/pkg (amd64) on satori
`, nil},
{"status cache perm", []string{"zlib"}, map[string]string{
"zlib": "\x00",
}, "", `
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(rosa.Std.Load(rosa.Zlib)).Value())),
Err: syscall.EACCES,
}
}},
{"status report", []string{"zlib"}, nil, strings.Repeat("\x00", len(pkg.Checksum{})+8), `
name : zlib-` + rosa.Std.Version(rosa.Zlib) + `
description : lossless data-compression library
website : https://zlib.net
status : not in report
`, nil},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
var (
cm *cache
buf strings.Builder
rp string
)
if tc.status != nil || tc.report != "" {
cm = &cache{
ctx: context.Background(),
msg: message.New(log.New(os.Stderr, "info: ", 0)),
base: t.TempDir(),
}
defer cm.Close()
}
if tc.report != "" {
rp = filepath.Join(t.TempDir(), "report")
if err := os.WriteFile(
rp,
unsafe.Slice(unsafe.StringData(tc.report), len(tc.report)),
0400,
); err != nil {
t.Fatal(err)
}
}
if tc.status != nil {
for name, status := range tc.status {
p, ok := rosa.ResolveName(name)
if !ok {
t.Fatalf("invalid name %q", name)
}
perm := os.FileMode(0400)
if status == "\x00" {
perm = 0
}
if err := cm.Do(func(cache *pkg.Cache) error {
return os.WriteFile(filepath.Join(
cm.base,
"status",
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)
}
}
}
var wantErr error
switch c := tc.wantErr.(type) {
case error:
wantErr = c
case func(cm *cache) error:
wantErr = c(cm)
default:
if tc.wantErr != nil {
t.Fatalf("invalid wantErr %#v", tc.wantErr)
}
}
if err := commandInfo(
cm,
tc.args,
&buf,
cm != nil,
rp,
); !reflect.DeepEqual(err, wantErr) {
t.Fatalf("commandInfo: error = %v, want %v", err, wantErr)
}
if got := buf.String(); got != strings.TrimPrefix(tc.want, "\n") {
t.Errorf("commandInfo:\n%s\nwant\n%s", got, tc.want)
}
})
}
}

View File

@@ -14,6 +14,7 @@ package main
import (
"context"
"crypto/sha512"
"errors"
"fmt"
"io"
@@ -23,7 +24,6 @@ import (
"path/filepath"
"runtime"
"strconv"
"strings"
"sync"
"sync/atomic"
"syscall"
@@ -53,14 +53,13 @@ func main() {
log.Fatal("this program must not run as root")
}
var cache *pkg.Cache
ctx, stop := signal.NotifyContext(context.Background(),
syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
defer stop()
var cm cache
defer func() {
if cache != nil {
cache.Close()
}
cm.Close()
if r := recover(); r != nil {
fmt.Println(r)
@@ -70,55 +69,34 @@ func main() {
var (
flagQuiet bool
flagCures int
flagBase string
flagIdle bool
flagHostAbstract bool
)
c := command.New(os.Stderr, log.Printf, "mbf", func([]string) (err error) {
c := command.New(os.Stderr, log.Printf, "mbf", func([]string) error {
msg.SwapVerbose(!flagQuiet)
flagBase = os.ExpandEnv(flagBase)
if flagBase == "" {
flagBase = "cache"
}
var base *check.Absolute
if flagBase, err = filepath.Abs(flagBase); err != nil {
return
} else if base, err = check.NewAbs(flagBase); err != nil {
return
}
var flags int
if flagIdle {
flags |= pkg.CSchedIdle
}
if flagHostAbstract {
flags |= pkg.CHostAbstract
}
cache, err = pkg.Open(ctx, msg, flags, flagCures, base)
return
cm.ctx, cm.msg = ctx, msg
cm.base = os.ExpandEnv(cm.base)
return nil
}).Flag(
&flagQuiet,
"q", command.BoolFlag(false),
"Do not print cure messages",
).Flag(
&flagCures,
&cm.cures,
"cures", command.IntFlag(0),
"Maximum number of dependencies to cure at any given time",
).Flag(
&flagBase,
&cm.jobs,
"jobs", command.IntFlag(0),
"Preferred number of jobs to run, when applicable",
).Flag(
&cm.base,
"d", command.StringFlag("$MBF_CACHE_DIR"),
"Directory to store cured artifacts",
).Flag(
&flagIdle,
&cm.idle,
"sched-idle", command.BoolFlag(false),
"Set SCHED_IDLE scheduling policy",
).Flag(
&flagHostAbstract,
&cm.hostAbstract,
"host-abstract", command.BoolFlag(
os.Getenv("MBF_HOST_ABSTRACT") != "",
),
@@ -126,6 +104,19 @@ func main() {
"abstract UNIX sockets",
)
c.NewCommand(
"checksum", "Compute checksum of data read from standard input",
func([]string) error {
go func() { <-ctx.Done(); os.Exit(1) }()
h := sha512.New384()
if _, err := io.Copy(h, os.Stdin); err != nil {
return err
}
log.Println(pkg.Encode(pkg.Checksum(h.Sum(nil))))
return nil
},
)
{
var flagShifts int
c.NewCommand(
@@ -137,7 +128,9 @@ func main() {
if flagShifts < 0 || flagShifts > 31 {
flagShifts = 12
}
return cache.Scrub(runtime.NumCPU() << flagShifts)
return cm.Do(func(cache *pkg.Cache) error {
return cache.Scrub(runtime.NumCPU() << flagShifts)
})
},
).Flag(
&flagShifts,
@@ -155,93 +148,7 @@ func main() {
"info",
"Display out-of-band metadata of an artifact",
func(args []string) (err error) {
if len(args) == 0 {
return errors.New("info requires at least 1 argument")
}
var r *rosa.Report
if flagReport != "" {
if r, err = rosa.OpenReport(flagReport); err != nil {
return err
}
defer func() {
if closeErr := r.Close(); err == nil {
err = closeErr
}
}()
defer r.HandleAccess(&err)()
}
for i, name := range args {
if p, ok := rosa.ResolveName(name); !ok {
return fmt.Errorf("unknown artifact %q", name)
} else {
var suffix string
if version := rosa.Std.Version(p); version != rosa.Unversioned {
suffix += "-" + version
}
fmt.Println("name : " + name + suffix)
meta := rosa.GetMetadata(p)
fmt.Println("description : " + meta.Description)
if meta.Website != "" {
fmt.Println("website : " +
strings.TrimSuffix(meta.Website, "/"))
}
if len(meta.Dependencies) > 0 {
fmt.Print("depends on :")
for _, d := range meta.Dependencies {
s := rosa.GetMetadata(d).Name
if version := rosa.Std.Version(d); version != rosa.Unversioned {
s += "-" + version
}
fmt.Print(" " + s)
}
fmt.Println()
}
const statusPrefix = "status : "
if flagStatus {
if r == nil {
var f io.ReadSeekCloser
f, err = cache.OpenStatus(rosa.Std.Load(p))
if err != nil {
if errors.Is(err, os.ErrNotExist) {
fmt.Println(
statusPrefix + "not yet cured",
)
} else {
return
}
} else {
fmt.Print(statusPrefix)
_, err = io.Copy(os.Stdout, f)
if err = errors.Join(err, f.Close()); err != nil {
return
}
}
} else {
status, n := r.ArtifactOf(cache.Ident(rosa.Std.Load(p)))
if status == nil {
fmt.Println(
statusPrefix + "not in report",
)
} else {
fmt.Println("size :", n)
fmt.Print(statusPrefix)
if _, err = os.Stdout.Write(status); err != nil {
return
}
}
}
}
if i != len(args)-1 {
fmt.Println()
}
}
}
return nil
return commandInfo(&cm, args, os.Stdout, flagStatus, flagReport)
},
).
Flag(
@@ -287,7 +194,9 @@ func main() {
if ext.Isatty(int(w.Fd())) {
return errors.New("output appears to be a terminal")
}
return rosa.WriteReport(msg, w, cache)
return cm.Do(func(cache *pkg.Cache) error {
return rosa.WriteReport(msg, w, cache)
})
},
)
@@ -382,25 +291,37 @@ func main() {
rosa.SetGentooStage3(flagGentoo, checksum)
}
_, _, _, stage1 := (t - 2).NewLLVM()
_, _, _, stage2 := (t - 1).NewLLVM()
_, _, _, stage3 := t.NewLLVM()
var (
pathname *check.Absolute
checksum [2]unique.Handle[pkg.Checksum]
)
if pathname, _, err = cache.Cure(stage1); err != nil {
return err
if err = cm.Do(func(cache *pkg.Cache) (err error) {
pathname, _, err = cache.Cure(
(t - 2).Load(rosa.Clang),
)
return
}); err != nil {
return
}
log.Println("stage1:", pathname)
if pathname, checksum[0], err = cache.Cure(stage2); err != nil {
return err
if err = cm.Do(func(cache *pkg.Cache) (err error) {
pathname, checksum[0], err = cache.Cure(
(t - 1).Load(rosa.Clang),
)
return
}); err != nil {
return
}
log.Println("stage2:", pathname)
if pathname, checksum[1], err = cache.Cure(stage3); err != nil {
return err
if err = cm.Do(func(cache *pkg.Cache) (err error) {
pathname, checksum[1], err = cache.Cure(
t.Load(rosa.Clang),
)
return
}); err != nil {
return
}
log.Println("stage3:", pathname)
@@ -417,10 +338,13 @@ func main() {
}
if flagStage0 {
if pathname, _, err = cache.Cure(
t.Load(rosa.Stage0),
); err != nil {
return err
if err = cm.Do(func(cache *pkg.Cache) (err error) {
pathname, _, err = cache.Cure(
t.Load(rosa.Stage0),
)
return
}); err != nil {
return
}
log.Println(pathname)
}
@@ -465,7 +389,11 @@ func main() {
switch {
default:
pathname, _, err := cache.Cure(rosa.Std.Load(p))
var pathname *check.Absolute
err := cm.Do(func(cache *pkg.Cache) (err error) {
pathname, _, err = cache.Cure(rosa.Std.Load(p))
return
})
if err != nil {
return err
}
@@ -505,7 +433,9 @@ func main() {
return err
}
if err = cache.EncodeAll(f, rosa.Std.Load(p)); err != nil {
if err = cm.Do(func(cache *pkg.Cache) error {
return cache.EncodeAll(f, rosa.Std.Load(p))
}); err != nil {
_ = f.Close()
return err
}
@@ -513,13 +443,15 @@ func main() {
return f.Close()
case flagEnter:
return cache.EnterExec(
ctx,
rosa.Std.Load(p),
true, os.Stdin, os.Stdout, os.Stderr,
rosa.AbsSystem.Append("bin", "mksh"),
"sh",
)
return cm.Do(func(cache *pkg.Cache) error {
return cache.EnterExec(
ctx,
rosa.Std.Load(p),
true, os.Stdin, os.Stdout, os.Stderr,
rosa.AbsSystem.Append("bin", "mksh"),
"sh",
)
})
}
},
).
@@ -551,7 +483,7 @@ func main() {
"shell",
"Interactive shell in the specified Rosa OS environment",
func(args []string) error {
presets := make([]rosa.PArtifact, len(args))
presets := make([]rosa.PArtifact, len(args)+3)
for i, arg := range args {
p, ok := rosa.ResolveName(arg)
if !ok {
@@ -559,21 +491,24 @@ func main() {
}
presets[i] = p
}
base := rosa.Clang
if !flagWithToolchain {
base = rosa.Musl
}
presets = append(presets,
base,
rosa.Mksh,
rosa.Toybox,
)
root := make(pkg.Collect, 0, 6+len(args))
root = rosa.Std.AppendPresets(root, presets...)
if flagWithToolchain {
musl, compilerRT, runtimes, clang := (rosa.Std - 1).NewLLVM()
root = append(root, musl, compilerRT, runtimes, clang)
} else {
root = append(root, rosa.Std.Load(rosa.Musl))
}
root = append(root,
rosa.Std.Load(rosa.Mksh),
rosa.Std.Load(rosa.Toybox),
)
if _, _, err := cache.Cure(&root); err == nil {
if err := cm.Do(func(cache *pkg.Cache) error {
_, _, err := cache.Cure(&root)
return err
}); err == nil {
return errors.New("unreachable")
} else if !pkg.IsCollected(err) {
return err
@@ -585,11 +520,22 @@ func main() {
}
cured := make(map[pkg.Artifact]cureRes)
for _, a := range root {
pathname, checksum, err := cache.Cure(a)
if err != nil {
if err := cm.Do(func(cache *pkg.Cache) error {
pathname, checksum, err := cache.Cure(a)
if err == nil {
cured[a] = cureRes{pathname, checksum}
}
return err
}); err != nil {
return err
}
}
// explicitly open for direct error-free use from this point
if cm.c == nil {
if err := cm.open(); err != nil {
return err
}
cured[a] = cureRes{pathname, checksum}
}
layers := pkg.PromoteLayers(root, func(a pkg.Artifact) (
@@ -599,7 +545,7 @@ func main() {
res := cured[a]
return res.pathname, res.checksum
}, func(i int, d pkg.Artifact) {
r := pkg.Encode(cache.Ident(d).Value())
r := pkg.Encode(cm.c.Ident(d).Value())
if s, ok := d.(fmt.Stringer); ok {
if name := s.String(); name != "" {
r += "-" + name
@@ -689,9 +635,7 @@ func main() {
)
c.MustParse(os.Args[1:], func(err error) {
if cache != nil {
cache.Close()
}
cm.Close()
if w, ok := err.(interface{ Unwrap() []error }); !ok {
log.Fatal(err)
} else {

View File

@@ -21,6 +21,7 @@ import (
"hakurei.app/container/std"
"hakurei.app/ext"
"hakurei.app/fhs"
"hakurei.app/internal/landlock"
"hakurei.app/message"
)
@@ -307,7 +308,7 @@ func (p *Container) Start() error {
done <- func() error {
// PR_SET_NO_NEW_PRIVS: thread-directed but acts on all processes
// created from the calling thread
if err := SetNoNewPrivs(); err != nil {
if err := setNoNewPrivs(); err != nil {
return &StartError{
Fatal: true,
Step: "prctl(PR_SET_NO_NEW_PRIVS)",
@@ -317,12 +318,14 @@ func (p *Container) Start() error {
// landlock: depends on per-thread state but acts on a process group
{
rulesetAttr := &RulesetAttr{Scoped: LANDLOCK_SCOPE_SIGNAL}
rulesetAttr := &landlock.RulesetAttr{
Scoped: landlock.LANDLOCK_SCOPE_SIGNAL,
}
if !p.HostAbstract {
rulesetAttr.Scoped |= LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
rulesetAttr.Scoped |= landlock.LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
}
if abi, err := LandlockGetABI(); err != nil {
if abi, err := landlock.GetABI(); err != nil {
if p.HostAbstract || !p.HostNet {
// landlock can be skipped here as it restricts access
// to resources already covered by namespaces (pid, net)
@@ -351,7 +354,7 @@ func (p *Container) Start() error {
}
} else {
p.msg.Verbosef("enforcing landlock ruleset %s", rulesetAttr)
if err = LandlockRestrictSelf(rulesetFd, 0); err != nil {
if err = landlock.RestrictSelf(rulesetFd, 0); err != nil {
_ = Close(rulesetFd)
return &StartError{
Fatal: true,

View File

@@ -26,6 +26,7 @@ import (
"hakurei.app/fhs"
"hakurei.app/hst"
"hakurei.app/internal/info"
"hakurei.app/internal/landlock"
"hakurei.app/internal/params"
"hakurei.app/ldd"
"hakurei.app/message"
@@ -456,7 +457,7 @@ func TestContainer(t *testing.T) {
c.RetainSession = tc.session
c.HostNet = tc.net
if info.CanDegrade {
if _, err := container.LandlockGetABI(); err != nil {
if _, err := landlock.GetABI(); err != nil {
if !errors.Is(err, syscall.ENOSYS) {
t.Fatalf("LandlockGetABI: error = %v", err)
}

View File

@@ -148,7 +148,7 @@ func (direct) lockOSThread() { runtime.LockOSThread() }
func (direct) setPtracer(pid uintptr) error { return ext.SetPtracer(pid) }
func (direct) setDumpable(dumpable uintptr) error { return ext.SetDumpable(dumpable) }
func (direct) setNoNewPrivs() error { return SetNoNewPrivs() }
func (direct) setNoNewPrivs() error { return setNoNewPrivs() }
func (direct) lastcap(msg message.Msg) uintptr { return LastCap(msg) }
func (direct) capset(hdrp *capHeader, datap *[2]capData) error { return capset(hdrp, datap) }

View File

@@ -1,65 +0,0 @@
package container_test
import (
"testing"
"unsafe"
"hakurei.app/container"
)
func TestLandlockString(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
rulesetAttr *container.RulesetAttr
want string
}{
{"nil", nil, "NULL"},
{"zero", new(container.RulesetAttr), "0"},
{"some", &container.RulesetAttr{Scoped: container.LANDLOCK_SCOPE_SIGNAL}, "scoped: signal"},
{"set", &container.RulesetAttr{
HandledAccessFS: container.LANDLOCK_ACCESS_FS_MAKE_SYM | container.LANDLOCK_ACCESS_FS_IOCTL_DEV | container.LANDLOCK_ACCESS_FS_WRITE_FILE,
HandledAccessNet: container.LANDLOCK_ACCESS_NET_BIND_TCP,
Scoped: container.LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET | container.LANDLOCK_SCOPE_SIGNAL,
}, "fs: write_file make_sym fs_ioctl_dev, net: bind_tcp, scoped: abstract_unix_socket signal"},
{"all", &container.RulesetAttr{
HandledAccessFS: container.LANDLOCK_ACCESS_FS_EXECUTE |
container.LANDLOCK_ACCESS_FS_WRITE_FILE |
container.LANDLOCK_ACCESS_FS_READ_FILE |
container.LANDLOCK_ACCESS_FS_READ_DIR |
container.LANDLOCK_ACCESS_FS_REMOVE_DIR |
container.LANDLOCK_ACCESS_FS_REMOVE_FILE |
container.LANDLOCK_ACCESS_FS_MAKE_CHAR |
container.LANDLOCK_ACCESS_FS_MAKE_DIR |
container.LANDLOCK_ACCESS_FS_MAKE_REG |
container.LANDLOCK_ACCESS_FS_MAKE_SOCK |
container.LANDLOCK_ACCESS_FS_MAKE_FIFO |
container.LANDLOCK_ACCESS_FS_MAKE_BLOCK |
container.LANDLOCK_ACCESS_FS_MAKE_SYM |
container.LANDLOCK_ACCESS_FS_REFER |
container.LANDLOCK_ACCESS_FS_TRUNCATE |
container.LANDLOCK_ACCESS_FS_IOCTL_DEV,
HandledAccessNet: container.LANDLOCK_ACCESS_NET_BIND_TCP |
container.LANDLOCK_ACCESS_NET_CONNECT_TCP,
Scoped: container.LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET |
container.LANDLOCK_SCOPE_SIGNAL,
}, "fs: execute write_file read_file read_dir remove_dir remove_file make_char make_dir make_reg make_sock make_fifo make_block make_sym fs_refer fs_truncate fs_ioctl_dev, net: bind_tcp connect_tcp, scoped: abstract_unix_socket signal"},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
if got := tc.rulesetAttr.String(); got != tc.want {
t.Errorf("String: %s, want %s", got, tc.want)
}
})
}
}
func TestLandlockAttrSize(t *testing.T) {
t.Parallel()
want := 24
if got := unsafe.Sizeof(container.RulesetAttr{}); got != uintptr(want) {
t.Errorf("Sizeof: %d, want %d", got, want)
}
}

View File

@@ -7,8 +7,8 @@ import (
"hakurei.app/ext"
)
// SetNoNewPrivs sets the calling thread's no_new_privs attribute.
func SetNoNewPrivs() error {
// setNoNewPrivs sets the calling thread's no_new_privs attribute.
func setNoNewPrivs() error {
return ext.Prctl(PR_SET_NO_NEW_PRIVS, 1, 0)
}

View File

@@ -140,21 +140,29 @@ var (
ErrInsecure = errors.New("configuration is insecure")
)
const (
// VAllowInsecure allows use of compatibility options considered insecure
// under any configuration, to work around ecosystem-wide flaws.
VAllowInsecure = 1 << iota
)
// Validate checks [Config] and returns [AppError] if an invalid value is encountered.
func (config *Config) Validate() error {
func (config *Config) Validate(flags int) error {
const step = "validate configuration"
if config == nil {
return &AppError{Step: "validate configuration", Err: ErrConfigNull,
return &AppError{Step: step, Err: ErrConfigNull,
Msg: "invalid configuration"}
}
// this is checked again in hsu
if config.Identity < IdentityStart || config.Identity > IdentityEnd {
return &AppError{Step: "validate configuration", Err: ErrIdentityBounds,
return &AppError{Step: step, Err: ErrIdentityBounds,
Msg: "identity " + strconv.Itoa(config.Identity) + " out of range"}
}
if config.SchedPolicy < 0 || config.SchedPolicy > ext.SCHED_LAST {
return &AppError{Step: "validate configuration", Err: ErrSchedPolicyBounds,
return &AppError{Step: step, Err: ErrSchedPolicyBounds,
Msg: "scheduling policy " +
strconv.Itoa(int(config.SchedPolicy)) +
" out of range"}
@@ -168,34 +176,51 @@ func (config *Config) Validate() error {
}
if config.Container == nil {
return &AppError{Step: "validate configuration", Err: ErrConfigNull,
return &AppError{Step: step, Err: ErrConfigNull,
Msg: "configuration missing container state"}
}
if config.Container.Home == nil {
return &AppError{Step: "validate configuration", Err: ErrConfigNull,
return &AppError{Step: step, Err: ErrConfigNull,
Msg: "container configuration missing path to home directory"}
}
if config.Container.Shell == nil {
return &AppError{Step: "validate configuration", Err: ErrConfigNull,
return &AppError{Step: step, Err: ErrConfigNull,
Msg: "container configuration missing path to shell"}
}
if config.Container.Path == nil {
return &AppError{Step: "validate configuration", Err: ErrConfigNull,
return &AppError{Step: step, Err: ErrConfigNull,
Msg: "container configuration missing path to initial program"}
}
for key := range config.Container.Env {
if strings.IndexByte(key, '=') != -1 || strings.IndexByte(key, 0) != -1 {
return &AppError{Step: "validate configuration", Err: ErrEnviron,
return &AppError{Step: step, Err: ErrEnviron,
Msg: "invalid environment variable " + strconv.Quote(key)}
}
}
if et := config.Enablements.Unwrap(); !config.DirectPulse && et&EPulse != 0 {
return &AppError{Step: "validate configuration", Err: ErrInsecure,
et := config.Enablements.Unwrap()
if !config.DirectPulse && et&EPulse != 0 {
return &AppError{Step: step, Err: ErrInsecure,
Msg: "enablement PulseAudio is insecure and no longer supported"}
}
if flags&VAllowInsecure == 0 {
switch {
case et&EWayland != 0 && config.DirectWayland:
return &AppError{Step: step, Err: ErrInsecure,
Msg: "direct_wayland is insecure and no longer supported"}
case et&EPipeWire != 0 && config.DirectPipeWire:
return &AppError{Step: step, Err: ErrInsecure,
Msg: "direct_pipewire is insecure and no longer supported"}
case et&EPulse != 0 && config.DirectPulse:
return &AppError{Step: step, Err: ErrInsecure,
Msg: "direct_pulse is insecure and no longer supported"}
}
}
return nil
}

View File

@@ -14,65 +14,109 @@ func TestConfigValidate(t *testing.T) {
testCases := []struct {
name string
config *hst.Config
flags int
wantErr error
}{
{"nil", nil, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
{"nil", nil, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
Msg: "invalid configuration"}},
{"identity lower", &hst.Config{Identity: -1}, &hst.AppError{Step: "validate configuration", Err: hst.ErrIdentityBounds,
{"identity lower", &hst.Config{Identity: -1}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrIdentityBounds,
Msg: "identity -1 out of range"}},
{"identity upper", &hst.Config{Identity: 10000}, &hst.AppError{Step: "validate configuration", Err: hst.ErrIdentityBounds,
{"identity upper", &hst.Config{Identity: 10000}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrIdentityBounds,
Msg: "identity 10000 out of range"}},
{"sched lower", &hst.Config{SchedPolicy: -1}, &hst.AppError{Step: "validate configuration", Err: hst.ErrSchedPolicyBounds,
{"sched lower", &hst.Config{SchedPolicy: -1}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrSchedPolicyBounds,
Msg: "scheduling policy -1 out of range"}},
{"sched upper", &hst.Config{SchedPolicy: 0xcafe}, &hst.AppError{Step: "validate configuration", Err: hst.ErrSchedPolicyBounds,
{"sched upper", &hst.Config{SchedPolicy: 0xcafe}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrSchedPolicyBounds,
Msg: "scheduling policy 51966 out of range"}},
{"dbus session", &hst.Config{SessionBus: &hst.BusConfig{See: []string{""}}},
{"dbus session", &hst.Config{SessionBus: &hst.BusConfig{See: []string{""}}}, 0,
&hst.BadInterfaceError{Interface: "", Segment: "session"}},
{"dbus system", &hst.Config{SystemBus: &hst.BusConfig{See: []string{""}}},
{"dbus system", &hst.Config{SystemBus: &hst.BusConfig{See: []string{""}}}, 0,
&hst.BadInterfaceError{Interface: "", Segment: "system"}},
{"container", &hst.Config{}, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
{"container", &hst.Config{}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
Msg: "configuration missing container state"}},
{"home", &hst.Config{Container: &hst.ContainerConfig{}}, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
{"home", &hst.Config{Container: &hst.ContainerConfig{}}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
Msg: "container configuration missing path to home directory"}},
{"shell", &hst.Config{Container: &hst.ContainerConfig{
Home: fhs.AbsTmp,
}}, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
}}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
Msg: "container configuration missing path to shell"}},
{"path", &hst.Config{Container: &hst.ContainerConfig{
Home: fhs.AbsTmp,
Shell: fhs.AbsTmp,
}}, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
}}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
Msg: "container configuration missing path to initial program"}},
{"env equals", &hst.Config{Container: &hst.ContainerConfig{
Home: fhs.AbsTmp,
Shell: fhs.AbsTmp,
Path: fhs.AbsTmp,
Env: map[string]string{"TERM=": ""},
}}, &hst.AppError{Step: "validate configuration", Err: hst.ErrEnviron,
}}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrEnviron,
Msg: `invalid environment variable "TERM="`}},
{"env NUL", &hst.Config{Container: &hst.ContainerConfig{
Home: fhs.AbsTmp,
Shell: fhs.AbsTmp,
Path: fhs.AbsTmp,
Env: map[string]string{"TERM\x00": ""},
}}, &hst.AppError{Step: "validate configuration", Err: hst.ErrEnviron,
}}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrEnviron,
Msg: `invalid environment variable "TERM\x00"`}},
{"insecure pulse", &hst.Config{Enablements: hst.NewEnablements(hst.EPulse), Container: &hst.ContainerConfig{
{"insecure pulse", &hst.Config{Enablements: new(hst.EPulse), Container: &hst.ContainerConfig{
Home: fhs.AbsTmp,
Shell: fhs.AbsTmp,
Path: fhs.AbsTmp,
}}, &hst.AppError{Step: "validate configuration", Err: hst.ErrInsecure,
}}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrInsecure,
Msg: "enablement PulseAudio is insecure and no longer supported"}},
{"direct wayland", &hst.Config{Enablements: new(hst.EWayland), DirectWayland: true, Container: &hst.ContainerConfig{
Home: fhs.AbsTmp,
Shell: fhs.AbsTmp,
Path: fhs.AbsTmp,
}}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrInsecure,
Msg: "direct_wayland is insecure and no longer supported"}},
{"direct wayland allow", &hst.Config{Enablements: new(hst.EWayland), DirectWayland: true, Container: &hst.ContainerConfig{
Home: fhs.AbsTmp,
Shell: fhs.AbsTmp,
Path: fhs.AbsTmp,
}}, hst.VAllowInsecure, nil},
{"direct pipewire", &hst.Config{Enablements: new(hst.EPipeWire), DirectPipeWire: true, Container: &hst.ContainerConfig{
Home: fhs.AbsTmp,
Shell: fhs.AbsTmp,
Path: fhs.AbsTmp,
}}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrInsecure,
Msg: "direct_pipewire is insecure and no longer supported"}},
{"direct pipewire allow", &hst.Config{Enablements: new(hst.EPipeWire), DirectPipeWire: true, Container: &hst.ContainerConfig{
Home: fhs.AbsTmp,
Shell: fhs.AbsTmp,
Path: fhs.AbsTmp,
}}, hst.VAllowInsecure, nil},
{"direct pulse", &hst.Config{Enablements: new(hst.EPulse), DirectPulse: true, Container: &hst.ContainerConfig{
Home: fhs.AbsTmp,
Shell: fhs.AbsTmp,
Path: fhs.AbsTmp,
}}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrInsecure,
Msg: "direct_pulse is insecure and no longer supported"}},
{"direct pulse allow", &hst.Config{Enablements: new(hst.EPulse), DirectPulse: true, Container: &hst.ContainerConfig{
Home: fhs.AbsTmp,
Shell: fhs.AbsTmp,
Path: fhs.AbsTmp,
}}, hst.VAllowInsecure, nil},
{"valid", &hst.Config{Container: &hst.ContainerConfig{
Home: fhs.AbsTmp,
Shell: fhs.AbsTmp,
Path: fhs.AbsTmp,
}}, nil},
}}, 0, nil},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
if err := tc.config.Validate(); !reflect.DeepEqual(err, tc.wantErr) {
if err := tc.config.Validate(tc.flags); !reflect.DeepEqual(err, tc.wantErr) {
t.Errorf("Validate: error = %#v, want %#v", err, tc.wantErr)
}
})

View File

@@ -7,12 +7,12 @@ import (
"syscall"
)
// Enablement represents an optional host service to export to the target user.
type Enablement byte
// Enablements denotes optional host service to export to the target user.
type Enablements byte
const (
// EWayland exposes a Wayland pathname socket via security-context-v1.
EWayland Enablement = 1 << iota
EWayland Enablements = 1 << iota
// EX11 adds the target user via X11 ChangeHosts and exposes the X11
// pathname socket.
EX11
@@ -28,8 +28,8 @@ const (
EM
)
// String returns a string representation of the flags set on [Enablement].
func (e Enablement) String() string {
// String returns a string representation of the flags set on [Enablements].
func (e Enablements) String() string {
switch e {
case 0:
return "(no enablements)"
@@ -47,7 +47,7 @@ func (e Enablement) String() string {
buf := new(strings.Builder)
buf.Grow(32)
for i := Enablement(1); i < EM; i <<= 1 {
for i := Enablements(1); i < EM; i <<= 1 {
if e&i != 0 {
buf.WriteString(", " + i.String())
}
@@ -60,12 +60,6 @@ func (e Enablement) String() string {
}
}
// NewEnablements returns the address of [Enablement] as [Enablements].
func NewEnablements(e Enablement) *Enablements { return (*Enablements)(&e) }
// Enablements is the [json] adapter for [Enablement].
type Enablements Enablement
// enablementsJSON is the [json] representation of [Enablements].
type enablementsJSON = struct {
Wayland bool `json:"wayland,omitempty"`
@@ -75,24 +69,21 @@ type enablementsJSON = struct {
Pulse bool `json:"pulse,omitempty"`
}
// Unwrap returns the underlying [Enablement].
func (e *Enablements) Unwrap() Enablement {
// Unwrap returns the value pointed to by e.
func (e *Enablements) Unwrap() Enablements {
if e == nil {
return 0
}
return Enablement(*e)
return *e
}
func (e *Enablements) MarshalJSON() ([]byte, error) {
if e == nil {
return nil, syscall.EINVAL
}
func (e Enablements) MarshalJSON() ([]byte, error) {
return json.Marshal(&enablementsJSON{
Wayland: Enablement(*e)&EWayland != 0,
X11: Enablement(*e)&EX11 != 0,
DBus: Enablement(*e)&EDBus != 0,
PipeWire: Enablement(*e)&EPipeWire != 0,
Pulse: Enablement(*e)&EPulse != 0,
Wayland: e&EWayland != 0,
X11: e&EX11 != 0,
DBus: e&EDBus != 0,
PipeWire: e&EPipeWire != 0,
Pulse: e&EPulse != 0,
})
}
@@ -106,22 +97,21 @@ func (e *Enablements) UnmarshalJSON(data []byte) error {
return err
}
var ve Enablement
*e = 0
if v.Wayland {
ve |= EWayland
*e |= EWayland
}
if v.X11 {
ve |= EX11
*e |= EX11
}
if v.DBus {
ve |= EDBus
*e |= EDBus
}
if v.PipeWire {
ve |= EPipeWire
*e |= EPipeWire
}
if v.Pulse {
ve |= EPulse
*e |= EPulse
}
*e = Enablements(ve)
return nil
}

View File

@@ -13,7 +13,7 @@ func TestEnablementString(t *testing.T) {
t.Parallel()
testCases := []struct {
flags hst.Enablement
flags hst.Enablements
want string
}{
{0, "(no enablements)"},
@@ -59,13 +59,13 @@ func TestEnablements(t *testing.T) {
sData string
}{
{"nil", nil, "null", `{"value":null,"magic":3236757504}`},
{"zero", hst.NewEnablements(0), `{}`, `{"value":{},"magic":3236757504}`},
{"wayland", hst.NewEnablements(hst.EWayland), `{"wayland":true}`, `{"value":{"wayland":true},"magic":3236757504}`},
{"x11", hst.NewEnablements(hst.EX11), `{"x11":true}`, `{"value":{"x11":true},"magic":3236757504}`},
{"dbus", hst.NewEnablements(hst.EDBus), `{"dbus":true}`, `{"value":{"dbus":true},"magic":3236757504}`},
{"pipewire", hst.NewEnablements(hst.EPipeWire), `{"pipewire":true}`, `{"value":{"pipewire":true},"magic":3236757504}`},
{"pulse", hst.NewEnablements(hst.EPulse), `{"pulse":true}`, `{"value":{"pulse":true},"magic":3236757504}`},
{"all", hst.NewEnablements(hst.EM - 1), `{"wayland":true,"x11":true,"dbus":true,"pipewire":true,"pulse":true}`, `{"value":{"wayland":true,"x11":true,"dbus":true,"pipewire":true,"pulse":true},"magic":3236757504}`},
{"zero", new(hst.Enablements(0)), `{}`, `{"value":{},"magic":3236757504}`},
{"wayland", new(hst.EWayland), `{"wayland":true}`, `{"value":{"wayland":true},"magic":3236757504}`},
{"x11", new(hst.EX11), `{"x11":true}`, `{"value":{"x11":true},"magic":3236757504}`},
{"dbus", new(hst.EDBus), `{"dbus":true}`, `{"value":{"dbus":true},"magic":3236757504}`},
{"pipewire", new(hst.EPipeWire), `{"pipewire":true}`, `{"value":{"pipewire":true},"magic":3236757504}`},
{"pulse", new(hst.EPulse), `{"pulse":true}`, `{"value":{"pulse":true},"magic":3236757504}`},
{"all", new(hst.EM - 1), `{"wayland":true,"x11":true,"dbus":true,"pipewire":true,"pulse":true}`, `{"value":{"wayland":true,"x11":true,"dbus":true,"pipewire":true,"pulse":true},"magic":3236757504}`},
}
for _, tc := range testCases {
@@ -137,7 +137,7 @@ func TestEnablements(t *testing.T) {
})
t.Run("val", func(t *testing.T) {
if got := hst.NewEnablements(hst.EWayland | hst.EPulse).Unwrap(); got != hst.EWayland|hst.EPulse {
if got := new(hst.EWayland | hst.EPulse).Unwrap(); got != hst.EWayland|hst.EPulse {
t.Errorf("Unwrap: %v", got)
}
})
@@ -146,9 +146,6 @@ func TestEnablements(t *testing.T) {
t.Run("passthrough", func(t *testing.T) {
t.Parallel()
if _, err := (*hst.Enablements)(nil).MarshalJSON(); !errors.Is(err, syscall.EINVAL) {
t.Errorf("MarshalJSON: error = %v", err)
}
if err := (*hst.Enablements)(nil).UnmarshalJSON(nil); !errors.Is(err, syscall.EINVAL) {
t.Errorf("UnmarshalJSON: error = %v", err)
}

View File

@@ -72,7 +72,7 @@ func Template() *Config {
return &Config{
ID: "org.chromium.Chromium",
Enablements: NewEnablements(EWayland | EDBus | EPipeWire),
Enablements: new(EWayland | EDBus | EPipeWire),
SessionBus: &BusConfig{
See: nil,

View File

@@ -1,4 +1,4 @@
package container
package landlock
import (
"strings"
@@ -14,11 +14,11 @@ const (
LANDLOCK_CREATE_RULESET_VERSION = 1 << iota
)
// LandlockAccessFS is bitmask of handled filesystem actions.
type LandlockAccessFS uint64
// AccessFS is bitmask of handled filesystem actions.
type AccessFS uint64
const (
LANDLOCK_ACCESS_FS_EXECUTE LandlockAccessFS = 1 << iota
LANDLOCK_ACCESS_FS_EXECUTE AccessFS = 1 << iota
LANDLOCK_ACCESS_FS_WRITE_FILE
LANDLOCK_ACCESS_FS_READ_FILE
LANDLOCK_ACCESS_FS_READ_DIR
@@ -38,8 +38,8 @@ const (
_LANDLOCK_ACCESS_FS_DELIM
)
// String returns a space-separated string of [LandlockAccessFS] flags.
func (f LandlockAccessFS) String() string {
// String returns a space-separated string of [AccessFS] flags.
func (f AccessFS) String() string {
switch f {
case LANDLOCK_ACCESS_FS_EXECUTE:
return "execute"
@@ -90,8 +90,8 @@ func (f LandlockAccessFS) String() string {
return "fs_ioctl_dev"
default:
var c []LandlockAccessFS
for i := LandlockAccessFS(1); i < _LANDLOCK_ACCESS_FS_DELIM; i <<= 1 {
var c []AccessFS
for i := AccessFS(1); i < _LANDLOCK_ACCESS_FS_DELIM; i <<= 1 {
if f&i != 0 {
c = append(c, i)
}
@@ -107,18 +107,18 @@ func (f LandlockAccessFS) String() string {
}
}
// LandlockAccessNet is bitmask of handled network actions.
type LandlockAccessNet uint64
// AccessNet is bitmask of handled network actions.
type AccessNet uint64
const (
LANDLOCK_ACCESS_NET_BIND_TCP LandlockAccessNet = 1 << iota
LANDLOCK_ACCESS_NET_BIND_TCP AccessNet = 1 << iota
LANDLOCK_ACCESS_NET_CONNECT_TCP
_LANDLOCK_ACCESS_NET_DELIM
)
// String returns a space-separated string of [LandlockAccessNet] flags.
func (f LandlockAccessNet) String() string {
// String returns a space-separated string of [AccessNet] flags.
func (f AccessNet) String() string {
switch f {
case LANDLOCK_ACCESS_NET_BIND_TCP:
return "bind_tcp"
@@ -127,8 +127,8 @@ func (f LandlockAccessNet) String() string {
return "connect_tcp"
default:
var c []LandlockAccessNet
for i := LandlockAccessNet(1); i < _LANDLOCK_ACCESS_NET_DELIM; i <<= 1 {
var c []AccessNet
for i := AccessNet(1); i < _LANDLOCK_ACCESS_NET_DELIM; i <<= 1 {
if f&i != 0 {
c = append(c, i)
}
@@ -144,18 +144,18 @@ func (f LandlockAccessNet) String() string {
}
}
// LandlockScope is bitmask of scopes restricting a Landlock domain from accessing outside resources.
type LandlockScope uint64
// Scope is bitmask of scopes restricting a Landlock domain from accessing outside resources.
type Scope uint64
const (
LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET LandlockScope = 1 << iota
LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET Scope = 1 << iota
LANDLOCK_SCOPE_SIGNAL
_LANDLOCK_SCOPE_DELIM
)
// String returns a space-separated string of [LandlockScope] flags.
func (f LandlockScope) String() string {
// String returns a space-separated string of [Scope] flags.
func (f Scope) String() string {
switch f {
case LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET:
return "abstract_unix_socket"
@@ -164,8 +164,8 @@ func (f LandlockScope) String() string {
return "signal"
default:
var c []LandlockScope
for i := LandlockScope(1); i < _LANDLOCK_SCOPE_DELIM; i <<= 1 {
var c []Scope
for i := Scope(1); i < _LANDLOCK_SCOPE_DELIM; i <<= 1 {
if f&i != 0 {
c = append(c, i)
}
@@ -184,12 +184,12 @@ func (f LandlockScope) String() string {
// RulesetAttr is equivalent to struct landlock_ruleset_attr.
type RulesetAttr struct {
// Bitmask of handled filesystem actions.
HandledAccessFS LandlockAccessFS
HandledAccessFS AccessFS
// Bitmask of handled network actions.
HandledAccessNet LandlockAccessNet
HandledAccessNet AccessNet
// Bitmask of scopes restricting a Landlock domain from accessing outside
// resources (e.g. IPCs).
Scoped LandlockScope
Scoped Scope
}
// String returns a user-facing description of [RulesetAttr].
@@ -239,13 +239,13 @@ func (rulesetAttr *RulesetAttr) Create(flags uintptr) (fd int, err error) {
return fd, nil
}
// LandlockGetABI returns the ABI version supported by the kernel.
func LandlockGetABI() (int, error) {
// GetABI returns the ABI version supported by the kernel.
func GetABI() (int, error) {
return (*RulesetAttr)(nil).Create(LANDLOCK_CREATE_RULESET_VERSION)
}
// LandlockRestrictSelf applies a loaded ruleset to the calling thread.
func LandlockRestrictSelf(rulesetFd int, flags uintptr) error {
// RestrictSelf applies a loaded ruleset to the calling thread.
func RestrictSelf(rulesetFd int, flags uintptr) error {
r, _, errno := syscall.Syscall(
ext.SYS_LANDLOCK_RESTRICT_SELF,
uintptr(rulesetFd),

View File

@@ -0,0 +1,65 @@
package landlock_test
import (
"testing"
"unsafe"
"hakurei.app/internal/landlock"
)
func TestLandlockString(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
rulesetAttr *landlock.RulesetAttr
want string
}{
{"nil", nil, "NULL"},
{"zero", new(landlock.RulesetAttr), "0"},
{"some", &landlock.RulesetAttr{Scoped: landlock.LANDLOCK_SCOPE_SIGNAL}, "scoped: signal"},
{"set", &landlock.RulesetAttr{
HandledAccessFS: landlock.LANDLOCK_ACCESS_FS_MAKE_SYM | landlock.LANDLOCK_ACCESS_FS_IOCTL_DEV | landlock.LANDLOCK_ACCESS_FS_WRITE_FILE,
HandledAccessNet: landlock.LANDLOCK_ACCESS_NET_BIND_TCP,
Scoped: landlock.LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET | landlock.LANDLOCK_SCOPE_SIGNAL,
}, "fs: write_file make_sym fs_ioctl_dev, net: bind_tcp, scoped: abstract_unix_socket signal"},
{"all", &landlock.RulesetAttr{
HandledAccessFS: landlock.LANDLOCK_ACCESS_FS_EXECUTE |
landlock.LANDLOCK_ACCESS_FS_WRITE_FILE |
landlock.LANDLOCK_ACCESS_FS_READ_FILE |
landlock.LANDLOCK_ACCESS_FS_READ_DIR |
landlock.LANDLOCK_ACCESS_FS_REMOVE_DIR |
landlock.LANDLOCK_ACCESS_FS_REMOVE_FILE |
landlock.LANDLOCK_ACCESS_FS_MAKE_CHAR |
landlock.LANDLOCK_ACCESS_FS_MAKE_DIR |
landlock.LANDLOCK_ACCESS_FS_MAKE_REG |
landlock.LANDLOCK_ACCESS_FS_MAKE_SOCK |
landlock.LANDLOCK_ACCESS_FS_MAKE_FIFO |
landlock.LANDLOCK_ACCESS_FS_MAKE_BLOCK |
landlock.LANDLOCK_ACCESS_FS_MAKE_SYM |
landlock.LANDLOCK_ACCESS_FS_REFER |
landlock.LANDLOCK_ACCESS_FS_TRUNCATE |
landlock.LANDLOCK_ACCESS_FS_IOCTL_DEV,
HandledAccessNet: landlock.LANDLOCK_ACCESS_NET_BIND_TCP |
landlock.LANDLOCK_ACCESS_NET_CONNECT_TCP,
Scoped: landlock.LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET |
landlock.LANDLOCK_SCOPE_SIGNAL,
}, "fs: execute write_file read_file read_dir remove_dir remove_file make_char make_dir make_reg make_sock make_fifo make_block make_sym fs_refer fs_truncate fs_ioctl_dev, net: bind_tcp connect_tcp, scoped: abstract_unix_socket signal"},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
if got := tc.rulesetAttr.String(); got != tc.want {
t.Errorf("String: %s, want %s", got, tc.want)
}
})
}
}
func TestLandlockAttrSize(t *testing.T) {
t.Parallel()
want := 24
if got := unsafe.Sizeof(landlock.RulesetAttr{}); got != uintptr(want) {
t.Errorf("Sizeof: %d, want %d", got, want)
}
}

View File

@@ -32,7 +32,14 @@ type outcome struct {
syscallDispatcher
}
func (k *outcome) finalise(ctx context.Context, msg message.Msg, id *hst.ID, config *hst.Config) error {
// finalise prepares an outcome for main.
func (k *outcome) finalise(
ctx context.Context,
msg message.Msg,
id *hst.ID,
config *hst.Config,
flags int,
) error {
if ctx == nil || id == nil {
// unreachable
panic("invalid call to finalise")
@@ -43,7 +50,7 @@ func (k *outcome) finalise(ctx context.Context, msg message.Msg, id *hst.ID, con
}
k.ctx = ctx
if err := config.Validate(); err != nil {
if err := config.Validate(flags); err != nil {
return err
}

View File

@@ -194,7 +194,7 @@ type outcomeStateSys struct {
// Copied from [hst.Config]. Safe for read by outcomeOp.toSystem.
appId string
// Copied from [hst.Config]. Safe for read by outcomeOp.toSystem.
et hst.Enablement
et hst.Enablements
// Copied from [hst.Config]. Safe for read by spWaylandOp.toSystem only.
directWayland bool

View File

@@ -297,12 +297,12 @@ func (k *outcome) main(msg message.Msg, identifierFd int) {
// accumulate enablements of remaining instances
var (
// alive enablement bits
rt hst.Enablement
rt hst.Enablements
// alive instance count
n int
)
for eh := range entries {
var et hst.Enablement
var et hst.Enablements
if et, err = eh.Load(nil); err != nil {
perror(err, "read state header of instance "+eh.ID.String())
} else {

View File

@@ -18,7 +18,13 @@ import (
func IsPollDescriptor(fd uintptr) bool
// Main runs an app according to [hst.Config] and terminates. Main does not return.
func Main(ctx context.Context, msg message.Msg, config *hst.Config, fd int) {
func Main(
ctx context.Context,
msg message.Msg,
config *hst.Config,
flags int,
fd int,
) {
// avoids runtime internals or standard streams
if fd >= 0 {
if IsPollDescriptor(uintptr(fd)) || fd < 3 {
@@ -34,7 +40,7 @@ func Main(ctx context.Context, msg message.Msg, config *hst.Config, fd int) {
k := outcome{syscallDispatcher: direct{msg}}
finaliseTime := time.Now()
if err := k.finalise(ctx, msg, &id, config); err != nil {
if err := k.finalise(ctx, msg, &id, config, flags); err != nil {
printMessageError(msg.GetLogger().Fatalln, "cannot seal app:", err)
panic("unreachable")
}

View File

@@ -288,7 +288,7 @@ func TestOutcomeRun(t *testing.T) {
},
Filter: true,
},
Enablements: hst.NewEnablements(hst.EWayland | hst.EDBus | hst.EPipeWire | hst.EPulse),
Enablements: new(hst.EWayland | hst.EDBus | hst.EPipeWire | hst.EPulse),
Container: &hst.ContainerConfig{
Filesystem: []hst.FilesystemConfigJSON{
@@ -427,7 +427,7 @@ func TestOutcomeRun(t *testing.T) {
DirectPipeWire: true,
ID: "org.chromium.Chromium",
Enablements: hst.NewEnablements(hst.EWayland | hst.EDBus | hst.EPipeWire | hst.EPulse),
Enablements: new(hst.EWayland | hst.EDBus | hst.EPipeWire | hst.EPulse),
Container: &hst.ContainerConfig{
Env: nil,
Filesystem: []hst.FilesystemConfigJSON{

View File

@@ -21,7 +21,7 @@ func TestSpPulseOp(t *testing.T) {
newConfig := func() *hst.Config {
config := hst.Template()
config.DirectPulse = true
config.Enablements = hst.NewEnablements(hst.EPulse)
config.Enablements = new(hst.EPulse)
return config
}

View File

@@ -27,6 +27,11 @@ import (
// AbsWork is the container pathname [TContext.GetWorkDir] is mounted on.
var AbsWork = fhs.AbsRoot.Append("work/")
// EnvJobs is the name of the environment variable holding a decimal
// representation of the preferred job count. Its value must not affect cure
// outcome.
const EnvJobs = "CURE_JOBS"
// ExecPath is a slice of [Artifact] and the [check.Absolute] pathname to make
// it available at under in the container.
type ExecPath struct {
@@ -397,7 +402,7 @@ const SeccompPresets = std.PresetStrict &
func (a *execArtifact) makeContainer(
ctx context.Context,
msg message.Msg,
flags int,
flags, jobs int,
hostNet bool,
temp, work *check.Absolute,
getArtifact GetArtifactFunc,
@@ -432,8 +437,8 @@ func (a *execArtifact) makeContainer(
z.Hostname = "cure-net"
}
z.Uid, z.Gid = (1<<10)-1, (1<<10)-1
z.Dir, z.Env, z.Path, z.Args = a.dir, a.env, a.path, a.args
z.Dir, z.Path, z.Args = a.dir, a.path, a.args
z.Env = slices.Concat(a.env, []string{EnvJobs + "=" + strconv.Itoa(jobs)})
z.Grow(len(a.paths) + 4)
for i, b := range a.paths {
@@ -563,6 +568,7 @@ func (c *Cache) EnterExec(
z, err = e.makeContainer(
ctx, c.msg,
c.flags,
c.jobs,
hostNet,
temp, work,
func(a Artifact) (*check.Absolute, unique.Handle[Checksum]) {
@@ -602,7 +608,7 @@ func (a *execArtifact) cure(f *FContext, hostNet bool) (err error) {
msg := f.GetMessage()
var z *container.Container
if z, err = a.makeContainer(
ctx, msg, f.cache.flags, hostNet,
ctx, msg, f.cache.flags, f.GetJobs(), hostNet,
f.GetTempDir(), f.GetWorkDir(),
f.GetArtifact,
f.cache.Ident,

View File

@@ -188,6 +188,10 @@ func (c *common) Unwrap() context.Context { return c.cache.ctx }
// GetMessage returns [message.Msg] held by the underlying [Cache].
func (c *common) GetMessage() message.Msg { return c.cache.msg }
// GetJobs returns the preferred number of jobs to run, when applicable. Its
// value must not affect cure outcome.
func (c *common) GetJobs() int { return c.cache.jobs }
// GetWorkDir returns a pathname to a directory which [Artifact] is expected to
// write its output to. This is not the final resting place of the [Artifact]
// and this pathname should not be directly referred to in the final contents.
@@ -552,6 +556,8 @@ type Cache struct {
base *check.Absolute
// Immutable cure options set by [Open].
flags int
// Immutable job count, when applicable.
jobs int
// Artifact to [unique.Handle] of identifier cache.
artifact sync.Map
@@ -1818,7 +1824,7 @@ func (c *Cache) Close() {
// caller-supplied value, however direct calls to [Cache.Cure] is not subject
// to this limitation.
//
// A cures value of 0 or lower is equivalent to the value returned by
// A cures or jobs value of 0 or lower is equivalent to the value returned by
// [runtime.NumCPU].
//
// A successful call to Open guarantees exclusive access to the on-filesystem
@@ -1828,10 +1834,10 @@ func (c *Cache) Close() {
func Open(
ctx context.Context,
msg message.Msg,
flags, cures int,
flags, cures, jobs int,
base *check.Absolute,
) (*Cache, error) {
return open(ctx, msg, flags, cures, base, true)
return open(ctx, msg, flags, cures, jobs, base, true)
}
// open implements Open but allows omitting the [lockedfile] lock when called
@@ -1839,13 +1845,16 @@ func Open(
func open(
ctx context.Context,
msg message.Msg,
flags, cures int,
flags, cures, jobs int,
base *check.Absolute,
lock bool,
) (*Cache, error) {
if cures < 1 {
cures = runtime.NumCPU()
}
if jobs < 1 {
jobs = runtime.NumCPU()
}
for _, name := range []string{
dirIdentifier,
@@ -1862,6 +1871,7 @@ func open(
c := Cache{
cures: make(chan struct{}, cures),
flags: flags,
jobs: jobs,
msg: msg,
base: base,

View File

@@ -25,6 +25,7 @@ import (
"hakurei.app/container"
"hakurei.app/fhs"
"hakurei.app/internal/info"
"hakurei.app/internal/landlock"
"hakurei.app/internal/pkg"
"hakurei.app/internal/stub"
"hakurei.app/message"
@@ -34,7 +35,7 @@ import (
func unsafeOpen(
ctx context.Context,
msg message.Msg,
flags, cures int,
flags, cures, jobs int,
base *check.Absolute,
lock bool,
) (*pkg.Cache, error)
@@ -229,7 +230,7 @@ func TestIdent(t *testing.T) {
var cache *pkg.Cache
if a, err := check.NewAbs(t.TempDir()); err != nil {
t.Fatal(err)
} else if cache, err = pkg.Open(t.Context(), msg, 0, 0, a); err != nil {
} else if cache, err = pkg.Open(t.Context(), msg, 0, 0, 0, a); err != nil {
t.Fatal(err)
}
t.Cleanup(cache.Close)
@@ -293,7 +294,7 @@ func checkWithCache(t *testing.T, testCases []cacheTestCase) {
flags := tc.flags
if info.CanDegrade {
if _, err := container.LandlockGetABI(); err != nil {
if _, err := landlock.GetABI(); err != nil {
if !errors.Is(err, syscall.ENOSYS) {
t.Fatalf("LandlockGetABI: error = %v", err)
}
@@ -303,7 +304,7 @@ func checkWithCache(t *testing.T, testCases []cacheTestCase) {
}
var scrubFunc func() error // scrub after hashing
if c, err := pkg.Open(t.Context(), msg, flags, 1<<4, base); err != nil {
if c, err := pkg.Open(t.Context(), msg, flags, 1<<4, 0, base); err != nil {
t.Fatalf("Open: error = %v", err)
} else {
t.Cleanup(c.Close)
@@ -605,7 +606,7 @@ func TestCache(t *testing.T) {
if c0, err := unsafeOpen(
t.Context(),
message.New(nil),
0, 0, base, false,
0, 0, 0, base, false,
); err != nil {
t.Fatalf("open: error = %v", err)
} else {
@@ -1262,7 +1263,7 @@ func TestNew(t *testing.T) {
if _, err := pkg.Open(
t.Context(),
message.New(nil),
0, 0, check.MustAbs(container.Nonexistent),
0, 0, 0, check.MustAbs(container.Nonexistent),
); !reflect.DeepEqual(err, wantErr) {
t.Errorf("Open: error = %#v, want %#v", err, wantErr)
}
@@ -1290,7 +1291,7 @@ func TestNew(t *testing.T) {
if _, err := pkg.Open(
t.Context(),
message.New(nil),
0, 0, tempDir.Append("cache"),
0, 0, 0, tempDir.Append("cache"),
); !reflect.DeepEqual(err, wantErr) {
t.Errorf("Open: error = %#v, want %#v", err, wantErr)
}

View File

@@ -43,8 +43,7 @@ var _ fmt.Stringer = new(tarArtifactNamed)
func (a *tarArtifactNamed) String() string { return a.name + "-unpack" }
// NewTar returns a new [Artifact] backed by the supplied [Artifact] and
// compression method. The source [Artifact] must be compatible with
// [TContext.Open].
// compression method. The source [Artifact] must be a [FileArtifact].
func NewTar(a Artifact, compression uint32) Artifact {
ta := tarArtifact{a, compression}
if s, ok := a.(fmt.Stringer); ok {

View File

@@ -9,7 +9,9 @@ import (
"os"
"path/filepath"
"reflect"
"runtime"
"slices"
"strconv"
"strings"
"hakurei.app/check"
@@ -21,6 +23,10 @@ func main() {
log.SetFlags(0)
log.SetPrefix("testtool: ")
environ := slices.DeleteFunc(slices.Clone(os.Environ()), func(s string) bool {
return s == "CURE_JOBS="+strconv.Itoa(runtime.NumCPU())
})
var hostNet, layers, promote bool
if len(os.Args) == 2 && os.Args[0] == "testtool" {
switch os.Args[1] {
@@ -48,15 +54,15 @@ func main() {
var overlayRoot bool
wantEnv := []string{"HAKUREI_TEST=1"}
if len(os.Environ()) == 2 {
if len(environ) == 2 {
overlayRoot = true
if !layers && !promote {
log.SetPrefix("testtool(overlay root): ")
}
wantEnv = []string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"}
}
if !slices.Equal(wantEnv, os.Environ()) {
log.Fatalf("Environ: %q, want %q", os.Environ(), wantEnv)
if !slices.Equal(wantEnv, environ) {
log.Fatalf("Environ: %q, want %q", environ, wantEnv)
}
var overlayWork bool

View File

@@ -7,10 +7,10 @@ func (t Toolchain) newAttr() (pkg.Artifact, string) {
version = "2.5.2"
checksum = "YWEphrz6vg1sUMmHHVr1CRo53pFXRhq_pjN-AlG8UgwZK1y6m7zuDhxqJhD0SV0l"
)
return t.NewPackage("attr", version, pkg.NewHTTPGetTar(
nil, "https://download.savannah.nongnu.org/releases/attr/"+
return t.NewPackage("attr", version, newTar(
"https://download.savannah.nongnu.org/releases/attr/"+
"attr-"+version+".tar.gz",
mustDecode(checksum),
checksum,
pkg.TarGzip,
), &PackageAttr{
Patches: []KV{
@@ -81,10 +81,10 @@ func (t Toolchain) newACL() (pkg.Artifact, string) {
version = "2.3.2"
checksum = "-fY5nwH4K8ZHBCRXrzLdguPkqjKI6WIiGu4dBtrZ1o0t6AIU73w8wwJz_UyjIS0P"
)
return t.NewPackage("acl", version, pkg.NewHTTPGetTar(
nil, "https://download.savannah.nongnu.org/releases/acl/"+
return t.NewPackage("acl", version, newTar(
"https://download.savannah.nongnu.org/releases/acl/"+
"acl-"+version+".tar.gz",
mustDecode(checksum),
checksum,
pkg.TarGzip,
), nil, &MakeHelper{
// makes assumptions about uid_map/gid_map

View File

@@ -16,9 +16,9 @@ import (
type PArtifact int
const (
LLVMCompilerRT PArtifact = iota
CompilerRT PArtifact = iota
LLVMRuntimes
LLVMClang
Clang
// EarlyInit is the Rosa OS init program.
EarlyInit
@@ -64,6 +64,7 @@ const (
GenInitCPIO
Gettext
Git
Glslang
GnuTLS
Go
Gperf
@@ -76,13 +77,17 @@ const (
LibXau
Libbsd
Libcap
Libclc
Libdrm
Libev
Libexpat
Libffi
Libgd
Libglvnd
Libiconv
Libmd
Libmnl
Libpciaccess
Libnftnl
Libpsl
Libseccomp
@@ -119,15 +124,18 @@ const (
PerlTermReadKey
PerlTextCharWidth
PerlTextWrapI18N
PerlUnicodeGCString
PerlUnicodeLineBreak
PerlYAMLTiny
PkgConfig
Procps
Python
PythonIniConfig
PythonMako
PythonMarkupSafe
PythonPackaging
PythonPluggy
PythonPyTest
PythonPyYAML
PythonPygments
QEMU
Rdfind
@@ -135,6 +143,8 @@ const (
Rsync
Sed
Setuptools
SPIRVHeaders
SPIRVTools
SquashfsTools
Strace
TamaGo
@@ -148,15 +158,17 @@ const (
WaylandProtocols
XCB
XCBProto
Xproto
XDGDBusProxy
XZ
Xproto
Zlib
Zstd
// PresetUnexportedStart is the first unexported preset.
PresetUnexportedStart
buildcatrust = iota - 1
llvmSource = iota - 1
buildcatrust
utilMacros
// Musl is a standalone libc that does not depend on the toolchain.

View File

@@ -7,10 +7,10 @@ func (t Toolchain) newArgpStandalone() (pkg.Artifact, string) {
version = "1.3"
checksum = "vtW0VyO2pJ-hPyYmDI2zwSLS8QL0sPAUKC1t3zNYbwN2TmsaE-fADhaVtNd3eNFl"
)
return t.NewPackage("argp-standalone", version, pkg.NewHTTPGetTar(
nil, "http://www.lysator.liu.se/~nisse/misc/"+
return t.NewPackage("argp-standalone", version, newTar(
"http://www.lysator.liu.se/~nisse/misc/"+
"argp-standalone-"+version+".tar.gz",
mustDecode(checksum),
checksum,
pkg.TarGzip,
), &PackageAttr{
Env: []string{

View File

@@ -7,9 +7,9 @@ func (t Toolchain) newBzip2() (pkg.Artifact, string) {
version = "1.0.8"
checksum = "cTLykcco7boom-s05H1JVsQi1AtChYL84nXkg_92Dm1Xt94Ob_qlMg_-NSguIK-c"
)
return t.NewPackage("bzip2", version, pkg.NewHTTPGetTar(
nil, "https://sourceware.org/pub/bzip2/bzip2-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("bzip2", version, newTar(
"https://sourceware.org/pub/bzip2/bzip2-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), &PackageAttr{
Writable: true,

View File

@@ -13,10 +13,11 @@ func (t Toolchain) newCMake() (pkg.Artifact, string) {
version = "4.3.1"
checksum = "RHpzZiM1kJ5bwLjo9CpXSeHJJg3hTtV9QxBYpQoYwKFtRh5YhGWpShrqZCSOzQN6"
)
return t.NewPackage("cmake", version, pkg.NewHTTPGetTar(
nil, "https://github.com/Kitware/CMake/releases/download/"+
"v"+version+"/cmake-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("cmake", version, newFromGitHubRelease(
"Kitware/CMake",
"v"+version,
"cmake-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), &PackageAttr{
// test suite expects writable source tree
@@ -90,7 +91,7 @@ index 2ead810437..f85cbb8b1c 100644
ConfigureName: "/usr/src/cmake/bootstrap",
Configure: []KV{
{"prefix", "/system"},
{"parallel", `"$(nproc)"`},
{"parallel", jobsE},
{"--"},
{"-DCMAKE_USE_OPENSSL", "OFF"},
{"-DCMake_TEST_NO_NETWORK", "ON"},
@@ -118,9 +119,6 @@ func init() {
// CMakeHelper is the [CMake] build system helper.
type CMakeHelper struct {
// Joined with name with a dash if non-empty.
Variant string
// Path elements joined with source.
Append []string
@@ -135,14 +133,6 @@ type CMakeHelper struct {
var _ Helper = new(CMakeHelper)
// name returns its arguments and an optional variant string joined with '-'.
func (attr *CMakeHelper) name(name, version string) string {
if attr != nil && attr.Variant != "" {
name += "-" + attr.Variant
}
return name + "-" + version
}
// extra returns a hardcoded slice of [CMake] and [Ninja].
func (attr *CMakeHelper) extra(int) P {
if attr != nil && attr.Make {
@@ -180,10 +170,8 @@ func (attr *CMakeHelper) script(name string) string {
}
generate := "Ninja"
jobs := ""
if attr.Make {
generate = "'Unix Makefiles'"
jobs += ` "--parallel=$(nproc)"`
}
return `
@@ -201,7 +189,7 @@ cmake -G ` + generate + ` \
}), " \\\n\t") + ` \
-DCMAKE_INSTALL_PREFIX=/system \
'/usr/src/` + name + `/` + filepath.Join(attr.Append...) + `'
cmake --build .` + jobs + `
cmake --build . --parallel=` + jobsE + `
cmake --install . --prefix=/work/system
` + attr.Script
}

View File

@@ -7,10 +7,10 @@ func (t Toolchain) newConnman() (pkg.Artifact, string) {
version = "2.0"
checksum = "MhVTdJOhndnZn2SWd8URKo_Pj7Zvc14tntEbrVOf9L3yVWJvpb3v3Q6104tWJgtW"
)
return t.NewPackage("connman", version, pkg.NewHTTPGetTar(
nil, "https://git.kernel.org/pub/scm/network/connman/connman.git/"+
return t.NewPackage("connman", version, newTar(
"https://git.kernel.org/pub/scm/network/connman/connman.git/"+
"snapshot/connman-"+version+".tar.gz",
mustDecode(checksum),
checksum,
pkg.TarGzip,
), &PackageAttr{
Patches: []KV{

View File

@@ -7,15 +7,15 @@ func (t Toolchain) newCurl() (pkg.Artifact, string) {
version = "8.19.0"
checksum = "YHuVLVVp8q_Y7-JWpID5ReNjq2Zk6t7ArHB6ngQXilp_R5l3cubdxu3UKo-xDByv"
)
return t.NewPackage("curl", version, pkg.NewHTTPGetTar(
nil, "https://curl.se/download/curl-"+version+".tar.bz2",
mustDecode(checksum),
return t.NewPackage("curl", version, newTar(
"https://curl.se/download/curl-"+version+".tar.bz2",
checksum,
pkg.TarBzip2,
), &PackageAttr{
// remove broken test
Writable: true,
ScriptEarly: `
chmod +w tests/data && rm tests/data/test459
chmod +w tests/data && rm -f tests/data/test459
`,
}, &MakeHelper{
Configure: []KV{
@@ -25,7 +25,7 @@ chmod +w tests/data && rm tests/data/test459
{"disable-smb"},
},
Check: []string{
`TFLAGS="-j$(expr "$(nproc)" '*' 2)"`,
"TFLAGS=" + jobsLFlagE,
"test-nonflaky",
},
},

View File

@@ -7,11 +7,11 @@ func (t Toolchain) newDBus() (pkg.Artifact, string) {
version = "1.16.2"
checksum = "INwOuNdrDG7XW5ilW_vn8JSxEa444rRNc5ho97i84I1CNF09OmcFcV-gzbF4uCyg"
)
return t.NewPackage("dbus", version, pkg.NewHTTPGetTar(
nil, "https://gitlab.freedesktop.org/dbus/dbus/-/archive/"+
"dbus-"+version+"/dbus-dbus-"+version+".tar.bz2",
mustDecode(checksum),
pkg.TarBzip2,
return t.NewPackage("dbus", version, newFromGitLab(
"gitlab.freedesktop.org",
"dbus/dbus",
"dbus-"+version,
checksum,
), &PackageAttr{
// OSError: [Errno 30] Read-only file system: '/usr/src/dbus/subprojects/packagecache'
Writable: true,
@@ -44,3 +44,38 @@ func init() {
ID: 5356,
}
}
func (t Toolchain) newXDGDBusProxy() (pkg.Artifact, string) {
const (
version = "0.1.7"
checksum = "UW5Pe-TP-XAaN-kTbxrkOQ7eYdmlAQlr2pdreLtPT0uwdAz-7rzDP8V_8PWuZBup"
)
return t.NewPackage("xdg-dbus-proxy", version, newFromGitHub(
"flatpak/xdg-dbus-proxy",
version,
checksum,
), nil, &MesonHelper{
Setup: []KV{
{"Dman", "disabled"},
},
},
DBus,
GLib,
), version
}
func init() {
artifactsM[XDGDBusProxy] = Metadata{
f: Toolchain.newXDGDBusProxy,
Name: "xdg-dbus-proxy",
Description: "a filtering proxy for D-Bus connections",
Website: "https://github.com/flatpak/xdg-dbus-proxy",
Dependencies: P{
GLib,
},
ID: 58434,
}
}

View File

@@ -7,10 +7,10 @@ func (t Toolchain) newDTC() (pkg.Artifact, string) {
version = "1.7.2"
checksum = "vUoiRynPyYRexTpS6USweT5p4SVHvvVJs8uqFkkVD-YnFjwf6v3elQ0-Etrh00Dt"
)
return t.NewPackage("dtc", version, pkg.NewHTTPGetTar(
nil, "https://git.kernel.org/pub/scm/utils/dtc/dtc.git/snapshot/"+
return t.NewPackage("dtc", version, newTar(
"https://git.kernel.org/pub/scm/utils/dtc/dtc.git/snapshot/"+
"dtc-v"+version+".tar.gz",
mustDecode(checksum),
checksum,
pkg.TarGzip,
), &PackageAttr{
// works around buggy test:

View File

@@ -7,10 +7,10 @@ func (t Toolchain) newElfutils() (pkg.Artifact, string) {
version = "0.194"
checksum = "Q3XUygUPv9vR1TkWucwUsQ8Kb1_F6gzk-KMPELr3cC_4AcTrprhVPMvN0CKkiYRa"
)
return t.NewPackage("elfutils", version, pkg.NewHTTPGetTar(
nil, "https://sourceware.org/elfutils/ftp/"+
return t.NewPackage("elfutils", version, newTar(
"https://sourceware.org/elfutils/ftp/"+
version+"/elfutils-"+version+".tar.bz2",
mustDecode(checksum),
checksum,
pkg.TarBzip2,
), &PackageAttr{
Env: []string{

View File

@@ -135,10 +135,11 @@ func newIANAEtc() pkg.Artifact {
version = "20251215"
checksum = "kvKz0gW_rGG5QaNK9ZWmWu1IEgYAdmhj_wR7DYrh3axDfIql_clGRHmelP7525NJ"
)
return pkg.NewHTTPGetTar(
nil, "https://github.com/Mic92/iana-etc/releases/download/"+
version+"/iana-etc-"+version+".tar.gz",
mustDecode(checksum),
return newFromGitHubRelease(
"Mic92/iana-etc",
version,
"iana-etc-"+version+".tar.gz",
checksum,
pkg.TarGzip,
)
}

View File

@@ -7,11 +7,11 @@ func (t Toolchain) newFakeroot() (pkg.Artifact, string) {
version = "1.37.2"
checksum = "4ve-eDqVspzQ6VWDhPS0NjW3aSenBJcPAJq_BFT7OOFgUdrQzoTBxZWipDAGWxF8"
)
return t.NewPackage("fakeroot", version, pkg.NewHTTPGetTar(
nil, "https://salsa.debian.org/clint/fakeroot/-/archive/upstream/"+
version+"/fakeroot-upstream-"+version+".tar.bz2",
mustDecode(checksum),
pkg.TarBzip2,
return t.NewPackage("fakeroot", version, newFromGitLab(
"salsa.debian.org",
"clint/fakeroot",
"upstream/"+version,
checksum,
), &PackageAttr{
Patches: []KV{
{"remove-broken-docs", `diff --git a/doc/Makefile.am b/doc/Makefile.am

View File

@@ -9,10 +9,11 @@ func (t Toolchain) newFlex() (pkg.Artifact, string) {
version = "2.6.4"
checksum = "p9POjQU7VhgOf3x5iFro8fjhy0NOanvA7CTeuWS_veSNgCixIJshTrWVkc5XLZkB"
)
return t.NewPackage("flex", version, pkg.NewHTTPGetTar(
nil, "https://github.com/westes/flex/releases/download/"+
"v"+version+"/flex-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("flex", version, newFromGitHubRelease(
"westes/flex",
"v"+version,
"flex-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), nil, (*MakeHelper)(nil),
M4,

View File

@@ -7,10 +7,11 @@ func (t Toolchain) newFuse() (pkg.Artifact, string) {
version = "3.18.2"
checksum = "iL-7b7eUtmlVSf5cSq0dzow3UiqSjBmzV3cI_ENPs1tXcHdktkG45j1V12h-4jZe"
)
return t.NewPackage("fuse", version, pkg.NewHTTPGetTar(
nil, "https://github.com/libfuse/libfuse/releases/download/"+
"fuse-"+version+"/fuse-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("fuse", version, newFromGitHubRelease(
"libfuse/libfuse",
"fuse-"+version,
"fuse-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), nil, &MesonHelper{
Setup: []KV{

View File

@@ -12,10 +12,10 @@ func (t Toolchain) newGit() (pkg.Artifact, string) {
version = "2.53.0"
checksum = "rlqSTeNgSeVKJA7nvzGqddFH8q3eFEPB4qRZft-4zth8wTHnbTbm7J90kp_obHGm"
)
return t.NewPackage("git", version, pkg.NewHTTPGetTar(
nil, "https://www.kernel.org/pub/software/scm/git/"+
return t.NewPackage("git", version, newTar(
"https://www.kernel.org/pub/software/scm/git/"+
"git-"+version+".tar.gz",
mustDecode(checksum),
checksum,
pkg.TarGzip,
), &PackageAttr{
ScriptEarly: `
@@ -58,7 +58,7 @@ disable_test t2200-add-update
"prove",
},
Install: `make \
"-j$(nproc)" \
` + jobsFlagE + ` \
DESTDIR=/work \
NO_INSTALL_HARDLINKS=1 \
install`,
@@ -114,3 +114,8 @@ git \
rm -rf /work/.git
`, resolvconf())
}
// newTagRemote is a helper around NewViaGit for a tag on a git remote.
func (t Toolchain) newTagRemote(url, tag, checksum string) pkg.Artifact {
return t.NewViaGit(url, "refs/tags/"+tag, mustDecode(checksum))
}

130
internal/rosa/glslang.go Normal file
View File

@@ -0,0 +1,130 @@
package rosa
import (
"slices"
"strings"
"hakurei.app/internal/pkg"
)
func (t Toolchain) newSPIRVHeaders() (pkg.Artifact, string) {
const (
version = "1.4.341.0"
checksum = "0PL43-19Iaw4k7_D8J8BvoJ-iLgCVSYZ2ThgDPGfAJwIJFtre7l0cnQtLjcY-JvD"
)
return t.NewPackage("spirv-headers", version, newFromGitHub(
"KhronosGroup/SPIRV-Headers",
"vulkan-sdk-"+version,
checksum,
), nil, &CMakeHelper{
Cache: []KV{
{"CMAKE_BUILD_TYPE", "Release"},
},
}), version
}
func init() {
artifactsM[SPIRVHeaders] = Metadata{
f: Toolchain.newSPIRVHeaders,
Name: "spirv-headers",
Description: "machine-readable files for the SPIR-V Registry",
Website: "https://github.com/KhronosGroup/SPIRV-Headers",
ID: 230542,
// upstream changed version scheme, anitya incapable of filtering them
latest: func(v *Versions) string {
for _, s := range v.Stable {
fields := strings.SplitN(s, ".", 4)
if len(fields) != 4 {
continue
}
if slices.ContainsFunc(fields, func(f string) bool {
return slices.ContainsFunc([]byte(f), func(d byte) bool {
return d < '0' || d > '9'
})
}) {
continue
}
return s
}
return v.Latest
},
}
}
func (t Toolchain) newSPIRVTools() (pkg.Artifact, string) {
const (
version = "2026.1"
checksum = "ZSQPQx8NltCDzQLk4qlaVxyWRWeI_JtsjEpeFt3kezTanl9DTHfLixSUCezMFBjv"
)
return t.NewPackage("spirv-tools", version, newFromGitHub(
"KhronosGroup/SPIRV-Tools",
"v"+version,
checksum,
), nil, &CMakeHelper{
Cache: []KV{
{"CMAKE_BUILD_TYPE", "Release"},
{"SPIRV-Headers_SOURCE_DIR", "/system"},
},
},
Python,
SPIRVHeaders,
), version
}
func init() {
artifactsM[SPIRVTools] = Metadata{
f: Toolchain.newSPIRVTools,
Name: "spirv-tools",
Description: "an API and commands for processing SPIR-V modules",
Website: "https://github.com/KhronosGroup/SPIRV-Tools",
Dependencies: P{
SPIRVHeaders,
},
ID: 14894,
}
}
func (t Toolchain) newGlslang() (pkg.Artifact, string) {
const (
version = "16.2.0"
checksum = "6_UuF9reLRDaVkgO-9IfB3kMwme3lQZM8LL8YsJwPdUFkrjzxJtf2A9X3w9nFxj2"
)
return t.NewPackage("glslang", version, newFromGitHub(
"KhronosGroup/glslang",
version,
checksum,
), &PackageAttr{
// test suite writes to source
Writable: true,
Chmod: true,
}, &CMakeHelper{
Cache: []KV{
{"CMAKE_BUILD_TYPE", "Release"},
{"BUILD_SHARED_LIBS", "ON"},
{"ALLOW_EXTERNAL_SPIRV_TOOLS", "ON"},
},
Script: "ctest",
},
Python,
Bash,
Diffutils,
SPIRVTools,
), version
}
func init() {
artifactsM[Glslang] = Metadata{
f: Toolchain.newGlslang,
Name: "glslang",
Description: "reference front end for GLSL/ESSL",
Website: "https://github.com/KhronosGroup/glslang",
ID: 205796,
}
}

View File

@@ -11,9 +11,9 @@ func (t Toolchain) newM4() (pkg.Artifact, string) {
version = "1.4.21"
checksum = "pPa6YOo722Jw80l1OsH1tnUaklnPFjFT-bxGw5iAVrZTm1P8FQaWao_NXop46-pm"
)
return t.NewPackage("m4", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/m4/m4-"+version+".tar.bz2",
mustDecode(checksum),
return t.NewPackage("m4", version, newTar(
"https://ftpmirror.gnu.org/gnu/m4/m4-"+version+".tar.bz2",
checksum,
pkg.TarBzip2,
), &PackageAttr{
Writable: true,
@@ -43,9 +43,9 @@ func (t Toolchain) newBison() (pkg.Artifact, string) {
version = "3.8.2"
checksum = "BhRM6K7URj1LNOkIDCFDctSErLS-Xo5d9ba9seg10o6ACrgC1uNhED7CQPgIY29Y"
)
return t.NewPackage("bison", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/bison/bison-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("bison", version, newTar(
"https://ftpmirror.gnu.org/gnu/bison/bison-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), nil, (*MakeHelper)(nil),
M4,
@@ -70,9 +70,9 @@ func (t Toolchain) newSed() (pkg.Artifact, string) {
version = "4.9"
checksum = "pe7HWH4PHNYrazOTlUoE1fXmhn2GOPFN_xE62i0llOr3kYGrH1g2_orDz0UtZ9Nt"
)
return t.NewPackage("sed", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/sed/sed-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("sed", version, newTar(
"https://ftpmirror.gnu.org/gnu/sed/sed-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), nil, (*MakeHelper)(nil),
Diffutils,
@@ -95,15 +95,15 @@ func (t Toolchain) newAutoconf() (pkg.Artifact, string) {
version = "2.73"
checksum = "yGabDTeOfaCUB0JX-h3REYLYzMzvpDwFmFFzHNR7QilChCUNE4hR6q7nma4viDYg"
)
return t.NewPackage("autoconf", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/autoconf/autoconf-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("autoconf", version, newTar(
"https://ftpmirror.gnu.org/gnu/autoconf/autoconf-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), &PackageAttr{
Flag: TExclusive,
}, &MakeHelper{
Check: []string{
`TESTSUITEFLAGS="-j$(nproc)"`,
"TESTSUITEFLAGS=" + jobsFlagE,
"check",
},
},
@@ -135,9 +135,9 @@ func (t Toolchain) newAutomake() (pkg.Artifact, string) {
version = "1.18.1"
checksum = "FjvLG_GdQP7cThTZJLDMxYpRcKdpAVG-YDs1Fj1yaHlSdh_Kx6nRGN14E0r_BjcG"
)
return t.NewPackage("automake", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/automake/automake-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("automake", version, newTar(
"https://ftpmirror.gnu.org/gnu/automake/automake-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), &PackageAttr{
Writable: true,
@@ -179,13 +179,13 @@ func (t Toolchain) newLibtool() (pkg.Artifact, string) {
version = "2.5.4"
checksum = "pa6LSrQggh8mSJHQfwGjysAApmZlGJt8wif2cCLzqAAa2jpsTY0jZ-6stS3BWZ2Q"
)
return t.NewPackage("libtool", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/libtool/libtool-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("libtool", version, newTar(
"https://ftpmirror.gnu.org/gnu/libtool/libtool-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), nil, &MakeHelper{
Check: []string{
`TESTSUITEFLAGS="-j$(nproc)"`,
"TESTSUITEFLAGS=" + jobsFlagE,
"check",
},
},
@@ -210,9 +210,9 @@ func (t Toolchain) newGzip() (pkg.Artifact, string) {
version = "1.14"
checksum = "NWhjUavnNfTDFkZJyAUonL9aCOak8GVajWX2OMlzpFnuI0ErpBFyj88mz2xSjz0q"
)
return t.NewPackage("gzip", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/gzip/gzip-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("gzip", version, newTar(
"https://ftpmirror.gnu.org/gnu/gzip/gzip-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), nil, &MakeHelper{
// dependency loop
@@ -236,9 +236,9 @@ func (t Toolchain) newGettext() (pkg.Artifact, string) {
version = "1.0"
checksum = "3MasKeEdPeFEgWgzsBKk7JqWqql1wEMbgPmzAfs-mluyokoW0N8oQVxPQoOnSdgC"
)
return t.NewPackage("gettext", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/gettext/gettext-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("gettext", version, newTar(
"https://ftpmirror.gnu.org/gnu/gettext/gettext-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), &PackageAttr{
Writable: true,
@@ -282,9 +282,9 @@ func (t Toolchain) newDiffutils() (pkg.Artifact, string) {
version = "3.12"
checksum = "9J5VAq5oA7eqwzS1Yvw-l3G5o-TccUrNQR3PvyB_lgdryOFAfxtvQfKfhdpquE44"
)
return t.NewPackage("diffutils", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/diffutils/diffutils-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("diffutils", version, newTar(
"https://ftpmirror.gnu.org/gnu/diffutils/diffutils-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), &PackageAttr{
Writable: true,
@@ -315,9 +315,9 @@ func (t Toolchain) newPatch() (pkg.Artifact, string) {
version = "2.8"
checksum = "MA0BQc662i8QYBD-DdGgyyfTwaeALZ1K0yusV9rAmNiIsQdX-69YC4t9JEGXZkeR"
)
return t.NewPackage("patch", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/patch/patch-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("patch", version, newTar(
"https://ftpmirror.gnu.org/gnu/patch/patch-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), &PackageAttr{
Writable: true,
@@ -347,9 +347,9 @@ func (t Toolchain) newBash() (pkg.Artifact, string) {
version = "5.3"
checksum = "4LQ_GRoB_ko-Ih8QPf_xRKA02xAm_TOxQgcJLmFDT6udUPxTAWrsj-ZNeuTusyDq"
)
return t.NewPackage("bash", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/bash/bash-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("bash", version, newTar(
"https://ftpmirror.gnu.org/gnu/bash/bash-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), &PackageAttr{
Flag: TEarly,
@@ -377,9 +377,9 @@ func (t Toolchain) newCoreutils() (pkg.Artifact, string) {
version = "9.10"
checksum = "o-B9wssRnZySzJUI1ZJAgw-bZtj1RC67R9po2AcM2OjjS8FQIl16IRHpC6IwO30i"
)
return t.NewPackage("coreutils", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/coreutils/coreutils-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("coreutils", version, newTar(
"https://ftpmirror.gnu.org/gnu/coreutils/coreutils-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), &PackageAttr{
Writable: true,
@@ -516,9 +516,9 @@ func (t Toolchain) newTexinfo() (pkg.Artifact, string) {
version = "7.3"
checksum = "RRmC8Xwdof7JuZJeWGAQ_GeASIHAuJFQMbNONXBz5InooKIQGmqmWRjGNGEr5n4-"
)
return t.NewPackage("texinfo", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/texinfo/texinfo-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("texinfo", version, newTar(
"https://ftpmirror.gnu.org/gnu/texinfo/texinfo-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), nil, &MakeHelper{
// nonstandard glibc extension
@@ -549,9 +549,9 @@ func (t Toolchain) newGperf() (pkg.Artifact, string) {
version = "3.3"
checksum = "RtIy9pPb_Bb8-31J2Nw-rRGso2JlS-lDlVhuNYhqR7Nt4xM_nObznxAlBMnarJv7"
)
return t.NewPackage("gperf", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gperf/gperf-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("gperf", version, newTar(
"https://ftpmirror.gnu.org/gperf/gperf-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), nil, (*MakeHelper)(nil),
Diffutils,
@@ -574,9 +574,9 @@ func (t Toolchain) newGawk() (pkg.Artifact, string) {
version = "5.4.0"
checksum = "m0RkIolC-PI7EY5q8pcx5Y-0twlIW0Yp3wXXmV-QaHorSdf8BhZ7kW9F8iWomz0C"
)
return t.NewPackage("gawk", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/gawk/gawk-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("gawk", version, newTar(
"https://ftpmirror.gnu.org/gnu/gawk/gawk-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), &PackageAttr{
Flag: TEarly,
@@ -602,9 +602,9 @@ func (t Toolchain) newGrep() (pkg.Artifact, string) {
version = "3.12"
checksum = "qMB4RjaPNRRYsxix6YOrjE8gyAT1zVSTy4nW4wKW9fqa0CHYAuWgPwDTirENzm_1"
)
return t.NewPackage("grep", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/grep/grep-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("grep", version, newTar(
"https://ftpmirror.gnu.org/gnu/grep/grep-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), &PackageAttr{
Writable: true,
@@ -639,7 +639,6 @@ func (t Toolchain) newFindutils() (pkg.Artifact, string) {
nil, "https://ftpmirror.gnu.org/gnu/findutils/findutils-"+version+".tar.xz",
mustDecode(checksum),
), &PackageAttr{
SourceKind: SourceKindTarXZ,
ScriptEarly: `
echo '#!/bin/sh' > gnulib-tests/test-c32ispunct.sh
echo 'int main(){return 0;}' > tests/xargs/test-sigusr.c
@@ -667,9 +666,9 @@ func (t Toolchain) newBC() (pkg.Artifact, string) {
version = "1.08.2"
checksum = "8h6f3hjV80XiFs6v9HOPF2KEyg1kuOgn5eeFdVspV05ODBVQss-ey5glc8AmneLy"
)
return t.NewPackage("bc", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/bc/bc-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("bc", version, newTar(
"https://ftpmirror.gnu.org/gnu/bc/bc-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), &PackageAttr{
// source expected to be writable
@@ -696,9 +695,9 @@ func (t Toolchain) newLibiconv() (pkg.Artifact, string) {
version = "1.19"
checksum = "UibB6E23y4MksNqYmCCrA3zTFO6vJugD1DEDqqWYFZNuBsUWMVMcncb_5pPAr88x"
)
return t.NewPackage("libiconv", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/libiconv/libiconv-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("libiconv", version, newTar(
"https://ftpmirror.gnu.org/gnu/libiconv/libiconv-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), nil, (*MakeHelper)(nil)), version
}
@@ -719,9 +718,9 @@ func (t Toolchain) newTar() (pkg.Artifact, string) {
version = "1.35"
checksum = "zSaoSlVUDW0dSfm4sbL4FrXLFR8U40Fh3zY5DWhR5NCIJ6GjU6Kc4VZo2-ZqpBRA"
)
return t.NewPackage("tar", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/tar/tar-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("tar", version, newTar(
"https://ftpmirror.gnu.org/gnu/tar/tar-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), nil, &MakeHelper{
Configure: []KV{
@@ -733,7 +732,7 @@ func (t Toolchain) newTar() (pkg.Artifact, string) {
// very expensive
"TARTEST_SKIP_LARGE_FILES=1",
`TESTSUITEFLAGS="-j$(nproc)"`,
"TESTSUITEFLAGS=" + jobsFlagE,
"check",
},
},
@@ -761,9 +760,9 @@ func (t Toolchain) newParallel() (pkg.Artifact, string) {
version = "20260322"
checksum = "gHoPmFkOO62ev4xW59HqyMlodhjp8LvTsBOwsVKHUUdfrt7KwB8koXmSVqQ4VOrB"
)
return t.NewPackage("parallel", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/parallel/parallel-"+version+".tar.bz2",
mustDecode(checksum),
return t.NewPackage("parallel", version, newTar(
"https://ftpmirror.gnu.org/gnu/parallel/parallel-"+version+".tar.bz2",
checksum,
pkg.TarBzip2,
), nil, (*MakeHelper)(nil),
Perl,
@@ -790,9 +789,9 @@ func (t Toolchain) newLibunistring() (pkg.Artifact, string) {
version = "1.4.2"
checksum = "iW9BbfLoVlXjWoLTZ4AekQSu4cFBnLcZ4W8OHWbv0AhJNgD3j65_zqaLMzFKylg2"
)
return t.NewPackage("libunistring", version, pkg.NewHTTPGetTar(
nil, "https://ftp.gnu.org/gnu/libunistring/libunistring-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("libunistring", version, newTar(
"https://ftpmirror.gnu.org/gnu/libunistring/libunistring-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), &PackageAttr{
Writable: true,
@@ -823,9 +822,9 @@ func (t Toolchain) newLibtasn1() (pkg.Artifact, string) {
version = "4.21.0"
checksum = "9DYI3UYbfYLy8JsKUcY6f0irskbfL0fHZA91Q-JEOA3kiUwpodyjemRsYRjUpjuq"
)
return t.NewPackage("libtasn1", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/libtasn1/libtasn1-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("libtasn1", version, newTar(
"https://ftpmirror.gnu.org/gnu/libtasn1/libtasn1-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), nil, (*MakeHelper)(nil)), version
}
@@ -846,9 +845,9 @@ func (t Toolchain) newReadline() (pkg.Artifact, string) {
version = "8.3"
checksum = "r-lcGRJq_MvvBpOq47Z2Y1OI2iqrmtcqhTLVXR0xWo37ZpC2uT_md7gKq5o_qTMV"
)
return t.NewPackage("readline", version, pkg.NewHTTPGetTar(
nil, "https://ftp.gnu.org/gnu/readline/readline-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("readline", version, newTar(
"https://ftpmirror.gnu.org/gnu/readline/readline-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), nil, &MakeHelper{
Configure: []KV{
@@ -889,10 +888,9 @@ func (t Toolchain) newGnuTLS() (pkg.Artifact, string) {
}
}
return t.NewPackage("gnutls", version, t.NewViaGit(
return t.NewPackage("gnutls", version, t.newTagRemote(
"https://gitlab.com/gnutls/gnutls.git",
"refs/tags/"+version,
mustDecode(checksum),
version, checksum,
), &PackageAttr{
Patches: []KV{
{"bootstrap-remove-gtk-doc", `diff --git a/bootstrap.conf b/bootstrap.conf
@@ -1062,9 +1060,9 @@ func (t Toolchain) newBinutils() (pkg.Artifact, string) {
version = "2.46.0"
checksum = "4kK1_EXQipxSqqyvwD4LbiMLFKCUApjq6PeG4XJP4dzxYGqDeqXfh8zLuTyOuOVR"
)
return t.NewPackage("binutils", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/binutils/binutils-"+version+".tar.bz2",
mustDecode(checksum),
return t.NewPackage("binutils", version, newTar(
"https://ftpmirror.gnu.org/gnu/binutils/binutils-"+version+".tar.bz2",
checksum,
pkg.TarBzip2,
), nil, (*MakeHelper)(nil),
Bash,
@@ -1087,12 +1085,16 @@ func (t Toolchain) newGMP() (pkg.Artifact, string) {
version = "6.3.0"
checksum = "yrgbgEDWKDdMWVHh7gPbVl56-sRtVVhfvv0M_LX7xMUUk_mvZ1QOJEAnt7g4i3k5"
)
return t.NewPackage("gmp", version, pkg.NewHTTPGetTar(
nil, "https://gcc.gnu.org/pub/gcc/infrastructure/"+
return t.NewPackage("gmp", version, newTar(
"https://gcc.gnu.org/pub/gcc/infrastructure/"+
"gmp-"+version+".tar.bz2",
mustDecode(checksum),
checksum,
pkg.TarBzip2,
), nil, (*MakeHelper)(nil),
), &PackageAttr{
Env: []string{
"CC=cc",
},
}, (*MakeHelper)(nil),
M4,
), version
}
@@ -1113,10 +1115,10 @@ func (t Toolchain) newMPFR() (pkg.Artifact, string) {
version = "4.2.2"
checksum = "wN3gx0zfIuCn9r3VAn_9bmfvAYILwrRfgBjYSD1IjLqyLrLojNN5vKyQuTE9kA-B"
)
return t.NewPackage("mpfr", version, pkg.NewHTTPGetTar(
nil, "https://gcc.gnu.org/pub/gcc/infrastructure/"+
return t.NewPackage("mpfr", version, newTar(
"https://gcc.gnu.org/pub/gcc/infrastructure/"+
"mpfr-"+version+".tar.bz2",
mustDecode(checksum),
checksum,
pkg.TarBzip2,
), nil, (*MakeHelper)(nil),
GMP,
@@ -1143,10 +1145,9 @@ func (t Toolchain) newMPC() (pkg.Artifact, string) {
version = "1.4.0"
checksum = "TbrxLiE3ipQrHz_F3Xzz4zqBAnkMWyjhNwIK6wh9360RZ39xMt8rxfW3LxA9SnvU"
)
return t.NewPackage("mpc", version, t.NewViaGit(
return t.NewPackage("mpc", version, t.newTagRemote(
"https://gitlab.inria.fr/mpc/mpc.git",
"refs/tags/"+version,
mustDecode(checksum),
version, checksum,
), &PackageAttr{
// does not find mpc-impl.h otherwise
EnterSource: true,
@@ -1182,10 +1183,17 @@ func (t Toolchain) newGCC() (pkg.Artifact, string) {
version = "15.2.0"
checksum = "TXJ5WrbXlGLzy1swghQTr4qxgDCyIZFgJry51XEPTBZ8QYbVmFeB4lZbSMtPJ-a1"
)
return t.NewPackage("gcc", version, pkg.NewHTTPGetTar(
nil, "https://ftp.tsukuba.wide.ad.jp/software/gcc/releases/"+
var configureExtra []KV
switch runtime.GOARCH {
case "amd64", "arm64":
configureExtra = append(configureExtra, KV{"with-multilib-list", "''"})
}
return t.NewPackage("gcc", version, newTar(
"https://ftp.tsukuba.wide.ad.jp/software/gcc/releases/"+
"gcc-"+version+"/gcc-"+version+".tar.gz",
mustDecode(checksum),
checksum,
pkg.TarGzip,
), &PackageAttr{
Patches: []KV{
@@ -1347,9 +1355,8 @@ ln -s system/lib /work/
// it also saturates the CPU for a consequential amount of time.
Flag: TExclusive,
}, &MakeHelper{
Configure: []KV{
Configure: append([]KV{
{"disable-multilib"},
{"with-multilib-list", `""`},
{"enable-default-pie"},
{"disable-nls"},
{"with-gnu-as"},
@@ -1357,7 +1364,7 @@ ln -s system/lib /work/
{"with-system-zlib"},
{"enable-languages", "c,c++,go"},
{"with-native-system-header-dir", "/system/include"},
},
}, configureExtra...),
Make: []string{
"BOOT_CFLAGS='-O2 -g'",
"bootstrap",

View File

@@ -21,9 +21,9 @@ cd /work/system/go/src
chmod -R +w ..
./make.bash
`, pkg.Path(AbsUsrSrc.Append("go"), false, pkg.NewHTTPGetTar(
nil, "https://dl.google.com/go/go1.4-bootstrap-20171003.tar.gz",
mustDecode(checksum),
`, pkg.Path(AbsUsrSrc.Append("go"), false, newTar(
"https://dl.google.com/go/go1.4-bootstrap-20171003.tar.gz",
checksum,
pkg.TarGzip,
)))
}
@@ -55,9 +55,9 @@ ln -s \
../go/bin/go \
../go/bin/gofmt \
/work/system/bin
`, pkg.Path(AbsUsrSrc.Append("go"), false, pkg.NewHTTPGetTar(
nil, "https://go.dev/dl/go"+version+".src.tar.gz",
mustDecode(checksum),
`, pkg.Path(AbsUsrSrc.Append("go"), false, newTar(
"https://go.dev/dl/go"+version+".src.tar.gz",
checksum,
pkg.TarGzip,
)))
}
@@ -141,8 +141,8 @@ rm \
)
const (
version = "1.26.1"
checksum = "DdC5Ea-aCYPUHNObQh_09uWU0vn4e-8Ben850Vq-5OoamDRrXhuYI4YQ_BOFgaT0"
version = "1.26.2"
checksum = "v-6BE89_1g3xYf-9oIYpJKFXlo3xKHYJj2_VGkaUq8ZVkIVQmLwrto-xGG03OISH"
)
return t.newGo(
version,

View File

@@ -10,10 +10,9 @@ func (t Toolchain) newGLib() (pkg.Artifact, string) {
version = "2.88.0"
checksum = "T79Cg4z6j-sDZ2yIwvbY4ccRv2-fbwbqgcw59F5NQ6qJT6z4v261vbYp3dHO6Ma3"
)
return t.NewPackage("glib", version, t.NewViaGit(
return t.NewPackage("glib", version, t.newTagRemote(
"https://gitlab.gnome.org/GNOME/glib.git",
"refs/tags/"+version,
mustDecode(checksum),
version, checksum,
), &PackageAttr{
Paths: []pkg.ExecPath{
pkg.Path(fhs.AbsEtc.Append(

View File

@@ -99,7 +99,7 @@ mkdir -p /work/system/bin/
f: func(t Toolchain) (pkg.Artifact, string) {
return t.newHakurei("-dist", `
export HAKUREI_VERSION
DESTDIR=/work /usr/src/hakurei/dist/release.sh
DESTDIR=/work /usr/src/hakurei/all.sh
`, true), hakureiVersion
},

View File

@@ -4,13 +4,13 @@ package rosa
import "hakurei.app/internal/pkg"
const hakureiVersion = "0.3.7"
const hakureiVersion = "0.4.0"
// hakureiSource is the source code of a hakurei release.
var hakureiSource = pkg.NewHTTPGetTar(
nil, "https://git.gensokyo.uk/rosa/hakurei/archive/"+
var hakureiSource = newTar(
"https://git.gensokyo.uk/rosa/hakurei/archive/"+
"v"+hakureiVersion+".tar.gz",
mustDecode("Xh_sdITOATEAQN5_UuaOyrWsgboxorqRO9bml3dGm8GAxF8NFpB7MqhSZgjJxAl2"),
"wfQ9DqCW0Fw9o91wj-I55waoqzB-UqzzuC0_2h-P-1M78SgZ1WHSPCDJMth6EyC2",
pkg.TarGzip,
)

View File

@@ -2,12 +2,12 @@ package rosa
import "hakurei.app/internal/pkg"
const kernelVersion = "6.12.80"
const kernelVersion = "6.12.81"
var kernelSource = pkg.NewHTTPGetTar(
nil, "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/"+
var kernelSource = newTar(
"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/"+
"snapshot/linux-"+kernelVersion+".tar.gz",
mustDecode("_iJEAYoQISJxefuWZYfv0RPWUmHHIjHQw33Fapix-irXrEIREP5ruK37UJW4uMZO"),
"fBkNwf82DQXh74in6gaF2Jot7Vg-Vlcp9BUtCEipL9mvcM1EXLVFdV7FcrO20Eve",
pkg.TarGzip,
)
@@ -1221,7 +1221,7 @@ install -Dm0500 \
/sbin/depmod
make \
"-j$(nproc)" \
` + jobsFlagE + ` \
-f /usr/src/kernel/Makefile \
O=/tmp/kbuild \
LLVM=1 \
@@ -1282,14 +1282,14 @@ func init() {
func (t Toolchain) newFirmware() (pkg.Artifact, string) {
const (
version = "20260309"
checksum = "M1az8BxSiOEH3LA11Trc5VAlakwAHhP7-_LKWg6k-SVIzU3xclMDO4Tiujw1gQrC"
version = "20260410"
checksum = "J8PdQlGqwrivpskPzbL6xacqR6mlKtXpe5RpzFfVzKPAgG81ZRXsc3qrxwdGJbil"
)
return t.NewPackage("firmware", version, pkg.NewHTTPGetTar(
nil, "https://gitlab.com/kernel-firmware/linux-firmware/-/"+
"archive/"+version+"/linux-firmware-"+version+".tar.bz2",
mustDecode(checksum),
pkg.TarBzip2,
return t.NewPackage("firmware", version, newFromGitLab(
"gitlab.com",
"kernel-firmware/linux-firmware",
version,
checksum,
), &PackageAttr{
// dedup creates temporary file
Writable: true,
@@ -1309,7 +1309,7 @@ func (t Toolchain) newFirmware() (pkg.Artifact, string) {
"install-zst",
},
SkipCheck: true, // requires pre-commit
Install: `make "-j$(nproc)" DESTDIR=/work/system dedup`,
Install: "make " + jobsFlagE + " DESTDIR=/work/system dedup",
},
Parallel,
Rdfind,

View File

@@ -7,10 +7,10 @@ func (t Toolchain) newKmod() (pkg.Artifact, string) {
version = "34.2"
checksum = "0K7POeTKxMhExsaTsnKAC6LUNsRSfe6sSZxWONPbOu-GI_pXOw3toU_BIoqfBhJV"
)
return t.NewPackage("kmod", version, pkg.NewHTTPGetTar(
nil, "https://www.kernel.org/pub/linux/utils/kernel/"+
return t.NewPackage("kmod", version, newTar(
"https://www.kernel.org/pub/linux/utils/kernel/"+
"kmod/kmod-"+version+".tar.gz",
mustDecode(checksum),
checksum,
pkg.TarGzip,
), nil, &MesonHelper{
Setup: []KV{

View File

@@ -7,10 +7,9 @@ func (t Toolchain) newLibmd() (pkg.Artifact, string) {
version = "1.1.0"
checksum = "9apYqPPZm0j5HQT8sCsVIhnVIqRD7XgN7kPIaTwTqnTuUq5waUAMq4M7ev8CODJ1"
)
return t.NewPackage("libmd", version, t.NewViaGit(
return t.NewPackage("libmd", version, t.newTagRemote(
"https://git.hadrons.org/git/libmd.git",
"refs/tags/"+version,
mustDecode(checksum),
version, checksum,
), nil, &MakeHelper{
Generate: "echo '" + version + "' > .dist-version && ./autogen",
ScriptMakeEarly: `
@@ -38,10 +37,9 @@ func (t Toolchain) newLibbsd() (pkg.Artifact, string) {
version = "0.12.2"
checksum = "NVS0xFLTwSP8JiElEftsZ-e1_C-IgJhHrHE77RwKt5178M7r087waO-zYx2_dfGX"
)
return t.NewPackage("libbsd", version, t.NewViaGit(
return t.NewPackage("libbsd", version, t.newTagRemote(
"https://gitlab.freedesktop.org/libbsd/libbsd.git",
"refs/tags/"+version,
mustDecode(checksum),
version, checksum,
), nil, &MakeHelper{
Generate: "echo '" + version + "' > .dist-version && ./autogen",
},

View File

@@ -4,13 +4,13 @@ import "hakurei.app/internal/pkg"
func (t Toolchain) newLibcap() (pkg.Artifact, string) {
const (
version = "2.77"
checksum = "2GOTFU4cl2QoS7Dv5wh0c9-hxsQwIzMB9Y_gfAo5xKHqcM13fiHt1RbPkfemzjmB"
version = "2.78"
checksum = "wFdUkBhFMD9InPnrBZyegWrlPSAg_9JiTBC-eSFyWWlmbzL2qjh2mKxr9Kx2a8ut"
)
return t.NewPackage("libcap", version, pkg.NewHTTPGetTar(
nil, "https://git.kernel.org/pub/scm/libs/libcap/libcap.git/"+
return t.NewPackage("libcap", version, newTar(
"https://git.kernel.org/pub/scm/libs/libcap/libcap.git/"+
"snapshot/libcap-"+version+".tar.gz",
mustDecode(checksum),
checksum,
pkg.TarGzip,
), &PackageAttr{
// uses source tree as scratch space

View File

@@ -7,9 +7,9 @@ func (t Toolchain) newLibev() (pkg.Artifact, string) {
version = "4.33"
checksum = "774eSXV_4k8PySRprUDChbEwsw-kzjIFnJ3MpNOl5zDpamBRvC3BqPyRxvkwcL6_"
)
return t.NewPackage("libev", version, pkg.NewHTTPGetTar(
nil, "https://dist.schmorp.de/libev/Attic/libev-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("libev", version, newTar(
"https://dist.schmorp.de/libev/Attic/libev-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), nil, (*MakeHelper)(nil)), version
}

View File

@@ -11,11 +11,11 @@ func (t Toolchain) newLibexpat() (pkg.Artifact, string) {
version = "2.7.5"
checksum = "vTRUjjg-qbHSXUBYKXgzVHkUO7UNyuhrkSYrE7ikApQm0g-OvQ8tspw4w55M-1Tp"
)
return t.NewPackage("libexpat", version, pkg.NewHTTPGetTar(
nil, "https://github.com/libexpat/libexpat/releases/download/"+
"R_"+strings.ReplaceAll(version, ".", "_")+"/"+
"expat-"+version+".tar.bz2",
mustDecode(checksum),
return t.NewPackage("libexpat", version, newFromGitHubRelease(
"libexpat/libexpat",
"R_"+strings.ReplaceAll(version, ".", "_"),
"expat-"+version+".tar.bz2",
checksum,
pkg.TarBzip2,
), nil, (*MakeHelper)(nil),
Bash,

View File

@@ -7,10 +7,11 @@ func (t Toolchain) newLibffi() (pkg.Artifact, string) {
version = "3.5.2"
checksum = "2_Q-ZNBBbVhltfL5zEr0wljxPegUimTK4VeMSiwJEGksls3n4gj3lV0Ly3vviSFH"
)
return t.NewPackage("libffi", version, pkg.NewHTTPGetTar(
nil, "https://github.com/libffi/libffi/releases/download/"+
"v"+version+"/libffi-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("libffi", version, newFromGitHubRelease(
"libffi/libffi",
"v"+version,
"libffi-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), nil, (*MakeHelper)(nil),
KernelHeaders,

View File

@@ -7,10 +7,10 @@ func (t Toolchain) newLibgd() (pkg.Artifact, string) {
version = "2.3.3"
checksum = "8T-sh1_FJT9K9aajgxzh8ot6vWIF-xxjcKAHvTak9MgGUcsFfzP8cAvvv44u2r36"
)
return t.NewPackage("libgd", version, pkg.NewHTTPGetTar(
nil, "https://github.com/libgd/libgd/releases/download/"+
"gd-"+version+"/libgd-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("libgd", version, newFromGitHubRelease(
"libgd/libgd",
"gd-"+version,
"libgd-"+version+".tar.gz", checksum,
pkg.TarGzip,
), &PackageAttr{
Env: []string{

View File

@@ -7,10 +7,11 @@ func (t Toolchain) newLibpsl() (pkg.Artifact, string) {
version = "0.21.5"
checksum = "XjfxSzh7peG2Vg4vJlL8z4JZJLcXqbuP6pLWkrGCmRxlnYUFTKNBqWGHCxEOlCad"
)
return t.NewPackage("libpsl", version, pkg.NewHTTPGetTar(
nil, "https://github.com/rockdaboot/libpsl/releases/download/"+
version+"/libpsl-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("libpsl", version, newFromGitHubRelease(
"rockdaboot/libpsl",
version,
"libpsl-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), &PackageAttr{
Writable: true,

View File

@@ -7,10 +7,11 @@ func (t Toolchain) newLibseccomp() (pkg.Artifact, string) {
version = "2.6.0"
checksum = "mMu-iR71guPjFbb31u-YexBaanKE_nYPjPux-vuBiPfS_0kbwJdfCGlkofaUm-EY"
)
return t.NewPackage("libseccomp", version, pkg.NewHTTPGetTar(
nil, "https://github.com/seccomp/libseccomp/releases/download/"+
"v"+version+"/libseccomp-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("libseccomp", version, newFromGitHubRelease(
"seccomp/libseccomp",
"v"+version,
"libseccomp-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), &PackageAttr{
ScriptEarly: `

View File

@@ -7,11 +7,10 @@ func (t Toolchain) newLibucontext() (pkg.Artifact, string) {
version = "1.5"
checksum = "Ggk7FMmDNBdCx1Z9PcNWWW6LSpjGYssn2vU0GK5BLXJYw7ZxZbA2m_eSgT9TFnIG"
)
return t.NewPackage("libucontext", version, pkg.NewHTTPGetTar(
nil, "https://github.com/kaniini/libucontext/archive/refs/tags/"+
"libucontext-"+version+".tar.gz",
mustDecode(checksum),
pkg.TarGzip,
return t.NewPackage("libucontext", version, newFromGitHub(
"kaniini/libucontext",
"libucontext-"+version,
checksum,
), &PackageAttr{
// uses source tree as scratch space
Writable: true,

View File

@@ -7,10 +7,9 @@ func (t Toolchain) newLibxml2() (pkg.Artifact, string) {
version = "2.15.2"
checksum = "zwQvCIBnjzUFY-inX5ckfNT3mIezsCRV55C_Iztde5OnRTB3u33lfO5h03g7DK_8"
)
return t.NewPackage("libxml2", version, t.NewViaGit(
return t.NewPackage("libxml2", version, t.newTagRemote(
"https://gitlab.gnome.org/GNOME/libxml2.git",
"refs/tags/v"+version,
mustDecode(checksum),
"v"+version, checksum,
), &PackageAttr{
// can't create shell.out: Read-only file system
Writable: true,

View File

@@ -7,10 +7,9 @@ func (t Toolchain) newLibxslt() (pkg.Artifact, string) {
version = "1.1.45"
checksum = "MZc_dyUWpHChkWDKa5iycrECxBsRd4ZMbYfL4VojTbung593mlH2tHGmxYB6NFYT"
)
return t.NewPackage("libxslt", version, t.NewViaGit(
return t.NewPackage("libxslt", version, t.newTagRemote(
"https://gitlab.gnome.org/GNOME/libxslt.git",
"refs/tags/v"+version,
mustDecode(checksum),
"v"+version, checksum,
), nil, &MakeHelper{
Generate: "NOCONFIGURE=1 ./autogen.sh",

View File

@@ -1,239 +1,48 @@
package rosa
import (
"runtime"
"slices"
"strconv"
"strings"
"sync"
import "hakurei.app/internal/pkg"
"hakurei.app/internal/pkg"
)
func init() {
artifactsM[llvmSource] = Metadata{
f: func(t Toolchain) (pkg.Artifact, string) {
return t.NewPatchedSource("llvm", llvmVersion, newFromGitHub(
"llvm/llvm-project",
"llvmorg-"+llvmVersion,
llvmChecksum,
), true, llvmPatches...), llvmVersion
},
// llvmAttr holds the attributes that will be applied to a new [pkg.Artifact]
// containing a LLVM variant.
type llvmAttr struct {
// Passed through to PackageAttr.Flag.
flags int
Name: "llvm-project",
Description: "LLVM monorepo with Rosa OS patches",
// Concatenated with default environment for PackageAttr.Env.
env []string
// Concatenated with generated entries for CMakeHelper.Cache.
cmake []KV
// Override CMakeHelper.Append.
append []string
// Passed through to PackageAttr.NonStage0.
nonStage0 []pkg.Artifact
// Passed through to PackageAttr.Paths.
paths []pkg.ExecPath
// Concatenated with default fixup for CMakeHelper.Script.
script string
// Patch name and body pairs.
patches []KV
}
const (
llvmProjectClang = 1 << iota
llvmProjectLld
llvmProjectAll = 1<<iota - 1
llvmRuntimeCompilerRT = 1 << iota
llvmRuntimeLibunwind
llvmRuntimeLibc
llvmRuntimeLibcxx
llvmRuntimeLibcxxABI
llvmAll = 1<<iota - 1
llvmRuntimeAll = llvmAll - (2 * llvmProjectAll) - 1
)
// llvmFlagName resolves a llvmAttr.flags project or runtime flag to its name.
func llvmFlagName(flag int) string {
switch flag {
case llvmProjectClang:
return "clang"
case llvmProjectLld:
return "lld"
case llvmRuntimeCompilerRT:
return "compiler-rt"
case llvmRuntimeLibunwind:
return "libunwind"
case llvmRuntimeLibc:
return "libc"
case llvmRuntimeLibcxx:
return "libcxx"
case llvmRuntimeLibcxxABI:
return "libcxxabi"
default:
panic("invalid flag " + strconv.Itoa(flag))
ID: 1830,
}
}
// newLLVMVariant returns a [pkg.Artifact] containing a LLVM variant.
func (t Toolchain) newLLVMVariant(variant string, attr *llvmAttr) pkg.Artifact {
if attr == nil {
panic("LLVM attr must be non-nil")
}
var projects, runtimes []string
for i := 1; i < llvmProjectAll; i <<= 1 {
if attr.flags&i != 0 {
projects = append(projects, llvmFlagName(i))
}
}
for i := (llvmProjectAll + 1) << 1; i < llvmRuntimeAll; i <<= 1 {
if attr.flags&i != 0 {
runtimes = append(runtimes, llvmFlagName(i))
}
}
var script string
cache := []KV{
{"CMAKE_BUILD_TYPE", "Release"},
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
}
if len(projects) > 0 {
cache = append(cache, []KV{
{"LLVM_ENABLE_PROJECTS", `"${ROSA_LLVM_PROJECTS}"`},
}...)
}
if len(runtimes) > 0 {
cache = append(cache, []KV{
{"LLVM_ENABLE_RUNTIMES", `"${ROSA_LLVM_RUNTIMES}"`},
}...)
}
cmakeAppend := []string{"llvm"}
if attr.append != nil {
cmakeAppend = attr.append
} else {
cache = append(cache, []KV{
{"LLVM_ENABLE_LIBCXX", "ON"},
{"LLVM_USE_LINKER", "lld"},
{"LLVM_INSTALL_BINUTILS_SYMLINKS", "ON"},
{"LLVM_INSTALL_CCTOOLS_SYMLINKS", "ON"},
{"LLVM_LIT_ARGS", "'--verbose'"},
}...)
}
if attr.flags&llvmProjectClang != 0 {
cache = append(cache, []KV{
{"CLANG_DEFAULT_LINKER", "lld"},
{"CLANG_DEFAULT_CXX_STDLIB", "libc++"},
{"CLANG_DEFAULT_RTLIB", "compiler-rt"},
{"CLANG_DEFAULT_UNWINDLIB", "libunwind"},
}...)
}
if attr.flags&llvmProjectLld != 0 {
script += `
ln -s ld.lld /work/system/bin/ld
`
}
if attr.flags&llvmRuntimeCompilerRT != 0 {
if attr.append == nil {
cache = append(cache, []KV{
{"COMPILER_RT_USE_LLVM_UNWINDER", "ON"},
}...)
}
}
if attr.flags&llvmRuntimeLibunwind != 0 {
cache = append(cache, []KV{
{"LIBUNWIND_USE_COMPILER_RT", "ON"},
}...)
}
if attr.flags&llvmRuntimeLibcxx != 0 {
cache = append(cache, []KV{
{"LIBCXX_HAS_MUSL_LIBC", "ON"},
{"LIBCXX_USE_COMPILER_RT", "ON"},
}...)
}
if attr.flags&llvmRuntimeLibcxxABI != 0 {
cache = append(cache, []KV{
{"LIBCXXABI_USE_COMPILER_RT", "ON"},
{"LIBCXXABI_USE_LLVM_UNWINDER", "ON"},
}...)
}
return t.NewPackage("llvm", llvmVersion, pkg.NewHTTPGetTar(
nil, "https://github.com/llvm/llvm-project/archive/refs/tags/"+
"llvmorg-"+llvmVersion+".tar.gz",
mustDecode(llvmChecksum),
pkg.TarGzip,
), &PackageAttr{
Patches: attr.patches,
NonStage0: attr.nonStage0,
Env: slices.Concat([]string{
"ROSA_LLVM_PROJECTS=" + strings.Join(projects, ";"),
"ROSA_LLVM_RUNTIMES=" + strings.Join(runtimes, ";"),
}, attr.env),
Paths: attr.paths,
Flag: TExclusive,
}, &CMakeHelper{
Variant: variant,
Cache: slices.Concat(cache, attr.cmake),
Append: cmakeAppend,
Script: script + attr.script,
},
Python,
Perl,
Diffutils,
Bash,
Gawk,
Coreutils,
Findutils,
KernelHeaders,
)
}
// newLLVM returns LLVM toolchain across multiple [pkg.Artifact].
func (t Toolchain) newLLVM() (musl, compilerRT, runtimes, clang pkg.Artifact) {
var target string
switch runtime.GOARCH {
case "386", "amd64":
target = "X86"
case "arm64":
target = "AArch64"
case "riscv64":
target = "RISCV"
default:
panic("unsupported target " + runtime.GOARCH)
}
minimalDeps := []KV{
{"LLVM_ENABLE_ZLIB", "OFF"},
{"LLVM_ENABLE_ZSTD", "OFF"},
{"LLVM_ENABLE_LIBXML2", "OFF"},
}
muslHeaders, _ := t.newMusl(true, []string{
"CC=clang",
})
compilerRT = t.newLLVMVariant("compiler-rt", &llvmAttr{
env: stage0ExclConcat(t, []string{},
func (t Toolchain) newCompilerRT() (pkg.Artifact, string) {
muslHeaders, _ := t.newMusl(true)
return t.NewPackage("compiler-rt", llvmVersion, t.Load(llvmSource), &PackageAttr{
NonStage0: []pkg.Artifact{
muslHeaders,
},
Env: stage0ExclConcat(t, []string{},
"LDFLAGS="+earlyLDFLAGS(false),
),
cmake: []KV{
Flag: TExclusive,
}, &CMakeHelper{
Append: []string{"compiler-rt"},
Cache: []KV{
{"CMAKE_BUILD_TYPE", "Release"},
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
// libc++ not yet available
{"CMAKE_CXX_COMPILER_TARGET", ""},
{"COMPILER_RT_BUILD_BUILTINS", "ON"},
{"COMPILER_RT_DEFAULT_TARGET_ONLY", "ON"},
{"COMPILER_RT_DEFAULT_TARGET_ONLY", "OFF"},
{"COMPILER_RT_SANITIZERS_TO_BUILD", "asan"},
{"LLVM_ENABLE_PER_TARGET_RUNTIME_DIR", "ON"},
@@ -244,11 +53,7 @@ func (t Toolchain) newLLVM() (musl, compilerRT, runtimes, clang pkg.Artifact) {
{"COMPILER_RT_BUILD_PROFILE", "OFF"},
{"COMPILER_RT_BUILD_XRAY", "OFF"},
},
append: []string{"compiler-rt"},
nonStage0: []pkg.Artifact{
muslHeaders,
},
script: `
Script: `
mkdir -p "/work/system/lib/clang/` + llvmVersionMajor + `/lib/"
ln -s \
"../../../${ROSA_TRIPLE}" \
@@ -261,286 +66,179 @@ ln -s \
"clang_rt.crtend-` + linuxArch() + `.o" \
"/work/system/lib/${ROSA_TRIPLE}/crtendS.o"
`,
})
musl, _ = t.newMusl(false, stage0ExclConcat(t, []string{
"CC=clang",
"LIBCC=/system/lib/clang/" + llvmVersionMajor + "/lib/" +
triplet() + "/libclang_rt.builtins.a",
"AR=ar",
"RANLIB=ranlib",
},
"LDFLAGS="+earlyLDFLAGS(false),
), compilerRT)
Python,
runtimes = t.newLLVMVariant("runtimes", &llvmAttr{
env: stage0ExclConcat(t, []string{},
KernelHeaders,
), llvmVersion
}
func init() {
artifactsM[CompilerRT] = Metadata{
f: Toolchain.newCompilerRT,
Name: "compiler-rt",
Description: "LLVM runtime: compiler-rt",
Website: "https://llvm.org/",
Dependencies: P{
Musl,
},
}
}
func (t Toolchain) newLLVMRuntimes() (pkg.Artifact, string) {
return t.NewPackage("llvm-runtimes", llvmVersion, t.Load(llvmSource), &PackageAttr{
NonStage0: t.AppendPresets(nil, CompilerRT),
Env: stage0ExclConcat(t, []string{},
"LDFLAGS="+earlyLDFLAGS(false),
),
flags: llvmRuntimeLibunwind | llvmRuntimeLibcxx | llvmRuntimeLibcxxABI,
cmake: slices.Concat([]KV{
Flag: TExclusive,
}, &CMakeHelper{
Append: []string{"runtimes"},
Cache: []KV{
{"CMAKE_BUILD_TYPE", "Release"},
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
{"LLVM_ENABLE_RUNTIMES", "'libunwind;libcxx;libcxxabi'"},
{"LIBUNWIND_USE_COMPILER_RT", "ON"},
{"LIBCXX_HAS_MUSL_LIBC", "ON"},
{"LIBCXX_USE_COMPILER_RT", "ON"},
{"LIBCXXABI_USE_COMPILER_RT", "ON"},
{"LIBCXXABI_USE_LLVM_UNWINDER", "ON"},
// libc++ not yet available
{"CMAKE_CXX_COMPILER_WORKS", "ON"},
{"LIBCXX_HAS_ATOMIC_LIB", "OFF"},
{"LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL", "OFF"},
}, minimalDeps),
append: []string{"runtimes"},
nonStage0: []pkg.Artifact{
compilerRT,
musl,
{"LLVM_ENABLE_ZLIB", "OFF"},
{"LLVM_ENABLE_ZSTD", "OFF"},
{"LLVM_ENABLE_LIBXML2", "OFF"},
},
})
},
Python,
clang = t.newLLVMVariant("clang", &llvmAttr{
flags: llvmProjectClang | llvmProjectLld,
env: stage0ExclConcat(t, []string{},
"CFLAGS="+earlyCFLAGS,
"CXXFLAGS="+earlyCXXFLAGS(),
"LDFLAGS="+earlyLDFLAGS(false),
),
cmake: slices.Concat([]KV{
{"LLVM_TARGETS_TO_BUILD", target},
{"CMAKE_CROSSCOMPILING", "OFF"},
{"CXX_SUPPORTS_CUSTOM_LINKER", "ON"},
}, minimalDeps),
nonStage0: []pkg.Artifact{
musl,
compilerRT,
runtimes,
},
script: `
ln -s clang /work/system/bin/cc
ln -s clang++ /work/system/bin/c++
ninja check-all
`,
patches: slices.Concat([]KV{
{"add-rosa-vendor", `diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index 9c83abeeb3b1..5acfe5836a23 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -190,6 +190,7 @@ public:
Apple,
PC,
+ Rosa,
SCEI,
Freescale,
IBM,
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index a4f9dd42c0fe..cb5a12387034 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -279,6 +279,7 @@ StringRef Triple::getVendorTypeName(VendorType Kind) {
case NVIDIA: return "nvidia";
case OpenEmbedded: return "oe";
case PC: return "pc";
+ case Rosa: return "rosa";
case SCEI: return "scei";
case SUSE: return "suse";
case Meta:
@@ -689,6 +690,7 @@ static Triple::VendorType parseVendor(StringRef VendorName) {
return StringSwitch<Triple::VendorType>(VendorName)
.Case("apple", Triple::Apple)
.Case("pc", Triple::PC)
+ .Case("rosa", Triple::Rosa)
.Case("scei", Triple::SCEI)
.Case("sie", Triple::SCEI)
.Case("fsl", Triple::Freescale)
`},
{"xfail-broken-tests", `diff --git a/clang/test/Modules/timestamps.c b/clang/test/Modules/timestamps.c
index 50fdce630255..4b4465a75617 100644
--- a/clang/test/Modules/timestamps.c
+++ b/clang/test/Modules/timestamps.c
@@ -1,3 +1,5 @@
+// XFAIL: target={{.*-rosa-linux-musl}}
+
/// Verify timestamps that gets embedded in the module
#include <c-header.h>
`},
{"path-system-include", `diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index 8ac8d4eb9181..e46b04a898ca 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -671,6 +671,12 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
addExternCSystemInclude(
DriverArgs, CC1Args,
concat(SysRoot, "/usr/include", MultiarchIncludeDir));
+ if (!MultiarchIncludeDir.empty() &&
+ D.getVFS().exists(concat(SysRoot, "/system/include", MultiarchIncludeDir)))
+ addExternCSystemInclude(
+ DriverArgs, CC1Args,
+ concat(SysRoot, "/system/include", MultiarchIncludeDir));
+
if (getTriple().getOS() == llvm::Triple::RTEMS)
return;
@@ -681,6 +687,7 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
addExternCSystemInclude(DriverArgs, CC1Args, concat(SysRoot, "/include"));
addExternCSystemInclude(DriverArgs, CC1Args, concat(SysRoot, "/usr/include"));
+ addExternCSystemInclude(DriverArgs, CC1Args, concat(SysRoot, "/system/include"));
if (!DriverArgs.hasArg(options::OPT_nobuiltininc) && getTriple().isMusl())
addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
`},
{"path-system-libraries", `diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index 8ac8d4eb9181..f4d1347ab64d 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -282,6 +282,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
const bool IsHexagon = Arch == llvm::Triple::hexagon;
const bool IsRISCV = Triple.isRISCV();
const bool IsCSKY = Triple.isCSKY();
+ const bool IsRosa = Triple.getVendor() == llvm::Triple::Rosa;
if (IsCSKY && !SelectedMultilibs.empty())
SysRoot = SysRoot + SelectedMultilibs.back().osSuffix();
@@ -318,12 +319,23 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
const std::string OSLibDir = std::string(getOSLibDir(Triple, Args));
const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot);
+ if (IsRosa) {
+ ExtraOpts.push_back("-rpath");
+ ExtraOpts.push_back("/system/lib");
+ ExtraOpts.push_back("-rpath");
+ ExtraOpts.push_back(concat("/system/lib", MultiarchTriple));
+ }
+
// mips32: Debian multilib, we use /libo32, while in other case, /lib is
// used. We need add both libo32 and /lib.
if (Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel) {
Generic_GCC::AddMultilibPaths(D, SysRoot, "libo32", MultiarchTriple, Paths);
- addPathIfExists(D, concat(SysRoot, "/libo32"), Paths);
- addPathIfExists(D, concat(SysRoot, "/usr/libo32"), Paths);
+ if (!IsRosa) {
+ addPathIfExists(D, concat(SysRoot, "/libo32"), Paths);
+ addPathIfExists(D, concat(SysRoot, "/usr/libo32"), Paths);
+ } else {
+ addPathIfExists(D, concat(SysRoot, "/system/libo32"), Paths);
+ }
}
Generic_GCC::AddMultilibPaths(D, SysRoot, OSLibDir, MultiarchTriple, Paths);
@@ -341,18 +353,30 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
Paths);
}
- addPathIfExists(D, concat(SysRoot, "/usr/lib", MultiarchTriple), Paths);
- addPathIfExists(D, concat(SysRoot, "/usr", OSLibDir), Paths);
+ if (!IsRosa) {
+ addPathIfExists(D, concat(SysRoot, "/usr/lib", MultiarchTriple), Paths);
+ addPathIfExists(D, concat(SysRoot, "/usr", OSLibDir), Paths);
+ } else {
+ addPathIfExists(D, concat(SysRoot, "/system/lib", MultiarchTriple), Paths);
+ addPathIfExists(D, concat(SysRoot, "/system", OSLibDir), Paths);
+ }
if (IsRISCV) {
StringRef ABIName = tools::riscv::getRISCVABI(Args, Triple);
addPathIfExists(D, concat(SysRoot, "/", OSLibDir, ABIName), Paths);
- addPathIfExists(D, concat(SysRoot, "/usr", OSLibDir, ABIName), Paths);
+ if (!IsRosa)
+ addPathIfExists(D, concat(SysRoot, "/usr", OSLibDir, ABIName), Paths);
+ else
+ addPathIfExists(D, concat(SysRoot, "/system", OSLibDir, ABIName), Paths);
}
Generic_GCC::AddMultiarchPaths(D, SysRoot, OSLibDir, Paths);
- addPathIfExists(D, concat(SysRoot, "/lib"), Paths);
- addPathIfExists(D, concat(SysRoot, "/usr/lib"), Paths);
+ if (!IsRosa) {
+ addPathIfExists(D, concat(SysRoot, "/lib"), Paths);
+ addPathIfExists(D, concat(SysRoot, "/usr/lib"), Paths);
+ } else {
+ addPathIfExists(D, concat(SysRoot, "/system/lib"), Paths);
+ }
}
ToolChain::RuntimeLibType Linux::GetDefaultRuntimeLibType() const {
@@ -457,6 +481,9 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
return Triple.isArch64Bit() ? "/system/bin/linker64" : "/system/bin/linker";
}
if (Triple.isMusl()) {
+ if (Triple.getVendor() == llvm::Triple::Rosa)
+ return "/system/bin/linker";
+
std::string ArchName;
bool IsArm = false;
diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp
index 64324a3f8b01..15ce70b68217 100644
--- a/clang/tools/clang-installapi/Options.cpp
+++ b/clang/tools/clang-installapi/Options.cpp
@@ -515,7 +515,7 @@ bool Options::processFrontendOptions(InputArgList &Args) {
FEOpts.FwkPaths = std::move(FrameworkPaths);
// Add default framework/library paths.
- PathSeq DefaultLibraryPaths = {"/usr/lib", "/usr/local/lib"};
+ PathSeq DefaultLibraryPaths = {"/usr/lib", "/system/lib", "/usr/local/lib"};
PathSeq DefaultFrameworkPaths = {"/Library/Frameworks",
"/System/Library/Frameworks"};
`},
}, clangPatches),
})
return
KernelHeaders,
), llvmVersion
}
func init() {
artifactsM[LLVMCompilerRT] = Metadata{
f: func(t Toolchain) (pkg.Artifact, string) {
_, compilerRT, _, _ := t.newLLVM()
return compilerRT, llvmVersion
},
Name: "llvm-compiler-rt",
Description: "LLVM runtime: compiler-rt",
Website: "https://llvm.org/",
}
artifactsM[LLVMRuntimes] = Metadata{
f: func(t Toolchain) (pkg.Artifact, string) {
_, _, runtimes, _ := t.newLLVM()
return runtimes, llvmVersion
},
f: Toolchain.newLLVMRuntimes,
Name: "llvm-runtimes",
Description: "LLVM runtimes: libunwind, libcxx, libcxxabi",
Website: "https://llvm.org/",
Dependencies: P{
CompilerRT,
},
}
}
func (t Toolchain) newClang() (pkg.Artifact, string) {
target := "'AArch64;RISCV;X86'"
if t.isStage0() {
target = "Native"
}
artifactsM[LLVMClang] = Metadata{
f: func(t Toolchain) (pkg.Artifact, string) {
_, _, _, clang := t.newLLVM()
return clang, llvmVersion
return t.NewPackage("clang", llvmVersion, t.Load(llvmSource), &PackageAttr{
NonStage0: t.AppendPresets(nil, LLVMRuntimes),
Env: stage0ExclConcat(t, []string{},
"CFLAGS="+earlyCFLAGS,
"CXXFLAGS="+earlyCXXFLAGS(),
"LDFLAGS="+earlyLDFLAGS(false),
),
Flag: TExclusive,
}, &CMakeHelper{
Append: []string{"llvm"},
Cache: []KV{
{"CMAKE_BUILD_TYPE", "Release"},
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
{"LLVM_ENABLE_PROJECTS", "'clang;lld'"},
{"LLVM_ENABLE_LIBCXX", "ON"},
{"LLVM_USE_LINKER", "lld"},
{"LLVM_INSTALL_BINUTILS_SYMLINKS", "ON"},
{"LLVM_INSTALL_CCTOOLS_SYMLINKS", "ON"},
{"LLVM_LIT_ARGS", "'--verbose'"},
{"CLANG_DEFAULT_LINKER", "lld"},
{"CLANG_DEFAULT_CXX_STDLIB", "libc++"},
{"CLANG_DEFAULT_RTLIB", "compiler-rt"},
{"CLANG_DEFAULT_UNWINDLIB", "libunwind"},
{"LLVM_TARGETS_TO_BUILD", target},
{"CMAKE_CROSSCOMPILING", "OFF"},
{"CXX_SUPPORTS_CUSTOM_LINKER", "ON"},
{"LLVM_ENABLE_ZLIB", "OFF"},
{"LLVM_ENABLE_ZSTD", "OFF"},
{"LLVM_ENABLE_LIBXML2", "OFF"},
},
Script: `
ln -s ld.lld /work/system/bin/ld
ln -s clang /work/system/bin/cc
ln -s clang++ /work/system/bin/c++
ninja ` + jobsFlagE + ` check-all
`,
},
Python,
Perl,
Diffutils,
Bash,
Gawk,
Coreutils,
Findutils,
KernelHeaders,
), llvmVersion
}
func init() {
artifactsM[Clang] = Metadata{
f: Toolchain.newClang,
Name: "clang",
Description: `an "LLVM native" C/C++/Objective-C compiler`,
Website: "https://llvm.org/",
ID: 1830,
Dependencies: P{
LLVMRuntimes,
},
}
}
var (
// llvm stores the result of Toolchain.newLLVM.
llvm [_toolchainEnd][4]pkg.Artifact
// llvmOnce is for lazy initialisation of llvm.
llvmOnce [_toolchainEnd]sync.Once
)
func (t Toolchain) newLibclc() (pkg.Artifact, string) {
return t.NewPackage("libclc", llvmVersion, t.Load(llvmSource), nil, &CMakeHelper{
Append: []string{"libclc"},
// NewLLVM returns LLVM toolchain across multiple [pkg.Artifact].
func (t Toolchain) NewLLVM() (musl, compilerRT, runtimes, clang pkg.Artifact) {
llvmOnce[t].Do(func() {
llvm[t][0], llvm[t][1], llvm[t][2], llvm[t][3] = t.newLLVM()
})
return llvm[t][0], llvm[t][1], llvm[t][2], llvm[t][3]
Cache: []KV{
{"CMAKE_BUILD_TYPE", "Release"},
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
{"LIBCLC_TARGETS_TO_BUILD", "all"},
},
Script: "ninja " + jobsFlagE + " test",
}), llvmVersion
}
func init() {
artifactsM[Libclc] = Metadata{
f: Toolchain.newLibclc,
Name: "libclc",
Description: "an open source, BSD/MIT dual licensed implementation of the library requirements of the OpenCL C programming language",
Website: "https://libclc.llvm.org/",
}
}

View File

@@ -1,4 +0,0 @@
package rosa
// clangPatches are patches applied to the LLVM source tree for building clang.
var clangPatches []KV

View File

@@ -1,12 +0,0 @@
package rosa
// clangPatches are patches applied to the LLVM source tree for building clang.
var clangPatches []KV
// one version behind, latest fails 5 tests with 2 flaky on arm64
const (
llvmVersionMajor = "21"
llvmVersion = llvmVersionMajor + ".1.8"
llvmChecksum = "8SUpqDkcgwOPsqHVtmf9kXfFeVmjVxl4LMn-qSE1AI_Xoeju-9HaoPNGtidyxyka"
)

View File

@@ -1,11 +1,9 @@
//go:build !arm64
package rosa
// latest version of LLVM, conditional to temporarily avoid broken new releases
const (
llvmVersionMajor = "22"
llvmVersion = llvmVersionMajor + ".1.2"
llvmVersion = llvmVersionMajor + ".1.3"
llvmChecksum = "FwsmurWDVyYYQlOowowFjekwIGSB5__aKTpW_VGP3eWoZGXvBny-bOn1DuQ1U5xE"
llvmChecksum = "CUwnpzua_y28HZ9oI0NmcKL2wClsSjFpgY9do5-7cCZJHI5KNF64vfwGvY0TYyR3"
)

View File

@@ -0,0 +1,191 @@
package rosa
// llvmPatches are centralised patches against latest LLVM monorepo.
var llvmPatches = []KV{
{"increase-stack-size-unconditional", `diff --git a/llvm/lib/Support/Threading.cpp b/llvm/lib/Support/Threading.cpp
index 9da357a7ebb9..b2931510c1ae 100644
--- a/llvm/lib/Support/Threading.cpp
+++ b/llvm/lib/Support/Threading.cpp
@@ -80,7 +80,7 @@ unsigned llvm::ThreadPoolStrategy::compute_thread_count() const {
// keyword.
#include "llvm/Support/thread.h"
-#if defined(__APPLE__)
+#if defined(__APPLE__) || 1
// Darwin's default stack size for threads except the main one is only 512KB,
// which is not enough for some/many normal LLVM compilations. This implements
// the same interface as std::thread but requests the same stack size as the
`},
{"add-rosa-vendor", `diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index 9c83abeeb3b1..5acfe5836a23 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -190,6 +190,7 @@ public:
Apple,
PC,
+ Rosa,
SCEI,
Freescale,
IBM,
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index a4f9dd42c0fe..cb5a12387034 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -279,6 +279,7 @@ StringRef Triple::getVendorTypeName(VendorType Kind) {
case NVIDIA: return "nvidia";
case OpenEmbedded: return "oe";
case PC: return "pc";
+ case Rosa: return "rosa";
case SCEI: return "scei";
case SUSE: return "suse";
case Meta:
@@ -689,6 +690,7 @@ static Triple::VendorType parseVendor(StringRef VendorName) {
return StringSwitch<Triple::VendorType>(VendorName)
.Case("apple", Triple::Apple)
.Case("pc", Triple::PC)
+ .Case("rosa", Triple::Rosa)
.Case("scei", Triple::SCEI)
.Case("sie", Triple::SCEI)
.Case("fsl", Triple::Freescale)
`},
{"xfail-broken-tests", `diff --git a/clang/test/Modules/timestamps.c b/clang/test/Modules/timestamps.c
index 50fdce630255..4b4465a75617 100644
--- a/clang/test/Modules/timestamps.c
+++ b/clang/test/Modules/timestamps.c
@@ -1,3 +1,5 @@
+// XFAIL: target={{.*-rosa-linux-musl}}
+
/// Verify timestamps that gets embedded in the module
#include <c-header.h>
`},
{"path-system-include", `diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index 8ac8d4eb9181..e46b04a898ca 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -671,6 +671,12 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
addExternCSystemInclude(
DriverArgs, CC1Args,
concat(SysRoot, "/usr/include", MultiarchIncludeDir));
+ if (!MultiarchIncludeDir.empty() &&
+ D.getVFS().exists(concat(SysRoot, "/system/include", MultiarchIncludeDir)))
+ addExternCSystemInclude(
+ DriverArgs, CC1Args,
+ concat(SysRoot, "/system/include", MultiarchIncludeDir));
+
if (getTriple().getOS() == llvm::Triple::RTEMS)
return;
@@ -681,6 +687,7 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
addExternCSystemInclude(DriverArgs, CC1Args, concat(SysRoot, "/include"));
addExternCSystemInclude(DriverArgs, CC1Args, concat(SysRoot, "/usr/include"));
+ addExternCSystemInclude(DriverArgs, CC1Args, concat(SysRoot, "/system/include"));
if (!DriverArgs.hasArg(options::OPT_nobuiltininc) && getTriple().isMusl())
addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
`},
{"path-system-libraries", `diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index 8ac8d4eb9181..f4d1347ab64d 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -282,6 +282,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
const bool IsHexagon = Arch == llvm::Triple::hexagon;
const bool IsRISCV = Triple.isRISCV();
const bool IsCSKY = Triple.isCSKY();
+ const bool IsRosa = Triple.getVendor() == llvm::Triple::Rosa;
if (IsCSKY && !SelectedMultilibs.empty())
SysRoot = SysRoot + SelectedMultilibs.back().osSuffix();
@@ -318,12 +319,23 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
const std::string OSLibDir = std::string(getOSLibDir(Triple, Args));
const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot);
+ if (IsRosa) {
+ ExtraOpts.push_back("-rpath");
+ ExtraOpts.push_back("/system/lib");
+ ExtraOpts.push_back("-rpath");
+ ExtraOpts.push_back(concat("/system/lib", MultiarchTriple));
+ }
+
// mips32: Debian multilib, we use /libo32, while in other case, /lib is
// used. We need add both libo32 and /lib.
if (Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel) {
Generic_GCC::AddMultilibPaths(D, SysRoot, "libo32", MultiarchTriple, Paths);
- addPathIfExists(D, concat(SysRoot, "/libo32"), Paths);
- addPathIfExists(D, concat(SysRoot, "/usr/libo32"), Paths);
+ if (!IsRosa) {
+ addPathIfExists(D, concat(SysRoot, "/libo32"), Paths);
+ addPathIfExists(D, concat(SysRoot, "/usr/libo32"), Paths);
+ } else {
+ addPathIfExists(D, concat(SysRoot, "/system/libo32"), Paths);
+ }
}
Generic_GCC::AddMultilibPaths(D, SysRoot, OSLibDir, MultiarchTriple, Paths);
@@ -341,18 +353,30 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
Paths);
}
- addPathIfExists(D, concat(SysRoot, "/usr/lib", MultiarchTriple), Paths);
- addPathIfExists(D, concat(SysRoot, "/usr", OSLibDir), Paths);
+ if (!IsRosa) {
+ addPathIfExists(D, concat(SysRoot, "/usr/lib", MultiarchTriple), Paths);
+ addPathIfExists(D, concat(SysRoot, "/usr", OSLibDir), Paths);
+ } else {
+ addPathIfExists(D, concat(SysRoot, "/system/lib", MultiarchTriple), Paths);
+ addPathIfExists(D, concat(SysRoot, "/system", OSLibDir), Paths);
+ }
if (IsRISCV) {
StringRef ABIName = tools::riscv::getRISCVABI(Args, Triple);
addPathIfExists(D, concat(SysRoot, "/", OSLibDir, ABIName), Paths);
- addPathIfExists(D, concat(SysRoot, "/usr", OSLibDir, ABIName), Paths);
+ if (!IsRosa)
+ addPathIfExists(D, concat(SysRoot, "/usr", OSLibDir, ABIName), Paths);
+ else
+ addPathIfExists(D, concat(SysRoot, "/system", OSLibDir, ABIName), Paths);
}
Generic_GCC::AddMultiarchPaths(D, SysRoot, OSLibDir, Paths);
- addPathIfExists(D, concat(SysRoot, "/lib"), Paths);
- addPathIfExists(D, concat(SysRoot, "/usr/lib"), Paths);
+ if (!IsRosa) {
+ addPathIfExists(D, concat(SysRoot, "/lib"), Paths);
+ addPathIfExists(D, concat(SysRoot, "/usr/lib"), Paths);
+ } else {
+ addPathIfExists(D, concat(SysRoot, "/system/lib"), Paths);
+ }
}
ToolChain::RuntimeLibType Linux::GetDefaultRuntimeLibType() const {
@@ -457,6 +481,9 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
return Triple.isArch64Bit() ? "/system/bin/linker64" : "/system/bin/linker";
}
if (Triple.isMusl()) {
+ if (Triple.getVendor() == llvm::Triple::Rosa)
+ return "/system/bin/linker";
+
std::string ArchName;
bool IsArm = false;
diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp
index 64324a3f8b01..15ce70b68217 100644
--- a/clang/tools/clang-installapi/Options.cpp
+++ b/clang/tools/clang-installapi/Options.cpp
@@ -515,7 +515,7 @@ bool Options::processFrontendOptions(InputArgList &Args) {
FEOpts.FwkPaths = std::move(FrameworkPaths);
// Add default framework/library paths.
- PathSeq DefaultLibraryPaths = {"/usr/lib", "/usr/local/lib"};
+ PathSeq DefaultLibraryPaths = {"/usr/lib", "/system/lib", "/usr/local/lib"};
PathSeq DefaultFrameworkPaths = {"/Library/Frameworks",
"/System/Library/Frameworks"};
`},
}

View File

@@ -1,4 +0,0 @@
package rosa
// clangPatches are patches applied to the LLVM source tree for building clang.
var clangPatches []KV

View File

@@ -20,9 +20,9 @@ cd "$(mktemp -d)"
--disable-dependency-tracking
./build.sh
./make DESTDIR=/work install check
`, pkg.Path(AbsUsrSrc.Append("make"), false, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/make/make-"+version+".tar.gz",
mustDecode(checksum),
`, pkg.Path(AbsUsrSrc.Append("make"), false, newTar(
"https://ftpmirror.gnu.org/gnu/make/make-"+version+".tar.gz",
checksum,
pkg.TarGzip,
))), version
}
@@ -78,11 +78,6 @@ type MakeHelper struct {
var _ Helper = new(MakeHelper)
// name returns its arguments joined with '-'.
func (*MakeHelper) name(name, version string) string {
return name + "-" + version
}
// extra returns make and other optional dependencies.
func (attr *MakeHelper) extra(flag int) P {
extra := P{Make}
@@ -176,7 +171,10 @@ func (attr *MakeHelper) script(name string) string {
s = "-" + s
}
if v[1] != "" {
s += "=" + v[1]
if v[0] != "" {
s += "="
}
s += v[1]
}
if !yield(s) {
return
@@ -190,7 +188,7 @@ func (attr *MakeHelper) script(name string) string {
scriptMake := `
make \
"-j$(nproc)"`
` + jobsFlagE
if len(attr.Make) > 0 {
scriptMake += " \\\n\t" + strings.Join(attr.Make, " \\\n\t")
}
@@ -198,7 +196,7 @@ make \
if !attr.SkipCheck {
scriptMake += attr.ScriptCheckEarly + `make \
"-j$(nproc)" \
` + jobsFlagE + ` \
`
if len(attr.Check) > 0 {
scriptMake += strings.Join(attr.Check, " \\\n\t")

66
internal/rosa/mesa.go Normal file
View File

@@ -0,0 +1,66 @@
package rosa
import "hakurei.app/internal/pkg"
func (t Toolchain) newLibglvnd() (pkg.Artifact, string) {
const (
version = "1.7.0"
checksum = "eIQJK2sgFQDHdeFkQO87TrSUaZRFG4y2DrwA8Ut-sGboI59uw1OOiIVqq2AIwnGY"
)
return t.NewPackage("libglvnd", version, newFromGitLab(
"gitlab.freedesktop.org",
"glvnd/libglvnd",
"v"+version,
checksum,
), nil, (*MesonHelper)(nil),
Binutils, // symbols check fail with llvm nm
), version
}
func init() {
artifactsM[Libglvnd] = Metadata{
f: Toolchain.newLibglvnd,
Name: "libglvnd",
Description: "The GL Vendor-Neutral Dispatch library",
Website: "https://gitlab.freedesktop.org/glvnd/libglvnd",
ID: 12098,
}
}
func (t Toolchain) newLibdrm() (pkg.Artifact, string) {
const (
version = "2.4.131"
checksum = "riHPSpvTnvCPbR-iT4jt7_X-z4rpwm6oNh9ZN2zP6RBFkFVxBRKmedG4eEXSADIh"
)
return t.NewPackage("libdrm", version, newFromGitLab(
"gitlab.freedesktop.org",
"mesa/libdrm",
"libdrm-"+version,
checksum,
), nil, &MesonHelper{
Setup: []KV{
{"Dintel", "enabled"},
},
},
Binutils, // symbols check fail with llvm nm
Libpciaccess,
KernelHeaders,
), version
}
func init() {
artifactsM[Libdrm] = Metadata{
f: Toolchain.newLibdrm,
Name: "libdrm",
Description: "a userspace library for accessing the DRM",
Website: "https://dri.freedesktop.org/",
Dependencies: P{
Libpciaccess,
},
ID: 1596,
}
}

View File

@@ -9,8 +9,8 @@ import (
func (t Toolchain) newMeson() (pkg.Artifact, string) {
const (
version = "1.10.2"
checksum = "18VmKUVKuXCwtawkYCeYHseC3cKpi86OhnIPaV878wjY0rkXH8XnQwUyymnxFgcl"
version = "1.11.0"
checksum = "b7oo3U_cklhzsTfsyYsjPGyeEufiS-Pm06JPLzodseS125Ach62ZBly7R6dSDiAc"
)
return t.New("meson-"+version, 0, []pkg.Artifact{
t.Load(Zlib),
@@ -23,10 +23,11 @@ python3 setup.py \
install \
--prefix=/system \
--root=/work
`, pkg.Path(AbsUsrSrc.Append("meson"), true, pkg.NewHTTPGetTar(
nil, "https://github.com/mesonbuild/meson/releases/download/"+
version+"/meson-"+version+".tar.gz",
mustDecode(checksum),
`, pkg.Path(AbsUsrSrc.Append("meson"), true, newFromGitHubRelease(
"mesonbuild/meson",
version,
"meson-"+version+".tar.gz",
checksum,
pkg.TarGzip,
))), version
}
@@ -66,11 +67,6 @@ type MesonHelper struct {
var _ Helper = new(MesonHelper)
// name returns its arguments joined with '-'.
func (*MesonHelper) name(name, version string) string {
return name + "-" + version
}
// extra returns hardcoded meson runtime dependencies.
func (*MesonHelper) extra(int) P { return P{Meson} }

View File

@@ -26,10 +26,9 @@ cp -v lksh /work/system/bin/sh
mkdir -p /work/bin/
ln -vs ../system/bin/sh /work/bin/
`, pkg.Path(AbsUsrSrc.Append("mksh"), false, pkg.NewHTTPGetTar(
nil,
`, pkg.Path(AbsUsrSrc.Append("mksh"), false, newTar(
"https://mbsd.evolvis.org/MirOS/dist/mir/mksh/mksh-R"+version+".tgz",
mustDecode(checksum),
checksum,
pkg.TarGzip,
))), version
}

View File

@@ -7,11 +7,10 @@ func (t Toolchain) newMuslFts() (pkg.Artifact, string) {
version = "1.2.7"
checksum = "N_p_ZApX3eHt7xoDCw1hLf6XdJOw7ZSx7xPvpvAP0knG2zgU0zeN5w8tt5Pg60XJ"
)
return t.NewPackage("musl-fts", version, pkg.NewHTTPGetTar(
nil, "https://github.com/void-linux/musl-fts/archive/refs/tags/"+
"v"+version+".tar.gz",
mustDecode(checksum),
pkg.TarGzip,
return t.NewPackage("musl-fts", version, newFromGitHub(
"void-linux/musl-fts",
"v"+version,
checksum,
), &PackageAttr{
Env: []string{
"CC=cc -fPIC",

View File

@@ -7,11 +7,10 @@ func (t Toolchain) newMuslObstack() (pkg.Artifact, string) {
version = "1.2.3"
checksum = "tVRY_KjIlkkMszcaRlkKdBVQHIXTT_T_TiMxbwErlILXrOBosocg8KklppZhNdCG"
)
return t.NewPackage("musl-obstack", version, pkg.NewHTTPGetTar(
nil, "https://github.com/void-linux/musl-obstack/archive/refs/tags/"+
"v"+version+".tar.gz",
mustDecode(checksum),
pkg.TarGzip,
return t.NewPackage("musl-obstack", version, newFromGitHub(
"void-linux/musl-obstack",
"v"+version,
checksum,
), &PackageAttr{
Env: []string{
"CC=cc -fPIC",

View File

@@ -4,7 +4,6 @@ import "hakurei.app/internal/pkg"
func (t Toolchain) newMusl(
headers bool,
env []string,
extra ...pkg.Artifact,
) (pkg.Artifact, string) {
const (
@@ -37,9 +36,9 @@ rmdir -v /work/lib
helper.Script = ""
}
return t.NewPackage(name, version, pkg.NewHTTPGetTar(
nil, "https://musl.libc.org/releases/musl-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage(name, version, newTar(
"https://musl.libc.org/releases/musl-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), &PackageAttr{
NonStage0: extra,
@@ -47,7 +46,15 @@ rmdir -v /work/lib
// expected to be writable in copies
Chmod: true,
Env: env,
Env: stage0ExclConcat(t, []string{
"CC=clang",
"LIBCC=/system/lib/clang/" + llvmVersionMajor + "/lib/" +
triplet() + "/libclang_rt.builtins.a",
"AR=ar",
"RANLIB=ranlib",
},
"LDFLAGS="+earlyLDFLAGS(false),
),
}, &helper,
Coreutils,
), version
@@ -55,7 +62,7 @@ rmdir -v /work/lib
func init() {
artifactsM[Musl] = Metadata{
f: func(t Toolchain) (pkg.Artifact, string) {
return t.newMusl(false, nil)
return t.newMusl(false, t.Load(CompilerRT))
},
Name: "musl",

View File

@@ -7,9 +7,9 @@ func (t Toolchain) newNcurses() (pkg.Artifact, string) {
version = "6.6"
checksum = "XvWp4xi6hR_hH8XUoGY26L_pqBSDapJYulhzZqPuR0KNklqypqNc1yNXU-nOjf5w"
)
return t.NewPackage("ncurses", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/ncurses/ncurses-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("ncurses", version, newTar(
"https://ftpmirror.gnu.org/gnu/ncurses/ncurses-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), nil, &MakeHelper{
// "tests" are actual demo programs, not a test suite.

View File

@@ -7,10 +7,10 @@ func (t Toolchain) newLibmnl() (pkg.Artifact, string) {
version = "1.0.5"
checksum = "DN-vbbvQDpxXJm0TJ6xlluILvfrB86avrCTX50XyE9SEFSAZ_o8nuKc5Gu0Am7-u"
)
return t.NewPackage("libmnl", version, pkg.NewHTTPGetTar(
nil, "https://www.netfilter.org/projects/libmnl/files/"+
return t.NewPackage("libmnl", version, newTar(
"https://www.netfilter.org/projects/libmnl/files/"+
"libmnl-"+version+".tar.bz2",
mustDecode(checksum),
checksum,
pkg.TarBzip2,
), &PackageAttr{
Patches: []KV{
@@ -55,10 +55,9 @@ func (t Toolchain) newLibnftnl() (pkg.Artifact, string) {
version = "1.3.1"
checksum = "91ou66K-I17iX6DB6hiQkhhC_v4DFW5iDGzwjVRNbJNEmKqowLZBlh3FY-ZDO0r9"
)
return t.NewPackage("libnftnl", version, t.NewViaGit(
return t.NewPackage("libnftnl", version, t.newTagRemote(
"https://git.netfilter.org/libnftnl",
"refs/tags/libnftnl-"+version,
mustDecode(checksum),
"libnftnl-"+version, checksum,
), &PackageAttr{
Env: []string{
"CFLAGS=-D_GNU_SOURCE",
@@ -98,10 +97,9 @@ func (t Toolchain) newIPTables() (pkg.Artifact, string) {
version = "1.8.13"
checksum = "TUA-cFIAsiMvtRR-XzQvXzoIhJUOc9J2gQDJCbBRjmgmVfGfPTCf58wL7e-cUKVQ"
)
return t.NewPackage("iptables", version, t.NewViaGit(
return t.NewPackage("iptables", version, t.newTagRemote(
"https://git.netfilter.org/iptables",
"refs/tags/v"+version,
mustDecode(checksum),
"v"+version, checksum,
), &PackageAttr{
ScriptEarly: `
rm \

View File

@@ -7,9 +7,9 @@ func (t Toolchain) newNettle() (pkg.Artifact, string) {
version = "4.0"
checksum = "6agC-vHzzoqAlaX3K9tX8yHgrm03HLqPZzVzq8jh_ePbuPMIvpxereu_uRJFmQK7"
)
return t.NewPackage("nettle", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/nettle/nettle-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("nettle", version, newTar(
"https://ftpmirror.gnu.org/gnu/nettle/nettle-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), nil, (*MakeHelper)(nil),
M4,

View File

@@ -7,9 +7,9 @@ func (t Toolchain) newNettle3() (pkg.Artifact, string) {
version = "3.10.2"
checksum = "07aXlj10X5llf67jIqRQAA1pgLSgb0w_JYggZVPuKNoc-B-_usb5Kr8FrfBe7g1S"
)
return t.NewPackage("nettle", version, pkg.NewHTTPGetTar(
nil, "https://ftpmirror.gnu.org/gnu/nettle/nettle-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("nettle", version, newTar(
"https://ftpmirror.gnu.org/gnu/nettle/nettle-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), nil, (*MakeHelper)(nil),
M4,

View File

@@ -13,25 +13,26 @@ func (t Toolchain) newNinja() (pkg.Artifact, string) {
}, nil, nil, `
cd "$(mktemp -d)"
python3 /usr/src/ninja/configure.py \
--verbose \
--bootstrap \
--gtest-source-dir=/usr/src/googletest
./ninja all
./ninja `+jobsFlagE+` all
./ninja_test
mkdir -p /work/system/bin/
cp ninja /work/system/bin/
`, pkg.Path(AbsUsrSrc.Append("googletest"), false,
pkg.NewHTTPGetTar(
nil, "https://github.com/google/googletest/releases/download/"+
"v1.16.0/googletest-1.16.0.tar.gz",
mustDecode("NjLGvSbgPy_B-y-o1hdanlzEzaYeStFcvFGxpYV3KYlhrWWFRcugYhM3ZMzOA9B_"),
newFromGitHubRelease(
"google/googletest",
"v1.16.0",
"googletest-1.16.0.tar.gz",
"NjLGvSbgPy_B-y-o1hdanlzEzaYeStFcvFGxpYV3KYlhrWWFRcugYhM3ZMzOA9B_",
pkg.TarGzip,
)), pkg.Path(AbsUsrSrc.Append("ninja"), true, t.NewPatchedSource(
"ninja", version, pkg.NewHTTPGetTar(
nil, "https://github.com/ninja-build/ninja/archive/refs/tags/"+
"v"+version+".tar.gz",
mustDecode(checksum),
pkg.TarGzip,
"ninja", version, newFromGitHub(
"ninja-build/ninja",
"v"+version,
checksum,
), false,
))), version
}

View File

@@ -8,17 +8,16 @@ import (
func (t Toolchain) newNSS() (pkg.Artifact, string) {
const (
version = "3.122"
checksum = "QvC6TBO4BAUEh6wmgUrb1hwH5podQAN-QdcAaWL32cWEppmZs6oKkZpD9GvZf59S"
version = "3.122.1"
checksum = "DyKZJj-Dkkx874rY8vNE59fXpwQfeJt7M1XcCinnNJIAK856FTFvuFYA0TwdMVCK"
version0 = "4_38_2"
checksum0 = "25x2uJeQnOHIiq_zj17b4sYqKgeoU8-IsySUptoPcdHZ52PohFZfGuIisBreWzx0"
)
return t.NewPackage("nss", version, pkg.NewHTTPGetTar(
nil, "https://github.com/nss-dev/nss/archive/refs/tags/"+
"NSS_"+strings.Join(strings.SplitN(version, ".", 2), "_")+"_RTM.tar.gz",
mustDecode(checksum),
pkg.TarGzip,
return t.NewPackage("nss", version, newFromGitHub(
"nss-dev/nss",
"NSS_"+strings.Join(strings.SplitN(version, ".", 3), "_")+"_RTM",
checksum,
), &PackageAttr{
Paths: []pkg.ExecPath{
pkg.Path(AbsUsrSrc.Append("nspr.zip"), false, pkg.NewHTTPGet(
@@ -83,16 +82,30 @@ func init() {
}
}
func init() {
const version = "0.4.0"
artifactsM[buildcatrust] = newViaPip(
"buildcatrust",
"transform certificate stores between formats",
version, "py3", "none", "any",
"k_FGzkRCLjbTWBkuBLzQJ1S8FPAz19neJZlMHm0t10F2Y0hElmvVwdSBRc03Rjo1",
"https://github.com/nix-community/buildcatrust/"+
"releases/download/v"+version+"/",
func (t Toolchain) newBuildCATrust() (pkg.Artifact, string) {
const (
version = "0.5.1"
checksum = "g9AqIksz-hvCUceSR7ZKwfqf8Y_UsJU_3_zLUIdc4IkxFVkgdv9kKVvhFjE4s1-7"
)
return t.newViaPip("buildcatrust", version,
"https://github.com/nix-community/buildcatrust/releases/"+
"download/v"+version+"/buildcatrust-"+version+"-py3-none-any.whl",
checksum), version
}
func init() {
artifactsM[buildcatrust] = Metadata{
f: Toolchain.newBuildCATrust,
Name: "buildcatrust",
Description: "transform certificate stores between formats",
Website: "https://github.com/nix-community/buildcatrust",
Dependencies: P{
Python,
},
ID: 233988,
}
}
func (t Toolchain) newNSSCACert() (pkg.Artifact, string) {

View File

@@ -4,13 +4,14 @@ import "hakurei.app/internal/pkg"
func (t Toolchain) newOpenSSL() (pkg.Artifact, string) {
const (
version = "3.6.1"
checksum = "boMAj2SIVIFXHswZva3qHJuFEpc32rxCCu07wjMPsVe9nn_976BGMmW_5P1zthgg"
version = "3.6.2"
checksum = "jH004dXTiE01Hp0kyShkWXwrSHEksZi4i_3v47D9H9Uz9LQ1aMwF7mrl2Tb4t_XA"
)
return t.NewPackage("openssl", version, pkg.NewHTTPGetTar(
nil, "https://github.com/openssl/openssl/releases/download/"+
"openssl-"+version+"/openssl-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("openssl", version, newFromGitHubRelease(
"openssl/openssl",
"openssl-"+version,
"openssl-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), &PackageAttr{
Env: []string{
@@ -24,9 +25,10 @@ func (t Toolchain) newOpenSSL() (pkg.Artifact, string) {
{"prefix", "/system"},
{"libdir", "lib"},
{"openssldir", "etc/ssl"},
{"", "no-docs"},
},
Check: []string{
`HARNESS_JOBS="$(expr "$(nproc)" '*' 2)"`,
"HARNESS_JOBS=" + jobsE,
"test",
},
},

View File

@@ -7,9 +7,9 @@ func (t Toolchain) newP11Kit() (pkg.Artifact, string) {
version = "0.26.2"
checksum = "3ei-6DUVtYzrRVe-SubtNgRlweXd6H2qHmUu-_5qVyIn6gSTvZbGS2u79Y8IFb2N"
)
return t.NewPackage("p11-kit", version, t.NewViaGit(
return t.NewPackage("p11-kit", version, t.newTagRemote(
"https://github.com/p11-glue/p11-kit.git",
"refs/tags/"+version, mustDecode(checksum),
version, checksum,
), nil, &MesonHelper{
Setup: []KV{
{"Dsystemd", "disabled"},

View File

@@ -9,10 +9,11 @@ func (t Toolchain) newPCRE2() (pkg.Artifact, string) {
version = "10.47"
checksum = "IbC24vVayju6nB9EhrBPSDexk22wDecdpyrjgC3nCZXkwTnUjq4CD2q5sopqu6CW"
)
return t.NewPackage("pcre2", version, pkg.NewHTTPGetTar(
nil, "https://github.com/PCRE2Project/pcre2/releases/download/"+
"pcre2-"+version+"/pcre2-"+version+".tar.bz2",
mustDecode(checksum),
return t.NewPackage("pcre2", version, newFromGitHubRelease(
"PCRE2Project/pcre2",
"pcre2-"+version,
"pcre2-"+version+".tar.bz2",
checksum,
pkg.TarBzip2,
), &PackageAttr{
ScriptEarly: `

View File

@@ -2,6 +2,7 @@ package rosa
import (
"slices"
"strings"
"hakurei.app/internal/pkg"
)
@@ -11,9 +12,9 @@ func (t Toolchain) newPerl() (pkg.Artifact, string) {
version = "5.42.2"
checksum = "Me_xFfgkRnVyG0sE6a74TktK2OUq9Z1LVJNEu_9RdZG3S2fbjfzNiuk2SJqHAgbm"
)
return t.NewPackage("perl", version, pkg.NewHTTPGetTar(
nil, "https://www.cpan.org/src/5.0/perl-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("perl", version, newTar(
"https://www.cpan.org/src/5.0/perl-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), &PackageAttr{
// uses source tree as scratch space
@@ -42,7 +43,7 @@ rm -f /system/bin/ps # perl does not like toybox ps
{"Duseshrplib"},
},
Check: []string{
"TEST_JOBS=256",
"TEST_JOBS=" + jobsLE,
"test_harness",
},
Install: `LD_LIBRARY_PATH="$PWD" ./perl -Ilib -I. installperl --destdir=/work`,
@@ -91,10 +92,10 @@ func (t Toolchain) newPerlModuleBuild() (pkg.Artifact, string) {
version = "0.4234"
checksum = "ZKxEFG4hE1rqZt52zBL2LRZBMkYzhjb5-cTBXcsyA52EbPeeYyVxU176yAea8-Di"
)
return t.newViaPerlModuleBuild("Module-Build", version, pkg.NewHTTPGetTar(
nil, "https://cpan.metacpan.org/authors/id/L/LE/LEONT/"+
return t.newViaPerlModuleBuild("Module-Build", version, newTar(
"https://cpan.metacpan.org/authors/id/L/LE/LEONT/"+
"Module-Build-"+version+".tar.gz",
mustDecode(checksum),
checksum,
pkg.TarGzip,
), nil), version
}
@@ -145,11 +146,11 @@ func (t Toolchain) newPerlLocaleGettext() (pkg.Artifact, string) {
version = "1.07"
checksum = "cFq4BKFD1MWSoa7lsrPjpdo9kzPqd0jlRcBFUyL1L1isw8m3D_Sge_ff0MAu_9J3"
)
return t.newViaPerlMakeMaker("Locale::gettext", version, pkg.NewHTTPGetTar(
nil, "https://cpan.metacpan.org/authors/id/P/PV/PVANDRY/"+
"Locale-gettext-"+version+".tar.gz",
mustDecode(checksum),
pkg.TarGzip,
return t.newViaPerlMakeMaker("Locale::gettext", version, newFromCPAN(
"PVANDRY",
"Locale-gettext",
version,
checksum,
), nil), version
}
func init() {
@@ -159,6 +160,8 @@ func init() {
Name: "perl-Locale::gettext",
Description: "message handling functions",
Website: "https://metacpan.org/release/Locale-gettext",
ID: 7523,
}
}
@@ -167,11 +170,11 @@ func (t Toolchain) newPerlPodParser() (pkg.Artifact, string) {
version = "1.67"
checksum = "RdURu9mOfExk_loCp6abxlcQV3FycSNbTqhRS9i6JUqnYfGGEgercK30g0gjYyqe"
)
return t.newViaPerlMakeMaker("Pod::Parser", version, pkg.NewHTTPGetTar(
nil, "https://cpan.metacpan.org/authors/id/M/MA/MAREKR/"+
"Pod-Parser-"+version+".tar.gz",
mustDecode(checksum),
pkg.TarGzip,
return t.newViaPerlMakeMaker("Pod::Parser", version, newFromCPAN(
"MAREKR",
"Pod-Parser",
version,
checksum,
), nil), version
}
func init() {
@@ -181,6 +184,8 @@ func init() {
Name: "perl-Pod::Parser",
Description: "base class for creating POD filters and translators",
Website: "https://metacpan.org/release/Pod-Parser",
ID: 3244,
}
}
@@ -189,11 +194,11 @@ func (t Toolchain) newPerlSGMLS() (pkg.Artifact, string) {
version = "1.1"
checksum = "aZijn4MUqD-wfyZgdcCruCwl4SgDdu25cNmJ4_UvdAk9a7uz4gzMQdoeB6DQ6QOy"
)
return t.newViaPerlMakeMaker("SGMLS", version, pkg.NewHTTPGetTar(
nil, "https://cpan.metacpan.org/authors/id/R/RA/RAAB/"+
"SGMLSpm-"+version+".tar.gz",
mustDecode(checksum),
pkg.TarGzip,
return t.newViaPerlMakeMaker("SGMLS", version, newFromCPAN(
"RAAB",
"SGMLSpm",
version,
checksum,
), nil), version
}
func init() {
@@ -203,6 +208,22 @@ func init() {
Name: "perl-SGMLS",
Description: "class for postprocessing the output from the sgmls and nsgmls parsers",
Website: "https://metacpan.org/release/RAAB/SGMLSpm-1.1",
ID: 389576,
latest: func(v *Versions) string {
for _, s := range v.Stable {
_, m, ok := strings.Cut(s, ".")
if !ok {
continue
}
if len(m) > 1 && m[0] == '0' {
continue
}
return s
}
return v.Latest
},
}
}
@@ -211,11 +232,11 @@ func (t Toolchain) newPerlTermReadKey() (pkg.Artifact, string) {
version = "2.38"
checksum = "qerL8Xo7kD0f42PZoiEbmE8Roc_S9pOa27LXelY4DN_0UNy_u5wLrGHI8utNlaiI"
)
return t.newViaPerlMakeMaker("Term::ReadKey", version, pkg.NewHTTPGetTar(
nil, "https://cpan.metacpan.org/authors/id/J/JS/JSTOWE/"+
"TermReadKey-"+version+".tar.gz",
mustDecode(checksum),
pkg.TarGzip,
return t.newViaPerlMakeMaker("Term::ReadKey", version, newFromCPAN(
"JSTOWE",
"TermReadKey",
version,
checksum,
), nil), version
}
func init() {
@@ -225,6 +246,8 @@ func init() {
Name: "perl-Term::ReadKey",
Description: "a perl module for simple terminal control",
Website: "https://metacpan.org/release/TermReadKey",
ID: 3372,
}
}
@@ -233,11 +256,11 @@ func (t Toolchain) newPerlTextCharWidth() (pkg.Artifact, string) {
version = "0.04"
checksum = "G2p5RHU4_HiZ23ZusBA_enTlVMxz0J4esUx4CGcOPhY6xYTbp-aXWRN6lYZpzBw2"
)
return t.newViaPerlMakeMaker("Text::CharWidth", version, pkg.NewHTTPGetTar(
nil, "https://cpan.metacpan.org/authors/id/K/KU/KUBOTA/"+
"Text-CharWidth-"+version+".tar.gz",
mustDecode(checksum),
pkg.TarGzip,
return t.newViaPerlMakeMaker("Text::CharWidth", version, newFromCPAN(
"KUBOTA",
"Text-CharWidth",
version,
checksum,
), nil), version
}
func init() {
@@ -247,6 +270,8 @@ func init() {
Name: "perl-Text::CharWidth",
Description: "get number of occupied columns of a string on terminal",
Website: "https://metacpan.org/release/Text-CharWidth",
ID: 14380,
}
}
@@ -255,11 +280,11 @@ func (t Toolchain) newPerlTextWrapI18N() (pkg.Artifact, string) {
version = "0.06"
checksum = "Vmo89qLgxUqyQ6QmWJVqu60aQAUjrNKRjFQSXGnvClxofzRjiCa6idzPgJ4VkixM"
)
return t.newViaPerlMakeMaker("Text::WrapI18N", version, pkg.NewHTTPGetTar(
nil, "https://cpan.metacpan.org/authors/id/K/KU/KUBOTA/"+
"Text-WrapI18N-"+version+".tar.gz",
mustDecode(checksum),
pkg.TarGzip,
return t.newViaPerlMakeMaker("Text::WrapI18N", version, newFromCPAN(
"KUBOTA",
"Text-WrapI18N",
version,
checksum,
), nil,
PerlTextCharWidth,
), version
@@ -275,6 +300,8 @@ func init() {
Dependencies: P{
PerlTextCharWidth,
},
ID: 14385,
}
}
@@ -283,11 +310,11 @@ func (t Toolchain) newPerlMIMECharset() (pkg.Artifact, string) {
version = "1.013.1"
checksum = "Ou_ukcrOa1cgtE3mptinb-os3bdL1SXzbRDFZQF3prrJj-drc3rp_huay7iDLJol"
)
return t.newViaPerlMakeMaker("MIME::Charset", version, pkg.NewHTTPGetTar(
nil, "https://cpan.metacpan.org/authors/id/N/NE/NEZUMI/"+
"MIME-Charset-"+version+".tar.gz",
mustDecode(checksum),
pkg.TarGzip,
return t.newViaPerlMakeMaker("MIME::Charset", version, newFromCPAN(
"NEZUMI",
"MIME-Charset",
version,
checksum,
), nil), version
}
func init() {
@@ -297,34 +324,38 @@ func init() {
Name: "perl-MIME::Charset",
Description: "Charset Information for MIME",
Website: "https://metacpan.org/release/MIME-Charset",
ID: 3070,
}
}
func (t Toolchain) newPerlUnicodeGCString() (pkg.Artifact, string) {
func (t Toolchain) newPerlUnicodeLineBreak() (pkg.Artifact, string) {
const (
version = "2019.001"
checksum = "ZHVkh7EDgAUHnTpvXsnPAuWpgNoBImtY_9_8TIbo2co_WgUwEb0MtXPhI8pAZ5OH"
)
return t.newViaPerlMakeMaker("Unicode::GCString", version, pkg.NewHTTPGetTar(
nil, "https://cpan.metacpan.org/authors/id/N/NE/NEZUMI/"+
"Unicode-LineBreak-"+version+".tar.gz",
mustDecode(checksum),
pkg.TarGzip,
return t.newViaPerlMakeMaker("Unicode::LineBreak", version, newFromCPAN(
"NEZUMI",
"Unicode-LineBreak",
version,
checksum,
), nil,
PerlMIMECharset,
), version
}
func init() {
artifactsM[PerlUnicodeGCString] = Metadata{
f: Toolchain.newPerlUnicodeGCString,
artifactsM[PerlUnicodeLineBreak] = Metadata{
f: Toolchain.newPerlUnicodeLineBreak,
Name: "perl-Unicode::GCString",
Name: "perl-Unicode::LineBreak",
Description: "String as Sequence of UAX #29 Grapheme Clusters",
Website: "https://metacpan.org/release/Unicode-LineBreak",
Dependencies: P{
PerlMIMECharset,
},
ID: 6033,
}
}
@@ -333,11 +364,11 @@ func (t Toolchain) newPerlYAMLTiny() (pkg.Artifact, string) {
version = "1.76"
checksum = "V1MV4KPym1LxSw8CRXqPR3K-l1hGHbT5Ob4t-9xju6R9X_CWyw6hI8wsMaNdHdBY"
)
return t.newViaPerlMakeMaker("YAML::Tiny", version, pkg.NewHTTPGetTar(
nil, "https://cpan.metacpan.org/authors/id/E/ET/ETHER/"+
"YAML-Tiny-"+version+".tar.gz",
mustDecode(checksum),
pkg.TarGzip,
return t.newViaPerlMakeMaker("YAML::Tiny", version, newFromCPAN(
"ETHER",
"YAML-Tiny",
version,
checksum,
), nil), version
}
func init() {
@@ -347,5 +378,7 @@ func init() {
Name: "perl-YAML::Tiny",
Description: "read/write YAML files with as little code as possible",
Website: "https://metacpan.org/release/YAML-Tiny",
ID: 3549,
}
}

View File

@@ -7,11 +7,11 @@ func (t Toolchain) newPkgConfig() (pkg.Artifact, string) {
version = "0.29.2"
checksum = "6UsGqEMA8EER_5b9N0b32UCqiRy39B6_RnPfvuslWhtFV1qYD4DfS10crGZN_TP2"
)
return t.NewPackage("pkg-config", version, pkg.NewHTTPGetTar(
nil, "https://gitlab.freedesktop.org/pkg-config/pkg-config/-/archive"+
"/pkg-config-"+version+"/pkg-config-pkg-config-"+version+".tar.bz2",
mustDecode(checksum),
pkg.TarBzip2,
return t.NewPackage("pkg-config", version, newFromGitLab(
"gitlab.freedesktop.org",
"pkg-config/pkg-config",
"pkg-config-"+version,
checksum,
), nil, &MakeHelper{
Generate: "./autogen.sh --no-configure",
Configure: []KV{

View File

@@ -7,11 +7,11 @@ func (t Toolchain) newProcps() (pkg.Artifact, string) {
version = "4.0.6"
checksum = "pl_fZLvDlv6iZTkm8l_tHFpzTDVFGCiSJEs3eu0zAX6u36AV36P_En8K7JPScRWM"
)
return t.NewPackage("procps", version, pkg.NewHTTPGetTar(
nil, "https://gitlab.com/procps-ng/procps/-/archive/"+
"v"+version+"/procps-v"+version+".tar.bz2",
mustDecode(checksum),
pkg.TarBzip2,
return t.NewPackage("procps", version, newFromGitLab(
"gitlab.com",
"procps-ng/procps",
"v"+version,
checksum,
), nil, &MakeHelper{
Generate: "./autogen.sh",
Configure: []KV{

View File

@@ -1,6 +1,7 @@
package rosa
import (
"path"
"slices"
"strings"
@@ -9,13 +10,13 @@ import (
func (t Toolchain) newPython() (pkg.Artifact, string) {
const (
version = "3.14.3"
checksum = "ajEC32WPmn9Jvll0n4gGvlTvhMPUHb2H_j5_h9jf_esHmkZBRfAumDcKY7nTTsCH"
version = "3.14.4"
checksum = "X0VRAAGOlCVldh4J9tRAE-YrJtDvqfQTJaqxKPXNX6YTPlwpR9GwA5WRIZDO-63s"
)
return t.NewPackage("python", version, pkg.NewHTTPGetTar(
nil, "https://www.python.org/ftp/python/"+version+
return t.NewPackage("python", version, newTar(
"https://www.python.org/ftp/python/"+version+
"/Python-"+version+".tgz",
mustDecode(checksum),
checksum,
pkg.TarGzip,
), &PackageAttr{
// test_synopsis_sourceless assumes this is writable and checks __pycache__
@@ -80,26 +81,42 @@ func init() {
}
}
// newViaPip is a helper for installing python dependencies via pip.
func newViaPip(
name, description, version, interpreter, abi, platform, checksum, prefix string,
// newViaPip installs a pip wheel from a url.
func (t Toolchain) newViaPip(
name, version, url, checksum string,
extra ...PArtifact,
) Metadata {
wname := name + "-" + version + "-" + interpreter + "-" + abi + "-" + platform + ".whl"
return Metadata{
f: func(t Toolchain) (pkg.Artifact, string) {
return t.New(name+"-"+version, 0, t.AppendPresets(nil,
slices.Concat(P{Python}, extra)...,
), nil, nil, `
) pkg.Artifact {
return t.New(name+"-"+version, 0, t.AppendPresets(nil,
slices.Concat(P{Python}, extra)...,
), nil, nil, `
pip3 install \
--no-index \
--prefix=/system \
--root=/work \
/usr/src/`+wname+`
`, pkg.Path(AbsUsrSrc.Append(wname), false, pkg.NewHTTPGet(
nil, prefix+wname,
mustDecode(checksum),
))), version
'/usr/src/`+path.Base(url)+`'
`, pkg.Path(AbsUsrSrc.Append(path.Base(url)), false, pkg.NewHTTPGet(
nil, url,
mustDecode(checksum),
)))
}
// newPypi creates [Metadata] for a [pypi] package.
//
// [pypi]: https://pypi.org/
func newPypi(
name string, id int,
description, version, interpreter, abi, platform, checksum string,
extra ...PArtifact,
) Metadata {
return Metadata{
f: func(t Toolchain) (pkg.Artifact, string) {
return t.newViaPip(name, version, "https://files.pythonhosted.org/"+path.Join(
"packages",
interpreter,
string(name[0]),
name,
name+"-"+version+"-"+interpreter+"-"+abi+"-"+platform+".whl",
), checksum, extra...), version
},
Name: "python-" + name,
@@ -107,6 +124,8 @@ pip3 install \
Website: "https://pypi.org/project/" + name + "/",
Dependencies: slices.Concat(P{Python}, extra),
ID: id,
}
}
@@ -123,11 +142,9 @@ pip3 install \
--prefix=/system \
--root=/work \
/usr/src/setuptools
`, pkg.Path(AbsUsrSrc.Append("setuptools"), true, pkg.NewHTTPGetTar(
nil, "https://github.com/pypa/setuptools/archive/refs/tags/"+
"v"+version+".tar.gz",
mustDecode(checksum),
pkg.TarGzip,
`, pkg.Path(AbsUsrSrc.Append("setuptools"), true, newFromGitHub(
"pypa/setuptools",
"v"+version, checksum,
))), version
}
func init() {
@@ -147,52 +164,71 @@ func init() {
}
func init() {
artifactsM[PythonPygments] = newViaPip(
"pygments",
artifactsM[PythonPygments] = newPypi(
"pygments", 3986,
" a syntax highlighting package written in Python",
"2.19.2", "py3", "none", "any",
"ak_lwTalmSr7W4Mjy2XBZPG9I6a0gwSy2pS87N8x4QEuZYif0ie9z0OcfRfi9msd",
"https://files.pythonhosted.org/packages/"+
"c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/",
"2.20.0", "py3", "none", "any",
"qlyqX2YSXcV0Z8XgGaPttc_gkq-xsu_nYs6NFOcYnk-CX7qmcj45gG-h6DpwPIcO",
)
artifactsM[PythonPluggy] = newViaPip(
"pluggy",
artifactsM[PythonPluggy] = newPypi(
"pluggy", 7500,
"the core framework used by the pytest, tox, and devpi projects",
"1.6.0", "py3", "none", "any",
"2HWYBaEwM66-y1hSUcWI1MyE7dVVuNNRW24XD6iJBey4YaUdAK8WeXdtFMQGC-4J",
"https://files.pythonhosted.org/packages/"+
"54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/",
)
artifactsM[PythonPackaging] = newViaPip(
"packaging",
artifactsM[PythonPackaging] = newPypi(
"packaging", 60461,
"reusable core utilities for various Python Packaging interoperability specifications",
"26.0", "py3", "none", "any",
"iVVXcqdwHDskPKoCFUlh2x8J0Gyq-bhO4ns9DvUJ7oJjeOegRYtSIvLV33Bki-pP",
"https://files.pythonhosted.org/packages/"+
"b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/",
"26.1", "py3", "none", "any",
"6WZjBJeRb0eZZavxM8cLPcgD-ch-1FblsHoCFKC_9VUC5XAmd397LwliVhsnQcSN",
)
artifactsM[PythonIniConfig] = newViaPip(
"iniconfig",
artifactsM[PythonIniConfig] = newPypi(
"iniconfig", 114778,
"a small and simple INI-file parser module",
"2.3.0", "py3", "none", "any",
"SDgs4S5bXi77aVOeKTPv2TUrS3M9rduiK4DpU0hCmDsSBWqnZcWInq9lsx6INxut",
"https://files.pythonhosted.org/packages/"+
"cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/",
)
artifactsM[PythonPyTest] = newViaPip(
"pytest",
artifactsM[PythonPyTest] = newPypi(
"pytest", 3765,
"the pytest framework",
"9.0.2", "py3", "none", "any",
"IM2wDbLke1EtZhF92zvAjUl_Hms1uKDtM7U8Dt4acOaChMnDg1pW7ib8U0wYGDLH",
"https://files.pythonhosted.org/packages/"+
"3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/",
"9.0.3", "py3", "none", "any",
"57WLrIVOfyoRDjt5qD6LGOaDcDCtzQnKDSTUb7GzHyJDtry_nGHHs4-0tW0tiIJr",
PythonIniConfig,
PythonPackaging,
PythonPluggy,
PythonPygments,
)
artifactsM[PythonMarkupSafe] = newPypi(
"markupsafe", 3918,
"implements a text object that escapes characters so it is safe to use in HTML and XML",
"3.0.3", "cp314", "cp314", "musllinux_1_2_"+linuxArch(),
perArch[string]{
"amd64": "E2mo9ig_FKgTpGon_8qqviSEULwhnmxTIqd9vfyNxNpK4yofVYM7eLW_VE-LKbtO",
"arm64": "iG_hqsncOs8fA7bCaAg0x9XenXWlo9sqblyPcSG7yA9sfGLvM9KZznCpwWfOCwFC",
"riscv64": "7DI7U0M3jvr7U4uZml25GLw3m3EvMubCtNukZmss1gkVJ_DVkhV5DgX3Wt_sztbv",
}.unwrap(),
)
artifactsM[PythonMako] = newPypi(
"mako", 3915,
"a template library written in Python",
"1.3.11", "py3", "none", "any",
"WJ_hxYI-nNiuDiM6QhfAG84uO5U-M2aneB0JS9AQ2J2Oi6YXAbBxIdOeOEng6CoS",
PythonMarkupSafe,
)
artifactsM[PythonPyYAML] = newPypi(
"pyyaml", 4123,
"a YAML parser and emitter for Python",
"6.0.3", "cp314", "cp314", "musllinux_1_2_"+linuxArch(),
perArch[string]{
"amd64": "4_jhCFpUNtyrFp2HOMqUisR005u90MHId53eS7rkUbcGXkoaJ7JRsY21dREHEfGN",
"arm64": "sQ818ZYSmC7Vj9prIPx3sEYqSDhZlWvLbgHV9w4GjxsfQ63ZSzappctKM7Lb0Whw",
}.unwrap(),
)
}

View File

@@ -7,9 +7,9 @@ func (t Toolchain) newQEMU() (pkg.Artifact, string) {
version = "10.2.2"
checksum = "uNzRxlrVoLWe-EmZmBp75SezymgE512iE5XN90Bl7wi6CjE_oQGQB-9ocs7E16QG"
)
return t.NewPackage("qemu", version, pkg.NewHTTPGetTar(
nil, "https://download.qemu.org/qemu-"+version+".tar.bz2",
mustDecode(checksum),
return t.NewPackage("qemu", version, newTar(
"https://download.qemu.org/qemu-"+version+".tar.bz2",
checksum,
pkg.TarBzip2,
), &PackageAttr{
Patches: []KV{

View File

@@ -7,9 +7,9 @@ func (t Toolchain) newRdfind() (pkg.Artifact, string) {
version = "1.8.0"
checksum = "PoaeJ2WIG6yyfe5VAYZlOdAQiR3mb3WhAUMj2ziTCx_IIEal4640HMJUb4SzU9U3"
)
return t.NewPackage("rdfind", version, pkg.NewHTTPGetTar(
nil, "https://rdfind.pauldreik.se/rdfind-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("rdfind", version, newTar(
"https://rdfind.pauldreik.se/rdfind-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), nil, &MakeHelper{
// test suite hard codes /bin/echo

View File

@@ -4,6 +4,7 @@ package rosa
import (
"errors"
"log"
"path"
"runtime"
"slices"
"strconv"
@@ -69,6 +70,18 @@ func triplet() string {
return linuxArch() + "-rosa-linux-musl"
}
// perArch is a value that differs per architecture.
type perArch[T any] map[string]T
// unwrap returns the value for the current architecture.
func (p perArch[T]) unwrap() T {
v, ok := p[runtime.GOARCH]
if !ok {
panic("unsupported target " + runtime.GOARCH)
}
return v
}
const (
// EnvTriplet holds the return value of triplet.
EnvTriplet = "ROSA_TRIPLE"
@@ -315,24 +328,23 @@ mkdir -vp /work/system/bin
name += "-std"
}
boot := t - 1
musl, compilerRT, runtimes, clang := boot.NewLLVM()
toybox := Toybox
if flag&TEarly != 0 {
toybox = toyboxEarly
}
std := []pkg.Artifact{cureEtc{newIANAEtc()}, musl}
toolchain := []pkg.Artifact{compilerRT, runtimes, clang}
utils := []pkg.Artifact{
boot.Load(Mksh),
boot.Load(toybox),
}
base := Clang
if flag&TNoToolchain != 0 {
toolchain = nil
base = Musl
}
support = slices.Concat(extra, std, toolchain, utils)
support = slices.Concat(extra, (t-1).AppendPresets([]pkg.Artifact{
cureEtc{newIANAEtc()},
},
base,
Mksh,
toybox,
))
env = fixupEnviron(env, []string{
EnvTriplet + "=" + triplet(),
lcMessages,
@@ -408,8 +420,6 @@ const helperInPlace = "\x00"
// Helper is a build system helper for [Toolchain.NewPackage].
type Helper interface {
// name returns the value passed to the name argument of [Toolchain.New].
name(name, version string) string
// extra returns helper-specific dependencies.
extra(flag int) P
@@ -431,11 +441,6 @@ type Helper interface {
script(name string) string
}
const (
// SourceKindTarXZ denotes a source tarball to be decompressed using [XZ].
SourceKindTarXZ = 1 + iota
)
// PackageAttr holds build-system-agnostic attributes.
type PackageAttr struct {
// Mount the source tree writable.
@@ -452,8 +457,6 @@ type PackageAttr struct {
// Passed to [Toolchain.NewPatchedSource].
Patches []KV
// Kind of source artifact.
SourceKind int
// Dependencies not provided by stage0.
NonStage0 []pkg.Artifact
@@ -525,11 +528,6 @@ func (t Toolchain) NewPackage(
panic("source must be non-nil")
}
wantsChmod, wantsWrite := helper.wantsChmod(), helper.wantsWrite()
if attr.SourceKind > 0 &&
(attr.Writable || attr.Chmod || wantsChmod || wantsWrite || len(attr.Patches) > 0) {
panic("source processing requested on a non-unpacked kind")
}
dc := len(attr.NonStage0)
if !t.isStage0() {
dc += 1<<3 + len(extra)
@@ -548,17 +546,23 @@ func (t Toolchain) NewPackage(
paPut(pv)
}
var scriptEarly string
var (
scriptEarly string
sourceSuffix string
)
if _, ok := source.(pkg.FileArtifact); ok {
if attr.Writable || attr.Chmod ||
wantsChmod || wantsWrite ||
len(attr.Patches) > 0 {
panic("source processing requested on a xz-compressed tarball")
}
var sourceSuffix string
switch attr.SourceKind {
case SourceKindTarXZ:
sourceSuffix = ".tar.xz"
scriptEarly += `
tar -C /usr/src/ -xf '/usr/src/` + name + `.tar.xz'
mv '/usr/src/` + name + `-` + version + `' '/usr/src/` + name + `'
`
break
}
dir := helper.wantsDir()
@@ -582,7 +586,7 @@ cd '/usr/src/` + name + `/'
}
return t.New(
helper.name(name, version),
name+"-"+version,
attr.Flag,
extraRes,
nil,
@@ -597,3 +601,65 @@ cd '/usr/src/` + name + `/'
})...,
)
}
const (
// jobsE is expression for preferred job count set by [pkg].
jobsE = `"$` + pkg.EnvJobs + `"`
// jobsE is expression for flag with preferred job count.
jobsFlagE = `"-j$` + pkg.EnvJobs + `"`
// jobsLE is expression for twice of preferred job count set by [pkg].
jobsLE = `"$(expr ` + jobsE + ` '*' 2)"`
// jobsE is expression for flag with double of preferred job count.
jobsLFlagE = `"-j$(expr ` + jobsE + ` '*' 2)"`
)
// newTar wraps [pkg.NewHTTPGetTar] with a simpler function signature.
func newTar(url, checksum string, compression uint32) pkg.Artifact {
return pkg.NewHTTPGetTar(nil, url, mustDecode(checksum), compression)
}
// newFromCPAN is a helper for downloading release from CPAN.
func newFromCPAN(author, name, version, checksum string) pkg.Artifact {
return newTar(
"https://cpan.metacpan.org/authors/id/"+
author[:1]+"/"+author[:2]+"/"+author+"/"+
name+"-"+version+".tar.gz",
checksum,
pkg.TarGzip,
)
}
// newFromGitLab is a helper for downloading source from GitLab.
func newFromGitLab(domain, suffix, ref, checksum string) pkg.Artifact {
return newTar(
"https://"+domain+"/"+suffix+"/-/archive/"+
ref+"/"+path.Base(suffix)+"-"+
strings.ReplaceAll(ref, "/", "-")+".tar.bz2",
checksum,
pkg.TarBzip2,
)
}
// newFromGitHub is a helper for downloading source from Microsoft Github.
func newFromGitHub(suffix, tag, checksum string) pkg.Artifact {
return newTar(
"https://github.com/"+suffix+
"/archive/refs/tags/"+tag+".tar.gz",
checksum,
pkg.TarGzip,
)
}
// newFromGitHubRelease is a helper for downloading release tarball from
// Microsoft Github.
func newFromGitHubRelease(
suffix, tag, name, checksum string,
compression uint32,
) pkg.Artifact {
return newTar(
"https://github.com/"+suffix+
"/releases/download/"+tag+"/"+name,
checksum,
compression,
)
}

View File

@@ -60,7 +60,7 @@ func getCache(t *testing.T) *pkg.Cache {
msg := message.New(log.New(os.Stderr, "rosa: ", 0))
msg.SwapVerbose(true)
if buildTestCache, err = pkg.Open(ctx, msg, 0, 0, a); err != nil {
if buildTestCache, err = pkg.Open(ctx, msg, 0, 0, 0, a); err != nil {
t.Fatal(err)
}
}
@@ -94,7 +94,7 @@ func TestCureAll(t *testing.T) {
func BenchmarkStage3(b *testing.B) {
for b.Loop() {
rosa.Std.Load(rosa.LLVMClang)
rosa.Std.Load(rosa.Clang)
b.StopTimer()
rosa.DropCaches()

View File

@@ -7,10 +7,10 @@ func (t Toolchain) newRsync() (pkg.Artifact, string) {
version = "3.4.1"
checksum = "VBlTsBWd9z3r2-ex7GkWeWxkUc5OrlgDzikAC0pK7ufTjAJ0MbmC_N04oSVTGPiv"
)
return t.NewPackage("rsync", version, pkg.NewHTTPGetTar(
nil, "https://download.samba.org/pub/rsync/src/"+
return t.NewPackage("rsync", version, newTar(
"https://download.samba.org/pub/rsync/src/"+
"rsync-"+version+".tar.gz",
mustDecode(checksum),
checksum,
pkg.TarGzip,
), &PackageAttr{
Flag: TEarly,

View File

@@ -7,10 +7,11 @@ func (t Toolchain) newSquashfsTools() (pkg.Artifact, string) {
version = "4.7.5"
checksum = "rF52wLQP-jeAmcD-48wqJcck8ZWRFwkax3T-7snaRf5EBnCQQh0YypMY9lwcivLz"
)
return t.NewPackage("squashfs-tools", version, pkg.NewHTTPGetTar(
nil, "https://github.com/plougher/squashfs-tools/releases/"+
"download/"+version+"/squashfs-tools-"+version+".tar.gz",
mustDecode(checksum),
return t.NewPackage("squashfs-tools", version, newFromGitHubRelease(
"plougher/squashfs-tools",
version,
"squashfs-tools-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), &PackageAttr{
// uses source tree as scratch space

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