Alien-Xmake

 view release on metacpan or  search on metacpan

builder/Alien/Xmake/Builder.pm  view on Meta::CPAN

# Based on Module::Build::Tiny which is copyright (c) 2011 by Leon Timmermans, David Golden.
# Module::Build::Tiny is free software; you can redistribute it and/or modify it under
# the same terms as the Perl 5 programming language system itself.
use v5.40;
use feature 'class';
no warnings 'experimental::class';

class Alien::Xmake::Builder {
    use CPAN::Meta;
    use ExtUtils::Install qw[pm_to_blib install];
    use ExtUtils::InstallPaths;
    use JSON::PP;
    use Config;
    use HTTP::Tiny;
    use Path::Tiny        qw[path cwd];
    use ExtUtils::Helpers qw[make_executable split_like_shell detildefy];
    use Data::Dumper;

    # Configuration
    field $target_version : param : reader //= 'v3.0.6';
    field $force  : param  //= 0;
    field $meta   : reader //= CPAN::Meta->load_file('META.json');
    field $action : param  //= 'build';
    field $target_config = 'lib/Alien/Xmake/ConfigData.pm';

    # Params to Build script
    field $install_base  : param    //= '';
    field $installdirs   : param    //= '';
    field $uninst        : param    //= 0;
    field $install_paths : param    //= ExtUtils::InstallPaths->new( dist_name => $meta->name );
    field $verbose       : param(v) //= 0;
    field $dry_run       : param    //= 0;
    field $pureperl      : param    //= 0;
    field $jobs          : param    //= 1;
    field $destdir       : param    //= '';
    field $prefix        : param    //= '';
    ADJUST {
        -e 'META.json' or die "No META information provided\n";
    }

    method Build_PL() {
        die "Pure perl Affix? Ha! You wish.\n" if $pureperl;
        say sprintf 'Creating new Build script for %s %s', $meta->name, $meta->version;

        # We must capture the current INC to ensure the builder finds itself
        # when running the generated script.
        my $inc_str = join( ' ', map {"-I$_"} @INC );
        $self->write_file( 'Build', sprintf <<'', $^X, $inc_str, __PACKAGE__, __PACKAGE__ );
#!%s %s
use lib 'builder';
use %s;
%s->new( @ARGV && $ARGV[0] =~ /\A\w+\z/ ? ( action => shift @ARGV ) : (),
    map { /^--/ ? ( shift(@ARGV) =~ s[^--][]r => 1 ) : /^-/ ? ( shift(@ARGV) =~ s[^-][]r => shift @ARGV ) : () } @ARGV )->Build();

        make_executable('Build');
        my @env = defined $ENV{PERL_MB_OPT} ? split_like_shell( $ENV{PERL_MB_OPT} ) : ();
        $self->write_file( '_build_params', encode_json( [ \@env, \@ARGV ] ) );
        if ( my $dynamic = $meta->custom('x_dynamic_prereqs') ) {
            my %meta_struct = ( %{ $meta->as_struct }, dynamic_config => 1 );
            require CPAN::Requirements::Dynamic;
            my $dynamic_parser = CPAN::Requirements::Dynamic->new();
            my $prereq         = $dynamic_parser->evaluate($dynamic);
            $meta_struct{prereqs} = $meta->effective_prereqs->with_merged_prereqs($prereq)->as_string_hash;
            $meta = CPAN::Meta->new( \%meta_struct );
        }
        $meta->save(@$_) for ['MYMETA.json'];
    }

    # Actions
    method ACTION_build ( ) {
        say 'Building Alien-Xmake...';

        # Prepare blib
        path('blib/lib')->mkpath;
        path('blib/arch')->mkpath;
        path('blib/script')->mkpath;
        path('blib/bin')->mkpath;

builder/Alien/Xmake/Builder.pm  view on Meta::CPAN

    }

    method _generate_share_config( $bin_path, $version ) {

        # Calculate relative path from Alien/xmake/ConfigData.pm to the binary
        # ConfigData is in lib/Alien/xmake/
        # Bin is in      lib/Alien/xmake/share/bin/
        my $lib_base = path('blib/lib/Alien/Xmake')->absolute;
        my $rel_bin  = $bin_path->relative($lib_base)->stringify;
        return { install_type => 'share', version => $version, bin => $rel_bin };
    }

    method _check_existing_share() {
        eval { require Alien::Xmake::ConfigData; 1; } or return undef;
        my $type = eval { Alien::Xmake::ConfigData->config('install_type') } // '';
        return undef unless $type eq 'share';
        my $bin = eval { Alien::Xmake::ConfigData->bin };
        return undef unless $bin && -x $bin;
        my $ver      = $self->_get_xmake_version($bin);
        my $bin_path = path($bin);
        my $dir      = $bin_path->parent;

        if ( $dir->basename eq 'bin' ) {
            $dir = $dir->parent;
        }
        return { version => $ver, bin => $bin, install_dir => $dir };
    }

    method _find_system_xmake ( ) {
        my $sep = ( $^O eq 'MSWin32' ) ? ';' : ':';
        for my $dir ( split /$sep/, $ENV{PATH} ) {
            my $p    = path($dir);
            my $exts = ( $^O eq 'MSWin32' ) ? [qw(.exe .cmd .bat)] : [''];
            for my $ext (@$exts) {
                my $full = $p->child("xmake$ext");
                return $full if -x $full;
            }
        }
        return undef;
    }

    method _get_xmake_version ($cmd) {
        my $safe_cmd = ( $^O eq 'MSWin32' ) ? qq{"$cmd"} : "$cmd";
        my $out      = `$safe_cmd --version`;
        if ( $out =~ /xmake\s+v?(\d+\.\d+\.\d+)/i ) {
            return "v$1";
        }
        return 'v0.0.0';
    }

    method _version_cmp ( $v1, $v2 ) {
        require version;
        $v1 =~ s/^v//;
        $v2 =~ s/^v//;
        return version->parse($v1) <=> version->parse($v2);
    }

    method _write_config_data ($data) {
        my $dest = path('blib')->child($target_config);
        $dest->parent->mkpath;
        my $dumper = Data::Dumper->new( [$data], ['conf'] );
        $dumper->Indent(1)->Terse(1)->Sortkeys(1);
        my $content = sprintf <<~'PERL', $dumper->Dump;
        package Alien::Xmake::ConfigData {
            use v5.40;
            use File::Spec;
            use File::Basename qw[dirname];

            my $config = %s;

            sub config ($s, $key //= ()) { defined $key ? $config->{$key} : $config }
            sub config_names { sort keys %%$config }

            #
            sub bin {
                my $bin = $config->{bin};
                return unless defined $bin;
                return $bin if $config->{install_type} eq 'system';
                File::Spec->rel2abs($bin, dirname(__FILE__))
            }
        };
        1;
        PERL
        $dest->spew_utf8($content);
        say "Generated $dest";
    }

    method _install_windows ($installdir) {
        my $temppath = path('_build_xmake');
        $temppath->mkpath;
        my $arch_env   = $ENV{PROCESSOR_ARCHITECTURE} // '';
        my $arch64_env = $ENV{PROCESSOR_ARCHITEW6432} // '';
        my $filename;

        # Check for ARM64
        if ( $arch_env eq 'ARM64' || $arch64_env eq 'ARM64' ) {

            # ARM64 releases currently use the 'bundle' naming convention
            $filename = "xmake-bundle-$target_version.arm64.exe";
        }

        # Check for x64 (AMD64/IA64)
        elsif ( $arch_env eq 'AMD64' || $arch_env eq 'IA64' || $arch64_env eq 'AMD64' || $arch64_env eq 'IA64' ) {
            $filename = "xmake-$target_version.win64.exe";
        }

        # Fallback to x86
        else {
            $filename = "xmake-$target_version.win32.exe";
        }
        my $url     = "https://github.com/xmake-io/xmake/releases/download/$target_version/$filename";
        my $outfile = $temppath->child('xmake-installer.exe');
        if ( !$self->_download_file( $url, $outfile ) ) {
            die "Download failed for $url";
        }
        my $install_str = $installdir->stringify;
        $install_str =~ s{/}{\\}g;
        my $outfile_str = $outfile->stringify;
        $outfile_str =~ s{/}{\\}g;
        say "Installing to $install_str...";



( run in 1.895 second using v1.01-cache-2.11-cpan-39bf76dae61 )