Is #include inside stdafx.h a bad idea?

  • Thread starter Chris Shearer Cooper
  • Start date
C

Chris Shearer Cooper

In our Visual Studio 2005 application, we have several of our application's
H files that are #included into stdafx.h.

What is odd, is that when we change those application H files, VS2005
doesn't trigger a rebuild of the entire app (or of anything, for that
matter).

Is this a setting somewhere?

Thanks!
Chris
 
V

Victor Bazarov

Chris said:
In our Visual Studio 2005 application, we have several of our
application's H files that are #included into stdafx.h.

I thought that it is exactly what the precompiled headers are for.
What is odd, is that when we change those application H files, VS2005
doesn't trigger a rebuild of the entire app (or of anything, for that
matter).

Is this a setting somewhere?

Aren't you supposed to have 'stdafx.cpp' added to your project as
well as 'stdafx.h'? That's what should trigger re-creation of the
precompiled headers and further recompilation of the modules...

Or just turn them precompiled headers off (are they on?)

V
 
N

Nathan Mates

In our Visual Studio 2005 application, we have several of our application's
H files that are #included into stdafx.h.
What is odd, is that when we change those application H files, VS2005
doesn't trigger a rebuild of the entire app (or of anything, for that
matter).

I've seen a lot of projects not compile every dependent cpp file
when Resource.h is changed. Is this the kind of header file you're
changing? Btw, you can rename your precompiled headers to something
that's a lot more meaningful - no need to keep up with MS-DOS 8.3
filenames or a bad keyboard splattering that became a (lousy)
standard.

Nathan Mates
 
C

Chris Shearer Cooper

Yeah ... and I was wondering where the setting was, that said "don't rebuild
just because resource.h changed" ... but no, the header files I'm changing
are not resource.h, they contain real live C++ class definitions ...
 
D

Doug Harrison [MVP]

Yeah ... and I was wondering where the setting was, that said "don't rebuild
just because resource.h changed" ...

That setting is expressed in the comment at the very top of the file:

//{{NO_DEPENDENCIES}}
but no, the header files I'm changing
are not resource.h, they contain real live C++ class definitions ...

Where are the files located, and what are their names? VC++ has gotten
smarter about excluding files from dependency checking. In VC6 and earlier,
there was a file (sysincl.dat, IIRC) that contained many hundreds of names
of system (C, C++, Windows) headers, and the compiler would exclude any
file with one of these names, wherever it was located. Nowadays, the
compiler excludes whole directories, which makes a lot more sense. You
should also make sure the relevant .obj files aren't dated far into the
future.
 
C

Chris Shearer Cooper

stdafx.h looks like this (it's the "..\otherproject\superfile.h", and
similar lines immediately following, that are my concern):
* neither stdafx.h nor superfile.h start with //{{NO_DEPENDENCIES}}
* I do a complete rebuild, and the problem doesn't go away (so it's not obj
files being dated in the future)

// stdafx.h : include file for standard system include files,

// or project specific include files that are used frequently, but

// are changed infrequently

//

#if !defined(AFX_STDAFX_H__213DF6DA_EB6C_11D5_9E8D_000000000000__INCLUDED_)

#define AFX_STDAFX_H__213DF6DA_EB6C_11D5_9E8D_000000000000__INCLUDED_

#if _MSC_VER >= 1000

#pragma once

#endif // _MSC_VER >= 1000

// Lowest operating system you need your app to run on

// WINVER 0x0400 is Windows 95 and Windows NT 4.0

// WINVER 0x0410 is Windows 98

// WINVER 0x0500 is Windows Me, 2000

// WINVER 0x0501 is Windows XP

// RTL features like WS_EX_LAYOUTRTL only appeared in version 0x0500

#if _MSC_VER >= 1400 // VS 2005

#define _WIN32_WINDOWS 0x0410

#define WINVER 0x0410

#define _WIN32_WINNT 0x0500

#endif



// Internet Explorer 5.0, 5.0a, 5.0b

#define _WIN32_IE 0x0500

#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers

#include <afxwin.h> // MFC core and standard components

#include <afxext.h> // MFC extensions

#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls

#include <afxtempl.h> // MFC support for Internet Explorer 4 Common Controls

#include <afxdisp.h> // For Drag & Drop

#include <afxole.h> // For Drag & Drop

//#include <afxadv.h> // For Drag & Drop

#ifndef _AFX_NO_AFXCMN_SUPPORT

#include <afxcmn.h> // MFC support for Windows Common Controls

#include <afxcview.h>

#endif

#ifndef WS_EX_NOINHERITLAYOUT

#define WS_EX_NOINHERITLAYOUT 0x00100000

#endif

#ifndef WS_EX_LAYOUTRTL

#define WS_EX_LAYOUTRTL 0x00400000

#endif

#define countof(x) (sizeof(x) / sizeof(x[0]))

#include "Resource.h"

#include "..\OtherProject\SuperFile.h"
 
C

Chris Shearer Cooper

Interesting thing I just discovered ... in the stdafx.h, I include a lot of
other files (the listing I gave in this previous post was deliberately
incomplete) ...
It appears that files that are in the same folder as stdafx.h do cause a
complete rebuild, but files that are in other folders (like ..\OtherProject)
are not. Does this jibe with what you said about the compiler excluding
whole directories? And if so, how do I tell the compiler to not exclude the
...\OtherProject directory?

Thanks
Chris

Chris Shearer Cooper said:
stdafx.h looks like this (it's the "..\otherproject\superfile.h", and
similar lines immediately following, that are my concern):
* neither stdafx.h nor superfile.h start with //{{NO_DEPENDENCIES}}
* I do a complete rebuild, and the problem doesn't go away (so it's not
obj files being dated in the future)

// stdafx.h : include file for standard system include files,

// or project specific include files that are used frequently, but

// are changed infrequently

//

#if
!defined(AFX_STDAFX_H__213DF6DA_EB6C_11D5_9E8D_000000000000__INCLUDED_)

#define AFX_STDAFX_H__213DF6DA_EB6C_11D5_9E8D_000000000000__INCLUDED_

#if _MSC_VER >= 1000

#pragma once

#endif // _MSC_VER >= 1000

// Lowest operating system you need your app to run on

// WINVER 0x0400 is Windows 95 and Windows NT 4.0

// WINVER 0x0410 is Windows 98

// WINVER 0x0500 is Windows Me, 2000

// WINVER 0x0501 is Windows XP

// RTL features like WS_EX_LAYOUTRTL only appeared in version 0x0500

#if _MSC_VER >= 1400 // VS 2005

#define _WIN32_WINDOWS 0x0410

#define WINVER 0x0410

#define _WIN32_WINNT 0x0500

#endif



// Internet Explorer 5.0, 5.0a, 5.0b

#define _WIN32_IE 0x0500

#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers

#include <afxwin.h> // MFC core and standard components

#include <afxext.h> // MFC extensions

#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common
Controls

#include <afxtempl.h> // MFC support for Internet Explorer 4 Common
Controls

#include <afxdisp.h> // For Drag & Drop

#include <afxole.h> // For Drag & Drop

//#include <afxadv.h> // For Drag & Drop

#ifndef _AFX_NO_AFXCMN_SUPPORT

#include <afxcmn.h> // MFC support for Windows Common Controls

#include <afxcview.h>

#endif

#ifndef WS_EX_NOINHERITLAYOUT

#define WS_EX_NOINHERITLAYOUT 0x00100000

#endif

#ifndef WS_EX_LAYOUTRTL

#define WS_EX_LAYOUTRTL 0x00400000

#endif

#define countof(x) (sizeof(x) / sizeof(x[0]))

#include "Resource.h"

#include "..\OtherProject\SuperFile.h"
 
D

Dan Baker

Chris Shearer Cooper said:
stdafx.h looks like this
#include "Resource.h"
<snip>

I don't think you want to #include "resource.h" ... Resource.h changes all
the time. Files in stdafx.h are compiled and placed in the pre-compiled
header, which means if you change your resources, you will not get those
changed.

I don't think this is the problem you are describing... Just a note.

DanB
 
D

David Ching

Chris Shearer Cooper said:
Interesting thing I just discovered ... in the stdafx.h, I include a lot
of other files (the listing I gave in this previous post was deliberately
incomplete) ...
It appears that files that are in the same folder as stdafx.h do cause a
complete rebuild, but files that are in other folders (like
..\OtherProject) are not. Does this jibe with what you said about the
compiler excluding whole directories? And if so, how do I tell the
compiler to not exclude the ..\OtherProject directory?

It shouldn't matter what directory the header is in. But VC++ maintains
dependency info on a very fine basis. For example, if you change a
protected member of a class in the .h, it won't compile the .cpp files that
include the class because it knows that protected members can't be accessed
outside of the class so there is no need to recompile code outside of the
classs. Maybe that's why changing some .h files for you doesn't build
anything.

-- David (MVP)
 
D

Doug Harrison [MVP]

Interesting thing I just discovered ... in the stdafx.h, I include a lot of
other files (the listing I gave in this previous post was deliberately
incomplete) ...
It appears that files that are in the same folder as stdafx.h do cause a
complete rebuild, but files that are in other folders (like ..\OtherProject)
are not. Does this jibe with what you said about the compiler excluding
whole directories? And if so, how do I tell the compiler to not exclude the
..\OtherProject directory?

The setting is at (menu drilling down into dialog box):

Tools/Options/Projects and Solutions/VC++ Directories/Exclude Directories

I have VC2005 SP1 here, and I just created a console application and put
the following into stdafx.h:

#include "../../other/zzz.h"

This file contains:

#pragma message("2")

When I change the message and recompile, stdafx.cpp and everything else is
rebuilt. I did not add zzz.h to the project, so apparently it's not
necessary to do so. If David is right, and minimal compilation is behind
it, then you should see messages like this in the output window:

1>Skipping... (no relevant changes detected)
 
A

Alex Blekhman

David Ching said:
It shouldn't matter what directory the header is in. But
VC++ maintains dependency info on a very fine basis. For
example, if you change a protected member of a class in
the .h, it won't compile the .cpp files that include the
class because it knows that protected members can't be
accessed outside of the class so there is no need to
recompile code outside of the classs.

It looks like quite dangerous decision. Protected members,
while being inaccessible, are perfectly visible for user's
code and participate in member call resolution. Access
rights are apllied afterwards. For example:

class X
{
public:
void f(double) {}

protected:
void f(const char*) {}
};

int main()
{
X x;

x.f(42);
x.f(3.14);

return 0;
}

The code above compiles as expected. Now if I change
protected `f' from

void f(const char*) {}

to

void f(int) {}

The `x.f(42);' statement won't compile anymore since
protected member function `void f(int)' participates in call
resolution and matches better than `void f(double)'.

Now, if compiler doesn't recompile corresponding .CPP file,
then the above compilation error will lurk untill full
rebuild. So, developer can continue with other tasks for a
long time without even knowing that there is an error.

Alex
 
B

Bruno van Dooren [MVP VC++]

Aren't you supposed to have 'stdafx.cpp' added to your project as
well as 'stdafx.h'? That's what should trigger re-creation of the
precompiled headers and further recompilation of the modules...

Or just turn them precompiled headers off (are they on?)

the precompiled header is generated through StdAfx.cpp.
only when that is recompiled, is the precompiled header re-generated.

If your cpp files do no include the changed header file directly, they will
not see the changes.
Rather, they will see what used to be in the header when StdAfx.cpp was last
compiled.

This is one of the gotchas of precompiled headers.
A full rebuild will solve this, since StdAfx will be compiled first.
Other than that you can only solve this by manually recompiling StdAfx.cpp
after a change.

--

Kind regards,
Bruno van Dooren
(e-mail address removed)
Remove only "_nos_pam"
 
D

David Ching

Alex Blekhman said:
It looks like quite dangerous decision. Protected members, while being
inaccessible, are perfectly visible for user's code and participate in
member call resolution. Access rights are apllied afterwards. For example:

Yes, you're right of course. I'm not sure how the decision of what to
compile is made in this instance, maybe VC++ handles it correctly. There
are times when I make changes, build my app, and the result crashes with a
disassembly window that doesn't match the source, or some other weird
result. Then I have to a Rebuild Solution in order to make sure everything
is in sync. So VC++ decision to compile certain things can and does get
confused at times. I'm sure we've all experienced this.

Thanks,
David (MVP)
 
A

Alex Blekhman

David Ching said:
[...] There are times when I make changes, build my app,
and the result crashes with a disassembly window that
doesn't match the source, or some other weird result.
Then I have to a Rebuild Solution in order to make sure
everything is in sync. So VC++ decision to compile
certain things can and does get confused at times. I'm
sure we've all experienced this.


Yes, this is well known problem in the project I currently
work on. We have quite a big amount of code and developers
already lost their faith in "Build" command. Almost
everybody does full rebuild after code sync and changes in
headers.
 
N

Nathan Mates

Yes, this is well known problem in the project I currently work
on. We have quite a big amount of code and developers already lost
their faith in "Build" command. Almost everybody does full rebuild
after code sync and changes in headers.

Do you have minimal rebuild turned on? That's under right click on
project -> Properties -> C/C++ -> Code Generation -> Enable Minimal
Rebuild. If that's set to Yes, try flipping the setting.

Nathan Mates
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top