1

I have to make conditional compilation to skip some part of code when they are not being used. The project is a MCU project which consists of external modules like LEDs, LCD, Keypads etc.

I have a optimization.h file which is used to tell which modules are used at the time of compilation. It goes like this...

#ifndef OPTIMIZATION_H
#define OPTIMIZATION_H

// 1 - Compile code only for given modules
// 0 - Compile for all available modules
#define _OPTIMIZE_ 1

// Modules to compile
#define _LED_    1
#define _SWITCH_ 1

// Modules not to compile
#define _LCD_    0
#define _SSD_    0

#endif

The code.c file goes like this...

#include "optimization.h"
void myFun()
{
// Compile when LED is used or all modules are asked to use
// i.e when _OPTIMIZE_ is 0 or _LED_ is 1

// Need to compile this code
#if !(_OPTIMIZE_) || (_LED_)
/* My code goes here */
#endif

// Need to compile this code
#if !(_OPTIMIZE_) || (_SWITCH_)
/* My code goes here */
#endif

// Need not to compile
#if !(_OPTIMIZE_) || (_LCD_)
/* My code goes here */
#endif

// Need not to compile
#if !(_OPTIMIZE_) || (_SSD_)
/* My code goes here */
#endif
}

If I wanted to use only LED and SWITCH only that part of code should be compiled. But all modules are compiled every time. What may be the problem...

Next-93
  • 97
  • 1
  • 7
  • [Works For Me™](https://gist.github.com/schwern/c6214f58ea4db2a788c0478746e1ab1e). Have you printed `OPTIMIZE` and friends to make they are what you expect? Also a [good editor](https://atom.io/) will indicate which paths are not followed for you. – Schwern Jan 04 '20 at 03:00
  • How do you (or we) know that they get compiled? Please produce a [mre] – klutt Jan 04 '20 at 03:01
  • 3
    Looks like it ought to work fine except that iirc, preprocessor variables with leading underscores are reserved for the compiler. There might be some strange definition conflicts going on. You should pick other names. You might try debugging using `#if _VAR_ \n #error Var was true! \n #endif`. Also, the parens in the `#if` directives aren't needed. Finally, you should consider a completely different approach. Split the functions into separate files and manage what gets compiled in the makefile. That's cleaner in the long run. – Gene Jan 04 '20 at 03:01
  • I am using MPLABX IDE which generally shades the codes which are not being used in the compilation. But my code above commented as Need not to compile are not shaded of. So they are being compiled... – Next-93 Jan 04 '20 at 03:27
  • 2
    Note that you should not, in general, create function, variable, tag or macro names that start with an underscore. Part of [C11 §7.1.3 Reserved identifiers](https://port70.net/~nsz/c/c11/n1570.html#7.1.3) says: — _All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use._ — _All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces._ See also [What does double underscore (`__const`) mean in C?](https://stackoverflow.com/q/1449181) – Jonathan Leffler Jan 04 '20 at 08:10
  • 3
    Don't trust IDE shading for debugging/testing. If you want to know whether something gets compiled write a `#error Yes, it gets compiled!` in there, it will tell you unmistakably. – Yunnosch Jan 04 '20 at 08:45

2 Answers2

0

The correct solution is to create a library with all the functions. Link your program against that library, and only the needed function will make it in the resulting binary.

For this to work you need to put each function into its own compilation unit. You could do this via separated source files, or with a single source file with preprocessor macro based selection and one compile command per option. I rather choose the first way.

the busybee
  • 10,755
  • 3
  • 13
  • 30
  • enabling the 'One ELF section per function' option in your compiler can also help – Tarick Welling Jan 06 '20 at 12:42
  • Spoken like a true CS grad. While this advice may be very appropriate for application-level programming, it's less appropriate for low-level programming, e.g. embedded systems or O.S./platform code, which must be kept minimal for efficiency's sake. The style you suggest results in deeper call trees than might otherwise be necessary. If your O.S. and C++ runtime was programmed in typical application programming styles, you'd get far worse performance from it. And on embedded systems with severely limited resources, you'd run out of code space or stack space sooner with that programming style. – phonetagger Jan 06 '20 at 22:03
  • 1
    @phonetagger I don't agree. I'm working with embedded systems since 30+ years and worked more than 90% of that time with MCS51, which is one of the most limited platforms. If you are so near at the border of performance and space, you'd rather use assembler. And the OP is talking about LEDs and keys, there is no need for performance. – the busybee Jan 07 '20 at 06:41
  • MCS51, and you're not running out of space? Interesting... My company, which makes electric meters, uses Silergy parts with integrated 8051 cores and banked memory so we can go beyond 64K, and we have one old product still in production with active feature development and less than 20 bytes of RAM free (the exact amount goes up & down as we refactor to reduce usage). – phonetagger Jan 07 '20 at 14:40
  • As far as your suggestion goes, if you already have separate functions, sure... What I meant was, if your codespace is limited, using conditional compilation and larger functions generally takes less codespace and results in shallower stack depth than you would get if you followed typical application programming practices where you split larger functions apart into tiny fragment functions each focused on one tiny aspect of an algorithm. – phonetagger Jan 07 '20 at 14:47
0

I'm afraid that you simplified your problem too much so we are unable to assist. The following code runs fine on my machine:

#include <stdio.h>
/*** from Optimize.h ***/

// 1 - Compile code only for given modules
// 0 - Compile for all available modules
#define _OPTIMIZE_ 1

// Modules to compile
#define _LED_    1
#define _SWITCH_ 1

// Modules not to compile
#define _LCD_    0
#define _SSD_    0

/*** from Code.c **/
int main()
{
// Need to compile this code
#if !(_OPTIMIZE_) || (_LED_)
    printf ("Module LED included\n");
#endif

// Need to compile this code
#if !(_OPTIMIZE_) || (_SWITCH_)
    printf ("Module SWITCH included\n");
#endif

// Need not to compile
#if !(_OPTIMIZE_) || (_LCD_)
    This line is invalid C code.
    printf ("Module LCD included\n");
#endif
}

Additionally I suggest to rename your preprocessor variables. Instead of #if !(_OPTIMIZE_) || (_LCD_), which are hard to read, you should write #if INCLUDE_ALL_MODULES || INCLUDE_LCD_MODULE. Consider also to use the construct #define INCLUDE_LCD_MODULE (INCLUDE_ALL_MODULES | 1).

user5329483
  • 1,260
  • 7
  • 11