Alien-Base

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

    on October 1, 2017, so you need to update your Build.PL so that
    Alien::Base::ModuleBuild is a configure requires.

0.038 2017-03-06 00:16:18 -0500
  - Production release identical to 0.035_01 release

0.037_02 2017-03-05 03:20:00 -0500
  - Additional fixex for t/yy-system_installed.t

0.037_01 2017-03-03 05:29:54 +1100
  - cflags and cflags_static were flipped in 0.035_01 is now fixed
    (should fix gh#183)

0.036 2017-02-27 03:28:36 -0500
  - Production release identical to 0.035_01 release

0.035_01 2017-02-15 04:41:31 -0500
  - Add support for Alien::Build (plicease #181)

0.034 2017-02-15 04:30:35 -0500
  - Fixed regression introduced in 0.032 which broke repos as array

Changes  view on Meta::CPAN

  - Production release identical to 0.014_01 release

0.014_01  Fri Mar 13, 2015
  - Generate config.site for autoconfigure source installs (plicease gh#113)

0.014  Feb 25, 2015
  - Production release identical to 0.012_01 release

0.012_01  Feb 24, 2015
  - Prefer and require PkgConfig.pm over pkg-config on 64 solaris
    If pkg-config is used it will likely be giving flags for 32 bit libs
    (plicease gh#110)
  - Allow for relocation of Alien-Base based dists.
    (plicease gh#111)

0.012  Feb 22, 2015
  - Fix bug introduced in 0.011 where bin_dir dies when install_type=system

0.011  Feb 22, 2015
  - Production release identical to 0.010_01 release

corpus/lib/Alien/Foo2/ConfigData.pm  view on Meta::CPAN

         'ffi_name' => undef,
         'finished_installing' => 1,
         'inline_auto_include' => [],
         'install_type' => 'share',
         'msys' => 0,
         'name' => 'libfoo2',
         'original_prefix' => '/home/user/.cpanm/work/1456299506.4021/Alien-Foo2-0.12/blib/lib/auto/share/dist/Alien-Foo2',
         'pkgconfig' => {
                          '_manual' => bless( {
                                                'keywords' => {
                                                                'Cflags' => '-I${pcfiledir}/lib/libfoo2-3.2.1/include',
                                                                'Libs' => '-L${pcfiledir}/lib -lfoo2',
                                                                'Version' => ''
                                                              },
                                                'package' => 'libfoo2',
                                                'vars' => {
                                                            'pcfiledir' => '/home/user/.cpanm/work/1456299506.4021/Alien-Foo2-0.12/blib/lib/auto/share/dist/Alien-Foo2'
                                                          }
                                              }, 'Alien::Base::PkgConfig' ),
                          'libfoo2' => bless( {
                                               'keywords' => {
                                                               'Cflags' => '-I${includedir}',
                                                               'Description' => 'Library supporting Foreign Function Interfaces',
                                                               'Libs' => '-L${toolexeclibdir} -lfoo2',
                                                               'Name' => 'libfoo2',
                                                               'Version' => '3.2.1'
                                                             },
                                               'package' => 'libfoo2',
                                               'vars' => {
                                                           'exec_prefix' => '${prefix}',
                                                           'includedir' => '${libdir}/libfoo2-3.2.1/include',
                                                           'libdir' => '${exec_prefix}/lib',

corpus/lib/auto/share/dist/Alien-libfoo1/_alien/alien.json  view on Meta::CPAN

   "libs" : "-lfoo ",
   "install_type" : "system",
   "version" : "1.2.3",
   "legacy" : {
      "finished_installing" : 1,
      "name" : "foo",
      "version" : "1.2.3",
      "original_prefix" : "/foo/bar/baz/auto/share/dist/Alien-libfoo1",
      "install_type" : "system"
   },
   "cflags_static" : "-DFOO=1 -DFOO_STATIC=1 ",
   "cflags" : "-DFOO=1 ",
   "libs_static" : "-lfoo -lbar -lbaz ",
   "prefix" : "/foo/bar/baz/auto/share/dist/Alien-libfoo1",
   "arbitrary" : "one"
}

corpus/lib/auto/share/dist/Alien-libfoo2/_alien/alien.json  view on Meta::CPAN

   "libs" : "-L/foo/bar/baz/auto/share/dist/Alien-libfoo1/lib -lfoo ",
   "install_type" : "share",
   "version" : "2.3.4",
   "legacy" : {
      "finished_installing" : 1,
      "name" : "foo",
      "version" : "2.3.4",
      "original_prefix" : "/foo/bar/baz/auto/share/dist/Alien-libfoo1",
      "install_type" : "share"
   },
   "cflags_static" : "-I/foo/bar/baz/auto/share/dist/Alien-libfoo1/include -DFOO=1 -DFOO_STATIC=1 ",
   "cflags" : "-I/foo/bar/baz/auto/share/dist/Alien-libfoo1/include -DFOO=1 ",
   "libs_static" : "-L/foo/bar/baz/auto/share/dist/Alien-libfoo1/lib -lfoo -lbar -lbaz ",
   "prefix" : "/foo/bar/baz/auto/share/dist/Alien-libfoo1",
   "arbitrary" : "two"
}

corpus/pkgconfig/libbar1.pc  view on Meta::CPAN

prefix=/home/user/opt/libfoo1/git-06747d318761884e70dfa433a9548219fd779d7d
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
toolexeclibdir=${exec_prefix}/lib/../lib
includedir=${libdir}/libfoo1-3.99999/include

Name: libfoo1
Description: Library supporting Foreign Function Interfaces
Version: 3.99999
Libs: -lbar1
Cflags: -DFOO=stuff

corpus/pkgconfig/libfoo1.pc  view on Meta::CPAN

prefix=/home/user/opt/libfoo1/git-06747d318761884e70dfa433a9548219fd779d7d
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
toolexeclibdir=${exec_prefix}/lib/../lib
includedir=${libdir}/libfoo1-3.99999/include

Name: libfoo1
Description: Library supporting Foreign Function Interfaces
Version: 3.99999
Libs: -lfoo1
Cflags: -DFOO=stuff

lib/Alien/Base.pm  view on Meta::CPAN

that should be bundled with your L<Alien::Base> subclass, please see
L<Alien::Base::Authoring>).

Then a C<MyLibrary::XS> can use C<Alien::MyLibrary> in its C<Build.PL>:

 use Alien::MyLibrary;
 use Module::Build 0.28; # need at least 0.28
 
 my $builder = Module::Build->new(
   ...
   extra_compiler_flags => Alien::MyLibrary->cflags,
   extra_linker_flags   => Alien::MyLibrary->libs,
   ...
 );
 
 $builder->create_build_script;

Or if you prefer L<ExtUtils::MakeMaker>, in its C<Makefile.PL>:

 use Alien::MyLibrary
 use ExtUtils::MakeMaker;
 use Config;
 
 WriteMakefile(
   ...
   CCFLAGS => Alien::MyLibrary->cflags . " $Config{ccflags}",
   LIBS   => ALien::MyLibrary->libs,
   ...
 );

Or if you are using L<ExtUtils::Depends>:

 use ExtUtils::MakeMaker;
 use ExtUtils::Depends;
 my $eud = ExtUtils::Depends->new(qw( MyLibrary::XS Alien::MyLibrary ));
 WriteMakefile(

lib/Alien/Base.pm  view on Meta::CPAN


  # get a reference to %Alien::MyLibrary::AlienLoaded
  # which contains names of already loaded libraries
  # this logic may be replaced by investigating the DynaLoader arrays
  my $loaded = do {
    no strict 'refs';
    no warnings 'once';
    \%{ $class . "::AlienLoaded" };
  };

  my @libs = $class->split_flags( $class->libs );

  my @L = grep { s/^-L// } @libs;
  my @l = grep { /^-l/ } @libs;

  unshift @DynaLoader::dl_library_path, @L;

  my @libpaths;
  foreach my $l (@l) {
    next if $loaded->{$l};

lib/Alien/Base.pm  view on Meta::CPAN

      : $class->config('working_directory');

  croak "Failed to find share dir for dist '$dist'"
    unless defined $dist_dir && -d $dist_dir;

  return $dist_dir;
}

sub new { return bless {}, $_[0] }

sub _flags
{
  my($class, $key) = @_;
  
  my $config = $class->runtime_prop;
  my $flags = $config->{$key};

  my $prefix = $config->{prefix};
  $prefix =~ s{\\}{/}g if $^O =~ /^(MSWin32|msys)$/;
  my $distdir = $config->{distdir};
  $distdir =~ s{\\}{/}g if $^O =~ /^(MSWin32|msys)$/;
  
  if($prefix ne $distdir)
  {
    $flags = join ' ', map { 
      s/^(-I|-L|-LIBPATH:)?\Q$prefix\E/$1$distdir/;
      s/(\s)/\\$1/g;
      $_;
    } $class->split_flags($flags);
  }
  
  $flags;
}

=head2 cflags

 my $cflags = Alien::MyLibrary->cflags;

 use Text::ParseWords qw( shellwords );
 my @cflags = shellwords( Alien::MyLibrary->cflags );

Returns the C compiler flags necessary to compile an XS
module using the alien software.  If you need this in list
form (for example if you are calling system with a list
argument) you can pass this value into C<shellwords> from
the Perl core L<Text::ParseWords> module.

=cut

sub cflags {
  my $class = shift;
  return $class->runtime_prop ? $class->_flags('cflags') : $class->_pkgconfig_keyword('Cflags');
}

sub cflags_static {
  my $class = shift;
  return $class->runtime_prop ? $class->_flags('cflags_static') : $class->_pkgconfig_keyword('Cflags', 'static');
}

=head2 libs

 my $libs = Alien::MyLibrary->libs;

 use Text::ParseWords qw( shellwords );
 my @cflags = shellwords( Alien::MyLibrary->libs );

Returns the library linker flags necessary to link an XS
module against the alien software.  If you need this in list
form (for example if you are calling system with a list
argument) you can pass this value into C<shellwords> from
the Perl core L<Text::ParseWords> module.

=cut

sub libs {
  my $class = shift;
  return $class->runtime_prop ? $class->_flags('libs') : $class->_pkgconfig_keyword('Libs');
}

sub libs_static {
  my $class = shift;
  return $class->runtime_prop ? $class->_flags('libs_static') : $class->_pkgconfig_keyword('Libs', 'static');
}

=head2 version

 my $version = Alien::MyLibrary->version;

Returns the version of the Alienized library or tool that was
determined at install time.

=cut

lib/Alien/Base.pm  view on Meta::CPAN


  if(defined $self->config('original_prefix') && $self->config('original_prefix') ne $self->dist_dir)
  {
    my $dist_dir = $self->dist_dir;
    $dist_dir =~ s{\\}{/}g if $^O eq 'MSWin32';
    my $old = quotemeta $self->config('original_prefix');
    @strings = map {
      s{^(-I|-L|-LIBPATH:)?($old)}{$1.$dist_dir}e;
      s/(\s)/\\$1/g;
      $_;
    } map { $self->split_flags($_) } @strings;
  }

  return join( ' ', @strings );
}

sub _pkgconfig {
  my $self = shift;
  my %all = %{ $self->config('pkgconfig') };

  # merge in found pc files

lib/Alien/Base.pm  view on Meta::CPAN

    return $ab_config->{legacy}->{$key};
  }

  my $config = $class . '::ConfigData';
  eval "require $config";
  warn $@ if $@;

  return $config->config(@_);
}

# helper method to split flags based on the OS
sub split_flags {
  my ($class, $line) = @_;
  if( $^O eq 'MSWin32' ) {
    $class->split_flags_windows($line);
  } else {
    # $os eq 'Unix'
    $class->split_flags_unix($line);
  }
}

sub split_flags_unix {
  my ($class, $line) = @_;
  shellwords($line);
}

sub split_flags_windows {
  # NOTE a better approach would be to write a function that understands cmd.exe metacharacters.
  my ($class, $line) = @_;

  # Double the backslashes so that when they are unescaped by shellwords(),
  # they become a single backslash. This should be fine on Windows since
  # backslashes are not used to escape metacharacters in cmd.exe.
  $line =~ s,\\,\\\\,g;
  shellwords($line);
}

lib/Alien/Base.pm  view on Meta::CPAN

sub inline_auto_include {
  my ($class) = @_;
  return [] unless $class->config('inline_auto_include');
  $class->config('inline_auto_include')
}

sub Inline {
  my ($class, $language) = @_;
  return if $language !~ /^(C|CPP)$/;
  my $config = {
    CCFLAGSEX    => $class->cflags,
    LIBS         => $class->libs,
  };
  
  if (@{ $class->inline_auto_include } > 0) {
    $config->{AUTO_INCLUDE} = join "\n", map { "#include \"$_\"" } @{ $class->inline_auto_include };
  }
  
  $config;
}

t/alien_base.t  view on Meta::CPAN


unshift @PKG_CONFIG_PATH, File::Spec->rel2abs(File::Spec->catdir( qw( corpus pkgconfig )));

subtest 'AB::MB sys install' => sub {

  skip_all 'test requires Alien::Base::PkgConfig'
    unless eval { require Alien::Base::PkgConfig; 1 };

  require Alien::Foo1;

  my $cflags  = Alien::Foo1->cflags;
  my $libs    = Alien::Foo1->libs;
  my $version = Alien::Foo1->version;

  $libs =~ s{^\s+}{};

  is $cflags, '-DFOO=stuff', "cflags: $cflags";
  is $libs,   '-lfoo1', "libs: $libs";
  is $version, '3.99999', "version: $version";
};

subtest 'AB::MB share install' => sub {

  skip_all 'test requires Alien::Base::PkgConfig'
    unless eval { require Alien::Base::PkgConfig; 1 };

  require Alien::Foo2;

  my $cflags  = Alien::Foo2->cflags;
  my $libs    = Alien::Foo2->libs;
  my $version = Alien::Foo2->version;
    
  ok $cflags,  "cflags: $cflags";
  ok $libs,    "libs:   $libs";
  is $version, '3.2.1', "version: $version";

  if($cflags =~ /-I(.*)$/)
  {
    ok -f "$1/foo2.h", "include path: $1";
  }
  else
  {
    fail "include path: ?";
  }
  
  if($libs =~ /-L([^ ]*)/)
  {

t/alien_base.t  view on Meta::CPAN

    fail "lib path: ?";
  }

};

subtest 'Alien::Build system' => sub {

  require Alien::libfoo1;
  
  is( -f File::Spec->catfile(Alien::libfoo1->dist_dir,'_alien/for_libfoo1'), T(), 'dist_dir');
  is( Alien::libfoo1->cflags, '-DFOO=1', 'cflags' );
  is( Alien::libfoo1->cflags_static, '-DFOO=1 -DFOO_STATIC=1', 'cflags_static');
  is( Alien::libfoo1->libs, '-lfoo', 'libs' );
  is( Alien::libfoo1->libs_static, '-lfoo -lbar -lbaz', 'libs_static' );
  is( Alien::libfoo1->version, '1.2.3', 'version');
  
  subtest 'install type' => sub {
    is( Alien::libfoo1->install_type, 'system' );
    is( Alien::libfoo1->install_type('system'), T() );
    is( Alien::libfoo1->install_type('share'), F() );
  };
  

t/alien_base.t  view on Meta::CPAN

  
  is( Alien::libfoo1->runtime_prop->{arbitrary}, 'one', 'runtime_prop' );
};

subtest 'Alien::Build share' => sub {

  require Alien::libfoo2;
  
  is( -f File::Spec->catfile(Alien::libfoo2->dist_dir,'_alien/for_libfoo2'), T(), 'dist_dir');
  
  subtest 'cflags' => sub {
    is(
      [split /\s+/, Alien::libfoo2->cflags],
      array {
        item match qr/^-I.*include/;
        item '-DFOO=1';
        end;
      },
      'cflags',
    );
    
    my($dir) = [split /\s+/, Alien::libfoo2->cflags]->[0] =~ /^-I(.*)$/;
    
    is(
      -f File::Spec->catfile($dir,'foo.h'),
      T(),
      '-I directory points to foo.h location',
    );
  
    is(
      [split /\s+/, Alien::libfoo2->cflags_static],
      array {
        item match qr/^-I.*include/;
        item '-DFOO=1';
        item '-DFOO_STATIC=1';
        end;
      },
      'cflags_static',
    );
    
    ($dir) = [split /\s+/, Alien::libfoo2->cflags_static]->[0] =~ /^-I(.*)$/;
    
    is(
      -f File::Spec->catfile($dir,'foo.h'),
      T(),
      '-I directory points to foo.h location (static)',
    );
  };
  
  subtest 'libs' => sub {
  

t/alien_base.t  view on Meta::CPAN

    },
    'bin_dir',
  );
  
  is( -f File::Spec->catfile(Alien::libfoo2->bin_dir,'foo-config'), T(), 'has a foo-config');
  
  is( Alien::libfoo2->runtime_prop->{arbitrary}, 'two', 'runtime_prop' );

};

subtest 'build flags' => sub {

  my %unix_flags = (
    q{ -L/a/b/c -lz -L/a/b/c } => [ "-L/a/b/c", "-lz", "-L/a/b/c" ],
  );

  my %win_flags = (
    q{ -L/a/b/c -lz -L/a/b/c } => [ "-L/a/b/c", "-lz", "-L/a/b/c" ],
    q{ -LC:/a/b/c -lz -L"C:/a/b c/d" } => [ "-LC:/a/b/c", "-lz", "-LC:/a/b c/d" ],
    q{ -LC:\a\b\c -lz } => [ q{-LC:\a\b\c}, "-lz" ], 
  );

  subtest 'unix' => sub {
    while ( my ($flag, $split) = each %unix_flags ) {
      is( [ Alien::Base->split_flags_unix( $flag ) ], $split );
    }
  };

  subtest 'windows' => sub {
    while ( my ($flag, $split) = each %win_flags ) {
      is( [ Alien::Base->split_flags_windows( $flag ) ], $split );
    }
  };

};

done_testing;

package
  FFI::CheckLib;

t/alien_base__system_installed.t  view on Meta::CPAN


my $skip;
system( "$pkg_config --version" );
if ( $? ) {
  plan skip_all => "Cannot use pkg-config: $?";
}

my @installed = shuffle map { /^(\S+)/ ? $1 : () } `$pkg_config --list-all`;
plan skip_all => "Could not find any library for testing" unless @installed;

my ($lib, $cflags, $libs);

my $i = 1;

while (1) {

  $lib = shift @installed;
  last unless defined $lib;

  chomp( $cflags = `$pkg_config --cflags $lib` );
  chomp( $libs = `$pkg_config --libs $lib` );

  $cflags =~ s/\s*$//;
  $libs   =~ s/\s*$//;

  if ($lib and $cflags and $libs) {
    last;
  } 

  last if $i++ == 3;

  $lib    = undef;
  $cflags = undef;
  $libs   = undef;
}

plan skip_all => "Could not find a suitable library for testing" unless defined $lib;

note "lib    = $lib\n";
note "cflags = $cflags\n";
note "libs   = $libs\n";

my $builder = Alien::Base::ModuleBuild->new( 
  module_name => 'MyTest', 
  dist_version => 0.01,
  alien_name => $lib,
  share_dir => 't',
); 

$builder->depends_on('build');

t/alien_base__system_installed.t  view on Meta::CPAN

  local $CWD;
  push @CWD, qw/blib lib/;

  use lib '.';
  require './MyTest.pm';
  my $alien = MyTest->new;

  isa_ok($alien, 'MyTest');
  isa_ok($alien, 'Alien::Base');

  note "alien->cflags = ", $alien->cflags;
  note "alien->libs   = ", $alien->libs;

  is($alien->cflags, $cflags, "get cflags from system-installed library");
  is($alien->libs  , $libs  , "get libs from system-installed library"  );
}

$builder->depends_on('realclean');

done_testing;



( run in 4.031 seconds using v1.01-cache-2.11-cpan-94b05bcf43c )