如何在64位Ubuntu上编译32位应用程序?

65

我正在尝试使用gcc 4.8在Ubuntu Server 12.04 LTS 64位上编译一个32位的C应用程序。我收到关于不兼容库以及跳过-lgcc的链接器错误信息。我需要做什么才能编译和链接32位应用程序?


相关链接:https://stackoverflow.com/questions/58654288/how-to-make-compiler-generate-a-elf32-x86-64-format-object-file - smwikipedia
3个回答

107
这已知可在Ubuntu 16.04至22.04上运行:
sudo apt install gcc-multilib g++-multilib

然后是一个最小的hello world:

main.c

#include <stdio.h>

int main(void) {
    puts("hello world");
    return 0;
}

使用以下编译器可以无警告地编译:

gcc -m32 -ggdb3 -O0 -pedantic-errors -std=c89 \
  -Wall -Wextra -pedantic -o main.out main.c

./main.out

输出:
hello world

并且:

file main.out

说:

main.out: ELF 32-bit LSB  executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=87c87a83878ce7e7d23b6236e4286bf1daf59033, not stripped

并且:

qemu-i386 main.out

也会给出:

hello world

但在一个 x86_64 可执行文件上失败了:

./main.out: Invalid ELF image for this architecture

此外,我已经在32位虚拟机中运行了编译文件,并且编译和运行了一个IA-32 C驱动程序+复杂的IA-32代码,所以我认为它可以工作。:-)
另请参阅:无法找到crtn.o,在64位系统上链接32位代码 很遗憾,这个软件包与交叉编译器(如gcc-arm-linux-gnueabihf)存在冲突https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1300211 问题的版本信息: 我们可以直接在64位Ubuntu上运行32位程序,因为Ubuntu内核已配置为:
CONFIG_IA32_EMULATION=y

根据:
grep CONFIG_IA32_EMULATION "/boot/config-$(uname -r)"

内核源代码树上提供帮助的人阅读:

Include code to run legacy 32-bit programs under a
64-bit kernel. You should likely turn this on, unless you're
100% sure that you don't have any 32-bit programs left.

这是因为x86 64位CPU有一个可以运行32位程序的模式,Linux内核使用它来实现。
TODO:相比于gcc,gcc-multilib编译时有哪些不同的选项?

7
为了过度验证结果而加一。 - Spike0xff
1
顺便提一下,对于C++项目,应安装g++-multilib软件包。 - E. Vakili
在Ubuntu 18.04的podman/docker容器中无法运行。事实上,我不明白为什么它会工作,因为提到的gcc-multilib软件包几乎没有任何文件,而且肯定没有库文件。 - Hi-Angel
因此,在使用Ubuntu的docker/podman容器时,对我有帮助的是安装lib32gcc-10-dev(值得注意的是,在我的情况下,版本10来自PPA;如果没有PPA,则会是较低的版本)。 - Hi-Angel

23

为了让Ubuntu Server 12.04 LTS 64位编译gcc 4.8 32位程序,你需要做两件事。

  1. 确保所有32位gcc 4.8开发工具都被完全安装:

    sudo apt-get install lib32gcc-4.8-dev

  2. 使用-m32标志编译程序

    gcc pgm.c -m32 -o pgm


1
请注意,-m32 标志仅适用于 32 位 x86。您需要不同的标志来编译 32 位 ARM、RISC-V 等架构的代码。 - Aaron Franke

12

通过将体系结构信息添加到要安装的软件包名称中来支持Multiarch安装(而不是使用可能可用或可能不可用的替代名称安装这些软件包)。

有关(现代)Multiarch安装的更多信息,请参见此答案

在您的情况下,最好安装32位gcc和libc:

sudo apt-get install libc6-dev:i386 gcc:i386

它将安装32位libc开发和gcc软件包,以及所有依赖软件包(所有32位版本),而不会破坏您的64位安装。


1
请注意,如果已经存在,64位的gcc将被卸载(尽管库将保留)。 - Paul Stelian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接