Alien-Xrepo

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN

    Default package kind (`shared` or `static`) for every action this instance performs. A per-call `kind => ...` wins. If left unset (the default), `-k` is omitted entirely so installs behave exactly like a bare `xrepo install`. Useful when you know...

- **cache**

    Boolean, default on. `install` memorizes each successful fetch result on disk (see ["`install( ... )`"](#install) below) so a repeated launch resolves the package with zero `xrepo` spawns. Entries are LRU-bounded and validated against the recorde...

## `install( ... )`

```perl
my $pkg_info = $repo->install( $package_name, $version_constraint, %options );
```

Installs (if missing) and fetches the metadata for a package.

Resolution is staged so repeated calls avoid the `xmake` process startup cost entirely:

- 1. A warm cache hit replays the memorized fetch result without invoking `xrepo`. The entry is only trusted while its recorded install directory still exists on disk, and stale entries automatically prune themselves. (See the **cache** constructor o...
- 2. Otherwise, `fetch --json` is tried first: an already-installed package answers with real paths immediately and the mutating `xrepo install` is skipped. That single fetch is also memorized for next time.
- 3. Only when a package truly is missing does `xrepo install` run, followed by a mandatory fetch to learn where its output landed.

- `$package_name`

    The name of the package (e.g., `zlib`, `opencv`).

- **$version\_constraint**

    Optional semantic version string (`1.2.x`, `latest`). Pass `undef` or an empty string for the default.

- `%options`

    Optional configuration options passed to `xrepo` (shared by most other methods; missing options are filled in automatically):

    - `plat`

        Target platform (e.g., `windows`, `linux`, `macosx`, `android`, `iphoneos`, `wasm`).

    - `arch`

        Target architecture (e.g., `x86_64`, `arm64`, `riscv64`).

    - `mode`

        Build mode: `debug` or `release`.

    - `kind`

        Library kind: `shared` or `static`. If omitted entirely, the package's own default applies, so a bare install behaves exactly like `xrepo install`.

        _Note: For FFI, you almost always want `shared`, but `static` is available if you are linking archives with, say, an XS module._

    - `toolchain`

        Specify a toolchain (e.g., `llvm`, `zig`, `mingw`).

    - `toolchain_host`

        Specify the host toolchain for cross-compilation.

    - `vs`, `vs_toolset`, `vs_sdkver`

        Visual Studio toolset/SDK selection (e.g., `--vs=2017`, `--vs_toolset=14.0`).

    - `ndk`

        The Android NDK directory.

    - `sdk`

        The SDK directory of a cross-toolchain.

    - `mingw`

        The MinGW SDK directory.

    - `jobs`, **linkjobs**

        Parallel compilation/link job counts.

    - `force`

        _install/download_: force reinstall/redownload all packages. _remove_: force removal even when still depended on.

    - `shallow`

        Do not install/download dependent packages.

    - `build`

        Always build and install from source.

    - `debugdir`

        Source directory used for debugging; enables `force` and `shallow` by default.

    - `configs( ... )`

        A hashref or string of package-specific configurations.

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

        Perl's built-in boolean scalars (`use feature 'true'/'false'`, enabled by `use v5.36+`) are normalized to the literal strings `'true'` / `'false'`, so `configs => { shared => true }` produces `--configs='shared=true'`.

    - `includes`

        A list or string of extra `rc` files to include in the environment.

        Each include is forwarded to `xmake` verbatim, so it must be a valid root-scope `xmake` configuration (e.g., `add_toolchains`); `xmake` textually prepends `rc` contents to the temporary project script. A vendored `package() {...}` recipe is N...

    - `installdir`, **cachedir**

        Root directories for the installed packages and the download/build cache, applied per-call via the `XMAKE_PKG_INSTALLDIR` / `XMAKE_PKG_CACHEDIR` environment variables. This lets each wrapper keep its libraries in a project-local directory ins...

    - `theme`

        Per-call `xmake` output theme override. Defaults to the `theme` constructor value (`plain`). See ["new( ... )"](#new).

    - `yes`, `confirm`

README.md  view on Meta::CPAN

Returns an [Alien::Xrepo::PackageInfo](https://metacpan.org/pod/Alien%3A%3AXrepo%3A%3APackageInfo) object.

## `fetch( ..., [ ... ] )`

```perl
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 [Alien::Xrepo::PackageInfo](https://metacpan.org/pod/Alien%3A%3AXrepo%3A%3APackageInfo) object, or a raw flag string when `cflags` or `ldflags` is requested.

- `cflags`

    Fetch `-I...` include flags as a string.

- `ldflags`

    Fetch `-L.../-l...` link flags as a string.

- `deps`

    Fetch packages together with their dependencies.

- `system`

    Only fetch the package on the current system.

- `external`

    Show `cflags` as external packages (with `-isystem`).

- `installdir`, `cachedir`

    Target the same isolated store used by `install( ... )` (see there).

## `info( ... )`

```perl
my $json = $repo->info( 'zlib', format => 'json' );
my $text = $repo->info( 'libpng' );
my $dot  = $repo->info( 'libpng', depgraph => 1, format => 'dot' );   # dependency graph (Graphviz)
```

Shows package information. Pass `format => 'json'` to receive the decoded data structure (array of hashes), `format => 'dot'` for a Graphviz DOT dependency graph, or `depgraph => 1` to include the package dependency tree. A DOT graph can be rendered ...

## `scan( [ ... ] )`

```perl
my @installed = $repo->scan( 'libpng' );
my @all       = $repo->scan();
```

Lists installed packages (optionally filtered by a Lua pattern). Returns the output lines as a list.

## `download( ... )`

```perl
$repo->download( 'zlib', undef, outputdir => './dl', shallow => 1 ); # Downloads the latest version
```

Only downloads the package source archives without building them. `outputdir` selects the destination directory (default `packages`). Supports `force`, `shallow`, and the standard `%options`.

## `import_pkg( ... )`

```perl
$repo->import_pkg( 'zlib', undef, packagedir => './packages' ); # Latest zlib version
$repo->import_pkg( 'libfake', '1.0.x' ); # A particular version of this fake lib
```

Imports pre-downloaded package archives into the local cache. `packagedir` selects the source directory.

## `export( ... )`

```perl
$repo->export( 'zlib', undef, packagedir => './packages', shallow => 1 ); # Export the latest version
```

Exports installed package files for offline use. `packagedir` selects the destination directory.

## `env( [ ..., [ ... ] ] )`

```perl
$repo->env( 'bash', bind => 'zlib' );   # run a program inside the package env
$repo->env( undef, show => 1 );         # only print the environment
```

Sets up the package environment and either prints it (`show`) or executes `$program` (default `shell`) inside it. `bind` selects which environment config or package to bind, `list` lists global configs, and `add`/`remove` manage global environment co...

## `list_repo()`

```perl
my @repos = $repo->list_repo();
```

Lists all configured remote repositories (as output lines).

## `uninstall( ..., [ ... ] )`

```perl
$repo->uninstall( 'zlib' );
$repo->uninstall( 'zl*', all => 1 );
```

Removes the specified package from the local cache. Accepts the same `%options` as `install( ... )`. `all` removes all matching packages (ignoring extra configs, Lua patterns allowed) and `force` removes addon packages even when they are still depend...

## `search( ..., [ ... ] )`

```perl
$repo->search( $query );
$repo->search( $query, addon => 1 );
```

Runs `xrepo search` and returns the matching packages as a list of `name` or `name-version` tokens (in list context; the match count in scalar context). Name and version are returned together because a package name may itself contain `-`, so the boun...

The output is captured, so nothing is printed to `STDOUT` by this method. On a failed run (nonzero exit, e.g., a missing `vcpkg::` namespace) it `warn`s and returns an empty list. `addon` searches the `addons/` sub-repository.

## `clean( [ ... ] )`

```perl
$repo->clean();
$repo->clean( installdir => './store' );   # clean an isolated store
```

Cleans the cached packages and downloads. Pass `installdir` and/or `cachedir` to target an isolated store.

## `add_repo( ... )`

```
$repo->add_repo( $name, $git_url, $branch );
```

Adds a custom `xmake` repository.

## `remove_repo( ... )`

```
$repo->remove_repo( $name );
```

Removes a custom repository.

## `update_repo( [...] )`

```
$repo->update_repo();        # Update all
$repo->update_repo( 'main' ); # Update specific repo
```

README.md  view on Meta::CPAN

$repo->download( 'zlib', undef, outputdir => './dl', shallow => 1 );   # fetch sources (no build)
$repo->import_pkg( 'zlib', undef, packagedir => './dl' );              # load into the cache
my $zlib = $repo->install('zlib');                                     # install offline
say 'installed ' . $zlib->version;
```

### Render the dependency graph

`info( ... depgraph =` 1, format => 'dot')> emits a Graphviz `DOT` description of a package and everything it pulls in. Pipe it to `dot -Tpng dep.dot -o dep.png` to picture how a library's prerequisites resolve:

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

my $dot = Alien::Xrepo->new->info( 'libpng', depgraph => 1, format => 'dot' );
say $dot;    # e.g.  dot -Tpng dep.dot -o dep.png
```

### Cross-compile a library, then read its compiler/link flags

Install a library for another platform/architecture (the same switches `xrepo` accepts become named options), then `fetch` the `-I...` / `-L.../-l...` flags you would pass to your own compiler:

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

my $repo = Alien::Xrepo->new;
$repo->install(
    'libpng', '1.6.x',
    plat => 'windows',
    arch => 'x64',
    mode => 'debug',
    kind => 'shared'
);

my $cflags  = $repo->fetch( 'libpng', undef, cflags  => 1 );   # "-Ic:/.../include ..."
my $ldflags = $repo->fetch( 'libpng', undef, ldflags => 1 );   # "-Lc:/.../lib -l... .."
say "CFLAGS:  $cflags";
say "LDFLAGS: $ldflags";
```

### Remove a package from the cache

`uninstall` removes a package from the local store (the same one `install`/`fetch`/`scan` use, or an isolated `root` you installed into). It accepts the same options as `install`; `all` removes every stored variant, and `force` removes a package even...

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

my $repo = Alien::Xrepo->new;

$repo->uninstall('freetype');               # remove one package
$repo->uninstall('zl*', all => 1);          # every variant matching the pattern
$repo->uninstall('fontconfig', force => 1); # remove even if still depended upon
```

Note that this edits the shared store. Unlike a builder's prune, which slims the `share` directory a distribution ships, `uninstall` frees space in the store you manage yourself.

# Third-party Package Managers

`xrepo` can install from external 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:

```perl
# 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:

```perl
$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 (`libpath`, `includedirs`, `links`, ...) are decoded into an [Alien::Xrepo::PackageInfo](https://metacpan.org/pod/Alien%3A%3AXrepo%3A%3APackageInfo) exactly like any `xmake-repo` package, so your wrapper code does not care where...

See the `xmake-repo` [integration notes](https://github.com/xmake-io/xrepo-docs/blob/master/getting_started.md) for the corresponding `add_requires` syntax inside an `xmake` project.

## How third-party namespaces are installed

A package in a third-party namespace (`vcpkg::zlib`) is installed by the _external_ manager, and `xmake`'s integration does not bootstrap that manager for you: e.g., the `vcpkg` integration raises **`vcpkg not found!`** when it cannot locate the tool...

```perl
packages => [ { name => 'vcpkg::zlib' }, { name => 'vcpkg' } ]
```

These two names mean different things, and their order in the recipe is not their install order:

- **Recipe order**: (`vcpkg::zlib` then `vcpkg`) is the _consumer_ order. [Alien::Xrepo::Runtime](https://metacpan.org/pod/Alien%3A%3AXrepo%3A%3ARuntime) resolves `libpath`, `find_header`, `cflags`, and `libs` against the _first_ package, so the libr...
- **Install order**: (`vcpkg` then `vcpkg::zlib`) is computed by [Alien::Xrepo::Build](https://metacpan.org/pod/Alien%3A%3AXrepo%3A%3ABuild)'s `_install_order()`: any bare package whose name is the namespace of a later `ns::pkg` entry is installed fi...

Once the bare tool is installed, the engine copies its install dir into the environment of the next namespaced spawn: for `vcpkg` it sets `VCPKG_ROOT` (and prepends the tool dir to `PATH`), so `xmake`'s `vcpkg` integration finds the freshly built bin...

Two implementation details make that work and are easy to get wrong (see [Alien::Xrepo::Build](https://metacpan.org/pod/Alien%3A%3AXrepo%3A%3ABuild)):

- `_pkg_installdir` refuses _namespaced_ (`::`) packages. The external manager owns the on-disk layout, so a per-package store path such as `<share>/vcpkg::zlib` is meaningless and the store guard would reject a perfectly valid install. Leaving `inst...
- Environment propagation uses a hash-slice `local`:

    ```
    local @ENV{ keys %env } = values %env if %env;
    ```

    The otherwise-obvious form `local $ENV{$_} = $env{$_} for keys %env` silently binds the _global_ `$_` (not the loop variable) in some builds of Perl, so the values never reach the child process.

Also note that the decoded `fetch --json` output for third-party packages is not always a tidy list: `libfiles`, `bindirs`, `includedirs`, and `linkdirs` may each arrive as a plain string when there is exactly one file or directory. The engine normal...

# SEE ALSO

[https://xrepo.xmake.io](https://xrepo.xmake.io), [https://packages.xmake.io/](https://packages.xmake.io/)

[Alien::Xmake](https://metacpan.org/pod/Alien%3A%3AXmake), [Alien::Xrepo::Build](https://metacpan.org/pod/Alien%3A%3AXrepo%3A%3ABuild), [Alien::Xrepo::Runtime](https://metacpan.org/pod/Alien%3A%3AXrepo%3A%3ARuntime)

[Alien::Xrepo::MB](https://metacpan.org/pod/Alien%3A%3AXrepo%3A%3AMB), [Alien::Xrepo::MM](https://metacpan.org/pod/Alien%3A%3AXrepo%3A%3AMM), [Alien::Xrepo::Build::Dist](https://metacpan.org/pod/Alien%3A%3AXrepo%3A%3ABuild%3A%3ADist)

[Affix](https://metacpan.org/pod/Affix), [Affix::Wrap](https://metacpan.org/pod/Affix%3A%3AWrap), [FFI::Platypus](https://metacpan.org/pod/FFI%3A%3APlatypus), [Inline::C](https://metacpan.org/pod/Inline%3A%3AC)



( run in 0.837 second using v1.01-cache-2.11-cpan-e623d60df62 )