You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have used build tags in a library so that it only depends on stdlib by default but usage of 3rd party libraries like github.com/pkg/errors can be enabled via build tags.
Reacted by Gautam Dey, Daniel Martí, TheDiveO and Reto
Build tags are commonly used for go generate - so that generators can be stored alongside the package in which they are used
Reacted by Caleb Spare, Michael McLoughlin, Gautam Dey, Ainar Garipov, Aynur Zulkarnaev, Michael Macnair, Steve Atkins, TheDiveO, Daniel Cormier and mpwalkerdine
New Go language or standard library features (e.g. // +build go1.13 in one file that implements something using features/code only available in 1.13, and // +build !go1.13 in the other file with the 1.12 implementation).
That being said, we don't use build tags very much.
Two files, named something like paranoia.go and nop_paranoia.go, which both define the same const bool, one setting it to true and one to false. Then elsewhere in the code:
if paranoia {
// extra testing
}
This way, we can run with the extra testing sometimes, but omit expensive tests entirely at compile time. (Some of the tests are inside hot loops, so being able to get rid of even the cost of the branch is actually relevant.)
Have also used them for what would typically be #defines in C; functionality changes which are innately program-wide and must be resolved at compile time because array sizes (for instance) depend on them.
I've seen a package (hajimehoshi/ebiten) ship with a number of examples in subdirectories, marked with +build example so they don't get built by default but are available for users to experiment with.
Reacted by Ainar Garipov, Abhinav Gupta, Nathan VanBenschoten and Peter Rabbitson
I used build tags to add enhanced debugging that goes into tight loops. Using an if statement much like @seebs .
One file id debug.go and the other debug_flg.go
They each define a debug constant.
then if I need to debug tight loops I'll eighter flip the const in debug.go from false to true (this is what I've mostly been doing this, because usually just want a single package) or build with the debug flag, which will cause debug_flg to compile and not debug.go to compile.
This being said, this is probably not the best way to do this.
The code generator (magic) only considers files with the magic build tag.
This excludes the generated foo_gen.go from consideration when the tool is
run again. The go tool is invoked without the build tag so only the
generated file is compiled in the final binary.
magic
go build
// +build
foo.go
Use
Ignore
magic
foo_gen.go
Ignore
Use
!magic
The desired experience here is for users to code in the input file like it's a
regular Go file (with auto-completion and other editor features) without
caring that it'll get substituted for the generated file at build time.
I use build tags to separate integration tests and examples (depending on external resources such as database) from unit tests (no external dependencies).
// +build integration
// +build example
so go test won't run them by default
Reacted by Nikita, Bill Mill, mpwalkerdine and Robert Liebowitz
This is important as some environments that Tegola is deployed into they do not want all the features, and turning them off or not configuring it is not good enough. So, having the ability to compile them out is important.
for building part of a program as a seperate binary. eg:part of a program parses some file, this would be used as an API by default, but with an alternate main file you can use the same codebase to build a parser(or any other modular thing) that would output to stdout or another file.
I used something like this in a "bigger" project where the program also had to use some modules(not go modules) as external binary and communicate over std in/out.
We could have a main wrapper that would usually not build, but with build tags we could build specific modules and use them in testing(or for example as seperate downloads)
Thanks all for your detailed replies! I will be working on compiling your answers into a document, and hopefully soon we'll be able to make some progress on supporting build tags in gopls.
Reacted by Daniel Martí, Gautam Dey, Aynur Zulkarnaev, Ingo Oeser, Jeff Hodges and Ignacio Gomez
Reacted by Daniel Martí, Aynur Zulkarnaev, Ingo Oeser, Jeff Hodges and Ignacio Gomez
I teach and use Go for programming labs, and keep solutions and skeleton code for the students in the same folder to ensure consistency with common files and to remember to change both if necessary.
I use // +build solution in solution files and // +build !solution in skeleton code, since they have overlapping type/func definitions. (This of course results in numerous compile errors when using gopls in VSCode.)
I run tests using go test -tags solution.
Running go test without the solution tag should fail the tests.
I then copy the skeleton code to a separate repo to share with the students.
gobbi, a package that provides bindings to GTK GUI toolkit, uses Go build tags to allow targeting of specific library versions. See here for more details.
Thanks all for the detailed replies! This information will be very valuable as we continue work on #29202. Closing this issue in favor of that one. Please feel free to comment here if you have a different use case for build tags.
I have one file with '// +build debug', and an almost identical file in the same folder with '// +build !debug'. gopls flagged every constant, variable and function as being redefined between the two files. The debug file just prints log messages to replace functions that make major changes to the running state of the system.
Activity
vcabbage commentedon Jul 31, 2019
I have used build tags in a library so that it only depends on stdlib by default but usage of 3rd party libraries like
github.com/pkg/errorscan be enabled via build tags.aykevl commentedon Jul 31, 2019
In TinyGo (which should eventually support IDEs), we use build tags to select various things:
stm32,nrf), chip (stm32f103xx,nrf52840), and board names (bluepill,pca10056)gc.none,gc.leaking, andgc.conservative)To manage all this, special JSON files are used that can be selected with a single compiler flag (similar to GCC spec files).
More uses may be added in the future.
niaow commentedon Jul 31, 2019
Build tags are commonly used for go generate - so that generators can be stored alongside the package in which they are used
muirdm commentedon Jul 31, 2019
We have used build tags mainly in two places:
// +build go1.13in one file that implements something using features/code only available in 1.13, and// +build !go1.13in the other file with the 1.12 implementation).That being said, we don't use build tags very much.
seebs commentedon Jul 31, 2019
Two files, named something like
paranoia.goandnop_paranoia.go, which both define the same const bool, one setting it to true and one to false. Then elsewhere in the code:This way, we can run with the extra testing sometimes, but omit expensive tests entirely at compile time. (Some of the tests are inside hot loops, so being able to get rid of even the cost of the branch is actually relevant.)
Have also used them for what would typically be #defines in C; functionality changes which are innately program-wide and must be resolved at compile time because array sizes (for instance) depend on them.
I've seen a package (hajimehoshi/ebiten) ship with a number of examples in subdirectories, marked with
+build exampleso they don't get built by default but are available for users to experiment with.gdey commentedon Jul 31, 2019
I used build tags to add enhanced debugging that goes into tight loops. Using an if statement much like @seebs .
One file id
debug.goand the otherdebug_flg.goThey each define a debug constant.
then if I need to debug tight loops I'll eighter flip the const in
debug.gofrom false to true (this is what I've mostly been doing this, because usually just want a single package) or build with the debug flag, which will cause debug_flg to compile and not debug.go to compile.This being said, this is probably not the best way to do this.
neild commentedon Jul 31, 2019
In google.golang.org/protobuf:
// +build ignoreto exclude an expensive integration test fromgo test ./....// +build puregoto select a slower implementation of various operations that doesn't depend on theunsafepackage.// +build go1.12to use(*reflect.Value).MapRangewhen available.// +build protoreflectto disable fast-path implementations of various operations to allow testing the reflection-based fallbacks.// +build proto1_legacyto enable support for some ancient features nobody should use. Used so we can run tests for that support.abhinav commentedon Aug 1, 2019
We use build tags to separate the almost identical input and output files of
our code generator.
Specifically, we have an input file that is valid Go code, and has a build tag
to exclude it from the build.
The code generator takes this file and spits out a nearly identical file with
the build tag inverted and some changes to the function bodies.
The code generator (
magic) only considers files with themagicbuild tag.This excludes the generated
foo_gen.gofrom consideration when the tool isrun again. The
gotool is invoked without the build tag so only thegenerated file is compiled in the final binary.
magicgo build// +buildmagic!magicThe desired experience here is for users to code in the input file like it's a
regular Go file (with auto-completion and other editor features) without
caring that it'll get substituted for the generated file at build time.
AndersonQ commentedon Aug 1, 2019
I use build tags to separate integration tests and examples (depending on external resources such as database) from unit tests (no external dependencies).
// +build integration// +build exampleso go test won't run them by default
gdey commentedon Aug 1, 2019
In the Tegola project we also use it select which features are enabled or not.
atlas/cache_s3.go:// +build !noS3Cacheatlas/provider_gpkg.go:// +build !noGpkgProvideratlas/cache_redis.go:// +build !noRedisCacheatlas/cache_azblob.go:// +build !noAzblobCacheatlas/provider_postgis.go:// +build !noPostgisProvidercmd/tegola/pprof.go:// +build pprofprovider/gpkg/gpkg.go:// +build cgoserver/viewer_disabled.go:// +build noViewerserver/viewer.go:// +build !noViewerThis is important as some environments that Tegola is deployed into they do not want all the features, and turning them off or not configuring it is not good enough. So, having the ability to compile them out is important.
JAicewizard commentedon Aug 1, 2019
for building part of a program as a seperate binary. eg:part of a program parses some file, this would be used as an API by default, but with an alternate main file you can use the same codebase to build a parser(or any other modular thing) that would output to stdout or another file.
I used something like this in a "bigger" project where the program also had to use some modules(not go modules) as external binary and communicate over std in/out.
We could have a main wrapper that would usually not build, but with build tags we could build specific modules and use them in testing(or for example as seperate downloads)
eliasnaur commentedon Aug 3, 2019
The gioui.org/ui/app package is like package os, but for GUI programs: it uses build tags to distinguish between GOOS. Some examples:
I also use the standard GOOS build tags in file names: os_js.go, gl_android.go, egl_windows.go etc.
6 remaining items
stamblerre commentedon Aug 13, 2019
Thanks all for your detailed replies! I will be working on compiling your answers into a document, and hopefully soon we'll be able to make some progress on supporting build tags in
gopls.meling commentedon Sep 19, 2019
I teach and use Go for programming labs, and keep solutions and skeleton code for the students in the same folder to ensure consistency with common files and to remember to change both if necessary.
I use
// +build solutionin solution files and// +build !solutionin skeleton code, since they have overlapping type/func definitions. (This of course results in numerous compile errors when using gopls in VSCode.)I run tests using
go test -tags solution.Running
go testwithout the solution tag should fail the tests.I then copy the skeleton code to a separate repo to share with the students.
jefferai commentedon Nov 20, 2019
Build tags are crucial for projects that have open source and enterprise variants.
rythmkraze commentedon Dec 1, 2019
gobbi, a package that provides bindings to GTK GUI toolkit, uses Go build tags to allow targeting of specific library versions. See here for more details.
stamblerre commentedon Jan 29, 2020
Thanks all for the detailed replies! This information will be very valuable as we continue work on #29202. Closing this issue in favor of that one. Please feel free to comment here if you have a different use case for build tags.
KBassford commentedon Mar 17, 2020
I have one file with '// +build debug', and an almost identical file in the same folder with '// +build !debug'. gopls flagged every constant, variable and function as being redefined between the two files. The debug file just prints log messages to replace functions that make major changes to the running state of the system.