aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/rosa/rosa.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/rosa/rosa.go')
-rw-r--r--internal/rosa/rosa.go200
1 files changed, 156 insertions, 44 deletions
diff --git a/internal/rosa/rosa.go b/internal/rosa/rosa.go
index beffb3ff..c730127b 100644
--- a/internal/rosa/rosa.go
+++ b/internal/rosa/rosa.go
@@ -54,29 +54,45 @@ var (
)
// linuxArch returns the architecture name used by linux corresponding to arch.
-func (s *S) linuxArch() string {
- switch s.arch {
+func linuxArch(arch string) string {
+ switch arch {
case "amd64":
return "x86_64"
case "arm64":
return "aarch64"
- case "riscv64":
- return "riscv64"
+
+ case "ppc64le", "riscv64":
+ return arch
+
+ default:
+ panic("unsupported target " + arch)
+ }
+}
+
+// llvmArch returns the LLVM target-triple-specific name corresponding to arch.
+func llvmArch(arch string) string {
+ switch arch {
+ case "ppc64le":
+ return "powerpc64le"
default:
- panic("unsupported target " + s.arch)
+ return linuxArch(arch)
}
}
+// linuxArch returns the architecture name used by linux corresponding to arch.
+func (s *S) linuxArch() string { return linuxArch(s.Arch()) }
+
+// llvmArch returns the LLVM target-triple-specific name corresponding to arch.
+func (s *S) llvmArch() string { return llvmArch(s.Arch()) }
+
// triple returns the Rosa OS host triple corresponding to arch.
-func (s *S) triple() string {
- return s.linuxArch() + "-rosa-linux-musl"
+func triple(arch string) string {
+ return llvmArch(arch) + "-rosa-linux-musl"
}
-const (
- // EnvTriple holds the Rosa OS host triple.
- EnvTriple = "ROSA_TRIPLE"
-)
+// triple returns the Rosa OS target triple corresponding to arch.
+func (s *S) triple() string { return triple(s.Arch()) }
// earlyLDFLAGS returns LDFLAGS corresponding to triplet.
func (s *S) earlyLDFLAGS(static bool) string {
@@ -213,6 +229,7 @@ var (
_toyboxEarly = H("toybox-early")
_llvm = H("llvm")
_patch = H("patch")
+ _qemu = H("qemu")
)
// HasStageEarly returns whether a stage0 distribution is available.
@@ -265,13 +282,13 @@ function apply {
}
}
- return t.New(name+"-src", Unversioned, nil, &PackageAttr{
- Paths: paths,
+ return t.native().New(name+"-src", Unversioned, nil, &PackageAttr{
+ Paths: paths,
+ Tools: P{_patch},
+ NoArch: true,
}, &GenericHelper{
Build: buf.String(),
- },
- _patch,
- )
+ })
}
// helperInPlace is a special directory value for omitting the cd statement.
@@ -280,7 +297,7 @@ const helperInPlace = "\x00"
// Helper is a build system helper for [Toolchain.New].
type Helper interface {
// tools returns helper-specific tool handles.
- tools() P
+ tools(t Toolchain) P
// inputs returns helper-specific input handles.
inputs() P
@@ -300,9 +317,16 @@ type Helper interface {
script(t Toolchain, name string) string
}
+// pathsHelper is a [Helper] with additional paths added to the container.
+type pathsHelper interface {
+ Helper
+
+ paths(t Toolchain) []pkg.ExecPath
+}
+
// PackageAttr holds build-system-agnostic attributes.
type PackageAttr struct {
- // Measure output if populated. Required by [THostNet].
+ // Measure output if populated. Required by HostNet.
KnownChecksum *pkg.Checksum
// Mount the source tree writable.
@@ -337,6 +361,14 @@ type PackageAttr struct {
// Whether to create [pkg.KindExecNet] instead of [pkg.KindExec].
HostNet bool
+ // Whether the [Helper] behaves identically across all architectures.
+ NoArch bool
+ // Whether libc can be omitted.
+ NoLibc bool
+ // Inputs added only during cross-compilation.
+ Cross P
+ // Native utilities added only during cross-compilation.
+ CrossTools P
// Native utilities used by the build process.
Tools P
// Unregistered extras.
@@ -403,6 +435,10 @@ func (t Toolchain) New(
attr = new(PackageAttr)
}
+ if attr.NoArch {
+ t = t.native()
+ }
+
if attr.Std && !t.stage.isStd() {
panic(BootstrapError(name))
}
@@ -418,9 +454,16 @@ func (t Toolchain) New(
root := make([]pkg.Artifact, 0, 1<<3+
len(attr.Extra)+
len(attr.Tools)+
+ len(attr.CrossTools)+
len(inputs))
root = append(root, attr.Extra...)
+ cross := t.cross()
+ var rootCross []pkg.Artifact
+ if cross {
+ rootCross = make([]pkg.Artifact, 0, 1+len(inputs)+len(attr.Cross))
+ }
+
const lcMessages = "LC_MESSAGES=C.UTF-8"
srn := rn
env := slices.Clone(attr.Env)
@@ -447,7 +490,6 @@ func (t Toolchain) New(
)
}
env = fixupEnviron(env, []string{
- EnvTriple + "=" + t.triple(),
lcMessages,
"LDFLAGS=" + t.earlyLDFLAGS(true),
}, "/system/bin",
@@ -481,7 +523,6 @@ func (t Toolchain) New(
toybox,
)
env = fixupEnviron(env, []string{
- EnvTriple + "=" + t.triple(),
lcMessages,
}, "/system/bin", "/bin")
@@ -491,24 +532,57 @@ func (t Toolchain) New(
wantsChmod, wantsWrite := helper.wantsChmod(), helper.wantsWrite()
{
+ native := t.native()
pv := paGet()
- for _, p := range helper.tools() {
- root = t.appendHandle(root, pv, p)
+ spv := pv
+ if cross {
+ spv = paGet()
+ }
+ for _, p := range helper.tools(t) {
+ root = native.appendHandle(root, pv, p)
}
- for _, p := range helper.inputs() {
- root = t.appendHandle(root, pv, p)
+
+ if !cross {
+ for _, p := range helper.inputs() {
+ root = t.appendHandle(root, spv, p)
+ }
+ } else {
+ for _, p := range helper.inputs() {
+ rootCross = t.appendHandle(rootCross, spv, p)
+ }
}
+
for _, p := range attr.Tools {
- root = t.appendHandle(root, pv, p)
+ root = native.appendHandle(root, pv, p)
}
- for _, p := range inputs {
- root = t.appendHandle(root, pv, p)
+
+ if !cross {
+ for _, p := range inputs {
+ root = t.appendHandle(root, spv, p)
+ }
+ } else {
+ if !attr.NoLibc {
+ rootCross = t.appendHandle(rootCross, spv, _musl)
+ }
+ for _, p := range inputs {
+ rootCross = t.appendHandle(rootCross, spv, p)
+ }
+ for _, p := range attr.Cross {
+ rootCross = t.appendHandle(rootCross, spv, p)
+ }
+ for _, p := range attr.CrossTools {
+ root = native.appendHandle(root, pv, p)
+ }
}
- boot := t.S.New(t.stage - 1)
+
+ boot := native.S.New(t.stage - 1)
for _, p := range extraBoot {
root = boot.appendHandle(root, pv, p)
}
paPut(pv)
+ if cross {
+ paPut(spv)
+ }
}
if t.stage == stageGentoo {
@@ -549,6 +623,9 @@ cd '/usr/src/` + name + `/'
)),
})
}
+ if ph, ok := helper.(pathsHelper); ok {
+ paths = append(paths, ph.paths(t)...)
+ }
bin := attr.Bin
if attr.PopulateUsrBin {
@@ -570,43 +647,68 @@ ln -s ../bin /usr/`
scriptEarly += " /bin/)\n"
}
+ arch := t.Arch()
+ sys := []pkg.ExecPath{pkg.Path(
+ fhs.AbsRoot, true,
+ root...,
+ ), pkg.Path(
+ absCureScript, false,
+ pkg.NewFile(scriptName, []byte(
+ "#!/system/bin/sh\n"+
+ "set -eu -o pipefail\n"+
+ scriptEarly+helper.script(t, name),
+ )),
+ )}
+ if cross {
+ var _arch string
+ _arch, arch = arch, t.S.native.Arch()
+ if len(rootCross) > 0 {
+ sys = append(sys, pkg.Path(
+ AbsSystem.Append(_arch), true,
+ rootCross...,
+ ))
+ }
+ srn += "-cross-" + _arch
+ }
+
return pkg.NewExec(
- srn, t.arch, attr.KnownChecksum, pkg.ExecTimeoutMax,
+ srn, arch, attr.KnownChecksum, pkg.ExecTimeoutMax,
attr.HostNet,
attr.Exclusive,
fhs.AbsRoot, env,
absCureScript,
nil,
- slices.Concat([]pkg.ExecPath{pkg.Path(
- fhs.AbsRoot, true,
- root...,
- ), pkg.Path(
- absCureScript, false,
- pkg.NewFile(scriptName, []byte(
- "#!/system/bin/sh\n"+
- "set -eu -o pipefail\n"+
- scriptEarly+helper.script(t, name),
- )),
- )}, paths)...,
+ slices.Concat(sys, paths)...,
)
}
+// A CrossError refers to a package that does not support cross-compilation and
+// is panicked by the helper implementation.
+type CrossError string
+
+func (e CrossError) Error() string {
+ return "package " + strconv.Quote(string(e)) +
+ " does not support cross-compilation"
+}
+
+var _ error = CrossError("")
+
// GenericHelper directly passes build script segments for invocations of
// one-off build scripts too specific to fit into any other [Helper]
-// implementation, but can still benefit from [Toolchain.NewPackage].
+// implementation, but can still benefit from [Toolchain.New].
type GenericHelper struct {
// Remain in current directory.
InPlace bool
// Concatenated for [Toolchain].
- Build, Check, Install string
+ Cross, Build, Check, Install string
}
var _ Helper = new(GenericHelper)
// tools is a noop.
-func (*GenericHelper) tools() P { return nil }
+func (*GenericHelper) tools(Toolchain) P { return nil }
// inputs is a noop.
func (*GenericHelper) inputs() P { return nil }
@@ -629,12 +731,22 @@ func (attr *GenericHelper) wantsDir() (string, bool) {
}
// script concatenates specified segments.
-func (attr *GenericHelper) script(t Toolchain, _ string) string {
+func (attr *GenericHelper) script(t Toolchain, name string) string {
if attr == nil {
attr = new(GenericHelper)
}
script := attr.Build
+ if t.cross() {
+ if attr.Cross == "" {
+ panic(CrossError(name))
+ }
+ cross := attr.Cross
+ if cross == "\x00" {
+ cross = ""
+ }
+ script = cross + script
+ }
if t.opts&OptSkipCheck == 0 {
script += attr.Check
}