初入门径:


go build [-o 输出名] [-i] [编译标记] [包名]

-o-i通用的编译标记参数go  clean, get, install, list, run, test包名go build



go build


对于:

1
2
3
4
5
6
7
8
 ll
total 32
drwxr-xr-x 6 fliter staff 192 Jun 3 10:20 .
drwxr-xr-x 15 fliter staff 480 Jun 2 21:22 ..
-rw-r--r-- 1 fliter staff 115 Jun 3 09:31 add.go
-rw-r--r-- 1 fliter staff 18 Jun 3 09:25 go.mod
-rw-r--r-- 1 fliter staff 110 Jun 3 08:52 m.go
-rw-r--r-- 1 fliter staff 166 Jun 3 08:52 sli.go
go buildgo build .

(如果有多个 main方法,则会抛错):



Go语言任何一个package中,都可以有唯一一个带有main方法的go文件. 也就是说,一个package下,只能有一个main方法,不管是在哪个文件中,但是只能有一个.



(将sli.go和m.go中的main方法改掉)

go buildgo build




通用的编译标记参数(即 编译时的附加参数)


附加参数 备注
-v 编译时显示包名
-p n 开启并发编译,默认情况下该值为 CPU 逻辑核数
-a 强制重新构建, 强行对所有涉及到的代码包(包含标准库中的代码包)进行重新构建,即使它们已是最新的
-n 打印编译时会用到的所有命令,但不真正执行
-x 打印编译时会用到的所有命令
-race 开启竞态检测
-work 打印出编译时生成的临时工作目录的路径,并在编译结束时保留它;在默认情况下,编译结束时会删除该目录


add.go:

1
2
3
4
5
6
7
8
9
10
package main

import "fmt"

func add(x int, y int) int {
return x + y
}
func main() {
fmt.Println(add(42, 13))
}
go build -a -v add.go


明明只用到了fmt包,为什么会多编译了这么多的代码包?

fmtruntime

从代码包编译的角度来说,如果代码包A依赖代码包B,则称代码包B是代码包A的依赖代码包(以下简称依赖包),代码包A是代码包B的触发代码包(以下简称触发包)

go build

此过程完成后,所有依赖关系也就形成了一棵含有重复元素的依赖树. 对于依赖树中的一个节点(代码包)来说,它的直接分支节点(前者的依赖包),是按照代码包导入路径的字典序从左到右排列的. 最左边的分支节点会最先被编译, 编译器会依此设定每个代码包的编译优先级


fmt
1
2
3
4
5
6
7
8
package main


func add(x int, y int) int {
return x + y
}
func main() {
}

即便一个包也不引用,程序依然在底层用到了上面这几个包.


- work


go build
-p ngo build-p 1
fmtgo build -a -v -p 1 add.go

可以认为上图显示的代码包的顺序,就是add直接或间接依赖的代码包按照优先级从高到低排列后的排序

-n-p 1




进阶编译标记参数:


-asmflags

此标记可以后跟另外一些标记,如-D、-I、-S等。这些后跟的标记用于控制Go语言编译器编译汇编语言文件时的行为。


-buildmode

此标记用于指定编译模式,使用方式如-buildmode=default(这等同于默认情况下的设置)。此标记支持的编译模式目前有6种。借此,我们可以控制编译器在编译完成后生成静态链接库(即.a文件,也就是我们之前说的归档文件)、动态链接库(即.so文件)或/和可执行文件(在Windows下是.exe文件)。


-compiler

此标记用于指定当前使用的编译器的名称。其值可以为gc或gccgo。其中,gc编译器即为Go语言自带的编辑器,而gccgo编译器则为GCC提供的Go语言编译器。而GCC则是GNU项目出品的编译器套件。GNU是一个众所周知的自由软件项目。在开源软件界不应该有人不知道它。好吧,如果你确实不知道它,赶紧去google吧。


-gccgoflags

此标记用于指定需要传递给gccgo编译器或链接器的标记的列表。


-gcflags

此标记用于指定需要传递给go tool compile命令的标记的列表。

-gcflags=”all=-N -l”

  • -N 取消优化
  • -l 取消内联
  • -m 逃逸分析,打印逃逸信息

  • go build -gcflags=-S fmt 仅打印fmt包的反汇编信息

  • go build -gcflags=all=-S fmt’ 打印fmt以及其依赖包的反汇编信息


-installsuffix

为了使当前的输出目录与默认的编译输出目录分离,可以使用这个标记。此标记的值会作为结果文件的父目录名称的后缀。其实,如果使用了-race标记,这个标记会被自动追加且其值会为race。如果我们同时使用了-race标记和-installsuffix,那么在-installsuffix标记的值的后面会再被追加_race,并以此来作为实际使用的后缀。


-ldflags

此标记用于指定需要传递给go tool link命令的标记的列表。


-linkshared

此标记用于与-buildmode=shared一同使用。后者会使作为编译目标的非main代码包都被合并到一个动态链接库文件中,而前者则会在此之上进行链接操作。


-pkgdir

使用此标记可以指定一个目录。编译器会只从该目录中加载代码包的归档文件,并会把编译可能会生成的代码包归档文件放置在该目录下。


-tags

此标记用于指定在实际编译期间需要受理的编译标签(也可被称为编译约束)的列表。这些编译标签一般会作为源码文件开始处的注释的一部分,例如,在$GOROOT/src/os/file_posix.go开始处的注释为:

1
2
3
4
5
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
go/build


-toolexec

此标记可以让我们去自定义在编译期间使用一些Go语言自带工具(如vet、asm等)的方式。




参考: