-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Problem
The TinyGo WebAssembly component rule contains a 50-line embedded bash script for environment setup, creating significant Windows compatibility issues and violating Bazel's hermetic build principles.
Current Implementation Issues
File: go/defs.bzl
(Lines 245-294)
# 50-line embedded bash script in Starlark!
wrapper_content = """#!/bin/bash
set -euo pipefail
# Resolve absolute paths for TinyGo requirements
if [[ "{tinygo_root}" = /* ]]; then
TINYGOROOT="{tinygo_root}"
else
TINYGOROOT="$(pwd)/{tinygo_root}"
fi
# Validate TINYGOROOT exists and has expected structure
if [[ ! -d "$TINYGOROOT" ]]; then
echo "Error: TINYGOROOT directory does not exist: $TINYGOROOT" >&2
exit 1
fi
# Create GOCACHE directory if it doesn't exist
mkdir -p "{cache_path}"
# Build absolute PATH from relative tool paths
TOOL_PATHS=""
{tool_path_resolution}
# Set up environment with absolute paths
export TINYGOROOT
export GOCACHE="{cache_path}"
export CGO_ENABLED="0"
export GO111MODULE="off"
export GOPROXY="direct"
export HOME="{home_path}"
export TMPDIR="{tmp_path}"
export PATH="$TOOL_PATHS"
# Execute TinyGo with resolved paths
exec "$@"
""".format(...)
Additional Issues
- Complex path resolution function (Lines 26-44) generates more shell code
- Tool path discovery logic embedded in shell instead of Starlark
- Environment variable construction done via string formatting instead of structured approach
Impact
- Windows incompatibility: Bash script won't run on Windows without WSL
- Complex debugging: 50+ lines of shell script are hard to debug when TinyGo builds fail
- Hermetic violations: Relies on system bash, shell utilities, and filesystem layout
- Maintenance burden: Shell logic embedded in Starlark is harder to test and maintain
- Security concerns: Complex shell scripts increase attack surface
Solution
Replace the embedded shell script with structured Starlark logic and ctx.actions.write
for environment setup.
Implementation Plan
-
Replace shell path resolution with Starlark:
def _build_tinygo_environment(ctx, tinygo_toolchain, tool_paths): """Build TinyGo environment using Starlark - THE BAZEL WAY""" # Calculate TINYGOROOT using Starlark path manipulation tinygo_root = "/".join(tinygo_toolchain.tinygo.path.split("/")[:-2]) # Build PATH using Starlark list operations path_components = [tool.dirname for tool in tool_paths] + ["/usr/bin", "/bin"] # Create environment file using ctx.actions.write env_content = """export TINYGOROOT="{}" export GOCACHE="{}" export PATH="{}" export CGO_ENABLED="0" """.format(tinygo_root, cache_path, ":".join(path_components)) env_file = ctx.actions.declare_file(ctx.label.name + "_env.sh") ctx.actions.write(output=env_file, content=env_content, is_executable=True) return env_file
-
Alternative: Use ctx.actions.run with env parameter:
# Instead of wrapper script, pass environment directly ctx.actions.run( executable = tinygo, arguments = tinygo_args, inputs = inputs, outputs = outputs, env = { "TINYGOROOT": tinygo_root, "GOCACHE": cache_path, "PATH": ":".join(path_components), "CGO_ENABLED": "0", }, mnemonic = "TinyGoCompile" )
-
Path validation in Starlark:
def _validate_tinygo_environment(ctx, tinygo_toolchain): """Validate TinyGo environment using Starlark checks""" tinygo_binary = tinygo_toolchain.tinygo if not tinygo_binary: fail("TinyGo binary not found in toolchain") # Use repository_ctx for file existence checks during toolchain setup # Runtime validation via separate action if needed
Files to Update
go/defs.bzl
- Replace embedded shell script with Starlark logicgo/defs.bzl
- Simplify_build_tool_path_resolution
functiongo/defs.bzl
- Update_compile_tinygo_module
to use structured environment
Research Required
- Test TinyGo's specific environment requirements
- Verify that
ctx.actions.run
env parameter works for complex toolchain setup - Check if any TinyGo-specific shell behavior needs preservation
Testing
- Test Go component compilation on Windows, macOS, and Linux
- Verify TinyGo cache handling works correctly
- Test with various Go module structures and dependencies
- Ensure wasm-opt integration still works
- Performance testing for large Go projects
Acceptance Criteria
- No embedded bash scripts in
go/defs.bzl
- All environment setup done via Starlark +
ctx.actions.write
orenv
parameter - Path resolution logic moved to Starlark functions
- Cross-platform compatibility verified (especially Windows)
- All TinyGo compilation features preserved
- Performance equal or better than current implementation
- Go component examples continue to work
Priority
MEDIUM-HIGH - Major Windows compatibility improvement, but more complex than other phases.
Dependencies
Independent issue, but benefits from completion of Issues #40 and #41 first.
Migration Strategy
This change affects the core Go compilation pipeline, so should be implemented carefully with comprehensive testing on all platforms.