Alien-Build

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN


    Load a checkpointed Alien::Build instance. You will need the original
    alienfile and the build root (usually _alien), and a build that had
    been properly checkpointed using the checkpoint method below.

PROPERTIES

    There are three main properties for Alien::Build. There are a number of
    properties documented here with a specific usage. Note that these
    properties may need to be serialized into something primitive like JSON
    that does not support: regular expressions, code references of blessed
    objects.

    If you are writing a plugin (Alien::Build::Plugin) you should use a
    prefix like "plugin_name" (where name is the name of your plugin) so
    that it does not interfere with other plugin or future versions of
    Alien::Build. For example, if you were writing
    Alien::Build::Plugin::Fetch::NewProtocol, please use the prefix
    plugin_fetch_newprotocol:

     sub init

corpus/lib/Alien/Foo.pm  view on Meta::CPAN

package Alien::Foo;

sub new { bless {}, __PACKAGE__ }
sub cflags       {}
sub libs         {}
sub dynamic_libs {}
sub bin_dir      { '/foo/bar/baz' }

1;

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

       {
         'alien_version' => undef,
         '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}',

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

package Alien::Base;

use strict;
use warnings;
use 5.008004;
use Carp;
use Path::Tiny ();
use Scalar::Util qw/blessed/;
use Capture::Tiny 0.17 qw/capture_stdout/;
use Text::ParseWords qw/shellwords/;
use Alien::Util;

# ABSTRACT: Base classes for Alien:: modules
our $VERSION = '2.84'; # VERSION


sub import {
  my $class = shift;

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

      }
      last;
    }
  }
  Carp::croak("unable to find dist share directory for $dist_name");
}

sub dist_dir {
  my $class = shift;

  my $dist = blessed $class || $class;
  $dist =~ s/::/-/g;

  my $dist_dir =
    $class->config('finished_installing')
      ? _dist_dir $dist
      : $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)$/;

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

    my $pkg = Alien::Base::PkgConfig->new($_);
    $all{$pkg->{package}} = $pkg;
  };
  File::Find::find( $wanted, $self->dist_dir );

  croak "No Alien::Base::PkgConfig objects are stored!"
    unless keys %all;

  # Run through all pkgconfig objects and ensure that their modules are loaded:
  for my $pkg_obj (values %all) {
    my $perl_module_name = blessed $pkg_obj;
    my $pm = "$perl_module_name.pm";
    $pm =~ s/::/\//g;
    eval { require $pm };
  }

  return @all{@_} if @_;

  my $manual = delete $all{_manual};

  if (keys %all) {
    return values %all;
  } else {
    return $manual;
  }
}


# helper method to call Alien::MyLib::ConfigData->config(@_)
sub config {
  my $class = shift;
  $class = blessed $class || $class;

  if(my $ab_config = $class->runtime_prop)
  {
    my $key = shift;
    return $ab_config->{legacy}->{$key};
  }

  my $config = $class . '::ConfigData';
  my $pm = "$class/ConfigData.pm";
  $pm =~ s{::}{/}g;

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


# ABSTRACT: Private legacy pkg-config class for Alien::Base
our $VERSION = '2.84'; # VERSION


sub new {
  my $class   = shift;

  # allow creation of an object from a full spec.
  if (ref $_[0] eq 'HASH') {
    return bless $_[0], $class;
  }

  my ($path) = @_;
  croak "Must specify a file" unless defined $path;

  $path = path( $path )->absolute;

  my($name) = $path->basename =~ /^(.*)\.pc$/;

  my $self = {
    package  => $name,
    vars     => { pcfiledir => $path->parent->stringify },
    keywords => {},
  };

  bless $self, $class;

  $self->read($path);

  return $self;
}

sub read {
  my $self = shift;
  my ($path) = @_;

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

  push @mb, extra_linker_flags   => _join(@ldflags_l);

  if(@ldflags)
  {
    push @mb, config => {
      lddlflags => _join(@ldflags) . " $Config{lddlflags}",
      ldflags   => _join(@ldflags) . " $Config{ldflags}",
    },
  }

  bless {
    cflags_I       => \@cflags_I,
    cflags_other   => \@cflags_other,
    ldflags_L      => \@ldflags_L,
    ldflags_l      => \@ldflags_l,
    ldflags_other  => \@ldflags_other,
    mm             => \@mm,
    mb             => \@mb,
    _export        => $export,
    _writemakefile => $writemakefile,
    requires       => \%requires,

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

# ABSTRACT: Build external dependencies for use in CPAN
our $VERSION = '2.84'; # VERSION


sub _path { goto \&Path::Tiny::path }


sub new
{
  my($class, %args) = @_;
  my $self = bless {
    install_prop => {
      root  => _path($args{root} || "_alien")->absolute->stringify,
      patch => (defined $args{patch}) ? _path($args{patch})->absolute->stringify : undef,
    },
    runtime_prop => {
      alien_build_version => $Alien::Build::VERSION || 'dev',
    },
    plugin_instance_prop => {},
    bin_dir => [],
    pkg_config_path => [],

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

  }
}

package Alien::Build::Meta;

our @CARP_NOT = qw( alienfile );

sub new
{
  my($class, %args) = @_;
  my $self = bless {
    phase => 'any',
    build_suffix => '',
    require => {
      any    => {},
      share  => {},
      system => {},
    },
    around => {},
    prop => {},
    %args,

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

# rename, if a good name can be thought of.

use overload '""' => sub { shift->as_string }, bool => sub { 1 }, fallback => 1;
use File::Temp qw( tempdir );

sub new
{
  my($class, $build, $name) = @_;
  my $root = $build->install_prop->{root};
  Path::Tiny->new($root)->mkpath unless -d $root;
  bless {
    dir => Path::Tiny->new(tempdir( "${name}_XXXX", DIR => $root)),
  }, $class;
}

sub as_string
{
  shift->{dir}->stringify;
}

sub DESTROY

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


Load a checkpointed L<Alien::Build> instance.  You will need the original
L<alienfile> and the build root (usually C<_alien>), and a build that
had been properly checkpointed using the C<checkpoint> method below.

=head1 PROPERTIES

There are three main properties for L<Alien::Build>.  There are a number
of properties documented here with a specific usage.  Note that these
properties may need to be serialized into something primitive like JSON
that does not support: regular expressions, code references of blessed
objects.

If you are writing a plugin (L<Alien::Build::Plugin>) you should use a
prefix like "plugin_I<name>" (where I<name> is the name of your plugin)
so that it does not interfere with other plugin or future versions of
L<Alien::Build>.  For example, if you were writing
C<Alien::Build::Plugin::Fetch::NewProtocol>, please use the prefix
C<plugin_fetch_newprotocol>:

 sub init

lib/Alien/Build/CommandSequence.pm  view on Meta::CPAN

use Text::ParseWords qw( shellwords );
use Capture::Tiny qw( capture );

# ABSTRACT: Alien::Build command sequence
our $VERSION = '2.84'; # VERSION


sub new
{
  my($class, @commands) = @_;
  my $self = bless {
    commands => \@commands,
  }, $class;
  $self;
}


sub apply_requirements
{
  my($self, $meta, $phase) = @_;
  my $intr = $meta->interpolator;

lib/Alien/Build/Interpolate.pm  view on Meta::CPAN

use warnings;
use 5.008004;

# ABSTRACT: Advanced interpolation engine for Alien builds
our $VERSION = '2.84'; # VERSION


sub new
{
  my($class) = @_;
  my $self = bless {
    helper  => {},
    classes => {},
  }, $class;
  $self;
}


sub add_helper
{
  my $self = shift;

lib/Alien/Build/Interpolate.pm  view on Meta::CPAN

  my($self) = @_;

  require Storable;

  my %helper;
  foreach my $name (keys %{ $self->{helper} })
  {
    $helper{$name} = $self->{helper}->{$name}->clone;
  }

  my $new = bless {
    helper => \%helper,
    classes => Storable::dclone($self->{classes}),
  }, ref $self;
}

package Alien::Build::Helper;

sub new
{
  my($class, $name, $code, $require) = @_;
  bless {
    name    => $name,
    code    => $code,
    require => $require,
  }, $class;
}

sub name { shift->{name} }

sub code
{

lib/Alien/Build/Log.pm  view on Meta::CPAN

our $VERSION = '2.84'; # VERSION


my $log_class;
my $self;

sub new
{
  my($class) = @_;
  Carp::croak("Cannot instantiate base class") if $class eq 'Alien::Build::Log';
  return bless {}, $class;
}


sub default
{
  $self || do {
    my $class = $log_class || $ENV{ALIEN_BUILD_LOG} || 'Alien::Build::Log::Default';
    unless(eval { $class->can('new') })
    {
      my $pm = "$class.pm";

lib/Alien/Build/MM.pm  view on Meta::CPAN

use Carp ();

# ABSTRACT: Alien::Build installer code for ExtUtils::MakeMaker
our $VERSION = '2.84'; # VERSION


sub new
{
  my($class, %prop) = @_;

  my $self = bless {}, $class;

  my %meta = map { $_ => $prop{$_} } grep /^my_/, keys %prop;

  my $build = $self->{build} =
    Alien::Build->load('alienfile',
      root     => "_alien",
      (-d 'patch' ? (patch => 'patch') : ()),
      meta_prop => \%meta,
    )
  ;

lib/Alien/Build/Plugin.pm  view on Meta::CPAN

# ABSTRACT: Plugin base class for Alien::Build
our $VERSION = '2.84'; # VERSION


sub new
{
  my $class = shift;
  my %args = @_ == 1 ? ($class->meta->default => $_[0]) : @_;

  my $instance_id = Digest::SHA::sha1_hex(Data::Dumper->new([$class, \%args])->Sortkeys(1)->Dump);
  my $self = bless { instance_id => $instance_id }, $class;

  my $prop = $self->meta->prop;
  foreach my $name (keys %$prop)
  {
    $self->{$name} = defined $args{$name}
      ? delete $args{$name}
      : ref($prop->{$name}) eq 'CODE'
        ? $prop->{$name}->()
        : $prop->{$name};
  }

lib/Alien/Build/Plugin.pm  view on Meta::CPAN

  my($class) = @_;
  $class = ref $class if ref $class;
  $meta{$class} ||= Alien::Build::PluginMeta->new( class => $class );
}

package Alien::Build::PluginMeta;

sub new
{
  my($class, %args) = @_;
  my $self = bless {
    prop => {},
    %args,
  }, $class;
}

sub default
{
  my($self) = @_;
  $self->{default} || do {
    Carp::croak "No default for @{[ $self->{class} ]}";

lib/Alien/Build/Version/Basic.pm  view on Meta::CPAN

# ABSTRACT: Very basic version object for Alien::Build
our $VERSION = '2.84'; # VERSION


sub new
{
  my($class, $value) = @_;
  $value =~ s/\.$//;  # trim trailing dot
  Carp::croak("invalud version: $value")
    unless $value =~ /^[0-9]+(\.[0-9]+)*$/;
  bless \$value, $class;
}


sub version ($)
{
  my($value) = @_;
  __PACKAGE__->new($value);
}


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

  $ok;
}


sub synthetic
{
  my($opt) = @_;
  $opt ||= {};
  my %alien = %$opt;
  require Test::Alien::Synthetic;
  bless \%alien, 'Test::Alien::Synthetic',
}


sub run_ok
{
  my($command, $message) = @_;

  my(@command) = ref $command ? @$command : (do {
    my $command = $command; # make a copy

    # 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.
    $command =~ s/\\/\\\\/g if $^O eq 'MSWin32';
    shellwords $command;
  });
  $message ||= ref $command ? "run @command" : "run $command";

  require Test::Alien::Run;
  my $run = bless {
    out    => '',
    err    => '',
    exit   => 0,
    sig    => 0,
    cmd    => [@command],
  }, 'Test::Alien::Run';

  my $ctx = context();
  my $exe = which $command[0];
  if(defined $exe)

t/alien_build.t  view on Meta::CPAN

        etc;
      },
    );

    is( $build->hook_prop, undef );

    is(
      \@foo1,
      array {
        item object {
          prop blessed => ref $build;
          call sub { shift->isa('Alien::Build') } => T();
        };
        item 'roger';
        item 'ramjet';
      }
    );
  };

  my $exception_count = 0;

t/alien_build_commandsequence.t  view on Meta::CPAN

  note capture_merged {
    Alien::Build::CommandSequence->new(
      [ 'stuff', '%{foo}', sub { @cap = @_ } ],
    )->execute($build);
  };

  is(
    \@cap,
    array {
      item object {
        prop blessed => ref $build;
        call sub { shift->isa('Alien::Build') } => T();
      };
      item hash {
        field command => ['stuff','myfoo'];
        field err  => match qr/stuff error/;
        field out  => match qr/stuff output/;
        field exit => 0;
      };
    },
  );

t/alien_build_commandsequence.t  view on Meta::CPAN

  note capture_merged {
    Alien::Build::CommandSequence->new(
      [ 'bogus', '%{foo}', sub { @cap = @_ } ],
    )->execute($build);
  };

  is(
    \@cap,
    array {
      item object {
        prop blessed => ref $build;
        call sub { shift->isa('Alien::Build') } => T();
      };
      item hash {
        field command => ['bogus','myfoo'];
        field err  => match qr/bogus error/;
        field out  => match qr/bogus output/;
        field exit => -1;
      };
    },
  );

t/alien_build_plugin_probe_cbuilder.t  view on Meta::CPAN


  my $mock = mock 'ExtUtils::CBuilder';

  my @args_new;
  my @args_compile;
  my @args_link_executable;

  $mock->add('new' => sub {
    shift;
    @args_new = @_;
    bless {}, 'ExtUtils::CBuilder';
  });

  $mock->add('compile' => sub {
    shift;
    @args_compile = @_;
    'mytest.o';
  });

  $mock->add('link_executable' => sub {
    shift;

t/alien_build_plugin_probe_cbuilder.t  view on Meta::CPAN

    },
  );

};

subtest 'program' => sub {

  my $mock = mock 'ExtUtils::CBuilder';

  $mock->add('new' => sub {
    bless {}, 'ExtUtils::CBuilder';
  });

  my $source;

  $mock->add('compile' => sub {
    my(undef, %args) = @_;
    $source = path($args{source})->slurp;
    'mytest.o';
  });

t/alien_build_plugin_probe_cbuilder.t  view on Meta::CPAN


  is( $build->install_type, 'system', 'is system' );
  is($source, 'int main(int foo1, char *foo2[]) { return 0; }', 'compiled with correct source');
};

subtest 'program' => sub {

  my $mock = mock 'ExtUtils::CBuilder';

  $mock->add('new' => sub {
    bless {}, 'ExtUtils::CBuilder';
  });

  $mock->add('compile' => sub {
    my(undef, %args) = @_;
    'mytest.o';
  });

  $mock->add('link_executable' => sub {
    'mytest';
  });

t/alien_build_plugin_probe_cbuilder.t  view on Meta::CPAN


  is( $build->runtime_prop->{version}, '1.2.3', 'version matches' );
  is( $build->install_prop->{probe_version_prop}, ['1.2.3'], 'set probe hook prop' );
};

subtest 'fail' => sub {

  my $mock = mock 'ExtUtils::CBuilder';

  $mock->add('new' => sub {
    bless {}, 'ExtUtils::CBuilder';
  });

  subtest 'compile' => sub {

    $mock->add('compile' => sub {
      my(undef, %args) = @_;
      die "error building mytest.o from mytest.c";
    });

    my $build = alienfile_ok q{

t/alien_build_plugin_probe_cbuilder.t  view on Meta::CPAN

  };

};


subtest 'atleast_version_pass' => sub {

  my $mock = mock 'ExtUtils::CBuilder';

  $mock->add('new' => sub {
    bless {}, 'ExtUtils::CBuilder';
  });

  $mock->add('compile' => sub {
    my(undef, %args) = @_;
    'mytest.o';
  });

  $mock->add('link_executable' => sub {
    'mytest';
  });

t/alien_build_plugin_probe_cbuilder.t  view on Meta::CPAN


  is( $build->runtime_prop->{version}, '1.2.3', 'version matches' );
  is( $build->install_prop->{probe_version_prop}, ['1.2.3'], 'set probe hook prop' );
};

subtest 'atleast_version_fail' => sub {

  my $mock = mock 'ExtUtils::CBuilder';

  $mock->add('new' => sub {
    bless {}, 'ExtUtils::CBuilder';
  });

  $mock->add('compile' => sub {
    my(undef, %args) = @_;
    'mytest.o';
  });

  $mock->add('link_executable' => sub {
    'mytest';
  });

t/lib/MyTest/System.pm  view on Meta::CPAN

    else
    {
      return $old->(@_);
    }
  };
}

sub new
{
  my($class, %cmds) = @_;
  my $self = bless { %cmds }, $class;
  push @stack, $self;
  weaken $stack[-1];
  $self;
}

sub add
{
  my($self, $command, $code) = @_;
  $self->{$command} = $code;
}

t/test_alien_synthetic.t  view on Meta::CPAN

use 5.008004;
use Test2::V0 -no_srand => 1;
use Test::Alien;
use File::Temp qw( tempdir );
use Path::Tiny qw( path );

is(
  synthetic(),
  object {
    prop blessed => 'Test::Alien::Synthetic';
    prop reftype => 'HASH';
    call cflags  => '';
    call libs    => '';
    call sub { [shift->dynamic_libs] }  => [];
    call sub { [shift->bin_dir] }       => [];
  },
  'empty synthetic alien',
);

is(
  synthetic({ cflags => '-DFOO=1 -I/foo/bar/baz'}),
  object {
    prop blessed       => 'Test::Alien::Synthetic';
    call cflags        => '-DFOO=1 -I/foo/bar/baz';
    call cflags_static => '-DFOO=1 -I/foo/bar/baz';
  },
  'cflags',
);

is(
  synthetic({ libs => '-L/foo/bar/baz -lfoo'}),
  object {
    prop blessed     => 'Test::Alien::Synthetic';
    call libs        => '-L/foo/bar/baz -lfoo';
    call libs_static => '-L/foo/bar/baz -lfoo';
  },
  'libs',
);

is(
  synthetic({ dynamic_libs => [qw( foo bar baz )] }),
  object {
    prop blessed => 'Test::Alien::Synthetic';
    call sub { [shift->dynamic_libs] } => [qw( foo bar baz )];
  },
  'dynamic_libs',
);

my $dir = tempdir( CLEANUP => 1 );

is(
  synthetic({ bin_dir => $dir }),
  object {
    prop blessed => 'Test::Alien::Synthetic';
    call bin_dir => $dir;
  },
  'bin_dir (exists)',
);

is(
  synthetic({ bin_dir => path($dir)->child('foo')->stringify }),
  object {
    prop blessed => 'Test::Alien::Synthetic';
    call sub { [shift->bin_dir] } => [];
  },
  'bin_dir (does not exist)',
);

is(
  synthetic({ cflags => '-DCFLAGS=1', cflags_static => '-DCFLAGS_STATIC=1', libs => '-L/lib -lfoo', libs_static => '-L/lib -lfoo -lbar -lbaz' }),
  object {
    prop blessed       => 'Test::Alien::Synthetic';
    call cflags        => '-DCFLAGS=1';
    call cflags_static => '-DCFLAGS_STATIC=1';
    call libs          => '-L/lib -lfoo';
    call libs_static   => '-L/lib -lfoo -lbar -lbaz';
  },
  'static flags',
);

done_testing;



( run in 0.801 second using v1.01-cache-2.11-cpan-de7293f3b23 )