Complete guide to building Go projects for multiple platforms.
- Overview
- Getting Started
- Features
- Configuration
- Usage Patterns
- Advanced Topics
- Reference Documentation
- Troubleshooting
go-multi-builder is a Bash script that simplifies building Go applications for multiple operating systems and architectures. It automates cross-compilation, provides parallel builds for speed, and offers comprehensive reporting.
- Time Savings: Build for multiple platforms in parallel
- Consistency: Same build process across all platforms
- Visibility: Clear reporting of build status and metrics
- Flexibility: Configure via CLI, env vars, or config files
- Reliability: Validates environment and provides helpful errors
curl -O https://raw.githubusercontent.com/acockrell/go-multi-builder/main/go-multi-build
chmod +x go-multi-buildgit clone https://github.com/acockrell/go-multi-builder.git
cd go-multi-builder
chmod +x go-multi-build# Download to a directory in your PATH
sudo curl -o /usr/local/bin/go-multi-build https://raw.githubusercontent.com/acockrell/go-multi-builder/main/go-multi-build
sudo chmod +x /usr/local/bin/go-multi-buildThe simplest usage requires no arguments if you're in a Go module directory:
./go-multi-buildThis will:
- Auto-detect the package name from
go.mod - Build for default platforms (linux/amd64, darwin/amd64, darwin/arm64)
- Output binaries to the current directory
-
Navigate to your Go project:
cd ~/my-go-project
-
Run the builder:
/path/to/go-multi-build
-
Check the output:
ls -lh myapp-*
You should see binaries like:
myapp-linux-amd64myapp-darwin-amd64myapp-darwin-arm64
Build multiple platforms simultaneously to save time:
./go-multi-build -POn a multi-core system, this can reduce build time by 50-70% when building for 3+ platforms.
When to use:
- Building for 3+ platforms
- Multi-core development machine
- CI/CD with sufficient resources
When to avoid:
- Limited CPU/memory
- Debugging build issues (sequential is clearer)
Automatically embed version information from git into your binaries:
./go-multi-build -vThis injects three variables into your main package:
main.Version- Git tag (or "dev")main.GitCommit- Short commit hashmain.BuildDate- UTC build timestamp
In your Go code:
package main
var (
Version = "dev"
GitCommit = "unknown"
BuildDate = "unknown"
)
func main() {
fmt.Printf("Version: %s (%s) built on %s\n", Version, GitCommit, BuildDate)
}Skip rebuilding platforms that already have binaries:
./go-multi-build -iUseful for:
- Iterative development
- Adding new platforms to existing builds
- Resuming interrupted builds
Compress binaries with UPX to reduce file size:
./go-multi-build -cRequirements:
- UPX must be installed (
brew install upxorapt-get install upx)
Compression ratios:
- Typically 40-60% size reduction
- No runtime performance impact (decompresses to memory)
Automatically displayed after builds complete:
Build Summary:
─────────────────────────────────────────────────
Status Platform Size Time
─────────────────────────────────────────────────
✓ linux/amd64 8.2M 3.45s
✓ darwin/arm64 8.1M 3.78s
⊙ windows/amd64 8.4M 0.00s
─────────────────────────────────────────────────
Total time: 7.23s
Legend:
- ✓ = Successfully built
- ⊙ = Skipped (incremental build)
- ✗ = Failed
Color-coded output for better readability:
- Green: Success messages
- Red: Error messages
- Yellow: Warnings
- Cyan: Info messages
- Blue: Verbose output
Disable with --no-color for:
- CI/CD logs
- Piping to files
- Terminal compatibility issues
Settings are applied in this order (later overrides earlier):
- Defaults - Built into the script
- Config File -
go-multi-build.conf - Environment Variables -
GO_BUILD_PLATFORMS, etc. - Command-Line Flags - Highest priority
Create go-multi-build.conf in your project root:
# Platforms to build
PLATFORMS="linux/amd64,linux/arm64,darwin/amd64,darwin/arm64,windows/amd64"
# Output directory
OUTPUT_DIR="./dist"
# Enable parallel builds
PARALLEL=true
# Enable compression
COMPRESS=true
# Custom ldflags
CUSTOM_LDFLAGS='-s -w -extldflags "-static"'See configuration.md for all options.
# Set platforms
export GO_BUILD_PLATFORMS="linux/amd64,windows/amd64"
# Run build
./go-multi-buildFlags always take highest priority:
./go-multi-build -P -p "linux/amd64,darwin/arm64" -o buildSee commands.md for complete flag reference.
Quick local builds for testing:
# Build only for your current platform
./go-multi-build -p "$(go env GOOS)/$(go env GOARCH)"
# Or use config file for dev
# go-multi-build.conf:
PLATFORMS="darwin/arm64" # Your local platform
OUTPUT_DIR="./build"Example GitHub Actions workflow:
- name: Build binaries
run: |
./go-multi-build -P -q -v -o distExample GitLab CI:
build:
script:
- ./go-multi-build -P -q -o dist
artifacts:
paths:
- dist/Recommended flags for CI/CD:
-q- Quiet mode (less log spam)-P- Parallel (faster builds)--no-color- Clean logs
Full production release with all features:
./go-multi-build \
-P \
-v \
-c \
--cleanup \
-o release \
-p "linux/amd64,linux/arm64,darwin/amd64,darwin/arm64,windows/amd64,windows/arm64"Or use a config file:
# release.conf
PLATFORMS="linux/amd64,linux/arm64,darwin/amd64,darwin/arm64,windows/amd64,windows/arm64"
OUTPUT_DIR="./release"
PARALLEL=true
COMPRESS=true
EMBED_VERSION=true
CUSTOM_LDFLAGS='-s -w -extldflags "-static"'Then:
CONFIG_FILE=release.conf ./go-multi-build --cleanupPass custom ldflags to strip symbols and reduce binary size:
./go-multi-build -l '-s -w -extldflags "-static"'Common ldflags:
-s- Strip symbol table-w- Strip DWARF debugging info-X main.Var=value- Set string variable-extldflags "-static"- Static linking
CGO Limitations:
go-multi-builder sets CGO_ENABLED=0 for pure Go cross-compilation. If your project requires CGO:
- You'll need platform-specific toolchains
- Consider building on native platforms instead
- Or use Docker with cross-compilation toolchains
Platform-Specific Issues:
- Windows: Produces
.exefiles automatically - Android: Requires Android NDK
- iOS: Cannot cross-compile (requires Xcode)
Verbose Mode:
./go-multi-build -VShows:
- Go version
- Directory operations
- Compression steps
- All build output
Dry Run:
Preview what will be built:
./go-multi-build --dry-runCommon Issues:
-
"Go is not installed"
- Solution: Install Go from https://golang.org/dl/
-
"go.mod not found"
- Solution: Run
go mod initin your project
- Solution: Run
-
Build fails for specific platform
- Check for platform-specific code
- Use build tags to exclude problematic code
- Configuration Reference - Complete configuration options
- Command Reference - All command-line flags and arguments
- Platform Support - Supported GOOS/GOARCH combinations
Problem: Script exits with error before building
Solutions:
- Ensure Go is installed:
go version - Check you're in a Go module:
ls go.mod - Run with verbose mode:
./go-multi-build -V
Problem: Binary built but won't execute on target platform
Solutions:
- Verify you built for correct platform
- Check for CGO dependencies (requires native builds)
- Ensure target has required shared libraries
- Try static linking:
-l '-extldflags "-static"'
Problem: Using -P flag causes builds to hang
Solutions:
- Try without
-Pto isolate issue - Check available memory
- Reduce number of platforms
- Check for zombie processes:
ps aux | grep go
Problem: -v flag doesn't embed version info
Solutions:
- Ensure you're in a git repository
- Check you have at least one tag:
git tag - Variables must be in
mainpackage - Variables must be declared as
var Version string
Problem: Output is plain text without colors
Solutions:
- Check terminal supports colors
- Remove
--no-colorflag if set - Check if output is piped (auto-disables colors)
- Verify
$TERMis set correctly
For more help, please open an issue on GitHub.