I have an executable made by linking several .o files, using a somewhat involved linker script. If a particular environment flag is set, I'd like there to be another section involved. So, something like:
/* withfoo.ld */
SECTIONS {
.foo 0x80000000 : {
_start_foo = .;
. += 0xfff;
_end_foo = .;
}
}
and then compile with:
if [ $FOO_DEFINED ]; then
gcc -Wl,-T normal.ld $(OBJS) foo.o foo.ld
else
gcc -Wl,-T normal.ld $(OBJS)
fi
where I'd like to not to have to modify normal.ld
. normal.ld
has a SECTIONS definition within it. So that gives me two SECTIONS... I'm getting the warning:
/usr/bin/ld: warning: foo.ld contains output sections; did you forget -T?
Is there an actual problem or is this just a warning? Also is there a proper way to do this that I'm not aware of?
GNU linker scripts and LD do not support conditional compile. You can't use two linker scripts at once and have it work as expected. You have to pre-process the linker script with some other type of macro language like m4
or even just use the GNU C Preprocessor cpp
.
Not sure if this is a type of solution you are looking for. The C preprocessor cpp
can process the text of any kind of file (even non-C files) and will blindly parse for pre-processor directives and macros just like a C file. You can also pass C style defines through the cpp
command line just like you can with GCC. You create a linker script with all the C pre-processor directives and generate specific linker scripts based on that. For example create a special linker script like this:
linker.ld.pp
:
SECTIONS {
#ifdef FOO
.foo 0x80000000 : {
_start_foo = .;
. += 0xfff;
_end_foo = .;
}
#endif
}
This uses typical C style #if/#ifdef/#endif
for conditional compilation. If you run it through the C pre-processor with a command like:
cpp -P -DFOO linker.ld.pp
You'd get output like this:
SECTIONS { .foo 0x80000000 : { _start_foo = .; . += 0xfff; _end_foo = .; } }
Not defining FOO
would be done like this:
cpp -P linker.ld.pp
The output would be:
SECTIONS { }
To redirect the pre-processor you can output to a linker script with:
cpp -P -DFOO linker.ld.pp >withfoo.ld
cpp -P linker.ld.pp >withoutfoo.ld
You can specify multiple -D
directives on the CPP command line to define multiple pre-processor symbols if you wish. The idea of this method is that you have a single linker script but you create a shell script to generate the necessary specialized scripts that are required.
Usually you specify linker scripts on the GCC command line with the -T
option:
gcc -T withfoo.ld $(OBJS) foo.o