What does go build build? (go build vs. go install)

huangapple go评论85阅读模式
英文:

What does go build build? (go build vs. go install)

问题

新的Go程序员经常不知道或混淆了go build命令的基本作用。

go buildgo install命令究竟构建了什么,它们将结果/输出放在哪里?

英文:

New Go programmers often don't know or get confused what the fundamental go build command does.

What do exactly the go build and go install commands build and where do they put the result/output?

答案1

得分: 198

go命令的功能取决于我们是针对一个“普通”包还是针对特殊的"main"包运行它。

对于包

  • go build 构建你的包然后 丢弃结果
  • go install 构建并 安装 包到 $GOPATH/pkg 目录中。

对于命令(main包)

  • go build 构建命令并将结果留在 当前工作目录 中。
  • go install 在临时目录中构建命令,然后将其移动到 $GOPATH/bin

go build应该传递什么?

你可以传递 go build,这些包是你想要构建的包。你也可以传递一个来自单个目录的 .go 文件列表,这些文件被视为指定单个包的源文件列表。

如果没有提供包(导入路径),则构建将应用于当前目录。

导入路径可以包含一个或多个 "..." 通配符(此时它是一个 模式)。... 可以匹配任何字符串,例如 net/... 匹配 net 包以及位于其任何子文件夹中的包。通常在项目根目录中使用以下命令构建当前文件夹和所有递归的包:

go build ./...

这个命令用于构建整个项目。

有关指定包的更多信息,请运行 go help packages

关于模块

Go 1.11 引入了对 Go 模块的初步支持,并且从 Go 1.13 开始,模块成为默认选项。当在包含 go.mod 文件的文件夹(或当前文件夹的父文件夹之一)中运行 go 工具时,go 工具以 模块感知 模式运行(传统模式称为 GOPATH 模式)。

> 在模块感知模式下,GOPATH 不再定义构建过程中导入的含义,但它仍然存储已下载的依赖项(在 GOPATH/pkg/mod 中)和已安装的命令(在 GOPATH/bin 中,除非设置了 GOBIN)。

在构建模块时,构建列表指定要构建的内容。构建列表最初只包含主模块(包含运行 go 命令的目录的模块),然后将主模块的依赖项递归地添加到构建列表中(也添加其依赖项的依赖项)。

有关更多信息,请运行 go help modules


基本上,你可以使用 go build 来检查包(以及它们的依赖项)是否可以构建,而 go install 则会将结果(永久地)安装到 $GOPATH 的正确文件夹中。

如果一切正常,go build 将静默终止,如果无法构建/编译包,它将给出错误消息。

每当 go 工具安装一个包或二进制文件时,它还会安装其所依赖的任何依赖项,因此运行 go install 也会自动安装程序所依赖的包(公开可用的“可获取的”包)。

首先,阅读官方的如何编写 Go 代码页面。

有关 go 工具的更多信息:命令 go

你还可以通过运行以下命令获得更多帮助:

go help build

值得注意的是,从 Go 1.5 开始,go install 还会删除由 go build 创建的可执行文件(来源):

> 如果 'go install'(没有参数,表示当前目录)成功,则删除由 'go build' 写入的可执行文件(如果存在)。这样可以避免留下过时的二进制文件...

补充一下,go run 将你的应用程序编译到一个临时文件夹,并启动该可执行二进制文件。当应用程序退出时,它会正确清理临时文件。

<sub>问题灵感来自 Dave Cheney 的What does go build build?</sub>

英文:

What the go command does depends on whether we run it for a "normal" package or for the special &quot;main&quot; package.

For packages

  • go build&#160;&#160; builds your package then discards the results.
  • go install builds then installs the package in your $GOPATH/pkg directory.

For commands (package main)

  • go build&#160;&#160; 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.

What to pass to go build?

You may pass packages to go build, packages you want to build. You may also pass a list of .go files from a single directory, which is then treated as the list of source files specifying a single package.

If no packages (import paths) are provided, the build is applied on the current directory.

An import path may contain one or more &quot;...&quot; wildcards (in which case it is a pattern). ... can match any string, e.g. net/... matches the net package and packages being in any of its subfolders. The command

go build ./...

often used to build the package in the current folder and all packages recursing down. This command issued in a project root builds the complete project.

For more about specifying packages, run go help packages.

Regarding modules

Preliminary support for Go modules was introduced in Go 1.11, and modules became default starting with Go 1.13. When the go tool is run from a folder which contains a go.mod file (or one of the parents of the current folder), the go tool runs in module-aware mode (the legacy mode is called GOPATH mode).

> In module-aware mode, GOPATH no longer defines the meaning of imports
during a build, but it still stores downloaded dependencies (in GOPATH/pkg/mod)
and installed commands (in GOPATH/bin, unless GOBIN is set).

When building modules, what is built is specified by the build list. The build list initially contains only the main module (the module containing the directory where the go command is run), and the dependencies of the main module are added to the build list, recursively (dependencies of dependencies are also added).

For more info, run go help modules.


Basically you can use go build as a check that the packages can be built (along with their dependencies) while go install also (permanently) installs the results in the proper folders of your $GOPATH.

go build will silently terminate if everything is OK, and will give you error messages if the packages cannot be built/compiled.

Whenever the go tool installs a package or binary, it also installs whatever dependencies it has, so running go install will also install packages your program depends on (publicly available, "go gettable" packages), automatically.

For a start, read the official How to Write Go Code page.

More information about the go tool: Command go

You can also get more help by running the following command:

go help build

It is also worth noting that starting with Go 1.5 go install also removes executables created by go build (source):

> If 'go install' (with no arguments, meaning the current directory)
succeeds, remove the executable written by 'go build', if present. This avoids leaving a stale binary behind...

To complete the list, go run compiles your application into a temporary folder, and starts that executable binary. When the app exits, it properly cleans up the temporary files.

<sub>Question inspired by Dave Cheney's What does go build build?</sub>

答案2

得分: 20

对于包:

> go build:构建你的包然后丢弃结果

在Go 1.10之后(2018年第一季度),这将不再是真实的,感谢CL 68116CL 75473。请参考这个线程,我在这里引用。

> > go buildgo install命令具体构建了什么?

> 每当go工具安装一个包或二进制文件时,它还会安装它所依赖的任何依赖项,因此运行go install也会自动安装程序所依赖的包(公开可获取的“go gettable”包)。

实际上... go install在Go 1.10中也会有变化,除了新的缓存之外:

> “go install”命令不再安装指定包的依赖项CL 75850)。

> 如果你运行“go install foo”,那么唯一安装的就是foo

> 以前的情况是不同的。如果依赖项已过时,“go install”还会安装任何依赖项。
在“go install”期间隐式安装依赖项对用户来说造成了很多困惑和头痛,但以前为了启用增量构建是必要的。
现在不再需要了。
我们认为新的“install我说的”语义将更容易理解,特别是因为从错误报告中明显可以看出,许多用户已经期望这样。
要在“go install”期间强制安装依赖项,请使用新的“go install -i,类似于“go build -i”和“go test -i”。

> “go install”以前安装任何重新构建的依赖项最常引起混淆的情况是与-a结合使用,它的意思是“强制重新构建所有依赖项”。
现在,“go install -a myprog”将强制完全重新构建myprog的所有依赖项,以及myprog本身,但只有myprog会被安装。(当然,所有重新构建的依赖项仍然会保存在构建缓存中。)
使这种情况更易于理解对于与新的基于内容的陈旧分析结合使用尤为重要,因为它认为有比以前更频繁重新构建依赖项的充分理由,这将增加“为什么我的依赖项被安装了”混淆的数量。
例如,如果你运行“go install -gcflags=-N myprog”,那么安装的是一个没有编译器优化的myprog,但它不再重新安装myprog使用的标准库中没有编译器优化的包。

英文:

For package:

> go build: builds your package then discards the results

That won't be true after Go 1.10 (Q1 2018), thank to CL 68116 and CL 75473. See this thread, that I reference here.

> > What do exactly the go build and go install commands build

> Whenever the go tool installs a package or binary, it also installs whatever dependencies it has, so running go install will also install packages your program depends on (publicly available, "go gettable" packages), automatically.

Actually... go install will change also with Go 1.10, in addition of the new cache:

> The "go install" command no longer installs dependencies of the named packages (CL 75850).

> If you run "go install foo", the only thing installed is foo.

> Before, it varied. If dependencies were out-of-date, "go install" also installed any dependencies.
The implicit installation of dependencies during "go install" caused a lot of confusion and headaches for users, but it was previously necessary to enable incremental builds.
Not anymore.
We think that the new "install what I said" semantics will be much more understandable, especially since it's clear from bug reports that many users already expected them.
To force installation of dependencies during "go install", use the new "go install -i", by analogy with "go build -i" and "go test -i".

> The fact that "go install" used to install any rebuilt dependencies caused confusion most often in conjunction with -a, which means "force rebuild of all dependencies".
Now, "go install -a myprog" will force a complete rebuild of all dependencies of myprog, as well as myprog itself, but only myprog will get installed. (All the rebuilt dependencies will still be saved in the build cache, of course.)
Making this case work more understandably is especially important in conjunction with the new content-based staleness analysis, because it sees good reasons to rebuild dependencies more often than before, which would have increased the amount of "why did my dependencies get installed" confusion.
For example, if you run "go install -gcflags=-N myprog", that installs a myprog built with no compiler optimizations, but it no longer also reinstalls the packages myprog uses from the standard library without compiler optimizations.

huangapple
  • 本文由 发表于 2015年6月3日 14:39:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/30612611.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定