技术解析

不懂就问:其他电脑编译好的二进制文件可以直接到其他机器使用吗?
0
1975-02-23 20:03:52
idczone
如题,经常遇到很多文件因为网络问题无法安装。
那么,我可以在其他电脑将二进制文件编译好,然后再通过网盘工具或者其他下载工具,将其下载到本地电脑直接使用吗?

比如我有一台香港的 ubuntu 服务器,编译安装好了一个软件,然后将其打包,我本地有一台电脑,直接将软件下载到本地,然后解压缩直接使用。可以这样吗
可以的,这个分为两种
1. 两台机器的操作系统、CPU 指令集一致,这样能保证可执行文件的结构以及相应的指令集符合目标机器的要求
2. 如果不符合上一个条件,可以使用交叉编译

你要处理一些环境变量之类的,不嫌麻烦完全可以

打包成 deb 包,包管理器会处理依赖问题

那得看在编译时有没有依赖特定的环境变量.

可以的:
如果 CPU 架构不同,可以交叉编译。
同 cpu 架构 + 不同操作系统:可以交叉编译。
同 cpu 架构 + 同操作系统 + 不同发行版:需要注意运行库版本的问题,方法也挺多的,比如静态编译,或者暴力点,用 ldd 等工具把依赖的 so 文件一起拷走。
同 cpu 加构 + 同操作系统发行版:最简单了,记好安装了哪些包,这边对应着装上就好,建议打包成 deb/rpm 等该发行版的包,更好安装和管理。

直接打 docker 镜像


简单来说,我在远程服务器上的二进制文件,将其打包成 deb 包。然后下载到本地,之后再将 deb 包解压安装即可?

静态编译 or docker or snap/flatpak/appimage

打包成 deb 用什么? checkinstall 吗?

1. 不同 CPU 架构下,需要交叉编译,用可以生成 target 二进制的 toolchain
2. 相同架构下,注意链接的动态库不能丢

前提是编译时使用的指令集在服务器和本地是通用的,比如两边都是 x64 的,也没用什么 avx512 之类的可能有一边不支持的指令。还有依赖的动态库两边也要兼容。

不同架构下的 docker 也不能直接跑。。

那就把 dockerfile 复制过来

同指令集(如 x86_64 ),同发行版同版本(如 Ubuntu 20.04 ),可以直接搬过来用。
当然前提是本机装齐依赖。
否则至少需要静态编译,或者把依赖的库版本一起复制过来。如果编译环境太新,运行环境太久,还要涉及到内核兼容性还有 libc 兼容性等等,出问题概率很大。
这就和 Windows 上的软件一样,你编译完的 exe 也不是拷出来就能用的,一样需要备齐 dll 依赖。然后新的软件老的系统可能跑不起来。

那就直接打 OVA 包

这个标题 shock 到我了。。。
我们平时下载的 binary file,不基本上都是别人在别的电脑上编译好的么。。。

我以为第一条回复就会是你这样的,结果到最后才有一条,看来是我不太了解背景。

看到标题,震惊之后我想可能是楼主想问交叉编译之类的吧,结果看了楼主的表述,确实是第一反应想到的。

希望楼主下次叫不懂就查或者搜索,这种烂问题已经问烂了

原来是这样,简单来说就是 a 机器上的 bin 文件放到 b 机器上,只要 b 的环境依赖和 a 一样,那就可以直接使用。
很尴尬的是,很多问题搜索后找不到,但是来论坛上问反而有人回答。可能是中文环境问题。一般报错或者简单的英文问题直接搜英文就有答案而且还很专业。搜索中文的,99%都是营销答案,抄的有时候还是很古老的东西。
看中文的问题经常让我怀疑我们中国人编程是真的不行。但是一到论坛上提问,却发现论坛上的回答又快又好,而且还很细致。以至于做一个答案汇总甚至都可以出一篇技术小短文了……

这个问题涉及到的因素太多了,建议你先保证两边的操作系统一致,比如 ubuntu xx.xx x86_64,然后试着先编译出来看看。不行的话具体问题具体分析

当然可以,一个简单的例子就是 Android 和 iOS 本身并没有办法在自己的平台上编译出二进制,而是依赖其它桌面平台来编译二进制来使用。
只是要处理好平台依赖,所以类似于 Windows Linux 和 Mac 之间,或者 ARM X86 可能会有些平台特有的 ABI 接口问题(也是可解决的),但同一个平台理论上还是比较好处理依赖的

所有的依赖 ABI 兼容就可以。至于怎么知道 ABI 是否兼容,linux 内核版本升级

接上条。没写完不小心按了回复。
linux 和 gcc,glibc 这十几年的升级都是 ABI 兼容的,其他的我不清楚,得看依赖的库了。其他的库如果能全部静态链接大概率也行。

感觉用 docker 就行了
只要你的电脑可以运行 docker,不管是 Windows 还是 macOS 、Linux 都可以。当然,都得是 AMD64 架构。你要是用的 Aarch64,应该会弄交叉编译
下载的二进制文件有时候会有些稀奇古怪的问题,不会搞的话就用 docker,省事

你要是在自己的电脑上装个一样的系统。依赖之类的弄好,拷过来基本上不会有什么问题

我开开心心的交叉编译,结果运行的时候来一个 kernel too old,其他 abi 都对,给我跳这个,心累。

我的第一反应也是这个,楼主不会认为装的二进制包都是本地编译的吧

可以,但不是随便就可以

话说上次 go 编译遇到 glibc 版本无法运行的问题。

这就是 docker 出场的时候了

一个程序要运行起来需要很多操作系统相关的东西,

相邻发行版直接拷过去试一试保不齐也能用
我自己的 VPS 和家里服务器之间这样弄过几次,跨越的版本是 16 和 18
缺了依赖的库有时可以手动装上,PPA 或者直接网站上下下来扔到路径里

中文资料很少的
因为英文社区异常活跃
很多非英语母语的人遇到问题如果母语资料不够用也会硬着头皮去英语社区用英语询问交流
久而久之全世界的人都在向英语社区共享问题、答案、经验、讨论、猜想、验证……
中文用户当然也逃不掉
所以直接英文搜索是最可能找到具体解决方案的,再不济直接用英文开贴询问

只要没有特别的依赖,大部分是没问题的,我曾经在 centos6 上编好的 binary,拷到 Ubuntu18.04 上能直接运行

程序需要关心的大体是这几层:硬件指令集、操作系统 API 、依赖(如动态链接库)、运行时(Runtime)、环境配置(如环境变量)。
如果你两台机器这几层都互相兼容,那么你从一台机器编译的程序可以直接在另一台机器运行。
网络问题可以尝试用代理解决,或者使用镜像源。
服务型软件可以考虑用容器方案,可以在各个地方使用极度相同的环境。

打包成 appimage 就可以了。

用 Golang,可以交叉编译

数据地带为您的网站提供全球顶级IDC资源
在线咨询
专属客服