我已经构建了一个静态库(* .a用于gcc,* .lib用于keil)。其源文件之一,编译成库,包含RADIO_IRQHandler的定义。此源文件的摘录名为" ral_irq_handlers.c",如下所示:
...
void ral_symbol_import(void) //dummy function
{
return;
}
...
void RADIO_IRQHandler(void)
{
...
}
...
此IRQ符号定义应覆盖在启动文件中声明的弱定义。启动文件不会编译到任何静态库中,只是项目中的常规文件。
下面是arm_startup_xxx.s文件(keil工具链)的摘录:
Default_Handler PROC
...
EXPORT RADIO_IRQHandler [WEAK]
...
...
RADIO_IRQHandler
...
B .
ENDP
ALIGN
下面列出了类似gcc_startup_xxx.s文件(gcc工具链)的摘录:
.globl Default_Handler
.type Default_Handler, %function
Default_Handler:
b .
.size Default_Handler, . - Default_Handler
.macro IRQ handler
.weak \handler
.set \handler, Default_Handler
.endm
...
IRQ RADIO_IRQHandler
...
.end
然后我发现了一种奇怪的行为。当我使用" ral_irq_handlers.c"中的任何API函数时在其中一个项目源文件中的源文件(编译到库中),链接正确完成。例如:
...
int main(void)
{
ral_symbol_import();
...
}
...
但是,如果我不使用" ral_irq_handlers.c"的任何API函数。源文件,链接器找不到我的库中定义的RADIO_IRQHandler符号。如果没有这个丑陋的黑客(调用虚函数强制正确链接),我能以某种方式做到这一点吗?
我想只修改库代码而不触及启动文件。
答案 0 :(得分:1)
据我所知你不能轻易做到这一点,因为链接器只会搜索你的库,如果它找不到处理程序的符号。正如它可以找到的那样(启动时的弱定义)它看起来没有任何进展。
但是你可以通过链接你的库来解决它:
... -Wl,--whole-archive -l:path/to/our/library.a -Wl,--no-whole-archive ...
此外,您实际上不必调用虚函数来导致模块的链接。您所需要的就是告诉链接器您需要它,例如:
void ral_symbol_import(void);
void (* const variable)() = &ral_symbol_import;