DEV Community

loading...
Cover image for How to cross-compile Go app for Apple Silicon (M1)
Tidal Migrations

How to cross-compile Go app for Apple Silicon (M1)

Petr Razumov
Originally published at tidalmigrations.com Updated on ・3 min read

This is the first part in the series on how we prepared our application to run on M1 (Apple Silicon).

At Tidal Migrations we build our CLI application — Tidal Tools — to make it easier for our customers to deal with all sorts of data necessary for their cloud migrations journey. The CLI app could be run anywhere — on a manager’s Microsoft Windows workstation, on a developer’s Apple MacBook Pro, or even on a Linux server since a long time ago in a datacenter far, far away… Because of this, having the ability to build the app for different operating systems was the top priority for us since the beginning of the development. That’s why we choose Go programming language for our CLI application development.

Go (sometimes referred as Golang) is a statically typed, compiled programming language designed at Google. Among other awesome features of Go, there is one which was crucial for us — the ability to cross-compile code for different operating systems and architectures. In other words, it is possible for a developer running, for example, macOS on her laptop to build an application suitable for running on Windows or Linux, or any other operating system which is supported by the Go compiler.

The following short walkthrough will guide you through the process of creating a simple Hello world application and building it for Linux, Windows and macOS on M1.

Let’s start with writing the actual code for our application:

// hello.go

package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Printf(
        "Hello world from %s/%s\n",
        runtime.GOOS,
        runtime.GOARCH,
    )
}
Enter fullscreen mode Exit fullscreen mode

If we build it (with go build hello.go command) and run the binary (./hello) it should display something like the following:

Hello world from linux/amd64
Enter fullscreen mode Exit fullscreen mode
Hello world from windows/amd64
Enter fullscreen mode Exit fullscreen mode

or

Hello world from darwin/arm64
Enter fullscreen mode Exit fullscreen mode

That depends on the OS and architecture of the computer where we build our app. But as I mentioned earlier, it is possible to build Go applications for operating systems and architectures different than the one where we run the build process. With modern Go tools it is pretty straightforward. All we need to do is to set some specific environment variables — GOOS and GOARCH — and voilà, we build binaries for different operating systems and architectures.

At first, let's build our “Hello world” app for Microsoft Windows:

GOOS=windows GOARCH=amd64 go build hello.go
Enter fullscreen mode Exit fullscreen mode

If we run ls, we'd see that a new file (hello.exe) appeared in the current directory:

$ ls
hello.exe  hello.go
Enter fullscreen mode Exit fullscreen mode

Let's determine a type of the hello.exe file using file command:

$ file hello.exe
hello.exe: PE32+ executable (console) x86-64 (stripped to external PDB), for MS Windows
Enter fullscreen mode Exit fullscreen mode

Now, let's build our application for some old (32-bit) Linux:

GOOS=linux GOARCH=386 go build -o hello-linux-386 hello.go
Enter fullscreen mode Exit fullscreen mode

A new file (hello-linux-386) should appear:

$ ls
hello.exe  hello.go  hello-linux-386
Enter fullscreen mode Exit fullscreen mode

And it should be of 32-bit executable type:

file hello-linux-386 
hello-linux-386: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, ..., not stripped
Enter fullscreen mode Exit fullscreen mode

And finally, let's build the same application for Apple Silicon:

GOOS=darwin GOARCH=arm64 go build -o hello-macos-arm64 hello.go
Enter fullscreen mode Exit fullscreen mode

Running that go build command should create the third binary in our folder:

$ ls
hello.exe  hello.go  hello-linux-386  hello-macos-arm64
Enter fullscreen mode Exit fullscreen mode

The type of the file is the following:

$ file hello-macos-arm64 
hello-macos-arm64: Mach-O 64-bit arm64 executable, flags:<|DYLDLINK|PIE>
Enter fullscreen mode Exit fullscreen mode

Hello world

That's it! With this simple trick you can build Go applications for different operating systems and architectures on your laptop or a single build server.

I hope you enjoyed this post! Stay tuned to learn more about our journey towards M1 version release!

Discussion (0)