I have a define in the base classes header file. Using the define in a derived class is not possible:
Plugin.h
#ifndef PLUGIN_H
#define PLUGIN_H
#include "../config.h"
#ifdef DEBUG
#define DEBUG_PLUGIN(...) ets_printf( __VA_ARGS__ )
#else
#define DEBUG_PLUGIN(...)
#endif
class Plugin {
public:
Plugin();
...
SimplePlugin.h
#ifndef SIMPLE_PLUGIN_H
#define SIMPLE_PLUGIN_H
#include "Plugin.h"
class SimplePlugin : public Plugin {
public:
SimplePlugin();
...
SimplePlugin.cpp
#include "SimplePlugin.h"
SimplePlugin::SimplePlugin() : _devices() {
DEBUG_PLUGIN("[SimplePlugin]\n"); // <-- not printed
}
config.h has DEBUG defined. Could you highlight the preprocessor magic?
UPDATE
The comments got me on the right track. Macro expansion does of course not depend on class hierarchy, in fact not on the compiler at all but on the preprocessor. The macro is defined, expanded by preprocessor an executes, otherwise we would see compile errors.
It finally turned out that the Arduino/esp8266 ets_printf function needs additional hardware configuration or it will only work unreliably. That unreliable behaviour made it look like as if it was only called depending on location in the file/class hierarchy.
Yes, you should read much more about the C/C++ preprocessor (both C & C++ share the same preprocessor, with some differences in predefined macros). It is operating textually only. It has no notion of types (e.g. class), or of scope.
You could get the preprocessed form of SimplePlugin.cpp using a command line like:
g++ -C -E SimplePlugin.cpp > SimplePlugin.ii
(you could have to add some additional -Dsymbol and -Idirectory before the -C, exactly as in your compilation command)
Then, look into the generated SimplePlugin.ii file (the preprocessed form from SimplePlugin.cpp...) with your editor or pager.
You might even remove the line information (emitted by the preprocessor in lines starting with #) with
g++ -C -E SimplePlugin.cpp | grep -v '^#' > SimplePlugin.nolines.ii
and then you could run g++ -c -Wall SimplePlugin.nolines.ii, the diagnostics would refer to the preprocessed file SimplePlugin.nolines.ii, not the original unpreprocessed SimplePlugin.cpp
Read also the documentation of GNU cpp
(I am guessing you use GCC; please adapt my answer to your compiler suite; I am even guessing that your bug might be unrelated to preprocessing)
Obvious possible explanations would be
ets_printf() - which is non-standard, and you have not described - does not work as you believe. For example, it could itself be a macro that is defined to do nothing if DEBUG is defined.
DEBUG is not actually defined in your config.h. A typo somewhere could easily mean some other macro is being defined, rather than the one you believe.
The header might actually be defining DEBUG but the preprocessor subsequently encounters an #undef DEBUG. That may be in the same header, a different header, or even in your including source file.
The problem is unlikely to have anything to do with definitions of classes or constructor. The preprocessor does not follow scoping rules.
Related
I want to ask if I can make a file of macros that basically defined at compile time and use these macros in my c++ code which compiles specific code if the condition is true. SO what is basically the extension for that file is it a .txt file or a .h file. and how to put this file in CmakeList.txt to make it executable at compile time. for example like this in a specific file?
#define melodic 1
#define noetic 2
A C++ macro is a shortcut for writing code, what happens when you compile your project is that this code:
#define SOMETHING 32
int i = SOMETHING
Is changed to before it is compiled:
int i = 32
So a macro just substitutes text wherever you place it. There is also another use of macros that maybe is what you are looking for. You can use the preprocessing directive #ifdef MACRO to compile some code conditionally. For example, let's say that you have a function that is only there for debugging, but you don't want that code to make it to release. You could define it like:
void hello() {
#ifdef DEBUG
print("debug");
#endif
}
Then, if that file has a #define DEBUG before the #ifdef macro, the code will be included. Otherwise, the code will be discarded. Note that to use #ifdef the macro body may be empty or not, it just checks if the defined directive was used.
What you might want to accomplish is to have a series of preprocessor macros that you either set or don't in a separate configuration file to change the code produced. They are a very powerful tool, but they must be use with caution since having too many can make code not very readable.
To accomplish that, you need to include the #define MACRO in the same file that you are checking if it is defined, and before you check it. If you are only using that macro in that file, it would be good to place it at the top of it, but if you use it on multiple files you can create a header file (.h) and use #include "name.h", since include copies the contents of the header file there, therefore adding the macro definitions to your file.
The preprocessor directives are dependent on the compiler, so the version and type of compiler you use (gcc, clang...) will have different support for them. However, defined and ifdef are very widely spread and most if not all compilers have them. I recommend reading more about directives, for example here.
Finally, in case you go the route of the .h file, you would add it like any other header file you have in your project to the CmakeList.txt.
So I'm currently working on something that uses OpenCL. The OpenCL spec provides the users with a directive which must be included before the inclusion of the header (cl.h)
#define CL_TARGET_OPENCL_VERSION 110
Which basically defines the version they want to use. Suppose I'm making a library and I want my users to define this instead of me defining this inside my files. What I did was.
-----main.cpp---
#define CL_TARGET_OPENCL_VERSION 110
#include "library.h"
-------x---------
----library.h-----
#ifdef CL_TARGET_OPENCL_VERSION
#pragma message("def")
#endif
#ifndef CL_TARGET_OPENCL_VERSION
#pragma message("ndef")
#endif
.... include other headers.
--------x---------
And the compiler prints both def and ndef messages. And the OpenCL library also throws a warning that it's undefined. I thought that the library header would get substituted into main and it'd only print the def message. Is there anything I understood wrong?
I'm particularly confused as to where does the preprocessor start? If it starts from main.cpp and goes from top to down, then it surely has defined the macro. After that it sees the library inclusion, then it should only print the def message but it prints both.
This leds me to believe the preprocessor does scan the header file before including it in main? Dunno the reason why. Also I have assured that the library header isn't included elsewhere.
One interesting thing I noticed was, if i did this
-----helper.h---
#define CL_TARGET_OPENCL_VERSION 110
-------x---------
----library.h-----
#include helper.h
#ifdef CL_TARGET_OPENCL_VERSION
#pragma message("def")
#endif
#ifndef CL_TARGET_OPENCL_VERSION
#pragma message("ndef")
#endif
.... include other headers.
--------x---------
It prints the def message "twice". If anybody can explain all this I'd be grateful.
EDIT:- The files I'm compiling are main.cpp library.h and library.cpp
Library.cpp includes library.h from the start as usual. Maybe this other cpp is causing the problem?
In C/C++ programs, the compiler handles each .c and .cpp file separately.
The compilers build each source file (NOT the header files, only .c and .cpp files) independently from each other (this source files are called compilation unit).
Thus, when your main.cpp is built, the compiler finds the #define CL_TARGET_OPENCL_VERSION 110 you have added on top of the main.cpp file, emiting the defmessage.
But when the compiler builds the library.cpp file, it does not find the version define, so it emits the ndef message.
So, following this explanation, it is completely normal that in your last case, when you add the define to the .h file, the compiler emits the def message twice, once for the main.cpp file and once for the library.cpp file.
Now, the problem is where should you add the define, in order to have the program built consistently, with the same version for all the .cpp files.
Usually, all the IDEs have some configuration page where you can add global defines, for all the project, which are "inserted" into all the compilation units before everything else. So when the IDE calls the compiler, it passes the same defines to all the compilation units. You should add this kind of defines in this page.
In your IDE (I am using Code::Blocks, v 17.12), you can find this page in the menu: Project / Build Options
For each type (Debug or Release), you have to go to the tab Compiler Settings, and there to the sub tab #defines. There you can add global defines, which can be different if you are building in Debug or in Release mode (of course, if you set the same in both modes, they would be the same).
Once you have added your define here, please, remove it from the main.cpp, library.h and any other place where you may have added it, in order to avoid duplicities.
From the comments about portability:
You have several options:
Always use Code::Blocks: this would be the easiest way, since you can pass the Code::Blocks project along with the source files, and everything would be already setup.
Use cmake, which is a script build system, where you can set defines and so in the same way as using an IDE. cmake is much widely used than Code::Blocks, so maybe it is a better option.
Add a new options.h header file, where you set all the defines, and include it to all your .c/.cpp. This setup has the additional benefit that for different systems, changing only the options.h file the build can be completely different. This is a manually setup of what the IDE is doing. It has the advantage that does not rely on external tools, but the disadvantage that you have to remember to add it in all the new .cpp files added to the project.
My recommendation is go with cmake, just as the others have said.
Prefer using #ifndef XXXX_h #define XXXX_h #endif over #pragma once
If your #include search path is sufficiently complicated, the compiler may be unable to tell the difference between two headers with the same basename (e.g. a/foo.h and b/foo.h), so a #pragma once in one of them will suppress both. It may also be unable to tell that two different relative includes (e.g. #include "foo.h" and #include "../a/foo.h" refer to the same file, so #pragma once will fail to suppress a redundant include when it should have.
This also affects the compiler's ability to avoid rereading files with #ifndef guards, but that is just an optimization. With #ifndef guards, the compiler can safely read any file it isn't sure it has seen already; if it's wrong, it just has to do some extra work. As long as no two headers define the same guard macro, the code will compile as expected. And if two headers do define the same guard macro, the programmer can go in and change one of them.
#pragma once has no such safety net -- if the compiler is wrong about the identity of a header file, either way, the program will fail to compile. If you hit this bug, your only options are to stop using #pragma once, or to rename one of the headers. The names of headers are part of your API contract, so renaming is probably not an option.
(The short version of why this is problematic to use #pragma is that neither the Unix nor the Windows filesystem API offer any mechanism that guarantees to tell you whether two absolute pathnames refer to the same file.)
Say I've two header files A.hpp and B.hpp and A.hpp gets included in the second file via #include "A.hpp" statement. Now when distributing the header files, I want another option which includes a single header file A_B.hpp which contains exactly the same code as the contents of A.hpp pasted over its #include statement.
For now I'm manually copy pasting the contents since releases are fewer and the size of files isn't much, but is there an automated way of doing something like this? Something like command B.hpp > A_B.hpp
Another thing to keep in mind, I don't want other preprocessor things like macro expansions, OS detection specific macros like -
#if defined(__unix__) || defined(__unix) || defined(__linux__)
#define OS_LINUX
#elif defined(WIN32) || defined(_WIN32) || defined(_WIN64)
#define OS_WIN
#elif defined(__APPLE__) || defined(__MACH__)
#define OS_MAC
#else
#error Unknown Platform
#endif
to get evaluated since they need to be present in the final file. Any other way to do such taks is also welcomed.
You'll need to write your own script for this. What you're asking for is far less than what gcc -E does (preprocess everything). Further, it's less than what cpp -fdirectives-only does, because you don't want to recurse. You effectively have a project-specific requirement, and you'll need to write project-specific code for it.
Perhaps you are looking for the unifdef utility.
Say I've two header files A.hpp and B.hpp and A.hpp gets included in the second file via #include "A.hpp" statement. Now when distributing the header files, I want another option which includes a single header file A_B.hpp which contains exactly the same code as the contents of A.hpp pasted over its #include statement.
Actually, you don't say what A.hpp & B.hpp are containing (and details are important). They probably are including some system headers (like <stdio.h> from C standard library, or <new> or <vector> headers from the C++ standard library).
Then, distributing their preprocessed form (the output of g++ -C -E b.hpp ...) is practically useless, because that form then contains some system and compiler specific declarations/definitions, which is not portable to another compiler (in practice the <map> from GCC 5 is probably not compatible with the <map> from GCC 6).
The whole point of standard libraries is that they are normalizing the name of headers (and their public interfaces) like <vector> or <stdio.h> but not the details of their contents (and private implementations). And compilation options (like -pthread or -std=gnu++11 or -O ...) may influence on the preprocessed form (notably thru common predefined macros).
You might use the -H preprocessor option to g++ to find out what is included (or even play tricks with various -M... options).
Perhaps you might want to distribute an amalgamation of your source code (like SQLite does), but that requires some careful design effort.
You could consider using some external preprocessor like m4 or GPP.
(but it is project-specific, and much less easy than what you think, precisely because of the role of standard headers in your project ones)
In an MSVC C++ program I have a part of code which I want to enable or disable depending on a preprocessor definition
// 1.h
#ifdef MYOPTION
//...
#endif
But I find that it is quite dangerous when it is used in a .h file included in more than one compilation unit, as I can easily get inconsistent headers (I don't want to define MYOPTION globally as it would require a complete recompilation each time I change it):
// 1.cpp
#define MYOPTION
#include "1.h"
// 2.cpp
#include "1.h"
Of course, it is much more complicated than this simplified example due to the chained header inclusion.
Is there a way to avoid such inconsistency, e.g. have a compile-time error without too much effort?
I thought of doing #define MYOPTION 0 or 1, but then I would have to write something like
#if MYOPTION == 1
//...
#elif !defined(MYOPTION)
#error ...
#endif
which looks too complicated... Maybe there is a better option?
How about something like this: have 1.h define a dummy section in the obj with different options. This way, if MYOPTION is ever used inconsistently, the linker will issue a warning.
1.h:
#ifdef MYOPTION
#pragma section("MYOPTION_GUARD",write)
#else
#pragma section("MYOPTION_GUARD",read)
#endif
namespace { __declspec(allocate("MYOPTION_GUARD")) int MYOPTION_guard; }
Compiling with MYOPTION defined in a.cpp but not in b.cpp yields this linker warning (using VC 2008):
b.obj : warning LNK4078: multiple 'MYOPTION_GUARD' sections found with different attributes (40300040)
A consistent definition yields no linker warnings at all.
I think you've listed most solution yourself, basically. I would use the last solution, but perhaps in a slightly different form:
#ifndef MYOPTION
#error ...
#endif
...
#if MYOPTION == 1
//...
#endif
Because often this #if MYOPTION == 1 will appear more than once in each file. It's also clearer that MYOPTION is a requisite for that file.
You say it "looks too complicated", but I'm afraid there's probably no solution that's less "complicated" than this.
Assuming that you actually need to use the defines, better is to define them via the compiler command line than #define in your source files. Then your configure script/makefile/build process sets the define once and you're guaranteed that it will agree properly across all source files.
Perhaps what you want is to create a separate configuration.
You can go to Build -> Configuration Manager and create a new configuration (separate from DEBUG, RELEASE). Creating a new configuration will allow you to define preprocessor symbols specific to that configuration.
For example, with a new configuration titled "MyOption 1" you could add the preprocessor definition MYOPTION = 1. The same thing goes with MYOPTION = 2, 3, ...
Each configuration has to be built separately.
DEBUG and RELEASE are examples of separate configurations; DEBUG defines _DEBUG and RELEASE defines NDEBUG
This is what I'm trying to do:
$ c++ -D GENERATED=build/generated-content main.cpp
My main.cpp file:
#include "GENERATED/header.h"
void f() { /* something */ }
Currently this code fails to compile. How should I fix it? And whether it's possible at all?
It seems you want to use different headers depending on some "compilation profile".
Instead of the -Dsolution, I would rather suggest using the -I directive to specify the include directories.
Given you have the following file tree:
/
debug/
header.h
release/
header.h
main.cpp:
#include "header.h"
/* some instructions, not relevant here */
And in your Makefile (or whatever tool you use), just specify the proper include directory to use, depending on whatever reason you want:
g++ -I debug main.cpp // Debug mode
g++ -I release main.cpp // Release mode
Important foot note: I don't know if you intended to use this as a debug/release switch. However, doing so would be weird: the interface (the included .h files) shouldn't change between release and debug. If you ever need this, the usual way is to enable/disable some parts of the code using defines, mostly in .c (and .cpp) files.
You can't do that directly, but this is possible:
c++ -D "GENERATED=\"build/generated-content\"" main.cpp
#define INCLUDE_NAME() GENERATED "/header.h"
#include INCLUDE_NAME()
EDIT: This solution does not work (see the comments below).
Essentially, any #include statement not conforming to the 'normal' syntax (either #include "" or #include <>) but being of the form #include SOMETHING will cause SOMETHING to be preprocessed, after which it has to conform to one of the 'normal' syntaxes. SOMETHING can be any sequence of pp-tokens.
However in this case, the result (as generated by GCC) is...
#include "build/generated-content" "/header.h"
... which does not conform to one of the 'normal' syntaxes.
I don't believe that is covered in the C++ Standard, so it would be up to the individual compiler vender whether or not to support it. I don't think any do.
However, just about every compiler allows you to specify a search directory for headers. It's usually the /i option.
So it would be:
$ c++ -i build/generated-content main.cpp
My main.cpp file:
#include "header.h"
void f() { /* something */ }