mirror of
https://github.com/taigrr/wails.git
synced 2026-04-03 13:48:55 -07:00
Compare commits
12 Commits
419-better
...
cross-comp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68cd6a7f0e | ||
|
|
e00ffdbeea | ||
|
|
4eebbfd22c | ||
|
|
1998736baa | ||
|
|
89579db7fa | ||
|
|
3679114445 | ||
|
|
9e5dd0bc86 | ||
|
|
8c9ca5be95 | ||
|
|
526136099b | ||
|
|
f490bf8bc9 | ||
|
|
3edca62a38 | ||
|
|
79188c503f |
@@ -22,8 +22,4 @@ Wails is what it is because of the time and effort given by these great people.
|
||||
* [Kris Raney](https://github.com/kraney)
|
||||
* [Jack Mordaunt](https://github.com/JackMordaunt)
|
||||
* [Michael Hipp](https://github.com/MichaelHipp)
|
||||
* [Travis McLane](https://github.com/tmclane)
|
||||
* [Reuben Thomas-Davis](https://github.com/Rested)
|
||||
* [Jarek](https://github.com/Jarek-SRT)
|
||||
* [Konez2k](https://github.com/konez2k)
|
||||
* [msms](https://github.com/sayuthisobri)
|
||||
* [Travis McLane](https://github.com/tmclane)
|
||||
@@ -57,7 +57,7 @@ _Ubuntu: 16.04, 18.04, 19.04_
|
||||
|
||||
_Also succesfully tested on: Zorin 15, Parrot 4.7, Linuxmint 19, Elementary 5, Kali, Neon_
|
||||
|
||||
#### Arch Linux / ArchLabs
|
||||
#### Arch Linux
|
||||
|
||||
`sudo pacman -S webkit2gtk gtk3`
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build linux darwin !windows
|
||||
// +build +linux +darwin !windows
|
||||
|
||||
package wails
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -117,10 +117,10 @@ func (fs *FSHelper) RemoveFile(filename string) error {
|
||||
}
|
||||
|
||||
// RemoveFiles removes the given filenames
|
||||
func (fs *FSHelper) RemoveFiles(files []string, continueOnError bool) error {
|
||||
func (fs *FSHelper) RemoveFiles(files []string) error {
|
||||
for _, filename := range files {
|
||||
err := os.Remove(filename)
|
||||
if err != nil && !continueOnError {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
299
cmd/helpers.go
299
cmd/helpers.go
@@ -5,10 +5,8 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -83,118 +81,44 @@ func EmbedAssets() ([]string, error) {
|
||||
return targetFiles, nil
|
||||
}
|
||||
|
||||
func InitializeCrossCompilation(verbose bool) error {
|
||||
// Check Docker
|
||||
if err := CheckIfInstalled("docker"); err != nil {
|
||||
return err
|
||||
}
|
||||
// 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 {
|
||||
|
||||
var packSpinner *spinner.Spinner
|
||||
if !verbose {
|
||||
packSpinner = spinner.New("Pulling wailsapp/xgo:latest docker image... (may take a while)")
|
||||
packSpinner.SetSpinSpeed(50)
|
||||
packSpinner.Start()
|
||||
} else {
|
||||
println("Pulling wailsapp/xgo:latest docker image... (may take a while)")
|
||||
}
|
||||
|
||||
err := NewProgramHelper(verbose).RunCommandArray([]string{"docker",
|
||||
"pull", "wailsapp/xgo:latest"})
|
||||
|
||||
if err != nil {
|
||||
if packSpinner != nil {
|
||||
packSpinner.Error()
|
||||
}
|
||||
return err
|
||||
}
|
||||
if packSpinner != nil {
|
||||
packSpinner.Success()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// BuildDocker builds the project using the cross compiling wailsapp/xgo:latest container
|
||||
func BuildDocker(binaryName string, buildMode string, projectOptions *ProjectOptions) error {
|
||||
var packSpinner *spinner.Spinner
|
||||
if buildMode == BuildModeBridge {
|
||||
if buildMode == BuildModeBridge && projectOptions.CrossCompile {
|
||||
return fmt.Errorf("you cant serve the application in cross-compilation")
|
||||
}
|
||||
|
||||
// Check build directory
|
||||
buildDirectory := filepath.Join(fs.Cwd(), "build")
|
||||
if !fs.DirExists(buildDirectory) {
|
||||
fs.MkDir(buildDirectory)
|
||||
}
|
||||
|
||||
buildCommand := slicer.String()
|
||||
userid := 1000
|
||||
user, _ := user.Current()
|
||||
if i, err := strconv.Atoi(user.Uid); err == nil {
|
||||
userid = i
|
||||
}
|
||||
for _, arg := range []string{
|
||||
"docker",
|
||||
"run",
|
||||
"--rm",
|
||||
"-v", fmt.Sprintf("%s:/build", filepath.Join(fs.Cwd(), "build")),
|
||||
"-v", fmt.Sprintf("%s:/source", fs.Cwd()),
|
||||
"-e", fmt.Sprintf("LOCAL_USER_ID=%v", userid),
|
||||
"-e", fmt.Sprintf("FLAG_LDFLAGS=%s", ldFlags(projectOptions, buildMode)),
|
||||
"-e", "FLAG_V=false",
|
||||
"-e", "FLAG_X=false",
|
||||
"-e", "FLAG_RACE=false",
|
||||
"-e", "FLAG_BUILDMODE=default",
|
||||
"-e", "FLAG_TRIMPATH=false",
|
||||
"-e", fmt.Sprintf("TARGETS=%s", projectOptions.Platform+"/"+projectOptions.Architecture),
|
||||
"-e", "GOPROXY=",
|
||||
"-e", "GO111MODULE=on",
|
||||
"wailsapp/xgo:latest",
|
||||
".",
|
||||
} {
|
||||
buildCommand.Add(arg)
|
||||
}
|
||||
|
||||
compileMessage := fmt.Sprintf(
|
||||
"Packing + Compiling project for %s/%s using docker image wailsapp/xgo:latest",
|
||||
projectOptions.Platform, projectOptions.Architecture)
|
||||
|
||||
if buildMode == BuildModeDebug {
|
||||
compileMessage += " (Debug Mode)"
|
||||
}
|
||||
|
||||
if !projectOptions.Verbose {
|
||||
packSpinner = spinner.New(compileMessage + "...")
|
||||
packSpinner.SetSpinSpeed(50)
|
||||
packSpinner.Start()
|
||||
} else {
|
||||
println(compileMessage)
|
||||
}
|
||||
|
||||
err := NewProgramHelper(projectOptions.Verbose).RunCommandArray(buildCommand.AsSlice())
|
||||
if err != nil {
|
||||
if packSpinner != nil {
|
||||
packSpinner.Error()
|
||||
// Generate Windows assets if needed
|
||||
if projectOptions.Platform == "windows" {
|
||||
cleanUp := !packageApp
|
||||
err := NewPackageHelper(projectOptions.Platform).PackageWindows(projectOptions, cleanUp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
if packSpinner != nil {
|
||||
packSpinner.Success()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
if projectOptions.CrossCompile {
|
||||
// Check build directory
|
||||
buildDirectory := filepath.Join(fs.Cwd(), "build")
|
||||
if !fs.DirExists(buildDirectory) {
|
||||
fs.MkDir(buildDirectory)
|
||||
}
|
||||
|
||||
// BuildNative builds on the target platform itself.
|
||||
func BuildNative(binaryName string, forceRebuild bool, buildMode string, projectOptions *ProjectOptions) error {
|
||||
// Check Docker
|
||||
if err := CheckIfInstalled("docker"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check Mewn is installed
|
||||
if err := CheckMewn(projectOptions.Verbose); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := CheckWindres(); err != nil {
|
||||
return err
|
||||
// Check xgo
|
||||
if err := CheckIfInstalled("xgo"); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Check Mewn is installed
|
||||
err := CheckMewn(projectOptions.Verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
compileMessage := "Packing + Compiling project"
|
||||
@@ -212,18 +136,40 @@ func BuildNative(binaryName string, forceRebuild bool, buildMode string, project
|
||||
println(compileMessage)
|
||||
}
|
||||
|
||||
buildCommand := slicer.String()
|
||||
buildCommand.Add("go")
|
||||
// embed resources
|
||||
targetFiles, err := EmbedAssets()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// cleanup temporary embedded assets
|
||||
defer func() {
|
||||
for _, filename := range targetFiles {
|
||||
if err := os.Remove(filename); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
buildCommand := slicer.String()
|
||||
if projectOptions.CrossCompile {
|
||||
buildCommand.Add("xgo")
|
||||
} else {
|
||||
buildCommand.Add("mewn")
|
||||
}
|
||||
|
||||
buildCommand.Add("build")
|
||||
if buildMode == BuildModeBridge {
|
||||
// Ignore errors
|
||||
buildCommand.Add("-i")
|
||||
}
|
||||
|
||||
if binaryName != "" {
|
||||
if !projectOptions.CrossCompile {
|
||||
buildCommand.Add("build")
|
||||
}
|
||||
|
||||
if binaryName != "" && !projectOptions.CrossCompile {
|
||||
// Alter binary name based on OS
|
||||
switch projectOptions.Platform {
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
if !strings.HasSuffix(binaryName, ".exe") {
|
||||
binaryName += ".exe"
|
||||
@@ -233,21 +179,46 @@ func BuildNative(binaryName string, forceRebuild bool, buildMode string, project
|
||||
binaryName = strings.TrimSuffix(binaryName, ".exe")
|
||||
}
|
||||
}
|
||||
buildCommand.Add("-o", filepath.Join("build", binaryName))
|
||||
buildCommand.Add("-o", binaryName)
|
||||
}
|
||||
|
||||
// If we are forcing a rebuild
|
||||
if forceRebuild {
|
||||
if forceRebuild && !projectOptions.CrossCompile {
|
||||
buildCommand.Add("-a")
|
||||
}
|
||||
|
||||
buildCommand.AddSlice([]string{"-ldflags", ldFlags(projectOptions, buildMode)})
|
||||
|
||||
if projectOptions.Verbose {
|
||||
fmt.Printf("Command: %v\n", buildCommand.AsSlice())
|
||||
// Setup ld flags
|
||||
ldflags := "-w -s "
|
||||
if buildMode == BuildModeDebug {
|
||||
ldflags = ""
|
||||
}
|
||||
|
||||
err := NewProgramHelper(projectOptions.Verbose).RunCommandArray(buildCommand.AsSlice())
|
||||
// Add windows flags
|
||||
if projectOptions.Platform == "windows" && buildMode == BuildModeProd {
|
||||
ldflags += "-H windowsgui "
|
||||
}
|
||||
|
||||
ldflags += "-X github.com/wailsapp/wails.BuildMode=" + buildMode
|
||||
|
||||
// If we wish to generate typescript
|
||||
if projectOptions.typescriptDefsFilename != "" {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filename := filepath.Join(cwd, projectOptions.FrontEnd.Dir, projectOptions.typescriptDefsFilename)
|
||||
ldflags += " -X github.com/wailsapp/wails/lib/binding.typescriptDefinitionFilename=" + filename
|
||||
}
|
||||
|
||||
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 {
|
||||
packSpinner.Error()
|
||||
@@ -258,55 +229,7 @@ func BuildNative(binaryName string, forceRebuild bool, buildMode string, project
|
||||
packSpinner.Success()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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 {
|
||||
var err error
|
||||
|
||||
// embed resources
|
||||
targetFiles, err := EmbedAssets()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if projectOptions.CrossCompile {
|
||||
if err := InitializeCrossCompilation(projectOptions.Verbose); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
helper := NewPackageHelper(projectOptions.Platform)
|
||||
|
||||
// Generate windows resources
|
||||
if projectOptions.Platform == "windows" {
|
||||
if err := helper.PackageWindows(projectOptions, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// cleanup temporary embedded assets
|
||||
defer func() {
|
||||
for _, filename := range targetFiles {
|
||||
if err := os.Remove(filename); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
if projectOptions.Platform == "windows" {
|
||||
helper.CleanWindows(projectOptions)
|
||||
}
|
||||
}()
|
||||
|
||||
if projectOptions.CrossCompile {
|
||||
err = BuildDocker(binaryName, buildMode, projectOptions)
|
||||
} else {
|
||||
err = BuildNative(binaryName, forceRebuild, buildMode, projectOptions)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// packageApp
|
||||
if packageApp {
|
||||
err = PackageApplication(projectOptions)
|
||||
if err != nil {
|
||||
@@ -319,11 +242,22 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
|
||||
|
||||
// PackageApplication will attempt to package the application in a platform dependent way
|
||||
func PackageApplication(projectOptions *ProjectOptions) error {
|
||||
// Package app
|
||||
message := "Generating .app"
|
||||
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("Packaging application...")
|
||||
if !projectOptions.Verbose {
|
||||
packageSpinner = spinner.New(message)
|
||||
packageSpinner.SetSpinSpeed(50)
|
||||
packageSpinner.Start()
|
||||
} else {
|
||||
println(message)
|
||||
}
|
||||
|
||||
err := NewPackageHelper(projectOptions.Platform).Package(projectOptions)
|
||||
@@ -388,7 +322,7 @@ func CheckMewn(verbose bool) (err error) {
|
||||
|
||||
// CheckWindres checks if Windres is installed and if not, aborts
|
||||
func CheckWindres() (err error) {
|
||||
if runtime.GOOS != "windows" { // FIXME: Handle windows cross-compile for windows!
|
||||
if runtime.GOOS != "windows" {
|
||||
return nil
|
||||
}
|
||||
programHelper := NewProgramHelper()
|
||||
@@ -530,7 +464,7 @@ func ServeProject(projectOptions *ProjectOptions, logger *Logger) error {
|
||||
time.Sleep(2 * time.Second)
|
||||
logger.Green(">>>>> To connect, you will need to run '" + projectOptions.FrontEnd.Serve + "' in the '" + projectOptions.FrontEnd.Dir + "' directory <<<<<")
|
||||
}()
|
||||
location, err := filepath.Abs(filepath.Join("build", projectOptions.BinaryName))
|
||||
location, err := filepath.Abs(projectOptions.BinaryName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -546,28 +480,3 @@ func ServeProject(projectOptions *ProjectOptions, logger *Logger) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ldFlags(po *ProjectOptions, buildMode string) string {
|
||||
// Setup ld flags
|
||||
ldflags := "-w -s "
|
||||
if buildMode == BuildModeDebug {
|
||||
ldflags = ""
|
||||
}
|
||||
|
||||
// Add windows flags
|
||||
if po.Platform == "windows" && buildMode == BuildModeProd {
|
||||
ldflags += "-H windowsgui "
|
||||
}
|
||||
|
||||
ldflags += "-X github.com/wailsapp/wails.BuildMode=" + buildMode
|
||||
|
||||
// If we wish to generate typescript
|
||||
if po.typescriptDefsFilename != "" {
|
||||
cwd, err := os.Getwd()
|
||||
if err == nil {
|
||||
filename := filepath.Join(cwd, po.FrontEnd.Dir, po.typescriptDefsFilename)
|
||||
ldflags += " -X github.com/wailsapp/wails/lib/binding.typescriptDefinitionFilename=" + filename
|
||||
}
|
||||
}
|
||||
return ldflags
|
||||
}
|
||||
|
||||
14
cmd/linux.go
14
cmd/linux.go
@@ -53,12 +53,6 @@ const (
|
||||
Deepin
|
||||
// Raspbian distribution
|
||||
Raspbian
|
||||
// Tumbleweed (OpenSUSE) distribution
|
||||
Tumbleweed
|
||||
// Leap (OpenSUSE) distribution
|
||||
Leap
|
||||
// ArchLabs distribution
|
||||
ArchLabs
|
||||
)
|
||||
|
||||
// DistroInfo contains all the information relating to a linux distribution
|
||||
@@ -116,15 +110,13 @@ func parseOsRelease(osRelease string) *DistroInfo {
|
||||
}
|
||||
|
||||
// Check distro name against list of distros
|
||||
switch strings.ToLower(osID) {
|
||||
switch osID {
|
||||
case "fedora":
|
||||
result.Distribution = Fedora
|
||||
case "centos":
|
||||
result.Distribution = CentOS
|
||||
case "arch":
|
||||
result.Distribution = Arch
|
||||
case "archlabs":
|
||||
result.Distribution = ArchLabs
|
||||
case "debian":
|
||||
result.Distribution = Debian
|
||||
case "ubuntu":
|
||||
@@ -155,10 +147,6 @@ func parseOsRelease(osRelease string) *DistroInfo {
|
||||
result.Distribution = Deepin
|
||||
case "raspbian":
|
||||
result.Distribution = Raspbian
|
||||
case "opensuse-tumbleweed":
|
||||
result.Distribution = Tumbleweed
|
||||
case "opensuse-leap":
|
||||
result.Distribution = Leap
|
||||
default:
|
||||
result.Distribution = Unknown
|
||||
}
|
||||
|
||||
@@ -22,25 +22,5 @@ UBUNTU_CODENAME=bionic
|
||||
if result.Distribution != Ubuntu {
|
||||
t.Errorf("expected 'Ubuntu' ID but got '%d'", result.Distribution)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTumbleweedDetection(t *testing.T) {
|
||||
osrelease := `
|
||||
NAME="openSUSE Tumbleweed"
|
||||
# VERSION="20200414"
|
||||
ID="opensuse-tumbleweed"
|
||||
ID_LIKE="opensuse suse"
|
||||
VERSION_ID="20200414"
|
||||
PRETTY_NAME="openSUSE Tumbleweed"
|
||||
ANSI_COLOR="0;32"
|
||||
CPE_NAME="cpe:/o:opensuse:tumbleweed:20200414"
|
||||
BUG_REPORT_URL="https://bugs.opensuse.org"
|
||||
HOME_URL="https://www.opensuse.org/"
|
||||
LOGO="distributor-logo"
|
||||
`
|
||||
|
||||
result := parseOsRelease(osrelease)
|
||||
if result.Distribution != Tumbleweed {
|
||||
t.Errorf("expected 'Tumbleweed' ID but got '%d'", result.Distribution)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,15 +176,6 @@ distributions:
|
||||
gccversioncommand: *gccdumpversion
|
||||
programs: *archdefaultprograms
|
||||
libraries: *archdefaultlibraries
|
||||
archlabs:
|
||||
id: archlabs
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: ArchLabs
|
||||
gccversioncommand: *gccdumpversion
|
||||
programs: *archdefaultprograms
|
||||
libraries: *archdefaultlibraries
|
||||
manjaro:
|
||||
id: manjaro
|
||||
releases:
|
||||
@@ -232,32 +223,3 @@ distributions:
|
||||
gccversioncommand: *gccdumpfullversion
|
||||
programs: *debiandefaultprograms
|
||||
libraries: *debiandefaultlibraries
|
||||
|
||||
opensuse-tumbleweed:
|
||||
id: opensuse-tumbleweed
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: openSUSE Tumbleweed
|
||||
gccversioncommand: *gccdumpfullversion
|
||||
programs: &opensusedefaultprograms
|
||||
- name: gcc
|
||||
help: Please install with `sudo zypper in gcc-c++` and try again
|
||||
- name: pkg-config
|
||||
help: Please install with `sudo zypper in pkgconf-pkg-config` and try again
|
||||
- name: npm
|
||||
help: Please install `sudo zypper in nodejs` and try again
|
||||
libraries: &opensusedefaultlibraries
|
||||
- name: gtk3-devel
|
||||
help: Please install with `sudo zypper in gtk3-devel` and try again
|
||||
- name: webkit2gtk3-devel
|
||||
help: Please install with `sudo zypper in webkit2gtk3-devel` and try again
|
||||
opensuse-leap:
|
||||
id: opensuse-leap
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: openSUSE Leap
|
||||
gccversioncommand: *gccdumpfullversion
|
||||
programs: *opensusedefaultprograms
|
||||
libraries: *opensusedefaultlibraries
|
||||
|
||||
@@ -72,23 +72,29 @@ func (b *PackageHelper) getPackageFileBaseDir() string {
|
||||
func (b *PackageHelper) Package(po *ProjectOptions) error {
|
||||
switch b.platform {
|
||||
case "darwin":
|
||||
// Check we have the exe
|
||||
if !b.fs.FileExists(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":
|
||||
return b.PackageWindows(po, true)
|
||||
return b.PackageWindows(po, false)
|
||||
case "linux":
|
||||
return b.packageLinux(po)
|
||||
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", b.platform)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *PackageHelper) packageLinux(po *ProjectOptions) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Package the application for OSX
|
||||
func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
|
||||
build := path.Join(b.fs.Cwd(), "build")
|
||||
|
||||
system := NewSystemHelper()
|
||||
config, err := system.LoadConfig()
|
||||
@@ -105,25 +111,34 @@ func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
|
||||
appname := po.Name + ".app"
|
||||
|
||||
// Check binary exists
|
||||
source := path.Join(build, exe)
|
||||
if po.CrossCompile == true {
|
||||
file, err := b.fs.FindFile(build, "darwin")
|
||||
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
|
||||
}
|
||||
source = path.Join(build, file)
|
||||
|
||||
// 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?", source)
|
||||
return fmt.Errorf("Target '%s' not available. Has it been compiled yet?", exe)
|
||||
}
|
||||
|
||||
// Remove the existing package
|
||||
os.RemoveAll(appname)
|
||||
|
||||
exeDir := path.Join(build, appname, "/Contents/MacOS")
|
||||
exeDir := path.Join(b.fs.Cwd(), appname, "/Contents/MacOS")
|
||||
b.fs.MkDirs(exeDir, 0755)
|
||||
resourceDir := path.Join(build, appname, "/Contents/Resources")
|
||||
resourceDir := path.Join(b.fs.Cwd(), appname, "/Contents/Resources")
|
||||
b.fs.MkDirs(resourceDir, 0755)
|
||||
tmpl := template.New("infoPlist")
|
||||
plistFile := filepath.Join(b.getPackageFileBaseDir(), "info.plist")
|
||||
@@ -139,7 +154,7 @@ func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filename := path.Join(build, appname, "Contents", "Info.plist")
|
||||
filename := path.Join(b.fs.Cwd(), appname, "Contents", "Info.plist")
|
||||
err = ioutil.WriteFile(filename, tpl.Bytes(), 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -160,25 +175,12 @@ func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// CleanWindows removes any windows related files found in the directory
|
||||
func (b *PackageHelper) CleanWindows(po *ProjectOptions) {
|
||||
pdir := b.fs.Cwd()
|
||||
basename := strings.TrimSuffix(po.BinaryName, ".exe")
|
||||
exts := []string{".ico", ".exe.manifest", ".rc", "-res.syso"}
|
||||
rsrcs := []string{}
|
||||
for _, ext := range exts {
|
||||
rsrcs = append(rsrcs, filepath.Join(pdir, basename+ext))
|
||||
}
|
||||
b.fs.RemoveFiles(rsrcs, true)
|
||||
}
|
||||
|
||||
// PackageWindows packages the application for windows platforms
|
||||
func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
|
||||
outputDir := b.fs.Cwd()
|
||||
basename := strings.TrimSuffix(po.BinaryName, ".exe")
|
||||
|
||||
// Copy icon
|
||||
tgtIconFile := filepath.Join(outputDir, basename+".ico")
|
||||
tgtIconFile := filepath.Join(b.fs.Cwd(), basename+".ico")
|
||||
if !b.fs.FileExists(tgtIconFile) {
|
||||
srcIconfile := filepath.Join(b.getPackageFileBaseDir(), "wails.ico")
|
||||
err := b.fs.CopyFile(srcIconfile, tgtIconFile)
|
||||
@@ -188,7 +190,7 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
|
||||
}
|
||||
|
||||
// Copy manifest
|
||||
tgtManifestFile := filepath.Join(outputDir, basename+".exe.manifest")
|
||||
tgtManifestFile := filepath.Join(b.fs.Cwd(), basename+".exe.manifest")
|
||||
if !b.fs.FileExists(tgtManifestFile) {
|
||||
srcManifestfile := filepath.Join(b.getPackageFileBaseDir(), "wails.exe.manifest")
|
||||
err := b.fs.CopyFile(srcManifestfile, tgtManifestFile)
|
||||
@@ -198,7 +200,7 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
|
||||
}
|
||||
|
||||
// Copy rc file
|
||||
tgtRCFile := filepath.Join(outputDir, basename+".rc")
|
||||
tgtRCFile := filepath.Join(b.fs.Cwd(), basename+".rc")
|
||||
if !b.fs.FileExists(tgtRCFile) {
|
||||
srcRCfile := filepath.Join(b.getPackageFileBaseDir(), "wails.rc")
|
||||
rcfilebytes, err := ioutil.ReadFile(srcRCfile)
|
||||
@@ -213,17 +215,23 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
|
||||
}
|
||||
|
||||
// Build syso
|
||||
sysofile := filepath.Join(outputDir, basename+"-res.syso")
|
||||
sysofile := filepath.Join(b.fs.Cwd(), basename+"-res.syso")
|
||||
|
||||
// cross-compile
|
||||
if b.platform != runtime.GOOS {
|
||||
folder, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
args := []string{
|
||||
"docker", "run", "--rm",
|
||||
"-v", outputDir + ":/build",
|
||||
"-v", folder + ":/build",
|
||||
"--entrypoint", "/bin/sh",
|
||||
"wailsapp/xgo:latest",
|
||||
"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
|
||||
}
|
||||
@@ -240,6 +248,16 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// clean up
|
||||
if cleanUp {
|
||||
filesToDelete := []string{tgtIconFile, tgtManifestFile, tgtRCFile, sysofile}
|
||||
err := b.fs.RemoveFiles(filesToDelete)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0"><dict>
|
||||
<key>CFBundlePackageType</key><string>APPL</string>
|
||||
<key>CFBundleName</key><string>{{.Title}}</string>
|
||||
<key>CFBundleExecutable</key><string>{{.Exe}}</string>
|
||||
<key>CFBundleIdentifier</key><string>{{.PackageID}}</string>
|
||||
|
||||
@@ -138,11 +138,11 @@ func (p *ProgramHelper) RunCommand(command string) error {
|
||||
|
||||
// RunCommandArray runs the command specified in the array
|
||||
func (p *ProgramHelper) RunCommandArray(args []string, dir ...string) error {
|
||||
programCommand := args[0]
|
||||
program := args[0]
|
||||
// TODO: Run FindProgram here and get the full path to the exe
|
||||
program, err := exec.LookPath(programCommand)
|
||||
program, err := exec.LookPath(program)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: Looks like '%s' isn't installed. Please install and try again.", programCommand)
|
||||
fmt.Printf("ERROR: Looks like '%s' isn't installed. Please install and try again.", program)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@@ -157,10 +158,10 @@ type ProjectOptions struct {
|
||||
selectedTemplate *TemplateDetails
|
||||
WailsVersion string
|
||||
typescriptDefsFilename string
|
||||
Verbose bool `json:"-"`
|
||||
CrossCompile bool
|
||||
Platform string
|
||||
Architecture string
|
||||
Verbose bool `json:"-"`
|
||||
CrossCompile bool `json:"-"`
|
||||
Platform string `json:"-"`
|
||||
Architecture string `json:"-"`
|
||||
}
|
||||
|
||||
// Defaults sets the default project template
|
||||
@@ -335,6 +336,11 @@ func processBinaryName(po *ProjectOptions) {
|
||||
if po.BinaryName == "" {
|
||||
var binaryNameComputed = computeBinaryName(po.Name)
|
||||
po.BinaryName = Prompt("The output binary name", binaryNameComputed)
|
||||
if runtime.GOOS == "windows" {
|
||||
if !strings.HasSuffix(po.BinaryName, ".exe") {
|
||||
po.BinaryName += ".exe"
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println("Output binary Name: " + po.BinaryName)
|
||||
}
|
||||
|
||||
@@ -276,9 +276,9 @@ func CheckDependencies(logger *Logger) (bool, error) {
|
||||
switch distroInfo.Distribution {
|
||||
case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali, Neon, Deepin, Raspbian:
|
||||
libraryChecker = DpkgInstalled
|
||||
case Arch, ArcoLinux, ArchLabs, Manjaro, ManjaroARM:
|
||||
case Arch, ArcoLinux, Manjaro, ManjaroARM:
|
||||
libraryChecker = PacmanInstalled
|
||||
case CentOS, Fedora, Tumbleweed, Leap:
|
||||
case CentOS, Fedora:
|
||||
libraryChecker = RpmInstalled
|
||||
case Gentoo:
|
||||
libraryChecker = EqueryInstalled
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.4",
|
||||
"react": "^16.13.0",
|
||||
"react-dom": "^16.13.0",
|
||||
"core-js": "^3.1.4",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6",
|
||||
"wails-react-scripts": "3.0.1-2",
|
||||
"react-modal": "3.11.2",
|
||||
"@wailsapp/runtime": "^1.0.10"
|
||||
"react-modal": "3.8.1",
|
||||
"@wailsapp/runtime": "^1.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
|
||||
@@ -8,21 +8,21 @@
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.4",
|
||||
"core-js": "^3.6.1",
|
||||
"regenerator-runtime": "^0.13.3",
|
||||
"vue": "^2.6.11",
|
||||
"@wailsapp/runtime": "^1.0.10"
|
||||
"vue": "^2.5.22",
|
||||
"@wailsapp/runtime": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^4.2.3",
|
||||
"@vue/cli-plugin-eslint": "^4.2.3",
|
||||
"@vue/cli-service": "^4.2.3",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-plugin-vue": "^6.2.1",
|
||||
"@vue/cli-plugin-babel": "^3.4.0",
|
||||
"@vue/cli-plugin-eslint": "^3.4.0",
|
||||
"@vue/cli-service": "^3.4.0",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"eslint": "^5.8.0",
|
||||
"eslint-plugin-vue": "^5.0.0",
|
||||
"eventsource-polyfill": "^0.9.6",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
"webpack-hot-middleware": "^2.25.0"
|
||||
"vue-template-compiler": "^2.5.21",
|
||||
"webpack-hot-middleware": "^2.24.3"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
|
||||
@@ -7,24 +7,24 @@
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.4",
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.1",
|
||||
"regenerator-runtime": "^0.13.3",
|
||||
"material-design-icons-iconfont": "^5.0.1",
|
||||
"vue": "^2.5.22",
|
||||
"vuetify": "^1.5.14",
|
||||
"@wailsapp/runtime": "^1.0.10"
|
||||
"@wailsapp/runtime": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^4.2.3",
|
||||
"@vue/cli-plugin-eslint": "^4.2.3",
|
||||
"@vue/cli-service": "^4.2.3",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-plugin-vue": "^6.2.1",
|
||||
"@vue/cli-plugin-babel": "^3.4.0",
|
||||
"@vue/cli-plugin-eslint": "^3.4.0",
|
||||
"@vue/cli-service": "^3.4.0",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"eslint": "^5.8.0",
|
||||
"eslint-plugin-vue": "^5.0.0",
|
||||
"eventsource-polyfill": "^0.9.6",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
"webpack-hot-middleware": "^2.25.0"
|
||||
"vue-template-compiler": "^2.5.21",
|
||||
"webpack-hot-middleware": "^2.24.3"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
|
||||
@@ -8,23 +8,23 @@
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.4",
|
||||
"core-js": "^3.6.1",
|
||||
"regenerator-runtime": "^0.13.3",
|
||||
"vue": "^2.6.11",
|
||||
"vuetify": "^2.2.15",
|
||||
"@wailsapp/runtime": "^1.0.10"
|
||||
"vue": "^2.5.22",
|
||||
"vuetify": "^2.0.15",
|
||||
"@wailsapp/runtime": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@mdi/font": "^4.9.95",
|
||||
"@vue/cli-plugin-babel": "^4.2.3",
|
||||
"@vue/cli-plugin-eslint": "^4.2.3",
|
||||
"@vue/cli-service": "^4.2.3",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-plugin-vue": "^6.2.1",
|
||||
"@mdi/font": "^4.3.95",
|
||||
"@vue/cli-plugin-babel": "^3.4.0",
|
||||
"@vue/cli-plugin-eslint": "^3.4.0",
|
||||
"@vue/cli-service": "^3.4.0",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"eslint": "^5.8.0",
|
||||
"eslint-plugin-vue": "^5.0.0",
|
||||
"eventsource-polyfill": "^0.9.6",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
"webpack-hot-middleware": "^2.25.0"
|
||||
"vue-template-compiler": "^2.5.21",
|
||||
"webpack-hot-middleware": "^2.24.3"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package cmd
|
||||
|
||||
// Version - Wails version
|
||||
const Version = "v1.6.0-pre2"
|
||||
const Version = "v1.0.2"
|
||||
|
||||
@@ -6,21 +6,11 @@ import (
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/leaanthony/slicer"
|
||||
"github.com/leaanthony/spinner"
|
||||
"github.com/wailsapp/wails/cmd"
|
||||
)
|
||||
|
||||
// getSupportedPlatforms returns a slice of platform/architecture
|
||||
// targets that are buildable using the cross-platform 'x' option.
|
||||
func getSupportedPlatforms() []string {
|
||||
return []string{
|
||||
"darwin/amd64",
|
||||
"linux/amd64",
|
||||
"linux/arm-7",
|
||||
"windows/amd64",
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
var packageApp = false
|
||||
@@ -40,15 +30,8 @@ func init() {
|
||||
BoolFlag("f", "Force rebuild of application components", &forceRebuild).
|
||||
BoolFlag("d", "Build in Debug mode", &debugMode).
|
||||
BoolFlag("verbose", "Verbose output", &verbose).
|
||||
StringFlag("t", "Generate Typescript definitions to given file (at runtime)", &typescriptFilename)
|
||||
|
||||
var b strings.Builder
|
||||
for _, plat := range getSupportedPlatforms() {
|
||||
fmt.Fprintf(&b, " - %s\n", plat)
|
||||
}
|
||||
initCmd.StringFlag("x",
|
||||
fmt.Sprintf("Cross-compile application to specified platform via xgo\n%s", b.String()),
|
||||
&platform)
|
||||
StringFlag("t", "Generate Typescript definitions to given file (at runtime)", &typescriptFilename).
|
||||
StringFlag("x", "Cross-compile application to specified platform via xgo", &platform)
|
||||
|
||||
initCmd.Action(func() error {
|
||||
|
||||
@@ -74,25 +57,6 @@ func init() {
|
||||
return fmt.Errorf("Unable to find 'project.json'. Please check you are in a Wails project directory")
|
||||
}
|
||||
|
||||
// Set cross-compile
|
||||
projectOptions.Platform = runtime.GOOS
|
||||
if len(platform) > 0 {
|
||||
supported := false
|
||||
for _, plat := range getSupportedPlatforms() {
|
||||
if plat == platform {
|
||||
supported = true
|
||||
}
|
||||
}
|
||||
if !supported {
|
||||
return fmt.Errorf("Unsupported platform '%s' specified.\nPlease run `wails build -h` to see the supported platform/architecture options.", platform)
|
||||
}
|
||||
|
||||
projectOptions.CrossCompile = true
|
||||
plat := strings.Split(platform, "/")
|
||||
projectOptions.Platform = plat[0]
|
||||
projectOptions.Architecture = plat[1]
|
||||
}
|
||||
|
||||
// Validate config
|
||||
// Check if we have a frontend
|
||||
err = cmd.ValidateFrontendConfig(projectOptions)
|
||||
@@ -171,6 +135,29 @@ func init() {
|
||||
buildSpinner.Success()
|
||||
}
|
||||
|
||||
// Set cross-compile
|
||||
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]
|
||||
}
|
||||
|
||||
// Check supported platforms
|
||||
supportedPlatforms := slicer.String([]string{"linux/amd64", "linux/386", "windows/amd64", "windows/386", "darwin/amd64"})
|
||||
targetPlatform := projectOptions.Platform + "/" + projectOptions.Architecture
|
||||
if !supportedPlatforms.Contains(targetPlatform) {
|
||||
println("\n*** WARNING: Unsupported target platform", targetPlatform+".", "Supported:", supportedPlatforms.Join(", "))
|
||||
}
|
||||
}
|
||||
|
||||
err = cmd.BuildApplication(projectOptions.BinaryName, forceRebuild, buildMode, packageApp, projectOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
2
go.mod
2
go.mod
@@ -10,7 +10,7 @@ require (
|
||||
github.com/kennygrant/sanitize v1.2.4
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
||||
github.com/leaanthony/mewn v0.10.7
|
||||
github.com/leaanthony/slicer v1.4.0
|
||||
github.com/leaanthony/slicer v1.4.1
|
||||
github.com/leaanthony/spinner v0.5.3
|
||||
github.com/mattn/go-colorable v0.1.1 // indirect
|
||||
github.com/mattn/go-isatty v0.0.7 // indirect
|
||||
|
||||
4
go.sum
4
go.sum
@@ -28,8 +28,8 @@ github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/leaanthony/mewn v0.10.7 h1:jCcNJyIUOpwj+I5SuATvCugDjHkoo+j6ubEOxxrxmPA=
|
||||
github.com/leaanthony/mewn v0.10.7/go.mod h1:CRkTx8unLiSSilu/Sd7i1LwrdaAL+3eQ3ses99qGMEQ=
|
||||
github.com/leaanthony/slicer v1.4.0 h1:Q9u4w+UBU4WHjXnEDdz+eRLMKF/rnyosRBiqULnc1J8=
|
||||
github.com/leaanthony/slicer v1.4.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
|
||||
github.com/leaanthony/slicer v1.4.1 h1:X/SmRIDhkUAolP79mSTO0jTcVX1k504PJBqvV6TwP0w=
|
||||
github.com/leaanthony/slicer v1.4.1/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
|
||||
github.com/leaanthony/spinner v0.5.3 h1:IMTvgdQCec5QA4qRy0wil4XsRP+QcG1OwLWVK/LPZ5Y=
|
||||
github.com/leaanthony/spinner v0.5.3/go.mod h1:oHlrvWicr++CVV7ALWYi+qHk/XNA91D9IJ48IqmpVUo=
|
||||
github.com/leaanthony/synx v0.1.0 h1:R0lmg2w6VMb8XcotOwAe5DLyzwjLrskNkwU7LLWsyL8=
|
||||
|
||||
@@ -42,12 +42,12 @@ type Bridge struct {
|
||||
server *http.Server
|
||||
|
||||
lock sync.Mutex
|
||||
sessions map[string]*session
|
||||
sessions map[string]session
|
||||
}
|
||||
|
||||
// Initialise the Bridge Renderer
|
||||
func (h *Bridge) Initialise(appConfig interfaces.AppConfig, ipcManager interfaces.IPCManager, eventManager interfaces.EventManager) error {
|
||||
h.sessions = map[string]*session{}
|
||||
h.sessions = map[string]session{}
|
||||
h.ipcManager = ipcManager
|
||||
h.appConfig = appConfig
|
||||
h.eventManager = eventManager
|
||||
@@ -70,11 +70,13 @@ func (h *Bridge) wsBridgeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (h *Bridge) startSession(conn *websocket.Conn) {
|
||||
s := newSession(conn,
|
||||
h.bindingCache,
|
||||
h.ipcManager,
|
||||
logger.NewCustomLogger("BridgeSession"),
|
||||
h.eventManager)
|
||||
s := session{
|
||||
conn: conn,
|
||||
bindingCache: h.bindingCache,
|
||||
ipc: h.ipcManager,
|
||||
log: h.log,
|
||||
eventManager: h.eventManager,
|
||||
}
|
||||
|
||||
conn.SetCloseHandler(func(int, string) error {
|
||||
h.log.Infof("Connection dropped [%s].", s.Identifier())
|
||||
@@ -158,7 +160,7 @@ func (h *Bridge) NotifyEvent(event *messages.EventData) error {
|
||||
}
|
||||
|
||||
message := fmt.Sprintf("window.wails._.Notify('%s','%s')", event.Name, data)
|
||||
dead := []*session{}
|
||||
dead := []session{}
|
||||
for _, session := range h.sessions {
|
||||
err := session.evalJS(message, notifyMessage)
|
||||
if err != nil {
|
||||
@@ -205,9 +207,6 @@ func (h *Bridge) SetTitle(title string) {
|
||||
// for the Renderer interface
|
||||
func (h *Bridge) Close() {
|
||||
h.log.Debug("Shutting down")
|
||||
for _, session := range h.sessions {
|
||||
session.Shutdown()
|
||||
}
|
||||
err := h.server.Close()
|
||||
if err != nil {
|
||||
h.log.Errorf(err.Error())
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package renderer
|
||||
|
||||
import (
|
||||
"time"
|
||||
"unsafe"
|
||||
"sync"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/leaanthony/mewn"
|
||||
@@ -21,22 +20,7 @@ type session struct {
|
||||
ipc interfaces.IPCManager
|
||||
|
||||
// Mutex for writing to the socket
|
||||
shutdown chan bool
|
||||
writeChan chan []byte
|
||||
|
||||
done bool
|
||||
}
|
||||
|
||||
func newSession(conn *websocket.Conn, bindingCache []string, ipc interfaces.IPCManager, logger *logger.CustomLogger, eventMgr interfaces.EventManager) *session {
|
||||
return &session{
|
||||
conn: conn,
|
||||
bindingCache: bindingCache,
|
||||
ipc: ipc,
|
||||
log: logger,
|
||||
eventManager: eventMgr,
|
||||
shutdown: make(chan bool),
|
||||
writeChan: make(chan []byte, 100),
|
||||
}
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
// Identifier returns a string identifier for the remote connection.
|
||||
@@ -49,15 +33,19 @@ func (s *session) Identifier() string {
|
||||
}
|
||||
|
||||
func (s *session) sendMessage(msg string) error {
|
||||
if !s.done {
|
||||
s.writeChan <- *(*[]byte)(unsafe.Pointer(&msg))
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
if err := s.conn.WriteMessage(websocket.TextMessage, []byte(msg)); err != nil {
|
||||
s.log.Debug(err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *session) start(firstSession bool) {
|
||||
s.log.Infof("Connected to frontend.")
|
||||
go s.writePump()
|
||||
|
||||
wailsRuntime := mewn.String("../../runtime/assets/wails.js")
|
||||
s.evalJS(wailsRuntime, wailsRuntimeMessage)
|
||||
@@ -86,10 +74,6 @@ func (s *session) start(firstSession bool) {
|
||||
s.log.Debugf("Got message: %#v\n", string(buffer))
|
||||
|
||||
s.ipc.Dispatch(string(buffer), s.Callback)
|
||||
|
||||
if s.done {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,38 +83,8 @@ func (s *session) Callback(data string) error {
|
||||
}
|
||||
|
||||
func (s *session) evalJS(js string, mtype messageType) error {
|
||||
|
||||
// Prepend message type to message
|
||||
return s.sendMessage(mtype.toString() + js)
|
||||
}
|
||||
|
||||
// Shutdown
|
||||
func (s *session) Shutdown() {
|
||||
s.done = true
|
||||
s.shutdown <- true
|
||||
s.log.Debugf("session %v exit", s.Identifier())
|
||||
}
|
||||
|
||||
// writePump pulls messages from the writeChan and sends them to the client
|
||||
// since it uses a channel to read the messages the socket is protected without locks
|
||||
func (s *session) writePump() {
|
||||
s.log.Debugf("Session %v - writePump start", s.Identifier())
|
||||
for {
|
||||
select {
|
||||
case msg, ok := <-s.writeChan:
|
||||
s.conn.SetWriteDeadline(time.Now().Add(1 * time.Second))
|
||||
if !ok {
|
||||
s.log.Debug("writeChan was closed!")
|
||||
s.conn.WriteMessage(websocket.CloseMessage, []byte{})
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.conn.WriteMessage(websocket.TextMessage, msg); err != nil {
|
||||
s.log.Debug(err.Error())
|
||||
return
|
||||
}
|
||||
case <-s.shutdown:
|
||||
break
|
||||
}
|
||||
}
|
||||
s.log.Debug("writePump exiting...")
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -139,7 +139,7 @@ struct webview_priv
|
||||
#define DEFAULT_URL \
|
||||
"data:text/" \
|
||||
"html,%3C%21DOCTYPE%20html%3E%0A%3Chtml%20lang=%22en%22%3E%0A%3Chead%3E%" \
|
||||
"3Cmeta%20charset=%22utf-8%22%3E%3Cmeta%20http-equiv=%22IE=edge%22%" \
|
||||
"3Cmeta%20charset=%22utf-8%22%3E%3Cmeta%20http-equiv=%22IE=edge%22%" \
|
||||
"20content=%22IE=edge%22%3E%3C%2Fhead%3E%0A%3Cbody%3E%3Cdiv%20id=%22app%22%" \
|
||||
"3E%3C%2Fdiv%3E%3Cscript%20type=%22text%2Fjavascript%22%3E%3C%2Fscript%3E%" \
|
||||
"3C%2Fbody%3E%0A%3C%2Fhtml%3E"
|
||||
@@ -1227,7 +1227,7 @@ struct webview_priv
|
||||
}
|
||||
VariantInit(&myURL);
|
||||
myURL.vt = VT_BSTR;
|
||||
// #ifndef UNICODE
|
||||
// #ifndef UNICODE
|
||||
{
|
||||
wchar_t *buffer = webview_to_utf16(webPageName);
|
||||
if (buffer == NULL)
|
||||
@@ -1237,9 +1237,9 @@ struct webview_priv
|
||||
myURL.bstrVal = SysAllocString(buffer);
|
||||
GlobalFree(buffer);
|
||||
}
|
||||
// #else
|
||||
// myURL.bstrVal = SysAllocString(webPageName);
|
||||
// #endif
|
||||
// #else
|
||||
// myURL.bstrVal = SysAllocString(webPageName);
|
||||
// #endif
|
||||
if (!myURL.bstrVal)
|
||||
{
|
||||
badalloc:
|
||||
@@ -1277,7 +1277,7 @@ struct webview_priv
|
||||
if (!SafeArrayAccessData(sfArray, (void **)&pVar))
|
||||
{
|
||||
pVar->vt = VT_BSTR;
|
||||
// #ifndef UNICODE
|
||||
// #ifndef UNICODE
|
||||
{
|
||||
wchar_t *buffer = webview_to_utf16(url);
|
||||
if (buffer == NULL)
|
||||
@@ -1287,9 +1287,9 @@ struct webview_priv
|
||||
bstr = SysAllocString(buffer);
|
||||
GlobalFree(buffer);
|
||||
}
|
||||
// #else
|
||||
// bstr = SysAllocString(url);
|
||||
// #endif
|
||||
// #else
|
||||
// bstr = SysAllocString(url);
|
||||
// #endif
|
||||
if ((pVar->bstrVal = bstr))
|
||||
{
|
||||
htmlDoc2->lpVtbl->write(htmlDoc2, sfArray);
|
||||
@@ -1444,12 +1444,12 @@ struct webview_priv
|
||||
rect.right - rect.left, rect.bottom - rect.top,
|
||||
HWND_DESKTOP, NULL, hInstance, (void *)w);
|
||||
#else
|
||||
w->priv.hwnd =
|
||||
w->priv.hwnd =
|
||||
CreateWindowEx(0, classname, w->title, style, rect.left, rect.top,
|
||||
rect.right - rect.left, rect.bottom - rect.top,
|
||||
HWND_DESKTOP, NULL, hInstance, (void *)w);
|
||||
#endif
|
||||
|
||||
|
||||
if (w->priv.hwnd == 0)
|
||||
{
|
||||
OleUninitialize();
|
||||
@@ -1466,7 +1466,8 @@ struct webview_priv
|
||||
#else
|
||||
SetWindowText(w->priv.hwnd, w->title);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
ShowWindow(w->priv.hwnd, SW_SHOWDEFAULT);
|
||||
UpdateWindow(w->priv.hwnd);
|
||||
SetFocus(w->priv.hwnd);
|
||||
@@ -1493,11 +1494,6 @@ struct webview_priv
|
||||
case WM_KEYDOWN:
|
||||
case WM_KEYUP:
|
||||
{
|
||||
// Disable refresh when pressing F5 on windows
|
||||
if (msg.wParam == VK_F5)
|
||||
{
|
||||
break;
|
||||
}
|
||||
HRESULT r = S_OK;
|
||||
IWebBrowser2 *webBrowser2;
|
||||
IOleObject *browser = *w->priv.browser;
|
||||
@@ -1607,7 +1603,7 @@ struct webview_priv
|
||||
|
||||
WEBVIEW_API void webview_set_title(struct webview *w, const char *title)
|
||||
{
|
||||
#ifdef UNICODE
|
||||
#ifdef UNICODE
|
||||
wchar_t *u16title = webview_to_utf16(title);
|
||||
if (u16title == NULL)
|
||||
{
|
||||
@@ -1615,11 +1611,12 @@ struct webview_priv
|
||||
}
|
||||
SetWindowText(w->priv.hwnd, u16title);
|
||||
GlobalFree(u16title);
|
||||
#else
|
||||
#else
|
||||
SetWindowText(w->priv.hwnd, title);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen)
|
||||
{
|
||||
if (w->priv.is_fullscreen == !!fullscreen)
|
||||
@@ -1930,26 +1927,22 @@ struct webview_priv
|
||||
[script setValue:self forKey:@"external"];
|
||||
}
|
||||
|
||||
static void webview_run_input_open_panel(id self, SEL cmd, id webview,
|
||||
id listener, BOOL allowMultiple)
|
||||
{
|
||||
static void webview_run_input_open_panel(id self, SEL cmd, id webview,
|
||||
id listener, BOOL allowMultiple) {
|
||||
char filename[256] = "";
|
||||
struct webview *w =
|
||||
(struct webview *)objc_getAssociatedObject(self, "webview");
|
||||
|
||||
webview_dialog(w, WEBVIEW_DIALOG_TYPE_OPEN, WEBVIEW_DIALOG_FLAG_FILE, "", "",
|
||||
filename, 255);
|
||||
filename[255] = '\0';
|
||||
if (strlen(filename) > 0)
|
||||
{
|
||||
if (strlen(filename)) {
|
||||
[listener chooseFilename:[NSString stringWithUTF8String:filename]];
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
[listener cancel];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void webview_external_invoke(id self, SEL cmd, id arg)
|
||||
{
|
||||
struct webview *w =
|
||||
@@ -1962,7 +1955,7 @@ struct webview_priv
|
||||
{
|
||||
return;
|
||||
}
|
||||
w->external_invoke_cb(w, [(NSString *)(arg) UTF8String]);
|
||||
w->external_invoke_cb(w, [(NSString *)(arg)UTF8String]);
|
||||
}
|
||||
|
||||
WEBVIEW_API int webview_init(struct webview *w)
|
||||
|
||||
@@ -108,8 +108,7 @@ export function Notify(eventName, data) {
|
||||
try {
|
||||
parsedData = JSON.parse(data);
|
||||
} catch (e) {
|
||||
e.message =
|
||||
Error('Invalid JSON data sent to notify [Event name = ' + eventName + '] ' + e.toString());
|
||||
Error('Invalid JSON data sent to notify. Event name = ' + eventName);
|
||||
}
|
||||
}
|
||||
// Do the callback
|
||||
|
||||
2799
runtime/js/package-lock.json
generated
2799
runtime/js/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@wailsapp/runtime",
|
||||
"version": "1.0.11",
|
||||
"version": "1.0.10",
|
||||
"description": "Wails Javascript runtime library",
|
||||
"main": "main.js",
|
||||
"types": "runtime.d.ts",
|
||||
@@ -25,4 +25,4 @@
|
||||
"devDependencies": {
|
||||
"dts-gen": "^0.5.8"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
12
runtime/js/runtime/runtime.d.ts
vendored
12
runtime/js/runtime/runtime.d.ts
vendored
@@ -6,12 +6,12 @@ declare const wailsapp__runtime: {
|
||||
OpenURL(url: string): Promise<any>;
|
||||
};
|
||||
Events: {
|
||||
Acknowledge(eventName: string): void;
|
||||
Emit(eventName: string, data?: any): void;
|
||||
Heartbeat(eventName: string, timeInMilliseconds: number, callback: (data?: any) => void): void;
|
||||
On(eventName: string, callback: (data?: any) => void): void;
|
||||
OnMultiple(eventName: string, callback: (data?: any) => void, maxCallbacks: number): void;
|
||||
Once(eventName: string, callback: (data?: any) => void): void;
|
||||
Acknowledge(eventName: string): void;
|
||||
Emit(eventName: string): void;
|
||||
Heartbeat(eventName: string, timeInMilliseconds: number, callback: () => void): void;
|
||||
On(eventName: string, callback: () => void): void;
|
||||
OnMultiple(eventName: string, callback: () => void, maxCallbacks: number): void;
|
||||
Once(eventName: string, callback: () => void): void;
|
||||
};
|
||||
Init(callback: () => void): void;
|
||||
Log: {
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "**** Checking if Wails passes unit tests ****"
|
||||
if ! go test ./...
|
||||
then
|
||||
echo ""
|
||||
echo "ERROR: Unit tests failed!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# Build runtime
|
||||
echo "**** Building Runtime ****"
|
||||
cd runtime/js
|
||||
@@ -23,23 +15,9 @@ cd lib/renderer
|
||||
mewn
|
||||
cd ../..
|
||||
|
||||
|
||||
cd cmd/wails
|
||||
echo "**** Checking if Wails compiles ****"
|
||||
if ! go build .
|
||||
then
|
||||
echo ""
|
||||
echo "ERROR: Build failed!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
echo "**** Installing Wails locally ****"
|
||||
if ! go install
|
||||
then
|
||||
echo ""
|
||||
echo "ERROR: Install failed!"
|
||||
exit 1;
|
||||
fi
|
||||
cd cmd/wails
|
||||
go install
|
||||
cd ../..
|
||||
|
||||
echo "**** Tidying the mods! ****"
|
||||
|
||||
Reference in New Issue
Block a user