为什么 go 和 rust 这类新兴语言发布程序大都使用静态编译?

2020-12-14 00:46:43 +08:00
 CrazyBoyFeng
尤其是 go,最初的版本里完全不提供动态链接编译。
难道他们没设想过这样的情景:
某天,tls 库被爆出漏洞,go 、rust 发布了一个更新。第二天你需要升级所有依赖 tls 库的 go 、rust 应用,且需要下载的数据量十分巨大(每个应用都包含系统库 /标准库)。

其次就是静态编译对 ram 和 rom 较少的嵌入式设备太不友好。别说全用静态编译了,只要有少数几个应用是自带库编译的,那 ram 和 rom 就得爆炸了。
8035 次点击
所在节点    程序员
57 条回复
zjsxwc
2020-12-14 12:02:26 +08:00
@waruqi
偏个题,现在嵌入式的定义已经改变了。
```
嵌入式新定义是在设计的时候可以把整机资源几乎占满。比方说设计的系统可以基本上 flash70%以上占用,CPU 平时长期 90%,内存占大半。因为功能固定需求固定,不会有其他因素干扰只要当前系统能跑起来就行,不用留手。
但是常规系统你让系统资源长期持续高负荷基本是不对的。
```
嵌入式用 java 也是很多的。
52coder
2020-12-14 12:05:49 +08:00
c 我记得默认是动态编译,参数加 static 可以搞成静态编译,一般在低版本 linux 编译的可以在高版本运行,反过来就跑不起来了,上周末学习了下 go,个人认为 go 当前的处理真的很好(想对比节省内存和磁盘,方便维护才是王道?),编个 go 出来,不用担心各种 glibc 版本依赖问题。(go 新手,有问题欢迎指出哈)
zhuangzhuang1988
2020-12-14 12:21:31 +08:00
还不是因为难,
c++表示 坑都是趟过的.
aloxaf
2020-12-14 12:21:34 +08:00
LZ 你陷入了完美主义谬误:
涅槃谬误(英语:nirvana fallacy )或完美主义谬误( perfectionist fallacy )是一种非形式谬误,系宣称某个解决方案无法做到涅槃(完美),因此不可行。较白话的诠释是:“不能做到完美,就不应该做”

静态链接有缺点,但动态链接难道就是完美的?就像前面有人提到的,更新一个 libcrypt 把 ssh 炸了。虽然这个我没遇到过,但我遇到过不少乱动 glibc 把包管理器炸掉的,我系统里至今留着一个 pacman-static,就是预防我哪天手贱。又比如 A 依赖旧版的 C,B 依赖新版的 C,在静态链接下完全不是问题,但动态链接下多来几个就有够你受的了。

为啥现在都用静态链接?因为「大多数时候」静态链接更方便,仅此而已。
learningman
2020-12-14 12:28:58 +08:00
@nightwitch 感谢,一个查了半个月的问题发现是 ABI 不兼容
expy
2020-12-14 12:32:43 +08:00
希望大家对 Electron 也能这么友好。
cholerae
2020-12-14 12:35:32 +08:00
rust 不了解,go 原本设计上就没打算在嵌入式环境使用,不用考虑嵌入式环境的问题。

升级所有依赖 tls 库的应用我没觉得有啥问题,任何一个有完善构建系统的公司做到这个不是很容易吗?至于那点网络流量和内存实在不值一提。
JohnSmith
2020-12-14 12:57:38 +08:00
侧面反应“没有银弹”
FH0
2020-12-14 13:08:49 +08:00
本来静态编译和动态编译就是互补的,都有优点和缺点,看取舍。go 的主战场不是嵌入式,在嵌入式上能用就行。
kindjeff
2020-12-14 13:10:11 +08:00
@expy #46 2MB 约等于不要钱,但是 200MB 还是要钱的
tkl
2020-12-14 13:10:26 +08:00
40 楼没人提到交叉编译?
raptor
2020-12-14 13:11:50 +08:00
@aloxaf 哈哈哈。说到这个我想起来曾经在 FreeBSD 上把 pkg 搞坏了,最后就是靠 pkg-static 修回来的。
icyalala
2020-12-14 13:24:54 +08:00
新语言,尤其是这些正处在迅速发展中的语言,在最初版本不提供动态链接这个很好理解。Swift 从 5.0 之前一直不愿声明 ABI 稳定,当时作者解释,一旦 ABI 稳定,那后续语言特性就受制于 ABI 的设计,有一些新语言特性就难以实现了。所以每一版更新,Calling Convention 有变动,旧的动态库就无法兼容了。

静态链接和动态链接只是个[权衡],动态链接有你说的那些优势,静态链接同样也有很多优势。没有版本和依赖问题,容易发布容易维护,这是静态链接最大的优势,在 go 和 rust 的使用场景和生态下,静态链接是更优的选择。
YouLMAO
2020-12-14 14:12:17 +08:00
先问是不是,再问为什么,

cgo 动态 dll
```
import (
"fmt"
"syscall"
"unsafe"
)

kernel32, _ = syscall.LoadLibrary("kernel32.dll")
getModuleHandle, _ = syscall.GetProcAddress(kernel32, "GetModuleHandleW")
```
ysc3839
2020-12-14 18:47:58 +08:00
@CrazyBoyFeng #16 我认为能系统级共享的库应该保留。
但是那些只有一个可执行文件,不需要复用代码的程序则不应该带一堆 dll,应该静态链接。
大多数 Golang 程序显然属于后者,不过 Golang 内置库是应该考虑像 VC++ 那样发布一个安装包,安装到系统中。
salmon5
2020-12-14 20:54:21 +08:00
维护成本是长期大概率时间,其他安全等成本是小概率事件(而且这个小概率事件可以通过业务解耦解决);所以大部分静态编译是好的,先进的
cuishuang
242 天前
@virusdefender 不用 CGO 啥的,肯定是静态的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/735084

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX