×
Community Blog Golang Cross Compilation on Alibaba Cloud

Golang Cross Compilation on Alibaba Cloud

This tutorial explores how Golang simplifies cross-platform development and testing, providing some best practices on how to use this service.

By Alex, Alibaba Cloud Community Blog author

For developing an application, developers use their machine that runs OS X, Windows or Linux. At the same time, they use a foreign platform such as Alibaba Cloud's ECS instances installed with Ubuntu or CentOS or another platform for testing. Therefore, there is a great need for the capability that uses a single system to compile binaries that run across multiple platforms. Golang offers a solution to the problem. It allows developers to design systems that run across diverse platforms. Also known as cross-compiling, Golang offers a tremendous advantage to cross-platform developers. The language has many built-in features to support development across platforms. This article explores how to use such solutions for making the development process less strenuous, what are the best practices, and how Golang facilitates testing out new solutions and package distribution.

Best Practices

To begin with, let's take a quick look at the key best practices for implementing cross-compilation.

Interfaces

To meet the interface requirements on Go, every object must ensure the implementation of all defined methods. This may result in the distinct implementation of two objects from different platforms but still meeting the requirements of Go interfaces. It is advisable to abstract all platform-specifics behind Go interfaces.

Build Constraints

The build constraints on Go control a compiled file's platform using language constructs. They are of two types:

  • The simple yet inflexible file-based constraints
  • The complex but flexible comment at a to-of-file constraint

OS and Architecture

Use the GOOS and GOARCH values in the runtime package to get the OS and architecture information at runtime. Next, compare those using standard conditionals with the values that are already known. Nonetheless, runtime checking is not useful most of the time as it increases the chances of encountering errors.

Requirements for Tutorial

You need the following essentials to work through the tutorial.

  • An Alibaba ECS instance that is installed with Ubuntu 16.04
  • A firewall and Sudo non-root user
  • Go installed on your system

Compile for a Specific Target OS

Compile the executables for specific target operating systems (OS) such as Darwin/amd64 and Linux/amd64 and build these executables in a local machine (for this tutorial, MacBook). Export the executables to the GitHub account and clone to the Ubuntu server hosted by Alibaba Cloud.

Mac OS

For a local Mac machine, build the executables for the Darwin/amd64 target. Once, the Go is installed, run the commands below.

cd src
GOOS=darwin GOARCH=amd64 CGO_ENABLED=1 ./make.bash ¨Cno-clean

Following is the anticipated response from the preceding command.

Installed Go for darwin/amd64 in /Users/name/go
Installed commands in /Users/name/go/bin

The command creates all libraries and tools in the go, godoc and, gofmt directories. Run the command below to create a PATH for the tools.

export PATH=$HOME/go/bin:$PATH

Now check the Go environment using the following commands.

go env
GOARCH="amd64"
GOBIN=""
GOCHAR="6"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="linux"
GOPATH=""
GORACE=""
GOROOT="/Users/name/go"
GOTOOLDIR="/Users/name/go/pkg/tool/darwin_amd64"
CC="gcc"
GOGCCFLAGS="-g -O2 -fPIC -m64"
CGO_ENABLED="1"

Run the command below to check the Go version.

go version
go version go1.12.1 darwin/amd64

Anticipated Errors: To solve the following anticipated errors while setting up the Go target, refer to this guide.

crypto/x509 root_darwin.go:9:43: error: 
CoreFoundation/CoreFoundation.h: 
root_darwin.go:10:31: error: Security/Security.h: 

Open the Go directory to view all the required tools to build the Go programs. For this tutorial, it shows the darwin_amd64 folder for Mac.

Linux amd64

For this step, compile an executable file to run on Linux/amd64. To start, run the command below.

GOOS=linux GOARCH=amd64 CGO_ENABLED=0 ./make.bash ¨Cno-clean

Set CGO_ENABLED to 0 to implement cross-compiling and get the following output.

Installed Go for linux/amd64 in /Users/name/go
Installed commands in /Users/name/go/bin

Now, you'll get new folders for Linux/amd64 in the bin and PKG directories.

Build for a Specified Target

Refer to the following table to choose a target OS:

$GOOS $GOARCH
darwin 386 32-bit MacOSX
darwin amd64 64-bit MacOSX
freebsd 386
freebsd amd64
linux 386 32 bit Linux
linux amd64 64 bit Linux
linux arm RISC Linux
netbsd 386
netbsd amd64
openbsd 386
openbsd amd64
plan9 386
windows 386 32 bit Windows
windows amd64 64 bit Windows

Now, execute the following commands to build the programs to run on Linux and Ubuntu.

cd $HOME
mkdir example

Setup a GOPATH as shown below:

export GOPATH=$HOME/example
cd example
mkdir src
cd src
mkdir simple
cd example/src/simple

Next, create a new file named main.go in the directory with the following content.

package main

import (
    "fmt"
)

func main() {
    fmt.Println("Hello World!")
}

Build a Linux/amd64 executable by running the command below in the terminal:

export GOARCH="amd64"
export GOOS="linux"

go build
file simple

Simple: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped

Run the following command in the terminal to build a darwin/amd64 executable.

go build
file simple

simple: Mach-O 64-bit executable x86_64

Choose a different platform and architecture by changing the OS/ARCH variables in the command. Once the build is complete, obtain an executable that is compatible with the target OS/ARCH variables.

Automate Compilation for Target Platforms

Deploying executables for multiple platforms is an extremely slow and time-consuming process. Let's write a program that will help us automate the process. The script shall have operating systems and platform pairs to generate executables in a directory.

Alright, let's get started!

Switch to your home directory by executing the following command:

cd ~

Run the command below to create a new bash file named auto-build.bash.

nano auto-build.bash

To avoid complicating the process, check what the script needs to contain and then compile it swiftly. Once you understand what needs to be done, it is very easy to work with such a script.

First, make the script executable using the following command.

auto-build.bash
#!/usr/bin/env bash

Consider the following requirements for the script:

  • Use the $n variable as a command-line argument to specify the import path. A $0 variable has the name of the executed script while a $1 variable has arguments provided by the user.
  • Enforce a requirement for the user to provide the value for their argument. There's no way to execute without it.
  • Use an IF statement that checks the $package variable's value.
  • Extract names of packages from the given path as denoted by / characters. You may want to split it into a $package_split array.
  • The script must further specify the targeted OS and architectures in the argument.
  • Include an argument GOOS and GOARCH environment variables for each OS and architectures combination with a FOR loop.
  • Use the package name, the OS and architecture to generate a name for the executable using a FOR loop.
  • The script shall use the GO build command to create executable with the FOR loop.
  • The script must run an error check for any build errors.

Based on the above requirements, refer to the following script:

auto-build.bash

#!/usr/bin/env bash

package=$1
if [[ -z "$package" ]]; then
  echo "usage: $0 <package-name>"
  exit 1
fi
package_split=(${package//\// })
package_name=${package_split[-1]}

platforms=("windows/amd64" "windows/386" "linux/amd64" "linux/386")

for platform in "${platforms[@]}"
do
    platform_split=(${platform//\// })
    GOOS=${platform_split[0]}
    GOARCH=${platform_split[1]}
    output_name=$package_name'-'$GOOS'-'$GOARCH
    if [ $GOOS = "windows" ]; then
        output_name+='.exe'
    fi  

    env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name $package
    if [ $? -ne 0 ]; then
        echo 'We have encountered an error while executing! Aborting the process...'
        exit 1
    fi
done

The above script allows building executables for Windows 64-bit, 32-bit, Linux 64-bit, and Linux 32-bit. There are many ways of creating a script, but the variables and methods remain more or less the same. Now, run the following command to make it executable.

- chmod +x auto-build.bash

There you go! Now the process of compiling executables is automated and can be run using the command below.

./auto-build.bash  $GOPATH/

Since there is no output for the completed processes, use the IS command to determine whether the executables are created successfully. Use any combination of operating systems and architectures with the platforms variable.

Go Tools

After building the Go programs for the chosen platforms and architectures, install the Go tools by executing the following commands.

go get golang.org/x/tools/cmd/godoc
go get golang.org/x/tools/cmd/vet
go get golang.org/x/tools/cmd/goimports
go get golang.org/x/tools/cmd/gorename
go get golang.org/x/tools/cmd/oracle
go get golang.org/x/tools/cmd/gotype
go get github.com/golang/lint/golint

Conclusion

This tutorial describes how developers must use Go to deal with packages and cross-compile executables for different target platforms. It suggests how to use a simple script to automate the compilation process for Linux and Windows to save time and increase efficiency. Refer to the Go document for comprehensive information about how to build Go executables from the source. Also, use a tool called gox to build executables for various platforms with minimal requirements. Now, without much ado subscribe to Alibaba Cloud ECS and get started with the lessons.

Don't have an Alibaba Cloud account? Sign up for an account and try over 40 products for free worth up to $1200. Get Started with Alibaba Cloud to learn more.

0 0 0
Share on

Alex

53 posts | 8 followers

You may also like