I recently needed to test some app on windows, and while cross-compiling in Go is straight-forward, the app had some C code and apparently on Arch Linux the mingw64-gcc package is misconfigured.
After some head scratching I figured out a workaround until the package is fixed (task #4313), you have to link your Go code against
ssp.
note this bug is specific to Arch Linux, however other distros might build the toolchain in the same manner.
Building the toolchain:
1. Download and unpack the Go source code:
note this guide assumes
$GOROOT is set to
/usr/src/go/.
-
Use mercurial (slow)
hg clone -u release https://code.google.com/p/go
-
Use the source tarball from golang.org
1a. (optional but recommended) add
export PATH="$PATH:$GOROOT/bin" to your
~/.bashrc (or the equivalent file for your shell).
2. Compiling the native toolchain:
|
cd $GOROOT/src $ ./make.bash ..... Installed Go for linux/amd64 in /usr/src/go-release Installed commands in /usr/src/go-release/bin |
3. Compiling the Windows toolchain without CGO:
|
cd $GOROOT/src $ env GOOS=windows GOARCH=386 ./make.bash --no-clean ..... Installed Go for windows/386 in /usr/src/go-release Installed commands in /usr/src/go-release/bin |
Repeat with
GOARCH=amd64 if you want to build win64 binaries.
4. Compiling the Windows toolchain with CGO support:
- Install
mingw-w64-gcc
|
sudo pacman -S mingw-w64-gcc ..... (1/1) installing mingw-w64-gcc |
|
cd $GOROOT/src $ env CGO_ENABLED=1 GOOS=windows GOARCH=386 CC_FOR_TARGET="i686-w64-mingw32-gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -lssp" ./make.bash --no-clean ...... Installed Go for windows/386 in /usr/src/go-release Installed commands in /usr/src/go-release/bin |
Repeat with
GOARCH=amd64 CC_FOR_TARGET="x86_64-w64-mingw32-gcc .... if you want to build win64 binaries.
note that once the bug is fixed, you can remove
-fno-stack-protector -D_FORTIFY_SOURCE=0 -lssp from
CC_FOR_TARGET.
Actually compiling your code to run on windows:
We use the same environment variables from earlier, except we have to replace
CC_FOR_TARGET with
CC
Code:
|
package main /* static int answerToLife() { return 42; } */ import "C" import "fmt" func main() { fmt.Println("the answer to life is", C.answerToLife()) } |
Testing:
|
$ env CGO_ENABLED=1 GOOS=windows GOARCH=386 CC="i686-w64-mingw32-gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -lssp" go build -o test32.exe $ file test32.exe test32.exe: PE32 executable (console) Intel 80386 (stripped to external PDB), for MS Windows # or build it as a GUI application so Windows won't open up a console window. $ env CGO_ENABLED=1 GOOS=windows GOARCH=386 CC="i686-w64-mingw32-gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -lssp" go build -ldflags -H=windowsgui -o test32.exe $ file test32.exe test32.exe: PE32 executable (GUI) Intel 80386 (stripped to external PDB), for MS Windows $ wine test32.exe the answer to life is 42 |
note that to build native go with cgo you will have to use
env CC=gcc go build