I'm using Keil to code for STM32 microcontrollers. In main.h file, I use this code:
#if defined __has_include //Keil recognizes this preprocessor. If it was unavailable, Keil would have marked it as gray
#if __has_include("Debugg.h")
#include "Debugg.h"
#endif
#endif
This, checks if the Debugg.h file exists. Let's imagine I have a #define in Debugg.h file:
#define DEBUGGING 1
Now, I expect that in main.h, the DEBUGGING is defined. Again main.h:
#if defined __has_include //Keil recognizes this preprocessor. If it was unavailable, Keil would have marked it as gray
#if __has_include("Debugg.h")
#include "Debugg.h"
#endif
#endif
#ifdef DEBUGGING
#define MAIN_DEBUG 1 //This line runs
#else
#define MAIN_DEBUG 0 //Keil IDE mark this line as gray, meaning "unavailable code"
#endif
But, whenever I try to print MAIN_DEBUG or use it, it is 0!
NOTE:
It seems that Keil IDE recognizes the __has_include preprocessor, but the compiler DOES NOT; because when I comment out these lines:
//#if defined __has_include
#if __has_include("Debugg.h")
#include "Debugg.h"
#endif
//#endif
I get these errors:
compiling main.c...
..\Library\main.h(5): error: #59: function call is not allowed in a constant expression
#if __has_include("Debugg.h")
..\Library\main.h(5): error: #31: expression must have integral type
#if __has_include("Debugg.h")
..\Library\main.c: 0 warnings, 2 errors
I also use the default ARM compiler version 5. Any suggestions?
Thanks.
Any suggestions?
Do not use non-portable extensions like __has_include. Build systems are used to detect information about environment, like available headers.
For example, CMake build system has check_include_file that you can check if an include file exists. Then if the include file Debugg.h (why upper+lower case mix?) exists, then add a macro HAS_DEBUGG_H to compilation and if that macro is defined, then include the header.
a libX.c, a libX.h and libX_conf.h file. the checking for Debugg.h is in config file. If it was available, it checks for the prints of a specific thread. If not, debugging is deactivated
That should be done with a macro, not with "detecting header file". There should be a macro, called like LIBX_DEBUG_ENABLE and if defined, libX should output debugging information. I.e. it is a user configuration setting done with a macro, not with deleting a file.
Related
EDIT : reformulate my question :
In file like delay.h (for avr programming in embedded system) you find this kind of pre-processor define :
#ifndef F_CPU
/* prevent compiler error by supplying a default */
# warning "F_CPU not defined for <util/delay.h>"
# define F_CPU 1000000UL
#endif
It seems quite simple. If nobody defined a value for F_CPU, this will declare 10000000 for it and continue compilation. There is no .c file only a .h file.
Now I have a couple of .c and .h file of my own. And when I try to implement this kind of protection for another value. I get a warning even if I previously declared the value in mu main.c file.
main.c file :
#define BAUDE_RATE_SPEED 115200
#include "uart_ctrl.h"
void main(){
}
uart_ctrl.h file :
#ifndef __UART_CTRL_H__
#define __UART_CTRL_H__
#ifndef BAUDE_RATE_SPEED
#define BAUDE_RATE_SPEED 9600
#warning "BAUDE_RATE_SPEED defined at 9600 in uart_ctrl.h"
#endif
void uart_config();
#endif
uart_ctrl.c file :
#include "uart_ctrl.h"
void uart_config(){
MCU_REGISTER.UART = BAUDE_RATE_SPEED;
}
build error :
Warning #warning "BAUDE_RATE_SPEED defined at 9600 in uart_ctrl.h" [-Wcpp] \uart_ctrl.h Build 1
Why this rise me a warning ? Is it normal and i don't understand behaviours or I missed something ?
Thanks again for your help.
------------- Previous question
Ok, I didn't exactly how to ask this questions. Let me know if you see a better option than the title I set.
On embedded system is very common to declare the mcu frequency with this statement for 20Mhz frequency.
#define F_CPU 20000000UL
And it's common too, to have this kind of check, in files using it. Let say delay.h :
#ifndef F_CPU
/* prevent compiler error by supplying a default */
# warning "F_CPU not defined for <util/delay.h>"
# define F_CPU 1000000UL
#endif
If I define F_CPU in my main or anywhere before including my delay.h the warning does not appear and the the first declared F_CPU value is used.
Now I'm writing my own library, I'm trying to do the same, with the same structure. For example :
#ifndef UART_BAUD_SPEED
/* prevent compiler error by supplying a default */
# warning "UART_BAUD_SPEED not defined bla bla"
# define UART_BAUD_SPEED 115200
#endif
But it trig warning anyway. If my library is .H file only or if this is couple h/c file.
How can I implement the same warning/error protection in my library ? What i'm missing ?
Thanks in advance for your help.
The compiler compiles each file separately. When it compiles main.c, main.c defines BAUDE_RATE_SPEED before it includes uart_ctrl.h. When it compiles uart_ctrl.c, nothing defines BAUDE_RATE_SPEED before uart_ctrl.h, so it is not defined and it gives the warning.
When you run the compiler it has an option to define things automatically before compiling the file, which might be where F_CPU comes from. It would be typical to add -DBAUDE_RATE_SPEED=9600 to the compiler command for all files in the project, instead of defining it separately in each file. If you are using an IDE, you may have to figure out where to enter this in the IDE.
Ok, I found where is my miss-understanding.
as #user253751 said, each files is compiled separately. But this only apply to file with couple .h/.c file. Because the delay.h file is header only file, it is never compiler alone. Only included. So the warning never triggered.
Thanks for your help.
I am using the following macro in some C files:
DBGL_LOG_INFO(DBGL_UART_LOG_ENABLED, "UART is initialized");
The macro calls my logging module, if the define LOG_UART_ENABLED is true.
If the define is false, the logging code will not be compiled and so does not influence my regular program code in release build.
But now, I have the following Problem:
The C files, which does contain this macro call should be also used in another project, where the log module does not exist. So the define DBGL_UART_LOG_ENABLED also does not exist in this other Project.
Of course, when I compile the file with this code in the project, i get the following error:
'DBGL_UART_LOG_ENABLED' undeclared (first use in this function); did you mean '...'?
Is it possible, to tell the compiler, that this code should be ignored, if the macro and the defines are missing?
Thank you in advance.
Conditionally define the macro. For instance, the following is a common pattern:
#ifndef DBGL_UART_LOG_ENABLED
# define DBGL_UART_LOG_ENABLED 0
#endfif
And you probably also need to handle DBGL_LOG_INFO:
#ifndef DBGL_LOG_INFO
# define DBGL_LOG_INFO(...) do {} while (false)
#endif
This defines the macro as an empty block that swallows its arguments. That way, you can continue to use the macro in code without it affecting the output.
This would be why such code is commonly written as
#ifdef DBGL_UART_LOG_ENABLED
/* do stuff with DBGL_UART_LOG_ENABLED */
#endif
I have two version of code and I need to switch them as work need to compile each one while keeping two version on an IAR project. I find something like "compile switch" but I don't know how is it doing. Is there anyone tell me a keyword or an advice that can I search?
You can use C preprocessor #define feature to toggle between code versions and use IAR EWARM project's Defined Symbols feature to enable a list of #defines in a specific header file (for example: defines.h) that will be included in all C files.
defines.h
#if defined(PROD_VERSION)
#define SOFTWARE_VERSION_PRODUCT ("1.0-release")
//...whetever specific #defines meant for the release version, for example...
//#define ENABLE_RF_STUB
#define USE_SERIAL_CTS_RTS
#elif defined(TEST_VERSION)
#define SOFTWARE_VERSION_PRODUCT ("1.0-test")
//...whetever specific #defines meant for the test version, for example...
#define ENABLE_RF_STUB
#define USE_SERIAL_CTS_RTS
#elif defined(DEBUG_VERSION)
#define SOFTWARE_VERSION_PRODUCT ("1.0-debug")
//...whetever specific #defines meant for the debug version, for example...
#define ENABLE_RF_STUB
//#define USE_SERIAL_CTS_RTS
#endif
in rf.c
#include "defines.h"
void rfInit(void)
{
#ifndef ENABLE_RF_STUB
//init RF here
#endif
}
In serial.c
#include "defines.h"
CPU_BOOLEAN isCtsRts()
{
#ifdef USE_SERIAL_CTS_RTS
return HAL_SERIAL.isCtsRts();
#else
return DEF_TRUE; //bypass CtsRts check
#endif
}
In your project option > C/C++ Compiler > Preprocessor > Defined symbols: add PROD_VERSION if you want the release version, or add TEST_VERSION if you want the test version or add DEBUG_VERSION if you want the debug version.
You can only choose one of the three configurations above only as IAR will only compile one version via the project compilation. Unless you can create a batch build script to allow building all the three versions under different output files created with three different project setups.
IAR has a configuration in toolbar Project > Edit_Configuration
It makes you set version "switches" via set these tool and it is possible to set preprocessor command for each setup.
I have a project in C that I need to modify and run. At some point, in a source file I have
#ifndef THE_FLAG
// declare important stuff
#endif
but, I don't know where THE_FLAG is #included from. It is not defined in my project, and it is hidden somewhere in external library.
I tried gcc -M but it shows the headers, without information if it was included directly or somewhere higher in the include hierarchy.
The project is too complicated to track all the dependencies by hand. It is build with ./configure && make.
Question: how to track this external dependency?
Try compiling with gcc -E. This will tell gcc to stop at the preprocessing stage. As part of that, it will tell you where all the #defines came from.
Note that this will create a text file, not a .o file.
You can get gcc to tell you exactly where the flag is defined by redefining it for test purposes, e.g.
#include <limits.h>
#define INT_MAX 42
int f(void)
{
return INT_MAX;
}
will make gcc complain
main.c:4:0: warning: "INT_MAX" redefined [enabled by default]
#define INT_MAX 42
^
In file included from main.c:2:0:
/usr/lib/gcc/x86_64-redhat-linux/4.8.1/include/limits.h:120:0: note: this is the location of the previous definition
#define INT_MAX __INT_MAX__
^
The same strategy also works well for finding struct definitions (very useful in case you have several architect specific header files and you are not sure which one is actually used!).
#include <stdio.h>
typedef void FILE;
void f(void)
{
}
gives
main.c:3:14: error: conflicting types for ‘FILE’
typedef void FILE;
^
In file included from main.c:1:0:
/usr/include/stdio.h:48:25: note: previous declaration of ‘FILE’ was here
typedef struct _IO_FILE FILE;
^
gcc -E will give us the output after preprocessor. But sometimes it will be difficult for a developer to verify if the .c file is very big and including some big header files. In such cases checking build output will be easier. #warning will print the message as warning during compilation.
#ifndef THE_FLAG
#warning "including ABC stuff"
// declare important stuff
#endif
We can make compiler warnings using #pragma also, but its not platform independent.
#pragma "including ABC stuff"
If we want to stop the compilation if some unwanted macros has been defined somewhere, we can use #error.
#ifdef UNWANTED_FLAG
#error "Build stopped. UNWANTED flag has been defined"
#endif
Using Eclipse IDE. Problem is that #defines aren't passing from the headers to the c and h files. Not sure if it's a project settings thing or what, but Visual Studio IDE is not giving me any trouble on the same project. Some of the projects in Eclipse don't have this problem though. Any ideas on what may be wrong? See example of the problem below.
Even though EXAMPLE is defined in header1.h, it is not recognized as defined in main.c. There is no issue with the compiler finding the headers either. Thanks for the help all.
Header1.h
#define EXAMPLE 1
main.c
#include "Header1.h"
#if defined(EXAMPLE)
/* code here */
#endif
You mention there is no issue with the compiler and visual studio, so assuming you are referring to the code being grayed out in the Eclipse IDE? If so, check the Indexer settings
Preferences --> C/C++ --> Indexer
Check Enable Indexer Check Index Source files not included in the
build Check Automatically update the index Check Use Active build
Configuration
etc,...
hope this was relevant to your issue.
Does this work?
#ifdef EXAMPLE
instead of
#if defined(EXAMPLE)
Behavior similar to that in the question can be seen when using #defines that are strings, not integers.
The following code seems like it should run Code(); only when MODE is equal to the string different:
mode.h
#define MODE something
different.cpp
#include "mode.h"
#if MODE == different
Code();
#endif
Eclipse shows Code(); as being active when it appears it should be inactive. The reason for this is that the preprocessor does not support string comparisons, only integer ones1.
When mousing over MODE in different.cpp, MODE is shown as having the value something. Although this is technically correct, it can be misleading since both MODE and something evaluate to the same thing (a defined but empty value). Given that they both have the same value (nothing) they evaluate as being equal and Code(); is run.
1 This is gone into in more detail in this question.
Solutions
Two possible ways of correctly handling this come to mind:
Assign numeric values to each option
Use unique #defines for each option
Use numeric values
The code could be written as follows:
mode.h
#define MODE_something 0
#define MODE_different 1
#define MODE MODE_something
different.cpp
#include "mode.h"
#if MODE == MODE_different
Code();
#endif
In this case the code works as expected since MODE and MODE_different evaluate to two distinct values (0 and 1, respectively).
Use unique #defines
Another approach is to use uniquely-named macros for each option. For example:
mode.h
// Select the active mode:
#define MODE_something
//#define MODE_different
different.cpp
#include "mode.h"
#ifdef MODE_different
Code();
#endif