First Time Using PCH, getting Linker Tool Error - c++

I'm a pretty novice programmer, just learning a little bit of c, but I always did it on Linux with gcc and Vim but decided to try using visual studio and I'm getting LNK2005 and LNK1169 errors, I've tried looking up the errors and how to fix them and properly use PCH because I think it would be useful to learn even if my programs are too small to make use of it.
From my understanding I need to #include "stdafx.h" at the top of my source file (called 'helloworld.c') I haven't touched 'stdafx.c' from the default that came when I create the project, I created a header file called 'bitwise.h' and it has one function in it called 'int bw()' I then have 'stdafx.h' and all I added was #include "bitwise.h" In my headerbitwise.h ive tried to include #include "stdafx.h" #include "stdafx.c" #include <stdio.h> and even not including anything. all of these break my program. The only way I can get it to compile is if i comment out//bw(); then my program compiles just fine.
here are the files that I think may be the culprit:
helloworld.c
#include "stdafx.h"
int main()
{
printf("\tHello World!\n");
getchar();
bw(); //If this line is commented out everything works just Honky-Dory
getchar();
return 0;
}
bitwise.h
#include "stdafx.h" //I've tried lots of diffrent lines here, nothing works
int bw()
{
int a = 1;
int x;
for (x = 0; x < 7; x++)
{
printf("\nNumber is Shifted By %i Bits: %i", x, a << x);
}
getchar();
return 0;
}
stdafx.c
// stdafx.cpp : source file that includes just the standard includes
// $safeprojectname$.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file
stdafx.h
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#include "bitwise.h"
#include <stdio.h>
#include <tchar.h>
// TODO: reference additional headers your program requires here

This is not much about PCH. You have mixed up header (.h) and implementation (.c) files. What you need to do is split implementation and declaration. You should do following:
rename your bitwise.h to bitwise.c since this is your implementation file, not a header!
create a new file bitwise.h and put only declaration there, it should look like this:
#pragma once
int bw();
Your project should be able to compile after that.
Please also note PCH file should contain includes that are infrequently changed, which is probably not your case since you are including also bitwise.h. You might want to remove this include from stdafx.h and include it into your helloworld.c.
And just a side note, during learning C do not think of including .c file via #include! If it fixes some of your compilation errors, your project design is probably very wrong.

Nitpick: You should not need to #include stdafx.h in bitwise.h, though it should still have a #pragma once.
Your code for bw() should still be in a separate bitwise.c file, not in the header. I think you may be confusing precompiled headers with function inlining? Right now, your code for bw is being compiled into what is supposed to be the dummy stdafx object, and again in the main object, and causing a conflict when linking.
Also, did you remember to mark your stdafx.h as the precompiled header (/Yu), and the stdafx.cpp as... whatever /Yc is supposed to mean? Make sure both options are set for all project configurations for both files in Properties -> C/C++ -> Precompiled Headers.

Related

How does VS Intellisense find definitions from stdafx.h while editing a header file?

This is an annoying hole in my knowledge and I can't seem to find an answer.
I understand why it works during compilation (the header is never compiled in isolation, so stdafx.h will have already been included), but not why it works while editing.
Say I have the following files:
stdafx.h
#pragma once
#include <string>
MyFunction.h
#pragma once
void MyFunction( std::string Text );
MyFunction.cpp
#include "stdafx.h"
#include "MyFunction.h"
void MyFunction( std::string Text )
{
// implementation here
}
When I'm editing MyFunction.h, how does Intellisense find std::string for the purpose of auto-complete, not showing it as undefined, etc?
I ask partly out of curiosity and partly because if I don't know the mechanism then I can't know if I'm at risk of breaking it or how to fix it when I do. I've seen it break a number of times, causing most of the header in question to be marked as an error, and then at some point it either just fixes itself or I accept it isn't coming back and add a few extra strategic includes into the header.
Just to repeat: I'm not asking how std::string is found during compilation, I'm asking how it's found when editing the header file.
How does VS Intellisense find definitions from stdafx.h while editing
a header file?
After some tests in different versions of VS(VS2012~VS2019), I think what you experienced is the expected behavior about VS intellisense.
To answer your original question How does VS Intellisense find...:
When editing in MyFunction.h, I think the Intellisense find the definitions in stdafx.h by reading the data or info(#include statements) in MyFunction.cpp file.
That is to say: When I have a.h, b.h and b.cpp in current project, if b.cpp has statements #include "a.h" and #include "b.h", then Intellisense search the definitions in these three files. So even your move the #include <string> from stdafx.h to MyFunction.cpp file, the MyFunction.h can also recognize the definitions.
So if one test.h is referenced(included) by one test.cpp file, and this test.cpp file also use #include to reference(include) test2.h, test3.h... When editing test.h, Intellisense will automatically search definitions in test.cpp, test2.h, test3.h... In my opinion, that's how VS Intellisense works in this scenario. (Same behavior in VS2012, VS2015, VS2017, VS2019 in my machine)
Hope it helps to resolve your puzzle and if I misunderstand anything, please feel free to correct me :)

Precompiled header problems

//........Project for ABC.dll
//ABC.h
#pragma once
class ABC{
public:
ABC(){}
private:
std::vector<int> m_vector;
};
//ABC.cpp
#include "Stdafx.h"
#include "ABC.h"
//Stdafx.h
#include <vector>
Till today, I've skipped #include <standard-lib.h> in my headers by delegating it to Stdafx.h header.
It's never been a problem when I worked in a single project file.
Now I'm trying to add a new DLL project to gather shared codes in one project.
It compiled well and generated ABC.dll too.
Here's a problem. When another project that uses ABC.dll show compile error saying that std::vector does not exist.
//...........Another Project using ABC.dll
int main(){
ABC abc;
}
Error C2039 'vector': is not a member of 'std'
To get it working, I had to include all the libraries in the consumer's Stdafx.h too.
Maybe I've been misusing the precompiled header.
I want to know whether the way I've been doing with the PCH was wrong or right.
If it's wrong, I would appreciate it if you suggest right ways of using PCH.
Thanks.
Your problems have nothing to do with precompiled headers. A good practice is to include all the stuff directly used by current file. This will prevent changes in includes of one header file from potentially requiring changes in includes in files that are using this header. vector needs to be included in ABC.h because it is directly used there. Otherwise you'll end up with endless struggling to figure out which headers needs to be included when including this particular library header.

Copy and pasting header files in to main.cpp produces redefinition error

#include <curses.h>
#include <Windows.h>
int main(){
return -2;
}
When I compile this, there is no error. If I swap the positions of #include <curses.h> and #include <Windows.h> then I get an error that MOUSE_MOVED is redefined (once in curses.h and the other in wincon.h - which is included by Windows.h). I'm guessing that wincon.h has a line similar to:
#ifndef MOUSE_MOVED
#define MOUSE_MOVED 2
#endif
but curses.h does not, which is why it depends on which way the include directives are ordered. On the other hand, having a look through wincon.h I couldn't see such a conditional statement, but I find it's pretty hard to keep track of what's being defined in header files when there are few comments.
My main concern though, is that when curses.h is included before Windows.h, it compiles fine. To see why this might be, I copied and pasted all of the contents of curses.h and put it in the same location as #include <curses.h>, I did the same with Windows.h and then wincon.h. Surprisingly to me, this brought back the error with MOUSE_MOVED again. All I did was copy and paste the contents of the headers, is this not what the preprocessor does anyway? Just replace the include directives with the contents of the header? Why would doing such a thing bring back the error? (MinGW g++ 6.1.0)
(I can't paste all of the contents of curses.h and Windows.h, but a small download for curses can be found here if needed)

Comprehension issue: Precompiled headers & include usage

I got a comprehension issue about precompiled headers, and the usage of the #include directive.
So I got my "stdafx.h" here and include there for example vector, iostream and string. The associated "stdafx.cpp" only includes the "stdafx.h", that's clear.
So if I design my own header file that uses for example "code" that's in vector or iostream, I have to include the header file because the compiler doesn't know the declarations at that time. So why are some posts here (include stdafx.h in header or source file?) saying, it's not good to include the "stdafx.h" in other header files even if this file includes the needed declarations of e.g. vectors? So basically it wouldn't matter to include directly a vector or the precompiled header file, both do the same thing.
I know of course, that I don't have to include a header file in another header file if the associated source file includes the needed header file, because the declarations are known at that time. Well, that only works if the header file is included somewhere.
So my question is: Should I avoid including the precompiled header file in any source file and why? And I am a bit confused, because I'm reading contradictory expressions on the web that I shouldn't include anything in header files anyway, or is it O.K. to include in header files?
So what's right now?
This will be a bit of a blanket statement with intent. The typical setup for PCH in a Visual Studio project follows this general design, and is worth reviewing. That said:
Design your header files as if there is no PCH master-header.
Never build include-order dependencies in your headers that you expect the including source files will fulfill prior to your headers.
The PCH master-header notwithstanding (I'll get to that in a moment), always include your custom headers before standard headers in your source files. This makes your custom header is more likely to be properly defined and not reliant on the including source file's previous inclusion of some standard header file.
Always set up appropriate include guards or pragmas to avoid multiple inclusion. They're critical for this to work correctly.
The PCH master-header is not to be included in your header files. When designing your headers, do so with the intent that everything needed (and only that which is needed) by the header to compile is included. If an including source file needs additional includes for its implementation, it can pull them in as needed after your header.
The following is an example of how I would setup a project that uses multiple standard headers in both the .h and .cpp files.
myobject.h
#ifndef MYAPP_MYOBJECT_H
#define MYAPP_MYOBJECT_H
// we're using std::map and std::string here, so..
#include <map>
#include <string>
class MyObject
{
// some code
private:
std::map<std::string, unsigned int> mymap;
};
#endif
Note the above header should compile in whatever .cpp it is included, with or without PCH being used. On to the source file...
myobject.cpp
// apart from myobject.h, we also need some other standard stuff...
#include "myobject.h"
#include <iostream>
#include <fstream>
#include <algorithm>
#include <numeric>
// code, etc...
Note myobject.h does not expect you to include something it relies on. It isn't using <iostream> or <algorithm>, etc. in the header; we're using it here.
That is a typical setup with no PCH. Now we add the PCH master
Adding the PCH Master Header
So how do we set up the PCH master-header to turbo-charge this thing? For the sake of this answer, I'm only dealing with pulling in standard headers and 3rd-party library headers that will not undergo change with the project development. You're not going to be editing <map> or <iostream> (and if you are, get your head examined). Anyway...
See this answer for how a PCH is typically configured in Visual Studio. It shows how one file (usually stdafx.cpp) is responsible for generating the PCH, the rest of your source files then use said-PCH by including stdafx.h.
Decide what goes in the PCH. As a general rule, that is how your PCH should be configured. Put non-volatile stuff in there, and leave the rest for the regular source includes. We're using a number of system headers, and those are going to be our choices for our PCH master.
Ensure each source file participating in the PCH turbo-mode is including the PCH master-header first, as described in the linked answer from (1).
So, first, the PCH master header:
stdafx.h
#ifndef MYAPP_STDAFX_H
#define MYAPP_STDAFX_H
// MS has other stuff here. keep what is needed
#include <algorithm>
#include <numeric>
#include <iostream>
#include <fstream>
#include <map>
#include <string>
#endif
Finally, the source files configured to use this then do this. The minimal change needed is:
UPDATED: myobject.cpp
#include "stdafx.h" // <=== only addition
#include "myobject.h"
#include <iostream>
#include <fstream>
#include <algorithm>
#include <numeric>
// code, etc...
Note I said minimal. In reality, none of those standard headers need appear in the .cpp anymore, as the PCH master is pulling them in. In other words, you can do this:
UPDATED: myobject.cpp
#include "stdafx.h"
#include "myobject.h"
// code, etc...
Whether you choose to or not is up to you. I prefer to keep them. Yes, it can lengthen the preprocessor phase for the source file as it pulls in the headers, runs into the include-guards, and throws everything away until the final #endif. If your platform supports #pragma once (and VS does) that becomes a near no-op.
But make no mistake: The most important part of all of this is the header myobject.h was not changed at all, and does not include, or know about, the PCH master header. It shouldn't have to, and should not be built so it has to.
Precompiled headers are a method to shorten the build time. The idea is that the compiler could "precompile" declarations and definitions in the header and not have to parse them again.
With the speed of todays computers, the precompilation is only significant for huge projects. These are projects with a minimum of over 50k lines of code. The definition of "signification" is usually tens of minutes to build.
There are many issues surrounding Microsoft's stdafx.h. In my experience, the effort and time spent with discovering and resolving the issues, makes this feature more of a hassle for smaller project sizes. I have my build set up so most of the time, I am compiling only a few files; the files that don't change are not compiled. Thus, I don't see any huge impact or benefit to the precompiled header.
When using the precompiled header feature, every .cpp file must begin by including the stdafx.h header. If it does not, a compiler error results. So there is no point in putting the include in some header file. That header file cannot be included unless the stdafx.h has already been included first.

Getting started with PCH in a VC++ project

I'm working on a VC++ project in VS 2012 that takes about 8-10 minutes for a full compile. I know PCH can speedup compile times by upto 10x. I have currently disabled PCH in my project and I'm including header files where they are needed. How do I get started with PCH? I've looked everywhere for "how to" guides but all I got is the docs.
I'm assuming I'll have to :
Configure my project for PCH, creating a blank PCH header file
Collect headers from every .cpp file and place it into the PCH header file
Modify every file removing all header imports
Recompile and hope that nothing goes wrong ;)
How do I get started with this (specifically #1)? Have you modified a project to use PCH and what are the stumbling blocks or common problems/issues therein? Can PCH cause any problems or is it just the same compile-time/runtime behaviour as normal includes? Is there a tool to automate the process or do I have to go thru 500 .cpp files by hand and modify it to use PCH?
And last but not least, what is the compilation time speedup I can expect with PCH? Is it 2x-10x? Or would it just go like 30% faster? (which does not justify the time involved)
After configuring my project to use PCH, full-compile times were down to half, and incremental builds occurred almost instantly. PCH is a very effective way to speedup compile times, and I highly recommend it.
Althouh dsharlet mentions many important points, he skips some crucial steps that I had to eventually figure out. So here is the complete guide to configuring your project to use PCH:
Getting started with PCH in a VC++ project
Backup your src dir and any other directories that contain source code ... (you'll need this in case anything goes wrong)
Create 2 files in your project, Globals.cpp and Globals.h .. (choose any name but stick to it)
Right click Globals.cpp and open Properties, choose Configuration > All configurations
Go to C/C++ | Precompiled Header, and fill these in:
Precompiled Header : Create (/Yc)
Precompiled Header File : Globals.h
Open Globals.cpp and add this one line in, and nothing more: #include "Globals.h"
Right click your VC++ project and open Properties, choose Configuration > All configurations
Go to C/C++ | Precompiled Header, and fill these in:
Precompiled Header : Use (/Yu)
Precompiled Header File : Globals.h
Open all the .h and .cpp files in your project, and add this at the very top: #include "Globals.h". If you DONOT want to include every file manually, you can use the Force Include /FI[name].
Open Globals.h and add the following in: (its very important you have #pragma once at the top)
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stddef.h>
#include <memory>
#include <string.h>
#include <limits.h>
#include <float.h>
#include <time.h>
#include <ctype.h>
#include <wchar.h>
#include <wctype.h>
#include <malloc.h>
#include <locale.h>
#include <math.h>
// Windows SDK
#define _WIN32_WINNT 0x0501 // _WIN32_WINNT_WINXP
#include <SDKDDKVer.h>
// Windows API
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
These includes are typical candidates for your PCH file
Remove the includes that you're not using
Go through your project and collect any more header files that do not change often
Using find and replace, search for each of the #include's in your PCH file, and remove them from all the .h and .cpp files in your project.
Do a full compile and ensure everything is working okay. Here are some solutions for common problems you'll encounter:
PCH file includes itself:
Your PCH file is including a header that includes the PCH header file again, creating a kind of circular dependency. Double click the error to take you to the offending file, and simply remove the line that says #include "Globals.h"
Undefined symbol X
Although all your project files can include the PCH header, the files included inside the PCH header cannot include the PCH header! (as stated above) so you'll need to add back any imports that were previously in the file. (diff the file with the backup version)
Cannot find symbol logf
Sometimes the global PCH file does not behave as expected, and breaks compiling with crazy errors that are impossible to solve. You can then turn off PCH for individual source code files.
Right click your .cpp file and open Properties, choose Configuration > All configurations
Go to C/C++ | Precompiled Header, and fill these in:
Precompiled Header : Not Using Precompiled Headers
Remove the line #include "Globals.h" in your .cpp file
Add back whatever imports the file originally had. (diff the file with the backup version)
Here's how I use PCH with decent results:
Go to the project properties, C/C++|PCH set Precompiled Header option to 'Use'. Set Precompiled Header File to something you want.
Go to the properties of a cpp file you want to be the PCH, and set the Precompiled Header option to 'Create' (it will have defaulted to 'Use' from the project property setting).
Include the pch header in all your cpp files in the project (basically, the ones that have 'Use' set for the Precompiled Header option). I suppose you could turn off 'Use' for some cpp files in the project instead of add the include for the PCH, but I've never tried that...
At this point, the project should still build and behave exactly as it used to, but there may not be any real improvement in compile time. Now, you'll need to move some of your #include "...h" to the PCH header file (and delete the includes of those files from elsewhere in the project). The includes that you should move to the PCH header should be headers that are included in many files, but change infrequently. Examples: STL headers, windows.h, core functionality headers from your project, etc.
Once PCH is set up, it should be transparent. It's basically just helping the compiler cache some intermediate compilation data. In other words, if you turned off PCH in your project, everything should still build exactly as it would have with PCH turned on (except slower!)
The speedup entirely depends on how much code is moved into the PCH (how much included code from headers is moved from arbitrary cpp files to the PCH header). I've seen multiple times improvement, but haven't benchmarked it precisely. I definitely felt like it was worth doing when I've gone through the trouble to use PCH on a big project.