NAME
Alien::Xrepo::Build - alienfile-shaped build engine where every stage is xrepo
SYNOPSIS
A distribution ships a declarative recipe (xrepo.json) and lets the engine drive installs through xrepo:
{
"name" : "Alien-Zstandard",
"packages" : [
{ "name" : "zstd", "kind" : "shared" }
]
}
# Build.PL
use Alien::Xrepo::Build;
my $snapshot = path('blib/lib/auto/share/dist/Alien-Zstandard/xrepo-snapshot.json');
Alien::Xrepo::Build->new( recipe => '.' )->run( snapshot => $snapshot );
DESCRIPTION
Alien::Xrepo::Build is a build engine in the spirit of Alien::Build: a stage pipeline with hooks and three property buckets, all serialized as plain JSON. Unlike alienfile, there are no download/extract/compile stages of our own, all of that is handled by xrepo via Alien::Xrepo. What remains is the essential orchestration:
probe: ask xrepo whether a package already satisfies the recipe and skip the install if it does
install: one xrepo install per package, per-package version/flags/configs merged over the ambient profile, failures isolated
gather: ensure every package has consumer-facing paths (
xrepo fetch --jsondata) recordedexport: optionally export packages and/or write the runtime snapshot for hermetic consumers
checkpoint/resume: a failed run can be resumed without reinstalling what already happened
Pipeline stages
The pipeline runs configure, probe, install, gather, export, test in order. Each stage method is idempotent per run (a checkpointed stage is skipped). Hooks run immediately before their stage body:
$build->register_hook( install => sub ($build) { ... } );
Properties
The three buckets mirror Alien::Build's meta/install/runtime split:
meta_prop-- recipe facts (name, packages, package defs, defaults, pkg_roots, local_repos, hooks)install_prop-- this run (store root, ambient profile, probe results)runtime_prop-- what consumers need (per-package include/lib/link data and anerrorsmap)
The recipe
xrepo.json is loaded and validated by Alien::Xrepo::Build::Recipe. Its packages array mirrors an Alien::Xrepo::Runtime pkg_name declaration:
a plain string is a bare xrepo package name
a hashref adds install flags, e.g.
{ "name" => "zstd", "version" => "1.5.6", "kind" => "shared", "configs" => { "legacy" => 1 } }
defaults holds ambient flags applied under every package (same key set, plus configs). pkg_roots, local_repos, hooks and name are the remaining top-level keys.
pkg_roots maps a package name to an environment variable whose value names that package's root directory (mirroring Alien::Build's pkg_roots): when the variable is set and points at an existing directory, the package is treated as system-provided there. Probe reports it satisfied, install/gather skip xrepo entirely, and the root's include/lib/bin subdirectories (when present) become the package's resolution data, so a root-resolved package leaves install_type at 'system'.
hooks lists recipe hook module names. Each module is loaded once when the configure stage runs and must expose a class method register_hooks($build); the module typically calls the build's register_hook to attach its stage callbacks:
METHODS
new( ... )
Alien::Xrepo::Build->new(
recipe => $path_or_recipe, # xrepo.json path/dir or a Recipe object
root => $store_root, # XMAKE_PKG_INSTALLDIR
repo => $alien_xrepo, # injectable engine
cache => 0, # bypass Alien::Xrepo's warm-start cache
verbose => true,
checkpoint => $state_file, # enables resume
snapshot => $snapshot_file, # write runtime data here during export
export_dir => $dir, # xrepo-export each package here
probe_policy => 'skip', # skip|always|off
resume => true # load checkpoint on construction
);
cache (default 1) is forwarded to the engine this class creates, so cache => 0 disables the on-disk resolution cache (see Alien::Xrepo); an injected repo => ... keeps its own cache setting.
run( %opts )
Run the full pipeline: configure, probe, install, gather, export, test. Ambient options (kind, mode, plat, arch, configs, ...) are folded over the recipe defaults into the install profile.
Including after a resume, stages that have already run are skipped.
configure( %opts )
Prepares the run: records the recipe facts into meta_prop, folds the ambient %opts over the recipe defaults into install_prop->{profile}, resolves install_prop->{store} (falling back to root), and registers every local_repos entry with the engine. install_type is reset to 'system' and the state is checkpointed. Safe to call more than once: a stage that already ran is skipped.
probe()
Asks the engine whether each package already satisfies the recipe and records the result as install_prop->{probed}{<name>} = { version => ..., satisfied => 0|1 }. A package with a usable pkg_roots entry is recorded as satisfied (with its root) without consulting the engine. Skipped entirely when probe_policy => 'off'>.
install()
Runs one xrepo install per package (per-package options merged over the profile). A package with a usable pkg_roots entry is recorded directly from its root and never passed to the engine. A package the probe found satisfied is skipped when probe_policy => 'skip'> (the default) unless force is set. A failing package is warned about, recorded in runtime_prop->{errors}, and does not abort the remaining packages. Each successful install is recorded in runtime_prop->{packages} and bumps install_type to 'share'.
gather()
Ensures every package not already recorded (installed, root-provided, or failed) has consumer-facing paths: it fetches each one through the engine and stores the resolution data in runtime_prop->{packages}. A root-provided package is recorded from its pkg_roots entry directly. A failed fetch is recorded in runtime_prop->{errors}.
export()
Optionally exports each successfully installed package into export_dir (xrepo export, one <name> subdirectory per package), and writes the hermetic snapshot JSON to snapshot: the install_type, per-package resolution data, any errors, and a digest of the configured recipe. The snapshot is what Alien::Xrepo::Runtime serves to resolve absolute paths with no xrepo process.
test()
Runs the test hooks. There is no built-in test body; attach your own with register_hook.
register_hook( $stage, $code )
Attach a hook. Hooks are invoked as $code->($build) before the stage body.
has_hook( $stage )
True when at least one hook is registered for the stage.
meta_prop()
Recipe facts: name, packages, package_defs, defaults, pkg_roots, local_repos, and hooks. Filled by the configure stage.
install_prop()
This run's state: the root, the merged ambient profile, the resolved store, and the per-package probed results.
runtime_prop()
What consumers need: per-package resolution data under packages and a failure map under errors. This is what the export stage serializes into the snapshot.
install_type()
'share' once any package resolved, 'system' before that. Restored from the checkpoint on a resume.
packages()
Recipe package names in order.
package_defs()
The normalized per-package defs from the recipe.
engine()
The underlying Alien::Xrepo instance (injectable via repo => for tests or alternate engines).
SEE ALSO
Alien::Xrepo::Runtime, Alien::Xrepo::Build::Recipe, Alien::Xrepo, Alien::Build, alienfile
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