静态库引用前置静态库已存在的全局符号报未定义引用怎么办
问题根本原因
你遇到的符号解析失败是静态库链接顺序错误导致的:
GNU链接器(ld)处理静态库时遵循「从左到右扫描、仅按需提取目标文件」的规则:
- 扫描到某个静态库时,只会把能解决当前已经存在的未定义符号的目标文件从库中提取出来
- 扫描完成后该静态库就不会再被回溯使用,后续新出现的未定义符号不会再到前面的静态库中查找
你当前的LDFLAGS顺序是-lc -lgcc -lcrt1:
- 先扫描
libc.a的时候,还没有遇到任何未定义的__libc_start_main符号,所以不会把包含该函数的目标文件从libc.a中提取出来 - 之后扫描
libcrt1.a的时候,才从crt1.o中发现了未定义的__libc_start_main,但此时后面已经没有libc.a可以提供该符号的实现,因此链接报错。
修复方案
调整LDFLAGS中静态库的顺序,遵循「被依赖的库放后面,依赖方放前面」的原则:
libcrt1.a(启动代码)依赖libc.a的接口,所以要放到-lc的前面libc.a可能依赖libgcc.a的内置函数实现,所以-lgcc放到-lc的后面
修改后的Makefile对应片段如下:
# 仅修改LDFLAGS部分即可,其余配置保持不变 LDFLAGS=-L/home/john/deps/install/opt/riscv/lib/gcc/riscv64-unknown-elf/8.1.0 -L/home/john/musl-1.1.23/install/lib -lcrt1 -lc -lgcc
可选补充说明
如果调整顺序后仍有少量未定义符号,可以给链接器加组包裹参数,让链接器反复扫描组内的库直到所有符号解析完成:
LDFLAGS=-L/home/john/deps/install/opt/riscv/lib/gcc/riscv64-unknown-elf/8.1.0 -L/home/john/musl-1.1.23/install/lib -lcrt1 -Wl,--start-group -lc -lgcc -Wl,--end-group
如果后续出现入口点相关的报错,还需要确认你打包的libcrt1.a是否完整包含了musl要求的crt1.o、crti.o、crtn.o等启动目标文件。
内容的提问来源于stack exchange,提问作者ballsmahoney
相关产品推荐
相关产品推荐

