DEV Community

Cover image for Advanced Go Build Techniques
JackTT
JackTT

Posted on • Updated on

Advanced Go Build Techniques

Table of contents

I/ Build options

The following are some of the most commonly used options for the go build command:

  • -o: Specifies the output file name. The default output file name is the name of the main package, with the .exe suffix added on Windows.
  • -v: Verbose output. This option prints the names of the packages as they are being compiled.
  • -work: Prints the name of the temporary work directory and does not delete it when exiting. This option is useful for debugging.
  • -x: Print the commands. This option prints the commands that are being executed by the go build command.
  • -asmflags: Arguments to pass to the go tool asm invocation.
  • -buildmode: The build mode to use. The default build mode is exe. Other possible values are shared, pie, and plugin.
  • -buildvcs: Whether to stamp binaries with version control information. The default value is auto.

For more information about the go build command, you can run the following command:

go help build
Enter fullscreen mode Exit fullscreen mode

II/ Which file will be included

When you use the go build command in Go, it compiles the Go source files in the current directory and its subdirectories to create an executable binary. By default, Go only compiles .go files and ignores other types of files in the directory. However, it's important to note that the behavior of the go build command can be influenced by build tags, build constraints.

The following types of files are typically ignored by go build:

1. Files with Non-.go Extensions:

Any files in the directory that don't have a .go extension will be ignored. This includes text files, configuration files, images, etc.

2. Files in Subdirectories:

The go build command compiles all .go files in the current directory and its subdirectories. Other files and directories will generally be ignored.

3. Files with Underscores OR Periods in the Beginning:

Directory and file names that begin with "." or "_" are ignored by the go tool, as are directories named "testdata".

4. Files Excluded by Build Constraints:

Go supports build constraints which allow you to include or exclude specific files from the build based on conditions like the target operating system or architecture. For example, files with build constraints like //go:build windows will be ignored when building for non-Windows platforms.

5. Files Excluded by Build Tags:

Build tags are special comments in Go source files that can be used to specify which files should be included in the build based on custom conditions. Files with build tags that don't match the build context will be ignored.

6. Files in Directories Named "testdata": Files in directories named testdata are ignored by design. This directory is commonly used to include test-related data that's not meant to be compiled.

III/ Build tags

Go's build tags provide a powerful mechanism for including or excluding specific code during the build process. By using build tags, developers can tailor their application to work with different build configurations, environments, or platform-specific requirements. This feature is particularly valuable when dealing with cross-compilation or creating binaries for specific operating systems.

A build tag is a comment placed at the beginning of a Go source file that specifies a set of conditions under which the code within that file should be included or excluded from the build. The syntax is //go:build . For instance, consider a scenario where you want to include a specific piece of code only when building for a certain version of the application:

main.go

package main

import "fmt"

var version string

func main() {
    fmt.Println(version)
}
Enter fullscreen mode Exit fullscreen mode

pro.go

//go:build pro

package main

func init() {
    version = "pro"
}
Enter fullscreen mode Exit fullscreen mode

free.go

//go:build free

package main

func init() {
    version = "pro"
}

Enter fullscreen mode Exit fullscreen mode

When you build with -tags=free, the output will be free because the free.go file was included. And when you build with -tags=pro, the output will be pro.

Build Tags Syntax

You can combine constraints in the same way as you would any other conditional statement in programming i.e AND, OR, NOT

NOT

//go:build !cgo
Enter fullscreen mode Exit fullscreen mode

This will only include the file in the build if CGO is NOT enabled.

AND

//go:build cgo && darwin
Enter fullscreen mode Exit fullscreen mode

This will only include the file in the build if CGO is enabled and the GOOS is set to darwin.

OR

//go:build darwin || linux
Enter fullscreen mode Exit fullscreen mode

Combine them all e.g

//go:build (linux || 386) && (darwin || !cgo)
Enter fullscreen mode Exit fullscreen mode

Results to (linux AND 386) OR (darwin AND (NOT cgo)).

Note:
Go versions 1.16 and earlier used a different syntax for build constraints, with a // +build prefix. The gofmt command will add an equivalent //go:build constraint when encountering the older syntax.

IV/ Build contraints

While custom build tags are set using the tags build flag, golang automatically sets a few tags based on environment variables and other factors. Here is a list of the available tags

1. OOS and GOARCH Environment Values
You can set constraints in your source code to only run files if a certain GOOS or GOARCH is used. e.g

//go:build darwin,amd64

package utils
Enter fullscreen mode Exit fullscreen mode

2. GO Version constraint

You can also constrain the inclusion of a file to the go version being used in building the entire module. EX to only build the file if the go version being used is 1.12 and above you would use //go:build go1.18. This would include the file if the go version is 1.18 or 1.21 (latest as of writing this).

References

Top comments (2)

Collapse
 
dyfet profile image
David Sugar

Isn't build constraints now defined with //go:build?

Collapse
 
jacktt profile image
JackTT • Edited

Yes, you are correct.
As go docs:
Go versions 1.16 and earlier used a different syntax for build constraints, with a "// +build" prefix. The gofmt command will add an equivalent //go:build constraint when encountering the older syntax.