我实现了一个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
未在最终使用编译程序。
答案 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
文件的处理方式不同。 为什么似乎存在于 gcc
和 ld
的设计中,但我仍然无法理解。
_write
中定义的libs.a
符号在最终链接期间使用 -Wl,--undefined=_write
调用 gcc。
(通过What are “nosys”, “nano”, “rdimon” terms when using ARM GCC?)。从 man ld
开始,--undefined=symbol
强制将符号作为未定义符号输入到输出文件中。
另见 Makani 固件存储库,其中一个静态库实现了系统调用 this answer(marks them as --undefined
的生成)