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)
Related
I have a program that references an "nvml.h" file in order to execute some portion of the code. On my Linux machine, this is accomplished by including the following line in the header file:
#include "/usr/local/cuda/include/nvml.h"
However, I want the user to be able to run the program even if this file does not exist on their system. I have rendered the program modular so this can be accomplished, but I still need some method by which I can check if the file exists at all and, if not, abstain from including it in my header file.
I have tried an IF/DEF statement in order to get it working on both Windows and Linux:
#if defined(Q_OS_UNIX)
#include "usr/local/cuda/include/nvml.h"
#else
#include "C:/Users/thisUser/nvml.h"
But I cannot think of a method by which I can use the IF/DEF structure to check for file existence. Is there any way to do this with preprocessor directives in C++?
You should just do
#include "nvml.h"
set the include path while compiling depending on platform:
g++ -I/usr/local/cuda/include ...
But I cannot think of a method by which I can use the IF/DEF structure to check for file existence. Is there any way to do this with preprocessor directives in C++?
Since C++17, there is the macro __has_include which does exactly this.
Prior to C++17, there was no such directive in the standard, although may have been supported as an extension. A compiler may support command line argument to provide macro definitions, which can be utilised to forward the result of a check for existence prior to compilation.
That said, for your particular case, it might be better to simply include <nvml.h> and add the parent directory to include path. See the manual of your compiler for details - or use a build system to take care of it.
C++17 simplifies this a bit with __has_include which provides the ability to conditionally #include a file only if the file is found in the system.
#if __has_include( <optional> )
# include <optional>
#elif __has_include( <experimental/optional> )
# include <experimental/optional>
#else
//
#endif
I'm building my own terminal app project in C++ and I'm asking myself if standard library has ifdef or ifndef preprocessors instructions. I want to know that because I need to create different header files which need some standard library headers such as "string" and some others, i don't want to include the same library 3 or more times because it makes the program heavier.
For example i wrote on my header files something like this to prevent the .h file to be included more than once:
#ifndef myheader_h
#define myheader_h
// my file code here
#endif
I tried compiling but the compiler say me nothing about errors or warnings.
I also tried to read the standard-library source code (https://en.cppreference.com/w/cpp/header) and I haven't found any preprocessor rule like ifdef or ifndef.
Should i include standard library headers like this?
#ifndef string_h
#define string_h
#include <string>
#endif
I hope my question isn't already asked because I haven't found it while searching it.
Updates
To some who said "you're not in the position where you need to worry about" and who said "it costs very little if it has proper include guards", I meant: program's heaviness is important, I want to make it slighter so I don't want to entirely include the same file multiple times. Have std lib files proper include guards? (my header files have them, didn't know std lib files)
There is no requirement for the standard header files to #define any specific pre-processor symbols to make sure they can be #included multiple times.
Having said that, any sane implementation would make sure that they can be #included multiple times without adversely affecting application code.
Turns out, that is a requirement by the standard for most headers (Thanks, #Rakete1111).
From the C++ standard
A translation unit may include library headers in any order ([lex]). Each may be included more than once, with no effect different from being included exactly once, except that the effect of including either <cassert> or <assert.h> depends each time on the lexically current definition of NDEBUG.
Not only that, they are very likely to be using the #pragma once directive. Hence, even if you use #include multiple times for the same header, they are going to be read only once.
In summary, don't worry about standard header files. If your header files are implemented correctly, your application would be just fine.
Those preprocessor directives you're talking about are called "header guards", and the standard library headers definitely have them (or some other mechanism that does the same thing) like all other proper header files. Including them multiple times shouldn't cause any problems, and you only need to worry about these when you're writing your own header files.
The "source code" that you're reading is just the documentation which says how the header files should work, but it doesn't provide the actual code. To see the code, you can look in the header files provided by your compiler. For example, the <iostream> header in Visual Studio has both #pragma once and header guards:
#pragma once
#ifndef _IOSTREAM_
#define _IOSTREAM_
//...
#endif /* _IOSTREAM_ */
The headers provided by the GCC compiler also has header guards:
#ifndef _GLIBCXX_IOSTREAM
#define _GLIBCXX_IOSTREAM 1
//...
#endif /* _GLIBCXX_IOSTREAM */
I'm asking myself [sic] if standard library has ifdef or ifndef preprocessors instructions
The standard doesn't specify whether there are ifdef-style header guards, although it does require that multiple inclusion is protected in some manner. I took a look at a random header of stdlibc++ standard library implementation. It does have header guards.
i don't want to include the same library 3 or more times because it makes the program heavier
Including a header file multiple times does not make a program "heavier".
Should i include standard library headers like this?
#ifndef string_h
#define string_h
#include <string>
#endif
That is not necessary, or particularly useful.
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.)
I know C or C++ code usually needs to use include guards like this:
#ifndef __A__H__
#define __A__H__
class A{
};
#endif
and to speed up compile time, in other cpp (e.g.:B.cpp), it can change
#include "A.h"
to:
#ifndef __A__H__
#include "A.h"
#endif
but the question is why doesn't the compiler automatically add or generate the include guard, and therefore why does the programmer need to add it manually if an include guard is usually required?
There are times when it is absolutely incorrect to generate the header guard. The standards contain an example: <assert.h> in C and <cassert> in C++.
The effect of reincluding those headers depends on the state of the NDEBUG macro when the header is (re)included. It is legitimate to write:
#undef NDEBUG
#include <assert.h>
…code using assert…
#define NDEBUG 1
#include <assert.h>
…more code using assert…
If the compiler automatically generated a header guard, that would not work correctly. Therefore, compilers do not generate header guards automatically.
Incidentally, user code should not use header guard macro names that start with double underscore, or underscore capital letter. Such names are reserved for the implementation. In C++, no user-defined name may legitimately contain a double underscore at all. Use something more like:
#ifndef A_H_INCLUDED
#define A_H_INCLUDED
…body of header…
#endif
The compiler, or more strictly the pre-processor cannot determine the programmer's intent in using inclusion. The compiler does not explicitly distinguish between .h files and .c or .cpp files; they differ only in the type of code one places in them. In fact the compiler deals only in a single translation unit; it is the responsibility of the C preprocessor to concatenate all included files into a single file for compilation. It would be incorrect for the pre-processor to omit an inclusion that it has previously included because it has no semantic knowledge of the code and may cause intended behaviour to change by second-guessing the developer.
In some circumstances, an IDE may add include guards for template code that it has generated. For example Microsoft Visual Studio will add them for code that it generates via its project start-up wizards. If it happens at all, it is properly the responsibility of the IDE rather than the compiler or pre-processor.
So there is third-party library that has a header file you need to include in order to use it. Since the implementation of the library is not object oriented I wrote a Class to encapsulate all usage of the library, so in case it needs to be replaced I can just modify the implementation of that class.
Since other developers will be working in the same code base I want a way to give them an error if they include the library. This is to avoid having references all over the place to the library.
For example if they do something like this:
#include "cool_library.h"
they get an error saying:
do not include directly cool_library.h, instead use the cool_library_wrapper class
is this possible? I'm using GNU GCC
Since you're using gcc, you can use the #include_next feature of the preprocessor: Create a header with the same name as the 3rd party's in a directory that will have higher precedence when looking for header files. In your version of the header use something like
#if WRAPPER_HEADER_HAS_BEEN_INCLUDED
# include_next <cool_library.h>
#else
# error ...
#endif
You could use a #error preprocessor directive within a #ifndef block.
For example in the orginal .h file have this:
#ifndef COOL_LIBRARY_WRAPPER_CLASS_INCLUDED
#error "do not include this file directly
#endif
And in the wrapper class's header file do this:
#define COOL_LIBRARY_WRAPPER_CLASS_INCLUDED
This would only be possible if you're okay with modifying the cool_library.h file. You could do something like:
cool_library.h
#ifndef INCLUDED_FROM_COOL_LIBRARY_WRAPPER
#error do not include directly cool_library.h, instead use the cool_library_wrapper class
#endif
.. remainder of original cool_library.h
cool_library_wrapper.h
#define INCLUDED_FROM_COOL_LIBRARY_WRAPPER
#include "cool_library.h"
... your wrapper
#undef INCLUDED_FROM_COOL_LIBRARY_WRAPPER
Of course, you still can't prevent your coworkers from defining INCLUDED_FROM_COOL_LIBRARY_WRAPPER themselves and including the original header file. This is a social problem that does not have a technical solution.
If you usually include some project-wide headers you could check for the presence of the include guard from the third-party header, e.g.
// third_party.h
#ifndef THIRD_PARTY_H
#define THIRD_PARTY_H
...
and
// your_project_wide.h
...
#ifdef THIRD_PARTY_H
#warning "Please include "cool_library.h"
#endif
...
Caveats here: #warning is a gcc extension, and all this relies on the external dependencies being included before your project headers (which you might not want to do).
Don't put <cool_library.h> in the normal build include path. You can either use special CFLAGS for your wrapper to give it access or access it with a more explicit path like <vendor/xyz/cool_library.h> from some higher-level include path.
Another path-based approach would be to put a local <cool_library.h> earlier in the include path and use the #ifdef/#error approach above. If the magic define is present then the stub header can use the more explicit path to pick up the real header. (Some compilers have a hack to continue the search path if you include something named exactly the same thing as the header that's being read)