-2

I understand that the purpose of precompiled header is about to speed up compilation process by using object file that was already compiled once and link it to actual project. But what I do not uderstand Is why should I explicitly enforce Visual Studio to use stdafx.h (Project Properities -> C/C++ -> Precompiled Headers -> Precompiled Header)? Why isn't #include "stdafx.h" not enough?

Wakan Tanka
  • 7,542
  • 16
  • 69
  • 122

2 Answers2

3

Why isn't #include "stdafx.h" [...] enough?

Because that is just a standard C++ preprocessor directive.* It's no different from #include <string> as far as the compiler is concerned. If you need to have additional semantics attached, you have to tell the compiler about it.

Since there appears to be confusion, how Visual Studio implements precompiled headers, here is a link to documentation: Creating Precompiled Header Files.


* Mind you, there's nothing special about the name "stdafx.h", other than it being the default header name used to generate a PCH.

IInspectable
  • 46,945
  • 8
  • 85
  • 181
  • Agreed in my Visual Studio projects the PCH header is not even named `stdafx.h`. Although I use a macro with CMake that specifies the name of the PCH header.. – drescherjm Feb 10 '17 at 20:14
  • Sorry but I do not follow. What additional semantic? Compiler just replaces `#include "stdafx.h"` with the content of `stdafx.h`. From this point I can call functions declared in `stdafx.h` and compiler will not complain. After compilation the `stdafx.obj` file is linked with my project. I do not see the need to explicitly specify something else here. – Wakan Tanka Feb 10 '17 at 20:25
  • @WakanTanka: You have described **standard** semantics. The additional semantics are, that the compiler replaces the `#include` directive with a **pre-processed** and **pre-compiled** version of the header. Besides, header files aren't compilation units. There is no *"stdafx.obj"* file (unless you also provide a *"stdafx.cpp"* file, which you do for PCH's). The .obj file has nothing to do with PCH's, though. – IInspectable Feb 10 '17 at 20:28
  • @IInspectable yes header is not compilation unit you're right, but `stdafx.cpp` is also created automatically in VS so the `stdafx.obj` exists during linking process. Basically what I do not understand is why this process is different from standard compilation/linking. – Wakan Tanka Feb 10 '17 at 20:36
  • @WakanTanka: Because `#include "stdafx.h"` (assuming PCH is enabled and that is the header used to create it) doesn't just expand this header file into the compilation unit. It expands a pre-processed and pro-compiled header file. PCH is a compilation optimization, which takes place prior to linking. PCH's have no effect on linking. If you want to see the **real** PCH that gets expanded, use the [/P (Preprocess to a File)](https://msdn.microsoft.com/en-us/library/8z9z0bx6.aspx) compiler option. – IInspectable Feb 10 '17 at 20:42
  • ... or open the generated .pch file in a text editor. – IInspectable Feb 10 '17 at 20:56
  • 1
    There's nothing that disallows a compiler to use precompiled headers to implement `#include "stdafx.h"`, so long as it behaves the same as the standard C++ preprocessor directive and can fall back to including the file as usual. And no, that's not just theoretical, that's what at least GCC really does. –  Feb 10 '17 at 21:02
  • @hvd: Well, that's GCC. Mostly a best-effort attempt to implement precompiled headers, without breaking anything. In practice, this means, that often times it cannot produce precompiled headers. On the other hand, MSC is way more aggressive, and it needs to be explicitly told to go for it. – IInspectable Feb 10 '17 at 21:13
  • 1
    @IInspectable Your answer suggests that the fact that `#include` is a standard C++ preprocessor directive means that it cannot cause a precompiled header to be used. A counterexample of a real-world compiler where it does exactly that shows that that logic is incorrect. –  Feb 10 '17 at 21:44
  • @hvd: That's not what my answer suggests. My answer explains, why you cannot just use `#include "stdafx.h"` **in Visual Studio** and have it automatically generate a PCH. You keep insisting, that a different question was asked. I'd value if you didn't rip my answer out of context, and have it stand up against a question that was never asked. I answered the question that was asked. – IInspectable Feb 10 '17 at 21:52
  • @IInspectable I think we can agree that the question asks why Visual Studio doesn't use a precompiled header when a `#include "stdafx.h"` directive is seen. To me, that suggests that the real question is why the Visual Studio developers have chosen not to use a precompiled header when a `#include` directive is seen. It didn't even occur to me that to you, it might not suggest that. At any rate, it's nothing worth getting upset over. –  Feb 10 '17 at 22:01
  • @hvd: Microsoft have decided to make this an explicit compiler option due to the feature set they support (some of which require that the developer makes the call whether it's safe or not). Had they opted for the measly *"let's see what I can do"* implementation of GCC, I'm sure they would have made that automatic as well. They went for useful features and **real** performance gains instead, at the expense of making it an explicit choice. – IInspectable Feb 10 '17 at 22:08
2

So called stdafx.h is supposed look as an ordinary header file. There's nothing special about its name. It is not supposed to automatically enable precompiled headers.

The idea is that stdafx.h will be seen as an ordinary header file by any other compiler and/or when you don't what to use precompiler headers in MSVC.

It is you who are supposed to tell the MSVC compiler that you actually want to enable precompiled headers. That's exactly why you have that project setting. And only when you enable precompiled headers, stdafx.h will acquire its special role and will receive special treatment from the compiler. And it is not necessarily stdafx.h. You can assign this special role to any other header by specifying a different name in project settings.

In fact, seeing a reference to AFX in a project that has nothing to do with Microsoft-specific libraries or frameworks would be quite an oddity.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • can you please be more specific what exact special treatment receives `stdafx.h` from compiler? How is it different than classic compilation linking process? – Wakan Tanka Feb 10 '17 at 20:27
  • 1
    @Wakan Tanka: Header precompilation has nothing to do with "linking". It is a completely different process. "Special treatment" that `stdafx.h` receives is basically that: its contents is *precompiled* only once and then used in precompiled form. That's all there is to it. – AnT stands with Russia Feb 10 '17 at 20:35
  • "It is you who are supposed to tell the MSVC compiler that you actually want to enable precompiled headers." Haven't I told it to MSVC when I did `#include "stdafx.h"`? – Wakan Tanka Feb 10 '17 at 20:40
  • @WakanTanka: No. That's no different from writing `#include "myheader.h"`. It's just a header file, with no special meaning. – IInspectable Feb 10 '17 at 20:43
  • Yes I did. I really appreciate that you're trying to help but I still do not follow. I understand that `#include "stdafx.h"` has no special meaning but I do not see the reason why it should. If `stdafx.obj` exists why it cannot be used during link time. I do not see why `stdafx.h` should be threaten differently than any regular header file. There is `stdafx.h` then there is `stdafx.cpp` which includes it and creates `stdafx.obj` from it after compilation and this `stdafx.obj` is linked during linking time. Thus `stdafx.obj` is created only once but linked every-time I recompile my project. – Wakan Tanka Feb 10 '17 at 21:07
  • @WakanTanka: You still haven't understood, that compiling and linking are different phases. Precompiled headers speed up **compilation**, and compilation alone. Visual Studio also implements *incremental linking* as a linker optimization, but that is completely unrelated to precompiled headers. .obj files are linker input. – IInspectable Feb 10 '17 at 21:20
  • @IInspectable Oh, holly s**t it is caused maybe by late hours or too little coffee. Now I get the point. Thank you for your patience. – Wakan Tanka Feb 10 '17 at 21:45
  • @Wakan Tanka: `stdafx.obj` plays no role in this process whatsoever. `stdafx.cpp` and `stdafx.obj` are normally just empty *dummy* files. Precompiled header data is stored (and read from) `.pch` file at compilation stage. `stdafx.cpp` is nothing more than a dummy file that *triggers* creation of `.pch` file. It serves no other role but triggering the creation of `.pch`. You don't actually need a separate `stdafx.cpp` at all, since you can appoint any other (one of yours) `.cpp` file as a trigger for `.pch` creation. This file is always compiled first. – AnT stands with Russia Feb 10 '17 at 21:54