Alien-Xmake

 view release on metacpan or  search on metacpan

Changes.md  view on Meta::CPAN

  - `scan` lists installed packages (optional lua-pattern filter)
  - `download` fetches package source archives
  - `import_pkg` / `export` handle offline package distribution
  - `list_repo` lists configured remote repositories
  - `env` sets up a package environment and runs a program (or `--show` it)
  - `search` supports `--addon`
  - `uninstall` supports `--all` and `--force`
  - `_build_args` now understands jobs, force/shallow/build, VS/NDK/SDK/MingW toolchain switches, and `--toolchain_host`
- Full coverage of xmake actions and plugins in Alien::Xmake
  - New constructor option `verbose` to echo commands as they run
  - Actions: `build`, `clean`, `create`, `configure`, `global`, `install`, `uninstall`, `package`, `pack`, `require`, `run`, `test`, `update`, `service`, `addon`
  - Plugins: `check`, `doxygen`, `format`, `lua`, `macro`, `project`, `repo`, `show`, `watch`
  - Generic escape hatch `task( $name, %options )` for tasks without a dedicated method
  - `show` strips ANSI codes, splits listings, and decodes `--format=json` into a data structure
  - The xmake `f`-style config switches are mapped to options like `plat`, `arch`, `mode`, `kind`, `vs`, `ndk`, `mingw`, `sdk`, `toolchain`, ... (plus a `set` hash for any `--key=value`)
  - `global` gets only the config keys xmake actually accepts there (`vs`, `ndk`, `qt`, ...)
  - Version-build accessor renamed `build()` to `buildid()` so `build` is the build action; the xmake `config` action is exposed as `configure()` to keep config( $key )` as the install-time data accessor
- New `installdir`/`cachedir` options to force a project-local package store (via `XMAKE_PKG_INSTALLDIR` / `XMAKE_PKG_CACHEDIR`) for reproducible, isolated builds
- `::PackageInfo` gains...
  - an `installdir` accessor (from fetch `artifacts.installdir`, else derived from the first libfile/include dir) and `bin_dir` falls back to `<installdir>/bin`, so tool packages (ninja, python, ...) can be installed and run as binaries
  - a `kind` accessor (`library` vs `binary`), surfaced by `print`/`dump`/`_data_printer`
- `Alien::Xrepo->new( root => $dir )` becomes the default `installdir` for every store-touching method, so one install call can run against a project-local store; used by `Alien::Xrepo::Base`
- Alien::Xrepo POD now describes binary/tool installs and not just shared libs for FFI
- New `theme` constructor option (default `plain`) so xmake/xrepo output carries no ANSI color codes; passed as `$ENV{XMAKE_THEME}` on every store-touching method, overridable per-call with `theme => ...`

## [0.08] - 2026-01-11

README.md  view on Meta::CPAN

    Open the interactive configuration menu (`--menu`).

- **export**, **import**

    Export/import configuration files.

- **builddir**

    Alternate build directory (`-o`).

## `global( %options )`

```perl
$xmake->global(network => 'y', theme => 'default');
$xmake->global(vs => '2022');
```

Reads/writes global (user-level) configuration. Shares the platform/toolchain options from `configure( ... )` that
exist on `global` (`android_sdk`, `build_toolver`, `cuda`, `emsdk`, `mingw`, `ndk`, `ndk_sdkver`, `qt`,
`qt_host`, `vcpkg`, `vs`, `wdk`).

- **clean**

    Reset global configuration to defaults (`-c`).

- **check**, **menu**

    Same semantics as `configure( ... )`.

- **theme**, **debugger**, **ccache**

    Global UI/terminal settings.

- **cachedir**

README.md  view on Meta::CPAN

`lsp` writes LSP-friendly output (`compile_flags.txt` or `compile_commands.json`).

## `repo( [$name], %options )`

```perl
my $repos = $xmake->repo( list => 1 );
$xmake->repo('local_extra', add => 1, url => 'git@github.com:me/xmake-repo.git');
```

Manages custom package repositories. `add`, `remove`, `update`, `clear` and `list` select the operation (`list`
returns captured output); `global` restricts the change to the global config; `url` and `branch` are used when
adding.

## `show( [$list], %options )`

```perl
my @platforms = $xmake->show('platforms');
my @targets   = $xmake->show('targets', format => 'json');
my $plain     = $xmake->show('targets', target => 'hello');
```

README.md  view on Meta::CPAN

say for $x->show('platforms');                     # windows, linux, macosx, android, ...
say for $x->show('architectures');

my @targets = $x->show('targets', format => 'json');   # inside a project dir
say $targets[0]->{name};

say 'installed: ' . $x->config('install_type');        # share | system
say 'version  : ' . $x->config('version');
```

The list queries also work from a bare `show` (no project needed) for the global catalogs. Several return rich JSON:
the `apis` value is a big HASH of the built-in module APIs, while `buildmodes`, `platforms`, `rules`, `themes` and
`targets` come back as ARRAY refs. `architectures`, `envs`, `policies` and `toolchains` still print aligned table
text (xmake does not JSON-serialize them), so those come back as a plain listing:

```perl
use v5.40;
use Alien::Xmake;

my $x = Alien::Xmake->new;

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

        path('config.log')->remove;
        path('Build')->remove;
        path('_build_params')->remove;
        true;
    }

    method ACTION_test ( ) {
        die "Run `./Build build` first.\n" unless -d 'blib';
        say 'Running tests...' if $verbose;
        require Test::Harness;
        my @tests = glob('t/*.t');
        return Test::Harness::runtests(@tests) if @tests;
        true;
    }

    method _copy_libs ( ) {
        my $src_root = path('lib');
        return unless $src_root->exists;
        my $iter = $src_root->iterator( { recurse => 1 } );
        while ( my $file = $iter->() ) {
            next unless $file->is_file;

eg/nuklear/nuklear.pl  view on Meta::CPAN

# installs, we feed a stream of "y" answers to stdin and pass --yes / --confirm=yes so nothing ever
# hangs waiting on a TTY. Well, that's the plan anyway...
my $src_dir  = $RealBin;
my $dest_dir = $RealBin;                                                         # install the .dll/.so next to this script
my $ext      = $^O eq 'MSWin32' ? '.dll' : $^O eq 'darwin' ? '.dylib' : '.so';
my $artifact = File::Spec->catfile( $dest_dir, "nk_win$ext" );
my $tool     = Alien::Xmake->new( verbose => 0, yes => 1 );
die 'no xmake available via Alien::Xmake' unless $tool->exe;

# Run `xmake <action>` in $dir (a temp copy of the project), feeding repeated "y" answers on stdin.
# xmake's first-run package install reads io.read() and ignores the global --yes/-y flag, so a
# piped/redirected "y" is the only way to answer it without a TTY. We redirect stdin from a temp
# file of "y"s via the shell; stdout/stderr are inherited so the user sees xmake's progress.
sub run_xmake ( $dir, @args ) {
    local $ENV{XMAKE_THEME} = 'plain';
    my ( $fh, $yfile ) = tempfile( SUFFIX => '.in', UNLINK => 0 );
    print {$fh} ("y\n") x 16;
    close $fh  or die "close $yfile: $!";
    chdir $dir or die "chdir $dir: $!";
    my $cmd = join ' ', map { /\s/ ? '"' . $_ . '"' : $_ } ( $tool->exe, @args );
    return system("$cmd < $yfile") == 0;

lib/Alien/Xmake.pm  view on Meta::CPAN

                        last;
                    }
                    last if $hit;
                }
                last if $hit;
            }
            $hit;
        };
    }

    method global (%opts) {
        my @args;
        push @args, '-c'                                                             if $opts{clean};
        push @args, '--check'                                                        if $opts{check};
        push @args, '--menu'                                                         if $opts{menu};
        push @args, '--theme=' . $opts{theme}                                        if $opts{theme};
        push @args, '--debugger=' . $opts{debugger}                                  if $opts{debugger};
        push @args, '--ccache=' . $opts{ccache}                                      if defined $opts{ccache};
        push @args, '--cachedir=' . $opts{cachedir}                                  if $opts{cachedir};
        push @args, '--policies=' . $opts{policies}                                  if $opts{policies};
        push @args, '--network=' . $opts{network}                                    if $opts{network};
        push @args, '--insecure-ssl'                                                 if $opts{insecure_ssl};
        push @args, '--proxy=' . $opts{proxy}                                        if $opts{proxy};
        push @args, '--proxy_hosts=' . $opts{proxy_hosts}                            if $opts{proxy_hosts};
        push @args, '--proxy_pac=' . $opts{proxy_pac}                                if $opts{proxy_pac};
        push @args, '--pkg_searchdirs=' . $self->_join( $opts{pkg_searchdirs}, ';' ) if $opts{pkg_searchdirs};
        push @args, '--pkg_cachedir=' . $opts{pkg_cachedir}                          if $opts{pkg_cachedir};
        push @args, '--pkg_installdir=' . $opts{pkg_installdir}                      if $opts{pkg_installdir};
        push @args, $self->_global_config_args( \%opts );
        push @args, $self->_extra_args( \%opts );
        $self->_run( 'global', @args );
    }

    method install ( $target //= (), %opts ) {
        my @args;
        push @args, '-o', $opts{installdir} if $opts{installdir};
        push @args, '--bindir=' . $opts{bindir}         if $opts{bindir};
        push @args, '--libdir=' . $opts{libdir}         if $opts{libdir};
        push @args, '--includedir=' . $opts{includedir} if $opts{includedir};
        push @args, '-g', $opts{group} if $opts{group};
        push @args, '-a'                              if $opts{all};

lib/Alien/Xmake.pm  view on Meta::CPAN

        $self->_run( 'project', @args );
    }

    method repo ( $name //= (), %opts ) {
        my @args;
        push @args, '-a'          if $opts{add};
        push @args, '-r'          if $opts{remove};
        push @args, '-u'          if $opts{update};
        push @args, '-c'          if $opts{clear};
        push @args, '-l'          if $opts{list};
        push @args, '-g'          if $opts{global};
        push @args, $name         if defined $name && length $name;
        push @args, $opts{url}    if $opts{url};
        push @args, $opts{branch} if $opts{branch};
        push @args, $self->_extra_args( \%opts );
        return $self->_out( 'repo', \%opts, @args ) if $opts{list};
        $self->_run( 'repo', @args );
    }

    method show ( $list //= (), %opts ) {
        my @args;

lib/Alien/Xmake.pm  view on Meta::CPAN

    }

    # Run a task and return its captured output (string or decoded JSON for --format=json).
    method _out ( $action, $opts, @args ) {
        my ( $out, $err, $exit ) = $self->_capture( $action, @args );
        return ()                if $exit != 0;
        return decode_json($out) if ( $opts->{format} // '' ) eq 'json' && $out =~ /[\{\[]/;
        $out;
    }

    # config-style keys that `xmake global` actually accepts.
    method _global_config_args ($opts) {
        my @args;
        for my $key (qw[android_sdk build_toolver cuda emsdk mingw ndk ndk_sdkver qt qt_host vcpkg vs wdk]) {
            push @args, "--$key=" . $self->_join( $opts->{$key}, ';' ) if defined $opts->{$key};
        }
        push @args, "--$_=$opts->{set}{$_}" for sort keys %{ $opts->{set} // {} };
        @args;
    }

    # Translate the shared xmake `f`-style option names into command line switches.
    method _config_args ($opts) {

lib/Alien/Xmake.pod  view on Meta::CPAN

=item B<export>, B<import>

Export/import configuration files.

=item B<builddir>

Alternate build directory (C<-o>).

=back

=head2 C<global( %options )>

    $xmake->global(network => 'y', theme => 'default');
    $xmake->global(vs => '2022');

Reads/writes global (user-level) configuration. Shares the platform/toolchain options from C<configure( ... )> that
exist on C<global> (C<android_sdk>, C<build_toolver>, C<cuda>, C<emsdk>, C<mingw>, C<ndk>, C<ndk_sdkver>, C<qt>,
C<qt_host>, C<vcpkg>, C<vs>, C<wdk>).

=over

=item B<clean>

Reset global configuration to defaults (C<-c>).

=item B<check>, B<menu>

Same semantics as C<configure( ... )>.

=item B<theme>, B<debugger>, B<ccache>

Global UI/terminal settings.

=item B<cachedir>

lib/Alien/Xmake.pod  view on Meta::CPAN

Generates IDE/third-party project files (C<vs>, C<vsxmake>, C<make>, C<cmake>, C<compile_commands>, ...). C<kind>
selects the generator, C<modes>/C<archs> restrict the configs to generate, C<target> generates only for that target and
C<lsp> writes LSP-friendly output (C<compile_flags.txt> or C<compile_commands.json>).

=head2 C<repo( [$name], %options )>

    my $repos = $xmake->repo( list => 1 );
    $xmake->repo('local_extra', add => 1, url => 'git@github.com:me/xmake-repo.git');

Manages custom package repositories. C<add>, C<remove>, C<update>, C<clear> and C<list> select the operation (C<list>
returns captured output); C<global> restricts the change to the global config; C<url> and C<branch> are used when
adding.

=head2 C<show( [$list], %options )>

    my @platforms = $xmake->show('platforms');
    my @targets   = $xmake->show('targets', format => 'json');
    my $plain     = $xmake->show('targets', target => 'hello');

Shows information about the current project or the C<xmake> installation.

lib/Alien/Xmake.pod  view on Meta::CPAN


    say for $x->show('platforms');                     # windows, linux, macosx, android, ...
    say for $x->show('architectures');

    my @targets = $x->show('targets', format => 'json');   # inside a project dir
    say $targets[0]->{name};

    say 'installed: ' . $x->config('install_type');        # share | system
    say 'version  : ' . $x->config('version');

The list queries also work from a bare C<show> (no project needed) for the global catalogs. Several return rich JSON:
the C<apis> value is a big HASH of the built-in module APIs, while C<buildmodes>, C<platforms>, C<rules>, C<themes> and
C<targets> come back as ARRAY refs. C<architectures>, C<envs>, C<policies> and C<toolchains> still print aligned table
text (xmake does not JSON-serialize them), so those come back as a plain listing:

    use v5.40;
    use Alien::Xmake;

    my $x = Alien::Xmake->new;

    my $apis = $x->show( 'apis', format => 'json' );          # HASH of built-in module APIs



( run in 1.855 second using v1.01-cache-2.11-cpan-1236ad508bc )