Skip to content

Commit

Permalink
pkg/kernels: add cross-compilation feature
Browse files Browse the repository at this point in the history
For example, on amd64, if the 'gcc-aarch64-linux-gnu' package is
installed, LVH can cross compile an arm64 kernel on amd64. On arm64, if
the 'gcc-x86-64-linux-gnu' package is install, LVH can cross compile an
amd64 kernel on arm64.

Signed-off-by: Mahe Tardy <[email protected]>
  • Loading branch information
mtardy committed Mar 12, 2024
1 parent 3b98951 commit 7e43e94
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 18 deletions.
10 changes: 8 additions & 2 deletions cmd/lvh/kernels/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,20 @@ import (
)

func buildCommand() *cobra.Command {
return &cobra.Command{
var arch string

cmd := &cobra.Command{
Use: "build <kernel>",
Short: "build kernel",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
log := logrus.New()
kname := args[0]
return kernels.BuildKernel(context.Background(), log, dirName, kname, false /* TODO: add fetch flag */)
return kernels.BuildKernel(context.Background(), log, dirName, kname, false /* TODO: add fetch flag */, arch)
},
}

cmd.Flags().StringVar(&arch, "arch", "", "target architecture to build the kernel, e.g. 'amd64' or 'arm64' (default to native architecture)")

return cmd
}
10 changes: 8 additions & 2 deletions cmd/lvh/kernels/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import (
)

func configureCommand() *cobra.Command {
return &cobra.Command{
var arch string

cmd := &cobra.Command{
Use: "configure <kernel>",
Short: "configure kernel",
Args: cobra.ExactArgs(1),
Expand All @@ -24,12 +26,16 @@ func configureCommand() *cobra.Command {
}

kname := args[0]
if err := kd.ConfigureKernel(context.Background(), log, kname); err != nil {
if err := kd.ConfigureKernel(context.Background(), log, kname, arch); err != nil {
log.Fatal(err)
}

},
}

cmd.Flags().StringVar(&arch, "arch", "", "target architecture to configure the kernel, e.g. 'amd64' or 'arm64' (default to native architecture)")

return cmd
}

func rawConfigureCommand() *cobra.Command {
Expand Down
27 changes: 24 additions & 3 deletions pkg/arch/arch.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,36 @@ var ErrUnsupportedArch = fmt.Errorf("unsupported architecture: %s", runtime.GOAR

// Target returns the Linux Makefile target to build the kernel, for historical
// reasons, those are different between architectures.
func Target() (string, error) {
switch runtime.GOARCH {
func Target(arch string) (string, error) {
if arch == "" {
arch = runtime.GOARCH
}
switch arch {
case "amd64":
return "bzImage", nil
case "arm64":
return "Image.gz", nil
default:
return "", ErrUnsupportedArch
return "", fmt.Errorf("unsupported architecture for Makefile target: %s", arch)
}
}

func CrossCompiling(targetArch string) bool {
return targetArch != "" && targetArch != runtime.GOARCH
}

func CrossCompileMakeArgs(targetArch string) ([]string, error) {
if !CrossCompiling(targetArch) {
return nil, nil
}

switch targetArch {
case "arm64":
return []string{"ARCH=arm64", "CROSS_COMPILE=aarch64-linux-gnu-"}, nil
case "amd64":
return []string{"ARCH=x86_64", "CROSS_COMPILE=x86_64-linux-gnu-"}, nil
}
return nil, fmt.Errorf("unsupported architecture for cross-compilation: %s", targetArch)
}

func QemuBinary() (string, error) {
Expand Down
38 changes: 29 additions & 9 deletions pkg/kernels/dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ func (kd *KernelsDir) RemoveKernelConfig(name string) *KernelConf {
return nil
}

func (kd *KernelsDir) ConfigureKernel(ctx context.Context, log *logrus.Logger, kernName string) error {
func (kd *KernelsDir) ConfigureKernel(ctx context.Context, log *logrus.Logger, kernName string, targetArch string) error {
kc := kd.KernelConfig(kernName)
if kc == nil {
return fmt.Errorf("kernel '%s' not found", kernName)
}
return kd.configureKernel(ctx, log, kc)
return kd.configureKernel(ctx, log, kc, targetArch)
}

func (kd *KernelsDir) RawConfigure(ctx context.Context, log *logrus.Logger, kernDir, kernName string) error {
Expand Down Expand Up @@ -206,13 +206,21 @@ func (kd *KernelsDir) rawConfigureKernel(
return nil
}

func (kd *KernelsDir) configureKernel(ctx context.Context, log *logrus.Logger, kc *KernelConf) error {
func (kd *KernelsDir) configureKernel(ctx context.Context, log *logrus.Logger, kc *KernelConf, targetArch string) error {
srcDir := filepath.Join(kd.Dir, kc.Name)
return kd.rawConfigureKernel(ctx, log, kc, srcDir, "defconfig", "prepare")
crossCompilationArgs, err := arch.CrossCompileMakeArgs(targetArch)
if err != nil {
return fmt.Errorf("failed to retrieve cross compilation args: %w", err)
}

configureMakeArgs := []string{"defconfig", "prepare"}
configureMakeArgs = append(configureMakeArgs, crossCompilationArgs...)

return kd.rawConfigureKernel(ctx, log, kc, srcDir, configureMakeArgs...)

}

func (kd *KernelsDir) buildKernel(ctx context.Context, log *logrus.Logger, kc *KernelConf) error {
func (kd *KernelsDir) buildKernel(ctx context.Context, log *logrus.Logger, kc *KernelConf, targetArch string) error {
if err := CheckEnvironment(); err != nil {
return err
}
Expand All @@ -224,23 +232,35 @@ func (kd *KernelsDir) buildKernel(ctx context.Context, log *logrus.Logger, kc *K
return err
} else if !exists {
log.Info("Configuring kernel")
err = kd.configureKernel(ctx, log, kc)
err = kd.configureKernel(ctx, log, kc, targetArch)
if err != nil {
return fmt.Errorf("failed to configure kernel: %w", err)
}
}

ncpus := fmt.Sprintf("%d", runtime.NumCPU())

target, err := arch.Target()
target, err := arch.Target(targetArch)
if err != nil {
return fmt.Errorf("failed to get make target: %w", err)
}
if err := runAndLogMake(ctx, log, kc, "-C", srcDir, "-j", ncpus, target, "modules"); err != nil {

buildMakeArgs := []string{"-C", srcDir, "-j", ncpus, target, "modules"}

crossCompilationArgs, err := arch.CrossCompileMakeArgs(targetArch)
if err != nil {
return fmt.Errorf("failed to retrieve cross compilation args: %w", err)
}
buildMakeArgs = append(buildMakeArgs, crossCompilationArgs...)

if err := runAndLogMake(ctx, log, kc, buildMakeArgs...); err != nil {
return fmt.Errorf("buiding bzImage && modules failed: %w", err)
}

if err := runAndLogMake(ctx, log, kc, "-C", srcDir, "tar-pkg"); err != nil {
archiveMakeArgs := []string{"-C", srcDir, "tar-pkg"}
archiveMakeArgs = append(archiveMakeArgs, crossCompilationArgs...)

if err := runAndLogMake(ctx, log, kc, archiveMakeArgs...); err != nil {
return fmt.Errorf("build dir failed: %w", err)
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/kernels/kernels.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ func FetchKernel(ctx context.Context, log *logrus.Logger, dir, kname string) err
return kurl.fetch(ctx, log, kd.Dir, kc.Name)
}

func BuildKernel(ctx context.Context, log *logrus.Logger, dir, kname string, fetch bool) error {
func BuildKernel(ctx context.Context, log *logrus.Logger, dir, kname string, fetch bool, arch string) error {
kd, kc, kurl, err := getKernelInfo(dir, kname)
if err != nil {
return err
Expand All @@ -176,5 +176,5 @@ func BuildKernel(ctx context.Context, log *logrus.Logger, dir, kname string, fet

}

return kd.buildKernel(ctx, log, kc)
return kd.buildKernel(ctx, log, kc, arch)
}

0 comments on commit 7e43e94

Please sign in to comment.