Thread: [Module-build-checkins] Module-Build/website dEx.pod,NONE,1.1
Status: Beta
Brought to you by:
kwilliams
From: Ken W. <kwi...@us...> - 2004-11-09 20:52:50
|
Update of /cvsroot/module-build/Module-Build/website In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv820 Added Files: dEx.pod Log Message: Randy's original version --- NEW FILE: dEx.pod --- =head1 NAME dEx - Dependency Expression Language =head1 SYNOPSIS # Create custom macros that can be expanded in other expressions define core = File::Spec in [0.80- !0.86] && Cwd > 2; define xml = HAS_LIB('xml2') && # <= builtin functions HAS_INCLUDE('libxml/tree.h', 'libxml/parser.h'); # Create tags that can be specified to select a # particular branch of an expression. choice dbd = (DBD::pg > 1.0 && DateTime::Format::pg) as :pg || (DBD::mysql && DateTime::Format::mysql) as :mysql; # The "master" expression; other than assignments, only one expr allowed Module::Build#(yaml_support && c_support) && # <= req specific features (( {OSNAME} in ['*nix' 'MacOS'] && {ITHREADS} && {core} && ( {xml} || XML::Simple ) && {dbd} ) || ( {OSNAME} == 'MSWin32' && {core} && {dbd} )) =head1 DESCRIPTION A dEx program concists of zero or more macro definitions, and zero or more choice selectors, and a single mandatory master expression. The program produces a true value if the master expression evalutes to true, otherwise the result of the program is false. An empty program is considered true. In addition to returning true or false. Evaluation produces detailed information about what conditions were satisfied and, more importantly, which ones were not. [Reported failures will likely be filtered. For example, if you there are a string of expressions grouped by AND operators, and one of those expressions is {OSNAME} == 'MSWin32' and the current OS is 'Linux' then that branch can be elminated from the report since there is no sensible way to correct that dependency... Unless there is no alternative, in which case it would be necessary to report that it is incompatible with the current OS.] =head2 Simple Expressions =over 4 =item * Checking for the presence of a module (any version). The simplest expresion is one that simply checks for the presence of a module, regardless of version: File::Spec The above expression will return true if the module is present. In general, it evaluates to the version of the installed module unless the module does not define a version in which case it still evaluates to a true value that is not a version. [???] =item * Checking for particular versions of a module with relational operators. You can use relational operators to check that the version of a module is relative to a particular version number: File::Spec > 0.80 File::Spec == 0.86 File::Spec > 0.80 && File::Spec != 0.85 The relational operators include: C<E<lt>>, C<E<lt>=>, C<E<gt>>, C<E<gt>=>, as well as the equality operators: C<==>, C<!=> The equality operators are overloaded for testing both versions and strings. [I think someone requested C<eq> and C<ne> for string comparisons so as to be more perl-like. Technically its simple to provide them as synonyms. But I would caution against trying to look too perl-like. When MB moves to Parrot, it's going to provide a build system for many more languages other than just perl. I originally chose to use one type of operator to make the language definition simpler even though it makes the implementation slightly more complex because of the overloading of the operator for different types of comparison.] =item * Checking for particular versions of a module with the set operator. The set operator provides a convenient shorthand for determining if a module's version meets complex requirements. For example the last example in the section above could also be written as: File::Spec in [0.80- !0.85] The elements of the set are ranges. Ranges can be closed: C<0.80-1.0> (from version 0.80 up to and including 1.0) or they can be open on either end C<-1.0> (any version up to and including 1.0), C<1.0-> (version 1.0 and greater). If a range is closed then the right-hand side version must be greater than or equal to the left-hand side. Ranges and versions can also be negated C<!1.0-1.99>. Successive elements of a set override previous elements, so that if there are any overlaps, the later element wins out. In the previous example: File::Spec in [0.80- !0.85] a version of 0.85 will fail even thought the first element of the set is a range that includes 0.85 because the subsequent element overrides it. =item * Checking for features Some modules provide optional features that may or may not be present or enabled. You can check for the presence of features: Module::Build#(yaml_support && c_support) Features are specified by following a module name with a hash and one or more feature names in parenthesis separated by the logical and operator C<&&>. [???allow all logical operators???] [Does it make sense to allow something like: Module::Build#(yaml_support) in [0.20- !0.23] where we check for version in the same expression where we check for features???] =back =head2 Combining Simple Expressions More complex expressions can be formed by joining simple expressions with the logical operators: C<&&>, C<||>, and C<^^> The logical and operator, C<&&>, returns true if the expressions on both the left-hand side and the right-hand side are true. The logical or operator, C<||>, returns true if either the expression on the left-hand side or the right-hand side are true. The logical exclusive-or operator, C<^^>, returns true if only one of the expressions on the left-hand side or the right-hand side are true. =head2 Grouping Expressions Parenthesis are used to group expression. =head2 Builtin Macros There are two types of macros. Although they look the same, they function a little differently. Some macros, like C<{OSNAME}> return a string. User defined operators are similar, though in general they generally evaluate to a more complex expression. Other macros, like C<{ITHREADS}>, simply return true or false. [???Is it an error to evaluate {OSNAME} as a boolean, outside of a comparison???] =over 4 =item * B<{OSNAME}> Evaluates to a string containing the name of the current operating system. Besides using C<{OSNAME}> with comparitive operators: {OSNAME} == 'Linux' It can also be used with the set operator: {OSNAME} in ['Linux' 'BSD' 'MacOSX'] =item * B<{ITHREADS}> Evaluates to true if ithreads are enabled. =back =head2 Builtin Functions =over 4 =item * B<HAS_INCLUDE()> Takes a list of one or more strings that are the names of include files, and it returns true if all of the named files are present in the include path. =item * B<HAS_LIB()> Takes a list of one or more strings that are the names of libraries, and it returns true if all of the named libraries are present in the library path. =item * B<HAS_PROGRAM()> Takes a list of one or more strings that are the names of programs, and it returns true if all of the named programs are present in the path. =back =head2 Defining and Using Custom Macros A macro can be defined with the following syntax: define <identifier> = <expression> ; where <identifier> is a valid identifier, and <expression> is any valid expression of arbitrary complexity. For example: define dbd = DBD::pg || DBD::mysql; The above defines a macro named C<dbd>. It can be expanded into another expression by placing the name between braces, Eg define store = BerkeleyDB || {dbd} Macros are not evaluated at the time they are encountered, although they are parsed and checked for correctness. The reason they are not evaluated immediately is that depending on their placement in the master expression, they may never need to be evaluted. For example, in the last expression above, if BerkeleyDB is present it is unnecessary to check the expression in {dbd}. =head2 Making Choices Sometimes it's desirable to allow the use to specify constraints on certain expressions. For example, the {dbd} macro we used above: define dbd = DBD::pg || DBD::mysql; Allows for the presence of either DBD driver. Sometimes we would like to be able to eliminate one of those alternatives from consideration. We can do that with the <choice> macro definition operator. choice dbd = DBD::pg as :pg || DBD::mysql as :mysql; When defined this way it still works like normal macro definitions except that now it will accept options which the user can supply. If the user supplies the option 'mysql' to the interpreter, then the test for DBD::pg will be eliminated from the expression when it is compiled, so that it will never be considered during evaluation. C<choice> statements can be arbitrarily complex. Just place the expression to be tagged in parenthesis. choice dbd = (DBD::pg && DateTime::Format::pg) as :pg || (DBD::mysql && DateTime::Format::mysql) as :mysql; When the interpreter sees an expression like the above, what it is essentially doing is something like: define pg = DBD::pg && DateTime::Format::pg; define mysql = DBD::mysql && DateTime::Format::mysql; choice dbd = :pg || :mysql; The reason for the strange notation of using a colon in front of the macro name is that it allows us to refer to the name of a variable without invoking that name. This is somewhat analogous to Ruby's symbols or to what some languages refer to as atoms. =head2 More about version specifications Are versions two integers separated by a decimal or decimal numbers? More than one decimal? (as in perl versions) Alpha/Beta versions? Underscores & letters? use version.pm if present or only if included in core (perl 5.8+)? =head1 DETAILS =head2 Types =over =item * Package Name =item * Version =item * Range =item * String =item * Set =item * Tag =back =head2 Operators =over =item * Relational operators =item * Equality operators =item * Set operator =item * Tag operator =item * Logical operators =item * Assignment operator =back =head2 Operator Precedence Relational operators <, <=, >, >= Equality operators ==, != Set operator in Tag operator as Logical operators &&, ||, ^^ Assignment operator = =cut |