In summary, the underlying problem seems to be the fact that the armcc
C preprocessor/compiler does not have an option to warn if undefined preprocessor macros are used in #if
preprocessor directives, and the downstream developers need hints to get their code to work correctly.
My first instinct is, as I mentioned in a comment, to use preprocessor macros to indicate if a color is selected, rather than which color is selected. In this case, the code block becomes
#if defined(CONFIG_COLOR_IS_RED)
/* Red case */
#elif defined(CONFIG_COLOR_IS_GREEN)
/* Green case */
#elif defined(CONFIG_COLOR_IS_BLUE)
/* Blue case */
#else
#error config.h is not included!
#endif
The downstream developers must include the entire block, of course. (Which seems to be an issue for OP; the downstreamers might be likely to forget or mis-edit the block.)
Another option would be to do the selection at the expression level (as opposed to block level); i.e. using a macro
CONFIG_COLOR(red-expression, green-expression, blue-expression)
which is defined in config.h
as, for example,
#if defined(CONFIG_COLOR_IS_RED)
#define CONFIG_COLOR(red, green, blue) (red)
#elif defined(CONFIG_COLOR_IS_GREEN)
#define CONFIG_COLOR(red, green, blue) (green)
#elif defined(CONFIG_COLOR_IS_BLUE)
#define CONFIG_COLOR(red, green, blue) (blue)
#else
#error Color not configured!
#endif
In this case, if the header file is not included, the compiler should warn at compile time about undeclared symbol CONFIG_COLOR
, and at link time refuse to link because symbol CONFIG_COLOR
is undefined.
In this case the user code is quite simple, for example
my_color_attribute = CONFIG_COLOR( my_red, my_green, my_blue );
or constants or expressions instead of my_red
, my_green
, and my_blue
. As you see, the macro chooses one value out of three, depending on which "color" is selected.
If block level code is required, then I'd suggest using macros
IF_RED
/* Red case */
ENDIF
IF_GREEN
/* Green case */
ENDIF
IF_BLUE
/* Blue case */
ENDIF
where the macros are defined in config.h
as e.g.
#if defined(COLOR_IS_RED)
#define IF_RED if (1) {
#define IF_GREEN if (0) {
#define IF_BLUE if (0) {
#elif defined(COLOR_IS_GREEN)
#define IF_RED if (0) {
#define IF_GREEN if (1) {
#define IF_BLUE if (0) {
#elif defined(COLOR_IS_BLUE)
#define IF_RED if (0) {
#define IF_GREEN if (0) {
#define IF_BLUE if (1) {
#else
#error Color not selected!
#endif
#define END_IF }
which generates defunct code (code that will never be reached) for the non-selected code cases; the compiler should be able to optimize the branches away, although I'm not sure if/which options are needed for armcc
.
If the config.h
header file is not included, then the compiler will choke on the IF_RED
etc. symbols as undefined.