Alien-Xrepo
view release on metacpan or search on metacpan
lib/Alien/Xrepo/Build/Recipe.pm view on Meta::CPAN
use v5.40;
use feature 'class';
no warnings 'experimental::class';
#
class Alien::Xrepo::Build::Recipe v1.0.0 {
use JSON::PP qw[decode_json];
use Path::Tiny;
use Scalar::Util qw[looks_like_number];
#
field $name : reader : param //= undef;
field $file : param //= undef;
field $dir : param //= undef;
field $packages : param //= undef;
field $defaults : reader : param //= undef;
field $pkg_roots : reader : param //= undef;
field $local_repos : reader : param //= undef;
field $hooks : reader : param //= undef;
#
field @order : reader(packages); # package names in recipe order (first = primary)
field %defs; # package name => normalized per-package hashref def
method package_defs { \%defs }
#
ADJUST {
if ( defined $file || defined $dir ) {
die 'Recipe: pass exactly one of file / dir / inline data' if defined $file && defined $dir;
die q[Recipe: inline 'packages' is ignored when a file is given] if defined $packages;
my $path = $file // path($dir)->child('xrepo.json');
die 'Recipe file not found: ' . $path unless -e $path;
my $data = eval { decode_json( path($path)->slurp_utf8 ) };
die "Recipe '$path' is not valid JSON: $@" if !defined $data || ref $data ne 'HASH';
$name //= $data->{name};
$packages //= $data->{packages};
$defaults //= $data->{defaults};
$pkg_roots //= $data->{pkg_roots};
$local_repos //= $data->{local_repos} // [];
$hooks //= $data->{hooks} // [];
}
die 'Recipe: packages is required' unless defined $packages;
@order = ( $self->_normalize_defs($packages) );
die 'Recipe: at least one package is required' unless @order;
$defaults //= {};
$pkg_roots //= {};
$local_repos //= [] if !defined $local_repos;
$hooks //= [] if !defined $hooks;
$self->_validate_profile( $defaults, 'defaults' );
$self->_validate_strings( $local_repos, 'local_repos' );
$self->_validate_strings( $hooks, 'hooks' );
die 'Recipe: pkg_roots must be a hashref' unless ref $pkg_roots eq 'HASH';
for my $root ( keys %$pkg_roots ) {
my $v = $pkg_roots->{$root};
die "Recipe: pkg_roots '$root' must be a plain string" if ref $v || !defined $v;
}
}
my %DEF_KEYS = map { $_ => 1 } qw[
name version
plat arch mode kind no_kind toolchain toolchain_host
vs vs_toolset vs_sdkver ndk sdk mingw
jobs linkjobs force shallow build debugdir
yes confirm theme cachedir installdir
configs includes
];
method version_for ($name) { $defs{$name}{version} // undef; }
method opts_for ( $name, %ambient ) {
my $def = $defs{$name};
return %ambient unless ref $def eq 'HASH';
my %merged = %ambient;
my $g_cfg = $merged{configs};
my %configs = ref $g_cfg eq 'HASH' ? %$g_cfg : ();
%configs = ( %configs, %{ $def->{configs} } ) if ref $def->{configs} eq 'HASH';
for my $key ( keys %$def ) {
next if $key eq 'name' || $key eq 'version' || $key eq 'configs';
$merged{$key} = $def->{$key};
}
$merged{configs} = \%configs if ref $g_cfg eq 'HASH' || ref $def->{configs} eq 'HASH';
return %merged;
}
method _normalize_defs ($in) {
my @raw = ref $in eq 'ARRAY' ? @$in : ($in);
my %seen;
my @names;
for my $entry (@raw) {
if ( ref $entry eq 'HASH' ) {
my %def = %$entry;
die "Recipe: package definition requires a 'name' key" unless defined $def{name} && length $def{name};
die "Recipe: package '$def{name}' name must be a plain string" if ref $def{name};
for my $key ( keys %def ) {
( run in 0.465 second using v1.01-cache-2.11-cpan-364913b4093 )