Initial Commit
This commit is contained in:
440
database/perl/vendor/lib/FFI/Build/MM.pm
vendored
Normal file
440
database/perl/vendor/lib/FFI/Build/MM.pm
vendored
Normal file
@@ -0,0 +1,440 @@
|
||||
package FFI::Build::MM;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use 5.008004;
|
||||
use Carp ();
|
||||
use FFI::Build;
|
||||
use JSON::PP ();
|
||||
use File::Glob ();
|
||||
use File::Basename ();
|
||||
use File::Path ();
|
||||
use File::Copy ();
|
||||
use ExtUtils::MakeMaker 7.12;
|
||||
|
||||
# ABSTRACT: FFI::Build installer code for ExtUtils::MakeMaker
|
||||
our $VERSION = '1.34'; # VERSION
|
||||
|
||||
|
||||
sub new
|
||||
{
|
||||
my($class, %opt) = @_;
|
||||
|
||||
my $save = defined $opt{save} ? $opt{save} : 1;
|
||||
|
||||
my $self = bless { save => $save }, $class;
|
||||
$self->load_prop;
|
||||
|
||||
$self;
|
||||
}
|
||||
|
||||
|
||||
sub mm_args
|
||||
{
|
||||
my($self, %args) = @_;
|
||||
|
||||
if($args{DISTNAME})
|
||||
{
|
||||
$self->{prop}->{distname} ||= $args{DISTNAME};
|
||||
$self->{prop}->{share} ||= "blib/lib/auto/share/dist/@{[ $self->distname ]}";
|
||||
$self->{prop}->{arch} ||= "blib/arch/auto/@{[ join '/', split /-/, $self->distname ]}";
|
||||
$self->save_prop;
|
||||
}
|
||||
else
|
||||
{
|
||||
Carp::croak "DISTNAME is required";
|
||||
}
|
||||
|
||||
|
||||
if(my $build = $self->build)
|
||||
{
|
||||
foreach my $alien (@{ $build->alien })
|
||||
{
|
||||
next if ref $alien;
|
||||
$args{BUILD_REQUIRES}->{$alien} ||= 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(my $test = $self->test)
|
||||
{
|
||||
foreach my $alien (@{ $test->alien })
|
||||
{
|
||||
next if ref $alien;
|
||||
$args{TEST_REQUIRES}->{$alien} ||= 0;
|
||||
}
|
||||
}
|
||||
|
||||
%args;
|
||||
}
|
||||
|
||||
sub distname { shift->{prop}->{distname} }
|
||||
|
||||
sub sharedir
|
||||
{
|
||||
my($self, $new) = @_;
|
||||
|
||||
if(defined $new)
|
||||
{
|
||||
$self->{prop}->{share} = $new;
|
||||
$self->save_prop;
|
||||
}
|
||||
|
||||
$self->{prop}->{share};
|
||||
}
|
||||
|
||||
sub archdir
|
||||
{
|
||||
my($self, $new) = @_;
|
||||
|
||||
if(defined $new)
|
||||
{
|
||||
$self->{prop}->{arch} = $new;
|
||||
$self->save_prop;
|
||||
}
|
||||
|
||||
$self->{prop}->{arch};
|
||||
}
|
||||
|
||||
sub load_build
|
||||
{
|
||||
my($self, $dir, $name, $install) = @_;
|
||||
return unless -d $dir;
|
||||
my($fbx) = File::Glob::bsd_glob("./$dir/*.fbx");
|
||||
|
||||
my $options;
|
||||
my $platform = FFI::Build::Platform->default;
|
||||
|
||||
if($fbx)
|
||||
{
|
||||
$name = File::Basename::basename($fbx);
|
||||
$name =~ s/\.fbx$//;
|
||||
$options = do {
|
||||
package FFI::Build::MM::FBX;
|
||||
our $DIR = $dir;
|
||||
our $PLATFORM = $platform;
|
||||
|
||||
# make sure we catch all of the errors
|
||||
# code copied from `perldoc -f do`
|
||||
my $return = do $fbx;
|
||||
unless ( $return ) {
|
||||
Carp::croak( "couldn't parse $fbx: $@" ) if $@;
|
||||
Carp::croak( "couldn't do $fbx: $!" ) unless defined $return;
|
||||
Carp::croak( "couldn't run $fbx" ) unless $return;
|
||||
}
|
||||
|
||||
$return;
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
$name ||= $self->distname;
|
||||
$options = {
|
||||
source => ["$dir/*.c", "$dir/*.cxx", "$dir/*.cpp"],
|
||||
};
|
||||
# if we see a Go, Rust control file then we assume the
|
||||
# ffi mod is written in that language.
|
||||
foreach my $control_file ("$dir/Cargo.toml", "$dir/go.mod")
|
||||
{
|
||||
if(-f $control_file)
|
||||
{
|
||||
$options->{source} = [$control_file];
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$options->{platform} ||= $platform;
|
||||
$options->{dir} ||= ref $install ? $install->($options) : $install;
|
||||
$options->{verbose} = 1 unless defined $options->{verbose};
|
||||
FFI::Build->new($name, %$options);
|
||||
}
|
||||
|
||||
sub build
|
||||
{
|
||||
my($self) = @_;
|
||||
$self->{build} ||= $self->load_build('ffi', undef, $self->sharedir . "/lib");
|
||||
}
|
||||
|
||||
sub test
|
||||
{
|
||||
my($self) = @_;
|
||||
$self->{test} ||= $self->load_build('t/ffi', 'test', sub {
|
||||
my($opt) = @_;
|
||||
my $buildname = $opt->{buildname} || '_build';
|
||||
"t/ffi/$buildname";
|
||||
});
|
||||
}
|
||||
|
||||
sub save_prop
|
||||
{
|
||||
my($self) = @_;
|
||||
return unless $self->{save};
|
||||
open my $fh, '>', 'fbx.json';
|
||||
print $fh JSON::PP::encode_json($self->{prop});
|
||||
close $fh;
|
||||
}
|
||||
|
||||
sub load_prop
|
||||
{
|
||||
my($self) = @_;
|
||||
return unless $self->{save};
|
||||
unless(-f 'fbx.json')
|
||||
{
|
||||
$self->{prop} = {};
|
||||
return;
|
||||
}
|
||||
open my $fh, '<', 'fbx.json';
|
||||
$self->{prop} = JSON::PP::decode_json(do { local $/; <$fh> });
|
||||
close $fh;
|
||||
}
|
||||
|
||||
sub clean
|
||||
{
|
||||
my($self) = @_;
|
||||
foreach my $stage (qw( build test ))
|
||||
{
|
||||
my $build = $self->$stage;
|
||||
$build->clean if $build;
|
||||
}
|
||||
unlink 'fbx.json' if -f 'fbx.json';
|
||||
}
|
||||
|
||||
|
||||
sub mm_postamble
|
||||
{
|
||||
my($self) = @_;
|
||||
|
||||
my $postamble = ".PHONY: fbx_build ffi fbx_test ffi-test fbx_clean ffi-clean\n\n";
|
||||
|
||||
# make fbx_realclean ; make clean
|
||||
$postamble .= "realclean :: fbx_clean\n" .
|
||||
"\n" .
|
||||
"fbx_clean ffi-clean:\n" .
|
||||
"\t\$(FULLPERL) -MFFI::Build::MM=cmd -e fbx_clean\n\n";
|
||||
|
||||
# make fbx_build; make
|
||||
$postamble .= "pure_all :: fbx_build\n" .
|
||||
"\n" .
|
||||
"fbx_build ffi:\n" .
|
||||
"\t\$(FULLPERL) -MFFI::Build::MM=cmd -e fbx_build\n\n";
|
||||
|
||||
# make fbx_test; make test
|
||||
$postamble .= "subdirs-test_dynamic subdirs-test_static subdirs-test :: fbx_test\n" .
|
||||
"\n" .
|
||||
"fbx_test ffi-test:\n" .
|
||||
"\t\$(FULLPERL) -MFFI::Build::MM=cmd -e fbx_test\n\n";
|
||||
|
||||
$postamble;
|
||||
}
|
||||
|
||||
sub action_build
|
||||
{
|
||||
my($self) = @_;
|
||||
my $build = $self->build;
|
||||
if($build)
|
||||
{
|
||||
my $lib = $build->build;
|
||||
if($self->archdir)
|
||||
{
|
||||
File::Path::mkpath($self->archdir, 0, oct(755));
|
||||
my $archfile = File::Spec->catfile($self->archdir, File::Basename::basename($self->archdir) . ".txt");
|
||||
open my $fh, '>', $archfile;
|
||||
my $lib_path = $lib->path;
|
||||
$lib_path =~ s/^blib\/lib\///;
|
||||
print $fh "FFI::Build\@$lib_path\n";
|
||||
close $fh;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sub action_test
|
||||
{
|
||||
my($self) = @_;
|
||||
my $build = $self->test;
|
||||
$build->build if $build;
|
||||
}
|
||||
|
||||
sub action_clean
|
||||
{
|
||||
my($self) = @_;
|
||||
my $build = $self->clean;
|
||||
();
|
||||
}
|
||||
|
||||
sub import
|
||||
{
|
||||
my(undef, @args) = @_;
|
||||
foreach my $arg (@args)
|
||||
{
|
||||
if($arg eq 'cmd')
|
||||
{
|
||||
package main;
|
||||
|
||||
my $mm = sub {
|
||||
my($action) = @_;
|
||||
my $build = FFI::Build::MM->new;
|
||||
$build->$action;
|
||||
};
|
||||
|
||||
no warnings 'once';
|
||||
|
||||
*fbx_build = sub {
|
||||
$mm->('action_build');
|
||||
};
|
||||
|
||||
*fbx_test = sub {
|
||||
$mm->('action_test');
|
||||
};
|
||||
|
||||
*fbx_clean = sub {
|
||||
$mm->('action_clean');
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
FFI::Build::MM - FFI::Build installer code for ExtUtils::MakeMaker
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.34
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
In your Makefile.PL:
|
||||
|
||||
use ExtUtils::MakeMaker;
|
||||
use FFI::Build::MM;
|
||||
|
||||
my $fbmm = FFI::Build::MM->new;
|
||||
|
||||
WriteMakefile($fbmm->mm_args(
|
||||
ABSTRACT => 'My FFI extension',
|
||||
DISTNAME => 'Foo-Bar-Baz-FFI',
|
||||
NAME => 'Foo::Bar::Baz::FFI',
|
||||
VERSION_FROM => 'lib/Foo/Bar/Baz/FFI.pm',
|
||||
...
|
||||
));
|
||||
|
||||
sub MY::postamble {
|
||||
$fbmm->mm_postamble;
|
||||
}
|
||||
|
||||
Then put the C, C++ or Fortran files in C<./ffi> for your runtime library
|
||||
and C<./t/ffi> for your test time library.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module provides a thin layer between L<FFI::Build> and L<ExtUtils::MakeMaker>.
|
||||
Its interface is influenced by the design of L<Alien::Build::MM>. The idea is that
|
||||
for your distribution you throw some C, C++ or Fortran source files into a directory
|
||||
called C<ffi> and these files will be compiled and linked into a library that can
|
||||
be used by your module. There is a control file C<ffi/*.fbx> which can be used to
|
||||
control the compiler and linker options. (options passed directly into L<FFI::Build>).
|
||||
The interface for this file is still under development.
|
||||
|
||||
=head1 CONSTRUCTOR
|
||||
|
||||
=head2 new
|
||||
|
||||
my $fbmm = FFI::Build::MM->new;
|
||||
|
||||
Create a new instance of L<FFI::Build::MM>.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 mm_args
|
||||
|
||||
my %new_args = $fbmm->mm_args(%old_args);
|
||||
|
||||
This method does two things:
|
||||
|
||||
=over 4
|
||||
|
||||
=item reads the arguments to determine sensible defaults (library name, install location, etc).
|
||||
|
||||
=item adjusts the arguments as necessary and returns an updated set of arguments.
|
||||
|
||||
=back
|
||||
|
||||
=head2 mm_postamble
|
||||
|
||||
my $postamble = $fbmm->mm_postamble;
|
||||
|
||||
This returns the Makefile postamble used by L<ExtUtils::MakeMaker>. The synopsis above for
|
||||
how to invoke it properly. It adds the following Make targets:
|
||||
|
||||
=over 4
|
||||
|
||||
=item fbx_build / ffi
|
||||
|
||||
build the main runtime library in C<./ffi>.
|
||||
|
||||
=item fbx_test / ffi-test
|
||||
|
||||
Build the test library in C<./t/ffi>.
|
||||
|
||||
=item fbx_clean / ffi-clean
|
||||
|
||||
Clean any runtime or test libraries already built.
|
||||
|
||||
=back
|
||||
|
||||
Normally you do not need to build these targets manually, they will be built automatically
|
||||
at the appropriate stage.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Author: Graham Ollis E<lt>plicease@cpan.orgE<gt>
|
||||
|
||||
Contributors:
|
||||
|
||||
Bakkiaraj Murugesan (bakkiaraj)
|
||||
|
||||
Dylan Cali (calid)
|
||||
|
||||
pipcet
|
||||
|
||||
Zaki Mughal (zmughal)
|
||||
|
||||
Fitz Elliott (felliott)
|
||||
|
||||
Vickenty Fesunov (vyf)
|
||||
|
||||
Gregor Herrmann (gregoa)
|
||||
|
||||
Shlomi Fish (shlomif)
|
||||
|
||||
Damyan Ivanov
|
||||
|
||||
Ilya Pavlov (Ilya33)
|
||||
|
||||
Petr Pisar (ppisar)
|
||||
|
||||
Mohammad S Anwar (MANWAR)
|
||||
|
||||
Håkon Hægland (hakonhagland, HAKONH)
|
||||
|
||||
Meredith (merrilymeredith, MHOWARD)
|
||||
|
||||
Diab Jerius (DJERIUS)
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2015,2016,2017,2018,2019,2020 by Graham Ollis.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
||||
Reference in New Issue
Block a user