Search code examples
cconditional-compilationkeil

Conditional compilation strategies - how to avoid undefined symbols in C


I am trying to make a modular project in C. I am writing a firmware for an embedded ARM CPU. It is composed of different parts, which cannot all be compiled at the same time due to memory limitation.

Simplifying, let's say I have a module A which manages all the optional parts of the firmware, each coded in its module (B, C, D, etc...)

in module A I use #ifdef clauses:

#ifdef USE_B
  #include "B.h"
#endif

#ifdef USE_C
  #include "C.h"
#endif

...

And then on top of that I simply #define the keyword for the module I want to include.

I have some global variables in file Z.c that should stay there. Since my aim is minimizing memory use, I enclose their declaration in #ifdef as well

#ifdef USE_B
  uint8_t usedonlybyb;
#endif

#ifdef USE_C
  uint8_t usedonlybyc;
#endif

...

What happens is that even if file B and file C are completely disconnected from other part of the project at compile time, at the end of the compilation I get "Undefined symbol" errors for the extern variables "usedonlybyx", which are not reachable by the disabled modules.

I'd like to keep the usedonlybyx variables declared in module Z, because that one is the general settings module.

Is there an elegant way to suppress those errors, and still be able to succeed in my scope?

Should I simply enclose the whole modules B, C, ... within #ifdef / #endif ?


Solution

  • Easier solution is to enclose the whole implementation and declaration inside b.h and b.c files inside #ifdef USE_B and #endif. Same for other modules. That way all the conditional compilation for one module is isolated and does not have to be throughout other code where #include "b.h" is used.

    // b.h
    #ifdef USE_B
    // declarations and include guards
    #endif
    
    // b.c
    #ifdef USE_B
    // definitions
    #endif
    
    // a.c
    #include "b.h" // <- no USE_B needed here