golang编译

 

 

 小结:

go build -ldflags "-H windowsgui -X main.BuildVersion=`date +%m-%d-%H-%M-%S-%Y` -X main.TaskType=PING"  -o  App.exe;

go build -ldflags "-H windowsgui -X main.TaskType=PING -X main.BuildVersion=v1"  -o  App.exe;

 

例:编译的时候,带上编译的人的姓名

go build -ldflags "-X main.Developer=zhangsan"
1
main.go

package main

import "fmt"

var Developer string

func main() {
fmt.Println("Developer:", Developer)
}

 

 

C:\>go help build
usage: go build [-o output] [build flags] [packages]

Build compiles the packages named by the import paths,
along with their dependencies, but it does not install the results.

If the arguments to build are a list of .go files from a single directory,
build treats them as a list of source files specifying a single package.

When compiling packages, build ignores files that end in '_test.go'.

When compiling a single main package, build writes
the resulting executable to an output file named after
the first source file ('go build ed.go rx.go' writes 'ed' or 'ed.exe')
or the source code directory ('go build unix/sam' writes 'sam' or 'sam.exe').
The '.exe' suffix is added when writing a Windows executable.

When compiling multiple packages or a single non-main package,
build compiles the packages but discards the resulting object,
serving only as a check that the packages can be built.

The -o flag forces build to write the resulting executable or object
to the named output file or directory, instead of the default behavior described
in the last two paragraphs. If the named output is an existing directory or
ends with a slash or backslash, then any resulting executables
will be written to that directory.

The -i flag installs the packages that are dependencies of the target.
The -i flag is deprecated. Compiled packages are cached automatically.

The build flags are shared by the build, clean, get, install, list, run,
and test commands:

-a
force rebuilding of packages that are already up-to-date.
-n
print the commands but do not run them.
-p n
the number of programs, such as build commands or
test binaries, that can be run in parallel.
The default is the number of CPUs available.
-race
enable data race detection.
Supported only on linux/amd64, freebsd/amd64, darwin/amd64, windows/amd64,
linux/ppc64le and linux/arm64 (only for 48-bit VMA).
-msan
enable interoperation with memory sanitizer.
Supported only on linux/amd64, linux/arm64
and only with Clang/LLVM as the host C compiler.
On linux/arm64, pie build mode will be used.
-v
print the names of packages as they are compiled.
-work
print the name of the temporary work directory and
do not delete it when exiting.
-x
print the commands.

-asmflags '[pattern=]arg list'
arguments to pass on each go tool asm invocation.
-buildmode mode
build mode to use. See 'go help buildmode' for more.
-compiler name
name of compiler to use, as in runtime.Compiler (gccgo or gc).
-gccgoflags '[pattern=]arg list'
arguments to pass on each gccgo compiler/linker invocation.
-gcflags '[pattern=]arg list'
arguments to pass on each go tool compile invocation.
-installsuffix suffix
a suffix to use in the name of the package installation directory,
in order to keep output separate from default builds.
If using the -race flag, the install suffix is automatically set to race
or, if set explicitly, has _race appended to it. Likewise for the -msan
flag. Using a -buildmode option that requires non-default compile flags
has a similar effect.
-ldflags '[pattern=]arg list'
arguments to pass on each go tool link invocation.
-linkshared
build code that will be linked against shared libraries previously
created with -buildmode=shared.
-mod mode
module download mode to use: readonly, vendor, or mod.
By default, if a vendor directory is present and the go version in go.mod
is 1.14 or higher, the go command acts as if -mod=vendor were set.
Otherwise, the go command acts as if -mod=readonly were set.
See https://golang.org/ref/mod#build-commands for details.
-modcacherw
leave newly-created directories in the module cache read-write
instead of making them read-only.
-modfile file
in module aware mode, read (and possibly write) an alternate go.mod
file instead of the one in the module root directory. A file named
"go.mod" must still be present in order to determine the module root
directory, but it is not accessed. When -modfile is specified, an
alternate go.sum file is also used: its path is derived from the
-modfile flag by trimming the ".mod" extension and appending ".sum".
-overlay file
read a JSON config file that provides an overlay for build operations.
The file is a JSON struct with a single field, named 'Replace', that
maps each disk file path (a string) to its backing file path, so that
a build will run as if the disk file path exists with the contents
given by the backing file paths, or as if the disk file path does not
exist if its backing file path is empty. Support for the -overlay flag
has some limitations:importantly, cgo files included from outside the
include path must be in the same directory as the Go package they are
included from, and overlays will not appear when binaries and tests are
run through go run and go test respectively.
-pkgdir dir
install and load all packages from dir instead of the usual locations.
For example, when building with a non-standard configuration,
use -pkgdir to keep generated packages in a separate location.
-tags tag,list
a comma-separated list of build tags to consider satisfied during the
build. For more information about build tags, see the description of
build constraints in the documentation for the go/build package.
(Earlier versions of Go used a space-separated list, and that form
is deprecated but still recognized.)
-trimpath
remove all file system paths from the resulting executable.
Instead of absolute file system paths, the recorded file names
will begin with either "go" (for the standard library),
or a module path@version (when using modules),
or a plain import path (when using GOPATH).
-toolexec 'cmd args'
a program to use to invoke toolchain programs like vet and asm.
For example, instead of running asm, the go command will run
'cmd args /path/to/asm <arguments for asm>'.

The -asmflags, -gccgoflags, -gcflags, and -ldflags flags accept a
space-separated list of arguments to pass to an underlying tool
during the build. To embed spaces in an element in the list, surround
it with either single or double quotes. The argument list may be
preceded by a package pattern and an equal sign, which restricts
the use of that argument list to the building of packages matching
that pattern (see 'go help packages' for a description of package
patterns). Without a pattern, the argument list applies only to the
packages named on the command line. The flags may be repeated
with different patterns in order to specify different arguments for
different sets of packages. If a package matches patterns given in
multiple flags, the latest match on the command line wins.
For example, 'go build -gcflags=-S fmt' prints the disassembly
only for package fmt, while 'go build -gcflags=all=-S fmt'
prints the disassembly for fmt and all its dependencies.

For more about specifying packages, see 'go help packages'.
For more about where packages and binaries are installed,
run 'go help gopath'.
For more about calling between Go and C/C++, run 'go help c'.

Note: Build adheres to certain conventions such as those described
by 'go help gopath'. Not all projects can follow these conventions,
however. Installations that have their own conventions or that use
a separate software build system may choose to use lower-level
invocations such as 'go tool compile' and 'go tool link' to avoid
some of the overheads and design decisions of the build tool.

See also: go install, go get, go clean.

C:\>go version
go version go1.16.7 windows/amd64

 

 

go build 可以用-gcflagsgo编译器传入参数,也就是传给go tool compile的参数,因此可以用go tool compile --help查看所有可用的参数。

其中-m可以检查代码的编译优化情况,包括逃逸情况和函数是否内联。

如果只在编译特定包时需要传递参数,格式应遵守“包名=参数列表”,如go build -gcflags -gcflags='log=-N -l' main.go

go build用-ldflags给go链接器传入参数,实际是给go tool link的参数,可以用go tool link --help查看可用的参数。

常用-X来指定版本号等编译时才决定的参数值。例如代码中定义var buildVer string,然后在编译时用go build -ldflags "-X main.buildVer=1.0" ... 来赋值。注意-X只能给string类型变量赋值。

go build 参数汇总_DisMisPres的博客-CSDN博客 https://blog.csdn.net/DisMisPres/article/details/115110442

go 的编译是以 package main 的 main() 函数作为主入口,生成可执行文件。若 build 的是非 main 包,则不会生成可执行文件,只检查是否可执行编译。
可以输入 go help build 查看官方解释。
go build 编译包时,会忽略“_test.go”结尾的文件(即测试文件)。

参数 含义
-o output 指定编译输出的名称,代替包名
-i install 安装作为目标的依赖关系的包(用于增量编译提速)
-a 强行对项目所有的代码包(包含标准库中的代码包)进行重新构建,即使它们已经是最新的了
-n 打印编译期间所用到的命令,仅仅是打印并不真正执行它们
-p n 指定编译过程中执行各任务的并行数量(确切地说应该是并发数量)。在默认情况下,该数量等于CPU的逻辑核数。但是在darwin/arm平台(即iPhone和iPad所用的平台)下,该数量默认是1
-race 开启竞态条件的检测。不过此标记目前仅在linux/amd64、freebsd/amd64、darwin/amd64和windows/amd64平台下受到支持
-msan 使用内存清除器启用互操作。只支持Linux/AMD 64、Linux/ARM 64,并且只有clang/llvm作为主机c+编译器
-v 打印出那些被编译时的代码包的名字
-x 打印编译期间所用到的其它命令(且执行),注意它与-n标记的区别
-work 打印出编译时生成的临时工作目录的路径,并在编译结束时保留它。在默认情况下,编译结束时会删除该目录
以下为不常用命令
-asmflags 此标记可以后跟另外一些标记,如-D、-I、-S等。这些后跟的标记用于控制Go语言编译器编译汇编语言文件时的行为
-buildmode 此标记用于指定编译模式,使用方式如-buildmode=default(这等同于默认情况下的设置)。此标记支持的编译模式目前有6种。借此,我们可以控制编译器在编译完成后生成静态链接库(即.a文件,也就是我们之前说的归档文件)、动态链接库(即.so文件)或/和可执行文件(在Windows下是.exe文件) go help buildmode
-compiler 此标记用于指定当前使用的编译器的名称。其值可以为gc或gccgo。其中,gc编译器即为Go语言自带的编辑器,而gccgo编译器则为GCC提供的Go语言编译器
-gccgoflags 此标记用于指定需要传递给gccgo编译器或链接器的标记的列表
-gcflags 此标记用于指定需要传递给go tool compile命令的标记的列表
-installsuffix 为了使当前的输出目录与默认的编译输出目录分离,可以使用这个标记。此标记的值会作为结果文件的父目录名称的后缀。其实,如果使用了-race标记,这个标记会被自动追加且其值会为race。如果我们同时使用了-race标记和-installsuffix,那么在-installsuffix标记的值的后面会再被追加_race,并以此来作为实际使用的后缀
-ldflags 此标记用于指定需要传递给go tool link命令的标记的列表
-linkshared 此标记用于与-buildmode=shared一同使用。后者会使作为编译目标的非main代码包都被合并到一个动态链接库文件中,而前者则会在此之上进行链接操作
-pkgdir 指定一个目录,并从改目录下加载编译好的.a 文件,并把编译可能产生新的 .a 文件放入到该目录中
-tags 此标记用于指定在实际编译期间需要受理的编译标签(也可被称为编译约束)的列表
-toolexec 此标记可以让我们去自定义在编译期间使用一些Go语言自带工具(如vet、asm等)的方式
-tags
例:编译debug版本

go build -tags "debug"
1
注意:build.go 和 build_debug.go 的文件开头的 // +build debug 注释,这个就是你编译时的 tags

main.go

package main
func main() {
tBuildTag()
}

build.go

// +build !debug

package main

import "fmt"

func tBuildTag() {
fmt.Println("no debug")
}

build_debug.go

// +build debug

package main

import "fmt"

func tBuildTag() {
fmt.Println("debug")
}

-ldflags ‘flag list’
'-s -w': 压缩编译后的体积
-s: 去掉符号表
-w: 去掉调试信息,不能gdb调试了
-X: 设置包中的变量值

例:编译的时候,带上编译的人的姓名

go build -ldflags "-X main.Developer=zhangsan"
1
main.go

package main

import "fmt"

var Developer string

func main() {
fmt.Println("Developer:", Developer)
}

执行编译好的程序,可以看到 Developer: zhangsan 输出。

-race
go run -race 是不会进行竞态检测的。需要先 go build -race,然后再执行编译好的文件。如下是一个竞态示例输出:

==================
WARNING: DATA RACE
Read at 0x00c0000c9ce0 by goroutine 8:
container/list.(*List).remove()
D:/Go/src/container/list/list.go:109 +0x119
container/list.(*List).Remove()
D:/Go/src/container/list/list.go:141 +0x27a
commonTest/list.tList1.func2()
F:/GoTest/GoTest/list/list.go:55 +0x10c

Previous write at 0x00c0000c9ce0 by goroutine 7:
container/list.(*List).insertValue()
D:/Go/src/container/list/list.go:104 +0x10c
container/list.(*List).PushBack()
D:/Go/src/container/list/list.go:155 +0xc6
commonTest/list.tList1.func1()
F:/GoTest/GoTest/list/list.go:27 +0x92

Goroutine 8 (running) created at:
commonTest/list.tList1()
F:/GoTest/GoTest/list/list.go:37 +0x1cb
commonTest/list.Test()
F:/GoTest/GoTest/list/entrance.go:4 +0x37
main.main()
F:/GoTest/GoTest/main.go:19 +0x32

Goroutine 7 (finished) created at:
commonTest/list.tList1()
F:/GoTest/GoTest/list/list.go:25 +0x17e
commonTest/list.Test()
F:/GoTest/GoTest/list/entrance.go:4 +0x37
main.main()
F:/GoTest/GoTest/main.go:19 +0x32
==================
google官方解释
go build 命令介绍
go build命令详解
“go build -X” 的妙用

 

 

golang项目中使用条件编译 - yuchen16 - 博客园 https://www.cnblogs.com/ksir16/p/9050721.html

How to use conditional compilation with the go build tool – The acme of foolishness https://dave.cheney.net/2013/10/12/how-to-use-conditional-compilation-with-the-go-build-tool

golang项目中使用条件编译

C语言中的条件编译

golang中没有类似C语言中条件编译的写法,比如在C代码中可以使用如下语法做一些条件编译,结合宏定义来使用可以实现诸如按需编译release和debug版本代码的需求

#ifndef
#define
...

#end

 

golang中的条件编译

golang支持两种条件编译的实现方式

  • build tags
  • 文件后缀

1. 通过Build tags实现

build tags 是通过代码注释的形式实现的,要写在文件的最顶端;

go build指令在编译项目的时候会检查每一个文件的build tags,用来决定是编译还是跳过该文件

build tags遵循以下规则

  1. 不同tag域之间用空格区分,他们是OR关系
  2. 同一tag域之内不同的tag用都好区分,他们是AND关系
  3. 每一个tag都由字母和数字构成,!开头表示条件“非”

示例:

// +build darwin freebsd netbsd openbsd

约束此文件只能在支持kqueue的BSD系统上编译

一个文件可能包含多行条件编译注释,比如:

// +build linux darwin
// +build 386

约束该文件在linux/386 或 darwin/386平台编译

需要注意的点

tag注释和包声明必须用空行隔开,比如下面的写法是错误的,编译器会把第一行作为包说明来处理,而不是build tags

1 // +build !linux
2 package mypkg // wrong

 

正确的写法如下:

1 // +build !linux
2 
3 package mypkg // correct

 

编译方法:

只需要在go build指令后用-tags指定编译条件即可

go build -tags linux

 

2. 通过文件名后缀实现

具有_$GOOS.go后缀的go文件在编译的时候会根据当前平台来判断是否将该文件导入并编译;同样适用于处理器架构判断 _$GOARCH.go

两者可以结合起来使用,形式为: _$GOOS_$GOARCH.go

示例:

mypkg_freebsd_arm.go // 只在 freebsd/arm 编译
mypkg_plan9.go       // 只在 plan9 编译

 

文件名必须提供,如果只由后缀的文件名会被编译器忽略,比如:

_linux.go
_freebsd_386.go

 

这两个文件会被编译器忽略,因为以下划线开头的文件都会被忽略

How to use conditional compilation with the go build tool

When developing Go packages that rely on specific features of the underlying platform or processor it is often necessary to provide a specialised implementation.

Go does not have a preprocessor, a macro system, or a #define declaration to control the inclusion of platform specific code. Instead a system of tags and naming convention defined in the go/build package and supported by the go tool allows Go packages to customise themselves for the specific platform they are being compiled for.

This post explains how conditional compilation is implemented and show you how you can use it in your projects.

But first, go list

Before we can talk about conditional compilation, we need to learn a little bit about the go list command. go list gives you access to the internal data structures which power the build process.

go list takes the most of the same arguments as go buildtest, and install but does not perform any compilation. Using the -f, format flag we can supply a snippet of text/template code which is executed in a context containing a go/build.Package structure.

Using the format flag, we can ask go list to tell us the names of the files that would be compiled.

% go list -f '{{.GoFiles}}' os/exec
[exec.go lp_unix.go]

In the example above I asked for the list of files in os/exec package that would be compiled on this linux/arm system. The result is two files, exec.go which contains the common code shared across all platforms, and lp_unix.go while contains an implementation of exec.LookPath for unix-like systems.

If I were to run the same command on a Windows system, the result would be

C:\go> go list -f '{{.GoFiles}}' os/exec
[exec.go lp_windows.go]

This short example demonstrates the two parts of the Go conditional compilation system, known as Build Constraints, which we will now explore in more detail.

Build tags

The first method of conditional compilation is via an annotation in the source code, commonly known as a build tag.

Build tags are implemented as comments and should appear as close to the top of the file as possible.

When go build is asked to build a package it will analyse each source file in the package looking for build tags. These tags control whether go build will pass the file to the compiler.

A build tags follow these three rules

  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. each term is an alphanumeric word or, preceded by !, its negation

As an example, the build tag found at the top of a source file

// +build darwin freebsd netbsd openbsd

would constrain this file to only building on BSD systems that supported kqueue.

A file may have multiple build tags. The overall constraint is the logical AND of the individual constraints. For example

// +build linux darwin
// +build 386

constrains the build to linux/386 or darwin/386 platforms only.

A note about comments

One thing that generally catches people out when they are first trying to make build tags work is this

// +build !linux
package mypkg // wrong

In this example there is no newline separating the build tag and the package declaration. Because of this the build tag is associated with the package declaration as a comment describing the package and thus ignored.

// +build !linux

package mypkg // correct

This is the correct form, a comment with a trailing newline stands alone and is not associated with any declaration and go vet will detect the missing newline.

% go vet mypkg
mypkg.go:1: +build comment appears too late in file
exit status 1

When this feature was added to go vet it detected several mistakes in the standard library and sub repos, so don’t feel bad if you get it wrong the first time.

For reference, here is a sample showing a licence preamble, a build tag, and a package declaration

% head headspin.go 
// Copyright 2013 Way out enterprises. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build someos someotheros thirdos,!amd64

// Package headspin implements calculates numbers so large
// they will make your head spin.
package headspin

File suffixes

The second option for providing conditional compilation is the name of the source file itself. This scheme is simpler than build tags, and allows the go/build package to exclude files without having to process the file.

The naming convention is described in the documentation for the go/build package. Simply put, if your source file includes the suffix, _$GOOS.go then it will only be built on that platform. All other platforms will behave as if the file is not present. The same applies for _$GOARCH.go. The two can be combined as _$GOOS_$GOARCH.go, but not _$GOARCH_$GOOS.go.

Some examples of file suffixes are,

mypkg_freebsd_arm.go // only builds on freebsd/arm systems
mypkg_plan9.go       // only builds on plan9

Your source files still require a name, a suffix is not sufficient, for example

_linux.go
_freebsd_386.go

will be ignored, even on linux or freebsd systems, because the go/build package ignores any file beginning with a period or an underscore.

Choosing between build tags and file suffixes

Build tags and file suffixes overlap in fuctionality. For example, a file called mypkg_linux.go that contained the build tag // +build linux is redundant.

In general, when choosing between a build tag or a file suffix, you should choose a file suffix when there is an exact match between the platform or architecture and the file you want to include. eg,

mypkg_linux.go         // only builds on linux systems
mypkg_windows_amd64.go // only builds on windows 64bit platforms

Conversely if your file is applicable to more than one platform or architecture, or you need to exclude a specific platform, a build tag should be used. eg,

% grep '+build' $HOME/go/src/pkg/os/exec/lp_unix.go 
// +build darwin dragonfly freebsd linux netbsd openbsd

builds on all unix like platforms.

% grep '+build' $HOME/go/src/pkg/os/types_notwin.go 
// +build !windows

builds on all platforms except Windows.

Wrapping up

While this post has focused only on Go source files, build tags and file suffixes can be used with any source file that the go tool can build. This includes .c and .s files. The Go standard library, specifically the runtimesyscallos and net packages contain great examples, I recommend studying them.

Test files also support build tags and file suffixes and behave in the same manner as Go source files, conditionally including test cases on a per platform basis. Again the standard library contains many great examples.

Finally, while the title of this article talks about the go tool, the conditional compilation features are not limited to just that tool. You can build your own tools to consume and analyse Go code with the same file suffix and build tag semantics using the go/build package.

Posted in GoPhotography by Dave Cheney · Tags: build constraintsbuild tagsgo build

 

 

 

 

posted @ 2021-11-05 09:52  papering  阅读(1178)  评论(0编辑  收藏  举报