Index: lib/Parrot/Configure/Options.pm =================================================================== --- lib/Parrot/Configure/Options.pm (revision 0) +++ lib/Parrot/Configure/Options.pm (revision 0) @@ -0,0 +1,307 @@ +# Copyright (C) 2001-2006, The Perl Foundation. +# $Id: Options.pm 17903 2007-03-31 15:53:17Z jkeenan $ +package Parrot::Configure::Options; +use strict; +use warnings; +use base qw( Exporter ); +our @EXPORT_OK = qw( + process_options + get_valid_options +); + +sub get_valid_options { + return qw(ask bindir cage cc ccflags ccwarn cgoto cxx datadir + debugging define exec-prefix execcapable floatval gc help icu-config + icudatadir icuheaders icushared includedir infodir inline intval + jitcapable ld ldflags lex libdir libexecdir libs link linkflags + localstatedir m maintainer mandir miniparrot nomanicheck oldincludedir + opcode ops optimize parrot_is_shared pmc prefix profile sbindir + sharedstatedir step sysconfdir verbose verbose-step version without-gdbm + without-gmp without-icu yacc); +} + +sub process_options { + my $optionsref = shift; + my @valid_opts = get_valid_options(); + $optionsref->{argv} = [] + unless defined $optionsref->{argv}; + $optionsref->{script} = q{Configure.pl} + unless defined $optionsref->{script}; + die "Must provide argument 'parrot_version'" + unless $optionsref->{parrot_version}; + die "Must provide argument 'svnid'" + unless $optionsref->{svnid}; + my %args; + for (@{$optionsref->{argv}}) { + my ( $key, $value ) = m/--([-\w]+)(?:=(.*))?/; + $key = 'help' unless defined $key; + $value = 1 unless defined $value; + + unless ( grep $key eq $_, @valid_opts ) { + die qq/Invalid option $key. See "perl Configure.pl --help" for valid options\n/; + } + + for ($key) { + if ($key =~ m/version/) { + print_version_info($optionsref); + return; + } + + if ($key =~ m/help/) { + print_help($optionsref); + return; + } + $args{$key} = $value; + } + } + + $args{debugging} = 1 + unless ( ( exists $args{debugging} ) && !$args{debugging} ); + $args{maintainer} = 1 if defined $args{lex} or defined $args{yacc}; + return \%args; +} + +################### SUBROUTINES ################### + +sub print_version_info { + my $argsref = shift; + print "Parrot Version $argsref->{parrot_version} Configure 2.0\n"; + print "$argsref->{svnid}\n"; +} + +sub print_help { + my $argsref = shift; + print <<"EOT"; +$argsref->{script} - Parrot Configure 2.0 + +General Options: + + --help Show this text + --version Show version information + --verbose Output extra information + --verbose=2 Output every setting change + --verbose-step=N Set verbose for step N only + --verbose-step=regex Set verbose for step matching description + --nomanicheck Don't check the MANIFEST + --step=(gen::languages) + Execute a single configure step + + --ask Have Configure ask for commonly-changed info + +Compile Options: + + --debugging=0 Disable debugging, default = 1 + --inline Compiler supports inline + --optimize Optimized compile + --optimize=flags Add given optimizer flags + --parrot_is_shared Link parrot dynamically + --m=32 Build 32bit executable on 64-bit architecture. + --profile Turn on profiled compile (gcc only for now) + --cage [CAGE] compile includes many additional warnings + + --cc=(compiler) Use the given compiler + --ccflags=(flags) Use the given compiler flags + --ccwarn=(flags) Use the given compiler warning flags + --cxx=(compiler) Use the given C++ compiler + --libs=(libs) Use the given libraries + --link=(linker) Use the given linker + --linkflags=(flags) Use the given linker flags + --ld=(linker) Use the given loader for shared libraries + --ldflags=(flags) Use the given loader flags for shared libraries + --lex=(lexer) Use the given lexical analyzer generator + --yacc=(parser) Use the given parser generator + + --define=inet_aton Quick hack to use inet_aton instead of inet_pton + +Parrot Options: + + --intval=(type) Use the given type for INTVAL + --floatval=(type) Use the given type for FLOATVAL + --opcode=(type) Use the given type for opcodes + --ops=(files) Use the given ops files + --pmc=(files) Use the given PMC files + + --cgoto=0 Don't build cgoto core - recommended when short of mem + --jitcapable Use JIT + --execcapable Use JIT to emit a native executable + --gc=(type) Determine the type of garbage collection + type=(gc|libc|malloc|malloc-trace) default is gc + +External Library Options: + + --without-gmp Build parrot without GMP support + --without-gdbm Build parrot without GDBM support + +ICU Options: + + For using a system ICU, these options can be used: + + --icu-config=/path/to/icu-config + Location of the script used for ICU autodetection. + You just need to specify this option if icu-config + is not in you PATH. + + --icu-config=none can be used to disable the autodetection feature. + It will also be disabled if you specify any other + of the following ICU options. + + If you do not have a full ICU installation: + + --without-icu Build parrot without ICU support + --icuheaders=(path) Location of ICU headers without /unicode + --icushared=(flags) Full linker command to create shared libraries + --icudatadir=(path) Directory to locate ICU's data file(s) + +Other Options (may not be implemented): + + --maintainer Create imcc's parser and lexer files. Needs a working + parser and lexer. + --miniparrot Build parrot assuming only pure ANSI C is available + +Install Options: + + --prefix=PREFIX install architecture-independent files in PREFIX + [/usr/local] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + + By default, `make install' will install all the files in + `/usr/local/bin', `/usr/local/lib' etc. You can specify + an installation prefix other than `/usr/local' using `--prefix', + for instance `--prefix=\$HOME'. + + For better control, use the options below. + + Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] + +EOT +}; + +1; + +#################### DOCUMENTATION #################### + +=head1 NAME + +Parrot::Configure::Options - Process command-line options to F + +=head1 SYNOPSIS + + use Parrot::Configure::Options qw( process_options ); + + $args = process_options( { + argv => [ @ARGV ], + script => $0, + parrot_version => $parrot_version, + svnid => + '$Id: Options.pm 17903 2007-03-31 15:53:17Z jkeenan $', + } ); + + @valid_options = get_valid_options(); + +=head1 DESCRIPTION + +Parrot::Configure::Options exports on demand two subroutines: +C, which processes the command-line options provided to +F; and C, which returns the list of +currently valid options. + +If you provide F with either C<--help> or C<--version>, +C will print out the appropriate message and perform a +bare C, I, the return value will be C. The calling +script -- whether F or a test file -- can then check for the +definedness of C's return value and proceed appropriately. + +An array of valid command-line option names stored internally is consulted; +the program will die if an invalid option is called. + +=head1 SUBROUTINES + +=head2 C + +=over 4 + +=item * Purpose + +Process command-line options provided to F and proceed +appropriately. + +=item * Arguments + +One argument: Reference to a hash holding the following key-value pairs: + + argv : reference to @ARGV; defaults to [] + script : Perl's $0: the calling program; + defaults to 'Configure.pl' + parrot_version : string holding Parrot version number + (currently supplied by + Parrot::BuildUtil::parrot_version()) + svnid : string holding Subversion Id string + +=item * Return Value + +=over 4 + +=item * C<--version> or C<--help> + +Bare return (C). + +=item * All other options + +Reference to a hash of option names and values. + +=back + +=item * Comment + +=back + +=head2 C + +=over 4 + +=item * Purpose + +Get a list of options currently valid for F. + +=item * Arguments + +None. + +=item * Return Value + +List of currently valid options. + +=item * Comment + +=back + +=head1 NOTES + +The functionality in this package was transferred from F by Jim +Keenan. + +=head1 SEE ALSO + +F. + +=cut + +# Local Variables: +# mode: cperl +# cperl-indent-level: 4 +# fill-column: 100 +# End: +# vim: expandtab shiftwidth=4: Index: MANIFEST =================================================================== --- MANIFEST (revision 17928) +++ MANIFEST (working copy) @@ -2212,6 +2212,7 @@ lib/Parrot/Config.pm [devel] lib/Parrot/Configure.pm [devel] lib/Parrot/Configure/Data.pm [devel] +lib/Parrot/Configure/Options.pm [devel] lib/Parrot/Configure/Step.pm [devel] lib/Parrot/Configure/Step/Base.pm [devel] lib/Parrot/Distribution.pm [devel] @@ -2747,6 +2748,7 @@ t/compilers/tge/grammar.t [] t/compilers/tge/harness [] t/compilers/tge/parser.t [] +t/configure/01-options.t [] t/configure/base.t [] t/configure/config_steps.t [] t/configure/configure.t [] Index: Configure.pl =================================================================== --- Configure.pl (revision 17928) +++ Configure.pl (working copy) @@ -262,6 +262,7 @@ use English qw( -no_match_vars ); use Parrot::BuildUtil; use Parrot::Configure; +use Parrot::Configure::Options qw( process_options ); # These globals are accessed in config/init/defaults.pm our $parrot_version = Parrot::BuildUtil::parrot_version(); @@ -277,165 +278,18 @@ # Copyright (C) 2003 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# Installation directories: -# Handle options +# from Parrot::Configure::Options +my $args = process_options( { + argv => [ @ARGV ], + script => $0, + parrot_version => $parrot_version, + svnid => '$Id$', +} ); +exit unless defined $args; -my @valid_opts = qw(ask bindir cage cc ccflags ccwarn cgoto cxx datadir - debugging define exec-prefix execcapable floatval gc help icu-config - icudatadir icuheaders icushared includedir infodir inline intval - jitcapable ld ldflags lex libdir libexecdir libs link linkflags - localstatedir m maintainer mandir miniparrot nomanicheck oldincludedir - opcode ops optimize parrot_is_shared pmc prefix profile sbindir - sharedstatedir step sysconfdir verbose verbose-step version without-gdbm - without-gmp without-icu yacc); +my %args = %$args; -my %args; -for (@ARGV) { - my ( $key, $value ) = m/--([-\w]+)(?:=(.*))?/; - $key = 'help' unless defined $key; - $value = 1 unless defined $value; - - unless ( grep $key eq $_, @valid_opts ) { - die qq/Invalid option $key. See "perl Configure.pl --help" for valid options\n/; - } - - for ($key) { - m/version/ && do { - my $svnid = '$Id$'; - print <<"END"; -Parrot Version $parrot_version Configure 2.0 -$svnid -END - exit; - }; - - m/help/ && do { - print <<"EOT"; -$0 - Parrot Configure 2.0 - -General Options: - - --help Show this text - --version Show version information - --verbose Output extra information - --verbose=2 Output every setting change - --verbose-step=N Set verbose for step N only - --verbose-step=regex Set verbose for step matching description - --nomanicheck Don't check the MANIFEST - --step=(gen::languages) - Execute a single configure step - - --ask Have Configure ask for commonly-changed info - -Compile Options: - - --debugging=0 Disable debugging, default = 1 - --inline Compiler supports inline - --optimize Optimized compile - --optimize=flags Add given optimizer flags - --parrot_is_shared Link parrot dynamically - --m=32 Build 32bit executable on 64-bit architecture. - --profile Turn on profiled compile (gcc only for now) - --cage [CAGE] compile includes many additional warnings - - --cc=(compiler) Use the given compiler - --ccflags=(flags) Use the given compiler flags - --ccwarn=(flags) Use the given compiler warning flags - --cxx=(compiler) Use the given C++ compiler - --libs=(libs) Use the given libraries - --link=(linker) Use the given linker - --linkflags=(flags) Use the given linker flags - --ld=(linker) Use the given loader for shared libraries - --ldflags=(flags) Use the given loader flags for shared libraries - --lex=(lexer) Use the given lexical analyzer generator - --yacc=(parser) Use the given parser generator - - --define=inet_aton Quick hack to use inet_aton instead of inet_pton - -Parrot Options: - - --intval=(type) Use the given type for INTVAL - --floatval=(type) Use the given type for FLOATVAL - --opcode=(type) Use the given type for opcodes - --ops=(files) Use the given ops files - --pmc=(files) Use the given PMC files - - --cgoto=0 Don't build cgoto core - recommended when short of mem - --jitcapable Use JIT - --execcapable Use JIT to emit a native executable - --gc=(type) Determine the type of garbage collection - type=(gc|libc|malloc|malloc-trace) default is gc - -External Library Options: - - --without-gmp Build parrot without GMP support - --without-gdbm Build parrot without GDBM support - -ICU Options: - - For using a system ICU, these options can be used: - - --icu-config=/path/to/icu-config - Location of the script used for ICU autodetection. - You just need to specify this option if icu-config - is not in you PATH. - - --icu-config=none can be used to disable the autodetection feature. - It will also be disabled if you specify any other - of the following ICU options. - - If you do not have a full ICU installation: - - --without-icu Build parrot without ICU support - --icuheaders=(path) Location of ICU headers without /unicode - --icushared=(flags) Full linker command to create shared libraries - --icudatadir=(path) Directory to locate ICU's data file(s) - -Other Options (may not be implemented): - - --maintainer Create imcc's parser and lexer files. Needs a working - parser and lexer. - --miniparrot Build parrot assuming only pure ANSI C is available - -Install Options: - - --prefix=PREFIX install architecture-independent files in PREFIX - [/usr/local] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] - - By default, `make install' will install all the files in - `/usr/local/bin', `/usr/local/lib' etc. You can specify - an installation prefix other than `/usr/local' using `--prefix', - for instance `--prefix=\$HOME'. - - For better control, use the options below. - - Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --datadir=DIR read-only architecture-independent data [PREFIX/share] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --infodir=DIR info documentation [PREFIX/info] - --mandir=DIR man documentation [PREFIX/man] - -EOT - exit; - }; - $args{$key} = $value; - } -} - -$args{debugging} = 1 unless ( ( exists $args{debugging} ) && !$args{debugging} ); -$args{maintainer} = 1 if defined $args{lex} or defined $args{yacc}; - print <<"END"; Parrot Version $parrot_version Configure 2.0 Copyright (C) 2001-2007, The Perl Foundation. Index: t/configure/01-options.t =================================================================== --- t/configure/01-options.t (revision 0) +++ t/configure/01-options.t (revision 0) @@ -0,0 +1,264 @@ +#! perl +# Copyright (C) 2007, The Perl Foundation. +# $Id: 01-options.t 17800 2007-03-28 01:19:35Z jkeenan $ +# 01-options.t + +use strict; +use warnings; + +BEGIN { + use FindBin qw($Bin); + use Cwd qw(cwd realpath); + realpath($Bin) =~ m{^(.*\/parrot)\/[^/]*\/[^/]*\/[^/]*$}; + our $topdir = $1; + if ( defined $topdir ) { + print "\nOK: Parrot top directory located\n"; + } + else { + $topdir = realpath($Bin) . "/../.."; + } + unshift @INC, qq{$topdir/lib}; +} +use Test::More tests => 32; +use Carp; +use lib ("lib"); +use_ok('Parrot::Configure::Options', qw| + process_options + get_valid_options +| ); +use_ok("Parrot::IO::Capture::Mini"); + + +my %valid; +%valid = map {$_, 1} get_valid_options(); +ok(scalar keys %valid, "non-zero quantity of valid options found"); +ok(defined $valid{debugging}, "debugging option found"); +ok(defined $valid{maintainer}, "maintainer option found"); +ok(defined $valid{help}, "help option found"); +ok(defined $valid{version}, "version option found"); +ok(defined $valid{verbose}, "verbose option found"); + +open my $FH, "$main::topdir/Configure.pl" + or croak "Unable to open handle to Configure.pl"; +my $bigstr; +{ + local $/ = undef; + $bigstr = <$FH>; +} +close $FH or croak "Unable to close handle to Configure.pl"; + +# Ignore any POD I have moved to an __END__ block. +$bigstr =~ s/__END__.*//s; +my (@lines, @possible_methods); +@lines = grep { /^=item/ } (split /\n/, $bigstr); +foreach my $l (@lines) { + my $method; + if ($l =~ /^=item C<--([-_\w]+)(?:[=>])/) { + $method = $1; + push @possible_methods, $method; + } +} +my $invalid = 0; +foreach my $m (@possible_methods) { + unless (defined $valid{$m}) { + carp "Possibly invalid method: $m"; + $invalid++; + } +} +ok(! $invalid, "No invalid methods described in POD"); + +my $parrot_version = '0.4.10'; +my $svnid = '$Id: 01-options.t 17800 2007-03-28 01:19:35Z jkeenan $'; +my ($args); +$args = process_options( { + argv => [], + script => $0, + parrot_version => $parrot_version, + svnid => $svnid, +} ); +ok(defined $args, "process_options() returned successfully"); +ok($args->{debugging}, "debugging turned on by default"); + +eval { + $args = process_options( { + argv => [], + script => $0, + svnid => $svnid, + } ); +}; +like($@, qr/Must provide argument 'parrot_version'/, + "process_options() failed due to lack of argument 'parrot_version'"); + +eval { + $args = process_options( { + argv => [], + script => $0, + parrot_version => $parrot_version, + } ); +}; +like($@, qr/Must provide argument 'svnid'/, + "process_options() failed due to lack of argument 'svnid'"); + +$args = process_options( { + script => $0, + parrot_version => $parrot_version, + svnid => $svnid, +} ); +ok(defined $args, + "process_options() returned successfully even though no explicit 'argv' key was provided"); + +$args = process_options( { + argv => [], + parrot_version => $parrot_version, + svnid => $svnid, +} ); +ok(defined $args, + "process_options() returned successfully even though no explicit 'scripts' key was provided"); + +my $CC = "/usr/bin/gcc-3.3"; +my $CX = "/usr/bin/g++-3.3"; +$args = process_options( { + argv => [ + q{--cc=$CC}, + q{--cxx=$CX}, + q{--link=$CX}, + q{--ld=$CX}, + q{--without-icu}, + q{--without-gmp}, + ], + script => $0, + parrot_version => $parrot_version, + svnid => $svnid, +} ); +ok(defined $args, + "process_options() returned successfully when options were specified"); + +my $badoption = q{samsonanddelilah}; +eval { + $args = process_options( { + argv => [ qq<--${badoption}=72> ], + script => $0, + parrot_version => $parrot_version, + svnid => $svnid, + } ); +}; +like($@, qr/^Invalid option $badoption/, + "process_options() failed due to bad option '$badoption'"); + +{ + my ($tie, $rv, $msg); + $tie = tie *STDOUT, "Parrot::IO::Capture::Mini" + or croak "Unable to tie"; + $args = process_options( { + argv => [ q{--help} ], + script => $0, + parrot_version => $parrot_version, + svnid => $svnid, + } ); + ok(! defined $args, + "process_options() returned undef after 'help' option"); + $msg = $tie->READLINE; + like($msg, qr/--help/i, + "got correct message after 'version' option"); +} + +{ + my ($tie, $rv, $msg); + $tie = tie *STDOUT, "Parrot::IO::Capture::Mini" + or croak "Unable to tie"; + $args = process_options( { + argv => [ q{--} ], + script => $0, + parrot_version => $parrot_version, + svnid => $svnid, + } ); + ok(! defined $args, + "process_options() returned undef after 'help' option: case '--'"); + $msg = $tie->READLINE; + like($msg, qr/--help/i, + "got correct message after 'version' option"); +} + +{ + my ($tie, $rv, $msg); + $tie = tie *STDOUT, "Parrot::IO::Capture::Mini" + or croak "Unable to tie"; + $args = process_options( { + argv => [ q{--version} ], + script => $0, + parrot_version => $parrot_version, + svnid => $svnid, + } ); + ok(! defined $args, + "process_options() returned undef after 'version' option"); + $msg = $tie->READLINE; + like($msg, qr/Parrot Version/i, + "got correct message after 'version' option"); +} + +$args = process_options( { + argv => [ q{--lex}, ], + script => $0, + parrot_version => $parrot_version, + svnid => $svnid, +} ); +ok(defined $args, + "process_options() returned successfully after 'lex' option"); +ok($args->{maintainer}, "'maintainer' attribute is true after 'lex' option"); + +$args = process_options( { + argv => [ q{--yacc}, ], + script => $0, + parrot_version => $parrot_version, + svnid => $svnid, +} ); +ok(defined $args, + "process_options() returned successfully after 'yacc' option"); +ok($args->{maintainer}, "'maintainer' attribute is true after 'yacc' option"); + +$args = process_options( { + argv => [ q{--debugging=1} ], + script => $0, + parrot_version => $parrot_version, + svnid => $svnid, +} ); +ok(defined $args, "process_options() returned successfully"); +ok($args->{debugging}, "debugging turned on explicitly"); + +$args = process_options( { + argv => [ q{--debugging=0} ], + script => $0, + parrot_version => $parrot_version, + svnid => $svnid, +} ); +ok(defined $args, "process_options() returned successfully"); +ok(! $args->{debugging}, "debugging explicitly turned off"); + +pass("Completed all tests in $0"); + +################### DOCUMENTATION ################### + +=head1 NAME + +01-options.t - test Parrot::Configure::Options + +=head1 SYNOPSIS + + % prove t/configure/01-options.t + +=head1 DESCRIPTION + +The files in this directory test functionality used by F. + +The tests in this file test subroutines exported by +Parrot::Configure::Options. + +=head1 AUTHOR + +James E Keenan + +=head1 SEE ALSO + +Parrot::Configure::Options, F. + +=cut