使用TinyGo编译Go二进制文件是否可以使其更小?

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

Is it possible to make a Go binary smaller by compiling it with TinyGo?

问题

根据TinyGo官网的介绍,它专为微控制器(MCU)设计。我想知道是否可以使用TinyGo将Go代码编译成适用于ARM/Linux系统的小型二进制文件?

目前,使用UPX --best --lzma编译我的Go代码生成的ARM二进制文件大小约为1MB,我希望能够进一步减小文件大小,因为系统的存储容量有限。

英文:

The TinyGo Homepage says that it is designed for micro controllers (or MCU). I wonder if it is possible to use TinyGo to compile go into small binary for ARM/Linux system?

Currently with UPX --best --lzma, my go code compiles to arm binary about 1MB, I hope to make it even smaller, because the system has limited storage.

答案1

得分: 4

简而言之,是的,但你可能需要将你的程序移植。

我想知道是否可以使用TinyGo将Go编译成适用于ARM/Linux系统的小型二进制文件?

是的(参考:https://tinygo.org/docs/guides/linux/)

TinyGo还可以让你编译适用于Linux系统的程序,包括32位和64位,在x86和ARM架构上都可以。

对于交叉编译,你可以像往常一样使用GOOS和GOARCH。

例如:

GOARCH=arm GOOS=linux tinygo build -o example ./...

至于与使用官方的go编译器/运行时相比,可执行文件的大小会有多大差异,这很可能取决于你的程序的具体情况。不过,TinyGo的目标之一就是提供更小的二进制文件。

我们可以尝试构建一些可执行文件并进行实际大小比较。顺便说一句,我意识到TinyGo的概述页面中提供了这个比较。我们可以在这里重现它,并加上一些额外的细节:

首先,TinyGo目前不支持Go 1.17(GitHub问题)。你必须在你的系统上安装Go 1.16或更低版本才能进行构建,或者使用TinyGo的dev分支。

然后,正如我在评论中提到的,要记住TinyGo不支持编译所有标准库包,所以如果你的代码使用了其中之一,你就需要进行移植。这是支持和不支持的包的列表:https://tinygo.org/docs/reference/lang-support/stdlib/

为了进行比较,我下载了TinyGo目前支持的Go 1.16.5版本。

# 参考:https://golang.org/doc/manage-install
$ go install golang.org/dl/go1.16.5@latest
$ go1.16.5 download

程序:

package main

import (
	"fmt"
)

func main() {
	fmt.Println("Hello World!")
}

我在Mac上,所以我必须使用适当的环境变量进行构建。我在构建时包含了-ldflags="-s -w",如评论中建议的。

$ go env | grep -E "(GOOS|GOARCH)"
GOARCH="amd64"
GOOS="darwin" 

$ go1.16.5 build -o example_go ./...
$ go1.16.5 build -ldflags="-s -w" -o example_go_ldflags ./...
$ GOROOT="/Users/blackgreen/sdk/go1.16.5" GOARCH=amd64 GOOS=darwin tinygo build -o example_tinygo ./...

$ du -hs example_*
1.9M	example_go
1.5M	example_go_ldflags
64K	    example_tinygo

对于一个简单的Hello World程序,可以看到明显的优势。毫不奇怪,它比ldflags的结果要好得多。

英文:

tl;dr: basically yes, but you might have to port your program.

> I wonder if it is possible to use TinyGo to compile go into small binary for ARM/Linux system?

Yes (reference: https://tinygo.org/docs/guides/linux/)

> TinyGo also lets you compile programs for Linux systems, both 32-bit and 64-bit, on both x86 and ARM architectures.
>
> For cross compiling, you can use GOOS and GOARCH as usual.

For example:

GOARCH=arm GOOS=linux tinygo build -o example ./...

As for how smaller the executable will be compared with one with the official go compiler/runtime, it will likely depend on the specifics of your program. It is true though that TinyGo raison d'etre is to provide smaller binaries.

<hr>

So, we can try building some executables and empirically compare sizes. BTW, I realized that this comparison is available in TinyGo overview page. We can reproduce it here anyway with a few additional details:

First, Go 1.17 is not supported yet (GitHub issue). You have to have Go 1.16 or lower installed in your system to be able to build, or use TinyGo dev branch.

Then, as I mentioned in the comments, keep in mind that TinyGo doesn't support compiling all standard library packages, so if your code makes use of one of them you'll have to port it. This is the list of supported and unsupported packages: https://tinygo.org/docs/reference/lang-support/stdlib/

To run the comparison, I download Go 1.16.5, which TinyGo supports as of today.

# reference: https://golang.org/doc/manage-install
$ go install golang.org/dl/go1.16.5@latest
$ go1.16.5 download

The program:

package main

import (
	&quot;fmt&quot;
)

func main() {
	fmt.Println(&quot;Hello World!&quot;)
}

I'm on a mac, so I have to build with the appropriate env vars. I include building with -ldflags=&quot;-s -w&quot; as suggested in the comments.

$ go env | grep -E &quot;(GOOS|GOARCH)&quot;
GOARCH=&quot;amd64&quot;
GOOS=&quot;darwin&quot; 

$ go1.16.5 build -o example_go ./...
$ go1.16.5 build -ldflags=&quot;-s -w&quot; -o example_go_ldflags ./...
$ GOROOT=&quot;/Users/blackgreen/sdk/go1.16.5&quot; GOARCH=amd64 GOOS=darwin tinygo build -o example_tinygo ./...

$ du -hs example_*
1.9M	example_go
1.5M	example_go_ldflags
64K	    example_tinygo

For a simple hello world program, there is a conspicuous gain. Unsurprisingly, it's significantly better than ldflags too.

huangapple
  • 本文由 发表于 2021年9月7日 16:49:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/69085092.html
匿名

发表评论

匿名网友

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

确定