Alien-Build

 view release on metacpan or  search on metacpan

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

sub init
{
  my($self, $meta) = @_;

  $meta->add_requires('configure' => 'ExtUtils::CBuilder' => 0 );

  if(@{ $self->aliens })
  {
    die "You can't specify both 'aliens' and either 'cflags' or 'libs' for the Probe::CBuilder plugin" if $self->cflags || $self->libs;

    $meta->add_requires('configure' => $_ => 0 ) for @{ $self->aliens };
    $meta->add_requires('Alien::Build::Plugin::Probe::CBuilder' => '0.53');

    my $cflags = '';
    my $libs   = '';
    foreach my $alien (@{ $self->aliens })
    {
      my $pm = "$alien.pm";
      $pm =~ s/::/\//g;
      require $pm;
      $cflags .= $alien->cflags . ' ';
      $libs   .= $alien->libs   . ' ';
    }
    $self->cflags($cflags);
    $self->libs($libs);
  }

  my @cpp;

  if($self->lang ne 'C')
  {
    $meta->add_requires('Alien::Build::Plugin::Probe::CBuilder' => '0.53');
    @cpp = ('C++' => 1) if $self->lang eq 'C++';
  }

  $meta->register_hook(
    probe => sub {
      my($build) = @_;

      $build->hook_prop->{probe_class} = __PACKAGE__;
      $build->hook_prop->{probe_instance_id} = $self->instance_id;

      local $CWD = File::Temp::tempdir( CLEANUP => 1, DIR => $CWD );

      open my $fh, '>', 'mytest.c';
      print $fh $self->program;
      close $fh;

      $build->log("trying: cflags=@{[ $self->cflags ]} libs=@{[ $self->libs ]}");

      my $cb = ExtUtils::CBuilder->new(%{ $self->options });

      my($out1, $obj) = capture_merged { eval {
        $cb->compile(
          source               => 'mytest.c',
          extra_compiler_flags => $self->cflags,
          @cpp,
        );
      } };

      if(my $error = $@)
      {
        $build->log("compile failed: $error");
        $build->log("compile failed: $out1");
        die $error;
      }

      my($out2, $exe) = capture_merged { eval {
        $cb->link_executable(
          objects              => [$obj],
          extra_linker_flags   => $self->libs,
        );
      } };

      if(my $error = $@)
      {
        $build->log("link failed: $error");
        $build->log("link failed: $out2");
        die $error;
      }

      my($out, $err, $ret) = capture { system($^O eq 'MSWin32' ? $exe : "./$exe") };
      die "execute failed" if $ret;

      my $cflags = $self->cflags;
      my $libs   = $self->libs;

      $cflags =~ s{\s*$}{ };
      $libs =~ s{\s*$}{ };

      $build->install_prop->{plugin_probe_cbuilder_gather}->{$self->instance_id} = {
        cflags  => $cflags,
        libs    => $libs,
      };

      if(defined $self->version)
      {
        my($version) = $out =~ $self->version;
        if (defined $self->atleast_version)
        {
          if(version_cmp ($version, $self->atleast_version) < 0)
          {
            die "CBuilder probe found version $version, but at least @{[ $self->atleast_version ]} is required.";
          }
        }
        $build->hook_prop->{version} = $version;
        $build->install_prop->{plugin_probe_cbuilder_gather}->{$self->instance_id}->{version} = $version;
      }

      'system';
    }
  );

  $meta->register_hook(
    gather_system => sub {
      my($build) = @_;

      return if $build->hook_prop->{name} eq 'gather_system'
      &&        ($build->install_prop->{system_probe_instance_id} || '') ne $self->instance_id;

      if(my $p = $build->install_prop->{plugin_probe_cbuilder_gather}->{$self->instance_id})
      {
        $build->runtime_prop->{$_} = $p->{$_} for keys %$p;
      }
    },
  );
}

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

Alien::Build::Plugin::Probe::CBuilder - Probe for system libraries by guessing with ExtUtils::CBuilder



( run in 0.410 second using v1.01-cache-2.11-cpan-efa8479b9fe )