#!/usr/bin/perl
# Marpa::R3 is Copyright (C) 2016, Jeffrey Kegler.
#
# This module is free software; you can redistribute it and/or modify it
# under the same terms as Perl 5.10.1. For more details, see the full text
# of the licenses in the directory LICENSES.
#
# This program is distributed in the hope that it will be
# useful, but it is provided “as is” and without any express
# or implied warranties. For details, see the full text of
# of the licenses in the directory LICENSES.
use 5.010001;
use strict;
use warnings;
use ExtUtils::Install;
use Fatal qw(open close mkdir chdir);
use File::Spec 0.82;
use File::Find 1.12;
use File::Copy;
use IPC::Cmd;
use English qw( -no_match_vars );
use Time::Piece 1.12;
use Cwd;
use Config;
use ExtUtils::MakeMaker;
use vars qw($VERSION $STRING_VERSION);
$VERSION = '4.001_004';
$STRING_VERSION = $VERSION;
## no critic (BuiltinFunctions::ProhibitStringyEval)
$VERSION = eval $VERSION;
## use critic
my $verbose = 1;
my $libmarpa_debug = 0;
my %perl_autoconf_os =
map { $_ => 1 } qw( MSWin32 openbsd solaris sunos midnightbsd );
my $use_perl_autoconf = $ENV{MARPA_USE_PERL_AUTOCONF}
|| ( $perl_autoconf_os{$^O} // 0 );
# This comment reminds me of how to use Module::CoreList.
# It's here for convenience in working on this file.
# perl -MModule::CoreList -E 'print $Module::CoreList::version{5.010001}{Carp};'
my %version_for_config = (
# Carp is 1.11 to allow objects to be thrown as exceptions.
'Carp' => '1.11',
'Config::AutoConf' => '0.22',
'CPAN::Meta::Converter' => '2.120921',
'Cwd' => '3.2501',
'Data::Dumper' => '2.125',
'DynaLoader' => '1.08',
'English' => '1.04',
'Exporter' => '5.62',
'ExtUtils::CBuilder' => '0.27',
# ExtUtils::MakeMaker must be 6.48 so that MIN_PERL_VERSION
# is supported
'ExtUtils::MakeMaker' => '6.48',
'ExtUtils::Manifest' => '1.51_01',
'ExtUtils::Mkbootstrap' => '6.42',
'Fatal' => '1.05',
'File::Copy' => '2.11',
'File::Spec' => '3.2501',
'File::Find' => '1.12',
'IPC::Cmd' => '0.40_1',
'List::Util' => '1.21',
'Scalar::Util' => '1.21',
'Test::More' => '0.94',
'Time::Piece' => '1.12',
'XSLoader' => '0.08',
);
if ($use_perl_autoconf) {
say "Using Config::AutoConf";
for my $package (qw( Config::AutoConf )) {
if ( not eval "require $package" ) {
die "$package is not installed: $EVAL_ERROR\n",
" Module $package is required for Windows and for USE_PERL_AUTOCONF mode\n";
}
my $version = $version_for_config{$package};
if ( not $package->VERSION($version) ) {
die "Version $version of $package is not installed\n",
" Version $version of $package is required for Windows and for USE_PERL_AUTOCONF mode\n";
}
} ## end for my $package (qw( Config::AutoConf ))
} ## end if ($use_perl_autoconf)
my $preamble = <<'END_OF_STRING';
# This file is written by Makefile.PL
# It is not intended to be modified directly
END_OF_STRING
sub installed_contents {
my ( $package ) = @_;
my $marpa_version = $STRING_VERSION;
my $text = $preamble;
$text .= "package $package;\n";
##no critic(ValuesAndExpressions::RequireInterpolationOfMetachars)
$text .= q{use vars qw($VERSION $STRING_VERSION)} . qq{;\n};
$text .= q{$VERSION = '} . $marpa_version . qq{';\n};
$text .= q{$STRING_VERSION = $VERSION} . qq{;\n};
$text .= q{$VERSION = eval $VERSION} . qq{;\n};
##use critic
$text .= "1;\n";
return $text;
} ## end sub installed_contents
sub xs_version_contents {
my ( $package ) = @_;
my @use_packages =
qw( Scalar::Util List::Util Carp Data::Dumper );
my $text = $preamble;
$text .= "package $package;\n";
##no critic(ValuesAndExpressions::RequireInterpolationOfMetachars)
$text .= q{use vars qw($TIMESTAMP)} . qq{;\n};
$text .= q{$TIMESTAMP='} . localtime()->datetime . qq{';\n};
##use critic
for my $package (@use_packages) {
my $version = $version_for_config{$package};
die "No version defined for $package" if not defined $version;
$text .= "use $package $version ();\n";
}
$text .= "1;\n";
return $text;
} ## end sub xs_version_contents
sub perl_version_contents {
my ( $package, ) = @_;
my @use_packages = qw( Scalar::Util Carp Data::Dumper Marpa::R3 );
my $text = $preamble;
my $marpa_version = $STRING_VERSION;
$text .= "package $package;\n";
##no critic(ValuesAndExpressions::RequireInterpolationOfMetachars)
$text .= q{use vars qw($TIMESTAMP)} . qq{;\n};
$text .= q{$TIMESTAMP='} . localtime()->datetime . qq{';\n};
##use critic
for my $package (@use_packages) {
my $version =
$package eq 'Marpa::R3'
? $marpa_version
: $version_for_config{$package};
die "No version defined for $package" if not defined $version;
$text .= "use $package $version ();\n";
} ## end for my $package (@use_packages)
$text .= "1;\n";
return $text;
} ## end sub perl_version_contents
sub file_write {
my ( $contents, @name_components ) = @_;
my $file_name = pop @name_components;
my $dir_name = File::Spec->catdir( @name_components );
-d $dir_name or mkdir $dir_name;
my $path_name = File::Spec->catfile( $dir_name, $file_name );
open my $fh, q{>}, $path_name;
print {$fh} $contents or die "print failed: $ERRNO";
close $fh;
return 1;
} ## end sub file_write
sub write_installed_pm {
my ( @components ) = @_;
my $filename = 'Installed';
my @package_components = @components[ 1 .. $#components ];
my $contents = installed_contents( join q{::}, @package_components,
$filename );
$filename .= q{.pm};
return file_write( $contents, @components, $filename );
} ## end sub write_installed_pm
my @packages_for_perl_autoconf = qw( Config::AutoConf );
my @always_required = qw(
Carp
Cwd
Data::Dumper
DynaLoader
English
Exporter
ExtUtils::CBuilder
ExtUtils::MakeMaker
ExtUtils::Manifest
ExtUtils::Mkbootstrap
Fatal
File::Copy
File::Spec
IPC::Cmd
List::Util
Scalar::Util
Test::More
Time::Piece
XSLoader
);
my %configure_requires =
map { ( $_, $version_for_config{$_} ) }
qw( CPAN::Meta::Converter ),
@always_required,
@packages_for_perl_autoconf;
my %pod_files = ();
{
local $RS = undef;
open my $manifest_fh, q{<}, 'MANIFEST';
my @pod_files = split /\n/xms, $manifest_fh->getline();
close $manifest_fh;
LINE: for my $pod_file (@pod_files) {
$pod_file =~ s/ \s* [#] .* \z //xms;
next LINE if not $pod_file =~ / [.] pod \z /xms;
next LINE if $pod_file =~ m{ libmarpa [/] dev [/] old_pod [/] }xms;
if ( ( my $destfile = $pod_file )
=~ s{ \A pod [/] }{Marpa/R3/}xms )
{
$destfile =~ s{[/]}{-}xmsg;
$pod_files{$pod_file} = q{$(INST_MAN1DIR)/} . $destfile;
next LINE;
} ## end if ( ( my $destfile = $pod_file ) =~ ...)
die "Failed to rename POD file: $pod_file";
} ## end LINE: for my $pod_file (@pod_files)
}
$pod_files{'pod/Marpa_R3.pod'} = q{$(INST_MAN1DIR)} . '/Marpa-R3.pod';
{
my @r3_components = qw(lib Marpa R3);
my $config_pm_filename = File::Spec->catfile(qw(inc Marpa R3 Config.pm ));
my @derived_files = (
File::Spec->catfile( @r3_components, 'Version.pm' ),
File::Spec->catfile( @r3_components, 'Installed.pm' ),
);
say {*STDERR} 'Writing version files' or die "say failed: $ERRNO";
write_installed_pm(qw(lib Marpa R3 ));
my $perl_version_pm = perl_version_contents('Marpa::R3::Perl');
my $version_pm = xs_version_contents('Marpa::R3');
file_write( $version_pm, qw(lib Marpa R3 Version.pm) );
}
my %pm_files = ();
File::Find::find(
sub {
return if not m/[.]pm \z/xms;
my ( $vol, $dirs, $file_name ) = File::Spec->splitpath($File::Find::name);
my @dirs = File::Spec->splitdir($dirs);
shift @dirs; # shift off the lib component
my $dest_dir = File::Spec->catdir( q{$(INST_LIB)}, @dirs );
my $dest_file = File::Spec->catpath( $vol, $dest_dir, $file_name );
$pm_files{$File::Find::name} = $dest_file;
},
'lib/Marpa/R3'
);
{
my $filename = 'R3.pm';
my $from_dir = File::Spec->catdir( qw{lib Marpa } );
my $from_file = File::Spec->catfile( $from_dir, $filename );
my $dest_dir = File::Spec->catdir( q{$(INST_LIB)}, qw{Marpa} );
my $dest_file = File::Spec->catfile( $dest_dir, $filename );
$pm_files{$from_file} = $dest_file;
}
# die Data::Dumper::Dumper(\%pm_files);
my @no_index_namespace_inclusive = qw(
Marpa::R3::Value
Marpa::R3::Perl
Marpa::R3::Test
Marpa::R3::Display
Marpa::R3::Inner
Marpa::R3::Internal
Marpa::R3::MetaAST
Marpa::R3::MetaG
);
my @files_to_cleanup = (
'lib/Marpa/R3/Version.pm', 'lib/Marpa/R3/Installed.pm',
'lib/Marpa/R3.o', 'engine/gnu_ac_build',
'engine/perl_ac_build',
);
my $libmarpa_build_dir =
$use_perl_autoconf
? 'engine/perl_ac_build'
: 'engine/gnu_ac_build';
my $libmarpa_in_build_dir =
$use_perl_autoconf
? $libmarpa_build_dir . q{/libmarpa$(LIB_EXT)}
: $libmarpa_build_dir . q{/.libs/libmarpa$(LIB_EXT)};
my $myextlib = join q{ }, 'xs/R3$(OBJ_EXT)', $libmarpa_in_build_dir;
# my $ccflags = $Config{ccflags} . " -Iengine/read_only -Ixs";
# my @debug_flags = ();
# if ($libmarpa_debug) {
# if ( defined $ENV{LIBMARPA_CFLAGS} ) {
# $ENV{CFLAGS} = $ENV{LIBMARPA_CFLAGS};
# }
# push @debug_flags, '-DMARPA_DEBUG=1';
# push @debug_flags, '-fno-inline', '-Wno-inline'
# if ( $Config{'cc'} eq 'gcc' );
# } ## end if ($libmarpa_debug)
undef &MY::postamble; # suppress warning
*MY::postamble = sub {
my ($self) = @_;
my @postamble_pieces = (".NOTPARALLEL:\n");
# == Logic to compile and build library for GNU autoconf
push @postamble_pieces, sprintf <<'END_OF_POSTAMBLE_PIECE',
engine/gnu_ac_build/.libs/libmarpa$(LIB_EXT):
%s
END_OF_POSTAMBLE_PIECE
$self->cd(File::Spec->catdir(qw(engine)), '$(MAKE)');
# == Logic to compile and build library for Perl autoconf
# GNU autoconf automatically creates/updates stamp-h1.
# For Config::AutoConf, but we don't use it, so we don't create one.
push @postamble_pieces, sprintf <<'END_OF_POSTAMBLE_PIECE',
engine/perl_ac_build/libmarpa$(LIB_EXT):
%s
END_OF_POSTAMBLE_PIECE
$self->cd(File::Spec->catdir(qw(engine)), '$(MAKE)');
# == Logic to build in XS directory:
push @postamble_pieces, sprintf <<'END_OF_POSTAMBLE_PIECE',
xs/R3$(OBJ_EXT):
%s
END_OF_POSTAMBLE_PIECE
$self->cd(File::Spec->catdir(qw(xs)), '$(MAKE)');
return join "\n", @postamble_pieces;
}; ## end sub MY::postamble
WriteMakefile(
clean => { FILES => ( join q{ }, @files_to_cleanup ) },
NAME => 'Marpa::R3',
VERSION => $STRING_VERSION,
AUTHOR => 'Jeffrey Kegler',
ABSTRACT => 'Release 3 of Marpa',
# recommends => \%recommends,
CONFIGURE_REQUIRES => \%configure_requires,
PM => \%pm_files,
TYPEMAPS => ['typemap'],
MIN_PERL_VERSION => '5.10.1',
# CCFLAGS => $ccflags,
DIR => ['engine', 'xs'],
META_ADD => {
no_index => {
directory => [
qw( tool engine author.t )
],
namespace => [
@no_index_namespace_inclusive
],
package =>
[ @no_index_namespace_inclusive, 'Marpa::R3::Trace::G' ],
}
},
META_MERGE => {
resources =>
{ repository => 'git://github.com/jeffreykegler/Marpa--R3.git', },
},
NO_META => 1,
MAN1PODS => \%pod_files,
LICENSE => 'perl_5',
MYEXTLIB => $myextlib
);
# vim: shiftwidth=4: