我可以在 .ld 文件中使用预处理器指令吗

Can I use Preprocessor Directives in .ld file

我可以在 .ld 文件中使用预处理器指令吗? 我需要使用两组 .ld 文件中的一组,并想让构建引擎使用宏来处理它,我可以这样做吗?

是的,你可以。您需要为您的链接描述文件手动 运行 预处理器,如下所示:

in="your_linker_script.ld"
out="generated_script.ld"
cflags=-Iinclude/

gcc -E -x c $cflags $in | grep -v '^#' >$out

标志:

  • -E 将 GCC 指定为仅 运行 预处理器
  • -x c 告诉 GCC 将您的链接描述文件视为 C 源文件(运行 GCC 需要使用您的 LD 脚本)

或者你可以简单地使用cpp工具,它实际上是C预处理器。

在此之后,您将能够使用生成的链接描述文件来构建您的程序(例如,在 Makefile 中)。

例子

以下是我在项目中解决这个问题的方法:

  1. Here 是我的链接描述文件使用预处理器(#include 指令和 CONFIG_TEXT_BASE 常量)。摘录:

     #include <config.h>
    
     . = CONFIG_TEXT_BASE;
    
  2. Here 是生成预处理链接描述文件的脚本。摘录:

     gcc -E -x c -Iinclude $cflags $in | grep -v '^#'    >>$out
    
  3. Here 是我的 Makefile,它在 $(LDS_GEN) 目标(第 53 行)生成预处理的链接器脚本,并且生成的脚本用于构建结果二进制(第 42 行)。摘录:

     $(LDS_GEN): $(LDS)
             build/gen-lds.sh $(LDS) $(LDS_GEN) $(CFLAGS)
    
     $(APP).bin: $(OBJS) $(LDS_GEN)
             $(LD) $(OBJS) -T $(LDS_GEN) -o $(APP).elf
    

为了简化 Sam 的回答,我将以下内容添加到我的 makefile 中,然后我们开始:)

PRE_LD_FILE = $(PROG_NAME).ld
LD_FILE = $(PROG_NAME)_generated.ld

$(LD_FILE) : $(PRE_LD_FILE)
    cpp $(PRE_LD_FILE) | grep -v '^#'   >>$(LD_FILE)

久违的小更新。这种预处理方式一直有效,直到内存文件不包含欺骗预处理器的行。例如:

"KEEP(*path/*.o(.rodata .rodata*))"

路径后的“/*”被认为是注释开始(该行包含被认为是 C 多行注释开始而不是匹配模式)。

此行对链接器有效,但它被视为注释,C 预处理器的输出将删除所有内容,直到找到假定的结束注释:

"KEEP(*path"

生成的文件显然对链接器无效。我暂时没有解决办法。