diff --git a/buildkit/build.go b/buildkit/build.go index 25998ef..757d0d0 100644 --- a/buildkit/build.go +++ b/buildkit/build.go @@ -30,6 +30,7 @@ type BuildWithBuildkitClientOptions struct { ProgressMode string SecretsHash string Secrets map[string]string + Platform BuildPlatform } func BuildWithBuildkitClient(appDir string, plan *plan.BuildPlan, opts BuildWithBuildkitClientOptions) error { @@ -60,7 +61,10 @@ func BuildWithBuildkitClient(appDir string, plan *plan.BuildPlan, opts BuildWith return fmt.Errorf("failed to get buildkit info: %w", err) } - buildPlatform := determineBuildPlatformFromHost() + buildPlatform := opts.Platform + if (buildPlatform == BuildPlatform{}) { + buildPlatform = DetermineBuildPlatformFromHost() + } llbState, image, err := ConvertPlanToLLB(plan, ConvertPlanOptions{ BuildPlatform: buildPlatform, diff --git a/buildkit/frontend.go b/buildkit/frontend.go index 78bb7de..47dc784 100644 --- a/buildkit/frontend.go +++ b/buildkit/frontend.go @@ -117,7 +117,7 @@ func validatePlatform(opts map[string]string) (BuildPlatform, error) { platformStr := opts["platform"] if platformStr == "" { // Default to host platform if none specified - return determineBuildPlatformFromHost(), nil + return DetermineBuildPlatformFromHost(), nil } // Error if multiple platforms are specified diff --git a/buildkit/platform.go b/buildkit/platform.go index af7702e..b3c2262 100644 --- a/buildkit/platform.go +++ b/buildkit/platform.go @@ -25,7 +25,7 @@ var ( } ) -func determineBuildPlatformFromHost() BuildPlatform { +func DetermineBuildPlatformFromHost() BuildPlatform { if runtime.GOARCH == "arm64" { return PlatformLinuxARM64 } diff --git a/cli/build.go b/cli/build.go index 1d25d55..31409bf 100644 --- a/cli/build.go +++ b/cli/build.go @@ -28,6 +28,10 @@ var BuildCommand = &cli.Command{ Name: "output", Usage: "output the final filesystem to a local directory", }, + &cli.StringFlag{ + Name: "platform", + Usage: "platform to build for (e.g. linux/amd64, linux/arm64)", + }, &cli.StringFlag{ Name: "progress", Usage: "buildkit progress output mode. Values: auto, plain, tty", @@ -63,6 +67,11 @@ var BuildCommand = &cli.Command{ secretsHash := getSecretsHash(env) + platform, err := getPlatform(cmd.String("platform")) + if err != nil { + return cli.Exit(err, 1) + } + err = buildkit.BuildWithBuildkitClient(app.Source, buildResult.Plan, buildkit.BuildWithBuildkitClientOptions{ ImageName: cmd.String("name"), DumpLLB: cmd.Bool("llb"), @@ -70,6 +79,7 @@ var BuildCommand = &cli.Command{ ProgressMode: cmd.String("progress"), SecretsHash: secretsHash, Secrets: env.Variables, + Platform: platform, }) if err != nil { return cli.Exit(err, 1) @@ -79,6 +89,21 @@ var BuildCommand = &cli.Command{ }, } +func getPlatform(platformStr string) (buildkit.BuildPlatform, error) { + var platform buildkit.BuildPlatform + if platformStr == "" { + platform = buildkit.DetermineBuildPlatformFromHost() + } else if platformStr == "linux/arm64" { + platform = buildkit.PlatformLinuxARM64 + } else if platformStr != "linux/amd64" { + return buildkit.BuildPlatform{}, fmt.Errorf("unsupported platform: %s. Must be one of: linux/amd64, linux/arm64", platformStr) + } else { + platform = buildkit.PlatformLinuxAMD64 + } + + return platform, nil +} + func validateSecrets(plan *plan.BuildPlan, env *app.Environment) error { for _, secret := range plan.Secrets { if _, ok := env.Variables[secret]; !ok {