最常见原因是将非源码文件(如.glade、.json、.txt、.o、.so)误作源文件传给gcc,导致ld无法识别格式而报错;应只传.c/.cpp/.h文件或用-l/-l引入库,.o文件需单独生成后链接。

gcc命令里混进了非源码文件
最常见原因是把不该传给gcc的文件(比如.glade、.json、.txt、甚至.o或.so)直接写在了编译命令末尾。链接器ld拿到这些文件后无法识别格式,就报file format not recognized; treating as linker script。
- 检查命令行:确认所有参数都是
.c、.cpp、.h(仅用于预处理)、或明确用-l/-L引入的库选项 - 典型错误示例:
gcc -o main main.c config.json -lpthread→ 把config.json删掉 - Makefile里也容易出错:比如写成
$(CC) -o app app.c utils.o,但utils.o其实是目标文件,不该放这里;应只列源文件,.o由规则生成后再链接
目标文件(.o)被误当源文件传给gcc
当gcc收到一个已编译好的.o文件,却没加-c或-shared等标志时,它会尝试“编译”这个二进制目标文件——显然失败,最终交给ld时就触发该错误。
- 现象:命令中出现类似
gcc -o prog foo.c bar.o baz.c,其中bar.o是提前生成的 - 正确做法:要么全用源文件(让
gcc统一编译+链接),要么分两步——先gcc -c生成所有.o,再用gcc(不带-c)链接它们 - 特别注意Makefile:检查依赖关系是否写错,比如把
target.o: target.c误写成target: target.o又漏掉规则,导致target.o被当作源文件传递
链接器收到非ELF格式的目标文件
启用LTO(Link-Time Optimization)后,clang++或新版gcc -flto生成的是LLVM bitcode或GIMPLE中间表示,不是标准ELF .o。GNU ld不认识这种格式,必然报错。
- 验证方式:运行
file CMakeFiles/xxx.dir/src/file.o或readelf -h file.o,若显示LLVM IR bitcode或not an ELF file,就是这个问题 - 解决方案:改用
lld(LLVM linker)或gold链接器,例如加-fuse-ld=lld到gcc命令;或关闭LTO(去掉-flto) - Clang用户尤其要注意:默认启用LTO时,必须配套使用
lld,不能依赖系统默认ld
文件本身损坏或编码异常
极少数情况下,源文件看似是.c,实则内容损坏、BOM头残留、或用了非UTF-8/ASCII编码(如UTF-16),导致预处理器输出乱码,汇编器产出无效目标文件,链接器无法解析。
- 用
file source.c看编码;用hexdump -C source.c | head查是否有BOM(EF BB BF开头) - 用
dos2unix source.c清除Windows换行符;或重定向保存:cat source.c | iconv -f UTF-16 -t UTF-8 > fixed.c - 临时验证:新建空白
test.c写int main(){return 0;},看能否编译通过——若能,则原文件确实有问题
gcc的每一个路径,再检查.o文件的真实格式,最后才排查源码文件本身。多数时候,删掉多传的一个非源文件,问题当场消失。











