有没有x86到x86的gcc交叉编译器?

比如, 想在debian系统中给centos 7编译c++程序, 不想用ssh或docker.

理论上需要一个能交叉编译的gcc, 类似于嵌入式开发的时候给嵌入式系统编译程序, 不知道有没有这样的开源项目.


同架构直接编译就行. 可以静态编译避免依赖动态库.

这个改动太大了, 动态库较多, 有几个没法转变为静态.

那你可以在debian里面编译好然后把依赖都拷贝过去,反正一个架构的机器的ELF文件是可以互相拷贝使用的. 或者用Nix/Guix 这种致力于bit to bit reproducible的包管理器

这样不太好, 有点乱, libc++这些基本库不知道会不会有问题. 另外, 内存占用也会增加不少. 这种方式应该是无法通过的, 影响团队协作, 把简单的事情搞复杂了. 这样还不如用ssh.

比较好的方法是用vscode的ssh远程开发功能, 不过这样就要告别emacs了.

你不用同个发行版同个版本的package manager提供的依赖,又不想连带依赖一起拷贝, 又想ABI不炸裂, 可以说是很有理想了 :slightly_smiling_face:

建议省事直接SSH

太复杂的方法影响团队其他成员, 基本没法实行. 其实一个交叉编译器完美解决问题, 不过没找到.

看来不得不用ssh了.

交叉编译器怎么解决依赖库的ABI稳定性问题?

跟arm交叉编译器一样, 这个还是挺可靠的, target上的所有东西都能编译, 包括kernel.

这个难点在 glibc 和其他库上,不在编译器,所以你问编译器就已经跑偏了。(更合理的问法是 SDK。)

最好的解决方案是 Docker(因为可以说 Docker 就是为这种场景设计的),简单易用轻量,pull 下来一个 CentOS 的 image 才 75 MB,然后你 attach 上去自己装个 gcc 配个环境,就可以在本地用纯 CentOS 环境了。如果你愿意,还可以把这套编译环境 push 到某个地方(比如 Docker Hub),让你团队成员直接 pull 下来用。

既然你不愿意用就算了。搞不懂你为啥愿意用 SSH 也不想试试 Docker。

你没搞懂我说的问题

在Debian系上编译意味着

  • 你要用debian的依赖(不会吧,不会吧,不会有人想在Debian上用RPM包吧)
  • 你Debian上的依赖和实际运行的机器上的依赖版本不一定一样, ABI不一定兼容

问题本质是编译环境和运行环境用的动态库不同, 不能保证软件行为可复现的问题.

和交叉编译有什么关系? 你要是有自信两边的依赖都能对上, 你直接编译就完事. 而复制全套依赖是比较省事的方案.

一般说编译器都包含libc/libc++, ld.so, pthread等, 我们这边平时沟通都包含了这些.

这个东西更准确的叫cross toolchain吧?

没有冲突啊, docker里可以启动ssh, 当作ssh server用. 直接用docker的还没搞明白, 这种情况下源代码目录需要挂载到docker容器里吗? 会频繁重启容器吗?

vscode的remote development里除了ssh还有docker方式, 这个还没试过, 原理还不太明白. ssh模式下, 它会安装vscode server到目标系统里, docker方式是不是也是, 把vscode server安装在容器里?

交叉编译工具(cross toolchain)编译的时候一般都不是用的其所在系统运行中的动态库, 它有单独的一套动态库, 这套动态库跟目标系统是一致的, 包括binutils工具都是独立的, 有点像一个chroot环境或者docker, 所以不受所在系统影响.

那你直接获取目标机器上的依赖和头文件过来编译就可, 没有 “x86到x86的交叉编译” 这种概念, 最多就是利用了不同版本的依赖库编译. 用docker或者什么其他的只是简化了获取依赖的步骤, 你要乐意, 从运行机器上复制库过来编译都行.

你是说直接使用debian上的编译和链接器, 但是不让它使用它自带的c/c++标准库的头文件和库文件, 而是用从centos复制过来的头文件和库文件? 这个太hack了, 牵涉的东西太多了, 涉及很多底层的东西, 不知道能否实现.

终于找到了这个东西crosstool-ng(http://crosstool-ng.github.io), 其实发帖的时候就感觉有这么个东西, 只不过印象太糢糊了, 实在是想不起来了, 刚找到它之后才想起来, 很早以前无意中看过这东西, 但是没用过.

看了一下这个东西, 感觉还是挺靠谱的, 而且相当强大, 理论上可以用它在macos上制作出一个交叉编译工具, 然后直接在macos上给centos 7编译程序.

可以attach上去,体验差不多类似于 WSL,挂载肯定要挂载。容器 start 之后可以一直挂着,也可以关掉,而不是删了创建删了创建……

啊,这

如果可以用clang的话,那直接用clang就可以了,不用管glibc和libstdc++的事情,clang会自己在sysroot里找到. 用法就是clang --sysroot=/mnt/centos

但是同样的用法在gcc里就不行, gcc自己带的一些库(libstdc++, libgcc_s)会导致编译失败

1 个赞

这真是一个奇怪的问题。这个问题根本就不涉及“交叉编译”的问题。

centos/debian只是不同的发行版。

这个问题的本质是如何解决依赖的问题。不同版本的kernel,不同版本的libc, 一起其他库的不同版本如何兼容的问题。

不同的发行版打包的内核版本,各个库的版本都可能不一样,甚至同样是centos,不同版本也会存在不同版本的库不兼容的问题。

所以明确自己的应用对库的依赖,并编写有关检查版本的脚本就可以了。

跟在centos还是debian没关系。

2 个赞

目标很具体, 是centos 7, 上层库的依赖可以手工解决, 主要是底层c/c++标准库这些需要交叉编译工具处理. 具体到centos 7, 一切版本号都是确定的.

其实我的最终目标是在macos上编译centos 7程序, 交叉编译工具理论上是可以做到的, 嵌入式系统基本全都是交叉编译的. 找到了crosstool-ng这个工具, 有空试下.

clang确实挺厉害. 不单编译器, binutils工具一般也需要配套.