MinGW-W64 And Go
Jul 23, 2015
5 minute read

This article covers how to setup mingw-w64 on Windows – specifically Windows 8 64-bit – and get the 64-bit version of Go to use a 64-bit version of gcc.

I’ve been working on writing a game using the Go programming language. While I’ve been working mostly in Linux these days, any game worth its salt should be able to run on Windows. The problem I’ve had with Go, OpenGL and Windows is that the cgo tool requires a matching gcc compiler. That means you need a 64-bit gcc if you’re using Go 64-bit. Up until now, I’ve been using mingw (see my articles on calling c code and using OpenGL with Go). Mingw does not ship a 64-bit version of gcc, which means I could only use Go 386.

It also means that I’m on my own when compiling dependencies and I may mess something up. As it turns out, I must have done something bad with assimp, because loading a ‘.fbx’ file with a mesh and animation was crashing on Windows using my Go wrapper for assimp but was operating fine in Linux. When I researched mingw-w64, besides the expected 64-bit gcc, I was super excited to see that it uses pacman for dependency management and installation. This means that I ended up just running pacman to install pre-built binaries for mingw-w64 that resulted in my assimp wrapper and game no longer crashing. And I got to use Go 64-bit to boot, which meant I could do more largely memory dependent experiments.

And the last little bit of joy I got from switching to mingw-w64 came in the form of a terminal window that was fully resizable! It sounds so silly that I was happy about this in 2015, but on Windows it just doesn’t seem common to have a decent terminal window.

Uninstalling Old Versions

Uninstall the following projects if you already have them installed:

  • Go 386 (32-bit)
  • mingw

Check your environment variables to see if C:\MinGW\bin is listed in either the user $PATH or the system $PATH variables. If it is there, then remove it while being careful with the ; characters so that you don’t corrupt your PATH.

Requirements

  • Go amd64 (64-bit) – tested with version 1.4.2
  • Msys2 (using the latest Msys2 installer) – tested with version x86_64-20150512

When you go to the mingw-w64 download page, you can see some pre-built tool chains. For this article, we will be using Msys2 which includes all the 64-bit goodness we need.

Installation of Go amd64

After downloading go1.4.2.windows-amd64.msi, run the installer. Accept the license agreement, keep the default folder of C:\Go and install. According to the install docs, the MSI file should automatically update your environment variables for you, it just requires you to restart any open terminals.

Installation of Msys2 and mingw-w64

After downloading msys2-x86_64-20150512.exe, run the installer. The instructions on the main Msys2 page have some nice images for those that are more visually oriented, but they are a little out of date. Follow the defaults of the installer program, which installs to the c:\msys64 folder and has you running MSYS2 after install.

Now that you have the msys2 environment installed with mingw-w64, in the MSYS2 terminal run the following command to update the installation:

pacman --needed -Sy bash pacman pacman-mirrors msys2-runtime

After that completes, restart the MSYS2 terminal (Found at C:\msys64\mingw64_shell.bat) and run:

pacman -Su

Due to whatever reasons the MSYS2 people have, it’s necessary to update with pacman in that order. If you get any errors while downloading during that first line where you update the msys2-runtime, keep retrying until everything is successful. Sourceforge has been super flaky as of late and it will throw off the install process if the first line doesn’t complete successfully.

Lastly, you need to get the actuall 64-bit gcc compilers with the following command:

pacman -S mingw-w64-x86_64-gcc

After those commands, you now have a completely up-to-date system with 64-bit versions of gcc.

Installing Dependency C/C++ Libraries

Lets say you want to want to use Go and OpenGL together. You’ll want to install dependeny packages like GLFW. To see if they exist in the new MSYS2/MinGW-w64 environment, query pacman with the following command:

pacman -Ss glfw

This will produce output like:

timothy@Blitz MINGW64 ~
$ pacman -Ss glfw
mingw32/mingw-w64-i686-glfw 3.1-1
    A free, open source, portable framework for OpenGL application development.
    (mingw-w64)
mingw64/mingw-w64-x86_64-glfw 3.1-1
    A free, open source, portable framework for OpenGL application development.
    (mingw-w64)

You can actually install 32-bit or 64-bit versions of most (all?) libraries in the pacman package system. For now, install the 64-bit version of GLFW as well as the git and mercurial version control systems by using the following command:

pacman -S mingw-w64-x86_64-glfw git mercurial

You should now be able to install the Go wrapper library for GLFW by running the following command which pulls the current library from github.com:

export GOPATH=/c/Gocode
go get -u github.com/go-gl/glfw/v3.1/glfw

You can customize the GOPATH variable to be whatever you want, but using the above line lets go create C:\Gocode and then install the GLFW wrapper library to C:\Gocode\src\github.com\go-gl\glfw\v3.1\glfw.

You can now take the sample code from the wrapper’s README.md (replicated below), save it to C:\Gocode\src\glfwtest.go and run it using go run /c/Gocode/src/glfwtest.go

package main

import (
    "runtime"
    "github.com/go-gl/glfw/v3.1/glfw"
)

func init() {
    // This is needed to arrange that main() runs on main thread.
    // See documentation for functions that are only allowed to be called from the main thread.
    runtime.LockOSThread()
}

func main() {
    err := glfw.Init()
    if err != nil {
        panic(err)
    }
    defer glfw.Terminate()

    window, err := glfw.CreateWindow(640, 480, "Testing", nil, nil)
    if err != nil {
        panic(err)
    }

    window.MakeContextCurrent()

    for !window.ShouldClose() {
        // Do OpenGL stuff.
        window.SwapBuffers()
        glfw.PollEvents()
    }
}