From c2fa4b6103de28d4ae5988ddae111894e12fd620 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Thu, 10 Feb 2022 19:54:48 +1100 Subject: [PATCH] Support multiple targets for windows --- v2/cmd/wails/internal/commands/build/build.go | 163 +++++++++++------- v2/pkg/commands/build/base.go | 4 +- v2/pkg/commands/build/build.go | 4 +- 3 files changed, 106 insertions(+), 65 deletions(-) diff --git a/v2/cmd/wails/internal/commands/build/build.go b/v2/cmd/wails/internal/commands/build/build.go index d7dc33f5d..6d0404733 100644 --- a/v2/cmd/wails/internal/commands/build/build.go +++ b/v2/cmd/wails/internal/commands/build/build.go @@ -3,6 +3,8 @@ package build import ( "fmt" "github.com/wailsapp/wails/v2/internal/colour" + "github.com/wailsapp/wails/v2/internal/project" + "github.com/wailsapp/wails/v2/internal/system" "io" "os" "os/exec" @@ -15,8 +17,6 @@ import ( "github.com/wailsapp/wails/v2/cmd/wails/internal" "github.com/wailsapp/wails/v2/internal/gomod" - "github.com/wailsapp/wails/v2/internal/system" - "github.com/leaanthony/clir" "github.com/leaanthony/slicer" "github.com/wailsapp/wails/v2/pkg/clilogger" @@ -50,7 +50,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) { // Setup Platform flag platform := runtime.GOOS - command.StringFlag("platform", "Platform to target", &platform) + command.StringFlag("platform", "Platform to target. Comma separate multiple platforms", &platform) // Verbosity verbosity := 1 @@ -103,28 +103,6 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) { app.PrintBanner() } - // Check platform - validPlatformArch := slicer.String([]string{ - "darwin", - "darwin/amd64", - "darwin/arm64", - "darwin/universal", - "linux", - //"linux/amd64", - //"linux/arm-7", - "windows", - "windows/amd64", - "windows/arm64", - }) - if !validPlatformArch.Contains(platform) { - return fmt.Errorf("platform %s is not supported. Platforms supported: %s", platform, validPlatformArch.Join(",")) - } - - if compress && platform == "darwin/universal" { - logger.Println("Warning: compress flag unsupported for universal binaries. Ignoring.") - compress = false - } - // Lookup compiler path compilerPath, err := exec.LookPath(compilerCommand) if err != nil { @@ -174,6 +152,10 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) { modeString = "Debug" } + var targets slicer.StringSlicer + targets.AddSlice(strings.Split(platform, ",")) + targets.Deduplicate() + // Create BuildOptions buildOptions := &build.Options{ Logger: logger, @@ -194,18 +176,6 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) { WebView2Strategy: wv2rtstrategy, } - // Calculate platform and arch - platformSplit := strings.Split(platform, "/") - buildOptions.Platform = platformSplit[0] - if system.IsAppleSilicon { - buildOptions.Arch = "arm64" - } else { - buildOptions.Arch = runtime.GOARCH - } - if len(platformSplit) == 2 { - buildOptions.Arch = platformSplit[1] - } - // Start a new tabwriter w := new(tabwriter.Writer) w.Init(os.Stdout, 8, 8, 0, '\t', 0) @@ -213,8 +183,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) { // Write out the system information fmt.Fprintf(w, "\n") fmt.Fprintf(w, "App Type: \t%s\n", buildOptions.OutputType) - fmt.Fprintf(w, "Platform: \t%s\n", buildOptions.Platform) - fmt.Fprintf(w, "Arch: \t%s\n", buildOptions.Arch) + fmt.Fprintf(w, "Platforms: \t%s\n", platform) fmt.Fprintf(w, "Compiler: \t%s\n", compilerPath) fmt.Fprintf(w, "Build Mode: \t%s\n", modeString) fmt.Fprintf(w, "Skip Frontend: \t%t\n", skipFrontend) @@ -223,7 +192,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) { fmt.Fprintf(w, "Clean Build Dir: \t%t\n", buildOptions.CleanBuildDirectory) fmt.Fprintf(w, "LDFlags: \t\"%s\"\n", buildOptions.LDFlags) fmt.Fprintf(w, "Tags: \t[%s]\n", strings.Join(buildOptions.UserTags, ",")) - if len(buildOptions.OutputFile) > 0 { + if len(buildOptions.OutputFile) > 0 && targets.Length() == 1 { fmt.Fprintf(w, "Output File: \t%s\n", buildOptions.OutputFile) } fmt.Fprintf(w, "\n") @@ -234,30 +203,102 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) { return err } - return doBuild(buildOptions) + cwd, err := os.Getwd() + if err != nil { + return err + } + projectOptions, err := project.Load(cwd) + + // Check platform + validPlatformArch := slicer.String([]string{ + "darwin", + "darwin/amd64", + "darwin/arm64", + "darwin/universal", + "linux", + //"linux/amd64", + //"linux/arm-7", + "windows", + "windows/amd64", + "windows/arm64", + }) + + targets.Each(func(platform string) { + + if !validPlatformArch.Contains(platform) { + buildOptions.Logger.Println("platform '%s' is not supported - skipping. Supported platforms: %s", platform, validPlatformArch.Join(",")) + return + } + + desiredFilename := projectOptions.OutputFilename + if desiredFilename == "" { + desiredFilename = projectOptions.Name + } + desiredFilename = strings.TrimSuffix(desiredFilename, ".exe") + + // Calculate platform and arch + platformSplit := strings.Split(platform, "/") + buildOptions.Platform = platformSplit[0] + if system.IsAppleSilicon { + buildOptions.Arch = "arm64" + } else { + buildOptions.Arch = runtime.GOARCH + } + if len(platformSplit) == 2 { + buildOptions.Arch = platformSplit[1] + } + + banner := "Building target: " + platform + logger.Println(banner) + logger.Println(strings.Repeat("-", len(banner))) + + if compress && platform == "darwin/universal" { + logger.Println("Warning: compress flag unsupported for universal binaries. Ignoring.") + compress = false + } + + switch buildOptions.Platform { + case "linux": + if runtime.GOOS != "linux" { + logger.Println("Crosscompiling to Linux not currently supported.\n") + return + } + case "darwin": + if runtime.GOOS != "darwin" { + logger.Println("Crosscompiling to Mac not currently supported.\n") + return + } + } + + if targets.Length() > 1 { + // target filename + switch buildOptions.Platform { + case "windows": + desiredFilename = fmt.Sprintf("%s-%s.exe", desiredFilename, buildOptions.Arch) + default: + desiredFilename = fmt.Sprintf("%s-%s-%s", desiredFilename, buildOptions.Platform, buildOptions.Arch) + } + } + buildOptions.OutputFile = desiredFilename + + // Start Time + start := time.Now() + + outputFilename, err := build.Build(buildOptions) + if err != nil { + logger.Println("Error: ", err.Error()) + return + } + buildOptions.IgnoreFrontend = true + + // Output stats + buildOptions.Logger.Println(fmt.Sprintf("Built '%s' in %s.\n", outputFilename, time.Since(start).Round(time.Millisecond).String())) + + }) + return nil }) } -// doBuild is our main build command -func doBuild(buildOptions *build.Options) error { - - // Start Time - start := time.Now() - - outputFilename, err := build.Build(buildOptions) - if err != nil { - return err - } - - // Output stats - elapsed := time.Since(start) - buildOptions.Logger.Println("") - buildOptions.Logger.Println(fmt.Sprintf("Built '%s' in %s.", outputFilename, elapsed.Round(time.Millisecond).String())) - buildOptions.Logger.Println("") - - return nil -} - func checkGoModVersion(logger *clilogger.CLILogger, updateGoMod bool) error { cwd, err := os.Getwd() if err != nil { diff --git a/v2/pkg/commands/build/base.go b/v2/pkg/commands/build/base.go index 79946f5e0..7fd5db408 100644 --- a/v2/pkg/commands/build/base.go +++ b/v2/pkg/commands/build/base.go @@ -548,7 +548,7 @@ func (b *BaseBuilder) BuildFrontend(outputLogger *clilogger.CLILogger) error { outputLogger.Println("No Install command. Skipping.") } else { // Do install if needed - outputLogger.Print("Installing frontend dependencies: ") + outputLogger.Print(" - Installing frontend dependencies: ") if verbose { outputLogger.Println("") outputLogger.Println(" Install command: '" + b.projectData.InstallCommand + "'") @@ -576,7 +576,7 @@ func (b *BaseBuilder) BuildFrontend(outputLogger *clilogger.CLILogger) error { return nil } - outputLogger.Print("Compiling frontend: ") + outputLogger.Print(" - Compiling frontend: ") cmd := strings.Split(buildCommand, " ") if verbose { outputLogger.Println("") diff --git a/v2/pkg/commands/build/build.go b/v2/pkg/commands/build/build.go index 7ee348d28..7289ba084 100644 --- a/v2/pkg/commands/build/build.go +++ b/v2/pkg/commands/build/build.go @@ -117,7 +117,7 @@ func Build(options *Options) (string, error) { // If we are building for windows, we will need to generate the asset bundle before // compilation. This will be a .syso file in the project root if options.Pack && options.Platform == "windows" { - outputLogger.Print("Generating bundle assets: ") + outputLogger.Print(" - Generating bundle assets: ") err := packageApplicationForWindows(options) if err != nil { return "", err @@ -134,7 +134,7 @@ func Build(options *Options) (string, error) { } // Compile the application - outputLogger.Print("Compiling application: ") + outputLogger.Print(" - Compiling application: ") if options.Platform == "darwin" && options.Arch == "universal" { outputFile := builder.OutputFilename(options)