当retarget.o在静态库中存档时,为什么retarget.c中的“_write”等函数没有链接?

时间:2016-01-25 06:43:03

标签: c linker arm uart newlib

我实现了一个retarget.c来将printf输出重新定位到串口进行调试,如果我的链接命令喜欢这个,它可以链接并且工作得很好:

arm-none-eabi-gcc --specs=nano.specs --specs=nosys.specs -g -mcpu=cortex-m4 -mthumb -fmessage-length=0 -std=c99 -fno-builtin -Wl,--gc-sections -Wl,-Map=main.map -T"$(LINKERFILE)" -o main.elf main.o retarget.o $(BUILDDIR)/libs.a -Wl,--start-group -lgcc -lc -lnosys -Wl,--end-group

但是当我将retarget.o存档到存档文件$(BUILDDIR)/libs.a中时,链接命令就像这样:

arm-none-eabi-gcc --specs=nano.specs --specs=nosys.specs -g -mcpu=cortex-m4 -mthumb -fmessage-length=0 -std=c99 -fno-builtin -Wl,--gc-sections -Wl,-Map=main.map -T"$(LINKERFILE)" -o main.elf main.o $(BUILDDIR)/libs.a -Wl,--start-group -lgcc -lc -lnosys -Wl,--end-group

它可以成功链接,但函数printf没有向串口输出任何内容,似乎我自己的版本函数,例如retarget.c中的_write未在最终使用编译程序。

1 个答案:

答案 0 :(得分:0)

因为 _write 已经在 libnosys.a 中定义,通过 --specs=nosys.specs 包含

注意:以下调查是使用从 patool 下载的 ARM 工具链 9-2019-q4-major 完成的。

这需要基本的规范文件知识here

编译器的内置规范可以通过 arm-none-eabi-gcc -dumpspecs ((About spec files)) 看到

在命令行开头传递 --specs=nosys.specs 会在对 -lnosys 的调用中插入一个 ld。 (gcc -dumpspecs)

arm-none-eabi-objdump -t arm-none-eabi/lib/libnosys.a | grep _write 定位可能覆盖您在 _write(...)

中定义的 $(BUILDDIR)/libs.a

我也很好奇为什么在调用 .a.o 文件与 gcc 文件的处理方式不同。 为什么似乎存在于 gccld 的设计中,但我仍然无法理解。

使用静态库_write中定义的libs.a符号

在最终链接期间使用 -Wl,--undefined=_write 调用 gcc。
(通过What are “nosys”, “nano”, “rdimon” terms when using ARM GCC?)。从 man ld 开始,--undefined=symbol 强制将符号作为未定义符号输入到输出文件中。

另见 Makani 固件存储库,其中一个静态库实现了系统调用 this answermarks them as --undefined 的生成)