28
votes

With "Show all files" option on in VS, i added a folder and created a new class in that folder. Since i'm using precompiled headers i also need to include the stdafx.h that's in the root directory relative to the new class file.

In my cpp file i have

#include "..\stdafx.h"

Yet I get the following error:

error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "stdafx.h"' to your source?

My understanding is, that the .. should instruct the compiler to go one directory level up ?

9

9 Answers

19
votes

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". All files will get this setting (thus the configuration at the project) EXCEPT....

One file is responsible for generating the PCH file. That file is typically the stdafx.cpp file in your project, and it typically has nothing in it except #include "stdafx.h". 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 stdafx.cpp is ALWAYS compiled first to regenerate the PCH data file. There are other ways of configuring PCH setting in Visual Studio, but this is the most common.

That being said, your problem is definitely irritating. The filename used to prime the PCH system and specified on both the "Use..." and "Create..." setting above MUST MATCH THE TEXT IN YOUR #include EXACTLY.

Therefore, it is highly likely you can address your problem by adding ".." to your project include directories and removing the ".." from your #include statement. you could also change it at the project-configuration level to be "..\stdafx.h" as the through-header, but that might be a problem if you have source files in multiple folders hierarchically.

Oh, and if it wasn't clear to you while perusing the PCH configuration settings, if you do NOT want to use PCH for any specific source file (and there are reasons not to sometimes) you can turn it OFF for specific source files, otherwise be sure to always have #include "your-pch-include-file.h" at the head of every source file (c/cpp,etc).

Hope you catch a break.

16
votes

I generally also like to have a hierarchical order in my projects, and I've found there are two simple ways to include a precompiled header:

Either

  1. Put the directory where stdafx.h lies into the compiler's include directories.

    (Properties - VC++ Directories - Include Directories: Add $(ProjectDir))

Or

  1. If there aren't too many subdirectories, a simple way to circumvent the error message is like this:

    • Put an stdafx.h file into each of your subdirectories which only includes the top-level stdafx.h:
      #include "..\stdafx.h"
    • Write #include "stdafx.h" as first line of all source files in your subdirectories, instead of including the top-level file there.

This way, all your code files use the same precompiled header file, and there is no other complicated setup to do.

13
votes

It's interesting that the trick that I use isn't in the answers:

  1. Create stdafx.h and stdafx.cpp in the root folder of the project.
  2. Go to project properties -> precompiled headers. Change to "use".
  3. Go to stdafx.cpp, right-click properties -> precompiled headers. Change to "create".
  4. Go to project properties -> advanced; change "Force include files" to stdafx.h;%(ForcedIncludeFiles)

Don't change any CPP file; keep your header files as they are. Build as-is.

No typing, no RSI, no hassle with include paths, no other pain and misery. And the beauty is that it will still work when you move your solution to another platform. Awesome.

3
votes

You can adjust the precompiled header settings on a per-file basis.

  1. In Solution Explorer right click on the .cpp file, select "Properties".
  2. I'd strongly recommend selecting "All Configurations" in the Configuration drop down List item.
  3. Browse to "C/C++" - "Precompiled Headers".
  4. Adjust the "Precompiled Header File" from "stdafx.h" to whatever you need (in your case for example "../stdafx.h").

Note this is tedious and error prone since it's done on a per-file basis, and future developers adding files to your project will have to follow the same steps. If they don't they will be faced with warnings and errors such as:

  • warning C4627: '#include "<path>"': skipped when looking for precompiled header use.

and

  • fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "stdafx.h"' to your source?

which don't give much indication as to this or any other approach.

I guess they'll eventually turn to StackOverflow and end up here... Hello, thanks for reading.

On that basis, it's worth going with alternatives, such as putting $(ProjectDir) on the C++ Include path (under C++\General) but then that can cause confusion when including other header files.

2
votes

PCH files are wierd, and even moreso in Visual Studio. When compiling a .cpp file that uses a PCH, VS expects the first non-comment/whitespace text to be #include "PCH_NAME_HERE". The PCH_NAME_HERE is exactly the PCH's name. No directories, nothing. Just the PCH's name as specified in the compiler options.

If you're going to do this directory fudging, then you need to modify your compiler settings so that the directory where the PCH is is in the directory search path. That way, you don't need to have the ..\ part.

1
votes

I would suggest to use:

$(ProjectDir)/pch/my_pch.h

as "Precompiled Header File"
and "Advanced > Force Include File"

This will auto include pch for your .cpp files in the beginning, so nothing needs to be changed in the .cpp files.

And this is better than changing the include directory, because sometimes you might have multiple pch files in the include directories, and then you can't tell which one has been used.

0
votes

The cause of the confusion is that Visual Studio treats the include directive that includes the precompiled header differently to other include directives. Specifically it does not look for the precompiled header using the normal path lookup approach, instead it simply attempts to match the include directive to that defined in the project configuration by simple string comparison.

Precompiler header configuration is set gobally but can be overridden per file. The normal global config (accessed via Project Properties -> Configuration Properties -> C/C++ -> Precompiled Headers) is:

Precompiled Header: Use (/Yu)
Precompiled Header File: stdafx.h
Precompiled Header Output File: $(IntDir)$(TargetName).pch

This configuration is applied to all files in the project by default. However the config for stdafx.cpp is set at the file level and overrides the Precompiled Header value to:

Precompiled Header: Create (/Yuc)

The effect of this is that for any source file configured to use the precompiled header (which by default is all of them except stdafx.cpp) VS will look for an include directive that matches the configured Precompiled Header File value. e.g.

#include "stdafx.h"

Because the check uses a simple string comparison instead of any kind of directory search, then (irrespective of the location of the source file relative to the project root directory or the location of the stdafx.h file) the path and filename used in the include directive must match exactly that used by the project's Precompiled Header File configuration setting. The unexpected side effect of this is that if you have a project subdirectory containing various source files, in those files you do not need to reference the stdafx.h file using a relative path like ..\stdafx.h (and if you do VS will raise an error stating that it encountered the end of file while looking for the precompiled header).

Just use the unadorned #include "stdafx.h" and it will work fine because VS will then recognise this as the directive to use the precompiled header, and it already knows where the correct precompiled header is because of stdafx.cpp Precompiled Header configuration being set to "Create (/Yc)".

-1
votes

If .cpp and .h files of your project live in different subdirectories (not plainly in the directory of the project), it would be a good coding style to use include paths relative to the solution directory (if you don't use a dedicated include directory). Particularly if you have multiple projects in a solution and need to share include files (e.g. for interoperability between projects, e.g. an .exe and a .dll).

To refactor your project you need to do the following:

  1. In each project specify additional include directory $(SolutionDir) : right-click on project, click "Properties", go to "Configuration Properties"->"C/C++"->"General" (to do this for all configurations at once, select "All Configurations" from the "Configuration" dropdown)
  2. Go to "C/C++"->"Precompiled Headers" and change "Precompiled Header File" value to the path relative to the solution directory, e.g. PROJECT_NAME/stdafx.h
  3. In your .cpp files include "PROJECT_NAME/stdafx.h", instead of just "stdafx.h"
  4. In your .h and .cpp files, when including something, use path as "PROJECT_NAME/dir1/dir2/file.h", except when including file from the same directory
-4
votes

Using quotes means it is a header file you own use <> means it is a system header file if I am not mistaken just use #include <stdafx.h> and let the compiler find it