# Copyright (C) 2004-2008, Parrot Foundation. # $Id: configuration.pod 37201 2009-03-08 12:07:48Z fperrad $ =pod =head1 NAME docs/configuration.pod - Parrot Configuration System =head1 DESCRIPTION Parrot configuration is broken up into I<steps>. Each step contains several related I<prompts>, I<probes>, or I<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 F<config> contains subdirectories for each type of step. Each step should consist of I<exactly one> F<.pm> file and any number of supporting F<.c>, F<.in>, etc. files. Any supporting files should be in a folder whose name is the same as the basename of the step's F<.pm> file; for example, if F<foo.pm> uses F<bar_c.in>, F<bar_c.in> should be in a directory called F<foo>; the full path might be F<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 I<clearly> belongs in a current step. For example, if you added a new user-configurable type called C<FOOVAL>, you would add the code used to determine its size in F<config/auto/sizes.pm>. However, if you were determining what dynaloading capabilities are available, you would create a new step. =head2 Initialization Steps I<Initialization steps> are run before any other steps. They do tasks such as preparing the configuration system's data structures and checking the F<MANIFEST>. New initialization steps will only be added when the configuration system is getting significant new capabilities. They're kept in the directory F<config/init>. =head2 Prompts Prompts ask the user for some information. These should be used sparingly. A step containing prompts is an I<interactive step>. Interactive steps should be in the F<config/inter> folder. Interactive steps often include simple probes to determine good guesses of what the user will answer. See L</Prompt or Probe?> for more information. Note that, by default, these prompts are turned off. To enable them run F<Configure.pl> with the C<--ask> option. =head2 Probes 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 I<automatic step>. Automatic steps should be in the F<config/auto> folder. =head2 Generations Generations create files needed after configuration has completed, such as Makefiles and configuration headers. A step containing generations is a I<generation step>. Generation steps should be in the F<config/gen> folder. Templates for files to be generated usually have the extension F<.in>. There are variable substitutes and funny macros like C<#IF> and C<#UNLESS> (conditional lines). =head2 Prompt or Probe? It can sometimes be hard to decide whether a given step should be an automatic or an interactive step. The guiding question is I<Would a user ever want to change this?>, or conversely, I<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 F<gcc>) would be an automatic step. =head2 Configuring Configuration The configuration system gets its own configuration data from, and is invoked via, the F<Configure.pl> script. The system is invoked by instantiating a L<Parrot::Configure> object, registering one or more steps with that object, and then calling C<Parrot::Configure::runsteps()>. =head2 Adding New Steps 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 F<config> prefix. For example, the step F<config/init/defaults.pm> uses the C<init::defaults> namespace. Each step inherits its constructor and some other methods from F<lib/Parrot/Configure/Step.pm>. Each step needs to define only two methods: C<_init()> and C<runstep()>. The C<_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{result} = q{}; return \%data; } =over 4 =item C<description> Of these three elements, C<description> is the most important as it is used extensively within C<lib/Parrot/Configure.pm>. Returns a short descriptive message that should be printed before the step executes. Some example descriptions: =over 4 =item F<config/auto/cgoto.pm> Does your compiler support computed goto... =item F<gen/config_h.pm> Generate C headers... =back Note that on non-interactive steps, the text I<done> will be printed after the description when the step finishes executing; for example, the user will see: Does your compiler support computed goto..............done. =item C<result> The C<result> is initialized to an empty string mainly to quiet 'uninitialized variable' warnings. Most configuration steps override the C<result> value inside their C<runstep()> method. =item C<runstep()> This method is called to actually execute the step. The return value should be C<1> if the step accomplishes what it is intended to do. Otherwise, the step should simply C<return>, I<i.e.>, return an undefined value. =back The configuration system won't execute your step by default unless it's specifically told to. To do this, edit F<lib/Parrot/Configure/Step/List.pm>. Steps are run in the order in which that are registered with the L<Parrot::Configure> object. Various utility functions for configuration steps are provided by the L<Parrot::Configure::Utils> module. A template for a new step might look like this: package auto::newstep; use strict; use warnings; our qw($description $result); use base qw(Parrot::Configure::Step); use Parrot::Configure::Utils; sub _init { my $self = shift; my %data; $data{description} = q{This is the step description}; $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 C<runstep()> method should return C<1> upon success and do a bare return on failure (thereby returning an undefined value). =head2 Command-line Arguments Command-line arguments look like C</--[-\w]+(=.*)?/>; the equals sign separates the name and the value. If the value is omitted, it's assumed to be C<1>. The options C<--help> and C<--version> are built in to Configure; any others are defined by steps. Command-line arguments are now processed by C<process_options()>, a subroutine exported by L<Parrot::Configure::Options>. If you add a new option, don't forget to add it to this documentation and to appropriate locations. Most options should be added to C<@shared_valid_options> in F<lib/Parrot/Configure/Options/Conf/Shared.pm>. Arguments passed to F<Configure.pl> are held in a L<Parrot::Configure::Data> object stored inside the L<Parrot::Configure> object. The options data object may be accessed via the C<Parrot::Configure::options()> method. =head2 Configuration by File As an alternative to typing a long string of options on the command-line, Parrot can now be configured from a configuration file. You put the options in a configuration file, then call F<Configure.pl> as follows: perl Configure.pl --file=/path/to/config/file That's it! No other command-line arguments needed (or permitted)! To learn how to create such a configuration file, call: perldoc Configure.pl =head2 Building Up Configuration Data The second step is F<config/init/defaults.pm>, which sets up some defaults in a L<Parrot::Configure::Data> object contained by the main L<Parrot::Configure> object. It can be accessed via the C<Parrot::Configure::data()> method. You get and set configuration system's data by interacting with this object. Some of its methods are summarized below. =over 4 =item C<get(keys)> Returns the values for the given keys. =item C<set(key, value, [key, value, ...])> Sets the given keys to the given values. =item C<add(delim, key, value, [key, value, ...])> Sets the given keys to the given values or appends values delimited by I<delim> to existing keys. =item C<keys()> Returns a list of all keys. =item C<dump()> Returns a string that can be C<eval>ed by Perl to create a hash representing the configuration system's data. See the L<Parrot::Configure::Data> documentation for further details. =back =head2 Special Configuration Items Some configuration items, by convention, have a special meaning (mainly prefixes) and are handled with some magic internally. =over 4 =item C<i_(\w+)> include files defines or undefs PARROT_HAS_HEADER_XXX in F<include/parrot/has_header.h> =item C<HAS_(\w+)> features defines PARROT_HAS_XXX in F<include/parrot/has_header.h> =item C<TEMP_(\w+)> temporary settings These settings are deleted before F<lib/Parrot/Config.pm> is written. These entries are only used e.g. for Makefile creation. =back =head2 Accessing Configuration Information via Perl 5 Variables Parrot 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 F<Configure.pl>. These variables are largely looked up in the C<%Config> found in the Perl 5 F<Config.pm>, but may also be sought in Perl 5 special variables such as C<$^O>. All such lookups should be done in configuration step C<init::defaults> and B<only> in that step. Special accessors are available for working with such variables; see F<config/init/defaults.pm> and F<lib/Parrot/Configure/Data.pm>. =head1 HISTORY The Parrot configuration system was created by Brent Dax and has been heavily mangled by Joshua Hoblitt. James Keenan refactored the configuration system. =head1 SEE ALSO L<Parrot::Configure>, L<Parrot::Configure::Data>, L<Parrot::Configure::Utils>, L<Parrot::Configure::Step> =cut