1 message in com.perforce.jamming[jamming] precompiled headers using m...
FromSent OnAttachments
Paul Forgey09 Sep 2003 12:28 
Subject:[jamming] precompiled headers using msvc and working with -j
From:Paul Forgey (pau@metainfo.com)
Date:09/09/2003 12:28:41 PM
List:com.perforce.jamming

I've seen requests bounced around the list for such a thing. I've come up with something that's been working quite well here for a while, although it is kind of ugly. Then again, vc's handling of pre-compiled headers is a mess if you try to make it work in an smp build environment anyway.

Hopefully, we'll be able to keep the same external Jamfile interface to it when we wire up precompiled headers to gcc-3.4 in our build system.

To use it, invoke the PreCompiledHeaders rule, with $(1) being the list of source files to be injected with the precompiled header, and $(2) to be the header file (single header file!). Two pch files will be generated; one for C and the other for C++. For all C sources, the compiler forces in an #include of $(2) using the C compiled pch output, and likewise for C++. That means you want proper #ifdef guarding and #ifdef/#ifndef __cplusplus sections in your pch and any header files it includes.

Assuming your header files are properly guarded, your code can continue to include the same files your precompiled header did with little impact on build performance. This is important if the same code is to be built where precompiled headers aren't supported. In this case, that's presently everything not built with msvc.

This isn't quite the Microsoft paradigm for handling precompiled headers, but it seems closer to the way most other compilers do it. Since we build on lots of platforms using different compilers, we wanted something that would translate well to non msvc environments.

I don't like how I added .h to the UserObject rule to support this. Maybe it would be better to use a new extension, like .pch, similar to Code Warrior.

This also works great for us on MFC projects. Assuming you have a SubDirC++Flags set for the proper -D options (like -D_AFXDLL -D_MBCS, or whatever options you are building with), just use: PreCompiledHeaders $(SOURCE_FILES) : stdafx.h ;

If you prefer to use ObjectDefines on the sources, then pass the same defines to $(3): PreCompiledHeaders $(SOURCE_FILES) : stdafx.h : $(MFC_DEFS) ;

rule UserObject { switch $(2) { # other stuff

# nt specific, for precompiled header output. # the .obj file is essentially throwaway case *.h : if $(NT) { switch $(<:B) { case CC* : CCFLAGS on $(<) += /TC /Yc

/Fp$(LOCATE_TARGET)$(SLASH)$(<:G=:S=.pch) ; Cc $(<) : $(>) ;

case C++* : C++FLAGS on $(<) += /Yc

/Fp$(LOCATE_TARGET)$(SLASH)$(<:G=:S=.pch) ; C++ $(<) : $(>) ; } }

# other stuff

case * : Echo "unknown suffix on " $(2) ; } }

rule PreCompiledHeaders { # source-file : header-file : [ defines ] if $(NT) {

local _srcs = [ FGristFiles $(1) ] ; local _hdrs = [ FGristFiles $(2) ] ;

Includes $(_srsc) : $(SUBDIR)$(SLASH)$(2) ;

local _ccpchs = [ FGristFiles "CC"$(2:S=.pch) ] ; local _c++pchs = [ FGristFiles "C++"$(2:S=.pch) ] ;

local _ccobjs = $(_ccpchs:S=$(SUFOBJ)) ; local _c++objs = $(_c++pchs:S=$(SUFOBJ)) ;

Object $(_ccobjs) : $(_hdrs) ; Object $(_c++objs) : $(_hdrs) ;

local _objs = $(_ccobjs) $(_c++objs) ;

DEFINES on $(_objs) += $(3) ; CCDEFS on $(_objs) = [ on $(_objs) FDefines $(DEFINES) ] ;

MakeLocate $(_ccpchs) : $(LOCATE_TARGET) ; MakeLocate $(_c++pchs) : $(LOCATE_TARGET) ;

Clean clean : $(_ccpchs) ; Clean clean : $(_c++pchs) ;

Depends $(_srcs:S=$(SUFOBJ)) : $(_ccobjs) $(_c++objs) ;

ObjectCcFlags $(1) : /FI$(2) /Yu$(2) /Fp$(LOCATE_TARGET)$(SLASH)$(_ccpchs:G=) ; ObjectC++Flags $(1) : /FI$(2) /Yu$(2) /Fp$(LOCATE_TARGET)$(SLASH)$(_c++pchs:G=) ;

} # $(NT) }