go-to-wheel

February 10, 2026 ยท View on GitHub

PyPI Changelog Tests License

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

OptionDescriptionDefault
--name NAMEPython package nameDirectory basename
--version VERSIONPackage version0.1.0
--output-dir DIRDirectory for built wheels./dist
--entry-point NAMECLI command nameSame as package name
--platforms PLATFORMSComma-separated list of targetsAll supported platforms
--go-binary PATHPath to Go binarygo
--description TEXTPackage description"Go binary packaged as Python wheel"
--license LICENSELicense identifierNone
--author AUTHORAuthor nameNone
--author-email EMAILAuthor emailNone
--url URLProject URLNone
--requires-python VERSIONPython version requirement>=3.10
--readme PATHPath to README markdown file for PyPI long descriptionNone
--set-version-var VARGo variable to set to --version value via -X ldflagNone
--ldflags FLAGSAdditional 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

PlatformWheel Tag
linux-amd64manylinux_2_17_x86_64
linux-arm64manylinux_2_17_aarch64
linux-amd64-muslmusllinux_1_2_x86_64
linux-arm64-muslmusllinux_1_2_aarch64
darwin-amd64macosx_10_9_x86_64
darwin-arm64macosx_11_0_arm64
windows-amd64win_amd64
windows-arm64win_arm64

How it works

  1. Cross-compiles the Go binary using GOOS and GOARCH environment variables with CGO_ENABLED=0 for static binaries
  2. Creates a Python package with a thin wrapper that execs the bundled binary
  3. 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:

uv run pytest

See also