This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Incorrect compiling with 'Release' and 'Debug' Targets

Hello everyone!

I've found myself in a spot of bother with Keil uVision 5.24.2.0 using ARM Compiler v5.06 update 5...although the build issues I have don't appear specific to these versions. Let me explain...

In my Keil project I have two targets: 'Release' and 'Debug'. The goal is to globally enable/disable various debug options and change formatted output simply by selecting the appropriate build target and compiling.

Here is how I tried to make it work:

- In 'Options for Target', C/C++ tab, 'Preprocessor Symbols' Define section, I have defined: 'DEBUG' for the Debug target 'noDEBUG' for the Release target all other settings are identical between the Debug and Release targets.

- I have a header file 'debug_config.h' in which I have enable/disable various debug options like so:

#ifndef __DEBUG_CONFIG_H
#define __DEBUG_CONFIG_H

#ifdef DEBUG
#define DEBUG_BUILD 1
#else
#define DEBUG_BUILD 0
#endif

#if ( DEBUG_BUILD == 1 )
#define TEST_MODE_RECOGNIZER 1
#endif

#endif

- In main.c and other source code files (which all #include "debug_config.h") I refer only to DEBUG_BUILD and TEST_MODE_* like this:

printf("IronMan Gen3.7 (%s)\r\n", (DEBUG_BUILD == 1) ? "Debug" : "Release");

#if ( TEST_MODE_RECOGNIZER == 1 )
printf("Jarvis 8.9b Test Mode\r\n");
#endif

With all that in place, if I 'Clean Targets', select 'Debug' target, then Build I will get the following output:

IronMan Gen3.7 (Debug)
Jarvis 8.9b Test Mode

Perfect!

Now I switch to 'Release' target and without doing 'Clean Targets' I do Build. I find main.c is NOT compiled! Why not? Other files which don't #include "debug_config.h" and don't mention DEBUG, DEBUG_BUILD, or TEST_MODE_RECOGNIZER are compiled. Because main.c is not recompiled I get the same output as above! What I want of course is:

IronMan Gen3.7 (Release)

I understand that I did not change main.c source code, so from compiler perspective it thinks perhaps it doesn't need to retranslate it. However, I selected different Target, which had different Defines, so I expected that it would recompile main.c like it did with other files.

I note there is a 'Undefine' section in the Target C/C++ Preprocessor Symbols, but it is grayed out. I can't select or enter anything there, otherwise I would 'Undefine DEBUG' for the Release target.

So I am stumped...

I hope this provides clear example of what I would like to do. Obviously there's something I've done wrong or misunderstood...

Thanks for any advice or suggestions on this!

Best!

Parents
  • Several issues to note:

    1) this way of conditionally defining a preprocessor switch macro:

    #if ( DEBUG_BUILD == 1 )
    #define TEST_MODE_RECOGNIZER 1
    #endif
    


    is a not-quite-optimal fit for this kind of testing the condition:

    #if ( TEST_MODE_RECOGNIZER == 1 )
    

    If your condition is #if instead of #ifdef/#if defined(), you should usually always #define the macro in question (to 1 or 0, accordingly). It'll still work the way you do it, because undefined macros will expand to 0 as a last-ditch effort, but you'll get flak from most code checking tools for that style.

    2) having a header that relies on:
    which all #include "debug_config.h"
    is riskier than it needs to be. It's better to move all those individual, conditionally defined macros directly into the IDE instead, if only because it saves you from silly problems in case you ever forget putting that #include "debug_config.h" in one header or .c file. And it'll save you from warnings about including headers that the code doesn't actually use.

    3) is your real issue:
    However, I selected different Target, which had different Defines, so I expected that it would recompile main.c like it did with other files.
    If you wanted that, you had better specify separate output folders for the two targets. It's arguably a bug that uVision doesn't automatically do that as soon as you set up the second target in the same project.

Reply
  • Several issues to note:

    1) this way of conditionally defining a preprocessor switch macro:

    #if ( DEBUG_BUILD == 1 )
    #define TEST_MODE_RECOGNIZER 1
    #endif
    


    is a not-quite-optimal fit for this kind of testing the condition:

    #if ( TEST_MODE_RECOGNIZER == 1 )
    

    If your condition is #if instead of #ifdef/#if defined(), you should usually always #define the macro in question (to 1 or 0, accordingly). It'll still work the way you do it, because undefined macros will expand to 0 as a last-ditch effort, but you'll get flak from most code checking tools for that style.

    2) having a header that relies on:
    which all #include "debug_config.h"
    is riskier than it needs to be. It's better to move all those individual, conditionally defined macros directly into the IDE instead, if only because it saves you from silly problems in case you ever forget putting that #include "debug_config.h" in one header or .c file. And it'll save you from warnings about including headers that the code doesn't actually use.

    3) is your real issue:
    However, I selected different Target, which had different Defines, so I expected that it would recompile main.c like it did with other files.
    If you wanted that, you had better specify separate output folders for the two targets. It's arguably a bug that uVision doesn't automatically do that as soon as you set up the second target in the same project.

Children