英文:
Can I import a Golang package based on the OS I'm building for?
问题
假设我有一个基于不同操作系统和某些情况下不同发行版的 Go 项目,我想根据操作系统/发行版选择使用 Systemd 客户端包、Upstart 客户端包、sysv 客户端包或 launchd 客户端包。我是否可以有选择地导入每个包,以便根据正在构建的操作系统/发行版只导入所需的包?还是说我必须为每个操作系统/发行版都导入每个包?
英文:
Say I have a go project that based on which OS, and in some cases which distro, I want to use say a Systemd client package vs an Upstart client package vs a sysv client package vs a launchd client package. Is it possible to selectively import each package so I only import the one I need per OS/distro I'm building for? Or do I have to import each package for each OS/distro?
答案1
得分: 9
> 构建约束
>
> 构建约束,也称为构建标签,是一个以行注释形式开始的行,
>
> // +build
>
> 它列出了一个文件应该包含在包中的条件。约束可以出现在任何类型的源文件中(不仅仅是Go文件),但它们必须出现在文件的顶部附近,只能由空行和其他行注释分隔。这些规则意味着在Go文件中,构建约束必须出现在包声明之前。
>
> 为了将构建约束与包文档区分开,一系列构建约束后必须有一个空行。
>
> 构建约束被评估为以空格分隔的选项的逻辑或;每个选项被评估为逗号分隔的项的逻辑与;每个项都是一个字母数字单词,或者在前面加上!表示其否定。也就是说,构建约束:
>
> // +build linux,386 darwin,!cgo
>
> 对应于布尔公式:
>
> (linux AND 386) OR (darwin AND (NOT cgo))
>
> 一个文件可以有多个构建约束。整体约束是各个约束的逻辑与。也就是说,构建约束:
>
> // +build linux darwin
> // +build 386
>
> 对应于布尔公式:
>
> (linux OR darwin) AND 386
>
> 在特定的构建过程中,以下单词被满足:
>
> - 目标操作系统,由runtime.GOOS指定
> - 目标架构,由runtime.GOARCH指定
> - 正在使用的编译器,可以是"gc"或"gccgo"
> - 如果ctxt.CgoEnabled为true,则为"cgo"
> - 从Go版本1.1开始的"go1.1"
> - 从Go版本1.2开始的"go1.2"
> - 从Go版本1.3开始的"go1.3"
> - 从Go版本1.4开始的"go1.4"
> - 从Go版本1.5开始的"go1.5"
> - 从Go版本1.6开始的"go1.6"
> - ctxt.BuildTags中列出的任何其他单词
>
> 如果一个文件的名称,在去掉扩展名和可能的_test后缀之后,与以下模式之一匹配:
>
> *_GOOS
> *_GOARCH
> *_GOOS_GOARCH
>
> (例如:source_windows_amd64.go),其中GOOS和GOARCH分别表示任何已知的操作系统和架构值,那么该文件被认为具有隐式的构建约束,需要这些术语(除了文件中的任何显式约束)。
>
> 要防止一个文件被考虑用于构建:
>
> // +build ignore
>
> (任何其他不满足的单词也可以,但是“ignore”是常规的。)
>
> 仅在使用cgo且仅在Linux和OS X上构建文件:
>
> // +build linux,cgo darwin,cgo
>
> 这样的文件通常与另一个文件配对,为其他系统实现默认功能,在这种情况下,该文件将带有约束:
>
> // +build !linux,!darwin !cgo
>
> 将文件命名为dns_windows.go将导致它仅在为Windows构建包时包含;类似地,将math_386.s命名为仅在为32位x86构建包时包含。
>
> 使用GOOS=android将与GOOS=linux一样匹配构建标签和文件,另外还会匹配android标签和文件。
使用构建约束。
使用一个包含多个文件的单一包。每个文件为特定的操作系统、架构等组合提供专门的功能。
英文:
> Package build
>
> Build Constraints
>
> A build constraint, also known as a build tag, is a line comment that
> begins
>
> // +build
>
> that lists the conditions under which a file should be included in the
> package. Constraints may appear in any kind of source file (not just
> Go), but they must appear near the top of the file, preceded only by
> blank lines and other line comments. These rules mean that in Go files
> a build constraint must appear before the package clause.
>
> To distinguish build constraints from package documentation, a series
> of build constraints must be followed by a blank line.
>
> A build constraint is evaluated as the OR of space-separated options;
> each option evaluates as the AND of its comma-separated terms; and
> each term is an alphanumeric word or, preceded by !, its negation.
> That is, the build constraint:
>
> // +build linux,386 darwin,!cgo
>
> corresponds to the boolean formula:
>
> (linux AND 386) OR (darwin AND (NOT cgo))
>
> A file may have multiple build constraints. The overall constraint is
> the AND of the individual constraints. That is, the build constraints:
>
> // +build linux darwin
> // +build 386
>
> corresponds to the boolean formula:
>
> (linux OR darwin) AND 386
>
> During a particular build, the following words are satisfied:
>
> - the target operating system, as spelled by runtime.GOOS
> - the target architecture, as spelled by runtime.GOARCH
> - the compiler being used, either "gc" or "gccgo"
> - "cgo", if ctxt.CgoEnabled is true
> - "go1.1", from Go version 1.1 onward
> - "go1.2", from Go version 1.2 onward
> - "go1.3", from Go version 1.3 onward
> - "go1.4", from Go version 1.4 onward
> - "go1.5", from Go version 1.5 onward
> - "go1.6", from Go version 1.6 onward
> - any additional words listed in ctxt.BuildTags
>
> If a file's name, after stripping the extension and a possible _test
> suffix, matches any of the following patterns:
>
> *_GOOS
> *_GOARCH
> *_GOOS_GOARCH
>
> (example: source_windows_amd64.go) where GOOS and GOARCH represent any
> known operating system and architecture values respectively, then the
> file is considered to have an implicit build constraint requiring
> those terms (in addition to any explicit constraints in the file).
>
> To keep a file from being considered for the build:
>
> // +build ignore
>
> (any other unsatisfied word will work as well, but “ignore” is
> conventional.)
>
> To build a file only when using cgo, and only on Linux and OS X:
>
> // +build linux,cgo darwin,cgo
>
> Such a file is usually paired with another file implementing the
> default functionality for other systems, which in this case would
> carry the constraint:
>
> // +build !linux,!darwin !cgo
>
> Naming a file dns_windows.go will cause it to be included only when
> building the package for Windows; similarly, math_386.s will be
> included only when building the package for 32-bit x86.
>
> Using GOOS=android matches build tags and files as for GOOS=linux in
> addition to android tags and files.
Use build constraints.
Use a single package with multiple files. Each file specializes for a particular OS, architecture, etc, combination.
答案2
得分: 2
一个构建约束被解释为用空格分隔的选项的逻辑或;每个选项被解释为逗号分隔的项的逻辑与;每个项是一个字母数字单词,或者在其前面加上!。
实际上,这将在Go 1.17(2021年第3季度)中发生变化。
//go:build行
go命令现在理解//go:build行,并优先使用它们而不是// +build行。
新的语法使用布尔表达式,与Go语言一样,应该更不容易出错。
从此版本开始,完全支持新的语法,并且所有Go文件都应该更新为具有相同含义的两种形式。为了帮助迁移,gofmt现在会自动同步这两种形式。
有关语法和迁移计划的更多详细信息,请参见https://golang.org/design/draft-gobuild。
从设计文档中可以看出:
设计的核心思想是用更熟悉的布尔表达式替换当前的构建标签选择的// +build行。
例如,旧的语法
// +build linux
// +build 386
将被新的语法替换为
//go:build linux && 386
英文:
> A build constraint is evaluated as the OR of space-separated options; each option evaluates as the AND of its comma-separated terms; and each term is an alphanumeric word or, preceded by !
Actually, that will change with Go 1.17 (Q3 2021)
> ## //go:build
lines
>
> The go
command now understands //go:build
lines and prefers them over // +build
lines.
>
> The new syntax uses boolean expressions, just like Go, and should be less error-prone.
>
> As of this release, the new syntax is fully supported, and all Go files should be updated to have both forms with the same meaning.
To aid in migration, gofmt
now automatically synchronizes the two forms.
For more details on the syntax and migration plan, see https://golang.org/design/draft-gobuild.
From the design document:
> The core idea of the design is to replace the current // +build
lines for build tag selection with new //go:build
lines that use more familiar boolean expressions.
>
> For example, the old syntax
>
>go
>// +build linux
>// +build 386
>
>would be replaced by the new syntax
>go
>//go:build linux && 386
>
1: https://twitter.com/golang/status/1403016905179422723
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论