-
Notifications
You must be signed in to change notification settings - Fork 17
Home
xcgo is a maximalist Docker image for cross-compiling and
releasing/distributing CGo-enabled Go/Golang applications. At this time, it can build and dist
macOS, Windows and Linux CGo projects for arch amd64.
xcgo has what gophers crave:
go 1.14-
OSX SDKCatalina /macOS 10.15 dockersnapcraftgoreleasergolangci-lintmage-
zshandoh-my-zsh - and a bunch of other stuff.
The primary source of documentation for xcgo is the wiki. Start there. There's a companion example project (neilotoole/sqlitr) that was created explicitly to exhibit xcgo: it demonstrates pretty much the entire array of xcgo's capabilities, showing how to release to brew, scoop, snap, Docker Hub, GitHub, etc. The neilotoole/xcgo images are published to Docker Hub.
Note: No effort has yet been made to provide support for other archs such as
386(or for an OS beyond the typical three), but pull requests are welcome. Note also that no effort has been made to make this image slim.xcgoby mission is maximalist (it's a 3GB+ image), but I'm sure theDockerfilecan be slimmed down. Again, pull requests are welcome.
You can test xcgo with:
$ docker run -it neilotoole/xcgo:latest go version
go version go1.14 linux/amd64To play around in the container, launch into a shell:
$ docker run -it neilotoole/xcgo:latest zshxcgo doesn't prescribe a particular usage approach. Some possibilities:
- Launch a container shell session, clone your repo, and build (or even edit and do all your work) within the container.
- Mount your local repo into the container, shell in, and build from within the container.
- With local repo mounted, invoke
xcgowithgoreleaser: this is pretty typical.
Let's look at a few of these approaches:
From inside the docker container, we'll build (amd64) binaries for macOS, Linux, and Windows.
$ git clone https://github.com/neilotoole/sqlitr.git && cd sqlitr
$ GOOS=darwin GOARCH=amd64 CC=o64-clang CXX=o64-clang++ go build -o dist/darwin_amd64/sqlitr
$ GOOS=linux GOARCH=amd64 go build -o dist/linux_amd64/sqlitr
$ GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ go build -o dist/windows_amd64/sqlitr.exeYou should end up with something like this:
$ tree ./dist
./dist
├── darwin_amd64
│ └── sqlitr
├── linux_amd64
│ └── sqlitr
└── windows_amd64
└── sqlitr.exeRunning file on each of the binaries:
./dist/darwin_amd64/sqlitr: Mach-O 64-bit x86_64 executable, flags:<NOUNDEFS|DYLDLINK|TWOLEVEL>
./dist/linux_amd64/sqlitr: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=9a130449828e21fc5ef935582d889bba0344432c, not stripped
./dist/windows_amd64/sqlitr.exe: PE32+ executable (console) x86-64, for MS WindowsNote that the linux binary listed above is dynamically linked. There are additional steps you can take to statically link instead (useful if you're distributing on an Alpine image for example). See sqlitr .goreleaser.yml
build_linuxsection.
Quite possibly you'll want to use xcgo in conjunction
with goreleaser.
Again, we'll use sqlitr to demonstrate. On your local machine, clone the sqlitr repo, mount it into the xcgo container and run goreleaser.
$ git clone https://github.com/neilotoole/sqlitr.git && cd sqlitr
$ docker run --rm --privileged \
-v $(pwd):/go/src/github.com/neilotoole/sqlitr \
-v /var/run/docker.sock:/var/run/docker.sock \
-w /go/src/github.com/neilotoole/sqlitr \
neilotoole/xcgo:latest goreleaser --snapshot --rm-distThe above will build that CGo project via goreleaser with binaries for macOS, Linux, and Windows.
$ tree ./dist 130 master
./dist
├── build_linux_linux_amd64
│ └── sqlitr
├── build_macos_darwin_amd64
│ └── sqlitr
├── build_windows_windows_amd64
│ └── sqlitr.exe
├── checksums.txt
├── config.yaml
├── goreleaserdocker393975300
│ ├── Dockerfile
│ ├── LICENSE
│ ├── README.md
│ ├── sqlitr
│ └── testdata
│ └── example.sqlite
├── sqlitr_v0.1.23-snapshot_darwin_amd64.tar.gz
├── sqlitr_v0.1.23-snapshot_linux_amd64
│ └── prime
│ ├── meta
│ │ └── snap.yaml
│ └── sqlitr
├── sqlitr_v0.1.23-snapshot_linux_amd64.deb
├── sqlitr_v0.1.23-snapshot_linux_amd64.rpm
├── sqlitr_v0.1.23-snapshot_linux_amd64.snap
├── sqlitr_v0.1.23-snapshot_linux_amd64.tar.gz
└── sqlitr_v0.1.23-snapshot_windows_amd64.zipThe above example uses goreleaser --snapshot. To actually publish artifacts (brew, scoop, snap, dockerhub, etc), you need to inject appropriate secrets into the xcgo container. In this next example we pass secrets for GitHub, docker, and snapcraft.
Note that this example actually won't succeed for you (as you don't have the secrets)
docker run --rm --privileged \
-v $(pwd):/go/src/github.com/neilotoole/sqlitr \
-v /var/run/docker.sock:/var/run/docker.sock \
-e "GITHUB_TOKEN=$GITHUB_TOKEN" \
-e "DOCKER_USERNAME=$DOCKER_USERNAME" -e "DOCKER_PASSWORD=$DOCKER_PASSWORD" -e "DOCKER_REGISTRY=$DOCKER_REGISTRY" \
-v "${HOME}/.snapcraft.login":/.snapcraft.login \
-w /go/src/github.com/neilotoole/sqlitr \
neilotoole/xcgo:latest goreleaser --rm-distAgain, see the neilotoole/sqlitr example project for more.
Some params that can be passed to xcgo (as args to docker run):
-
Docker:
-e DOCKER_USERNAME=X -e DOCKER_PASSWORD=XWhen present,
xcgo'sentrypoint.shperforms adocker login. Supply-e DOCKER_REGISTRY=Xto use a registry other than Docker Hub. -
GitHub:
-e GITHUB_TOKEN=Xor-e GORELEASER_GITHUB_TOKEN=XUsed to publish artifacts to GitHub (e.g. by
goreleaser). -
Snapcraft:
-v "${HOME}/.snapcraft.login":/.snapcraft.loginWhen
/.snapcraft.loginis present in thexcgocontainer,entrypoint.shperforms asnapcraftlogin. This enables uses ofsnapcraft, e.g. bygoreleaserto publish asnap. Supply-e SNAPCRAFT_LOGIN_FILE=/other/place/.snapcraft.loginto specify an alternative mount location for the login file. See the wiki for more.