diff --git a/WindowsCrossCompiling.md b/WindowsCrossCompiling.md new file mode 100644 index 000000000..797091c72 --- /dev/null +++ b/WindowsCrossCompiling.md @@ -0,0 +1,118 @@ +# Building Windows Go programs on Linux + +See [here](https://go.dev/doc/install/source#environment) for available `GOOS` and `GOARCH` values. + +## Go version >= 1.5 + +Since Go version 1.5 cross-compiling of pure Go executables has become very easy. Try it out with the code below. More can be found at this blog post by [Dave Cheney][1]. + +[1]: http://dave.cheney.net/2015/08/22/cross-compilation-with-go-1-5 + +```go +$ cat hello.go +package main + +import "fmt" + +func main() { + fmt.Printf("Hello\n") +} +$ GOOS=windows GOARCH=386 go build -o hello.exe hello.go +``` + +In cmd.exe instead of PowerShell: + +```go +$ set GOOS=windows +$ set GOARCH=386 +$ go build -o hello.exe hello.go +``` + +You can now run `hello.exe` on a Windows machine near you. + +Note that the command above will silently rebuild most of standard library, and for this reason will be quite slow. To speed-up the process, you can install all the windows-amd64 standard packages on your system with + +``` +GOOS=windows GOARCH=amd64 go install +``` + +Note also that `cgo` is disabled when cross-compiling, so any file that mentions `import "C"` will be silently ignored (See https://github.com/golang/go/issues/24068). In order to use cgo, or any of the build modes `c-archive`, `c-shared`, `shared`, `plugin`, you need to have a C cross-compiler. + + +## Older Go version (<1.5) + +I use linux/386, but, I suspect, this procedure will apply to other host platforms as well. + +Preparation (if needed): +```sh +sudo apt-get install gcc +export go env GOROOT +``` + +First step is to build host version of go: + +```sh +cd $GOROOT/src +sudo -E GOOS=windows GOARCH=386 PATH=$PATH ./make.bash +``` + +Next you need to build the rest of go compilers and linkers. I have small program to do that: + +```sh +$ cat ~/bin/buildcmd +#!/bin/sh +set -e +for arch in 8 6; do + for cmd in a c g l; do + go tool dist install -v cmd/$arch$cmd + done +done +exit 0 +``` + +Last step is to build Windows versions of standard commands and libraries. I have a small script for that too: + +```sh +$ cat ~/bin/buildpkg +#!/bin/sh +if [ -z "$1" ]; then + echo 'GOOS is not specified' 1>&2 + exit 2 +else + export GOOS=$1 + if [ "$GOOS" = "windows" ]; then + export CGO_ENABLED=0 + fi +fi +shift +if [ -n "$1" ]; then + export GOARCH=$1 +fi +cd $GOROOT/src +go tool dist install -v pkg/runtime +go install -v -a std +``` + +I run it like that: + +```sh +$ ~/bin/buildpkg windows 386 +``` + +to build Windows/386 version of Go commands and packages. You can probably see from my script that I exclude building of any cgo related parts — these will not work for me, since I do not have correspondent gcc cross-compiling tools installed. So I just skip those. + +Now we're ready to build our Windows executable: + +```go +$ cat hello.go +package main + +import "fmt" + +func main() { + fmt.Printf("Hello\n") +} +$ GOOS=windows GOARCH=386 go build -o hello.exe hello.go +``` + +We just need to find a Windows computer to run our `hello.exe`. \ No newline at end of file