Inital commit
This commit is contained in:
25
wails/tools/BUILD.bazel
Normal file
25
wails/tools/BUILD.bazel
Normal file
@@ -0,0 +1,25 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_binary")
|
||||
|
||||
go_binary(
|
||||
name = "build_assets_action",
|
||||
srcs = ["build_assets_action.go"],
|
||||
importpath = "github.com/Eriyc/rules_wails/wails/tools/build_assets_action",
|
||||
pure = "off",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "generate_bindings_action",
|
||||
srcs = ["generate_bindings_action.go"],
|
||||
importpath = "github.com/Eriyc/rules_wails/wails/tools/generate_bindings_action",
|
||||
pure = "off",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "launch_app",
|
||||
srcs = ["launch_app.go"],
|
||||
importpath = "github.com/Eriyc/rules_wails/wails/tools/launch_app",
|
||||
pure = "off",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
225
wails/tools/build_assets_action.go
Normal file
225
wails/tools/build_assets_action.go
Normal file
@@ -0,0 +1,225 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var appName string
|
||||
var binaryName string
|
||||
var configFile string
|
||||
var macOSMinimumSystemVersion string
|
||||
var manifestPath string
|
||||
var outDir string
|
||||
var wailsPath string
|
||||
|
||||
flag.StringVar(&appName, "app-name", "", "")
|
||||
flag.StringVar(&binaryName, "binary-name", "", "")
|
||||
flag.StringVar(&configFile, "config-file", "config.yml", "")
|
||||
flag.StringVar(&macOSMinimumSystemVersion, "macos-minimum-system-version", "", "")
|
||||
flag.StringVar(&manifestPath, "manifest", "", "")
|
||||
flag.StringVar(&outDir, "out", "", "")
|
||||
flag.StringVar(&wailsPath, "wails", "", "")
|
||||
flag.Parse()
|
||||
|
||||
require(manifestPath != "", "missing --manifest")
|
||||
require(outDir != "", "missing --out")
|
||||
require(wailsPath != "", "missing --wails")
|
||||
require(appName != "", "missing --app-name")
|
||||
require(binaryName != "", "missing --binary-name")
|
||||
|
||||
var err error
|
||||
wailsPath, err = filepath.Abs(wailsPath)
|
||||
must(err)
|
||||
must(resolveGoEnvToAbsolutePath())
|
||||
|
||||
tempRoot, err := os.MkdirTemp("", "rules-wails-build-assets-*")
|
||||
must(err)
|
||||
defer func() {
|
||||
_ = os.Chmod(tempRoot, 0o755)
|
||||
_ = os.RemoveAll(tempRoot)
|
||||
}()
|
||||
|
||||
workDir := filepath.Join(tempRoot, "work")
|
||||
homeDir := filepath.Join(tempRoot, "home")
|
||||
must(os.MkdirAll(workDir, 0o755))
|
||||
must(os.MkdirAll(homeDir, 0o755))
|
||||
must(stageManifest(manifestPath, workDir))
|
||||
|
||||
command := exec.Command(
|
||||
wailsPath,
|
||||
"update",
|
||||
"build-assets",
|
||||
"-name", appName,
|
||||
"-binaryname", binaryName,
|
||||
"-config", filepath.Join(workDir, configFile),
|
||||
"-dir", workDir,
|
||||
)
|
||||
command.Dir = workDir
|
||||
command.Env = append(os.Environ(),
|
||||
"HOME="+homeDir,
|
||||
"LC_ALL=C",
|
||||
"TZ=UTC",
|
||||
)
|
||||
command.Stdout = os.Stdout
|
||||
command.Stderr = os.Stderr
|
||||
must(command.Run())
|
||||
|
||||
updateMacOSMinimumVersion(filepath.Join(workDir, "darwin", "Info.plist"), macOSMinimumSystemVersion)
|
||||
updateMacOSMinimumVersion(filepath.Join(workDir, "darwin", "Info.dev.plist"), macOSMinimumSystemVersion)
|
||||
|
||||
must(os.RemoveAll(outDir))
|
||||
must(os.MkdirAll(outDir, 0o755))
|
||||
must(copyTree(workDir, outDir))
|
||||
}
|
||||
|
||||
func resolveGoEnvToAbsolutePath() error {
|
||||
goBinary := os.Getenv("GO_BIN")
|
||||
if goBinary == "" || filepath.IsAbs(goBinary) {
|
||||
return nil
|
||||
}
|
||||
|
||||
absolutePath, err := filepath.Abs(goBinary)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.Setenv("GO_BIN", absolutePath)
|
||||
}
|
||||
|
||||
func updateMacOSMinimumVersion(path string, minimumVersion string) {
|
||||
if minimumVersion == "" {
|
||||
return
|
||||
}
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err := os.Stat("/usr/libexec/PlistBuddy"); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
setCommand := exec.Command("/usr/libexec/PlistBuddy", "-c", "Set :LSMinimumSystemVersion "+minimumVersion, path)
|
||||
if err := setCommand.Run(); err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
addCommand := exec.Command("/usr/libexec/PlistBuddy", "-c", "Add :LSMinimumSystemVersion string "+minimumVersion, path)
|
||||
_ = addCommand.Run()
|
||||
}
|
||||
|
||||
func stageManifest(manifestPath string, destinationRoot string) error {
|
||||
entries, err := readManifest(manifestPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
destinationPath := filepath.Join(destinationRoot, entry.relativePath)
|
||||
if err := os.MkdirAll(filepath.Dir(destinationPath), 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := copyFile(entry.sourcePath, destinationPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readManifest(path string) ([]manifestEntry, error) {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
entries := make([]manifestEntry, 0)
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
parts := strings.SplitN(line, "\t", 2)
|
||||
if len(parts) != 2 {
|
||||
return nil, fmt.Errorf("invalid manifest line: %s", line)
|
||||
}
|
||||
entries = append(entries, manifestEntry{
|
||||
sourcePath: parts[0],
|
||||
relativePath: parts[1],
|
||||
})
|
||||
}
|
||||
|
||||
return entries, scanner.Err()
|
||||
}
|
||||
|
||||
func copyTree(sourceRoot string, destinationRoot string) error {
|
||||
return filepath.Walk(sourceRoot, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
relativePath, err := filepath.Rel(sourceRoot, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if relativePath == "." {
|
||||
return nil
|
||||
}
|
||||
|
||||
destinationPath := filepath.Join(destinationRoot, relativePath)
|
||||
if info.IsDir() {
|
||||
return os.MkdirAll(destinationPath, 0o755)
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(destinationPath), 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return copyFile(path, destinationPath)
|
||||
})
|
||||
}
|
||||
|
||||
func copyFile(sourcePath string, destinationPath string) error {
|
||||
sourceFile, err := os.Open(sourcePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer sourceFile.Close()
|
||||
|
||||
destinationFile, err := os.Create(destinationPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer destinationFile.Close()
|
||||
|
||||
if _, err := io.Copy(destinationFile, sourceFile); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return destinationFile.Chmod(0o644)
|
||||
}
|
||||
|
||||
func must(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func require(condition bool, message string) {
|
||||
if !condition {
|
||||
panic(message)
|
||||
}
|
||||
}
|
||||
|
||||
type manifestEntry struct {
|
||||
sourcePath string
|
||||
relativePath string
|
||||
}
|
||||
239
wails/tools/generate_bindings_action.go
Normal file
239
wails/tools/generate_bindings_action.go
Normal file
@@ -0,0 +1,239 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type repeatedFlag []string
|
||||
|
||||
func (value *repeatedFlag) String() string {
|
||||
return strings.Join(*value, ",")
|
||||
}
|
||||
|
||||
func (value *repeatedFlag) Set(input string) error {
|
||||
*value = append(*value, input)
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
var clean bool
|
||||
var extraArgs repeatedFlag
|
||||
var manifestPath string
|
||||
var mode string
|
||||
var outDir string
|
||||
var outputPath string
|
||||
var packageDir string
|
||||
var ts bool
|
||||
var wailsPath string
|
||||
|
||||
flag.BoolVar(&clean, "clean", true, "")
|
||||
flag.Var(&extraArgs, "extra-arg", "")
|
||||
flag.StringVar(&manifestPath, "manifest", "", "")
|
||||
flag.StringVar(&mode, "mode", "", "")
|
||||
flag.StringVar(&outDir, "out-dir", "", "")
|
||||
flag.StringVar(&outputPath, "out", "", "")
|
||||
flag.StringVar(&packageDir, "package-dir", "", "")
|
||||
flag.BoolVar(&ts, "ts", true, "")
|
||||
flag.StringVar(&wailsPath, "wails", "", "")
|
||||
flag.Parse()
|
||||
|
||||
require(mode != "", "missing --mode")
|
||||
require(outDir != "", "missing --out-dir")
|
||||
require(wailsPath != "", "missing --wails")
|
||||
|
||||
var err error
|
||||
wailsPath, err = filepath.Abs(wailsPath)
|
||||
must(err)
|
||||
must(resolveGoEnvToAbsolutePath())
|
||||
|
||||
switch mode {
|
||||
case "action":
|
||||
require(manifestPath != "", "missing --manifest")
|
||||
require(outputPath != "", "missing --out")
|
||||
must(runActionMode(manifestPath, outputPath, outDir, wailsPath, clean, ts, extraArgs))
|
||||
case "workspace":
|
||||
require(packageDir != "", "missing --package-dir")
|
||||
must(runWorkspaceMode(packageDir, outDir, wailsPath, clean, ts, extraArgs))
|
||||
default:
|
||||
panic("unsupported --mode")
|
||||
}
|
||||
}
|
||||
|
||||
func resolveGoEnvToAbsolutePath() error {
|
||||
goBinary := os.Getenv("GO_BIN")
|
||||
if goBinary == "" || filepath.IsAbs(goBinary) {
|
||||
return nil
|
||||
}
|
||||
|
||||
absolutePath, err := filepath.Abs(goBinary)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.Setenv("GO_BIN", absolutePath)
|
||||
}
|
||||
|
||||
func runActionMode(manifestPath string, outputPath string, outDir string, wailsPath string, clean bool, ts bool, extraArgs []string) error {
|
||||
tempRoot, err := os.MkdirTemp("", "rules-wails-bindings-*")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(tempRoot)
|
||||
|
||||
workDir := filepath.Join(tempRoot, "work")
|
||||
if err := os.MkdirAll(workDir, 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := stageManifest(manifestPath, workDir); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := runBindings(workDir, outDir, wailsPath, clean, ts, extraArgs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(outputPath); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.MkdirAll(outputPath, 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
return copyTree(filepath.Join(workDir, outDir), outputPath)
|
||||
}
|
||||
|
||||
func runWorkspaceMode(packageDir string, outDir string, wailsPath string, clean bool, ts bool, extraArgs []string) error {
|
||||
return runBindings(packageDir, outDir, wailsPath, clean, ts, extraArgs)
|
||||
}
|
||||
|
||||
func runBindings(cwd string, outDir string, wailsPath string, clean bool, ts bool, extraArgs []string) error {
|
||||
commandArgs := []string{"generate", "bindings", "-d", outDir}
|
||||
if clean {
|
||||
commandArgs = append(commandArgs, "-clean")
|
||||
}
|
||||
if ts {
|
||||
commandArgs = append(commandArgs, "-ts")
|
||||
}
|
||||
commandArgs = append(commandArgs, extraArgs...)
|
||||
|
||||
command := exec.Command(wailsPath, commandArgs...)
|
||||
command.Dir = cwd
|
||||
command.Stdout = os.Stdout
|
||||
command.Stderr = os.Stderr
|
||||
return command.Run()
|
||||
}
|
||||
|
||||
func stageManifest(manifestPath string, destinationRoot string) error {
|
||||
entries, err := readManifest(manifestPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
destinationPath := filepath.Join(destinationRoot, entry.relativePath)
|
||||
if err := os.MkdirAll(filepath.Dir(destinationPath), 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := copyFile(entry.sourcePath, destinationPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readManifest(path string) ([]manifestEntry, error) {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
entries := make([]manifestEntry, 0)
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
parts := strings.SplitN(line, "\t", 2)
|
||||
if len(parts) != 2 {
|
||||
return nil, fmt.Errorf("invalid manifest line: %s", line)
|
||||
}
|
||||
entries = append(entries, manifestEntry{
|
||||
sourcePath: parts[0],
|
||||
relativePath: parts[1],
|
||||
})
|
||||
}
|
||||
|
||||
return entries, scanner.Err()
|
||||
}
|
||||
|
||||
func copyTree(sourceRoot string, destinationRoot string) error {
|
||||
return filepath.Walk(sourceRoot, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
relativePath, err := filepath.Rel(sourceRoot, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if relativePath == "." {
|
||||
return nil
|
||||
}
|
||||
|
||||
destinationPath := filepath.Join(destinationRoot, relativePath)
|
||||
if info.IsDir() {
|
||||
return os.MkdirAll(destinationPath, 0o755)
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(destinationPath), 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return copyFile(path, destinationPath)
|
||||
})
|
||||
}
|
||||
|
||||
func copyFile(sourcePath string, destinationPath string) error {
|
||||
sourceFile, err := os.Open(sourcePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer sourceFile.Close()
|
||||
|
||||
destinationFile, err := os.Create(destinationPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer destinationFile.Close()
|
||||
|
||||
if _, err := io.Copy(destinationFile, sourceFile); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return destinationFile.Chmod(0o644)
|
||||
}
|
||||
|
||||
func must(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func require(condition bool, message string) {
|
||||
if !condition {
|
||||
panic(message)
|
||||
}
|
||||
}
|
||||
|
||||
type manifestEntry struct {
|
||||
sourcePath string
|
||||
relativePath string
|
||||
}
|
||||
139
wails/tools/launch_app.go
Normal file
139
wails/tools/launch_app.go
Normal file
@@ -0,0 +1,139 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var binaryPath string
|
||||
var buildAssetsPath string
|
||||
var frontendURL string
|
||||
var iconPath string
|
||||
var mode string
|
||||
|
||||
flag.StringVar(&binaryPath, "binary", "", "")
|
||||
flag.StringVar(&buildAssetsPath, "build-assets", "", "")
|
||||
flag.StringVar(&frontendURL, "frontend-url", "http://127.0.0.1:9245", "")
|
||||
flag.StringVar(&iconPath, "icon", "", "")
|
||||
flag.StringVar(&mode, "mode", "run", "")
|
||||
flag.Parse()
|
||||
|
||||
require(binaryPath != "", "missing --binary")
|
||||
require(buildAssetsPath != "", "missing --build-assets")
|
||||
|
||||
environment := os.Environ()
|
||||
if mode == "dev" && os.Getenv("FRONTEND_DEVSERVER_URL") == "" {
|
||||
environment = append(environment, "FRONTEND_DEVSERVER_URL="+frontendURL)
|
||||
}
|
||||
|
||||
if runtime.GOOS == "darwin" {
|
||||
os.Exit(runDarwin(binaryPath, buildAssetsPath, iconPath, mode, environment))
|
||||
}
|
||||
|
||||
command := exec.Command(binaryPath)
|
||||
command.Stdout = os.Stdout
|
||||
command.Stderr = os.Stderr
|
||||
command.Stdin = os.Stdin
|
||||
command.Env = environment
|
||||
if err := command.Run(); err != nil {
|
||||
if exitError, ok := err.(*exec.ExitError); ok {
|
||||
os.Exit(exitError.ExitCode())
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func runDarwin(binaryPath string, buildAssetsPath string, iconPath string, mode string, environment []string) int {
|
||||
appName := strings.TrimSuffix(filepath.Base(binaryPath), filepath.Ext(binaryPath))
|
||||
if appName == "" {
|
||||
appName = "wails-app"
|
||||
}
|
||||
|
||||
appDir := filepath.Join(os.TempDir(), appName+"-bazel-"+mode)
|
||||
defer os.RemoveAll(appDir)
|
||||
|
||||
appContents := filepath.Join(appDir, "Contents")
|
||||
appMacOS := filepath.Join(appContents, "MacOS")
|
||||
appResources := filepath.Join(appContents, "Resources")
|
||||
appBinary := filepath.Join(appMacOS, appName)
|
||||
|
||||
must(os.MkdirAll(appMacOS, 0o755))
|
||||
must(os.MkdirAll(appResources, 0o755))
|
||||
must(copyFile(binaryPath, appBinary, 0o755))
|
||||
|
||||
for _, candidate := range []string{
|
||||
filepath.Join(buildAssetsPath, "darwin", "Info.dev.plist"),
|
||||
filepath.Join(buildAssetsPath, "darwin", "Info.plist"),
|
||||
} {
|
||||
if mode != "dev" && strings.HasSuffix(candidate, "Info.dev.plist") {
|
||||
continue
|
||||
}
|
||||
if _, err := os.Stat(candidate); err == nil {
|
||||
must(copyFile(candidate, filepath.Join(appContents, "Info.plist"), 0o644))
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if iconPath != "" {
|
||||
if _, err := os.Stat(iconPath); err == nil {
|
||||
must(copyFile(iconPath, filepath.Join(appResources, filepath.Base(iconPath)), 0o644))
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := os.Stat("/usr/bin/codesign"); err == nil {
|
||||
codesign := exec.Command("/usr/bin/codesign", "--force", "--deep", "--sign", "-", appDir)
|
||||
_ = codesign.Run()
|
||||
}
|
||||
|
||||
command := exec.Command(appBinary)
|
||||
command.Stdout = os.Stdout
|
||||
command.Stderr = os.Stderr
|
||||
command.Stdin = os.Stdin
|
||||
command.Env = environment
|
||||
if err := command.Run(); err != nil {
|
||||
if exitError, ok := err.(*exec.ExitError); ok {
|
||||
return exitError.ExitCode()
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func copyFile(sourcePath string, destinationPath string, mode os.FileMode) error {
|
||||
sourceFile, err := os.Open(sourcePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer sourceFile.Close()
|
||||
|
||||
destinationFile, err := os.Create(destinationPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer destinationFile.Close()
|
||||
|
||||
if _, err := io.Copy(destinationFile, sourceFile); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return destinationFile.Chmod(mode)
|
||||
}
|
||||
|
||||
func must(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func require(condition bool, message string) {
|
||||
if !condition {
|
||||
panic(message)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user