This is a creation in Article, where the information may have evolved or changed.
When we write a go code that relies on a specific platform or CPU architecture, we need to give different implementations
C language has a preprocessor that can be compiled by macro or # define containing code specified by a specific platform
But go does not have a preprocessor, and he is using tags and naming conventions defined in the Go/build package to allow go packages to manage code for different platforms
This article will tell you how the conditional compilation system for Go is implemented, and illustrates how to use the
1. Preliminary knowledge: The use of the Go List command
Need to understand the simple usage of Go list before speaking conditional compilation
Go list accesses the data structures within the source file that can affect the compilation process
Go list and go build, Test,install most of the parameters are the same, but go list does not perform the compilation operation. Using the-f parameter allows us to provide the code in the text/template containing the go/build. The package context is executed correctly (that is, let go/build. The context in the package is formatted with this format ' {{. text/template. Gofiles}} ' in the placeholder, the classmate who wrote the HTTP server program should be familiar with it.
Using the format parameter, we can get the file name that will be compiled via go list
- % Go list-f ' {{. Gofiles}} ' Os/exec
- [Exec.go Lp_unix.go]
In this example, we use Go list to see which files in the Os/exec package will be compiled under the Linux/arm platform.
The results show that exec.go contains common code that is available on all platforms, and Lp_unix.go contains the exec in the *nix system. Lookpath
Running the same command under Windows System results in the following:
- C:\go> Go list-f ' {{. Gofiles}} ' Os/exec
- [Exec.go Lp_windows.go]
The above example is the two part of the Go Conditional compilation system, which is called: Compile constraints, which are described in detail below
2. First conditional compilation method: Compile label
Add annotations to the source code, often referred to as compilation tags (build tag)
The compilation tag is added as a comment as close as possible to the top of the source code file
Go build reads each source file in the package while building a package and parses the compiled note, which determines whether the source file participates in this compilation
Add rules for compiling tags (attach original text):
1. A build tag is evaluated as the OR of space-separated options
2. Each option evaluates as the and of its comma-separated terms
3. Alphanumeric word or, preceded by!, it negation
1). The compilation tab consists of a space-delimited compilation option (options) with a logical relationship of "or"
2). Each compilation option consists of a comma-delimited list of conditional items in a logical "and" relationship
3). The name of each condition item is denoted by the letter + number, in front Plus! means negative.
Example (compile tags to be placed at the top of the source file)
- +build Darwin FreeBSD NetBSD OpenBSD
This will allow the source file to be compiled only in the BSD system that supports Kqueue.
A source file can have more than one compilation tag, the relationship between multiple compiled tags is logical "and"
- +build Linux Darwin
- +build 386
This will restrict this source file to be compiled only on linux/386 or darwin/386 platforms.
Notes about annotations
Starting with a compile tag often makes the following error
- +build!linux
- Package mypkg//Wrong
In this example, there is no blank line between the compiler tag and the package declaration, so that the compilation tag is ignored as a comment on the package declaration rather than a compile tag.
The following is the correct way to write the label, add a blank line at the end of the label so that the label does not comment on the other statement
- +build!linux
- Package mypkg//correct
The Go Vet command also detects this missing blank line error, which can be used initially to avoid missing empty rows.
- % Go vet mypkg
- Mypkg.go:1: +build comment appears too late in file
- Exit Status 1
As a reference, the following example puts licence declaration, compile label and package declaration together, please pay attention to distinguish
- % Head Headspin.go
- Copyright Enterprises. All rights reserved.
- Use of this source code was governed by a Bsd-style
- License that can is found in the license file.
- +build Someos Someotheros Thirdos,!amd64
- Package Headspin implements calculates numbers so large
- They'll make your head spin.
- Package Headspin
3. Second conditional compilation method: File suffix
This method provides conditional compilation by changing the suffix of the file name, which is simpler than compiling the tag, and Go/build can decide which files do not need to participate in the compilation without reading the source file.
File naming conventions can be found in the Go/build package detailed instructions, simply say if your source file contains the suffix: _$goos.go, then the source file will only be compiled under this platform, _$goarch.go. The two suffixes can be used together, but note the order: _$goos_$goarch.go, cannot be reversed with: _$goarch_$goos.go
Examples are as follows:
- Mypkg_freebsd_arm.go//Only builds on freebsd/arm systems
- Mypkg_plan9.go//Only builds on Plan9
The source file cannot provide only conditional compilation suffixes, and must also have a file name:
- _linux.go
- _freebsd_386.go
These two source files are ignored on all platforms because Go/build will ignore all source files with the following underscore or dot
4. Compilation of tags and file suffix selection
There is overlap in the functionality of the compiled label and the file suffix, such as a file name: Mypkg_linux.go contains//+build Linux will appear redundant
Typically, if the source file matches the platform or CPU architecture exactly, use the file suffix, for example:
- Mypkg_linux.go//Only builds on Linux systems
- Mypkg_windows_amd64.go//builds on Windows 64bit platforms
Conversely, if the source file can be used on more than one platform or more than one CPU architecture, or if the specified platform needs to be removed, then compile tags, such as the following compile tags, can be compiled on all *nix platforms:
- % grep ' +build ' $HOME/go/src/pkg/os/exec/lp_unix.go
- +build Darwin Dragonfly FreeBSD Linux NetBSD OpenBSD
Below is a compilation that can be compiled on all platforms except Windows
- % grep ' +build ' $HOME/go/src/pkg/os/types_notwin.go
- +build!windows
5. Summary
This article focuses on all go source files that can be compiled by the Go tool, compiling tags and file suffix names (also including. C and. s files)
The Go standard library contains a number of examples, especially Runtime,syscall,os and net packages, that readers can use to learn from these packages.
The test file also supports compiling tags and file suffix conditional compilation, and works the same way as the go source file. There are some test samples that can be conditionally included under different platforms. Also, the standard library contains a number of examples
Finally, this document is about how to use the Go tool to achieve conditional compilation, but conditional compilation is not limited to go tool, you can use the Go/build package to write your own conditional compilation tool