GitHub - simonw/go-to-wheel: Wrap Go binaries in Python wheels (original) (raw)
Compile Go CLI programs into Python wheels.
This tool takes a Go module directory, cross-compiles it for multiple platforms, and produces properly-tagged Python wheels that can be installed via pip or pipx to get the Go binary on your PATH.
See Distributing Go binaries like sqlite-scanner through PyPI using go-to-wheel for background on this project.
Installation
pip install go-to-wheel
or
pipx install go-to-wheel
Requires Go to be installed and available in your PATH.
Quick start
Build wheels for all platforms from a Go module:
go-to-wheel path/to/go-module
This will create wheels in a ./dist directory for Linux (glibc and musl), macOS (Intel and Apple Silicon), and Windows (amd64 and arm64).
Usage
go-to-wheel path/to/go-folder [options]
Options
| Option | Description | Default |
|---|---|---|
| --name NAME | Python package name | Directory basename |
| --version VERSION | Package version | 0.1.0 |
| --output-dir DIR | Directory for built wheels | ./dist |
| --entry-point NAME | CLI command name | Same as package name |
| --platforms PLATFORMS | Comma-separated list of targets | All supported platforms |
| --go-binary PATH | Path to Go binary | go |
| --description TEXT | Package description | "Go binary packaged as Python wheel" |
| --license LICENSE | License identifier | None |
| --author AUTHOR | Author name | None |
| --author-email EMAIL | Author email | None |
| --url URL | Project URL | None |
| --requires-python VERSION | Python version requirement | >=3.10 |
| --readme PATH | Path to README markdown file for PyPI long description | None |
| --set-version-var VAR | Go variable to set to --version value via -X ldflag | None |
| --ldflags FLAGS | Additional Go linker flags (appended to default -s -w) | None |
Examples
Build wheels with a custom package name:
go-to-wheel ./mytool --name my-python-tool
Build for specific platforms only:
go-to-wheel ./mytool --platforms linux-amd64,darwin-arm64
Embed the wheel version into the Go binary at compile time (requires a var version in your Go source):
go-to-wheel ./mytool --version 2.0.0 --set-version-var main.version
This passes -X main.version=2.0.0 to the Go linker, so the compiled binary knows its own version without hardcoding it in the Go source. A typical Go pattern for this:
var version = "dev"
func main() { if os.Args[1] == "--version" { fmt.Println(version) // prints "2.0.0" when built with --set-version-var } }
Pass arbitrary Go linker flags with --ldflags:
go-to-wheel ./mytool --version 2.0.0
--ldflags "-X main.version=2.0.0 -X main.commit=abc123"
The flags are appended to the default -s -w, so the full linker invocation becomes -ldflags="-s -w -X main.version=2.0.0 -X main.commit=abc123".
Build with full metadata for PyPI:
go-to-wheel ./mytool
--name mytool-bin
--version 2.0.0
--description "My awesome tool"
--license MIT
--author "Jane Doe"
--author-email "jane@example.com"
--url "https://github.com/jane/mytool"
--readme README.md
Supported platforms
| Platform | Wheel Tag |
|---|---|
| linux-amd64 | manylinux_2_17_x86_64 |
| linux-arm64 | manylinux_2_17_aarch64 |
| linux-amd64-musl | musllinux_1_2_x86_64 |
| linux-arm64-musl | musllinux_1_2_aarch64 |
| darwin-amd64 | macosx_10_9_x86_64 |
| darwin-arm64 | macosx_11_0_arm64 |
| windows-amd64 | win_amd64 |
| windows-arm64 | win_arm64 |
How it works
- Cross-compiles the Go binary using
GOOSandGOARCHenvironment variables withCGO_ENABLED=0for static binaries - Creates a Python package with a thin wrapper that
execs the bundled binary - Packages everything into a wheel with the correct platform tag
The resulting wheel can be installed with pip:
pip install ./dist/mytool-1.0.0-py3-none-manylinux_2_17_x86_64.whl
Or tested directly with uv:
uv run --with ./dist/mytool-1.0.0-py3-none-manylinux_2_17_x86_64.whl mytool --help
Development
Clone the repository:
git clone https://github.com/simonw/go-to-wheel cd go-to-wheel
Run tests:
See also
- maturin - The Rust equivalent that inspired this tool
- pip-binary-factory - Template for packaging pre-built binaries