Clownfish-CFC
view release on metacpan or search on metacpan
lib/Clownfish/CFC/Perl/Build.pm view on Meta::CPAN
my $self_or_class = shift;
return @BASE_PATH;
}
sub cf_linker_flags {
my $self = shift;
my $dlext = $Config{dlext};
# Only needed on Windows
return () if $dlext !~ /dll$/i;
# Link against import library on MSVC
my $ext = $Config{cc} =~ /^cl\b/ ? 'lib' : $dlext;
my @linker_flags;
for my $module_name (@_) {
# Find library to link against
my @module_parts = split( '::', $module_name );
my $class_name = $module_parts[-1];
my $lib_file;
my $found;
for my $dir ( catdir( $self->blib, 'arch' ), @INC ) {
$lib_file = catfile(
$dir, 'auto', @module_parts, "$class_name.$ext",
);
if ( -f $lib_file ) {
$found = 1;
last;
}
}
die("No Clownfish library file found for module $module_name")
if !$found;
push( @linker_flags, $lib_file );
}
return @linker_flags;
}
sub _cfh_filepaths {
my $self = shift;
my @paths;
my $source_dirs = $self->clownfish_params('source');
for my $source_dir (@$source_dirs) {
next unless -e $source_dir;
push @paths, @{ $self->rscan_dir( $source_dir, qr/\.cf[hp]$/ ) };
}
return \@paths;
}
sub cf_copy_include_file {
my ($self, @path) = @_;
my $dest_dir = catdir( $self->blib, 'arch', 'Clownfish', '_include' );
for my $include_dir ($self->cf_c_include_dirs) {
my $file = catfile ( $include_dir, @path );
if ( -e $file ) {
$self->copy_if_modified(
from => $file,
to => catfile( $dest_dir, @path ),
);
return;
}
}
die( "Clownfish include file " . catfile(@path) . " not found" );
}
my %hierarchy_cache;
sub _compile_clownfish {
my $self = shift;
require Clownfish::CFC::Model::Hierarchy;
require Clownfish::CFC::Binding::Perl;
require Clownfish::CFC::Binding::Perl::Class;
return @hierarchy_cache{ qw( hierarchy binding ) }
if %hierarchy_cache;
# Compile Clownfish.
my $hierarchy = Clownfish::CFC::Model::Hierarchy->new(
dest => $AUTOGEN_DIR,
);
my $source_dirs = $self->clownfish_params('source');
for my $source_dir (@$source_dirs) {
$hierarchy->add_source_dir($source_dir);
}
for my $include_dir ($self->cf_include_dirs) {
$hierarchy->add_include_dir($include_dir);
}
$hierarchy->build;
$hierarchy->read_host_data_json;
# Process all Binding classes in buildlib.
local @INC = ( @INC, '.' );
my $pm_filepaths = $self->rscan_dir( $BUILDLIB_DIR, qr/\.pm$/ );
for my $pm_filepath (@$pm_filepaths) {
next unless $pm_filepath =~ /Binding/;
require $pm_filepath;
my $package_name = $pm_filepath;
$package_name =~ s/buildlib\/(.*)\.pm$/$1/;
$package_name =~ s/\//::/g;
$package_name->bind_all($hierarchy);
}
my $binding = Clownfish::CFC::Binding::Perl->new(
hierarchy => $hierarchy,
lib_dir => $LIB_DIR,
header => $self->clownfish_params('autogen_header'),
footer => '',
);
@hierarchy_cache{ qw( hierarchy binding ) } = ( $hierarchy, $binding );
return ( $hierarchy, $binding );
}
# Deprecated.
lib/Clownfish/CFC/Perl/Build.pm view on Meta::CPAN
if ( !$self->up_to_date( $perl_binding_c_file, $perl_binding_o_file ) ) {
# Don't use Clownfish compiler flags for XS
$cbuilder->compile(
source => $perl_binding_c_file,
extra_compiler_flags => $self->extra_compiler_flags,
include_dirs => [ $self->cf_c_include_dirs ],
object_file => $perl_binding_o_file,
# 'defines' is an undocumented parameter to compile(), so we
# should officially roll our own variant and generate compiler
# flags. However, that involves writing a bunch of
# platform-dependent code, so we'll just take the chance that this
# will break.
defines => {
VERSION => qq|"$version"|,
XS_VERSION => qq|"$version"|,
},
);
}
# Create .bs bootstrap file, needed by Dynaloader.
my $bs_file = catfile( $archdir, "$class_name.bs" );
$self->add_to_cleanup($bs_file);
if ( !$self->up_to_date( $perl_binding_o_file, $bs_file ) ) {
require ExtUtils::Mkbootstrap;
ExtUtils::Mkbootstrap::Mkbootstrap($bs_file);
if ( !-f $bs_file ) {
# Create file in case Mkbootstrap didn't do anything.
open( my $fh, '>', $bs_file )
or confess "Can't open $bs_file: $!";
}
utime( (time) x 2, $bs_file ); # touch
}
# Clean up after CBuilder under MSVC.
$self->add_to_cleanup('compilet*');
$self->add_to_cleanup('*.ccs');
$self->add_to_cleanup( catfile( $libdir, "$class_name.ccs" ) );
$self->add_to_cleanup( catfile( $libdir, "$class_name.def" ) );
$self->add_to_cleanup( catfile( $libdir, "${class_name}_def.old" ) );
$self->add_to_cleanup( catfile( $libdir, "$class_name.exp" ) );
$self->add_to_cleanup( catfile( $libdir, "$class_name.lib" ) );
$self->add_to_cleanup( catfile( $libdir, "$class_name.lds" ) );
$self->add_to_cleanup( catfile( $libdir, "$class_name.base" ) );
# .o => .(a|bundle)
my $lib_file = catfile( $archdir, "$class_name.$Config{dlext}" );
if ( !$self->up_to_date( [ @objects, $AUTOGEN_DIR ], $lib_file ) ) {
my $linker_flags = $self->extra_linker_flags;
my @xs_prereqs = $self->_cf_find_xs_prereqs($module);
push @$linker_flags, $self->cf_linker_flags(@xs_prereqs);
$cbuilder->link(
module_name => $module_name,
objects => \@objects,
lib_file => $lib_file,
extra_linker_flags => $linker_flags,
);
# Install .lib file on Windows
# TODO: Install .dll.a when building with GCC on Windows?
my $implib_file = catfile( $libdir, "$class_name.lib" );
if ( -e $implib_file ) {
$self->copy_if_modified(
from => $implib_file,
to => catfile( $archdir, "$class_name.lib" ),
);
}
}
}
sub _cf_find_xs_prereqs {
my ( $self, $module ) = @_;
my $modules = $self->clownfish_params('modules');
my @xs_prereqs;
for my $parcel_name ( @{ $module->{parcels} } ) {
my $parcel = Clownfish::CFC::Model::Parcel->acquire($parcel_name);
for my $prereq_parcel ( @{ $parcel->prereq_parcels } ) {
my $prereq_module;
if ($prereq_parcel->included) {
$prereq_module = $prereq_parcel->get_xs_module;
}
else {
my $prereq_parcel_name = $prereq_parcel->get_name;
for my $candidate (@$modules) {
my @matches = grep {
$_ eq $prereq_parcel_name
} @{ $candidate->{parcels} };
if (@matches) {
$prereq_module = $candidate->{name};
last;
}
}
}
die("No XS module found for parcel $parcel_name")
if !defined($prereq_module);
push @xs_prereqs, $prereq_module
if $prereq_module ne $module->{name}
&& !grep { $_ eq $prereq_module } @xs_prereqs;
}
}
return @xs_prereqs;
}
sub ACTION_code {
my $self = shift;
$self->depends_on(qw(
clownfish
compile_custom_xs
));
$self->SUPER::ACTION_code;
}
sub ACTION_clean {
( run in 1.230 second using v1.01-cache-2.11-cpan-e93a5daba3e )