Alien-Xmake

 view release on metacpan or  search on metacpan

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

    # Install a shared lib with an automatic configuration
    my $ogg = $repo->install('libvorbis');

    # Install a library with specific configuration
    # equivalent to: xrepo install -p windows -a x86_64 -m debug --configs='shared=true,vs_runtime=MD' libpng
    my $pkg = $repo->install(
        'libpng', '1.6.x',
        plat    => 'windows',
        arch    => 'x64',
        mode    => 'debug',
        configs => { vs_runtime => 'MD' }
    );
    die 'Install failed' unless $pkg;

    # Or install a binary tool and run it (ninja, cmake, python, node, ...)
    my $ninja = $repo->install('ninja');
    my ($ninja_exe) = map { path($_)->child($^O eq 'MSWin32' ? 'ninja.exe' : 'ninja') } $ninja->bin_dir;
    system $ninja_exe, '--version';

    # Wrap a single function from sqlite3 with Affix
    use Affix;
    my $sqlite3 = $repo->install('sqlite3');
    affix $sqlite3->libpath, 'sqlite3_libversion', [], String;
    say 'SQLite version: ' . sqlite3_libversion();

=head1 DESCRIPTION

This module acts as an intelligent bridge between Perl and a wide range of package systems:
L<xrepo|https://packages.xmake.io/>, L<vcpkg|https://vcpkg.io/en/packages>, L<conan|https://conan.io/center>,
L<brew|https://brew.sh/> (homebrew/linuxbrew), L<conda|https://anaconda.org/>, L<dub|https://dub.pm/> (Dlang libs),
L<apt|https://www.debian.org/distrib/packages> on Debian,
L<pacman|https://wiki.archlinux.org/title/Pacman#Installing_packages> (if you use arch, btw),
L<clib|https://github.com/clibs/clib/>, L<Cargo|https://crates.io/> for Rust crates,
L<Portage|https://packages.gentoo.org/> on Gentoo, L<Nimble|https://nimpackages.com/> for nimlang,
L<NuGet|https://www.nuget.org/> for .NET,
L<Zypper|https://documentation.suse.com/smart/systems-management/html/concept-zypper/index.html> on openSUSE, and even
your own custom repositories with smart prerequisite management.

With a single line, you can fetch B<shared libraries> as well as B<binary tools and interpreters> without touching a
system package manager:

=over

=item * B<Libraries> (C<zlib>, C<libpng>, C<sqlite3>, ...) to bind with FFI or link from XS.

=item * B<Tools and interpreters> (C<ninja>, C<cmake>, C<meson>, C<python>, C<node>, C<go>, C<rust>, ...) to run from
your Perl code or to drive your build.

=back

You are free to install B<both kinds into the same store>: C<ninja> next to C<libpng>. Use L<Affix>, L<FFI::Platypus>,
L<Inline>, or plain XS to bind the libraries, and C<bin_dir>/C<installdir> to locate and run the binaries.

While FFI or XS can handle the binding or linking to native functions, Alien::Xrepo handles the B<acquisition> of the
libraries and binaries. It automates the entire dependency lifecycle:

=over

=item 1. Provisioning:

Downloads and installs both libraries (C<libpng>, C<openssl>, ...) and binary tools (C<ninja>, C<python>, ...) via
C<xrepo>, handling version constraints and custom repository lookups.

=item 2. Configuration:

Ensures libraries are compiled with FFI compatible flags (forcing C<shared> libraries instead of static archives) and
supports cross-compilation parameters (platform, architecture, toolchains).

=item 3. Introspection:

Parses the build metadata to locate the exact absolute paths to the runtime binaries (C<.dll>, C<.so>, C<.dylib>) and
header files, the C<bin_dir> of any installed tool, and the C<-I> / C<-L> / C<-l> flags a compiler needs, abstracting
away operating system filesystem differences.

=back

This eliminates the need for manual compilation steps or hard coding paths in your Perl scripts, making your FFI
bindings or XS wrappers portable and reproducible.

=head1 THIRD-PARTY PACKAGE MANAGERS

xrepo can install from external C/C++ package managers instead of (or alongside) the official xmake-repo. You select
the manager with a package-spec namespace and every Alien::Xrepo method takes it verbatim:

    # Vcpkg, Homebrew/Linuxbrew, Conan
    my $zlib = $repo->install( 'vcpkg::zlib' );
    my $zlib = $repo->install( 'brew::zlib'  );
    my $zlib = $repo->install( 'conan::zlib/1.2.11' );

    # Pacman (archlinux/msys2), Clib, Dub, Cargo, Conda, apt
    $repo->install( 'pacman::libcurl' );
    $repo->install( 'dub::log 0.4.3' );

Searching and flag fetching work against them too:

    $repo->search( 'vcpkg::pcre' );          # search the vcpkg namespace
    my $flags = $repo->fetch( 'conan::zlib/1.2.11', undef, cflags => 1, ldflags => 1 );

The installed results (C<libpath>, C<includedirs>, C<links>, ...) are decoded into an L<Alien::Xrepo::PackageInfo>
exactly like any xmake-repo package, so your wrapper code does not care where the library came from.

See the C<xmake-repo> integration notes at L<https://github.com/xmake-io/xrepo-docs/blob/master/getting_started.md> for
the corresponding C<add_requires> syntax inside an xmake project.

=head1 CONSTRUCTOR

=head2 C<new( ... )>

    my $repo = Alien::Xrepo->new( verbose => 1 );

Creates a new instance.

=over

=item B<verbose>

Boolean. If true, prints command output and status messages to C<STDOUT>. Defaults to C<0>.

=item B<root>

Optional default installation root (package store) for this instance. Every store-touching method (C<install>,

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


=item B<mode>

Build mode: C<debug> or C<release>.

=item B<kind>

Library kind: C<shared> (default) or C<static>.

I<Note: For FFI, you almost always want C<shared>, but C<static> is available if you are linking archives with, say, an
XS module.>

=item B<toolchain>

Specify a toolchain (e.g., C<llvm>, C<zig>, C<mingw>).

=item B<toolchain_host>

Specify the host toolchain for cross compilation.

=item B<vs>, B<vs_toolset>, B<vs_sdkver>

Visual Studio toolset/sdk selection (e.g., C<--vs=2017>, C<--vs_toolset=14.0>).

=item B<ndk>

The Android NDK directory.

=item B<sdk>

The SDK directory of a cross toolchain.

=item B<mingw>

The MinGW SDK directory.

=item B<jobs>, B<linkjobs>

Parallel compilation/link job counts.

=item B<force>

I<install/download>: force reinstall/redownload all packages. I<remove>: force removal even when still depended on.

=item B<shallow>

Do not install/download dependent packages.

=item B<build>

Always build and install from source.

=item B<debugdir>

Source directory used for debugging; enables C<force> and C<shallow> by default.

=item B<configs( ... )>

A hashref or string of package-specific configurations.

    configs => { openssl => 'true', shared => 'true' }
    # becomes --configs='openssl=true,shared=true'

=item B<includes>

A list or string of extra dependencies to include in the environment.

=item B<installdir>, B<cachedir>

Root directories for the installed packages and the download/build cache, applied per-call via the
C<XMAKE_PKG_INSTALLDIR> / C<XMAKE_PKG_CACHEDIR> environment variables. This lets each wrapper keep its libraries in a
project-local directory instead of the shared per-user store, which gives reproducible builds and protects against an
unrelated C<xrepo> run upgrading or removing the packages your wrapper depends on. Pass the same values to C<fetch>,
C<scan>, C<uninstall>, and friends so they operate on the same store.

=item B<theme>

Per-call xmake output theme override. Defaults to the C<theme> constructor value (C<plain>). See L</"new( ... )">.

=item B<yes>, B<confirm>

Per-call auto-confirmation overrides for the constructor C<yes =E<gt> ...> / C<confirm =E<gt> ...> options, applied as
C<-y> or C<--confirm=...> to the underlying C<xrepo> invocation. Defaults to the constructor values. See L</"new( ...
)">.

=back

=back

Returns an L<Alien::Xrepo::PackageInfo> object.

=head2 C<fetch( $pkg, $version, %options )>

    my $pkg_info = $repo->fetch( 'libpng' );
    my $cflags   = $repo->fetch( 'zlib', undef, cflags => 1 );

Fetches metadata for an already-installed package without installing it again. Returns an L<Alien::Xrepo::PackageInfo>
object, or a raw flag string when C<cflags> or C<ldflags> is requested.

=over

=item B<cflags>

Fetch C<-I...> include flags as a string.

=item B<ldflags>

Fetch C<-L.../-l...> link flags as a string.

=item B<deps>

Fetch packages together with their dependencies.

=item B<system>

Only fetch the package on the current system.

=item B<external>

Show C<cflags> as external packages (with C<-isystem>).

=item B<installdir>, B<cachedir>



( run in 0.354 second using v1.01-cache-2.11-cpan-aadc1410aed )