gitlab.com/polyapp-open-source/poly@v0.0.0-20200304172929-90b164ae7520/cmd/build.go (about) 1 package cmd 2 3 import ( 4 "os" 5 "os/exec" 6 "path/filepath" 7 8 "github.com/spf13/cobra" 9 ) 10 11 // buildCmd represents the build command 12 //nolint 13 var buildCmd = &cobra.Command{ 14 Use: "build", 15 Short: "Runs go build across all main.go files", 16 Long: `Runs 'go list' to get a list of packages and then runs 'go build' 17 across each package individually with standard & GOOS=js GOARCH=wasm environments. 18 If GOOS=js GOARCH=wasm it builds the file and deposits it in ./public or 19 any other directory specified by the WASMOut parameter with the .wasm file extension. 20 If tinygo is installed it is used when GOOS=js GOARCH=wasm and the result is saved 21 as buildname_tinygo.wasm alongside the 'go build' output, buildname.wasm 22 GOOS=js and GOARCH=wasm makes an effort to not build code which could rely on non-js syscalls. 23 Results are collected and printed one after the other. Example output: 24 25 gledr@LAPTOP-AH6IAHBO MINGW64 ~/Polyapp_Apps/gocode/src/gitlab.com/polyapp-open-source/poly/testdata (CI-expansion) 26 $ poly build 27 ----- Command: C:\Go\bin\go.exe build -o C:\Users\gledr\Polyapp_Apps\gocode\src\gitlab.com\polyapp-open-source\poly\testdata\cmd\cmd.exe gitlab.com/polyapp-open-source/poly/testdata/cmd ----- GOOS: windows GOARCH: ----- 28 ----- Command: C:\Go\bin\go.exe build -o C:\Users\gledr\Polyapp_Apps\gocode\src\gitlab.com\polyapp-open-source\poly\testdata\cmd\hello\hello.exe gitlab.com/polyapp-open-source/poly/testdata/cmd/hello ----- GOOS: windows GOARCH: ----- 29 ----- Command: C:\Go\bin\go.exe build -ldflags=-s -w -o C:\Users\gledr\Polyapp_Apps\gocode\src\gitlab.com\polyapp-open-source\poly\testdata\cmd\wasm1\wasm1.wasm gitlab.com/polyapp-open-source/poly/testdata/cmd/wasm1 ----- GOOS: js GOARCH: wasm ----- 30 ----- Command: C:\Go\bin\go.exe build -ldflags=-s -w -o C:\Users\gledr\Polyapp_Apps\gocode\src\gitlab.com\polyapp-open-source\poly\testdata\cmd\wasm2\wasm2.wasm gitlab.com/polyapp-open-source/poly/testdata/cmd/wasm2 ----- GOOS: js GOARCH: wasm ----- 31 ----- Command: C:\Go\bin\go.exe build -ldflags=-s -w -o C:\Users\gledr\Polyapp_Apps\gocode\src\gitlab.com\polyapp-open-source\poly\testdata\cmd\wasm3\wasm3.wasm gitlab.com/polyapp-open-source/poly/testdata/cmd/wasm3 ----- GOOS: js GOARCH: wasm ----- 32 33 `, 34 Run: func(cmd *cobra.Command, args []string) { 35 exitCode := Build(cmd.Flag("WASMOut").Value.String()) 36 os.Exit(exitCode) 37 }, 38 } 39 40 func init() { 41 rootCmd.AddCommand(buildCmd) 42 buildCmd.Flags().String("WASMOut", "./public", "Place all compiled WASM binaries into this relative directory") 43 } 44 45 // Build performs the work of 'poly build'. 46 func Build(WASMOut string) (exitCode int) { //nolint 47 defaultPaths, JSWASMPaths := GetTargets() 48 49 defaultProcs := startDefaultBuild(defaultPaths) 50 51 JSWASMProcs := startWASMBuild(JSWASMPaths, WASMOut) 52 53 largestExitCode := 0 54 largestDefaultExitCode := waitAndResolveDefaultBuilds(defaultProcs) 55 if largestDefaultExitCode > largestExitCode { 56 largestExitCode = largestDefaultExitCode 57 } 58 largestWASMExitCode := waitAndResolveWASMBuilds(JSWASMProcs, JSWASMPaths) 59 if largestWASMExitCode > largestExitCode { 60 largestExitCode = largestWASMExitCode 61 } 62 63 return largestExitCode 64 } 65 66 // startWASMBuild spawns some processes to being a WASM build. 67 // We try to compile with both tinygo and regular 'go build' every time. 68 func startWASMBuild(JSWASMPaths []string, wasmOutPath string) (JSWASMProcs []*procInfo) { //nolint 69 JSWASMProcs = make([]*procInfo, len(JSWASMPaths)*2) 70 for i, targetPath := range JSWASMPaths { 71 var outputPath string 72 if wasmOutPath == "" { 73 outputPath = filepath.Join(ListPathToAbsPath(targetPath), GetOutputFileName(targetPath, regularGoWASM)) 74 } else { 75 outputPath = filepath.Join(ListPathToAbsPath(wasmOutPath), GetOutputFileName(targetPath, regularGoWASM)) 76 } 77 JSWASMProc := procInfo{ 78 Cmd: exec.Command("go", "build", "-ldflags=-s -w", "-o", outputPath, targetPath), 79 } 80 JSWASMProc.Cmd.Env = append(os.Environ(), "GOOS=js", "GOARCH=wasm") 81 JSWASMProc.Cmd.Stdout = &JSWASMProc.Stdout 82 JSWASMProc.Cmd.Stderr = &JSWASMProc.Stderr 83 JSWASMProc.StartError = JSWASMProc.Cmd.Start() 84 JSWASMProcs[i] = &JSWASMProc 85 } 86 for i, targetPath := range JSWASMPaths { 87 var outputPath string 88 if wasmOutPath == "" { 89 outputPath = filepath.Join(ListPathToAbsPath(targetPath), GetOutputFileName(targetPath, tinygoWASM)) 90 } else { 91 outputPath = filepath.Join(ListPathToAbsPath(wasmOutPath), GetOutputFileName(targetPath, tinygoWASM)) 92 } 93 JSWASMProc := procInfo{ 94 Cmd: exec.Command("tinygo", "build", "-o", outputPath, "-target", "wasm", targetPath), 95 } 96 JSWASMProc.Cmd.Stdout = &JSWASMProc.Stdout 97 JSWASMProc.Cmd.Stderr = &JSWASMProc.Stderr 98 JSWASMProc.StartError = JSWASMProc.Cmd.Start() 99 JSWASMProcs[i+len(JSWASMPaths)] = &JSWASMProc 100 } 101 return JSWASMProcs 102 } 103 104 func startDefaultBuild(defaultPaths []string) (defaultProcs []*procInfo) { 105 defaultProcs = make([]*procInfo, len(defaultPaths)) 106 for i, targetPath := range defaultPaths { 107 outputPath := filepath.Join(ListPathToAbsPath(targetPath), GetOutputFileName(targetPath, notWASM)) 108 defaultProc := procInfo{ 109 Cmd: exec.Command("go", "build", "-o", outputPath, targetPath), 110 } 111 defaultProc.Cmd.Stdout = &defaultProc.Stdout 112 defaultProc.Cmd.Stderr = &defaultProc.Stderr 113 defaultProc.StartError = defaultProc.Cmd.Start() 114 defaultProcs[i] = &defaultProc 115 } 116 return defaultProcs 117 } 118 119 // waitAndResolveWASMBuilds waits for the tinygo and regular 'go build' WASM builds. 120 // this function ignores tinygo errors when computing largestExitCode. 121 func waitAndResolveWASMBuilds(JSWASMProcs []*procInfo, JSWASMPaths []string) (largestExitCode int) { //nolint 122 largestExitCode = 0 123 for i, proc := range JSWASMProcs { 124 proc.WaitError = proc.Cmd.Wait() 125 proc.print() 126 osExitValue := proc.getExitValue() 127 if i < len(JSWASMPaths) { 128 // go build 129 if osExitValue > largestExitCode { 130 largestExitCode = osExitValue 131 } 132 } 133 // else tinygo build - don't report tinygo's exit code since tinygo need not be installed for build to succeed 134 } 135 return largestExitCode 136 } 137 138 // waitAndResolveDefaultBuilds waits for the default builds to finish and reports the largest exit code. 139 func waitAndResolveDefaultBuilds(defaultProcs []*procInfo) (largestExitCode int) { //nolint 140 for _, proc := range defaultProcs { 141 proc.WaitError = proc.Cmd.Wait() 142 proc.print() 143 osExitValue := proc.getExitValue() 144 if osExitValue > largestExitCode { 145 largestExitCode = osExitValue 146 } 147 } 148 return largestExitCode 149 }