8

Can I use Preprocessor Directives in .ld file? I need to to use one of two sets of .ld file and wants to let Build engine deside that using macro, Can I do that?

Kunal
  • 115
  • 1
  • 5

3 Answers3

14

Yes, you can. You need to run preprocessor manually for your linker script, like this:

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

gcc -E -P -x c $cflags $in >$out

Flags:

  • -E specifies GCC to only run preprocessor
  • -P prevents preprocessor from generating linemarkers (#line directives)
  • -x c tells GCC to treat your linker script as C source file (it's needed to run GCC with your LD script)

Or you can simply use cpp tool, which is actually C preprocessor.

After this you will be able to use generated linker script to build your program (e.g. in Makefile).

Example

Here is how I solved this problem in my project:

  1. Here is my linker script uses preprocessor (#include directive and CONFIG_TEXT_BASE constant). Excerpt:

     #include <config.h>
    
     . = CONFIG_TEXT_BASE;
    
  2. Here is script to generate preprocessed linker script. Excerpt:

     gcc -E -P -x c -Iinclude $cflags $in >>$out
    
  3. Here is my Makefile, it's generating preprocessed linker script at $(LDS_GEN) target (line 53) and the this generated script is being used to build result binary (line 42). Excerpt:

     $(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 Protsenko
  • 14,045
  • 4
  • 59
  • 75
2

Small update after long time. This way of pre-processing works until the memory file does not contain lines that are fooling the pre-processor. E.g.:

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

The "/*" after path is considered comment start (the line contains what is considered a C multi-line comment start and not a match pattern).

This line is valid for the linker but it is considered comment and the output from C pre-processor will remove everything till a supposed closing comment is found:

"KEEP(*path"

The resulting file is clearly invalid for the linker. I have no solution at the moment.

AlSavi
  • 94
  • 5
  • Solved using "-CC" option of the gcc pre-processor: gcc -CC -E -x c ... – AlSavi Jul 31 '20 at 15:13
  • A development system I'm using had this pre-processor step for the .ld file built-in to its automated build system. I solved the problem by changing path/* to path/?* – dsmtoday May 18 '21 at 17:30
0

As a simplification of Sam's answer, I added the below to my makefile and away we go :)

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)
Joel Roberts
  • 149
  • 1
  • 9