Skip to content

Commit

Permalink
Initial re-write of Configure.pl (based on Rakudo's Configure.pl, wit…
Browse files Browse the repository at this point in the history
…h new options for --gen-nqp and --gen-parrot.)
  • Loading branch information
pmichaud committed Jan 27, 2012
1 parent e798a04 commit 7c94ff3
Showing 1 changed file with 119 additions and 169 deletions.
288 changes: 119 additions & 169 deletions skel/Configure.pl
Expand Up @@ -4,221 +4,171 @@
use 5.008;
use strict;
use warnings;
use Text::ParseWords;
use Getopt::Long;
use Cwd;
use lib "tools/lib";
use NQP::Configure qw(sorry slurp cmp_rev gen_nqp read_config
fill_template_text fill_template_file
system_or_die verify_install);

my $lang = 'Rakudo';
my $lclang = lc $lang;
my $uclang = uc $lang;

MAIN: {
if (-r "config.default") {
unshift @ARGV, shellwords(slurp('config.default'));
}

my %config;
my $config_status = "${lclang}_config_status";
$config{$config_status} = join(' ', map { "\"$_\""} @ARGV);

my $exe = $NQP::Configure::exe;

my %options;
GetOptions(\%options, 'help!', 'parrot-config=s', 'makefile-timing!',
'gen-parrot!', 'prefix=s', 'gen-parrot-option=s@');
GetOptions(\%options, 'help!', 'prefix=s',
'with-nqp=s', 'gen-nqp:s',
'with-parrot=s', 'gen-parrot:s', 'parrot-option=s@',
'make-install!', 'makefile-timing!',
);

# Print help if it's requested
if ($options{'help'}) {
print_help();
exit(0);
}

# Determine the revision of Parrot we require
open my $REQ, '<', "build/PARROT_REVISION"
or die "cannot open build/PARROT_REVISION: $!\n";
my ($reqsvn, $reqpar) = split(' ', <$REQ>);
$reqsvn += 0;
close $REQ;

# Update/generate parrot build if needed
if ($options{'gen-parrot'}) {
my @opts = @{ $options{'gen-parrot-option'} || [] };
my $prefix = $options{'prefix'} || cwd()."/install";
# parrot's Configure.pl mishandles win32 backslashes in --prefix
$prefix =~ s{\\}{/}g;
my @command = ($^X, "build/gen_parrot.pl", "--prefix=$prefix",
($^O !~ /win32/i ? "--optimize" : ()), @opts);

print "Generating Parrot ...\n";
print "@command\n\n";
system @command;
}

# Get a list of parrot-configs to invoke.
my @parrot_config_exe = qw(
install/bin/parrot_config
parrot_config
);
if (exists $options{'prefix'}) {
unshift @parrot_config_exe,
$options{'prefix'} . '/bin/parrot_config';
my $prefix = $options{'prefix'} || cwd().'/install';
my $with_parrot = $options{'with-parrot'};
$options{'gen-parrot'} ||= 'parrot-3.11.0' if defined $options{'gen-parrot'};
my $gen_parrot = $options{'gen-parrot'};

# Save options in config.status
unlink('config.status');
if (open(my $CONFIG_STATUS, '>', 'config.status')) {
print $CONFIG_STATUS
"$^X Configure.pl $config{$config_status} \$*\n";
close($CONFIG_STATUS);
}

if ($options{'parrot-config'} && $options{'parrot-config'} ne '1') {
@parrot_config_exe = ($options{'parrot-config'});
# --with-parrot and --gen-parrot imply --gen-nqp
if (defined $with_parrot || defined $gen_parrot) {
$options{'gen-nqp'} ||= '';
}

# Get configuration information from parrot_config
my %config = read_parrot_config(@parrot_config_exe);
$options{'gen-nqp'} ||= 'nqp-2012.01' if defined $options{'gen-nqp'};
my $with_nqp = $options{'with-nqp'};
my $gen_nqp = $options{'gen-nqp'};

my $parrot_errors = '';
if (!%config) {
$parrot_errors .= "Unable to locate parrot_config\n";
}
elsif ($reqsvn > $config{'revision'} &&
($reqpar eq '' || version_int($reqpar) > version_int($config{'VERSION'}))) {
$parrot_errors .= "Parrot revision r$reqsvn required (currently r$config{'revision'})\n";
# determine the version of NQP we want
my ($nqp_want) = split(' ', slurp('tools/build/NQP_REVISION'));

if (defined $gen_nqp) {
$with_nqp = gen_nqp($nqp_want, %options);
}

if ($parrot_errors) {
die <<"END";
===SORRY!===
$parrot_errors
To automatically build the version of Parrot that came with this
distribution ($reqpar), try re-running Configure.pl with the
'--gen-parrot' option. Or, use the '--parrot-config' option to
explicitly specify the location of parrot_config to be used to
build Rakudo Star.
my @errors;

END
my %nqp_config;
if ($with_nqp) {
%nqp_config = read_config($with_nqp)
or push @errors, "Unable to read configuration from $with_nqp.";
}
else {
%nqp_config = read_config("$prefix/bin/nqp$exe", "nqp$exe")
or push @errors, "Unable to find an NQP executable.";
$with_nqp = fill_template_text('@bindir@/nqp@exe@', %nqp_config)
}

# Verify the Parrot installation is sufficient for building Rakudo
verify_parrot(%config);

# Create the Makefile using the information we just got
create_makefile($options{'makefile-timing'}, %config);
my $make = $config{'make'};
%config = (%config, %nqp_config);
my $nqp_have = $config{'nqp::version'} || '';
if ($nqp_have && cmp_rev($nqp_have, $nqp_want) < 0) {
push @errors, "NQP revision $nqp_want required (currently $nqp_have).";
}

{
no warnings;
print "Cleaning up ...\n";
if (open my $CLEAN, '-|', "$make clean") {
my @slurp = <$CLEAN>;
close $CLEAN;
}
if (!@errors) {
push @errors, verify_install([ @NQP::Configure::required_parrot_files,
@NQP::Configure::required_nqp_files ],
%config);
push @errors,
"(Perhaps you need to 'make install', 'make install-dev',",
"or install the 'devel' package for NQP or Parrot?)"
if @errors;
}

print <<"END";
if (@errors && !defined $gen_nqp) {
push @errors,
"\nTo automatically clone (git) and build a copy of NQP $nqp_want,",
"try re-running Configure.pl with the '--gen-nqp' or '--gen-parrot'",
"options. Or, use '--with-nqp=' or '--with-parrot=' to explicitly",
"specify the NQP or Parrot executable to use to build $lang.";
}

You can now use '$make' to build Rakudo Perl.
After that, you can use '$make rakudo-test' to run some local tests,
or '$make install' to create a 'perl6' executable in the local directory
and in $config{'bindir'}/perl6 .
sorry(@errors) if @errors;

END
exit 0;
print "Using $with_nqp (version $config{'nqp::version'}).\n";

}
$config{'makefile-timing'} = $options{'makefile-timing'};
$config{'stagestats'} = '--stagestats' if $options{'makefile-timing'};
$config{'shell'} = $^O eq 'MSWin32' ? 'cmd' : 'sh';
if ($^O eq 'MSWin32' or $^O eq 'cygwin') {
$config{'dll'} = '$(PARROT_BIN_DIR)/$(PARROT_LIB_SHARED)';
$config{'dllcopy'} = '$(PARROT_LIB_SHARED)';
$config{'make_dllcopy'} =
'$(PARROT_DLL_COPY): $(PARROT_DLL)'."\n\t".'$(CP) $(PARROT_DLL) .';
}

my $make = fill_template_text('@make@', %config);
fill_template_file('tools/build/Makefile.in', 'Makefile', %config);

sub read_parrot_config {
my @parrot_config_exe = @_;
my %config = ();
for my $exe (@parrot_config_exe) {
{
no warnings;
if (open my $PARROT_CONFIG, '-|', "$exe --dump") {
print "\nReading configuration information from $exe ...\n";
while (<$PARROT_CONFIG>) {
if (/(\w+) => '(.*)'/) { $config{$1} = $2 }
}
close $PARROT_CONFIG or die $!;
last if %config;
print "Cleaning up ...\n";
if (open my $CLEAN, '-|', "$make clean") {
my @slurp = <$CLEAN>;
close($CLEAN);
}
}
return %config;
}


sub verify_parrot {
print "Verifying Parrot installation...\n";
my %config = @_;
my $EXE = $config{'exe'};
my $PARROT_BIN_DIR = $config{'bindir'};
my $PARROT_VERSION = $config{'versiondir'};
my $PARROT_LIB_DIR = $config{'libdir'}.$PARROT_VERSION;
my $PARROT_SRC_DIR = $config{'srcdir'}.$PARROT_VERSION;
my $PARROT_INCLUDE_DIR = $config{'includedir'}.$PARROT_VERSION;
my $PARROT_TOOLS_DIR = "$PARROT_LIB_DIR/tools";
my @required_files = (
"$PARROT_LIB_DIR/library/PGE/Perl6Grammar.pbc",
"$PARROT_LIB_DIR/library/PCT/HLLCompiler.pbc",
"$PARROT_BIN_DIR/ops2c".$EXE,
"$PARROT_TOOLS_DIR/build/pmc2c.pl",
"$PARROT_SRC_DIR",
"$PARROT_SRC_DIR/pmc",
"$PARROT_INCLUDE_DIR",
"$PARROT_INCLUDE_DIR/pmc",
);
my @missing = map { " $_" } grep { ! -e } @required_files;
if (@missing) {
my $missing = join("\n", @missing);
die <<"END";
===SORRY!===
I'm missing some needed files from the Parrot installation:
$missing
(Perhaps you need to use Parrot's "make install-dev" or
install the "parrot-devel" package for your system?)

END
if ($options{'make-install'}) {
system_or_die($make);
system_or_die($make, 'install');
print "\n$lang has been built and installed.\n";
}
}

# Generate a Makefile from a configuration
sub create_makefile {
my ($makefile_timing, %config) = @_;

my $maketext = slurp( 'build/Makefile.in' );

$config{'stagestats'} = $makefile_timing ? '--stagestats' : '';
$config{'win32_libparrot_copy'} = $^O eq 'MSWin32' ? 'copy $(PARROT_BIN_DIR)\libparrot.dll .' : '';
$maketext =~ s/@(\w+)@/$config{$1}/g;
if ($^O eq 'MSWin32') {
$maketext =~ s{/}{\\}g;
$maketext =~ s{\\\*}{\\\\*}g;
$maketext =~ s{http:\S+}{ do {my $t = $&; $t =~ s'\\'/'g; $t} }eg;
else {
print "\nYou can now use '$make' to build $lang.\n";
print "After that, '$make test' will run some tests and\n";
print "'$make install' will install $lang.\n";
}

if ($makefile_timing) {
$maketext =~ s{(?<!\\\n)^\t(?!\s*-?cd)(?=[^\n]*\S)}{\ttime }mg;
}

my $outfile = 'Makefile';
print "\nCreating $outfile ...\n";
open(my $MAKEOUT, '>', $outfile) ||
die "Unable to write $outfile\n";
print {$MAKEOUT} $maketext;
close $MAKEOUT or die $!;

return;
}

sub slurp {
my $filename = shift;

open my $fh, '<', $filename or die "Unable to read $filename\n";
local $/ = undef;
my $maketext = <$fh>;
close $fh or die $!;

return $maketext;
}

sub version_int {
sprintf('%d%03d%03d', split(/\./, $_[0]))
exit 0;
}


# Print some help text.
sub print_help {
print <<'END';
Configure.pl - Rakudo Configure
print <<"END";
Configure.pl - $lang Configure
General Options:
--help Show this text
--gen-parrot Download and build a copy of Parrot to use
--gen-parrot-option='--option=value'
Set parrot config option when using --gen-parrot
--parrot-config=/path/to/parrot_config
Use config information from parrot_config executable
Experimental developer's options:
--makefile-timing Insert 'time' command all over in the Makefile
--prefix=dir Install files in dir
--with-nqp=path/to/bin/nqp
NQP executable to use to build $lang
--gen-nqp[=branch]
Download and build a copy of NQP
--with-parrot=path/to/bin/parrot
Parrot executable to use to build NQP
--gen-parrot[=branch]
Download and build a copy of Parrot
--parrot-option='--option'
Options to pass to Parrot's Configure.pl
--makefile-timing Enable timing of individual makefile commands
Configure.pl also reads options from 'config.default' in the current directory.
END

return;
Expand Down

0 comments on commit 7c94ff3

Please sign in to comment.