I beg your pardon if this question has been already answered, but I have been trying to implement precompiled headers in my game engine with no success so far.
My precompiled header is called UtilBase.h:
#pragma once
#if !defined(NF3D_UTIL_BASE_H)
#define NF3D_UTIL_BASE_H
// This is a precompiled header.
#pragma message("Compiling precompiled header.")
// Include engine specific files.
#include <Utilities\Platform\Types.h>
// Include external header files (STL, Win32 API, Direct3D 11, etc)
// There are some typedefs here:
typedef __int32 int32; // And so on.
#endif
Although this is against the standards, I included UtilBase.h in other headers because I need access to some of its contents. It is also included in all .cpp files, first line, from the current project (the solution has two projects).
I need it in some headers because it stores some typedefs that are used in function declarations. For example, I have some file called Window.h:
#pragma once // And include guards that are omitted here
int32 NF3DCreateWindow();
The associated source file is called UtilBase.cpp and has only one line of code:
#include <Utilities\UtilBase.h>
The project has been set up correctly in my opinion:
for all platforms and configurations.
UtilBase.cpp has this setting:
However, when I compile I get this error:
1>Source Files\Utilities\UtilBase.cpp(2): error C2857: '#include' statement specified with the /YcD:\New Frontiers\NewFrontiers3D\Header Files\Utilities\UtilBase.h command-line option was not found in the source file
which points to the only line in UtilBase.cpp (#include <Utilities\UtilBase.h>).
Why does this happen and what can I do to make it work? I will gladly send any further information about this scenario. Thank you very much in advance.
Finally made it! For anybody in my situation here is what I did: in project settings, Precompiled Header File tag, I added $(ProjDir)\Header Files\Utilities\UtilBase.h and it was evaluated to the full path of the file. The correct way is to simply add the file: Utilities\UtilBase.h and that's it.
Thank you for your support.
try #ifndef instead of #if !defined
Related
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.)
My app is working correctly, but I'm trying to clear up something. When I include the precompile header in my source files, I get the following happen.
Basically the first line is underlined as if there is a problem with it, so I have to include it again underneath, with the correct path... but I need both or it wont compile.
Any ideas?
The Visual Studio uses precompiled header only if the name matches (the name is not case-sensitive). Let say, a precompiled header name StdAfx.h is set in your project, so only when a code contains #include "stdafx.h" then is precompiled header used.
The #include "..\stdafx.h" is not recognized as the precompiled header even though it is the real location.
You need to add an include path to the location of stdafx.h into your project settings and then the header #include "stdafx.h" will be work correctly.
Another common issue with a precompiled header is that the include directive is in a header. It should be always in the source file (.ccp).
I have a precompiled header that contains includes for various 3rd party libraries, e.g.:
#ifndef PRECOMPILED_H
#define PRECOMPILED_H
#include "booststuff.h"
#include "luastuff.h"
#endif
Where booststuff.h and luastuff.h are header files in my project that just include various boost / lua related things and set up some typedefs / usings / namespace aliases.
I set up the precompiled header in the usual way inside visual studio (2012), and use the force include option to include it in every cpp file.
In the cpp files, I've also been fairly careful to #include "booststuff.h" where I actually use it as well (I sometimes disable precompiled headers to test this). However, I've been wondering lately whether that's a good idea. So:
Does anything bad happen if I include a file again that's already included in the precompiled header (I don't see why it would, but I've seen things about headers having to be included "in the same order", and not really understood what they were on about)?
Does it affect Intellisense (unusably slow with a fairly small project)? I'd be happy to give up some portability for better Intellisense since I currently have no desire to switch platforms.
If each include file has #pragma once in it, the compiler will completely skip reading the file on the second and subsequent attempts to include it. It isn't stated explicitly but I assume the precompiled header tracks this information as well.
I've inherited some code that did something like this,
Header: HeaderFile.h
#ifndef HEADERFILE_H
#define HEADERFILE_H
#ifndef HEADERFILE_PCH_H
#include<LibStuff>
#include<LibStuff2>
#include<LibStuff3>
#include<LibStuff4>
#include<LibStuff5>
#endif
#include "FilesInProject"
Class A
{
//Code
};
#endif
Cpp: HeaderFile.cpp
#include "HeaderFile_pch.h" //(1)
#include "HeaderFile.h"
//More code
I understand what a precompiled header is for and what the code is doing here (sort of). When I copy these files into my project, this is so I can update deprecated code but not effect the original project, VS2010 chocks on line (1). VS2010 Saying it can't find that file.
I've gone between the two projects and I can't find any differences in settings.
What am I missing and why is it okay to imbed PCH's in headers like this instead of actually moving them to a file called HeaderFile_pch.h. Is this some kind of macro hack?
For starters, there is no such file as Headerfile_pch.h either in the samples you provided above nor likely on your local fs.
Visual C++ allows you to define several ways of setting up precompiled header files. The most common is to enable it for ALL source files at the project configuration level, Under Configuration Properties/C++/Precompiled Headers, setting "Precompiled Header", select "Use". The same location, setting "Precompiled Header File", is usually "stdafx.h" but can be anything you choose. All files will get this setting (thus the configuration at the project level) EXCEPT....
One file is responsible for generating the PCH file. That file is typically the stdafx.cpp file in your project, but again, it can be whatever single source you desire. Most just setup a dummy cpp file that has one thing in it: #include "myheader.h" (duh).. Configuring Precompiled Headers for THAT ONE FILE, switch from "Use" to "Create". This ensures that if the prime-header for PCH gets out of synch that source file is recompiled first to regenerate the PCH data file before the others are kicked off.
The one attribute of this that is absolutely mandatory: that include header (myheader.h or whatever you're calling it) must be the first include in any source file you're compiling that is participating in using pch including (hopefully obviously) the file you specified as the "generator" (the one marked as "Create" in the prior paragraph).
Lastly, you can disable pch on a file-by-file basis if this is a problem due to unusual conditions in your build environment (i.e. 3rd party headers that do stupid things).
There are other ways of configuring PCH setting in Visual Studio, but this is by far the most common.
I have a class with two possible implementations, depending on a preprocessor switch. The way I have handled this is to create "src\CompSwitch1\class.h" and "src\CompSwitch2\class.h". In my standard include file, I use
#ifdef CompSwitch1
#include "CompSwitch1\class.h"
#elif CompSwitch2
#include "CompSwitch2\class.h"
#else
#error "Specify CompSwitch1 or CompSwitch2"
#endif
This works for most of my classes that need two versions. However, on one of them, I get a linker error (lnk2019: unresolved external symbol). I'm using MS Visual Studio 2005 and 2008, and it appears on both of them.
At the top of the .h file, I test against the preprocessor option.
Also, although I only referenced the .h file for brevity, there is also a .cpp file for each of these, in the appropriate directory.
It sounds like you might have included the header file for one of the classes, but linked the object file for for the other one, or neither
it should really be #ELIF DEFINED( CompSwitch2 ) really. Otherwise you are assuming "CompSwitch2" has been defined with a value of 1 ...
Try to put in the cpp implementation files after they include your header the following preprocessor line(s):
//in compswitch1.cpp
#ifndef CompSwitch1
# error "inconsistent header included"
#endif
//in compswitch2.cpp
#ifndef CompSwitch2
# error "inconsistent header included"
#endif
If you compile wrong header/cpp pairs you should get at least compilation errors and not linking errors. There are much easier to identify/fix ;)
Another possibility is that the cpp-files are not included into compilation at all. Put a message pragma inside the cpp file to see if they get compiled at all:
#pragma message( "Compiling " __FILE__ )
Or try to identify in the build directory if there object files created, which relate to cpp-compilation units.
Hope that helps,
Ovanes
You can use preprocessed cpp file (stage where all includes and macros are expanded).
In VS 2008 right click on your file in Solution Explorer->Properties->C++->Preprocessor and set "Generate Preprocessed File" set "With Line Numbers (/P)".
After that right click again your file and choose "Compile". File with extension "i") (e.g. main.i) will be created in the same directory where cpp resides. Open it and see which include file is included.
This method is very handful to solve hard compilation problems (e.g. some macro from system header files replaces something in your code).