ko
ko copied to clipboard
Look at zig for cross-platform CGO builds
Most of the solutions I've seen for doing cross-platform builds involves doing virtualization inside docker containers for each target platform. This doesn't really work for ko
, because I'd like to be able to use it in environments where I don't have (or want to have) docker installed.
I came across https://github.com/ziglang/zig/issues/7342 which seems to indicate that it's (almost?) possible to use zig with go to do this painlessly. I'd like for this to work without ko
having any knowledge of what's happening, just some stuff users can set in their environment to make it work, e.g.:
# More likely in .ko.yaml, but the default "static" image lacks libc... maybe make default based on CGO_ENABLED?
KO_DEFAULTBASEIMAGE="gcr.io/distroless/base"
CGO_ENABLED=1
CC="zig cc"
# Proposal from current issue, subject to change
ZIG_CGO=1
This way, we won't have to land any changes to ko
for this to work (other than documenting it).
This issue is stale because it has been open for 90 days with no
activity. It will automatically close after 30 more days of
inactivity. Reopen the issue with /reopen
. Mark the issue as
fresh by adding the comment /remove-lifecycle stale
.
This might be what we need https://github.com/dosgo/zigtool
With that zigtool shim:
cmd/foo/foo.go
:
package main
//int Add(int a, int b){
// return a+b;
//}
import "C"
import "fmt"
func main() {
a := C.int(10)
b := C.int(20)
c := C.Add(a, b)
fmt.Println(c) // 30
}
CC=zigcc CXX=zigcpp CGO_ENABLED=1 ko publish --platform linux/arm64 ./cmd/foo/
2021/11/29 17:00:15 Using base gcr.io/distroless/static:nonroot for github.com/google/ko/cmd/foo
2021/11/29 17:00:17 Building github.com/google/ko/cmd/foo for linux/arm64
2021/11/29 17:00:18 Loading kind.local/foo-8bf617b112fa676029b7bb7a9e1d7883:b5baa9b222de56dedba9befaeed7e7809f83489f534886b215c65d897f9bd57e2021/11/29 17:00:19 Loaded kind.local/foo-8bf617b112fa676029b7bb7a9e1d7883:b5baa9b222de56dedba9befaeed7e7809f83489f534886b215c65d897f9bd57e
2021/11/29 17:00:19 Adding tag latest
2021/11/29 17:00:19 Added tag latest
kind.local/foo-8bf617b112fa676029b7bb7a9e1d7883:b5baa9b222de56dedba9befaeed7e7809f83489f534886b215c65d897f9bd57e```
If that actually works, maybe we should just document this and link out to it?
Looks like there's still some rough edges, it looks like only amd64
and arm64
work, arm
, ppc64le
, and s390x
all fail with some cryptic errors https://gist.github.com/benmoss/8749e1a96375e48666b0b6c0f9ab7ca7
windows/amd64
works though!
We talked about this some today and came up with some ideas:
If CGO_ENABLED=1
explicitly, and you requested multiple platforms, we can check if zig
is installed and invoke it as your C compiler.
There's a slight wrinkle since zig
doesn't understand Go's GOARCH
/GOOS
, so we could do something like what https://github.com/dosgo/zigtool does and translate them.
Instead of depending on zigtool being installed, ko
can invoke zig
by doing CC="ko cc" GOARCH=foo go build
. ko cc
would be a new hidden command, that just translates GOARCH
etc into zig-consumable triplets, and invokes zig
. The benefit of this is that we'd know ko
is installed, and wouldn't need another tool just to do this translation.
(CC=
accepts quotes and spaces: https://go-review.googlesource.com/c/go/+/341936)
The next step is probably to start testing this out with something and seeing what breaks. Any explorers out there?
we w/@caarlos0 created an example project that shows how you can use GoReleaser and zig to cross-compile the go application with CGO:
https://github.com/goreleaser/zig-cross-compilation