The Makefile, Project and Workspace Creator.
Designed by Justin Michel (michel_j@ociweb.com) and Chad Elliott.
Implemented by Chad Elliott (elliott_c@ociweb.com).


A single tool (mpc.pl) can be used to generate tool specific input (i.e.
Makefile, dsp, vcproj, etc).  The generator takes platform and building
tool generic files (mpc files) as input which describe basic information
needed to generate a "project" file for various build tools.  These tools
include GNU Make, NMake, Visual C++ 6, Visual C++ 7, etc.

One of the many unique and useful features of the Makefile, Project and
Workspace Creator is that the project definition files can employ the idea
of inheritance.  This feature allows a user to set up a basic base project
(mpb file) that can contain information that is applicable to all
sub-projects.  Things such as include paths, library paths and inter-project
dependencies could be described in this base project and any project that
inherits from it would contain this information as well.

Another set of files, known as template input files (mpd files), provides
the generator with the necessary information to fill platform and build
tool specific information for dynamic and static library and binary
executable projects.

Together, the generic input files and the template input files are applied
toward a platform and build specific template (mpt file) to create the final
product (a build tool specific input file).  These templates contain
"variables" that are filled in by the project creator with information
gathered through the mpc and mpd files and possibly by default values set
within the template itself.

Workspaces are defined by providing a list of mpc files in a single (mwc)
file.  For each mpc file specified, the workspace creator (mwc.pl) calls
upon the project creator to generate the project.  After all of the projects
are successfully generated, the tool specific workspace is generated
containing the projects and any defined inter-project dependency information
(if supported by the build tool).  If no workspace files are provided to the
workspace creator, then the current directory is traversed and any mpc files
located will be part of the workspace that is generated.


Workspace Declarations
----------------------

workspace(workspace_name) {
  file.mpc
  directory
  relative/path/to/another/mwc_file
}

Workspaces can contain individual mpc files, directories or other mwc files.
In the case of a directory, the workspace creator will traverse it and use
any mpc files that are found.  If another workspace file is listed in the
workspace files, it will be aggregated into the workspace with paths relative
to the directory in which the main workspace is found.  These "aggregated"
workspaces should not inherit from any other base workspace.  The workspace
files should have an 'mwc' extension.


Project Declarations
--------------------

project(project_name) : baseproject, anotherbaseproject {
  exename   = foo
  includes += "."
  libpaths  = directory

  Source_Files {
    file1.cpp
    file2.cpp
    .
    .
    fileN.cpp
  }

  Header_Files {
    file1.h
    file2.h
    .
    .
    fileN.h
  }
}


The (project_name) part of the project declaration is optional.  If it is
left off, the project name will default to the name of the mpc file without
the extension.  Inheritance is optional.

If the project name or workspace name contains an asterisk (*) then the
default project (workspace) name will be used in its place.  For example, if
the mpc file is named example.mpc and it contains the following:

project(*client) {

The project name will be example_client.  If the any part of the modified
project (workspace) name contains a capital letter then each word will be
capitalized.  For instance, if the above mpc file example was named
Example.mpc, then the modified project name would be Example_Client.

If multiple projects are going to be contained within a single workspace
(using mwc.pl), there can be no duplication of project names.  This is
disallowed due to limitations of some workspace tools.

Project Keywords
----------------
exename		Specifies the name of the executable that will be created
sharedname	Specifies the name of the shared library that will be created
staticname	Specifies the name of the static library that will be created
dllout		If defined, specifies where the dynamic libraries will be
                placed.  This overrides libout in the dynamic case.
libout		Specifies where the dynamic and static libraries will be placed
install		Specifies where executables will be installed
pch_header	Specifies the precompiled header file name
pch_source	Specifies the precompiled source file name
version         Specifies the version number for the library or executable
macros          These values will be passed as macros to the compiler.
libpaths	Specifies 1 or more locations to find libraries
includes	Specifies 1 or more locations to find include files
libs		Specifies 1 or more libraries to link into the exe or library
lit_libs	Specifies 1 or more libraries to link into the exe or library.
                If libraries receive a library decorator, then these will not.
pure_libs	Specifies 1 or more libraries to link into the exe or library.
                If libraries receive a library decorator, then these will not.
                If libraries receive a file extension, then these will not.
after           Specifies that this project must be built after 1 or more
                project names listed.
dynamicflags	Specifies preprocessor flags needed for dynamic libraries
staticflags	Specifies preprocessor flags needed for static libraries

verbatim        This allows arbitrary information to be place in a generated
                project file.  The syntax is as follows:

                verbatim(<project type>, <location>) {
                  ..
                  ..
                }

                When MPC is generating a project of type <project type> and
                comes upon a marker that matches the <location> name, it
                will place the text found inside the construct directly into
                the generated project.  If you need to preserve white space,
                the line or lines should be placed inside double quotes.

specific        This scope allows assignments that are specific to a
                particular project type.  The syntax is as follows:

                specific(<project type> [, <project type> ...]) {
                  lit_libs += c
                  ...
                }

                If a keyword is not recognized as a valid MPC keyword, it is
                interpreted as a template value modifier.  In this
                situation, this construct has the exact same restrictions as
                the -value_template command line option.  See the USAGE file
                for more information.

requires        Specifies which features should be enabled in order to
                generate the project file.  Under the GNUACE type, it also
                specifies which tao macros should be set to build the
                target.
avoids          Specifies which features should be disabled in order to
                generate the project file.  Under the GNUACE type, it also
                specifies which tao macros should not be set to build the
                target.

The Following are GNUACE only:
tagname         Specifies the make macro to check before building the target
tagchecks       Specifies the values for tagname to check

NOTE: Within the GNUACE project type, setting sharedname to empty and
setting staticname to the static library name will result in a project that
will generate only static libraries.

Custom File Definitions
-----------------------
In order to support a variety of custom build rules, MPC allows you to
define your own custom file types.  Below is an example of a custom
definition.

project {
  Define_Custom(MOC) {
    automatic        = 0
    command          = $(QTDIR)/bin/moc
    output_option    = -o
    inputext         = .h
    pre_extension    = _moc
    source_outputext = .cpp
  }

  MOC_Files {
    QtReactor.h
  }

  Source_Files {
    QtReactor_moc.cpp
  }
}

The above example defines a custom file type "MOC" which describes basic
information about how to process the input files and what output files are
created.  Once the custom file type is defined, MOC_Files can be defined in
order to specify the input files for this new file type.

Here is a list of keywords that can be used within the scope of
Define_Custom:

automatic           If set to 1, then attempt to automatically determine
                    which files belong to the set of input files for the
                    custom type.  If set to 0, then no files are
                    automatically added to the input files.  If omitted,
                    then automatic is assumed to be 1.  Custom file types
                    that are automatic will have the side effect of possibly
                    adding files to Source_Files, Inline_Files, Header_Files
                    Template_Files, Resource_Files and Documentation_Files
                    depending on which extension types the command generates.
dependent           If this value is set, then a dependency upon the command
                    will be placed upon all of the generated files.  The
                    default for this is unset and no dependency will be
                    generated.
command             The name of the command that should be used to process
                    the input files for the custom type.
commandflags        Any options that should be passed to the command go here.
inputext            This is a comma separated list of input file extensions
                    that belong to the command.
keyword             This is a special assignment that takes the form of the
                    following:

                    keyword newname = existing_custom_name

                    This has the effect of mapping newname to be the
                    same as existing_custom_name.  existing_custom_name,
                    which is optional, corresponds to one of the keywords
                    available within a Define_Custom scope (except for
                    keyword).  This function puts newname into the project
                    level scope such that it can be used outside of the
                    scope of the particular custom file type being defined.
                    It should be noted that the mapped keywords can not be
                    used within the scope of a 'specific' clause.  It does
                    not cause an error, but it has absolutely no affect.
                    If existing_custom_name is not supplied, then the only
                    way to utilize the newname value is from within the
                    template code. ex. <%newname%>
libpath             If the command requires an additional library path, add
                    it here.
output_option       If the command takes an option to specify a single file
                    output name, then set it here.  Otherwise, this should be
                    omitted.
pch_option          This option must take a file name argument and would be
                    passed to the command only when there is a pch header
                    file.  This gives command the option to generate cpp
                    files with precompiled header includes.
pre_extension       If the command produces multiple files of the same
                    extension, this comma separated list can be used to
                    specify them.  For example, tao_idl creates two types of
                    files per extension (C.h, S.h, C.cpp, S.cpp, etc).
pre_filename        This is similar to pre_extension except that the values
                    are prepended to the file name instead of the extension.
source_outputext    This is a comma separated list of possible source file
                    output extensions.  If the command does not produce
                    source files, then this can be omitted.
inline_outputext    This is a comma separated list of possible inline file
                    output extensions.  If the command does not produce
                    inline files, then this can be omitted.
header_outputext    This is a comma separated list of possible header file
                    output extensions.  If the command does not produce
                    header files, then this can be omitted.
template_outputext  This is a comma separated list of possible template file
                    output extensions.  If the command does not produce
                    template files, then this can be omitted.
resource_outputext  This is a comma separated list of possible resource file
                    output extensions.  If the command does not produce
                    resource files, then this can be omitted.
documentation_outputext  This is a comma separated list of possible
                         documentation file output extensions.  If the
                         command does not produce documentation files, then
                         this can be omitted.
generic_outputext   If the command does not generate any of the other output
                    types listed above, then the extensions should be listed
                    under this.

Particular output extensions are not required.  However at least one output
extension type is required in order for MPC to generate a target.  Your
command doesn't necessarily have to generate output, but an extension type
is none the less required.  This can be desirable in some situations,
whereas the command set to run for the custom type may be a script that runs
a test.  Thereby, integrating building and testing.

For custom file types, there are two keywords that can be used within the
custom file type input lists: commandflags and gendir.  The commandflags can
be used to augment or override the commandflags defined in the Define_Custom
section.  gendir can be used to specify the directory in which the generated
output will go.  Below is an
example:

  MOC_Files {
    commandflags += -nw
    gendir = moc_generated
    QtReactor.h
  }

  Source_Files {
    moc_generated/QtReactor_moc.cpp
  }

In the above example, the generated file (QtReactor_moc.cpp) is placed in
the moc_generated directory and the -nw option is added to commandflags.

The following example illustrates the use of the keyword mapping capability
of the Define_Custom:

project {
  Define_Custom(CIDL) {
    automatic         = 0;
    command           =  $(CIAO_ROOT)/bin/cidlc
    commandflags      = -I$(TAO_ROOT)/tao -I$(TAO_ROOT)/orbsvcs/orbsvcs --
    inputext          = .cidl
    source_outputext  = _svnt.cpp
    generic_outputext = E.idl

    // Allow cidlflags to be used outside the scope of CIDL_Files
    keyword cidlflags = commandflags
  }

  // This will get added to all commandflags for CIDL_Files
  cidlflags += --some_option

  CIDL_Files {
    // This will have a combination of the original commandflags plus
    // the value added to cidlflags above.
    file.cidl
  }

  CIDL_Files {
    // This will have a combination of the original commandflags plus
    // the value added to cidlflags above plus the value added to
    // cidlflags here.
    cidlflags += --another_option
    another_file.cidl
  }
}

Special type of feature project
-------------------------------
A feature project contains information as a project would, but can only
be a base project, can not inherit from other projects and will only be
added to a sub project if the features that it requires (or avoids) are
present.

A feature definition requires at least one feature name.  A name by itself
specifies that the feature is required.  A '!' in front of the feature name
indicates that the feature must be disabled.  There may be more than one
feature listed between the parenthesis and they must be comma separated.

The following feature definition requires that the qt feature be enabled.

feature(qt) {
  Define_Custom(MOC) {
    automatic        = 0
    command          = $(QTDIR)/bin/moc
    output_option    = -o
    inputext         = .h
    pre_extension    = _moc
    source_outputext = .cpp
  }

  MOC_Files {
    QtReactor.h
  }

  Source_Files(ACE_COMPONENTS) {
    Demux {
      QtReactor_moc.cpp
    }
  }
}

Assuming that the above feature definition is stored in a file named
qt_reactor.mpb, an mpc project could inherit from it and would only receive
the feature definition if the qt feature was enabled.

project: acelib, qt_reactor {
  ...
}


Special Keywords Available to Templates
---------------------------------------
project_name	This contains the name of the project.
project_file	This contains the name of the output file.
guid		This is used by the VC7 project and workspace creator.
configurations	When used within a foreach context, this info (each
		configuration) is gathered for use with the VC7 workspace
		creator.
flag_overrides  Used to determine flags that have been overridden on a per
                file basis.
custom_types    The list of custom file types that may have been defined
                in the mpc file or a base project.
fornotlast      Insert the text on every foreach iteration except the last.
forlast         Insert the text only on the last foreach iteration.
fornotfirst     Insert the text on every foreach iteration except the first.
forfirst        Insert the text only on the first foreach iteration.
forcount        A one based index number of the foreach iterations.

Workspaces
----------
Workspaces (mwc files) can have assignments similar to projects.  There are
currently only two assignments allowed.

The first is 'cmdline'.  The values given to the cmdline assignment will be
processed as command line options, but only to the projects that are
contained within the workspace (or the scope of the assignment).  The only
valid command line options for cmdline are -base, -global, -include, -ti,
-template, -static, -relative, -notoplevel, -value_template
and -value_project.

The second assignment is 'implicit'.  This assignment takes two different
types of values.  It takes a boolean value (0 or 1) to indicate that an
implicit project should be created in directories that contain no mpc file,
but contain project related files (source, headers, etc.).  The default
value for implicit is 0.  It also takes a charater string that represents a
base project (similar to the -base option).  In this case, implicit is
enabled and each implicitly generate project file will have the base project
or base projects (when addition is used) when the project is created.

Defaulting Behavior
-------------------
1) If a project name is not specified

   it will be defaulted to the name of the mpc file without the extension

2) If a particular list is not specified (Source_Files, Header_Files, etc.)

   all of the files in the directory will be added to the corresponding list
   by extension

3) If custom files (ex. idl files) exist in the directory and
   the custom files components (ex. IDL_Files) are left defaulted (i.e. not
   listed) or the custom files components are specified and none of the
   custom generated files are listed in the corresponding lists

   the custom files are added to the custom files component list if they
   weren't specified and all of the (would be) generated files will be added
   to the front of the corresponding lists (source, inline and header lists)

4) If files are listed in the Source_Files list and
   a corresponding header or inline file exists

   the corresponding file will be added to the corresponding list (if it
   isn't already there)

5) If a sharedname is specified and staticname is not

   staticname is assigned the sharedname value (the same applies if
   staticname is specified and sharedname is not)

6) If exename is specified then the project target is considered an
   executable.  If neither exename, sharedname or staticname are used and
   any of the source files listed contains a "main", then the project target
   is considered an executable, otherwise it is considered a library.

7) If pch_header is not specified and a header file matches *_pch.h

   it is assumed to be the precompiled header file (the same applies to
   pch_source)

8) If -relative is not used to set ACE_ROOT and the ACE_ROOT environment
   variable is set

   it will be used to set the relative value for ACE_ROOT.  If -relative is
   not used to set TAO_ROOT, it will be set from the TAO_ROOT environment
   variable.  If that is not set, the relative value of ACE_ROOT plus /TAO.

Processing Order
----------------
1) Project file is read
2) Template input file is read
3) Template file is read
4) Output project is written
