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
Related
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.
I'm fairly new to programming in C. My problem is that I have two implementations of a function and I want to be able to switch between them easily.
Right now I define the two implementations of the function as function_implementation1 and function_implementation1 in the files "funtion_implementation1.h" and "funtion_implementation2.h" respectively. To switch between them I have the following file:
#define IMPLEMENTATION1
#ifdef IMPLEMENTATION_1
#include "funtion_implementation1.h"
#define myFunction function_implementation1
#endif
#ifdef IMPLEMENTATION_2
#include "funtion_implementation2.h"
#define myFunction function_implementation2
#endif
In order to switch from one implementation to the other I just have to change the first line. This approach works, and I was satisfied with it for a while, but now it is bugging me that I have to open this file so often. I have a parameters.h file where I define all my parameters and I would rather choose which implementation to use in that file. Sadly, moving the first line to that file does not work. If I do that myFunction is not defined.
What is the best way to do this?
you should include your parameters file where you use alias, macros, etc:
#include "Parameters.h"
also, all your headers files should start with:
#ifndef __FILE_H__
#define __FILE_H__
// definitions go there
#endif
This prevents nested include of header files
Use preprocessor options, specifically the -D option. If you wanted to use IMPLEMENTATION1, when you are compiling that file on the command line (or in IDE), add -D IMPLEMENTATION1. This defines that macro. Same works for any macro
I have a file called assert.h which defines several assertion macros. The project is called Core and lives in a folder with the same name. However, this file lives in Core/hul, which is a submodule of the project that implements some abstract utilities. Here's an excerpt of the file:
#if defined(HUL_DEBUG)
# if defined(HUL_TEST)
# define HUL_ASSERT(e) HUL_TEST_ASSERT(e)
# else
# include <assert.h>
# define HUL_ASSERT(e) assert(e)
# endif
#else
# define HUL_ASSERT(e) /* empty, do nothing */
#endif
As you can see, when HUL_TEST is defined assertion macros expand to a unit test assertion callback. That works fine. When compiling for release (e.g. HUL_DEBUG is not defined) it does nothing. Also fine. When compiling for debug (without testing), it includes the system's assert.h and defines a macro that expands to assert. Everything OK so far.
The problem is that regardless of including <hul/assert.h> or <assert.h> it's always hul/assert.h that is included, which is not what I want. This is one of the reasons that hul/assert.h is qualified under the hul folder.
The obvious first thing to check is Other C Flags and Header Search Paths. But the later is empty and the former is as follows:
-I../../include/Core
-I../../test/include/Core
-I../../test/include
As you can see, Core/hul is not included, so #include <assert.h> should not resolve to hul/assert.h. The question is, why does it? Am I missing some configuration?
Note: of course I could change the file's name, but I rather understand why this is happening. This framework will still grow immensely in number of files and I don't want to be worrying about this kind of conflicts.
set USE_HEADERMAP = NO. When set to YES, XCode uses a dictionary that maps a header file name to a path where to find in order to speed up compilation. So regardless where you place your header file, if it has found his way into this map it will be found forth on.
Another way would be to use absolute paths for all user header files, e.g. #include "./assert.h" (which should give you an error if the file is not located directly in the project directory or any manually defines user header search path).
Hope it helps;
Browsing through MRI's code, I found these #defines I don't understand:
#define ROBJECT_EMBED_LEN_MAX ROBJECT_EMBED_LEN_MAX
#define ROBJECT_EMBED ROBJECT_EMBED
enum {
ROBJECT_EMBED_LEN_MAX = 3,
ROBJECT_EMBED = RUBY_FL_USER1,
ROBJECT_ENUM_END
};
What's the point of those #defines? They seem to do nothing...
This code is found in the ruby/include/ruby/ruby.h file in the ruby github repo.
The #defines make it possible to test for the existence of the definition at compile-time using #ifdef. (You cannot test for the existence of an enum at compile-time.)
Since the C preprocessor doesn't do recursive substitution, defining a symbol as itself effectively does nothing; the symbol is replaced once with itself, and then passed normally to the compiler.
I'm writing a C extension for Ruby, and I have something like this in the extconf.rb file:
if(not have_library('z'))
$stderr << "Error, could not locate zlib.\n"
abort "Missing zlib"
end
So the installation process aborts if zlib is missing. Instead, since my extension can work with AND without zlib, I would like to do something like the following;
if(have_library('z'))
# do something so that -DHAVE_ZLIB is passed to the compiler
# when compiling the extension.
end
How can I do that?
EDIT: The question is on the comment in the if...end statement: how to add the -DHAVE_ZLIB definition for the compiler?
If you can rely on checking for a header file then have_header will define a HAVE_HEADER_H macro for you. For example:
have_header('zlib.h')
will define HAVE_ZLIB_H, which you can then refer to in your code.
If this isn’t enough or you need to define a macro for some other reason you can use the $defs global:
if(have_library('z'))
$defs << '-DHAVE_ZLIB'
# Now HAVE_ZLIB will be defined for you to check in your code
end
I would do it as the following your in extconf.rb file
$libs = ["-lliba", "-llibb"]
if have_library('z')
# where $libs is your array of libraries defined
$libs << "-llibz"
end
As you can see in the api docs for have_library, the method have_library returns either true or false