diff --git a/cmd/common/compile.go b/cmd/common/compile.go index 4e844708..5bca20d1 100644 --- a/cmd/common/compile.go +++ b/cmd/common/compile.go @@ -16,7 +16,8 @@ const makefileName = "Makefile" var defaultWasmOutput = filepath.Join("wasm", "workflow.wasm") // getBuildCmd returns a single step that builds the workflow and returns the WASM bytes. -func getBuildCmd(workflowRootFolder, mainFile, language string) (func() ([]byte, error), error) { +// If stripSymbols is true, debug symbols are stripped from the binary to reduce size. +func getBuildCmd(workflowRootFolder, mainFile, language string, stripSymbols bool) (func() ([]byte, error), error) { tmpPath := filepath.Join(workflowRootFolder, ".cre_build_tmp.wasm") switch language { case constants.WorkflowLanguageTypeScript: @@ -33,11 +34,15 @@ func getBuildCmd(workflowRootFolder, mainFile, language string) (func() ([]byte, }, nil case constants.WorkflowLanguageGolang: // Build the package (.) so all .go files (main.go, workflow.go, etc.) are compiled together + ldflags := "-buildid=" + if stripSymbols { + ldflags = "-buildid= -w -s" + } cmd := exec.Command( "go", "build", "-o", tmpPath, "-trimpath", - "-ldflags=-buildid= -w -s", + "-ldflags="+ldflags, ".", ) cmd.Dir = workflowRootFolder @@ -68,11 +73,15 @@ func getBuildCmd(workflowRootFolder, mainFile, language string) (func() ([]byte, }, nil default: // Build the package (.) so all .go files are compiled together + ldflags := "-buildid=" + if stripSymbols { + ldflags = "-buildid= -w -s" + } cmd := exec.Command( "go", "build", "-o", tmpPath, "-trimpath", - "-ldflags=-buildid= -w -s", + "-ldflags="+ldflags, ".", ) cmd.Dir = workflowRootFolder @@ -90,8 +99,10 @@ func getBuildCmd(workflowRootFolder, mainFile, language string) (func() ([]byte, } // CompileWorkflowToWasm compiles the workflow at workflowPath and returns the WASM binary. -// It runs the sequence of commands from getBuildCmds (make build + copy for WASM, or single build for Go/TS), then reads the temp WASM file. -func CompileWorkflowToWasm(workflowPath string) ([]byte, error) { +// If stripSymbols is true, debug symbols are stripped to reduce binary size (used for deploy). +// If false, debug symbols are kept for better error messages (used for simulate). +// For custom builds (WASM language with Makefile), stripSymbols has no effect. +func CompileWorkflowToWasm(workflowPath string, stripSymbols bool) ([]byte, error) { workflowRootFolder, workflowMainFile, err := WorkflowPathRootAndMain(workflowPath) if err != nil { return nil, fmt.Errorf("workflow path: %w", err) @@ -122,7 +133,7 @@ func CompileWorkflowToWasm(workflowPath string) ([]byte, error) { return nil, fmt.Errorf("unsupported workflow language for file %s", workflowMainFile) } - buildStep, err := getBuildCmd(workflowRootFolder, workflowMainFile, language) + buildStep, err := getBuildCmd(workflowRootFolder, workflowMainFile, language, stripSymbols) if err != nil { return nil, err } diff --git a/cmd/common/compile_test.go b/cmd/common/compile_test.go index aec71b63..0280c9f1 100644 --- a/cmd/common/compile_test.go +++ b/cmd/common/compile_test.go @@ -40,21 +40,21 @@ func TestFindMakefileRoot(t *testing.T) { func TestCompileWorkflowToWasm_Go_Success(t *testing.T) { t.Run("basic_workflow", func(t *testing.T) { path := deployTestdataPath("basic_workflow", "main.go") - wasm, err := CompileWorkflowToWasm(path) + wasm, err := CompileWorkflowToWasm(path, true) require.NoError(t, err) assert.NotEmpty(t, wasm) }) t.Run("configless_workflow", func(t *testing.T) { path := deployTestdataPath("configless_workflow", "main.go") - wasm, err := CompileWorkflowToWasm(path) + wasm, err := CompileWorkflowToWasm(path, true) require.NoError(t, err) assert.NotEmpty(t, wasm) }) t.Run("missing_go_mod", func(t *testing.T) { path := deployTestdataPath("missing_go_mod", "main.go") - wasm, err := CompileWorkflowToWasm(path) + wasm, err := CompileWorkflowToWasm(path, true) require.NoError(t, err) assert.NotEmpty(t, wasm) }) @@ -62,7 +62,7 @@ func TestCompileWorkflowToWasm_Go_Success(t *testing.T) { func TestCompileWorkflowToWasm_Go_Malformed_Fails(t *testing.T) { path := deployTestdataPath("malformed_workflow", "main.go") - _, err := CompileWorkflowToWasm(path) + _, err := CompileWorkflowToWasm(path, true) require.Error(t, err) assert.Contains(t, err.Error(), "failed to compile workflow") assert.Contains(t, err.Error(), "undefined: sdk.RemovedFunctionThatFailsCompilation") @@ -73,7 +73,7 @@ func TestCompileWorkflowToWasm_Wasm_Success(t *testing.T) { _ = os.Remove(wasmPath) t.Cleanup(func() { _ = os.Remove(wasmPath) }) - wasm, err := CompileWorkflowToWasm(wasmPath) + wasm, err := CompileWorkflowToWasm(wasmPath, true) require.NoError(t, err) assert.NotEmpty(t, wasm) @@ -89,14 +89,14 @@ func TestCompileWorkflowToWasm_Wasm_Fails(t *testing.T) { wasmPath := filepath.Join(wasmDir, "workflow.wasm") require.NoError(t, os.WriteFile(wasmPath, []byte("not really wasm"), 0600)) - _, err := CompileWorkflowToWasm(wasmPath) + _, err := CompileWorkflowToWasm(wasmPath, true) require.Error(t, err) assert.Contains(t, err.Error(), "no Makefile found") }) t.Run("make_build_fails", func(t *testing.T) { path := deployTestdataPath("wasm_make_fails", "wasm", "workflow.wasm") - _, err := CompileWorkflowToWasm(path) + _, err := CompileWorkflowToWasm(path, true) require.Error(t, err) assert.Contains(t, err.Error(), "failed to compile workflow") assert.Contains(t, err.Error(), "build output:") @@ -120,7 +120,7 @@ func TestCompileWorkflowToWasm_TS_Success(t *testing.T) { if err := install.Run(); err != nil { t.Skipf("bun install failed (network or cre-sdk): %v", err) } - wasm, err := CompileWorkflowToWasm(mainPath) + wasm, err := CompileWorkflowToWasm(mainPath, true) if err != nil { t.Skipf("TS compile failed (published cre-sdk may lack full layout): %v", err) } diff --git a/cmd/workflow/build/build.go b/cmd/workflow/build/build.go index f1d3cc7e..b58c7e1a 100644 --- a/cmd/workflow/build/build.go +++ b/cmd/workflow/build/build.go @@ -58,7 +58,7 @@ func execute(workflowFolder, outputPath string) error { outputPath = cmdcommon.EnsureWasmExtension(outputPath) ui.Dim("Compiling workflow...") - wasmBytes, err := cmdcommon.CompileWorkflowToWasm(resolvedPath) + wasmBytes, err := cmdcommon.CompileWorkflowToWasm(resolvedPath, true) if err != nil { ui.Error("Build failed:") return fmt.Errorf("failed to compile workflow: %w", err) diff --git a/cmd/workflow/deploy/compile.go b/cmd/workflow/deploy/compile.go index f2b1281d..4fa27b49 100644 --- a/cmd/workflow/deploy/compile.go +++ b/cmd/workflow/deploy/compile.go @@ -67,7 +67,7 @@ func (h *handler) Compile() error { h.runtimeContext.Workflow.Language = cmdcommon.GetWorkflowLanguage(workflowMainFile) } - wasmFile, err = cmdcommon.CompileWorkflowToWasm(resolvedWorkflowPath) + wasmFile, err = cmdcommon.CompileWorkflowToWasm(resolvedWorkflowPath, true) if err != nil { ui.Error("Build failed:") return fmt.Errorf("failed to compile workflow: %w", err) diff --git a/cmd/workflow/deploy/compile_test.go b/cmd/workflow/deploy/compile_test.go index 02317b11..acc2a30d 100644 --- a/cmd/workflow/deploy/compile_test.go +++ b/cmd/workflow/deploy/compile_test.go @@ -295,7 +295,7 @@ func outputPathWithExtensions(path string) string { // file content equals CompileWorkflowToWasm(workflowPath) + brotli + base64. func assertCompileOutputMatchesUnderlying(t *testing.T, simulatedEnvironment *chainsim.SimulatedEnvironment, inputs Inputs, ownerType string) { t.Helper() - wasm, err := cmdcommon.CompileWorkflowToWasm(inputs.WorkflowPath) + wasm, err := cmdcommon.CompileWorkflowToWasm(inputs.WorkflowPath, true) require.NoError(t, err) compressed, err := cmdcommon.CompressBrotli(wasm) require.NoError(t, err) diff --git a/cmd/workflow/simulate/simulate.go b/cmd/workflow/simulate/simulate.go index f5ce48ff..7899b58e 100644 --- a/cmd/workflow/simulate/simulate.go +++ b/cmd/workflow/simulate/simulate.go @@ -324,7 +324,7 @@ func (h *handler) Execute(inputs Inputs) error { spinner := ui.NewSpinner() spinner.Start("Compiling workflow...") - wasmFileBinary, err = cmdcommon.CompileWorkflowToWasm(resolvedWorkflowPath) + wasmFileBinary, err = cmdcommon.CompileWorkflowToWasm(resolvedWorkflowPath, false) spinner.Stop() if err != nil { ui.Error("Build failed:")