|
You can reduce compilation time by precompiling common include (header) files.
HP aC++ provides two mechanisms for precompiling headers.
Header caching
is easy to use and was first incorporated in version A.01.21 (for HP-UX 10.x) and HP aC++
A.03.13 (for HP-UX 11.x).
The prior mechanism,
manual precompiled headers
,
remains available.
NOTE:
Mixing the two mechanisms for a single compilation is not supported.
The +hdr_cache option is incompatibile with the +hdr_create and +hdr_use
options.
|
|
Deciding which Mechanism to Use |
When deciding whether to use header caching or manual precompiled headers,
filespace and ease of use are of major concern.
With header caching, HP aC++ precompiles what is
included in the source file (prefix header region) and is responsible for
correctness. You need only specify the +hdr_cache option.
However, significantly more disk space is required compared to manual
precompiled headers. And an initial compile or a re-compile may take
more time.
With manual precompiled headers, you control exactly what is precompiled,
and when, and you are responsible for the correctness of the code.
However, you can minimize disk space usage and precompilation time.
One way of deciding which mechanism to use would be to specify
+hdr_cache to determine if file space is a concern. If it is,
then consider the manual precompiled header mechanism.
| | Header Caching
|
Header caching enables the compiler to cache and use the result of
compiling header files from one build to the next. The first
build after enabling this option is likely to take somewhat longer
but subsequent builds, to the extent that the contents of the
cache remain valid, should be measurably faster.
To request header caching, just specify
the +hdr_cache option
on the aCC command line or in your Makefile or use the
CXXOPTS environment variable.
There are no other requirements.
The header caching mechanism automatically decides if and when to
create a precompiled header and if and when to reuse an existing one.
NOTE:
Compilation caches for programs using templates or large headers
can require substantial disk space.
If you need to reclaim disk space, it is safe to remove the
cache directory (aCC_cache) in its entirety (rm -rf aCC_cache),
but avoid removing only portions of the directory.
Header Cache Processing
When you are compiling with +hdr_cache for the first time,
or if the elements of the compilation environment have changed
since the prior compilation,
the compiler does the following for each source file on the command line:
-
Creates an aCC_cache sub-directory in the directory where the
source file resides (for an initial compile only).
This directory acts as a repository for precompiled header files.
Note, use the +hdr_dir
option to specify a different location and/or name for the aCC_cache directory.
-
Identifies the prefix header region in each source file,
precompiles it, and stores the precompiled version of its contents
in the the aCC_cache directory.
- Encapsulates the unique compilation environment of the source file
and stores its content in the aCC_cache directory.
This information is used in future compiles to determine
whether or not a given precompiled header is valid for reuse.
Use the
+hdr_info option to see if a cache is
being reused or recreated. If you find that you need more than one
cache directory, use the
+hdr_dir option.
By contrast, for an unchanged compilation in which the compiler has
examined the compilation environment
and found no significant changes, the existing precompiled header
is reused and compilation continues.
Typically, for such compiles, performance is significantly improved.
The prefix header region is the initial region of a source file that
contains #include and #define directives.
The end of the prefix header region (and thus the automatic precompile)
is reached when the compiler encounters a code sequence other than a
#include or #define directive
(i.e., a declaration or operator), or
when a #pragma hdr_stop
is encountered.
Performance and File Space Considerations
In order to use header caching most effectively, consider the following points.
-
In general, compile time will be faster for a re-compile using an existing
precompiled header file, than for a compilation that does not use
precompiled headers.
Most notable improvement would be for code that uses many header files.
-
Compile time will be slower for an initial compilation or one for which the
prefix header region
has changed than for a re-compile using an existing precompiled header.
-
A given application using automatic precompiled header files may require
more file space than would a manual precompiled header file.
It is good programming practice to not include unnecessary headers.
-
Try to include all necessary headers before any of the other
code in a source file. This will insure that maximum
precompilation occurs.
-
In compiling a source-file, if you do not want to precompile all
#include header files, specify the
#pragma hdr_stop
directive to end the prefix header region prior to those headers that are not
to be precompiled.
-
Remember that compilation time is generally improved for source code
in which the
prefix header region is not modified.
| | Manual
Precompiled Headers |
You can manually create a precompiled header file.
Then when you compile your application or library,
you specify the precompiled header file on the command line.
Note, with this method, just one precompiled header file is allowed per
compilation.
To manually create and use a precompiled header file, follow these steps:
- First you need a source (
.C) file that includes all the header files you
want to precompile (precomp.C in the following example).
- Next create a precompiled header file (in this case named
precomp)
from precomp.C by using the +hdr_create option.
Use the -c option to suppress creation of the executable file.
Each time you use the +hdr_create option to create a
precompiled header file, by default, a corresponding .o file is
also created. Information resulting from the compilation of declarations
is put into this .o file. The .o file may contain information related to
debugging, virtual function tables, and inline function bodies.
This saves space and time by eliminating duplication in future
+hdr_use compiles.
aCC precomp.C -c +hdr_create precomp
- When you want to compile
precomp, use the
+hdr_use option.
This is known as a load compile.
aCC main.C +hdr_use precomp
| Verbose Information |
Use the +hdr_v
option for verbose information when precompiling a header or when compiling a
precompiled header file.
To see what goes into the precompiled header file:
aCC precomp.C -c +hdr_create precomp +hdr_v
To see what is being brought into the compiler during a load compile:
aCC main.C +hdr_use precomp +hdr_v
| | For More Information |
| | Example Source Files |
The files in the example below are written so that you can compile them
either with or without precompiled headers, as described in
Writing Headers that can be Either Compiled or Precompiled.
Thus you could issue the following command to compile the files without
precompiling:
aCC main.C
Or to use the precompiled header created in the prior example:
aCC main.C +hdr_use precomp
In the following example, header file a.h is included in precomp.C
and precomp.C is included in main.C.
// a.h
#ifndef A_H
#define A_H
extern "C" int printf(char *, ...);
class foo {
private:
int x;
public:
foo() { printf("constructor for foo\n");x++; }
};
#endif // A_H
// precomp.C
#ifndef PRECOMP
#define PRECOMP
#include "a.h"
class bar : foo {
private:
int y;
public:
bar() { printf("constructor for bar\n");y++; }
};
#endif // PRECOMP
// main.C
#include "precomp.C" // Use this include statement
// ONLY if you want
// headers that can be
// either precompiled or compiled.
void main()
{
bar b;
}
< | | Writing Headers
that can be Either Compiled or Precompiled |
If you want to be able to either compile a header file directly or to
precompile and than compile it (a load compile),
the file must have the following characteristics.
- You must #include the precompiled header source (.C) file in your main
program.
Even though this is not necessary for a load compile,
it is required when you compile without first precompiling.
- In order to create a precompiled header file, you must have one source
(
.C) file that includes all of the other header files you intend to
precompile.
- Use include guards in the source file that includes the header files and
in the header files themselves.
Include guards are generally used to ensure that the
contents of the header files are included only once. They are required in a
load compile since you #include the precompiled header source (.C) file in main.C.
The +hdr_use option has
the side effect of defining a compilation flag (e.g. A_H and PRECOMP),
so the conditional directives prevent redefinitions of the contents
of a.h and precomp.C respectively.
For more information about preprocessor directives, refer to
Preprocessing in HP aC++
| | Safeguarding your
Precompiled Header Files |
Be certain you remake a precompiled header file
if anyone could have changed any of the header files it represents.
Otherwise these header changes will not be part of the load compile.
It is also recommended that, from time to time, you re-compile everything
(header and .C files) without the +hdr_use option. This ensures that each
.C file contains exactly the correct #include directives.
For example, suppose you have source files prog1.C and prog2.C that each
require a #include prog.h directive. If the #include directive is missing
from prog2.C, an error message would be generated if you re-compile that file
without the +hdr_use option. With the +hdr_use option, however,
no error is generated since prog.h is in the precompiled header file
because of the prog1.C #include directive.
| | Creating a Two-tiered
Headers Process |
When project files are under active development, it is sometimes better to
divide your header files and precompiled header files into groups,
depending on how often they are being modified. For example,
- Build a file called
StableHeaders.C that includes only headers
that are changed infrequently.
- Build a file called
VolatileHeaders.C that includes only headers
that are frequently changed. (If you use include guards, this file can
include headers from the set in StableHeaders.C.)
- Build two precompiled header files, and combine them into one
using commands like the following:
aCC StableHeaders.C -c +hdr_create Stable
aCC VolatileHeaders.C +hdr_use Stable -c +hdr_create Total
- Compile a program with the resulting precompiled header (in this case, Total).
aCC Prog.C +hdr_use Total
|
|