Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between `//go:build` and `// +build` directives?

Tags:

go

build

go-build

for example, https://github.com/golang/sys/blob/master/cpu/cpu_gccgo_x86.go#L5 :

//go:build (386 || amd64 || amd64p32) && gccgo
// +build 386 amd64 amd64p32
// +build gccgo

package cpu

In my eyes, as a build tag, // +build ... can work well.
Why is //go:build still explicitly specified?

Btw, it is hard to find the mannual of //go:build, but // +build is easy(https://pkg.go.dev/cmd/go#hdr-Build_constraints)

like image 664
wymli Avatar asked Jul 13 '21 10:07

wymli


People also ask

What is go build?

gobuild is an automatic build tool that aims to replace Makefiles for simple projects written in the Go programming language. It creates a dependency graph of all local imports and compiles them in the right order using the gc Go compiler.

Where do go build files go?

go build builds the command and leaves the result in the current working directory. go install builds the command in a temporary directory then moves it to $GOPATH/bin .

Does go build get dependencies?

Additionally, other commands, such as go build or go test, will add new dependencies automatically based on the stipulated requirements. For example, as earlier illustrated, they can do this to satisfy import requirements, including upgrading go. mod file and installing the new dependencies.

Does go run build?

go run is just a shortcut for compiling then running in a single step. While it is useful for development you should generally build it and run the binary directly when using it in production. There must be more to it than that - if I time the println in a helloworld, it runs faster with go run than compiled.

What is the difference between go build vs Go run?

Before go run vs go build, let’s take a look at both the commands individually. The go build command-line tool takes a .go file and generates an executable file for windows and binary files for Linux. Note:- Go build tool will only make an executable or binary file if the .go file contains the main package and main function in it.

What is the use case for the +build directive in go?

It was introduced in Go 1.17. It is meant to replace the old // +build directives; the use case is still same: it "lists the conditions under which a file should be included in the package". The new syntax brings a few key improvements:

What is the use of go build command in Linux?

The go build command-line tool takes a .go file and generates an executable file for windows and binary files for Linux. Note:- Go build tool will only make an executable or binary file if the .go file contains the main package and main function in it.

Does go build tool make executable files?

Note:- Go build tool will only make an executable or binary file if the .go file contains the main package and main function in it. The Program with the main package and main function is considered as a command and program without is considered as a package.


1 Answers

Go 1.18

The new directive //go:build is now preferred and the toolchain will actively remove old directives; as mentioned in Go 1.18 release notes:

In Go 1.18, go fix now removes the now-obsolete // +build lines in modules declaring go 1.18 or later in their go.mod files.

Due to the above, if you attempt to build a module with go.mod at 1.17 or lower that requires a dependency at 1.18 or above, the build may fail if the dependency is missing // +build lines.

Go 1.17

//go:build is the new conditional compilation directive used to specify build constraints. It was introduced in Go 1.17.

It is meant to replace the old // +build directives; the use case is still same: it "lists the conditions under which a file should be included in the package". The new syntax brings a few key improvements:

  • consistency with other existing Go directives and pragmas, e.g. //go:generate
  • support for standard boolean expression, e.g. //go:build foo && bar, whereas the old // +build comment has less intuitive syntax. For example AND was expressed with commas // +build foo,bar and OR with spaces // +build foo bar
  • it's supported by go fmt, which will automatically fix incorrect placement of the directive in source files, thus avoiding common mistakes as not leaving a blank line between the directive and the package statement.

The two build directives will coexist over a few Go releases in order to ensure a smooth transition, as outlined in the relevant proposal document (in the quote below N is 17, emphasis mine):

Go 1.N would start the transition. In Go 1.N:

  • Builds will start preferring //go:build lines for file selection. If there is no //go:build in a file, then any // +build lines still apply.

  • Builds will no longer fail if a Go file contains //go:build without // +build.

  • Builds will fail if a Go or assembly file contains //go:build too late in the file. Gofmt will move misplaced //go:build and // +build lines to their proper location in the file.

  • Gofmt will format the expressions in //go:build lines using the same rules as for other Go boolean expressions (spaces around all && and || operators).

  • If a file contains only // +build lines, gofmt will add an equivalent //go:build line above them.

  • If a file contains both //go:build and // +build lines, gofmt will consider the //go:build the source of truth and update the // +build lines to match, preserving compatibility with earlier versions of Go. Gofmt will also reject //go:build lines that are deemed too complex to convert into // +build format, although this situation will be rare. (Note the “If” at the start of this bullet. Gofmt will not add // +build lines to a file that only has //go:build.)

  • The buildtags check in go vet will add support for //go:build constraints. It will fail when a Go source file contains //go:build and // +build lines with different meanings. If the check fails, one can run gofmt -w.

  • The buildtags check will also fail when a Go source file contains //go:build without // +build and its containing module has a go line listing a version before Go 1.N. If the check fails, one can add any // +build line and then run gofmt -w, which will replace it with the correct ones. Or one can bump the go.mod go version to Go 1.N.

More info about syntax changes: Golang conditional compilation

like image 50
blackgreen Avatar answered Oct 24 '22 03:10

blackgreen