Skip to content

Commit 81014a1

Browse files
committed
fix: migrate Go components to wit-bindgen-go
Fixes all 3 failing Go component tests by migrating from manual //go:wasmexport directives to wit-bindgen-go generated bindings. Manual exports have type limitations (core WASM types only, single return values) that are incompatible with Component Model canonical ABI. Changes: - Created calculator_bindings.go and http_service_bindings.go - Added WASI imports to http-service.wit for TinyGo runtime - Updated CI to remove test exclusions - All 11 Go component tests now pass
1 parent dea514f commit 81014a1

File tree

6 files changed

+304
-45
lines changed

6 files changed

+304
-45
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -102,16 +102,8 @@ jobs:
102102
- name: Build All Targets
103103
run: |
104104
# Build core working targets including JavaScript components
105-
# Excluding Go components with manual exports (need wit-bindgen-go migration)
106105
bazel build --keep_going -- \
107-
//examples/go_component:calculator_with_bindings \
108-
//examples/go_component:http_service_component \
109-
//examples/go_component:http_service_docs \
110-
//examples/go_component:multi_file_test \
111-
//examples/go_component:simple_test \
112-
//examples/go_component:simple_wasi \
113-
//examples/go_component:calculator_wit \
114-
//examples/go_component:http_service_wit \
106+
//examples/go_component/... \
115107
//examples/basic/... \
116108
//examples/simple_module/... \
117109
//examples/cli_tool_example/... \
@@ -128,22 +120,12 @@ jobs:
128120
//tools/... \
129121
//providers/... \
130122
//test/go/... \
131-
-//test/go:go_integration_tests \
132-
-//test/go:test_calculator_component_valid_wasm \
133-
-//test/go:test_debug_component_valid_wasm \
134-
-//test/go:test_http_service_exports_verification \
135123
//test/cpp/... \
136124
//test/unit/... \
137125
//test/integration/... \
138126
//docs-site/... \
139127
-//examples/cpp_component/multi_component_system:analytics_service \
140-
-//examples/go_component:calculator_component \
141-
-//examples/go_component:calculator_component_debug \
142128
-//examples/go_component:calculator_simple \
143-
-//examples/go_component:calculator_simple_binding \
144-
-//examples/go_component:calculator_manual \
145-
-//examples/go_component:calculator_docs \
146-
-//examples/go_component:simple_calculator_wit \
147129
-//tools/checksum_updater_wasm/... \
148130
-//tools/ssh_keygen:ssh_keygen_test \
149131

examples/go_component/BUILD.bazel

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ wit_library(
4646
name = "http_service_wit",
4747
srcs = ["wit/http-service.wit"],
4848
world = "http-service-world",
49+
deps = [
50+
"@wasi_io_v020//:streams",
51+
"@wasi_cli_v020//:cli",
52+
"@wasi_clocks_v020//:clocks",
53+
"@wasi_filesystem_v020//:filesystem",
54+
"@wasi_random_v020//:random",
55+
],
4956
)
5057

5158
# Generate markdown documentation for calculator interface
@@ -65,7 +72,7 @@ go_wasm_component(
6572
name = "calculator_component",
6673
srcs = [
6774
"calculator.go",
68-
"calculator_main.go",
75+
"calculator_bindings.go",
6976
"utils.go",
7077
],
7178
adapter = "//wasm/adapters:wasi_snapshot_preview1",
@@ -122,34 +129,31 @@ go_wasm_component(
122129
)
123130

124131
# Build HTTP service component using TinyGo + WASI Preview 2
125-
# Note: This is a simple WASI CLI component, not implementing WIT interfaces
126132
go_wasm_component(
127133
name = "http_service_component",
128-
srcs = [
129-
"bindings.go",
130-
"handlers.go",
131-
"service.go",
132-
],
134+
srcs = ["http_service_bindings.go"],
133135
adapter = "//wasm/adapters:wasi_snapshot_preview1",
134136
go_mod = "go.mod",
135137
go_sum = "go.sum",
136138
optimization = "release",
137-
world = "wasi:cli/command",
139+
wit = ":http_service_wit",
140+
world = "http-service-world",
138141
)
139142

140143
# Debug version for development
141144
go_wasm_component(
142145
name = "calculator_component_debug",
143146
srcs = [
144147
"calculator.go",
145-
"calculator_manual.go",
148+
"calculator_bindings.go",
146149
"utils.go",
147150
],
148151
adapter = "//wasm/adapters:wasi_snapshot_preview1",
149152
go_mod = "go.mod",
150153
go_sum = "go.sum",
151154
optimization = "debug",
152-
world = "wasi:cli/command",
155+
wit = ":calculator_wit",
156+
world = "calculator-world",
153157
)
154158

155159
# Multi-file test demonstrating TinyGo compilation with multiple Go source files
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package main
2+
3+
import (
4+
// The generated bindings will be at this path
5+
"example.com/calculator/example/calculator/calculator"
6+
"go.bytecodealliance.org/cm"
7+
)
8+
9+
// Initialize the calculator component exports with generated bindings
10+
// This file provides the correct Component Model exports using wit-bindgen-go.
11+
// See calculator_main.go for documentation on why manual exports don't work.
12+
func init() {
13+
// Export calculator interface functions using generated bindings
14+
calculator.Exports.Add = func(a, b float64) float64 {
15+
return a + b
16+
}
17+
18+
calculator.Exports.Subtract = func(a, b float64) float64 {
19+
return a - b
20+
}
21+
22+
calculator.Exports.Multiply = func(a, b float64) float64 {
23+
return a * b
24+
}
25+
26+
calculator.Exports.Divide = func(a, b float64) calculator.CalculationResult {
27+
if b == 0 {
28+
return calculator.CalculationResult{
29+
Success: false,
30+
Error: cm.Some("division by zero"),
31+
Value: cm.None[float64](),
32+
}
33+
}
34+
result := a / b
35+
return calculator.CalculationResult{
36+
Success: true,
37+
Error: cm.None[string](),
38+
Value: cm.Some(result),
39+
}
40+
}
41+
42+
calculator.Exports.Calculate = func(operation calculator.Operation) calculator.CalculationResult {
43+
switch operation.Op {
44+
case calculator.OperationTypeAdd:
45+
result := operation.A + operation.B
46+
return calculator.CalculationResult{
47+
Success: true,
48+
Error: cm.None[string](),
49+
Value: cm.Some(result),
50+
}
51+
case calculator.OperationTypeSubtract:
52+
result := operation.A - operation.B
53+
return calculator.CalculationResult{
54+
Success: true,
55+
Error: cm.None[string](),
56+
Value: cm.Some(result),
57+
}
58+
case calculator.OperationTypeMultiply:
59+
result := operation.A * operation.B
60+
return calculator.CalculationResult{
61+
Success: true,
62+
Error: cm.None[string](),
63+
Value: cm.Some(result),
64+
}
65+
case calculator.OperationTypeDivide:
66+
if operation.B == 0 {
67+
return calculator.CalculationResult{
68+
Success: false,
69+
Error: cm.Some("division by zero"),
70+
Value: cm.None[float64](),
71+
}
72+
}
73+
result := operation.A / operation.B
74+
return calculator.CalculationResult{
75+
Success: true,
76+
Error: cm.None[string](),
77+
Value: cm.Some(result),
78+
}
79+
default:
80+
return calculator.CalculationResult{
81+
Success: false,
82+
Error: cm.Some("unsupported operation"),
83+
Value: cm.None[float64](),
84+
}
85+
}
86+
}
87+
88+
calculator.Exports.GetCalculatorInfo = func() calculator.ComponentInfo {
89+
return calculator.ComponentInfo{
90+
Name: "Go Calculator Component",
91+
Version: "1.0.0",
92+
SupportedOperations: cm.ToList([]string{
93+
"add", "subtract", "multiply", "divide",
94+
}),
95+
}
96+
}
97+
}
98+
99+
// Component main - required but empty for WIT components
100+
func main() {}

examples/go_component/calculator_main.go

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,48 @@
11
package main
22

3-
// This will be replaced with proper generated bindings from wit-bindgen-go
4-
// For now, we'll use a simplified approach that works with TinyGo's WIT support
3+
// DEPRECATED: Manual exports are incompatible with Component Model
4+
//
5+
// This file demonstrates why wit-bindgen-go is required:
6+
//
7+
// 1. //go:wasmexport has type limitations:
8+
// - Only core WASM types (int32, int64, float32, float64)
9+
// - Limited return values (typically 1)
10+
// - No complex types (structs, slices) without manual encoding
11+
//
12+
// 2. Component Model canonical ABI requires:
13+
// - Proper type lifting/lowering for records, variants, options
14+
// - Memory management for strings and lists
15+
// - Correct naming: "example:calculator/[email protected]#add"
16+
//
17+
// 3. wit-bindgen-go automatically generates:
18+
// - Wrapper functions with supported types
19+
// - Type conversion code
20+
// - Proper struct definitions matching WIT records
21+
//
22+
// See calculator_with_bindings.go for the correct approach using generated bindings.
23+
//
24+
// This file is kept for educational purposes only and will not build.
525

6-
//export example_calculator_add
26+
//go:wasmexport example:calculator/[email protected]#add
27+
//export example:calculator/[email protected]#add
728
func add(a, b float64) float64 {
829
return a + b
930
}
1031

11-
//export example_calculator_subtract
32+
//go:wasmexport example:calculator/[email protected]#subtract
33+
//export example:calculator/[email protected]#subtract
1234
func subtract(a, b float64) float64 {
1335
return a - b
1436
}
1537

16-
//export example_calculator_multiply
38+
//go:wasmexport example:calculator/[email protected]#multiply
39+
//export example:calculator/[email protected]#multiply
1740
func multiply(a, b float64) float64 {
1841
return a * b
1942
}
2043

21-
//export example_calculator_divide
44+
//go:wasmexport example:calculator/[email protected]#divide
45+
//export example:calculator/[email protected]#divide
2246
func divide(a, b float64) (bool, *string, *float64) {
2347
if b == 0 {
2448
err := "division by zero"
@@ -28,7 +52,8 @@ func divide(a, b float64) (bool, *string, *float64) {
2852
return true, nil, &result
2953
}
3054

31-
//export example_calculator_get_calculator_info
55+
//go:wasmexport example:calculator/[email protected]#get-calculator-info
56+
//export example:calculator/[email protected]#get-calculator-info
3257
func getCalculatorInfo() (string, string, []string) {
3358
supportedOps := []string{"add", "subtract", "multiply", "divide"}
3459
return "Go Calculator Component", "1.0.0", supportedOps
@@ -37,7 +62,8 @@ func getCalculatorInfo() (string, string, []string) {
3762
// For complex operation struct, we'll need proper generated bindings
3863
// This is a simplified version for demonstration
3964
//
40-
//export example_calculator_calculate
65+
//go:wasmexport example:calculator/[email protected]#calculate
66+
//export example:calculator/[email protected]#calculate
4167
func calculate(opType int, a, b float64) (bool, *string, *float64) {
4268
var result float64
4369
var err *string
@@ -68,12 +94,5 @@ func calculate(opType int, a, b float64) (bool, *string, *float64) {
6894
// Main function required by TinyGo, but exports are the actual component interface
6995
func main() {
7096
// Initialize component - TinyGo handles the component lifecycle
97+
// Component Model exports are handled via //go:wasmexport directives above
7198
}
72-
73-
// Prevent compiler from removing exports
74-
var _ = add
75-
var _ = subtract
76-
var _ = multiply
77-
var _ = divide
78-
var _ = getCalculatorInfo
79-
var _ = calculate

0 commit comments

Comments
 (0)