NAME

Alien::Xrepo::Runtime - Consumer class for xrepo-based Alien modules

SYNOPSIS

package Alien::Zstd;
use v5.40;
use experimental 'class';
use Alien::Xrepo::Runtime;

class Alien::Zstd : isa(Alien::Xrepo::Runtime) {
    method recipe {
        return {
            name        => 'Alien-Zstd',
            packages    => [ { name => 'zstd', kind => 'shared' } ],
            local_repos => ['vendor/recipes'],   # optional, used by the build engine
        };
    }
}

1;

# A dist with no extra recipe fields may declare only pkg_name instead:

package Alien::Zstd;
use v5.40;
use experimental 'class';
use Alien::Xrepo::Runtime;

class Alien::Zstd : isa(Alien::Xrepo::Runtime) {
    method pkg_name {
        return [ { name => 'zstd', kind => 'shared' } ];
    }
}

1;

DESCRIPTION

Alien::Xrepo::Runtime is the post-build accessor layer for an xrepo-based Alien. It deliberately avoids the Alien::Base model of generating a per-subclass ::ConfigData module at build time. Instead, package paths are resolved by querying xrepo itself lazily, once per package, cached for the process. This means a fresh checkout of an Alien using this class works perfectly with no build step at all.

Optionally, an xrepo.json recipe instead of an inline pkg_name, alongside a snapshot written by Alien::Xrepo::Build (auto-detected from the dist's share directory, see autodetect_snapshot), makes resolution fully hermetic. The accessors then serve recorded paths and never spawn xrepo. When the build installs packages into the dist's share directory (share_dir), the snapshot records share-relative paths. These are dynamically resolved against the snapshot file's own directory, ensuring the same snapshot serves a source-tree blib build and the installed File::ShareDir tree alike.

Describing the dist once: the recipe()

A distribution that ships extra recipe fields (local_repos, pkg_roots, hooks, defaults) benefits from a single declaration that serves both phases. A subclass may instead declare a recipe method, honored when no recipe/pkg_name constructor argument is supplied (and taking precedence over a pkg_name method). It may return:

The build engine, through Alien::Xrepo::Build, consumes this very same hashref (it may be passed directly as the recipe => ... argument). This guarantees the distribution's description lives in exactly one place and no separate xrepo.json is strictly necessary. A recipe's defaults are treated as ambient install options for every package during dynamic resolution. Because this matches the install profile the build engine derives, dynamic and hermetic resolution always agree.

METHODS

The accessor surface strictly follows Alien::Base conventions. Each accessor takes an optional package name and defaults to the primary (first declared) package.

cflags( [$pkg] )

Include flags (-I...) for the package. Returns an empty string when the package cannot be resolved.

cflags_static( [$pkg] )

Include flags for static linking. Currently acts as an alias of cflags( ) in this release.

libs( [$pkg] )

Link flags (-L... -l...) for the package. Returns an empty string when the package cannot be resolved.

libs_static( [$pkg] )

Link flags for static linking. Currently acts as an alias of libs( ) in this release.

libpath( [$pkg] )

Absolute path to the package's runtime library (DLL/SO/dylib). Returns undef for a header-only package or when resolution fails.

ffi_lib( [$pkg] )

An alias of libpath( ) under the name that Alien::Base build_ffi consumers call.

dynamic_libs( [$pkg] )

Absolute paths to every library file xrepo reported for the package.

bin_dir( [$pkg] )

Executable directories (a tool package's bin). Returns an empty list when the package has none.

prepend_to_path( [$pkg] )

Prepends the package's bin_dir directories to $ENV{PATH} (joined with the platform's path separator, functioning properly on both POSIX and Windows). This lets a consumer spawn the shipped tool (e.g., Exotic::Ninja) without knowing where xrepo installed it. Returns the prepended directories, or an empty list (leaving PATH untouched) when the package has none:

my $ninja = Exotic::Ninja->new;
$ninja->prepend_to_path;
system('ninja', '--version') == 0 or die 'ninja did not run';
version( [$pkg] )

The installed version as reported by xrepo, or undef before resolution.

kind( [$pkg] )

The package kind (library for libraries, binary for tools) as reported by xrepo.

dist_dir( [$pkg] )

The package's install root (where its files live), or undef before resolution.

install_type( [$pkg] )

'share' once the package has resolved, 'system' otherwise. In hermetic snapshot mode, the value recorded in the snapshot is returned unchanged.

alt( $name )

Returns an accessor bound to a non-primary package; calling alt on the primary returns $self. Example: Exotic::SDL3->alt('libsdl3_ttf')->cflags.

find_header( $file, [$pkg] )

Absolute path to a header within the package include directories, or undef if it is not found.

package_info( [$pkg] )

The underlying Alien::Xrepo::PackageInfo, or undef before resolution.

package_names()

The recipe's package names in declaration order (the first is the primary package).

package_defs()

The recipe's normalized per-package definition hashref.

split_flags( $flags, [$pkg] )

Splits a flag string on whitespace and returns the individual flags in a Windows-safe list form. The package argument is accepted for compatibility with other accessors, but the split logic itself does not strictly require it.

CONSTRUCTOR

Alien::Zstd->new(
    pkg_name     => 'zstd',                  # or an arrayref of names / hashref defs
    recipe       => $path_or_recipe,         # alternative to inline pkg_name
    install_opts => { kind => 'shared' },    # ambient flags under every package
    root         => $store_root,
    repo         => $alien_xrepo,            # injectable engine
    cache        => 0,                       # bypass Alien::Xrepo's warm-start cache
    snapshot     => $file,                   # hermetic data; wins over dynamic fetch
    autodetect_snapshot => 1,                # look in the installed dist's share dir
    verbose      => 1
)

recipe is undef by default; when set, it may be an Alien::Xrepo::Build::Recipe object, a file or directory path to an xrepo.json, or a hashref of recipe fields (name, packages, defaults, pkg_roots, local_repos, hooks).

Subclasses may also declare recipe, pkg_name, and install_opts as methods, which the constructor honors when no constructor argument is supplied. A subclass's recipe method takes precedence over pkg_name.

cache (default 1) is forwarded to the engine created by this class, so passing cache => 0 disables "Cache System" in Alien::Xrepo's on-disk resolution cache for a fully live, one-spawn-per-package consumer. When repo => ... injects an engine directly, that engine's own cache setting is respected instead.

SEE ALSO

Alien::Xrepo::Build, Alien::Xrepo::Build::Recipe, Alien::Xrepo, Alien::Base

LICENSE

Copyright (C) Sanko Robinson.

This library is free software; you can redistribute it and/or modify it under the terms found in the Artistic License 2. Other copyrights, terms, and conditions may apply to data transmitted through this module.

AUTHOR

Sanko Robinson https://github.com/sanko