parrotcode: Parrot Configuration System | |
Contents | Configuration |
docs/configuration.pod - Parrot Configuration System
Parrot configuration is broken up into steps. Each step contains several related prompts, probes, or generations. Steps should be mostly of a single type, though some overlap is allowed (for example, allowing a probe to ask the user what to do in an exceptional situation).
The directory config contains subdirectories for each type of step. Each step should consist of exactly one .pm file and any number of supporting .c, .in, etc. files. Any supporting files should be in a folder whose name is the same as the basename of the step's .pm file; for example, if foo.pm uses bar_c.in, bar_c.in should be in a directory called foo; the full path might be config/auto/foo/bar_c.in.
Generally,
when adding a new component to the configuration process you should add a new step unless that component clearly belongs in a current step.
For example,
if you added a new user-configurable type called FOOVAL
,
you would add the code used to determine its size in config/auto/sizes.pm.
However,
if you were determining what dynaloading capabilities are available,
you would create a new step.
Initialization steps are run before any other steps. They do tasks such as preparing the configuration system's data structures and checking the MANIFEST. New initialization steps will only be added when the configuration system is getting significant new capabilities. They're kept in the directory config/init.
Prompts ask the user for some information. These should be used sparingly. A step containing prompts is an interactive step. Interactive steps should be in the config/inter folder.
Interactive steps often include simple probes to determine good guesses of what the user will answer. See "Prompt or Probe?" for more information.
Note that,
by default,
these prompts are turned off.
To enable them run Configure.pl with the --ask
option.
Probes are automated tests of some feature of the computer. These should be used wherever a value will not need to be modified often by the user. A step containing probes is an automatic step. Automatic steps should be in the config/auto folder.
Generations create files needed after configuration has completed, such as Makefiles and configuration headers. A step containing generations is a generation step. Generation steps should be in the config/gen folder.
Templates for files to be generated usually have the extension .in. There are variable substitutes and funny macros like 'CONDITIONED_LINE' and 'INVERSE_CONDITIONED_LINE'.
It can sometimes be hard to decide whether a given step should be an automatic or an interactive step. The guiding question is Would a user ever want to change this?, or conversely, Is this something that can be completely determined without user intervention? A step figuring out what the compiler's command is would probably be an interactive step; conversely, a step figuring out if that command is connected to a specific compiler (like gcc) would be an automatic step.
The configuration system gets its own configuration data from,
and is invoked via,
the Configure.pl script.
The system is invoked by instantiating a Parrot::Configure object,
registering one or more steps with that object,
and then calling Parrot::Configure::runsteps()
.
New steps should be added in one of the four folders mentioned above.
All steps are really classes; each exists in a unique namespace.
The namespace used depends on the step's relative path in the source tree sans the config prefix.
For example,
the step config/init/defaults.pm uses the init::defaults
namespace.
Each step inherits its constructor and some other methods from lib/Parrot/Configure/Step/Base.pm.
Each step needs to define only two methods: _init()
and runstep()
.
The _init()
method should follow the following example,
defining three elements within an internal hash:
sub _init {
my $self = shift;
my %data;
$data{description} = q{This is the step description};
$data{args} = [ qw( optional arguments ) ];
$data{result} = q{};
return \%data;
}
description
description
is the most important as it is used extensively within lib/Parrot/Configure.pm
. Determining if your compiler supports computed goto...
Generating config.h...
Determining if your compiler supports computed goto...done.
args
result
result
is initialized to an empty string mainly to quiet 'uninitialized variable' warnings. Most configuration steps override the result
value inside their runstep()
method.1
if the step accomplishes what it is intended to do. Otherwise, the step should simply return
, i.e., return an undefined value.The configuration system won't execute your step by default unless it's specifically told to. To do this, edit lib/Parrot/Configure/Step/List.pm. Steps are run in the order in which that are registered with the Parrot::Configure object.
Various utility functions for configuration steps are provided by the Parrot::Configure::Step module.
A template for a new step might look like this:
package auto::newstep;
use strict;
use warnings;
use vars qw($description $result @args);
use base qw(Parrot::Configure::Step::Base);
use Parrot::Configure::Step;
sub _init {
my $self = shift;
my %data;
$data{description} = q{This is the step description};
$data{args} = [ qw( optional arguments ) ];
$data{result} = q{};
return \%data;
}
sub runstep {
my ($self, $conf) = @_
...
if ($success) {
$self->set_result('yes');
return 1;
} else {
$self->set_result('no');
return;
}
}
The step's runstep()
method should return 1
upon success and do a bare return on failure (thereby returning an undefined value).
Command-line arguments look like /--[-\w]+(=.*)?/
; the equals sign separates the name and the value. If the value is omitted, it's assumed to be 1. The options --help
and --version
are built in to Configure; any others are defined by steps.
Command-line arguments are now processed by process_options()
, a subroutine exported by Parrot::Configure::Options. If you add a new option, don't forget to add it to this documentation and to two locations in lib/Parrot/Configure/Options.pm:
Parrot::Configure::Options::get_valid_options()
; andParrot::Configure::Options::print_help()
.Arguments passed to Configure.pl are held in a Parrot::Configure::Data object stored inside the Parrot::Configure object. The options data object may be accessed via the "options" in Parrot::Configure method.
Steps use the args
method to list any options they're interested in. They should be listed without the dashes.
The second step is config/init/defaults.pm, which sets up some defaults in a Parrot::Configure::Data object contained by the main Parrot::Configure object. It can be accessed via the "data" in Parrot::Configuremethod. You get and set configuration system's data by interacting with this object. Some of its methods are summarized below.
get(keys)
set(key, value, [key, value, ...])
add(delim, key, value, [key, value, ...])
keys()
dump()
eval
ed by Perl to create a hash representing the configuration system's data.Some configuration items, by convention, have a special meaning (mainly prefixes) and are handled with some magic internally.
i_(\w+)
include filesHAS_(\w+)
featuresTEMP_(\w+)
temporary settingsParrot configuration is currently jump-started by extracting considerable information from variables associated with the instance of Perl 5 which the user is using to run Configure.pl. These variables are largely looked up in the %Config
found in the Perl 5 Config.pm, but may also be sought in Perl 5 special variables such as $^O
. All such lookups should be done in configuration step init::defaults
and only in that step. Special accessors are available for working with such variables; see config/init/defaults.pm and lib/Parrot/Configure/Data.pm.
The Parrot configuration system was created by Brent Dax and has been heavily mangled by Joshua Hoblitt.
Parrot::Configure, Parrot::Configure::Data, Parrot::Configure::Step, Parrot::Configure::Step::Base
|