iPXE
|
Overuse of #ifdef
has long been a problem in Etherboot.
Etherboot provides a rich array of features, but all these features take up valuable space in a ROM image. The traditional solution to this problem has been for each feature to have its own #ifdef
option, allowing the feature to be compiled in only if desired.
The problem with this is that it becomes impossible to compile, let alone test, all possible versions of Etherboot. Code that is not typically used tends to suffer from bit-rot over time. It becomes extremely difficult to predict which combinations of compile-time options will result in code that can even compile and link correctly.
To solve this problem, we have adopted a new approach from Etherboot 5.5 onwards. #ifdef
is now "considered harmful", and its use should be minimised. Separate features should be implemented in separate .c files, and should always be compiled (i.e. they should not be guarded with a
#ifdef
MY_PET_FEATURE
statement). By making (almost) all code always compile, we avoid the problem of bit-rot in rarely-used code.
The file config.h, in combination with the make
command line, specifies the objects that will be included in any particular build of Etherboot. For example, suppose that config.h includes the line
When a particular Etherboot image (e.g. bin/rtl8139.zdsk
) is built, the options specified in config.h are used to drag in the relevant objects at link-time. For the above example, serial.o and tftp.o would be linked in.
There remains one problem to solve: how do these objects get used? Traditionally, we had code such as
in main.c, but this reintroduces #ifdef
and so is a Bad Idea. We cannot simply remove the #ifdef
and make it
because then serial.o would end up always being linked in.
The solution is to use linker tables .