Affix

 view release on metacpan or  search on metacpan

builder/Affix/Builder.pm  view on Meta::CPAN

        $meta->save(@$_) for ['MYMETA.json'];
    }

    sub find ( $pattern, $base ) {
        $base = path($base) unless builtin::blessed $base;
        my $blah = $base->visit(
            sub ( $path, $state ) {
                $state->{$path} = $path if $path =~ $pattern;
            },
            { recurse => 1 }
        );
        values %$blah;
    }

    # infix builder
    method step_clone_infix() {
        return if cwd->absolute->child('infix')->exists;
        my $clone_dir = cwd->absolute->child('infix');
        die 'Failed to clone infix' if system( 'git', 'clone', '--depth', '1', 'https://github.com/sanko/infix.git', $clone_dir->stringify );
    }

    method step_infix () {
        $self->step_clone_infix();
        my $cwd       = cwd->absolute;
        my $infix_dir = $cwd->child('infix');

        # Use architecture-specific directory to avoid collision on shared filesystems (WSL vs Windows)
        my $build_lib = $infix_dir->child( 'build_lib', $Config{archname} );

        # If library already exists and is newer than source, we are good.
        my $is_msvc  = ( $Config{cc} =~ /cl(\.exe)?$/i );
        my $lib_ext  = $is_msvc ? '.lib' : '.a';
        my $lib_pre  = $is_msvc ? ''     : 'lib';
        my $lib_file = $build_lib->child( $lib_pre . 'infix' . $lib_ext );
        my $src_file = $infix_dir->child( 'src', 'infix.c' );
        if ( -e $lib_file && !$force ) {

            # Check timestamps to ensure we rebuild if source changed
            if ( $src_file->stat->mtime <= $lib_file->stat->mtime ) {
                return 0;
            }
        }
        #
        warn "Building infix static library for $Config{archname}..." if $verbose;
        $build_lib->mkpath unless -d $build_lib;
        my @include_dirs = ( $infix_dir->child('include'), $infix_dir->child('src') );

        # Detect Compiler settings using Perl's Config as base
        my $cc_cmd  = $Config{cc} || 'cc';
        my $cc_type = 'gcc';                 # Default flavor
        if    ( $cc_cmd =~ /cl(\.exe)?$/i ) { $cc_type = 'msvc'; }
        elsif ( $cc_cmd =~ /clang/i )       { $cc_type = 'clang'; }
        elsif ( $cc_cmd =~ /gcc/i )         { $cc_type = 'gcc'; }
        elsif ( $cc_cmd =~ /egcc/i )        { $cc_type = 'gcc'; }

        # Setup Flags
        my ( $ar_cmd, @cflags, @arflags, $out_flag_cc, $out_flag_ar );
        my @includes = map { ( $cc_type eq 'msvc' ? '/I' : '-I' ) . $_ } @include_dirs;
        if ( $cc_type eq 'msvc' ) {
            $ar_cmd      = 'lib';
            @cflags      = ( '/nologo', '/c', '/std:c11', '/W3', '/GS', '/MD', '/O2', @includes );
            @cflags      = ( @cflags, '/DINFIX_DEBUG_ENABLED=1' ) if $verbose;
            @arflags     = ('/nologo');
            $out_flag_cc = '/Fo';
            $out_flag_ar = '/OUT:';
        }
        else {
            # GCC / Clang
            $ar_cmd      = 'ar';
            @cflags      = ( '-std=c11', '-Wall', '-Wextra', '-O2', '-fPIC', @includes );
            @cflags      = ( @cflags, '-DINFIX_DEBUG_ENABLED=1' ) if $verbose;
            @arflags     = ('rcs');
            $out_flag_cc = '-o';
            $out_flag_ar = '';

            # Pass pthread to compilation of static lib too (safe practice)
            push @cflags, '-pthread' unless $^O eq 'MSWin32';
        }

        # Compile infix.c -> infix.o
        my $obj_ext  = $cc_type eq 'msvc' ? '.obj' : '.o';
        my $obj_file = $build_lib->child( 'infix' . $obj_ext );
        my @compile_cmd;
        if ( $cc_type eq 'msvc' ) {
            @compile_cmd = ( $cc_cmd, @cflags, $out_flag_cc . $obj_file, $src_file );
        }
        else {
            @compile_cmd = ( $cc_cmd, @cflags, '-c', $src_file, $out_flag_cc, $obj_file );
        }
        warn "  Compiling: @compile_cmd\n" if $verbose;
        if ( system(@compile_cmd) != 0 ) {
            die "Failed to compile infix.c";
        }

        # Archive infix.o -> libinfix.a
        my @archive_cmd;
        if ( $cc_type eq 'msvc' ) {
            @archive_cmd = ( $ar_cmd, @arflags, $out_flag_ar . $lib_file, $obj_file );
        }
        else {
            @archive_cmd = ( $ar_cmd, @arflags, $lib_file, $obj_file );
        }
        warn "  Archiving: @archive_cmd\n" if $verbose;
        if ( system(@archive_cmd) != 0 ) {
            die "Failed to create infix static library";
        }
        warn "Infix library built: $lib_file\n" if $verbose;
        return 0;
    }

    # Detects if linking against librt is required (common on Linux/BSD/Solaris for shm_open)
    method check_for_lrt() {
        return ''                                if $^O eq 'MSWin32';
        warn "Checking if -lrt is required...\n" if $verbose;
        my $cc        = $Config{cc} || 'cc';
        my $test_code = <<'END_C';
#include <sys/mman.h>
#include <fcntl.h>
int main(void) { shm_open("/test", O_RDONLY, 0); return 0; }
END_C
        my ( $fh, $src ) = tempfile( SUFFIX => '.c', UNLINK => 1 );
        print $fh $test_code;
        close $fh;

builder/Affix/Builder.pm  view on Meta::CPAN


            #~ warn "Processing source: $source\n";
            my $cxx       = $source =~ /cx+$/;
            my $file_base = $source->basename(qr[.c$]);
            my $tempdir   = path('lib');
            $tempdir->mkdir( { verbose => $verbose, mode => oct '755' } );
            my $version = $meta->version;
            my $obj     = $builder->object_file($source);

            #~ warn "Checking obj: $obj\n";
            # Check mtimes of all .c and .h files under lib/ (includes Affix.c, marshal.c, Affix.h)
            my $newest_dep = $source->stat->mtime;
            my $iter       = path('lib')->iterator;
            while ( my $entry = $iter->() ) {
                next unless $entry->is_file;
                next unless $entry =~ /\.[ch]$/;
                my $dep_mtime = $entry->stat->mtime;
                $newest_dep = $dep_mtime if $dep_mtime > $newest_dep;
            }
            my $should_compile
                = ( $force ||
                    ( !-f $obj ) ||
                    ( $newest_dep >= path($obj)->stat->mtime ) ||
                    ( path(__FILE__)->stat->mtime > path($obj)->stat->mtime ) );
            if ($should_compile) {
                my $reason
                    = !-f $obj                                            ? 'object file missing' :
                    $newest_dep >= path($obj)->stat->mtime                ? 'source newer than object' :
                    path(__FILE__)->stat->mtime > path($obj)->stat->mtime ? 'builder changed' :
                    'forced';
                warn "Compiling $source ($reason)\n";
                $recompiled = 1;
            }
            push @dirs, $source->dirname();
            $has_cxx = 1 if $cxx;
            push @objs,
                $should_compile ?
                $builder->compile(
                quiet        => 0,
                'C++'        => $cxx,
                source       => $source->stringify,
                defines      => { VERSION => qq/"$version"/, XS_VERSION => qq/"$version"/ },
                include_dirs => [
                    cwd->stringify,                                             cwd->child('infix')->realpath->stringify,
                    cwd->child('infix')->child('include')->realpath->stringify, cwd->child('infix')->child('src')->realpath->stringify,
                    $source->dirname,                                           $pre->child( $meta->name, 'include' )->stringify
                ],
                extra_compiler_flags =>
                    ( '-fPIC -std=' . ( $cxx ? $cppver : $cver ) . ' ' . $cflags . ( $debug ? ' -ggdb3 -g -Wall -Wextra -pedantic' : '' ) )
                ) :
                $obj;
        }

        # Point to the Architecture-specific build lib
        my $infix_build_lib = cwd->absolute->child('infix')->child( 'build_lib', $Config{archname} )->stringify;

        # Check for -lrt requirement
        my $lrt_flag = $self->check_for_lrt();
        my $data     = {

            # Removed incorrect -lstdc++ logic. Added -lm for math.
            # -pthread is already in $ldflags via ADJUST
            extra_linker_flags =>
                [ split( ' ', $ldflags ), "-L$infix_build_lib", '-linfix', ( $lrt_flag ? ( split( ' ', $lrt_flag ) ) : () ), '-lm' ],
            objects     => [@objs],
            lib_file    => $lib_file,
            module_name => join '::',
            @parts
        };
        warn "Linking $lib_file\n" if $recompiled;
        return $builder->link(%$data);
    }
    };
1;



( run in 1.942 second using v1.01-cache-2.11-cpan-3fabe0161c3 )