add cross-platform build and packaging

This commit is contained in:
konez2k
2020-02-19 13:44:30 +01:00
committed by Lea Anthony
parent f220e0e5bd
commit b7f0155c3b
3 changed files with 107 additions and 30 deletions

View File

@@ -84,10 +84,14 @@ func EmbedAssets() ([]string, error) {
// BuildApplication will attempt to build the project based on the given inputs
func BuildApplication(binaryName string, forceRebuild bool, buildMode string, packageApp bool, projectOptions *ProjectOptions) error {
if buildMode == BuildModeBridge && projectOptions.CrossCompile {
return fmt.Errorf("you cant serve the application in cross-compilation")
}
// Generate Windows assets if needed
if runtime.GOOS == "windows" {
if projectOptions.Platform == "windows" {
cleanUp := !packageApp
err := NewPackageHelper().PackageWindows(projectOptions, cleanUp)
err := NewPackageHelper(projectOptions.Platform).PackageWindows(projectOptions, cleanUp)
if err != nil {
return err
}
@@ -130,16 +134,22 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
}()
buildCommand := slicer.String()
buildCommand.Add("go")
if projectOptions.CrossCompile {
buildCommand.Add("xgo")
} else {
buildCommand.Add("mewn")
}
if buildMode == BuildModeBridge {
// Ignore errors
buildCommand.Add("-i")
}
buildCommand.Add("build")
if !projectOptions.CrossCompile {
buildCommand.Add("build")
}
if binaryName != "" {
if binaryName != "" && !projectOptions.CrossCompile {
// Alter binary name based on OS
switch runtime.GOOS {
case "windows":
@@ -155,7 +165,7 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
}
// If we are forcing a rebuild
if forceRebuild {
if forceRebuild && !projectOptions.CrossCompile {
buildCommand.Add("-a")
}
@@ -166,7 +176,7 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
}
// Add windows flags
if runtime.GOOS == "windows" && buildMode == BuildModeProd {
if projectOptions.Platform == "windows" && buildMode == BuildModeProd {
ldflags += "-H windowsgui "
}
@@ -183,6 +193,13 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
}
buildCommand.AddSlice([]string{"-ldflags", ldflags})
if projectOptions.CrossCompile {
buildCommand.Add("-targets", projectOptions.Platform+"/"+projectOptions.Architecture)
buildCommand.Add("-out", "build/"+binaryName)
buildCommand.Add("./")
}
err = NewProgramHelper(projectOptions.Verbose).RunCommandArray(buildCommand.AsSlice())
if err != nil {
if packSpinner != nil {
@@ -209,20 +226,21 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
func PackageApplication(projectOptions *ProjectOptions) error {
// Package app
message := "Generating .app"
if runtime.GOOS == "windows" {
if projectOptions.Platform == "windows" {
err := CheckWindres()
if err != nil {
return err
}
message = "Generating resource bundle"
}
var packageSpinner *spinner.Spinner
if projectOptions.Verbose {
packageSpinner = spinner.New(message)
packageSpinner.SetSpinSpeed(50)
packageSpinner.Start()
}
err := NewPackageHelper().Package(projectOptions)
err := NewPackageHelper(projectOptions.Platform).Package(projectOptions)
if err != nil {
if packageSpinner != nil {
packageSpinner.Error()

View File

@@ -18,17 +18,19 @@ import (
// PackageHelper helps with the 'wails package' command
type PackageHelper struct {
fs *FSHelper
log *Logger
system *SystemHelper
platform string
fs *FSHelper
log *Logger
system *SystemHelper
}
// NewPackageHelper creates a new PackageHelper!
func NewPackageHelper() *PackageHelper {
func NewPackageHelper(platform string) *PackageHelper {
return &PackageHelper{
fs: NewFSHelper(),
log: NewLogger(),
system: NewSystemHelper(),
platform: platform,
fs: NewFSHelper(),
log: NewLogger(),
system: NewSystemHelper(),
}
}
@@ -63,16 +65,23 @@ func defaultString(val string, defaultVal string) string {
func (b *PackageHelper) getPackageFileBaseDir() string {
// Calculate template base dir
_, filename, _, _ := runtime.Caller(1)
return filepath.Join(path.Dir(filename), "packages", runtime.GOOS)
return filepath.Join(path.Dir(filename), "packages", b.platform)
}
// Package the application into a platform specific package
func (b *PackageHelper) Package(po *ProjectOptions) error {
switch runtime.GOOS {
switch b.platform {
case "darwin":
// Check we have the exe
if !b.fs.FileExists(po.BinaryName) {
return fmt.Errorf("cannot bundle non-existent binary file '%s'. Please build with 'wails build' first", po.BinaryName)
// Check cross-compiled application
if b.platform == runtime.GOOS {
return fmt.Errorf("cannot bundle non-existent binary file '%s'. Please build with 'wails build' first", po.BinaryName)
}
if _, err := b.fs.FindFile(path.Join(b.fs.Cwd(), "build"), "darwin"); err != nil {
return fmt.Errorf("cannot bundle non-existent cross-compiled binary file '%s'. Please build with 'wails build -x darwin' first", po.BinaryName)
}
}
return b.packageOSX(po)
case "windows":
@@ -80,7 +89,7 @@ func (b *PackageHelper) Package(po *ProjectOptions) error {
case "linux":
return fmt.Errorf("linux is not supported at this time. Please see https://github.com/wailsapp/wails/issues/2")
default:
return fmt.Errorf("platform '%s' not supported for bundling yet", runtime.GOOS)
return fmt.Errorf("platform '%s' not supported for bundling yet", b.platform)
}
}
@@ -103,6 +112,22 @@ func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
// Check binary exists
source := path.Join(b.fs.Cwd(), exe)
if b.platform != runtime.GOOS {
file, err := b.fs.FindFile(path.Join(b.fs.Cwd(), "build"), "darwin")
if err != nil {
return err
}
// rename to exe
if err := os.Rename(path.Join(b.fs.Cwd(), "build", file), path.Join(b.fs.Cwd(), "build", exe)); err != nil {
return err
}
source = path.Join(b.fs.Cwd(), "build", exe)
}
if !b.fs.FileExists(source) {
// We need to build!
return fmt.Errorf("Target '%s' not available. Has it been compiled yet?", exe)
@@ -192,16 +217,36 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
// Build syso
sysofile := filepath.Join(b.fs.Cwd(), basename+"-res.syso")
batfile, err := fs.LocalDir(".")
if err != nil {
return err
}
// cross-compile
if b.platform != runtime.GOOS {
folder, err := os.Getwd()
if err != nil {
return err
}
windresBatFile := filepath.Join(batfile.fullPath, "windres.bat")
windresCommand := []string{windresBatFile, sysofile, tgtRCFile}
err = NewProgramHelper().RunCommandArray(windresCommand)
if err != nil {
return err
args := []string{
"docker", "run", "--rm",
"-v", folder + ":/build",
"--entrypoint", "/bin/sh",
"techknowlogick/xgo",
"-c", "/usr/bin/x86_64-w64-mingw32-windres -o /build/" + basename + "-res.syso /build/" + basename + ".rc",
}
if err := NewProgramHelper().RunCommandArray(args); err != nil {
return err
}
} else {
batfile, err := fs.LocalDir(".")
if err != nil {
return err
}
windresBatFile := filepath.Join(batfile.fullPath, "windres.bat")
windresCommand := []string{windresBatFile, sysofile, tgtRCFile}
err = NewProgramHelper().RunCommandArray(windresCommand)
if err != nil {
return err
}
}
// clean up

View File

@@ -3,6 +3,8 @@ package main
import (
"fmt"
"os"
"runtime"
"strings"
"github.com/leaanthony/spinner"
"github.com/wailsapp/wails/cmd"
@@ -133,7 +135,19 @@ func init() {
}
// Set cross-compile
projectOptions.Platform = platform
projectOptions.Platform = runtime.GOOS
if len(platform) > 0 {
projectOptions.CrossCompile = true
projectOptions.Platform = platform
projectOptions.Architecture = "amd64"
// check build architecture
if strings.Contains(platform, "/") {
p := strings.Split(platform, "/")
projectOptions.Platform = p[0]
projectOptions.Architecture = p[1]
}
}
err = cmd.BuildApplication(projectOptions.BinaryName, forceRebuild, buildMode, packageApp, projectOptions)
if err != nil {