在32位linux机器上用gcc -m64编译64位程序会失败,根本原因是缺少64位abi支持文件(如gnu/stubs-64.h),必须安装gcc-multilib及其依赖(如libc6-dev-amd64、lib64gcc1等)才能提供完整头文件和库。

直接说结论:在32位Linux机器上用 gcc -m64 编译64位程序,大概率会失败——不是参数错,而是缺关键支持文件。必须先装 gcc-multilib(或对应版本的 multilib 包),否则连 gnu/stubs-64.h 都找不到。
为什么 -m64 在32位系统上会报错
错误典型如:gnu/stubs-64.h: 没有那个文件或目录。这不是 GCC 不认识 -m64,而是它试图包含 64 位 ABI 的头文件和链接脚本,而这些根本没装进 32 位系统的默认环境里。GCC 本身可能支持该选项(gcc -v 里能看到 target 是 x86_64-linux-gnu),但缺少 libc6-dev-amd64、lib64gcc1 等运行时与开发组件。
-
-m64只是告诉编译器“生成 x86_64 指令和 ABI”,不负责提供配套头文件和库 - 32 位系统默认只装 i386/i686 相关的
libc6-dev、libgcc1,没有 amd64 版本 - 即使你手动指定
--sysroot=/path/to/amd64/sysroot,也绕不开基础头文件缺失问题
Debian/Ubuntu 上必须装的包:gcc-multilib
这个包名是入口,但它实际拉取的是整套跨架构支持链。执行后会安装:libc6-amd64、libc6-dev-amd64、lib64gcc1、lib64gomp1 等核心组件。
- 命令:
sudo apt-get install gcc-multilib - 验证是否生效:
gcc -m64 -E -x c /dev/null -o /dev/null(成功即无报错) - 注意:不同 GCC 版本对应不同 multilib 包名,比如
gcc-12-multilib;若系统默认 GCC 较新,可能需明确指定版本
-m64 和 -m32 的共存与冲突
同一个 GCC 安装下,-m64 和 -m32 可以共存,但它们依赖的底层库路径、头文件搜索顺序完全不同。混用时容易出符号未定义或 ABI 不匹配。
- 编译目标必须全程一致:源码、所有依赖静态库(.a)、链接时的
-lxxx库都得是同一架构 -
ldd查看可执行文件依赖,确认全是lib64/下的库(如libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6) - Makefile 中建议显式控制:
CFLAGS += -m64,并在链接阶段加LDFLAGS += -m64,避免部分目标漏掉 - 如果项目含汇编(.s 文件),
-m64不影响其内容,但必须确保汇编代码本身是 x86_64 兼容的(比如用movq而非movl)
64位共享库编译要额外加 -fPIC
光有 -m64 不够。动态库(.so)必须位置无关,否则加载失败。这是硬性要求,跟位数无关,但 64 位下更易暴露问题。
- 正确命令:
gcc -m64 -fPIC -shared -o libfoo.so foo.c - 错误写法:
gcc -m64 -shared -o libfoo.so foo.c→ 报错relocation R_X86_64_32 against `.rodata' can not be used when making a shared object -
-fPIC生成 GOT/PLT 调用,-fpic在某些平台受限(x86_64 推荐统一用-fPIC) - 注意:静态库(.a)不需要
-fPIC,但若该静态库将来被链接进共享库,则其目标文件(.o)必须由-fPIC编译
真正卡住人的从来不是 -m64 这个开关,而是它背后一整套 ABI 支持链是否完整。装完 gcc-multilib 后,别忘了检查 /usr/include/x86_64-linux-gnu/ 是否存在,以及 /usr/lib/x86_64-linux-gnu/ 下有没有对应 .so 和 .a 文件——这才是 -m64 能跑起来的底线。











