The name 'ppremake' stands for Panda Pre-make; ppremake is a
preprocessor that reads a series of source description files and
generates a series of makefiles (or, potentially, other kinds of
package build description files, like VC++ project files).


WHY PPREMAKE?
  
  We needed something like ppremake to meet our complex multi-platform
  build requirements.  Panda should be built in different ways
  according to platform:
  
    * On Unix systems that support shared libraries (.so files), each
      subdirectory becomes a different .so file.  This provides the
      maximum convenience while developing; local changes remain local
      to a particular .so file and don't require relinking of the
      whole thing.
  
    * On Windows systems, the number of shared libraries (.dll files)
      must be reduced to minimize overhead, as well as to allow STL to
      work properly between different subdirectories within a package.
      (In VC6, STL constructs other than vectors do not work between
      different DLL's.)  Thus, we must define a number of 'metalib'
      objects that each represents a set of subdirectories that are to
      be linked into one DLL.
  
    * On systems that do not support shared libraries at all, or for
      developers who do not wish to use them, each subdirectory
      becomes a static library.
  
  Also, it should be possible to build Panda natively on each
  platform, without having to install Unix tools (e.g. Cygwin).  This
  means that we cannot depend on common Unix tools and commands (like
  install, cp, mv) being present, and makes it difficult to define one
  set of makefiles for all platforms.  Furthermore, the use of
  makefiles themselves is not universal; Windows developers are used
  to using VC++ project files to define the build relationships, and
  may resist a command-line based build system using makefiles.
  
  Finally, the relationships between source files should be recorded
  only once; it won't do to have to maintain a set of makefiles for
  Unix systems and a separate set of VC++ project files for Windows
  systems.  This invites error and accidental omissions on one side or
  the other.


WHAT IS PPREMAKE, EXACTLY?

  By design, ppremake is more of a scripting language framework than a
  specific application.  It is intended to contain as few assumptions
  as possible about the structure of the source tree it is processing
  or the precise nature of the makefiles (or other build scripts) it
  is generating.

  The ppremake executable is hardcoded to define a set of useful
  predefined variables and functions, and to follow a particular
  procedure to get started scanning a source directory when it is
  invoked.  However, once it is started, the actual behavior of
  ppremake, including the meaning of all the variables defined within
  the various Sources.pp files (see below) and all of the generated
  output, is almost entirely controlled by scripts written in its own
  scripting language.  Most of these control scripts are defined
  in the directory $DTOOL/pptempl.


SOURCE TREE AND INSTALL TREE HIERARCHY 

  The layout of the source tree and of the install tree for Panda are
  strongly influenced by the Unix convention for open source projects,
  particularly as standardized by GNU.  This convention has a long
  history and is widely understood by open source developers.

  The complete source hierarchy available on SourceForge consists of a
  collection of packages, with names like dtool, panda, pandatool, and
  direct; each package is the root of a separate buildable hierarchy
  that includes a src and a metalibs directory; within these
  directories, the source files themselves are distributed logically
  among a number of further subdirectories.  The structure looks
  something like this:

    panda3d/README
    panda3d/dtool/
    panda3d/dtool/Package.pp
    panda3d/dtool/Sources.pp
    panda3d/dtool/src/
    ...
    panda3d/panda/
    panda3d/panda/Package.pp
    panda3d/panda/Sources.pp
    panda3d/panda/src/
    panda3d/panda/src/Sources.pp
    panda3d/panda/src/express/
    panda3d/panda/src/express/Sources.pp
    panda3d/panda/src/express/typedObject.cxx
    panda3d/panda/src/express/typedObject.h
    ...
    panda3d/panda/metalibs/
    panda3d/panda/metalibs/Sources.pp
    panda3d/panda/metalibs/pandaexpress/
    panda3d/panda/metalibs/pandaexpress/Sources.pp
    panda3d/panda/metalibs/pandaexpress/pandaexpress.cxx
    ...

  Note that there is a file called Sources.pp in each subdirectory
  within the hierarchy, and there is a Package.pp at the root of each
  package.  These files define the build relationships among all the
  source files in the hierarchy, and are the input files read by
  ppremake to generate makefiles.

  Once the source tree is unpacked, the user's first step (after
  customizing the local configuration requirements by setting up a
  local Config.pp file) will be to cd into the root of one of the
  packages--typically dtool, which must be built before any of the
  others--and run ppremake to generate all of the makefiles for that
  package.  (This is akin to running ./configure within the root of a
  package for most GNU software.  Unfortunately, Panda cannot easily
  take advantage of GNU's autoconf scripts, because of its difficult
  multiplatform requirements.)

  Once the package has been configured, the user can build the entire
  package with the command 'make' (or 'nmake' in a non-Cygwin Windows
  environment).  The source files within the tree are compiled in
  place.  At this point, nothing has yet been installed publicly.  In
  most Unix/GNU packages, the user may at this point run any
  applications built within the tree prior to installation, but Panda
  relies too heavily on shared libraries to make this work reliably.
  You must 'make install' before you can execute any of the
  applications within the Panda package.

  Installing the package with 'make install' (or 'nmake install')
  copies to a public location all of the files that are necessary to
  make use of the package, either for running applications or building
  new applications.  This includes all the executables (.exe files) as
  well as shared libraries (.dll or .so files) for runtime, as well as
  header files (.h files) and static libraries (.lib or .a files) for
  building new applications.

  The location to which these files are installed is specified by the
  user in the local Config.pp file; the common Unix convention is to
  install these in the directory /usr/local/panda.  The executables
  will go into /usr/local/panda/bin, the static and dynamic libraries
  into /usr/local/panda/lib, and the header files into
  /usr/local/panda/include.  Note that all packages within the source
  hierarchy, including dtool, panda, pandatool, and direct, will be
  installed into the *same* public install tree, whether it is called
  /usr/local/panda or something else.  (On a Windows environment the
  directory name /usr/local/panda may be inappropriate.  It is up to
  the user to specify a suitable directory name.  We suggest
  C:\Panda3d.)

  Once dtool has been built and installed, the next step is to cd to
  the panda package, ppremake, and 'make' followed by 'make install',
  and so on with the direct and/or pandatool packages.  All of these
  packages will be installed into /usr/local/panda (or whichever
  directory the user specified as the install tree).


AN ALTERNATIVE INSTALL TREE PHILOSOPHY

  Installing all the packages to the same install tree works well for
  the outside developer who is primarily interested in taking the
  whole body of code as a complete piece, but we have different needs
  for our own in-house development.  It is convenient to be able to
  treat the individual packages separately; our in-house 'ctattach'
  scripts (not included with the distribution) allow us to use one of
  several automatically-built trees for development, or upon need, to
  switch on-the-fly to using our own personally built tree.

  In order to make this work, the source tree and the install tree
  must become the same thing.  When we are developing in-house, 'make
  install' copies all the relevant files to the bin, lib, and include
  subdirectories of the root of the source package, instead of to a
  common public install directory.  This allows us to easily
  mix-and-match the files from packages built at various times.


PPREMAKE VARIABLES TO SUPPORT EITHER PHILOSOPHY

  Variables are defined in ppremake either with the appropriate
  #define or #defer command in the local Config.pp, or in the absence of
  this, they are taken from environment variables.

  In the normal, install-in-one-place philosophy, the user should
  define only INSTALL_DIR, which indicates the root directory name all
  packages will be installed to.  In the alternative philosophy, used
  in-house, the environment variables DTOOL, PANDA, DIRECT,
  etc. should be defined, which indicate the location of the source
  directories for each of the various trees.

  In either case, the various Package.pp scripts will define the
  following ppremake variables appropriately:

    DTOOL_INSTALL
    PANDA_INSTALL
    DIRECT_INSTALL
    (etc).

  The above indicate the directories in which files from each tree
  should be installed.  In the normal philosophy, these will all
  contain the same string, the same thing specified by INSTALL_DIR.

    DTOOL_INSTALL_OTHER
    PANDA_INSTALL_OTHER
    DIRECT_INSTALL_OTHER
    (etc).

  These variables have the same meaning as the above, except that they
  are intended to be used from a different package.  That is, if code
  in the Panda source tree needs to reference an installed file from
  Dtool, it should expect to find it in $[DTOOL_INSTALL_OTHER].
