Affix

 view release on metacpan or  search on metacpan

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

            my $v    = $self->_can_run('v') // croak "V not found";
            if ( $mode eq 'dynamic' ) {
                $self->_run( $v, '-shared', '-o', "$out", "$file" );
                return $out;
            }
            else {
                my $c_file = $build_dir->child( $self->_base($file) . '.c' );
                $self->_run( $v, '-o', "$c_file", "$file" );
                return $self->_build_c( { path => $c_file }, undef, 'static' );
            }
        }

        #~ swiftc point.swift -emit-module -emit-library
        #~ https://forums.swift.org/t/creating-a-c-accessible-shared-library-in-swift/45329/5
        #~ https://theswiftdev.com/building-static-and-dynamic-swift-libraries-using-the-swift-compiler/#should-i-choose-dynamic-or-static-linking
        method _build_swift ( $src, $out, $mode ) {
            my $file = $src->{path};
            my $sc   = $self->_can_run('swiftc') // croak "Swiftc not found";

            # Swiftc uses -emit-library for both, just differs on output filename usually
            # But for static we usually want -static if available or just .a
            if ( $mode eq 'dynamic' ) {
                $self->_run( $sc, '-emit-library', "$file", '-o', "$out" );
                return $out;
            }
            else {
                my $lib = $build_dir->child( $self->_base($file) . $Config{_a} );

                # Note: Swift static linking is complex on Linux, but -emit-library -static usually works
                $self->_run( $sc, '-emit-library', '-static', '-parse-as-library', "$file", '-o', "$lib" );
                return { file => $lib };
            }
        }

        #~ https://gcc.gnu.org/onlinedocs/gcc-3.4.0/gnat_ug_unx/Creating-an-Ada-Library.html
        method _build_ada ( $src, $out, $mode ) {
            my $file = $src->{path};
            my $gnat = $self->_can_run('gnatmake') // croak "GNAT not found";

            # Ada compilation is usually to Object first
            my $obj = $build_dir->child( $self->_base($file) . $Config{_o} );
            my @cmd = ( $gnat, '-c', '-u', "$file" );
            push @cmd, '-fPIC' unless $os eq 'MSWin32';

            # GNAT often outputs to CWD
            $self->_run(@cmd);
            my $cwd_obj = Path::Tiny::path( $self->_base($file) . $Config{_o} );
            $cwd_obj->move($obj) if $cwd_obj->exists && $cwd_obj->absolute ne $obj->absolute;
            if ( $mode eq 'dynamic' ) {

                # Link the object to shared
                # We use the generic linker logic for this single file
                my $linker = $Config{cc} // 'cc';
                $self->_run( $linker, '-shared', '-o', "$out", "$obj" );
                return $out;
            }
            return { file => $obj, libs => ['gnat'] };
        }

        #~ https://github.com/bennoleslie/haskell-shared-example
        #~ https://www.hobson.space/posts/haskell-foreign-library/
        method _build_haskell ( $src, $out, $mode ) {
            my $file = $src->{path};
            my $ghc  = $self->_can_run('ghc') // croak "GHC not found";
            if ( $mode eq 'dynamic' ) {
                my @cmd = ( $ghc, '-shared', '-dynamic', "$file", '-o', "$out" );
                push @cmd, '-fPIC' unless $os eq 'MSWin32';
                $self->_run(@cmd);
                return $out;
            }
            else {
                my $obj = $build_dir->child( $self->_base($file) . $Config{_o} );
                my @cmd = ( $ghc, '-c', "$file", '-o', "$obj", '-no-hs-main' );
                push @cmd, '-fPIC' unless $os eq 'MSWin32';
                $self->_run(@cmd);
                return { file => $obj };
            }
        }

        #~ https://github.com/crystal-lang/crystal/issues/921#issuecomment-2413541412
        method _build_crystal ( $src, $out, $mode ) {
            my $file = $src->{path};
            my $cr   = $self->_can_run('crystal') // croak "Crystal not found";
            if ( $mode eq 'dynamic' ) {

                # Experimental: Attempt to pass linker flags
                # Crystal doesn't have a native 'build shared' flag easily exposed
                # It prefers static binaries.
                $self->_run( $cr, 'build', "$file", '--link-flags', '-shared', '-o', "$out" );
                return $out;
            }
            else {
                my $obj = $build_dir->child( $self->_base($file) . $Config{_o} );
                my @cmd = ( $cr, 'build', '--emit', 'obj', "$file", '-o', "$obj" );
                push @cmd, '--link-flags', '-fPIC' unless $os eq 'MSWin32';
                $self->_run(@cmd);
                return { file => $obj, libs => [ 'pcre', 'gc' ] };
            }
        }

        #~ https://futhark.readthedocs.io/en/stable/usage.html
        method _build_futhark ( $src, $out, $mode ) {
            my $file = $src->{path};
            my $fut  = $self->_can_run('futhark') // croak "Futhark not found";

            # Futhark -> C
            my $c_file = $build_dir->child( $self->_base($file) . '.c' );
            my $prefix = $build_dir->child( $self->_base($file) );
            $self->_run( $fut, 'c', '--library', "$file", '-o', "$prefix" );

            # Reuse C builder
            return $self->_build_c( { path => $c_file }, $out, $mode );
        }

        method _build_pascal ( $src, $out, $mode ) {
            my $file = $src->{path};
            my $fpc  = $self->_can_run('fpc') // croak "FPC not found";
            if ( $mode eq 'dynamic' ) {

                # Free Pascal needs 'library' keyword in source for shared libs usually
                # -CD creates dynamic lib



( run in 0.976 second using v1.01-cache-2.11-cpan-97f6503c9c8 )