英文:
`go build` rebuilds unnecessarily
问题
go build和go run在我拥有的一个小程序上非常慢(特别是cgo调用)。我希望go可以缓存二进制文件,只有在源代码更新时才重新构建。我可以使用一个简单的Makefile和一个%规则,但是语言设计者声称go的构建支持不需要Makefile。
我是否忽视了其他的选择?go社区是否更喜欢另一种构建系统,比如基于哈希的系统,用于缓存和重用构建产物?
英文:
go build and go run are very slow on a tiny program I have (cgo invocations in particular). I'd like go to cache the binary so that it only rebuilds when the source is newer. I would use a simple Makefile with a % rule, but the language designers claim that go's build support doesn't need Makefiles.
Is there another alternative I've overlooked? Does the go community prefer another build system, maybe hash-based instead, for caching and reusing build products?
答案1
得分: 7
go build
和go install
将很快(Go 1.10,2018年第一季度)变得更快:请参阅此线程和此草案文档。
go命令现在维护一个构建包和其他小型元数据的缓存(CL 68116和CL 75473)。缓存默认为操作系统定义的用户缓存目录,但可以通过设置
$GOCACHE
来移动。
运行"go env GOCACHE
"以查看当前的有效设置。现在,go命令从不从缓存中删除任何内容。如果缓存变得太大,请运行"go clean -cache
"而不是删除目录。该命令将保留缓存的log.txt
文件。几周后,我将要求人们将他们的log.txt
文件发布到Github问题中,以便我们可以评估缓存大小管理方法。
构建缓存的主要效果是,像"
go test
"和"go build
"这样的命令运行快速,并始终进行增量构建,尽可能地重用过去的构建步骤。
您不必使用"go test -i
"或"go build -i
"或"go install
"来获得快速的增量构建。我们将不再需要教新用户这些变通方法。一切都将变得快速。
请注意,go install
不会安装指定包的依赖项:请参阅"go build
构建了什么?"。
英文:
go build
and go install
will soon (Go 1.10, Q1 2018) be much faster: see this thread and this draft document.
> The go command now maintains a cache of built packages and other small metadata (CL 68116 and CL 75473). The cache defaults to the operating system-defined user cache directory but can be moved by setting $GOCACHE
.
Run "go env GOCACHE
" to see the current effective setting. Right now the go command never deletes anything from the cache. If the cache gets too big, run "go clean -cache
" instead of deleting the directory. That command will preserve the cache's log.txt
file. In a few weeks I'll ask people to post their log.txt
files to a Github issue so that we can evaluate cache size management approaches.
> The main effect of the build cache is that commands like "go test
" and "go build
" run fast and do incremental builds always, reusing past build steps as aggressively as possible.
You do not have to use "go test -i
" or "go build -i
" or "go install
" just to get fast incremental builds. We will not have to teach new users those workarounds anymore. Everything will just be fast.
Note that go install
won't installs dependencies of the named packages: see "What does go build
build?".
答案2
得分: 1
我写了一个工具,恰好可以作为副作用解决这个问题。go build
本身不会检查生成的可执行文件是否已经是最新的。go install
会进行检查,如果你将其调整为安装到你选择的位置,那么你将得到期望的结果,类似于go build
。
你可以通过以下方式观察到你描述的行为:
$ go get -d github.com/anacrolix/missinggo/cmd/nop
$ time go run "$GOPATH"/src/github.com/anacrolix/missinggo/cmd/nop/*.go
real 0m0.176s
user 0m0.142s
sys 0m0.048s
这是在一个热启动的情况下。go run
每次调用都会进行链接,就像go build
一样。请注意,github.com/anacrolix/missinggo/cmd/nop
是一个完全不做任何事情的程序。
下面是使用我的工具godo调用相同的包:
$ time godo github.com/anacrolix/missinggo/cmd/nop
real 0m0.073s
user 0m0.029s
sys 0m0.033s
对于较大的程序,差异应该更加明显。
因此,总结起来,你可以使用go install
或类似godo的替代工具作为标准工具选项。
英文:
I wrote a tool that happens to solve this as a side effect. go build
alone will not check if the executable it's producing is already up to date. go install
does, and if you tweak it to install to a location of your choice, then you'll get the desired result, similar to go build
.
You can see the behaviour you describe by doing something like this:
$ go get -d github.com/anacrolix/missinggo/cmd/nop
$ time go run "$GOPATH"/src/github.com/anacrolix/missinggo/cmd/nop/*.go
real 0m0.176s
user 0m0.142s
sys 0m0.048s
That's on a warm run. go run
will link on every invocation, just as go build
would. Note that github.com/anacrolix/missinggo/cmd/nop
is an program that does absolutely nothing.
Here's invoking the same package, using my tool, godo:
$ time godo github.com/anacrolix/missinggo/cmd/nop
real 0m0.073s
user 0m0.029s
sys 0m0.033s
For larger programs, the difference should be more pronounced.
So in summary, your standard tooling option is to use go install
, or an alternative like godo.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论