mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -04:00
new docs
This commit is contained in:
parent
a7cd155bb1
commit
4a7f71dbd7
510
panda/src/doc/ppremake-syntax.txt
Normal file
510
panda/src/doc/ppremake-syntax.txt
Normal file
@ -0,0 +1,510 @@
|
||||
NAMED SCOPES
|
||||
|
||||
Any discussion of ppremake script syntax must begin with an
|
||||
introduction to ppremake's concept of named scopes. This concept is
|
||||
relied on heavily within ppremake scripts and is the source of most of
|
||||
the scripting language's power.
|
||||
|
||||
Like many block-scoped languages, ppremake can support arbitrary
|
||||
nesting levels of scopes. Each nested scope can access variables in
|
||||
the outer scopes, and can define new variables that are local to that
|
||||
scope.
|
||||
|
||||
In ppremake, there is one (unnamed) global scope, in which all the
|
||||
variables defined in Global.pp and related files are declared. There
|
||||
are also a number of individually named scopes, one scope for each
|
||||
directory in the source hierarchy that contains a Sources.pp file.
|
||||
Each of these scopes is a child of the global scope, each of these
|
||||
defines the varibles defined within its Sources.pp file. The name of
|
||||
each scope is the name of the directory.
|
||||
|
||||
For instance, imagine the following simple directory hierarchy:
|
||||
|
||||
root
|
||||
root/Package.pp
|
||||
root/Sources.pp
|
||||
root/apple
|
||||
root/apple/Sources.pp
|
||||
root/apple/pear
|
||||
root/apple/pear/Sources.pp
|
||||
root/banana
|
||||
root/banana/Sources.pp
|
||||
|
||||
In this example, there will be five scopes, ordered like this:
|
||||
|
||||
global scope
|
||||
|
|
||||
+------+--+--+-----+
|
||||
| | | |
|
||||
root/ apple/ pear/ banana/
|
||||
|
||||
That is, there is an unnamed global scope, and four named scopes, one
|
||||
for each of the four Sources.pp files: "root/", "apple/", "pear/", and
|
||||
"banana/". Each of the named scopes is a sibling of the others, with
|
||||
no relation to the directory hierarchy; all of the named scopes are
|
||||
children of the global scope. (The trailing slash is used to
|
||||
differentiate these automatically-created named scopes from explicit
|
||||
nested scopes, described below.)
|
||||
|
||||
It is possible to access, from any one of the scopes, variables that
|
||||
are defined in another scope. The syntax to do this is discussed in
|
||||
more detail below, but for instance the expression $[FOO(apple/)]
|
||||
returns the value of $[FOO] as if it were evaluated within the "apple"
|
||||
scope.
|
||||
|
||||
Although all of the automatically-created named scopes are given a
|
||||
flat hierarchy, it is possible to define further nested scopes with
|
||||
the #begin .. #end syntax (described below) within any of the
|
||||
Sources.pp files. For instance, in the apple/Sources.pp file, you may
|
||||
have the syntax:
|
||||
|
||||
#define var1 abc
|
||||
#define var2 def
|
||||
|
||||
#begin foo
|
||||
#define var2 123
|
||||
#define var3 456
|
||||
#end foo
|
||||
|
||||
This adds a new named scope called "foo", which is a child of "apple/":
|
||||
|
||||
global scope
|
||||
|
|
||||
+------+--+--+-----+
|
||||
| | | |
|
||||
root/ apple/ pear/ banana/
|
||||
|
|
||||
foo
|
||||
|
||||
Within the apple scope, this new named scope can be referenced by the
|
||||
name "foo"; within other scopes, it must be referenced explicitly as
|
||||
"apple/foo". In the example, the value of $[var2(apple/)] is "def",
|
||||
but the value of $[var2(apple/foo)] is "123".
|
||||
|
||||
|
||||
PPREMAKE COMMANDS
|
||||
|
||||
The following commands are available in ppremake scripts. The
|
||||
commands are similar in syntax to C preprocessor directives: each
|
||||
command must be given one per line, with a hash mark (#) as the first
|
||||
non-blank character of the line.
|
||||
|
||||
Simple commands:
|
||||
|
||||
#format <format>
|
||||
|
||||
Defines the type of file that is to be generated by the next
|
||||
#output command (see #output, below). The <format> string must
|
||||
evaluate to one of a number of strings that are predefined within
|
||||
ppremake. Presently, this may be one of the following:
|
||||
|
||||
straight - the output file is generated exactly as given,
|
||||
without any additional formatting.
|
||||
|
||||
collapse - multiple consecutive blank lines are collapsed into
|
||||
one blank line, but otherwise the output is generated exactly
|
||||
as given.
|
||||
|
||||
makefile - the output file is a makefile. This implies that
|
||||
multiple consecutive blank lines may be collapsed, and long
|
||||
lines (particularly variable assignment lines) may be folded
|
||||
with the backslash character for readability.
|
||||
|
||||
#print <text>
|
||||
|
||||
Outputs the indicated text to standard error as soon as it is
|
||||
encountered. This is primarily useful for debugging ppremake
|
||||
scripts.
|
||||
|
||||
#include <filename>
|
||||
|
||||
Includes the named file. As in all the other commands given here,
|
||||
the angle brackets are not part of the literal syntax; don't
|
||||
confuse this with the C #include statement. Instead, <filename>
|
||||
means any ppremake expression which can be evaluated to a string.
|
||||
If the file does not exist, an error is generated.
|
||||
|
||||
#sinclude <filename>
|
||||
|
||||
Includes the named file if it exists, or quietly ignores it if it
|
||||
does not. This can be used to include an optional configuration
|
||||
file if it exists.
|
||||
|
||||
#call <subroutine> <params>
|
||||
|
||||
Calls the named subroutine immediately. Here <subroutine> is the
|
||||
name of the subroutine to call, and <params> is the
|
||||
comma-separated list of expressions to subsitute in for the
|
||||
subroutine's formal parameters. The subroutine must have
|
||||
previously been defined with the #defsub command (see below).
|
||||
|
||||
#error <text>
|
||||
|
||||
Generates an error and immediately terminates ppremake, reporting
|
||||
the indicated error message. Usually this appears within an #if
|
||||
.. #endif block testing for an unexpected error condition. It may
|
||||
also be used during debugging.
|
||||
|
||||
#define <varname> <value>
|
||||
|
||||
Declares a new variable within the current scope with the
|
||||
indicated name, and sets it to the indicated value. Variables and
|
||||
expressions within <value> are evaluated immediately, and the
|
||||
resulting string is stored as the new variable's value.
|
||||
|
||||
If there was already a variable within the current scope with this
|
||||
name, that variable is replaced with the new value. However, if
|
||||
there was a variable by the same name in an enclosing scope, the
|
||||
variable in the scope above is left unchanged, and a new variable
|
||||
is defined within the current scope, shadowing the variable above.
|
||||
|
||||
Note that <varname> in the above does not include the dollar sign
|
||||
and square bracket syntax. This syntax is used when evaluating
|
||||
variables, not when referring to them by name.
|
||||
|
||||
#defer <varname> <value>
|
||||
|
||||
Behaves the same as #define, but variables and expressions within
|
||||
<value> are not evaluated immediately. Instead, the <value>
|
||||
string is assigned to the variable exactly as it is now. When the
|
||||
variable is evaluated later, expressions appearing within the
|
||||
string will be evaluated at that time. This behaves kind of like
|
||||
a simple function declaration: the variable's literal value
|
||||
depends on the values of the expressions it depends on, which may
|
||||
be modified at any subsequent point (thus changing the value of
|
||||
the variable correspondingly).
|
||||
|
||||
This operation is equivalent to VARIABLE = VALUE syntax in GNU
|
||||
make (and in most makefile syntax). On the other hand, #define is
|
||||
equivalent to VARIABLE := VALUE in GNU make.
|
||||
|
||||
#set <varname> <value>
|
||||
|
||||
Changes the value of an existing variable to the indicated value.
|
||||
Like #define, variables and expressions within <value> are
|
||||
evaluated immediately.
|
||||
|
||||
This is different from #define in that (a) the variable must
|
||||
already exist (i.e. it has appeared as the target of a previous
|
||||
#define or #defer), and (b) it is possible to change the value of
|
||||
a variable in an enclosing scope (as opposed to #define and
|
||||
#defer, which can only shadow a variable in an enclosing scope,
|
||||
but cannot change the parent variable itself).
|
||||
|
||||
#map <varname> <key_varname>(<scope_names>)
|
||||
|
||||
Defines a new map variable. A map variable is a unique construct
|
||||
in ppremake which associates scopes with named keys. See the
|
||||
discussion on map variables, below.
|
||||
|
||||
Note that, like #define, #defer, and #set, <varname> and
|
||||
<key_varname> in the above do not include the dollar sign and
|
||||
square bracket syntax. This syntax is used when evaluating
|
||||
variables, not when referring to them by name.
|
||||
|
||||
#addmap <varname> <key>
|
||||
|
||||
Adds a new entry to the indicated map variable, mapping the
|
||||
indicated key string to the current scope. This command should
|
||||
normally appear within a #forscopes .. #end block, to add a series
|
||||
of keys for each of a number of different scopes.
|
||||
|
||||
|
||||
Conditional commands:
|
||||
|
||||
#if <expr>
|
||||
...
|
||||
#elif <expr>
|
||||
...
|
||||
#else
|
||||
...
|
||||
#endif
|
||||
|
||||
This defines a block of code that should only be executed if the
|
||||
condition is met. The usual semantics apply: in the case of #if,
|
||||
the immediately following code is executed only if <expr>
|
||||
evaluates true; otherwise, the condition for any subsequent #elif
|
||||
commands are tested, until one is found that evaluates true. If
|
||||
no #elif condition evaluates true, the code under #else is
|
||||
executed; in any case, normal evaluation resumes after #endif.
|
||||
|
||||
#if conditions can be nested without limit, but each #endif must
|
||||
match a corresponding #if. Error reporting for a mismatched #if
|
||||
.. #endif pair is limited.
|
||||
|
||||
As with ppremake in general, an expression is considered to be
|
||||
true if it evaluates to a nonempty string, or false if it
|
||||
evaluates to an empty string.
|
||||
|
||||
|
||||
Block commands:
|
||||
|
||||
Each of the following commands opens a block which should be closed
|
||||
with a corresponding #end command. It is akin to the matching of
|
||||
#if .. #endif. Block commands may be nested without limit. In
|
||||
ppremake, each #end has a parameter, which must match the name on
|
||||
the corresponding block command, as a visual aid to the programmer.
|
||||
|
||||
#begin <scopename>
|
||||
..
|
||||
#end <scopename>
|
||||
|
||||
Begins a new nested scope. All the variables declared within this
|
||||
block will be associated with the new scope of the indicated name,
|
||||
which will be a child of the current scope.
|
||||
|
||||
#foreach <iterator> <values>
|
||||
..
|
||||
#end <iterator>
|
||||
|
||||
Executes the nested block of code repeatedly, once for each of the
|
||||
space-separated words in <values>. The <iterator> represents the
|
||||
name of a variable that will be created each time through the
|
||||
loop, with the next value in sequence.
|
||||
|
||||
#forscopes <scopenames>
|
||||
..
|
||||
#end <scopenames>
|
||||
|
||||
Executes the nested block of code repeatedly, once for each of the
|
||||
scopes named by the space-separated list of names in <scopenames>.
|
||||
Each time through the loop, the code will be re-evaluated within a
|
||||
different named scope, potentially providing new values for all of
|
||||
the variables referenced. Unlike #foreach, no iterator variable
|
||||
is necessary.
|
||||
|
||||
#formap <iterator> <mapvarname>
|
||||
..
|
||||
#end <iterator>
|
||||
|
||||
Executes the nested block of code repeatedly, once for each key in
|
||||
the map variable. Each time through the loop, a variable named
|
||||
<iterator> is created with the value of the current key, and the
|
||||
code is also evaluated within the associated scope.
|
||||
|
||||
#defsub <subname> <params>
|
||||
..
|
||||
#end <subname>
|
||||
|
||||
Defines a new subroutine. The nested block of code will be
|
||||
evaluated when #call <subname> is later invoked. The <params>
|
||||
list is a comma-delimited list of formal parameter names; these
|
||||
names are the names of variables that will be filled in with the
|
||||
corresponding actual parameters on the #call command.
|
||||
|
||||
#defun <funcname> <params>
|
||||
..
|
||||
#end <funcname>
|
||||
|
||||
Defines a new function. This is similar to a subroutine, except
|
||||
that the function is invoked inline, like a variable: $[<funcname>
|
||||
<params>], instead of with the #call command.
|
||||
|
||||
All output generated within the function (that is, lines of text
|
||||
between #defun and #end that are not part of a command) are
|
||||
concatenated together into one string (newlines are removed) and
|
||||
returned as the result of the function.
|
||||
|
||||
#output <filename> <flags>
|
||||
..
|
||||
#end <filename>
|
||||
|
||||
Sends all output within the block (that is, lines of text between
|
||||
#output and #end that are not part of a command) to the indicated
|
||||
filename. The <flags> are an optional space-separated list of
|
||||
keywords that modify the output behavior, presently the only
|
||||
recognized flag is "notouch".
|
||||
|
||||
If the file does not exist, it is created. If the file already
|
||||
existed and its contents will be changed by this command, a
|
||||
message is printed to the user and the file is rewritten.
|
||||
|
||||
If the file already existed and its contents would not have been
|
||||
changed by this command, nothing is printed to the user, although
|
||||
the file is still rewritten (and the file modification timestamp
|
||||
is correspondingly updated with the current time and date).
|
||||
However, if the keyword "notouch" is included among the optional
|
||||
<flags> following the filename, the file (and consequently its
|
||||
timestamp) will not be modified unless the contents are actually
|
||||
different.
|
||||
|
||||
|
||||
VARIABLE REFERENCES
|
||||
|
||||
The ppremake syntax supports three different kinds of variable
|
||||
references: ordinary variables, map variables, and function calls.
|
||||
|
||||
Ordinary variable references:
|
||||
|
||||
Variables in ppremake are always referenced using a leading dollar
|
||||
sign immediately followed by the name of the variable enclosed in
|
||||
square brackets. This syntax was chosen to resemble the GNU make
|
||||
variable syntax, but to be visually distinct to avoid confusion with
|
||||
actual make variables (which we might be writing to a makefile).
|
||||
|
||||
Note that the dollar sign and square brackets are not actually part
|
||||
of the variable names, but are simply the syntax used to reference
|
||||
the variable. However, this syntax is used throughout this document
|
||||
to refer to variables, to clarify that we are referring to ppremake
|
||||
variable names.
|
||||
|
||||
Common ordinary variables that might be referenced in this way are
|
||||
ppremake built-in variables like $[DIRNAME] or $[PLATFORM], or any
|
||||
user-defined variable created with #define or #defer. Since
|
||||
environment variables are also automatically pulled into the
|
||||
ppremake variable space (similar to the behavior of make),
|
||||
environment variables may also be referenced in this way, although
|
||||
writing scripts that depend on environment variables is not
|
||||
recommended as it is not as portable (not every platform gives the
|
||||
user easy access to environment variables).
|
||||
|
||||
There are also some fancy ways to expand ordinary variables.
|
||||
|
||||
Inline pattern substitution:
|
||||
|
||||
Borrowing more syntax from GNU make, ppremake allows you to
|
||||
modify the contents of the variable according to a pattern-based
|
||||
substitution, similar to the $[patsubst] function. The syntax
|
||||
is $[varname:<from>=<to>], where <from> and <to> are filename
|
||||
patterns each involving a percent sign (%). The percent sign
|
||||
stands for the part of the filename that remains the same; the
|
||||
rest is modified accordingly. For instance, $[file:%.c=%.o]
|
||||
will expand the variable $[file] and automatically replace a .c
|
||||
extension with .o. It is equivalent to $[patsubst
|
||||
%.c,%.o,$[file]]. See ppremake-variables.txt.
|
||||
|
||||
Inline foreign scoping:
|
||||
|
||||
A special ppremake syntax exists to evaluate a variable within
|
||||
one or more different named scopes. The syntax here is
|
||||
$[varname(<scope names>)], where <scope names> represents a
|
||||
space-separated list of words that name the scope or scopes
|
||||
within which the variable is to be evaluated. The result is the
|
||||
space-separated concatenation of the values of the variable in
|
||||
each of the named scopes.
|
||||
|
||||
To make a contrived example, suppose you had a scope named
|
||||
"foo", in which a variable $[LETTER] is defined to be the string
|
||||
"alpha", and a scope named "bar", in which a variable $[LETTER]
|
||||
is defined to be the string "beta". In the current scope,
|
||||
however, $[LETTER] is defined as "none".
|
||||
|
||||
In this example, the expression $[LETTER] evaluates to "none",
|
||||
but $[LETTER(foo)] evaluates to "alpha" and $[LETTER(foo bar)]
|
||||
evaluates to "alpha beta".
|
||||
|
||||
Map variables:
|
||||
|
||||
A map variable is a special ppremake construct to index into a table
|
||||
of named scopes by key. The map variable is an indexed lookup into
|
||||
a set of named scopes, to determine in which scope a given variable
|
||||
has a particular value.
|
||||
|
||||
To define a map variable, you need to have a set of named scopes,
|
||||
and an ordinary "key" variable that has been declared in each of
|
||||
them. The syntax is:
|
||||
|
||||
#map <varname> <key_varname>(<scope_names>)
|
||||
|
||||
Where <varname> is the name of the map variable you are declaring,
|
||||
<key_varname> is the name of the key variable that exists in each of
|
||||
the scopes, and <scope_names> is the list of scope names over which
|
||||
the map variable is being built.
|
||||
|
||||
This builds up an index into <scope_names> based on the value of the
|
||||
$[<key_varname>] within each scope. Within each scope, the
|
||||
$[<key_varname>] variable is divided at the spaces into words, and
|
||||
each word is added to the index as a key referencing this scope.
|
||||
|
||||
|
||||
For example, consider the $[LETTER] example above. You could define
|
||||
a simple map variable thus:
|
||||
|
||||
#map letmap LETTER(foo bar)
|
||||
|
||||
This defines a new map variable called "letmap" that maps into the
|
||||
two named scopes "foo" and "bar", with the key being the value of
|
||||
$[LETTER] in each of those two scopes. That is, evaluating letmap
|
||||
with the string "alpha" will return the scope "foo", while
|
||||
evaluating letmap with the string "beta" will return the scope
|
||||
"bar".
|
||||
|
||||
In other words, letmap is now a map variable with two key/value
|
||||
pairs. The two keys are "alpha" and "beta", which map to the two
|
||||
scopes "foo" and "bar", respectively. The keys represent the values
|
||||
of the ordinary variable $[LETTER] as evaluated within the two
|
||||
scopes.
|
||||
|
||||
Note the similarity to the $[LETTER(foo bar)] syntax, which
|
||||
incidentally returns the string "alpha beta"--the same two keys that
|
||||
become part of the map variable. A map variable is a lot like an
|
||||
inline foreign scoping reference, except it remembers which scope
|
||||
each key came from.
|
||||
|
||||
|
||||
To look up scopes in a map variable, use the syntax:
|
||||
|
||||
$[<varname> <expr>,<key>]
|
||||
|
||||
This returns the value of <expr> as evaluated within whatever scope
|
||||
is referenced by the string <key>. To continue our example,
|
||||
|
||||
$[letmap $[upcase $[LETTER]],alpha]
|
||||
|
||||
will evaluate $[upcase $[LETTER]] in the "foo" scope--that is, the
|
||||
scope associated with the key "alpha"--which incidentally returns
|
||||
the string "ALPHA".
|
||||
|
||||
It is also legal to look up multiple scopes at once. If <key>
|
||||
contains spaces, it is divided up into words at the spaces, and each
|
||||
word is taken as a separate key. The result of the map variable
|
||||
reference is the concatenation of all the evaluations of the
|
||||
expressions in all the matched keys.
|
||||
|
||||
|
||||
It is sometimes useful to ask whether a key is defined in a map
|
||||
variable or not. The $[unmapped] function can do this; see
|
||||
ppremake-variables.txt. Also, the $[closure] function is useful for
|
||||
evaluating map variables recursively; see ppremake-variables.txt.
|
||||
|
||||
|
||||
Function calls:
|
||||
|
||||
Function calls are a little more conventional to other scripting
|
||||
languages. User functions are defined with the syntax:
|
||||
|
||||
#defun <funcname> <params>
|
||||
..
|
||||
#end <funcname>
|
||||
|
||||
where <funcname> is any arbitrary function name, and <params> is an
|
||||
optional list of comma-separated formal parameters. Any text that
|
||||
appears between #defun and its matching #end (and is not part of
|
||||
some other command) is returned as the result of the function.
|
||||
|
||||
For instance:
|
||||
|
||||
#defun updowncase abc,def
|
||||
#if $[def]
|
||||
$[upcase $[abc]]
|
||||
#else
|
||||
$[downcase $[abc]]
|
||||
#endif
|
||||
#end updowncase
|
||||
|
||||
This defines a function with two parameters. If the second
|
||||
parameter is true (nonempty), the result of the function is the
|
||||
upcase of the first parameter; otherwise, the result of the function
|
||||
is the downcase of the first parameter.
|
||||
|
||||
To invoke the function, the syntax is somewhat like a variable
|
||||
expansion:
|
||||
|
||||
$[<function> <params>]
|
||||
|
||||
E.g.:
|
||||
|
||||
$[updowncase $[filename],]
|
||||
|
||||
Many pre-defined functions are also available; see
|
||||
ppremake-variables.txt.
|
@ -5,6 +5,14 @@ heavily from that of GNU makefile syntax, with GNU make's parentheses
|
||||
replaced by square brackets to prevent confusion with actual makefile
|
||||
syntax.
|
||||
|
||||
Note that the dollar sign and square brackets are not actually part of
|
||||
the variable names, but are simply the syntax used to reference the
|
||||
variable. This syntax is included with each variable definition in
|
||||
this document, because that is how you are most likely to see the
|
||||
variable references.
|
||||
|
||||
|
||||
|
||||
The general convention is for variables that are built into ppremake,
|
||||
or defined by the system ppremake scripts in the $DTOOL root
|
||||
directory, should be defined with uppercase letters. User-defined
|
||||
@ -14,7 +22,6 @@ lowercase letters. However, following the GNU makefile convention,
|
||||
all built-in function names are lowercase.
|
||||
|
||||
|
||||
|
||||
The following variables are built into the ppremake executable, and
|
||||
are always defined:
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user