From 2bfd3b7fadfd4c30226487a777764c504d07ed93 Mon Sep 17 00:00:00 2001 From: Moritz Lenz Date: Wed, 6 Nov 2013 15:14:35 +0100 Subject: import NQP::Configure from NQP --- tools/lib/NQP/Configure.pm | 221 ++++++++++++++++++++++++++++++++------------- 1 file changed, 158 insertions(+), 63 deletions(-) diff --git a/tools/lib/NQP/Configure.pm b/tools/lib/NQP/Configure.pm index e93c366..f12e3b3 100644 --- a/tools/lib/NQP/Configure.pm +++ b/tools/lib/NQP/Configure.pm @@ -2,6 +2,7 @@ package NQP::Configure; use strict; use warnings; use Cwd; +use File::Copy qw(copy); use base qw(Exporter); our @EXPORT_OK = qw(sorry slurp system_or_die @@ -9,10 +10,11 @@ our @EXPORT_OK = qw(sorry slurp system_or_die read_parrot_config read_config fill_template_file fill_template_text git_checkout - verify_install + verify_install gen_moar gen_nqp gen_parrot); our $exe = $^O eq 'MSWin32' ? '.exe' : ''; +our $bat = $^O eq 'MSWin32' ? '.bat' : ''; our @required_parrot_files = qw( @bindir@/parrot@exe@ @@ -24,11 +26,16 @@ our @required_parrot_files = qw( ); our @required_nqp_files = qw( - @bindir@/nqp@exe@ + @bindir@/nqp-p@exe@ ); -our $nqp_git = 'git://github.com/perl6/nqp.git'; -our $par_git = 'git://github.com/parrot/parrot.git'; +our $nqp_git = 'http://github.com/perl6/nqp.git'; +our $par_git = 'http://github.com/parrot/parrot.git'; +our $moar_git= 'https://github.com/MoarVM/MoarVM.git'; + +our $nqp_push = 'git@github.com:perl6/nqp.git'; +our $par_push = 'git@github.com:parrot/parrot.git'; +our $moar_push= 'git@github.com:MoarVM/MoarVM.git'; sub sorry { my @msg = @_; @@ -78,11 +85,12 @@ sub cmp_rev { sub read_config { my @config_src = @_; my %config = (); + local $_; for my $file (@config_src) { no warnings; if (open my $CONFIG, '-|', "$file --show-config") { while (<$CONFIG>) { - if (/^([\w:]+)=(.*)/) { $config{$1} = $2 } + if (/^([^\s=]+)=(.*)/) { $config{$1} = $2 } } close($CONFIG); } @@ -129,7 +137,7 @@ END } close($PARROT_CONFIG) or die $!; } - elsif (open my $PARROT, '-|', "$file parrot-config.pir") { + elsif (open my $PARROT, '-|', "\"$file\" parrot-config.pir") { while (<$PARROT>) { if (/^([\w:]+)=(.*)/) { $config{$1} = $2 } } @@ -146,13 +154,26 @@ sub fill_template_file { my $infile = shift; my $outfile = shift; my %config = @_; - my $text = slurp( $infile ); - $text = fill_template_text($text, %config); - print "\nCreating $outfile ...\n"; - open(my $OUT, '>', $outfile) - or die "Unable to write $outfile\n"; - print $OUT $text; - close($OUT) or die $!; + + my $OUT; + if (ref $outfile) { + $OUT = $outfile; + } + else { + print "\nCreating $outfile ...\n"; + open($OUT, '>', $outfile) + or die "Unable to write $outfile\n"; + } + + my @infiles = ref($infile) ? @$infile : $infile; + for my $if (@infiles) { + my $text = slurp( $if ); + $text = fill_template_text($text, %config); + print $OUT $text; + } + unless (ref $outfile) { + close($OUT) or die "Error while writing '$outfile': $!"; + } } @@ -160,6 +181,13 @@ sub fill_template_text { my $text = shift; my %config = @_; + my $escape = sub { + my $str = $_[0]; + $str =~ s{ }{\\ }g; + $str; + }; + + $text =~ s/@@([:\w]+)@@/$escape->($config{$1} || $config{"parrot::$1"} || '')/ge; $text =~ s/@([:\w]+)@/$config{$1} || $config{"parrot::$1"} || ''/ge; if ($text =~ /nqp::makefile/) { if ($^O eq 'MSWin32') { @@ -188,12 +216,15 @@ sub git_checkout { my $repo = shift; my $dir = shift; my $checkout = shift; + my $pushurl = shift; my $pwd = cwd(); # get an up-to-date repository if (! -d $dir) { system_or_die('git', 'clone', $repo, $dir); chdir($dir); + system('git', 'config', 'remote.origin.pushurl', $pushurl) + if defined $pushurl; } else { chdir($dir); @@ -237,67 +268,84 @@ sub gen_nqp { my $nqp_want = shift; my %options = @_; + my $backends = $options{'backends'}; my $gen_nqp = $options{'gen-nqp'}; - my $with_parrot = $options{'with-parrot'}; my $gen_parrot = $options{'gen-parrot'}; my $prefix = $options{'prefix'} || cwd().'/install'; my $startdir = cwd(); - my $nqpdir = "$startdir/nqp"; my $PARROT_REVISION = 'nqp/tools/build/PARROT_REVISION'; - my %config; - my $nqp_exe; - if ($with_parrot) { - %config = read_parrot_config($with_parrot) - or die "Unable to read parrot configuration from $with_parrot\n"; - $prefix = $config{'parrot::prefix'}; - $nqp_exe = fill_template_text('@bindir@/nqp@ext@', %config); - %config = read_config($nqp_exe); - } - elsif ($prefix) { - $nqp_exe = "$prefix/bin/nqp$exe"; - %config = read_config($nqp_exe); - } + my (%impls, %need); + + if ($backends =~ /parrot/) { + my %c = read_parrot_config("$prefix/bin/parrot"); - my $nqp_have = $config{'nqp::version'} || ''; - my $nqp_ok = $nqp_have && cmp_rev($nqp_have, $nqp_want) >= 0; - if ($gen_nqp && -d $gen_nqp) { - $nqpdir = $gen_nqp; - print "Building NQP from source in $nqpdir\n"; + if (%c) { + my $bin = fill_template_text('@bindir@/nqp-p@ext@', %c); + $impls{parrot}{bin} = $bin; + %c = read_config($bin); + my $nqp_have = $c{'nqp::version'}; + my $nqp_ok = $nqp_have && cmp_rev($nqp_have, $nqp_want) >= 0; + if ($nqp_ok) { + $impls{parrot}{config} = \%c; + } + else { + $need{parrot} = 1; + } + } + else { + $need{parrot} = 1; + } } - elsif ($gen_nqp) { - my $nqp_repo = git_checkout($nqp_git, 'nqp', $gen_nqp); - $nqp_ok = $nqp_have eq $nqp_repo; + for my $b (qw/jvm moar/) { + if ($backends =~ /$b/) { + my $postfix = substr $b, 0, 1; + my $bin = "$prefix/bin/nqp-$postfix$bat"; + $impls{$b}{bin} = $bin; + my %c = read_config($bin); + my $nqp_have = $c{'nqp::version'} || ''; + my $nqp_ok = $nqp_have && cmp_rev($nqp_have, $nqp_want) >= 0; + if ($nqp_ok) { + $impls{$b}{config} = \%c; + } + else { + $need{$b} = 1; + } + } } - elsif (!$nqp_ok || defined $gen_parrot && !-f $PARROT_REVISION) { - git_checkout($nqp_git, 'nqp', $nqp_want); + + return %impls unless %need; + + if (defined $gen_nqp || defined $gen_parrot) { + git_checkout($nqp_git, 'nqp', $nqp_want, $nqp_push); } - if (defined $gen_parrot) { - $PARROT_REVISION = "$nqpdir/tools/build/PARROT_REVISION"; + if ($need{parrot} && defined $gen_parrot) { my ($par_want) = split(' ', slurp($PARROT_REVISION)); - $with_parrot = gen_parrot($par_want, %options, prefix => $prefix); - %config = read_parrot_config($with_parrot); - } - elsif (!%config) { - %config = read_parrot_config("$prefix/bin/parrot$exe", "parrot$exe"); - $with_parrot = fill_template_text('@bindir@/parrot@exe@', %config); + my $parrot = gen_parrot($par_want, %options, prefix => $prefix); + my %c = read_parrot_config($parrot); + $impls{parrot}{bin} = fill_template_text('@bindir@/nqp-p@ext@', %c); + $impls{parrot}{config} = \%c; } - if ($nqp_ok && -M $nqp_exe < -M $with_parrot) { - print "$nqp_exe is NQP $nqp_have.\n"; - return $nqp_exe; - } + return %impls unless defined($gen_nqp) || defined($gen_parrot); - my @cmd = ($^X, 'Configure.pl', "--with-parrot=$with_parrot", - "--make-install"); + my $backends_to_build = join ',', sort keys %need; + my @cmd = ($^X, 'Configure.pl', "--prefix=$prefix", + "--backends=$backends", "--make-install"); print "Building NQP ...\n"; - chdir($nqpdir); + chdir("$startdir/nqp"); print "@cmd\n"; system_or_die(@cmd); chdir($startdir); - return fill_template_text('@bindir@/nqp@exe@', %config); + + for my $k (keys %need) { + my %c = read_config($impls{$k}{bin}); + %c = (%{ $impls{$k}{config} || {} }, %c); + $impls{$k}{config} = \%c; + } + return %impls; } @@ -310,30 +358,25 @@ sub gen_parrot { my @opts = @{ $options{'parrot-option'} || [] }; push @opts, "--optimize"; my $startdir = cwd(); - my $parrotdir = "$startdir/parrot"; my $par_exe = "$options{'prefix'}/bin/parrot$exe"; my %config = read_parrot_config($par_exe); my $par_have = $config{'parrot::git_describe'} || ''; my $par_ok = $par_have && cmp_rev($par_have, $par_want) >= 0; - if ($gen_parrot && -d $gen_parrot) { - $parrotdir = $gen_parrot; - print "Building Parrot from source in $parrotdir\n"; - } - elsif ($gen_parrot) { - my $par_repo = git_checkout($par_git, 'parrot', $gen_parrot); + if ($gen_parrot) { + my $par_repo = git_checkout($par_git, 'parrot', $gen_parrot, $par_push); $par_ok = $par_have eq $par_repo; } elsif (!$par_ok) { - git_checkout($par_git, 'parrot', $par_want); + git_checkout($par_git, 'parrot', $par_want, $par_push); } if ($par_ok) { print "$par_exe is Parrot $par_have.\n"; return $par_exe; } - chdir($parrotdir) or die $!; + chdir("$startdir/parrot") or die $!; if (-f 'Makefile') { %config = read_parrot_config('config_lib.pir'); my $make = $config{'parrot::make'}; @@ -357,9 +400,61 @@ sub gen_parrot { system_or_die($make, 'install-dev'); chdir($startdir); + # That is a hack to get the import-lib in place. Parrot seems unpatchable because + # its static build shares the same libname as the import-lib. + if (-e "$startdir/parrot/libparrot.lib" && !-e "$startdir/install/bin/libparrot.lib") { + copy("$startdir/parrot/libparrot.lib", "$startdir/install/bin/libparrot.lib"); + } + print "Parrot installed.\n"; return fill_template_text('@bindir@/parrot@exe@', %config); } +sub gen_moar { + my $moar_want = shift; + my %options = @_; + + my $prefix = $options{'prefix'} || cwd()."/install"; + my $gen_moar = $options{'gen-moar'}; + my @opts = @{ $options{'moar-option'} || [] }; + push @opts, "--optimize"; + my $startdir = cwd(); + + my $moar_exe = "$prefix/bin/moar$exe"; + my $moar_have = qx{ $moar_exe --version }; + if ($moar_have) { + $moar_have = $moar_have =~ /version (\S+)/ ? $1 : undef; + } + + my $moar_ok = $moar_have && cmp_rev($moar_have, $moar_want) >= 0; + if ($moar_ok) { + print "Found $moar_exe version $moar_have, which is new enough.\n"; + return $moar_exe; + } + elsif ($moar_have) { + print "Found $moar_exe version $moar_have, which is too old.\n"; + } + + return unless defined $gen_moar; + + my $moar_repo = git_checkout($moar_git, 'MoarVM', $gen_moar || $moar_want, $moar_push); + + unless (cmp_rev($moar_repo, $moar_want) >= 0) { + die "You asked me to build $gen_moar, but $moar_repo is not new enough to satisfy version $moar_want\n"; + } + + chdir("$startdir/MoarVM") or die $!; + + $prefix =~ s{\\}{/}g; + print "\nConfiguring and building MoarVM ...\n"; + my @cmd = ($^X, "Configure.pl", @opts, "--prefix=$prefix", '--make-install'); + print "@cmd\n"; + system_or_die(@cmd); + + chdir($startdir); + + return $moar_exe; +} + 1; -- cgit v1.1