Skip to content

Commit

Permalink
bib: add cross arch building
Browse files Browse the repository at this point in the history
This commit adds experimental cross arch building.

I.e. you `bootc-image-builder` on a mac and target an `amd64` machine.

The usage would be:
```
sudo podman run ... \
  --type qcow2 \
  --target-arch amd64 \
     quay.io/centos-bootc/fedora-bootc:eln
```
and this is predicated on the idea that the target container is
available for both host and target architecture. When that is the case
the container for the host architecture is used as a buildroot, the
container for the target architecture is the target tree. Note that some
stages chroot into the target tree so `qemu-user` is essential for this
to work so that target achitecture code can be run transparently (because
only very small amounts of code need to run emulated this is pretty fast
still).

It will need qemu-user{,-static} installed on the host. Sadly we
cannot just install qemu-user into the container because the binfmt_misc
system is global and not namespaced. So while adding the binfmt_misc
handler from inside the container would work with enough privs it
would alter the global machine state and we should not do it.
  • Loading branch information
mvo5 committed Feb 7, 2024
1 parent fc873e2 commit eb01203
Showing 1 changed file with 29 additions and 4 deletions.
33 changes: 29 additions & 4 deletions bib/cmd/bootc-image-builder/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,19 @@ func makeManifest(c *ManifestConfig, cacheRoot string) (manifest.OSBuildManifest
}

// resolve container
resolver := container.NewResolver(c.Architecture.String())
hostArch := arch.Current()
resolverNative := container.NewResolver(hostArch.String())
resolverTarget := container.NewResolver(c.Architecture.String())

containerSpecs := make(map[string][]container.Spec)
for plName, sourceSpecs := range manifest.GetContainerSourceSpecs() {
var resolver container.Resolver
if plName == "build" {
resolver = resolverNative
} else {
resolver = resolverTarget
}

for _, c := range sourceSpecs {
resolver.Add(c)
}
Expand Down Expand Up @@ -152,8 +162,8 @@ func saveManifest(ms manifest.OSBuildManifest, fpath string) error {
}

func manifestFromCobra(cmd *cobra.Command, args []string) ([]byte, error) {
hostArch := arch.Current()
repos, err := loadRepos(hostArch.String())
buildArch := arch.Current()
repos, err := loadRepos(buildArch.String())
if err != nil {
return nil, err
}
Expand All @@ -163,6 +173,20 @@ func manifestFromCobra(cmd *cobra.Command, args []string) ([]byte, error) {
configFile, _ := cmd.Flags().GetString("config")
tlsVerify, _ := cmd.Flags().GetBool("tls-verify")
imgType, _ := cmd.Flags().GetString("type")
targetArch, _ := cmd.Flags().GetString("target-arch")
if targetArch != "" {
// TODO: detect if binfmt_misc for target arch is
// available, e.g. by mounting the binfmt_misc fs into
// the container and inspects the files or by
// including tiny statically linked target-arch
// binaries inside our bib container
fmt.Fprintf(os.Stderr, "WARNING: target-arch is experimental and needs an installed 'qemu-user' package\n")
if imgType == "iso" {
return nil, fmt.Errorf("cannot build iso for different target arches yet")
}
buildArch = arch.FromString(targetArch)
}
// TODO: add "target-variant", see https://github.com/osbuild/bootc-image-builder/pull/139/files#r1467591868

var config *BuildConfig
if configFile != "" {
Expand All @@ -179,7 +203,7 @@ func manifestFromCobra(cmd *cobra.Command, args []string) ([]byte, error) {
ImgType: imgType,
Config: config,
Repos: repos,
Architecture: hostArch,
Architecture: buildArch,
TLSVerify: tlsVerify,
}
return makeManifest(manifestConfig, rpmCacheRoot)
Expand Down Expand Up @@ -315,6 +339,7 @@ func run() error {
manifestCmd.Flags().String("config", "", "build config file")
manifestCmd.Flags().String("type", "qcow2", "image type to build [qcow2, ami]")
manifestCmd.Flags().Bool("tls-verify", true, "require HTTPS and verify certificates when contacting registries")
manifestCmd.Flags().String("target-arch", "", "build for the given target architecture (experimental)")

logrus.SetLevel(logrus.ErrorLevel)
buildCmd.Flags().AddFlagSet(manifestCmd.Flags())
Expand Down

0 comments on commit eb01203

Please sign in to comment.