diff --git a/cmd/gio/gio.go b/cmd/gio/gio.go index 9ec96a3c..82f7c133 100644 --- a/cmd/gio/gio.go +++ b/cmd/gio/gio.go @@ -14,10 +14,10 @@ import ( ) var ( - target = flag.String("target", "", "specify target (ios, tvos, android)") + target = flag.String("target", "", "specify target (ios, tvos, android, js)") archNames = flag.String("arch", "", "specify architecture(s) to include") buildMode = flag.String("buildmode", "archive", "specify buildmode: archive or exe") - destPath = flag.String("o", "", "output file (Android .aar or .apk file) or directory (iOS/tvOS .framework)") + destPath = flag.String("o", "", "output file (Android .aar or .apk file) or directory (iOS/tvOS .framework or webassembly files)") appID = flag.String("appid", "org.gioui.app", "app identifier (for -buildmode=exe)") verbose = flag.Bool("v", false, "verbose output") ) @@ -46,7 +46,7 @@ func main() { os.Exit(2) } switch *target { - case "ios", "tvos", "android": + case "ios", "tvos", "android", "js": default: errorf("invalid -target %s\n", *target) } @@ -64,6 +64,8 @@ func main() { pkg: pkg, } switch *target { + case "js": + bi.archs = []string{"wasm"} case "ios", "tvos": // Only 64-bit support. bi.archs = []string{"arm64", "amd64"} @@ -89,6 +91,8 @@ func build(bi *buildInfo) error { } defer os.RemoveAll(tmpDir) switch *target { + case "js": + return buildJS(bi) case "ios", "tvos": return buildIOS(tmpDir, *target, bi) case "android": diff --git a/cmd/gio/jsbuild.go b/cmd/gio/jsbuild.go new file mode 100644 index 00000000..336881bf --- /dev/null +++ b/cmd/gio/jsbuild.go @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +package main + +import ( + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" +) + +func buildJS(bi *buildInfo) error { + out := *destPath + if out == "" { + out = filepath.Base(bi.pkg) + } + if err := os.MkdirAll(out, 0700); err != nil { + return err + } + cmd := exec.Command( + "go", + "build", + "-o", filepath.Join(out, "main.wasm"), + bi.pkg, + ) + cmd.Env = append( + os.Environ(), + "GOOS=js", + "GOARCH=wasm", + ) + _, err := runCmd(cmd) + if err != nil { + return err + } + const indexhtml = ` + +
+ + + + + + + + + + +` + if err := ioutil.WriteFile(filepath.Join(out, "index.html"), []byte(indexhtml), 0600); err != nil { + return err + } + goroot, err := runCmd(exec.Command("go", "env", "GOROOT")) + if err != nil { + return err + } + wasmjs := filepath.Join(goroot, "misc", "wasm", "wasm_exec.js") + if _, err := os.Stat(wasmjs); err != nil { + return fmt.Errorf("failed to find $GOROOT/misc/wasm/wasm_exec.js driver: %v", err) + } + return copyFile(filepath.Join(out, "wasm_exec.js"), wasmjs) +}