Alien-Xmake
view release on metacpan or search on metacpan
- `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
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**
`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');
```
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 )