open_toontown_panda3d/panda/src/doc/ppremake-process.txt

143 lines
7.4 KiB
Plaintext

The following steps are executed when ppremake is invoked:
1. Look in the current directory for a file called Package.pp. If
it is not found, but Sources.pp is present in the current
directory, then look for Package.pp in the parent directory.
Repeat until Package.pp is located; this is the root of the
source directory hierarchy.
2. Read and interpret the Package.pp file. This should, in turn,
read in (via the #include directive; see below) whatever other
configuration scripts are relevant to the current package. The
exact behavior of Package.pp is not hardcoded into ppremake, but
the Package.pp scripts for each of the Panda directories will
ultimately include the following files in order:
Any Package.pp for a dependent tree (e.g. $PANDA/Package.pp, etc.)
$DTOOL/Package.pp
$DTOOL/Config.pp
$DTOOL/Config.Platform.pp
The user's Config.pp file, as specified by $PPREMAKE_CONFIG.
$DTOOL/pptempl/System.pp
The various Package.pp files are designed to cascade down, such
that when you invoke ppremake from a high-level tree, such as
Direct (for instance), ppremake invokes $DIRECT/Package.pp, which
in turn invokes $PANDA/Package.pp, which in turn invokes
$DTOOL/Package.pp. At the bottom level, $DTOOL/Package.pp does
most of the remaining setup work, in particular including the
various Config.pp files, and System.pp.
The Config.pp files are intended to define the variables the user
might customize for a particular build environment; the user's
personal Config.pp file is included last, and may override any of
the default values defined in the system Config.pp files.
One particularly critical variable that is defined by Config.pp
is $[BUILD_TYPE]. This represents the type of makefile rules
that are to be generated, e.g. "unix" to generate standard
Unix-style makefile syntax, or "msvc" to generate syntax specific
to Microsoft's nmake. The particular string specified here
controls the selection of which Template files are to be loaded
in a later step to actually generate output files in each source
directory.
The System.pp file is also essential and defines a few more
variables that ppremake will be looking for during its execution.
This tells ppremake the names of certain critical files that it
needs to include. The use of System.pp to define these
filenames, instead of hardcoding them into ppremake, is
consistent with the ppremake philosophy of letting as much of its
behavior as possible be controlled from within the scripting
language itself.
3. Once Package.pp has been read, traverse the entire source
hierarchy, and read each Sources.pp file. A separate named scope
is defined for each Sources.pp file; the name of the scope is
taken from the name of the directory containing the file.
4. Read in the global variable declarations. This is loaded from a
particular file specified by System.pp; this file defines global
declarations that will be useful when processing each Template
file later. To save time, this file is read once and stored in a
global scope, rather than re-read with each Template file. The
particular filename is specified by the ppremake variable
$[GLOBAL_FILE], which was set by System.pp; normally this is
$DTOOL/pptempl/Global.pp.
$DTOOL/pptempl/Global.pp will, in turn, also read in the file
$DTOOL/pptempl/Global.$[BUILD_TYPE].pp if it exists, which may
specify further global declarations that are specific to the
particular build type in effect. Remember, $[BUILD_TYPE] was
specified when Config.pp was read, and controls the particular
type of makefiles or build scripts that are to be generated.
5. Build the inter-directory dependency chain. This is the chain of
relationships between different directories within the source
hierarchy. Each directory may depend on code from zero or more
other directories within the same package. (That is, a directory
may include header files defined within another directory, and/or
require linking with a library built in that directory.)
This inter-directory dependency is critical to determine things
such as build order. If one directory must be built before
another directory, the makefiles must be constructed with this
relationship explicit.
This relationship is determined for each directory by executing
the script named by $[DEPENDS_FILE] (this variable was set by
System.pp) within each source directory scope. Remember, each
Sources.pp file has already been read in, and assigned its own
unique named scope. The DEPENDS_FILE script is responsible for
defining the variable $[DEPEND_DIRS] to contain the
space-separated list of directories (that is, named scopes) that
the files in this current directory depend on.
Normally, System.pp sets $[DEPENDS_FILE] to
$DTOOL/pptempl/Depends.pp. This script builds up $[DEPEND_DIRS]
based on the $[get_depend_libs] function which is defined in
Global.pp, which is in turn based on variables like $[LOCAL_LIBS]
defined within the Sources.pp file.
The inter-directory dependency information can be accessed from
within ppremake scripts simply by examining the $[DEPEND_DIRS]
variable within the appropriate scope. In addition, the
directory relationships are automatically used to sort the
variables $[SUBDIR] and $[SUBTREE] in order, such that each
directory is listed after the directories it depends on.
There is one other variable which should be defined by the
DEPENDS_FILE script: $[DEPENDABLE_HEADERS] should list the source
files within the current directory that may be named as #include
files in other files. This is used to build file-level
dependencies to support the $[dependencies] built-in function,
and is not related to inter-directory dependencies.
6. Finally, generate the actual output files in each source
directory. This is done by executing the script named by
$[TEMPLATE_FILE] (set by System.pp) within each source directory
scope.
Normally, System.pp sets $[TEMPLATE_FILE] to
$DTOOL/pptempl/Template.$[BUILD_TYPE].pp. Recall again that
$[BUILD_TYPE] was specified when Config.pp was read, and controls
the particular type of makefiles or build scripts that are to be
generated, so there is a different Template script file for each
supported build type.
The Template file is responsible for generating the actual
makefile (or whatever build script is required) as appropriate to
each source directory. It now has all the information required:
all source directories have been read, so the relationships
between different source directories can control the output;
also, the inter-directory and inter-file dependencies are
available.
Generally, a Template file will include at least one #output
directive to generate the appropriate makefile for this
directory. Since there may be different kinds of source
directories, each with very different makefile requirements, the
Template files usually have one large #if condition based on the
value of $[DIR_TYPE], which is set within each Sources.pp (and
is set in System.pp to default to "src").