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 )