Initial Commit
This commit is contained in:
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