Compile Golang for 386 (Pentium MMX or later)

One of the awesome things about Go is its ability to cross-compile for the platform you want. But, commonly, Go is compiled for distribution targeting more recent hardware.

If you have your old PC serving a couple websites, you may want to install a service written in Go. And your service can be compiled targeting an hardware higher that your have.

For example, if the service was compiled for a x86_64 processor and you try to run it in a 32bit processor, the processor will not know how to execute it. But there are also instructions sets like SSE2, which was introduced only with Pentium 4. If a program has SSE2 instructions, it will not execute in a Pentium III because it only have MMX and SSE instructions sets.

If you try to run Go and you got an error like the error bellow, most certainly, you are in this case:

# go version
Illegal instruction

From distribution package

Most probably, the community of your Linux distribution compiled Go with this in mind.

If so, you just have to install it. If got the error, you can try one the following options.

Docker image

There is an official image of Go for i386, but you cannot run it in a processor without SSE2. Maybe they did not targeted this hardware.

You can pull an image of your favorite Linux distribution and install Go from there.

Alternatively, you can build your own the Docker image. Start by cloning the repository:

git clone https://github.com/docker-library/golang/tree/master/

Move into the folder of the version and distribution you want.

NOTE: you might need to change the FROM image. For example, for alpine the Dockerfile starts with:

FROM alpine:3.6

But Docker pulls the amd64 image. Replace that with by:

FROM i386/alpine:3.6

Then, build it:

docker build -t golang .

Build from sources

Official Golang webpage provide instructions about Installing Go from source, but they aren’t as precise as they should be.

In the end of the document, they talk about the environment variables to adjust the compilation (sometimes seems they did not work):

  • $GO386 (for 386 only, default is auto-detected if built on either 386 or amd64, 387 otherwise)

    This controls the code generated by gc to use either the 387 floating-point unit (set to 387) or SSE2 instructions (set to sse2) for floating point computations.

    • GO386=387: use x87 for floating point operations; should support all x86 chips (Pentium MMX or later).
      GO386=sse2: use SSE2 for floating point operations; has better performance than 387, but only available on Pentium 4/Opteron/Athlon 64 or later.

Here you can find a failed attempt to build Go from source (if you were able to do it, please contribute): https://github.com/rigon/golang-387

Virtualize hardware

Compile huge packages in old hardware can take an eternity. Luckily you can virtualize the old hardware in recent machines.

Following there is a guide step-by-step to configure VirtManager to do that.

  1. Select how to install guest operating system

    How to install OS

  2. Select install media

    Install media

  3. Select memory and CPU (max as possible)

    Memory and CPU

  4. Select storage

    Storage

  5. Select a name and thick Customize configuration before install

    Name and configuration

  6. Here is where magic takes place.
    Under CPUsConfiguration, select the hardware you want to virtualize. You can choose for example pentium3

    CPU model

Now you can compile the software in your ultra fast machine in the same environment as your old machine e then copy the executables.

Or, you can even build the Docker images in the virtual machine and then push/pull them in the target.