Initial Commit
This commit is contained in:
357
database/perl/vendor/lib/FFI/Build/File/Base.pm
vendored
Normal file
357
database/perl/vendor/lib/FFI/Build/File/Base.pm
vendored
Normal file
@@ -0,0 +1,357 @@
|
||||
package FFI::Build::File::Base;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use 5.008004;
|
||||
use Carp ();
|
||||
use FFI::Temp;
|
||||
use File::Basename ();
|
||||
use FFI::Build::Platform;
|
||||
use overload '""' => sub { $_[0]->path }, bool => sub { 1 }, fallback => 1;
|
||||
|
||||
# ABSTRACT: Base class for File::Build files
|
||||
our $VERSION = '1.34'; # VERSION
|
||||
|
||||
|
||||
sub new
|
||||
{
|
||||
my($class, $content, %config) = @_;
|
||||
|
||||
my $base = $config{base} || 'ffi_build_';
|
||||
my $dir = $config{dir};
|
||||
my $build = $config{build};
|
||||
my $platform = $config{platform} || FFI::Build::Platform->new;
|
||||
|
||||
my $self = bless {
|
||||
platform => $platform,
|
||||
build => $build,
|
||||
}, $class;
|
||||
|
||||
if(!defined $content)
|
||||
{
|
||||
Carp::croak("content is required");
|
||||
}
|
||||
elsif(ref($content) eq 'ARRAY')
|
||||
{
|
||||
$self->{path} = File::Spec->catfile(@$content);
|
||||
}
|
||||
elsif(ref($content) eq 'SCALAR')
|
||||
{
|
||||
my %args;
|
||||
$args{TEMPLATE} = "${base}XXXXXX";
|
||||
$args{DIR} = $dir if $dir;
|
||||
$args{SUFFIX} = $self->default_suffix;
|
||||
$args{UNLINK} = 0;
|
||||
|
||||
my $fh = $self->{fh} = FFI::Temp->new(%args);
|
||||
|
||||
binmode( $fh, $self->default_encoding );
|
||||
print $fh $$content;
|
||||
close $fh;
|
||||
|
||||
$self->{path} = $fh->filename;
|
||||
$self->{temp} = 1;
|
||||
}
|
||||
elsif(ref($content) eq '')
|
||||
{
|
||||
$self->{path} = $content;
|
||||
}
|
||||
|
||||
if($self->platform->osname eq 'MSWin32')
|
||||
{
|
||||
$self->{native} = File::Spec->catfile($self->{path});
|
||||
$self->{path} =~ s{\\}{/}g;
|
||||
}
|
||||
|
||||
$self;
|
||||
}
|
||||
|
||||
|
||||
sub default_suffix { die "must define a default extension in subclass" }
|
||||
sub default_encoding { die "must define an encoding" }
|
||||
sub accept_suffix { () }
|
||||
|
||||
|
||||
sub path { shift->{path} }
|
||||
sub basename { File::Basename::basename shift->{path} }
|
||||
sub dirname { File::Basename::dirname shift->{path} }
|
||||
sub is_temp { shift->{temp} }
|
||||
sub platform { shift->{platform} }
|
||||
sub build { shift->{build} }
|
||||
|
||||
|
||||
sub native {
|
||||
my($self) = @_;
|
||||
$self->platform->osname eq 'MSWin32'
|
||||
? $self->{native}
|
||||
: $self->{path};
|
||||
}
|
||||
|
||||
|
||||
sub slurp
|
||||
{
|
||||
my($self) = @_;
|
||||
my $fh;
|
||||
open($fh, '<', $self->path) || Carp::croak "Error opening @{[ $self->path ]} for read $!";
|
||||
binmode($fh, $self->default_encoding);
|
||||
my $content = do { local $/; <$fh> };
|
||||
close $fh;
|
||||
$content;
|
||||
}
|
||||
|
||||
|
||||
sub keep
|
||||
{
|
||||
delete shift->{temp};
|
||||
}
|
||||
|
||||
|
||||
sub build_item
|
||||
{
|
||||
Carp::croak("Not implemented!");
|
||||
}
|
||||
|
||||
|
||||
sub needs_rebuild
|
||||
{
|
||||
my($self, @source) = @_;
|
||||
# if the target doesn't exist, then we definitely
|
||||
# need a rebuild.
|
||||
return 1 unless -f $self->path;
|
||||
my $target_time = [stat $self->path]->[9];
|
||||
foreach my $source (@source)
|
||||
{
|
||||
my $source_time = [stat "$source"]->[9];
|
||||
return 1 if ! defined $source_time;
|
||||
return 1 if $source_time > $target_time;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
sub ld
|
||||
{
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub DESTROY
|
||||
{
|
||||
my($self) = @_;
|
||||
|
||||
if($self->{temp})
|
||||
{
|
||||
unlink($self->path);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
FFI::Build::File::Base - Base class for File::Build files
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.34
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
Create your own file class
|
||||
|
||||
package FFI::Build::File::Foo;
|
||||
use base qw( FFI::Build::File::Base );
|
||||
use constant default_suffix => '.foo';
|
||||
use constant default_encoding => ':utf8';
|
||||
|
||||
Use it:
|
||||
|
||||
# use an existing file in the filesystem
|
||||
my $file = FFI::Build::File::Foo->new('src/myfile.foo');
|
||||
|
||||
# generate a temp file with provided content
|
||||
# file will be deletd when $file falls out of scope.
|
||||
my $file = FFI::Build::File::Foo->new(\'content for a temp foo');
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This class is the base class for other L<FFI::Build::File> classes.
|
||||
|
||||
=head1 CONSTRUCTOR
|
||||
|
||||
=head2 new
|
||||
|
||||
my $file = FFI::Build::File::Base->new(\$content, %options);
|
||||
my $file = FFI::Build::File::Base->new($filename, %options);
|
||||
|
||||
Create a new instance of the file class. You may provide either the
|
||||
content of the file as a scalar reference, or the path to an existing
|
||||
filename. Options:
|
||||
|
||||
=over 4
|
||||
|
||||
=item base
|
||||
|
||||
The base name for any temporary file C<ffi_build_> by default.
|
||||
|
||||
=item build
|
||||
|
||||
The L<FFI::Build> instance to use.
|
||||
|
||||
=item dir
|
||||
|
||||
The directory to store any temporary file.
|
||||
|
||||
=item platform
|
||||
|
||||
The L<FFI::Build::Platform> instance to use.
|
||||
|
||||
=back
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 default_suffix
|
||||
|
||||
my $suffix = $file->default_suffix;
|
||||
|
||||
B<MUST> be overridden in the subclass. This is the standard extension for the file type. C<.c> for a C file, C<.o> or C<.obj> for an object file depending on platform. etc.
|
||||
|
||||
=head2 default_encoding
|
||||
|
||||
my $encoding = $file->default_encoding;
|
||||
|
||||
B<MUST> be overridden in the subclass. This is the passed to C<binmode> when the file is opened for reading or writing.
|
||||
|
||||
=head2 accept_suffix
|
||||
|
||||
my @suffix_list = $file->accept_suffix;
|
||||
|
||||
Returns a list of regexes that recognize the file type.
|
||||
|
||||
=head2 path
|
||||
|
||||
my $path = $file->path;
|
||||
|
||||
The full or relative path to the file.
|
||||
|
||||
=head2 basename
|
||||
|
||||
my $basename = $file->basename;
|
||||
|
||||
The base filename part of the path.
|
||||
|
||||
=head2 dirname
|
||||
|
||||
my $dir = $file->dirname;
|
||||
|
||||
The directory part of the path.
|
||||
|
||||
=head2 is_temp
|
||||
|
||||
my $bool = $file->is_temp;
|
||||
|
||||
Returns true if the file is temporary, that is, it will be deleted when the file object falls out of scope.
|
||||
You can call C<keep>, to keep the file.
|
||||
|
||||
=head2 platform
|
||||
|
||||
my $platform = $file->platform;
|
||||
|
||||
The L<FFI::Build::Platform> instance used for this file object.
|
||||
|
||||
=head2 build
|
||||
|
||||
my $build = $file->build;
|
||||
|
||||
The L<FFI::Build> instance used for this file object, if any.
|
||||
|
||||
=head2 native
|
||||
|
||||
my $path = $file->native;
|
||||
|
||||
Returns the operating system native version of the filename path. On Windows, this means that forward slash C<\> is
|
||||
used instead of backslash C</>.
|
||||
|
||||
=head2 slurp
|
||||
|
||||
my $content = $file->slurp;
|
||||
|
||||
Returns the content of the file.
|
||||
|
||||
=head2 keep
|
||||
|
||||
$file->keep;
|
||||
|
||||
Turns off the temporary flag on the file object, meaning it will not automatically be deleted when the
|
||||
file object is deallocated or falls out of scope.
|
||||
|
||||
=head2 build_item
|
||||
|
||||
$file->build_item;
|
||||
|
||||
Builds the file into its natural output type, usually an object file. It returns a new file instance,
|
||||
or if the file is an object file then it returns empty list.
|
||||
|
||||
=head2 build_all
|
||||
|
||||
$file->build_all;
|
||||
|
||||
If implemented the file in question can directly create a shared or dynamic library
|
||||
without needing a link step. This is useful for languages that have their own build
|
||||
systems.
|
||||
|
||||
=head2 needs_rebuild
|
||||
|
||||
my $bool = $file->needs_rebuild
|
||||
|
||||
=head2 ld
|
||||
|
||||
=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
|
||||
244
database/perl/vendor/lib/FFI/Build/File/C.pm
vendored
Normal file
244
database/perl/vendor/lib/FFI/Build/File/C.pm
vendored
Normal file
@@ -0,0 +1,244 @@
|
||||
package FFI::Build::File::C;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use 5.008004;
|
||||
use base qw( FFI::Build::File::Base );
|
||||
use constant default_suffix => '.c';
|
||||
use constant default_encoding => ':utf8';
|
||||
use Capture::Tiny ();
|
||||
use File::Path ();
|
||||
use FFI::Build::File::Object;
|
||||
|
||||
# ABSTRACT: Class to track C source file in FFI::Build
|
||||
our $VERSION = '1.34'; # VERSION
|
||||
|
||||
|
||||
sub accept_suffix
|
||||
{
|
||||
(qr/\.(c|i)$/)
|
||||
}
|
||||
|
||||
sub build_item
|
||||
{
|
||||
my($self) = @_;
|
||||
|
||||
my $oname = $self->basename;
|
||||
$oname =~ s/\.(c(xx|pp)|i)?$//;
|
||||
$oname .= $self->platform->object_suffix;
|
||||
|
||||
my $buildname = '_build';
|
||||
$buildname = $self->build->buildname if $self->build;
|
||||
|
||||
my $object = FFI::Build::File::Object->new(
|
||||
[ $self->dirname, $buildname, $oname ],
|
||||
platform => $self->platform,
|
||||
build => $self->build,
|
||||
);
|
||||
|
||||
return $object if -f $object->path && !$object->needs_rebuild($self->_deps);
|
||||
|
||||
File::Path::mkpath($object->dirname, { verbose => 0, mode => oct(700) });
|
||||
|
||||
my @cmd = (
|
||||
$self->_base_args,
|
||||
-c => $self->path,
|
||||
$self->platform->flag_object_output($object->path),
|
||||
);
|
||||
|
||||
my($out, $exit) = Capture::Tiny::capture_merged(sub {
|
||||
$self->platform->run(@cmd);
|
||||
});
|
||||
|
||||
if($exit || !-f $object->path)
|
||||
{
|
||||
print $out;
|
||||
die "error building $object from $self";
|
||||
}
|
||||
elsif($self->build && $self->build->verbose >= 2)
|
||||
{
|
||||
print $out;
|
||||
}
|
||||
elsif($self->build && $self->build->verbose >= 1)
|
||||
{
|
||||
print "CC @{[ $self->path ]}\n";
|
||||
}
|
||||
|
||||
$object;
|
||||
}
|
||||
|
||||
sub cc
|
||||
{
|
||||
my($self) = @_;
|
||||
$self->platform->cc;
|
||||
}
|
||||
|
||||
sub _base_args
|
||||
{
|
||||
my($self) = @_;
|
||||
my @cmd = ($self->cc);
|
||||
push @cmd, $self->build->cflags_I if $self->build;
|
||||
push @cmd, $self->platform->ccflags;
|
||||
push @cmd, @{ $self->build->cflags } if $self->build;
|
||||
@cmd;
|
||||
}
|
||||
|
||||
sub _base_args_cpp
|
||||
{
|
||||
my($self) = @_;
|
||||
my @cmd = ($self->platform->cpp);
|
||||
push @cmd, $self->build->cflags_I if $self->build;
|
||||
push @cmd, grep /^-[DI]/, $self->platform->ccflags;
|
||||
push @cmd, grep /^-D/, @{ $self->build->cflags } if $self->build;
|
||||
@cmd;
|
||||
}
|
||||
|
||||
sub build_item_cpp
|
||||
{
|
||||
my($self) = @_;
|
||||
|
||||
my $oname = $self->basename;
|
||||
$oname =~ s/\.(c(xx|pp)|i)$?$//;
|
||||
$oname .= '.i';
|
||||
|
||||
my $buildname = '_build';
|
||||
$buildname = $self->build->buildname if $self->build;
|
||||
|
||||
my $ifile = FFI::Build::File::C->new(
|
||||
[ $self->dirname, $buildname, $oname ],
|
||||
platform => $self->platform,
|
||||
build => $self->build,
|
||||
);
|
||||
|
||||
File::Path::mkpath($ifile->dirname, { verbose => 0, mode => oct(700) });
|
||||
|
||||
my @cmd = (
|
||||
$self->_base_args_cpp,
|
||||
$self->path,
|
||||
);
|
||||
|
||||
my($out, $err, $exit) = Capture::Tiny::capture(sub {
|
||||
$self->platform->run(@cmd);
|
||||
});
|
||||
|
||||
if($exit)
|
||||
{
|
||||
print "[out]\n$out\n" if defined $out && $out ne '';
|
||||
print "[err]\n$err\n" if defined $err && $err ne '';
|
||||
die "error building $ifile from $self";
|
||||
}
|
||||
else
|
||||
{
|
||||
my $fh;
|
||||
open($fh, '>', $ifile->path);
|
||||
print $fh $out;
|
||||
close $fh;
|
||||
}
|
||||
|
||||
$ifile;
|
||||
}
|
||||
|
||||
sub _deps
|
||||
{
|
||||
my($self) = @_;
|
||||
|
||||
return $self->path unless $self->platform->cc_mm_works;
|
||||
|
||||
my @cmd = (
|
||||
$self->_base_args,
|
||||
'-MM',
|
||||
$self->path,
|
||||
);
|
||||
|
||||
my($out,$err,$exit) = Capture::Tiny::capture(sub {
|
||||
$self->platform->run(@cmd);
|
||||
});
|
||||
|
||||
if($exit)
|
||||
{
|
||||
print $out;
|
||||
print $err;
|
||||
warn "error computing dependencies for $self";
|
||||
return ($self->path);
|
||||
}
|
||||
else
|
||||
{
|
||||
$out =~ s/^\+.*\n//; # remove the command line
|
||||
# which on windows could have an confusing :
|
||||
my(undef, $deps) = split /:/, $out, 2;
|
||||
$deps =~ s/^\s+//;
|
||||
$deps =~ s/\s+$//;
|
||||
return grep !/^\\$/, split /\s+/, $deps;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
FFI::Build::File::C - Class to track C source file in FFI::Build
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.34
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use FFI::Build::File::C;
|
||||
|
||||
my $c = FFI::Build::File::C->new('src/foo.c');
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
File class for C source files.
|
||||
|
||||
=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
|
||||
100
database/perl/vendor/lib/FFI/Build/File/CXX.pm
vendored
Normal file
100
database/perl/vendor/lib/FFI/Build/File/CXX.pm
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
package FFI::Build::File::CXX;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use 5.008004;
|
||||
use base qw( FFI::Build::File::C );
|
||||
use constant default_suffix => '.cxx';
|
||||
use constant default_encoding => ':utf8';
|
||||
|
||||
# ABSTRACT: Class to track C source file in FFI::Build
|
||||
our $VERSION = '1.34'; # VERSION
|
||||
|
||||
|
||||
sub accept_suffix
|
||||
{
|
||||
(qr/\.c(xx|pp)$/)
|
||||
}
|
||||
|
||||
sub cc
|
||||
{
|
||||
my($self) = @_;
|
||||
$self->platform->cxx;
|
||||
}
|
||||
|
||||
sub ld
|
||||
{
|
||||
my($self) = @_;
|
||||
$self->platform->cxx;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
FFI::Build::File::CXX - Class to track C source file in FFI::Build
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.34
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use FFI::Build::File::CXX;
|
||||
|
||||
my $c = FFI::Build::File::CXX->new('src/foo.cxx');
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
File class for C++ source files.
|
||||
|
||||
=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
|
||||
101
database/perl/vendor/lib/FFI/Build/File/Library.pm
vendored
Normal file
101
database/perl/vendor/lib/FFI/Build/File/Library.pm
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
package FFI::Build::File::Library;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use 5.008004;
|
||||
use base qw( FFI::Build::File::Base );
|
||||
use constant default_encoding => ':raw';
|
||||
|
||||
# ABSTRACT: Class to track object file in FFI::Build
|
||||
our $VERSION = '1.34'; # VERSION
|
||||
|
||||
|
||||
sub default_suffix
|
||||
{
|
||||
shift->platform->library_suffix;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
FFI::Build::File::Library - Class to track object file in FFI::Build
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.34
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use FFI::Build;
|
||||
|
||||
my $build = FFI::Build->new(source => 'src/*.c');
|
||||
# $lib is an instance of FFI::Build::File::Library
|
||||
my $lib = $build->build;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is a class to track a library generated by L<FFI::Build>.
|
||||
This is returned by L<FFI::Build>'s build method. This class
|
||||
is a subclass of L<FFI::Build::File::Base>. The most important
|
||||
method is probably C<path>, which returns the path to the library
|
||||
which can be passed into L<FFI::Platypus> for immediate use.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 path
|
||||
|
||||
my $path = $lib->path;
|
||||
|
||||
Returns the path of the library.
|
||||
|
||||
=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
|
||||
98
database/perl/vendor/lib/FFI/Build/File/Object.pm
vendored
Normal file
98
database/perl/vendor/lib/FFI/Build/File/Object.pm
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
package FFI::Build::File::Object;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use 5.008004;
|
||||
use base qw( FFI::Build::File::Base );
|
||||
use constant default_encoding => ':raw';
|
||||
use Carp ();
|
||||
|
||||
# ABSTRACT: Class to track object file in FFI::Build
|
||||
our $VERSION = '1.34'; # VERSION
|
||||
|
||||
|
||||
sub default_suffix
|
||||
{
|
||||
shift->platform->object_suffix;
|
||||
}
|
||||
|
||||
sub build_item
|
||||
{
|
||||
my($self) = @_;
|
||||
unless(-f $self->path)
|
||||
{
|
||||
Carp::croak "File not built"
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
FFI::Build::File::Object - Class to track object file in FFI::Build
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.34
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use FFI::Build::File::Object;
|
||||
my $o = FFI::Build::File::Object->new('src/_build/foo.o');
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This class represents an object file. You normally do not need
|
||||
to use it directly.
|
||||
|
||||
=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
|
||||
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
|
||||
623
database/perl/vendor/lib/FFI/Build/Platform.pm
vendored
Normal file
623
database/perl/vendor/lib/FFI/Build/Platform.pm
vendored
Normal file
@@ -0,0 +1,623 @@
|
||||
package FFI::Build::Platform;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use 5.008004;
|
||||
use Carp ();
|
||||
use Text::ParseWords ();
|
||||
use FFI::Temp;
|
||||
use Capture::Tiny ();
|
||||
use File::Spec;
|
||||
use FFI::Platypus::ShareConfig;
|
||||
|
||||
# ABSTRACT: Platform specific configuration.
|
||||
our $VERSION = '1.34'; # VERSION
|
||||
|
||||
|
||||
sub new
|
||||
{
|
||||
my($class, $config) = @_;
|
||||
$config ||= do {
|
||||
require Config;
|
||||
\%Config::Config;
|
||||
};
|
||||
my $self = bless {
|
||||
config => $config,
|
||||
}, $class;
|
||||
$self;
|
||||
}
|
||||
|
||||
|
||||
my $default;
|
||||
sub default
|
||||
{
|
||||
$default ||= FFI::Build::Platform->new;
|
||||
}
|
||||
|
||||
sub _self
|
||||
{
|
||||
my($self) = @_;
|
||||
ref $self ? $self : $self->default;
|
||||
}
|
||||
|
||||
|
||||
sub osname
|
||||
{
|
||||
_self(shift)->{config}->{osname};
|
||||
}
|
||||
|
||||
|
||||
sub object_suffix
|
||||
{
|
||||
_self(shift)->{config}->{obj_ext};
|
||||
}
|
||||
|
||||
|
||||
sub library_suffix
|
||||
{
|
||||
my $self = _self(shift);
|
||||
my $osname = $self->osname;
|
||||
my @suffix;
|
||||
if($osname eq 'darwin')
|
||||
{
|
||||
push @suffix, '.dylib', '.bundle';
|
||||
}
|
||||
elsif($osname =~ /^(MSWin32|msys|cygwin)$/)
|
||||
{
|
||||
push @suffix, '.dll';
|
||||
}
|
||||
else
|
||||
{
|
||||
push @suffix, '.' . $self->{config}->{dlext};
|
||||
}
|
||||
wantarray ? @suffix : $suffix[0]; ## no critic (Freenode::Wantarray)
|
||||
}
|
||||
|
||||
|
||||
sub library_prefix
|
||||
{
|
||||
my $self = _self(shift);
|
||||
|
||||
# this almost certainly requires refinement.
|
||||
if($self->osname eq 'cygwin')
|
||||
{
|
||||
return 'cyg';
|
||||
}
|
||||
elsif($self->osname eq 'msys')
|
||||
{
|
||||
return 'msys-';
|
||||
}
|
||||
elsif($self->osname eq 'MSWin32')
|
||||
{
|
||||
return '';
|
||||
}
|
||||
else
|
||||
{
|
||||
return 'lib';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub cc
|
||||
{
|
||||
my $self = _self(shift);
|
||||
my $cc = $self->{config}->{cc};
|
||||
[$self->shellwords($cc)];
|
||||
}
|
||||
|
||||
|
||||
sub cpp
|
||||
{
|
||||
my $self = _self(shift);
|
||||
my $cpp = $self->{config}->{cpprun};
|
||||
[$self->shellwords($cpp)];
|
||||
}
|
||||
|
||||
|
||||
sub cxx
|
||||
{
|
||||
my $self = _self(shift);
|
||||
|
||||
my @cc = @{ $self->cc };
|
||||
|
||||
if($self->{config}->{ccname} eq 'gcc')
|
||||
{
|
||||
if($cc[0] =~ /gcc$/)
|
||||
{
|
||||
my @maybe = @cc;
|
||||
$maybe[0] =~ s/gcc$/g++/;
|
||||
return \@maybe if $self->which($maybe[0]);
|
||||
}
|
||||
if($cc[0] =~ /clang/)
|
||||
{
|
||||
my @maybe = @cc;
|
||||
$maybe[0] =~ s/clang/clang++/;
|
||||
return \@maybe if $self->which($maybe[0]);
|
||||
}
|
||||
|
||||
# TODO: there are probably situations, eg solaris
|
||||
# where we don't want to try c++ in the case of
|
||||
# a ccname = gcc ?
|
||||
my @maybe = qw( c++ g++ clang++ );
|
||||
|
||||
foreach my $maybe (@maybe)
|
||||
{
|
||||
return [$maybe] if $self->which($maybe);
|
||||
}
|
||||
}
|
||||
elsif($self->osname eq 'MSWin32' && $self->{config}->{ccname} eq 'cl')
|
||||
{
|
||||
# TODO: see https://github.com/PerlFFI/FFI-Platypus/issues/203
|
||||
#return \@cc;
|
||||
}
|
||||
|
||||
Carp::croak("unable to detect corresponding C++ compiler");
|
||||
}
|
||||
|
||||
|
||||
sub for
|
||||
{
|
||||
my $self = _self(shift);
|
||||
|
||||
my @cc = @{ $self->cc };
|
||||
|
||||
if($self->{config}->{ccname} eq 'gcc')
|
||||
{
|
||||
if($cc[0] =~ /gcc$/)
|
||||
{
|
||||
my @maybe = @cc;
|
||||
$maybe[0] =~ s/gcc$/gfortran/;
|
||||
return \@maybe if $self->which($maybe[0]);
|
||||
}
|
||||
|
||||
foreach my $maybe (qw( gfortran ))
|
||||
{
|
||||
return [$maybe] if $self->which($maybe);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Carp::croak("unable to detect correspnding Fortran Compiler");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub ld
|
||||
{
|
||||
my($self) = @_;
|
||||
my $ld = $self->{config}->{ld};
|
||||
[$self->shellwords($ld)];
|
||||
}
|
||||
|
||||
|
||||
sub shellwords
|
||||
{
|
||||
my $self = _self(shift);
|
||||
|
||||
my $win = !!($self->osname eq 'MSWin32');
|
||||
|
||||
grep { defined $_ } map {
|
||||
ref $_
|
||||
# if we have an array ref then it has already been shellworded
|
||||
? @$_
|
||||
: do {
|
||||
# remove leading whitespace, confuses some older versions of shellwords
|
||||
my $str = /^\s*(.*)$/ && $1;
|
||||
# escape things on windows
|
||||
$str =~ s,\\,\\\\,g if $win;
|
||||
Text::ParseWords::shellwords($str);
|
||||
}
|
||||
} @_;
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub ccflags
|
||||
{
|
||||
my $self = _self(shift);
|
||||
my @ccflags;
|
||||
push @ccflags, $self->shellwords($self->{config}->{cccdlflags});
|
||||
push @ccflags, $self->shellwords($self->{config}->{ccflags});
|
||||
push @ccflags, $self->shellwords($self->{config}->{optimize});
|
||||
my $dist_include = eval { File::Spec->catdir(FFI::Platypus::ShareConfig::dist_dir('FFI-Platypus'), 'include') };
|
||||
push @ccflags, "-I$dist_include" unless $@;
|
||||
\@ccflags;
|
||||
}
|
||||
|
||||
|
||||
sub ldflags
|
||||
{
|
||||
my $self = _self(shift);
|
||||
my @ldflags = $self->shellwords($self->{config}->{lddlflags});
|
||||
if($self->osname eq 'cygwin')
|
||||
{
|
||||
no warnings 'qw';
|
||||
# doesn't appear to be necessary, Perl has this in lddlflags already on cygwin
|
||||
#push @ldflags, qw( -Wl,--enable-auto-import -Wl,--export-all-symbols -Wl,--enable-auto-image-base );
|
||||
}
|
||||
elsif($self->osname eq 'MSWin32' && $self->{config}->{ccname} eq 'cl')
|
||||
{
|
||||
push @ldflags, qw( -dll );
|
||||
@ldflags = grep !/^-nodefaultlib$/, @ldflags;
|
||||
}
|
||||
elsif($self->osname eq 'MSWin32')
|
||||
{
|
||||
no warnings 'qw';
|
||||
push @ldflags, qw( -Wl,--enable-auto-import -Wl,--export-all-symbols -Wl,--enable-auto-image-base );
|
||||
}
|
||||
elsif($self->osname eq 'darwin')
|
||||
{
|
||||
# we want to build a .dylib instead of a .bundle
|
||||
@ldflags = map { $_ eq '-bundle' ? '-shared' : $_ } @ldflags;
|
||||
}
|
||||
\@ldflags;
|
||||
}
|
||||
|
||||
|
||||
sub cc_mm_works
|
||||
{
|
||||
my $self = _self(shift);
|
||||
my $verbose = shift;
|
||||
$verbose ||= 0;
|
||||
|
||||
unless(defined $self->{cc_mm_works})
|
||||
{
|
||||
require FFI::Build::File::C;
|
||||
my $c = FFI::Build::File::C->new(\"#include \"foo.h\"\n");
|
||||
my $dir = FFI::Temp->newdir;
|
||||
{
|
||||
open my $fh, '>', "$dir/foo.h";
|
||||
print $fh "\n";
|
||||
close $fh;
|
||||
}
|
||||
|
||||
my @cmd = (
|
||||
$self->cc,
|
||||
$self->ccflags,
|
||||
"-I$dir",
|
||||
'-MM',
|
||||
$c->path,
|
||||
);
|
||||
|
||||
my($out, $exit) = Capture::Tiny::capture_merged(sub {
|
||||
$self->run(@cmd);
|
||||
});
|
||||
|
||||
if($verbose >= 2)
|
||||
{
|
||||
print $out;
|
||||
}
|
||||
elsif($verbose >= 1)
|
||||
{
|
||||
print "CC (checkfor -MM)\n";
|
||||
}
|
||||
|
||||
|
||||
if(!$exit && $out =~ /foo\.h/)
|
||||
{
|
||||
$self->{cc_mm_works} = '-MM';
|
||||
}
|
||||
else
|
||||
{
|
||||
$self->{cc_mm_works} = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$self->{cc_mm_works};
|
||||
}
|
||||
|
||||
|
||||
sub flag_object_output
|
||||
{
|
||||
my $self = _self(shift);
|
||||
my $file = shift;
|
||||
if($self->osname eq 'MSWin32' && $self->{config}->{ccname} eq 'cl')
|
||||
{
|
||||
return ("-Fo$file");
|
||||
}
|
||||
else
|
||||
{
|
||||
return ('-o' => $file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub flag_library_output
|
||||
{
|
||||
my $self = _self(shift);
|
||||
my $file = shift;
|
||||
if($self->osname eq 'MSWin32' && $self->{config}->{ccname} eq 'cl')
|
||||
{
|
||||
return ("-OUT:$file");
|
||||
}
|
||||
elsif($self->osname eq 'darwin')
|
||||
{
|
||||
return ('-install_name' => "\@rpath/$file", -o => $file);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ('-o' => $file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub flag_exe_output
|
||||
{
|
||||
my $self = _self(shift);
|
||||
my $file = shift;
|
||||
if($self->osname eq 'MSWin32' && $self->{config}->{ccname} eq 'cl')
|
||||
{
|
||||
my $file = File::Spec->rel2abs($file);
|
||||
return ("/Fe:$file");
|
||||
}
|
||||
else
|
||||
{
|
||||
return ('-o' => $file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub flag_export
|
||||
{
|
||||
my $self = _self(shift);
|
||||
return () unless $self->osname eq 'MSWin32' && $self->{config}->{ccname} eq 'cl';
|
||||
return map { "/EXPORT:$_" } @_;
|
||||
}
|
||||
|
||||
|
||||
sub which
|
||||
{
|
||||
my(undef, $command) = @_;
|
||||
require IPC::Cmd;
|
||||
my @command = ref $command ? @$command : ($command);
|
||||
IPC::Cmd::can_run($command[0]);
|
||||
}
|
||||
|
||||
|
||||
sub run
|
||||
{
|
||||
my $self = shift;
|
||||
my @command = map { ref $_ ? @$_ : $_ } grep { defined $_ } @_;
|
||||
print "+@command\n";
|
||||
system @command;
|
||||
$?;
|
||||
}
|
||||
|
||||
|
||||
sub _c { join ',', @_ }
|
||||
sub _l { join ' ', map { ref $_ ? @$_ : $_ } @_ }
|
||||
|
||||
sub diag
|
||||
{
|
||||
my $self = _self(shift);
|
||||
my @diag;
|
||||
|
||||
push @diag, "osname : ". _c($self->osname);
|
||||
push @diag, "cc : ". _l($self->cc);
|
||||
push @diag, "cxx : ". (eval { _l($self->cxx) } || '---' );
|
||||
push @diag, "for : ". (eval { _l($self->for) } || '---' );
|
||||
push @diag, "ld : ". _l($self->ld);
|
||||
push @diag, "ccflags : ". _l($self->ccflags);
|
||||
push @diag, "ldflags : ". _l($self->ldflags);
|
||||
push @diag, "object suffix : ". _c($self->object_suffix);
|
||||
push @diag, "library prefix : ". _c($self->library_prefix);
|
||||
push @diag, "library suffix : ". _c($self->library_suffix);
|
||||
push @diag, "cc mm works : ". $self->cc_mm_works;
|
||||
|
||||
join "\n", @diag;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
FFI::Build::Platform - Platform specific configuration.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.34
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use FFI::Build::Platform;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This class is used to abstract out the platform specific parts of the L<FFI::Build> system.
|
||||
You shouldn't need to use it directly in most cases, unless you are working on L<FFI::Build>
|
||||
itself.
|
||||
|
||||
=head1 CONSTRUCTOR
|
||||
|
||||
=head2 new
|
||||
|
||||
my $platform = FFI::Build::Platform->new;
|
||||
|
||||
Create a new instance of L<FFI::Build::Platform>.
|
||||
|
||||
=head2 default
|
||||
|
||||
my $platform = FFI::Build::Platform->default;
|
||||
|
||||
Returns the default instance of L<FFI::Build::Platform>.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
All of these methods may be called either as instance or classes
|
||||
methods. If called as a class method, the default instance will
|
||||
be used.
|
||||
|
||||
=head2 osname
|
||||
|
||||
my $osname = $platform->osname;
|
||||
|
||||
The "os name" as understood by Perl. This is the same as C<$^O>.
|
||||
|
||||
=head2 object_suffix
|
||||
|
||||
my $suffix = $platform->object_suffix;
|
||||
|
||||
The object suffix for the platform. On UNIX this is usually C<.o>. On Windows this
|
||||
is usually C<.obj>.
|
||||
|
||||
=head2 library_suffix
|
||||
|
||||
my(@suffix) = $platform->library_suffix;
|
||||
my $suffix = $platform->library_suffix;
|
||||
|
||||
The library suffix for the platform. On Linux and some other UNIX this is often C<.so>.
|
||||
On OS X, this is C<.dylib> and C<.bundle>. On Windows this is C<.dll>.
|
||||
|
||||
=head2 library_prefix
|
||||
|
||||
my $prefix = $platform->library_prefix;
|
||||
|
||||
The library prefix for the platform. On Unix this is usually C<lib>, as in C<libfoo>.
|
||||
|
||||
=head2 cc
|
||||
|
||||
my @cc = @{ $platform->cc };
|
||||
|
||||
The C compiler
|
||||
|
||||
=head2 cpp
|
||||
|
||||
my @cpp = @{ $platform->cpp };
|
||||
|
||||
The C pre-processor
|
||||
|
||||
=head2 cxx
|
||||
|
||||
my @cxx = @{ $platform->cxx };
|
||||
|
||||
The C++ compiler that naturally goes with the C compiler.
|
||||
|
||||
=head2 for
|
||||
|
||||
my @for = @{ $platform->for };
|
||||
|
||||
The Fortran compiler that naturally goes with the C compiler.
|
||||
|
||||
=head2 ld
|
||||
|
||||
my $ld = $platform->ld;
|
||||
|
||||
The C linker
|
||||
|
||||
=head2 shellwords
|
||||
|
||||
my @words = $platform->shellwords(@strings);
|
||||
|
||||
This is a wrapper around L<Text::ParseWords>'s C<shellwords> with some platform workarounds
|
||||
applied.
|
||||
|
||||
=head2 ccflags
|
||||
|
||||
my @ccflags = @{ $platform->cflags};
|
||||
|
||||
The compiler flags, including those needed to compile object files that can be linked into a dynamic library.
|
||||
On Linux, for example, this is usually includes C<-fPIC>.
|
||||
|
||||
=head2 ldflags
|
||||
|
||||
my @ldflags = @{ $platform->ldflags };
|
||||
|
||||
The linker flags needed to link object files into a dynamic library. This is NOT the C<libs> style library
|
||||
flags that specify the location and name of a library to link against, this is instead the flags that tell
|
||||
the linker to generate a dynamic library. On Linux, for example, this is usually C<-shared>.
|
||||
|
||||
=head2 cc_mm_works
|
||||
|
||||
my $bool = $platform->cc_mm_works;
|
||||
|
||||
Returns the flags that can be passed into the C compiler to compute dependencies.
|
||||
|
||||
=head2 flag_object_output
|
||||
|
||||
my @flags = $platform->flag_object_output($object_filename);
|
||||
|
||||
Returns the flags that the compiler recognizes as being used to write out to a specific object filename.
|
||||
|
||||
=head2 flag_library_output
|
||||
|
||||
my @flags = $platform->flag_library_output($library_filename);
|
||||
|
||||
Returns the flags that the compiler recognizes as being used to write out to a specific library filename.
|
||||
|
||||
=head2 flag_exe_output
|
||||
|
||||
my @flags = $platform->flag_exe_output($library_filename);
|
||||
|
||||
Returns the flags that the compiler recognizes as being used to write out to a specific exe filename.
|
||||
|
||||
=head2 flag_export
|
||||
|
||||
my @flags = $platform->flag_export(@symbols);
|
||||
|
||||
Returns the flags that the linker recognizes for exporting functions.
|
||||
|
||||
=head2 which
|
||||
|
||||
my $path = $platform->which($command);
|
||||
|
||||
Returns the full path of the given command, if it is available, otherwise C<undef> is returned.
|
||||
|
||||
=head2 run
|
||||
|
||||
$platform->run(@command);
|
||||
|
||||
=head2 diag
|
||||
|
||||
Diagnostic for the platform as a string. This is for human consumption only, and the format
|
||||
may and will change over time so do not attempt to use is programmatically.
|
||||
|
||||
=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