File Coverage

bin/af
Criterion Covered Total %
statement 210 252 83.3
branch 45 64 70.3
condition 6 11 54.5
subroutine 39 41 95.1
pod 0 5 0.0
total 300 373 80.4


line stmt bran cond sub pod time code
1             #!perl
2              
3 6     6   2569 use strict;
  6         10  
  6         162  
4 6     6   24 use warnings;
  6         7  
  6         129  
5 6     6   90 use 5.014;
  6         15  
6             #use lib::findbin '../lib'; # dev-only
7 6     6   24 use App::af;
  6         7  
  6         136  
8 6     6   837 use File::chdir;
  6         5457  
  6         660  
9              
10             # PODNAME: af
11             # ABSTRACT: Command line tool for alienfile
12             # VERSION
13              
14              
15             use Moose;
16 6     6   35 use namespace::autoclean;
  6         10  
  6         55  
17 6     6   39140 use MooseX::Types::Path::Tiny qw( AbsPath );
  6         12  
  6         41  
18 6     6   436 use Path::Tiny qw( path );
  6         13  
  6         83  
19 6     6   14893  
  6         9  
  6         2667  
20             with 'App::af';
21             with 'App::af::role::alienfile';
22              
23              
24             has local => (
25             is => 'ro',
26             isa => AbsPath,
27             traits => ['App::af::opt'],
28             short => 'l',
29             coerce => 1,
30             opt_type => 's',
31             default => '.',
32             );
33              
34             {
35             my($self) = @_;
36              
37 4     4 0 5 unless(-d $self->local)
38             {
39 4 50       51 say STDERR "no such directory: @{[ $self->local ]}";
40             return 2;
41 0         0 }
  0         0  
42 0         0  
43             local $ENV{ALIEN_INSTALL_TYPE} = 'share';
44             my $build = $self->build;
45 4         104 $build->load_requires('configure');
46 4         17 $build->load_requires('share');
47 4         69 eval { $build->download };
48 4         101 warn $@ if $@;
49 4         83  
  4         15  
50 4 100       7411 unless(defined $build->install_prop->{download} &&
51             length $build->install_prop->{download})
52 4 100 66     180 {
53             say STDERR "Recipe did not seem to download a file or directory";
54             return 2;
55 1         20 }
56 1         19  
57             my $download = path($build->install_prop->{download});
58              
59 3         30 if(-f $download)
60             {
61 3 100       97 my $to = $self->local->child($download->basename);
    50          
62             $download->copy($to) || die "unable to copy $download => $to $!";
63 2         81 say "Wrote archive to $to";
64 2 50       108 }
65 2         3405 elsif(-d $download)
66             {
67             require File::Copy::Recursive;
68             my $to = $self->local->child($download->basename);
69 1         554 File::Copy::Recursive::dircopy("$download", "$to") || die "unable to copy $download => $to $!";
70 1         3685 say "Wrote directory to $to";
71 1 50       60 }
72 1         1475 else
73             {
74             say STDERR "Recipe did not seem to download a file or directory";
75             return 2;
76 0         0 }
77 0         0  
78             0;
79             }
80 3         113  
81             __PACKAGE__->meta->make_immutable;
82             }
83              
84             use Moose;
85             use namespace::autoclean;
86             use MooseX::Types::Path::Tiny qw( AbsPath );
87 6     6   8892 use File::Temp qw( tempdir );
  6         10  
  6         24  
88 6     6   32638  
  6         12  
  6         30  
89 6     6   376 with 'App::af';
  6         8  
  6         32  
90 6     6   13747 with 'App::af::role::alienfile';
  6         13  
  6         1643  
91             with 'App::af::role::libandblib';
92              
93              
94             has root => (
95             is => 'ro',
96             isa => AbsPath,
97             traits => ['App::af::opt'],
98             opt_type => 's',
99             coerce => 1,
100             lazy => 1,
101             default => sub {
102             shift->_tmp->child('root');
103             },
104             );
105              
106             has _tmp => (
107             is => 'ro',
108             isa => AbsPath,
109             lazy => 1,
110             default => sub {
111             my $dir = Path::Tiny->new(tempdir( CLEANUP => 1));
112             $dir->child($_)->mkpath for qw( root stage prefix );
113             $dir;
114             },
115             );
116              
117             {
118             my($self) = @_;
119              
120             my $build = $self->build( root => $self->root->stringify );
121              
122             $build->set_stage($self->_tmp->child('stage')->stringify);
123             $build->set_prefix($self->_tmp->child('prefix')->stringify);
124             $build->load_requires('configure');
125             my $type = $build->install_type;
126              
127             say "install type: $type";
128              
129             0;
130             }
131             }
132              
133             use Moose;
134             use namespace::autoclean;
135             use File::Temp qw( tempdir );
136             use MooseX::Types::Path::Tiny qw( AbsPath );
137             use YAML qw( Dump );
138 6     6   8006 use Path::Tiny qw( path );
  6         12  
  6         26  
139 6     6   34464  
  6         11  
  6         28  
140 6     6   368 with 'App::af';
  6         11  
  6         282  
141 6     6   29 with 'App::af::role::alienfile';
  6         10  
  6         31  
142 6     6   15499 with 'App::af::role::libandblib';
  6         24297  
  6         299  
143 6     6   38  
  6         9  
  6         2625  
144              
145             has stage => (
146             is => 'ro',
147             isa => AbsPath,
148             traits => ['App::af::opt'],
149             coerce => 1,
150             lazy => 1,
151             opt_type => 's',
152             default => sub {
153             tempdir( CLEANUP => 1);
154             },
155             );
156              
157             has prefix => (
158             is => 'rw',
159             isa => AbsPath,
160             traits => ['App::af::opt'],
161             opt_type => 's',
162             coerce => 1,
163             );
164              
165             has type => (
166             is => 'ro',
167             isa => 'Str',
168             traits => ['App::af::opt'],
169             opt_type => 's',
170             );
171              
172             has dry_run => (
173             is => 'ro',
174             isa => 'Int',
175             traits => ['App::af::opt'],
176             );
177              
178             has root => (
179             is => 'ro',
180             isa => AbsPath,
181             traits => ['App::af::opt'],
182             opt_type => 's',
183             coerce => 1,
184             lazy => 1,
185             default => sub {
186             tempdir( CLEANUP => 1);
187             },
188             );
189              
190             has before => (
191             is => 'ro',
192             isa => 'ArrayRef[Str]',
193             traits => ['App::af::opt'],
194             opt_type => 's{2}',
195             );
196              
197             has after => (
198             is => 'ro',
199             isa => 'ArrayRef[Str]',
200             traits => ['App::af::opt'],
201             opt_type => 's{2}',
202             );
203              
204             {
205             my($self) = @_;
206              
207             local $ENV{ALIEN_INSTALL_TYPE} = $ENV{ALIEN_INSTALL_TYPE};
208              
209             if(defined $self->type)
210             {
211             unless($self->type =~ /^(share|system)$/)
212             {
213             say STDERR "unknown install type: @{[ $self->type ]}";
214             return 2;
215             }
216             $ENV{ALIEN_INSTALL_TYPE} = $self->type;
217             }
218              
219             if(-d $self->stage && $self->stage->children)
220             {
221             say "stage directory is not empty";
222             exit 2;
223             }
224              
225             my($build, $prefix) = $self->build( root => $self->root->stringify );
226             $self->prefix($prefix) if defined($prefix) && ! $self->prefix;
227              
228             my @all_hooks = qw(
229             probe download fetch decode prefer extract patch
230             build stage gather_share gather_system
231             );
232              
233             my $repl = sub {
234             no warnings 'once';
235             require Shell::Perl;
236             my $pirl = Shell::Perl->new(on_quit => 'return');
237             $pirl->set_package("App::af::pirl");
238             $App::af::pirl::build = $build;
239             $App::af::pirl::meta = $build->meta;
240 6     6   42 eval { $pirl->run };
  6         17  
  6         4850  
241             warn $@ if $@;
242             };
243              
244             while(@{ $self->before })
245             {
246             my $hook = shift @{ $self->before };
247             my $command = shift @{ $self->before };
248              
249             my @hook = $hook =~ /^(\%|\*)$/
250             ? @all_hooks
251             : ($hook);
252              
253             $build->meta->before_hook(
254             $_ => sub {
255             my($build) = @_;
256             $build->log(" [ before @{[ $build->hook_prop->{name} ]} ] + $command");
257             $build->checkpoint;
258             $command eq ':repl'
259             ? $repl->()
260             : $build->system($command);
261             }
262             ) for @hook;
263             }
264              
265             while(@{ $self->after })
266             {
267             my $hook = shift @{ $self->after };
268             my $command = shift @{ $self->after };
269              
270             my @hook = $hook =~ /^(\%|\*)$/
271             ? @all_hooks
272             : ($hook);
273              
274             $build->meta->around_hook(
275             $_ => sub {
276             my $orig = shift;
277             my $ret = eval { $orig->(@_) };
278             my $error = $@;
279             $build->log(" [ after @{[ $build->hook_prop->{name} ]} ] + $command");
280             $build->checkpoint;
281             $command eq ':repl'
282             ? $repl->()
283             : $build->system($command);
284             die $error if $error;
285             $ret;
286             },
287             ) for @hook
288             }
289              
290              
291             if($self->dry_run && ! defined $self->prefix)
292             {
293             $self->prefix(tempdir( CLEANUP => 1 ));
294             }
295              
296             unless(defined $self->prefix)
297             {
298             say STDERR "You must specify a prefix with --prefix or use --dry-run";
299             return 2;
300             }
301              
302             if(-d $self->prefix->child('_alien'))
303             {
304             my $test = $self->prefix->child('_alien/test');
305             eval { $test->touch };
306             if($@)
307             {
308             say STDERR "prefix is not writable. You may need to use su or sudo";
309             return 2;
310             }
311             $test->remove;
312             }
313              
314             $build->set_stage($self->stage->stringify);
315             $build->set_prefix($self->prefix->stringify);
316             $build->load_requires('configure');
317             $build->load_requires($build->install_type);
318             $build->download;
319             $build->build;
320              
321             unless($self->dry_run)
322             {
323             require File::Copy::Recursive;
324              
325             if(-d $self->prefix)
326             {
327             # this is slightly dangerous.
328             foreach my $child ($self->prefix->children)
329             {
330             say "rm -rf $child";
331             $_->remove_tree({ safe => 0 }) for $self->prefix->children;
332             }
333             }
334              
335             File::Copy::Recursive::dircopy($self->stage, $self->prefix) || die "unable to copy @{[ $self->stage ]} => @{[ $self->prefix ]} $!";
336             say "copied staged install into @{[ $self->prefix ]}";
337             };
338              
339             print Dump($build->runtime_prop);
340              
341             0;
342             }
343             __PACKAGE__->meta->make_immutable;
344             }
345              
346             use Moose;
347             use namespace::autoclean;
348             use YAML qw( Dump );
349              
350              
351             with 'App::af';
352             with 'App::af::role::alienfile';
353 6     6   9113 with 'App::af::role::phase';
  6         9  
  6         32  
354 6     6   33866  
  6         14  
  6         38  
355 6     6   369 {
  6         11  
  6         1247  
356             my($self) = @_;
357              
358             $self->check_phase;
359              
360             my $build = $self->build;
361              
362             if($self->phase eq 'all')
363             {
364 5     5 0 11 print Dump({
365             map { $_ => $build->requires($_) } qw( configure any share system )
366 5         16 });
367             }
368 5         17 else
369             {
370 5 100       145 print Dump($build->requires($self->phase));
371             }
372              
373 1         3 0;
  4         61  
374             }
375              
376             __PACKAGE__->meta->make_immutable;
377             }
378 4         76  
379             use Moose;
380             use namespace::autoclean;
381 5         16540 use Capture::Tiny qw( capture );
382              
383             with 'App::af';
384             with 'App::af::role::alienfile';
385             with 'App::af::role::phase';
386              
387              
388 6     6   6765 has plugin => (
  6         14  
  6         215  
389 6     6   32775 is => 'ro',
  6         11  
  6         32  
390 6     6   395 isa => 'Int',
  6         8  
  6         4655  
391             traits => ['App::af::opt'],
392             );
393              
394             has precompile => (
395             is => 'ro',
396             isa => 'Int',
397             traits => ['App::af::opt'],
398             );
399              
400             {
401             my($self) = @_;
402              
403             $self->check_phase;
404              
405             if($self->plugin)
406             {
407             require Alien::Build;
408             require Test2::Mock;
409              
410             my %need;
411 5     5 0 8  
412             my $mock = Test2::Mock->new(class => 'Alien::Build::Meta');
413 5         19 $mock->around('apply_plugin' => sub {
414             my($orig, $self, @args) = @_;
415 5 50       69 local @INC = @INC;
416             push @INC, sub {
417 0         0 my(undef, $filename) = @_;
418 0         0 my $mod = $filename;
419             $mod =~ s{/}{::}g;
420 0         0 $mod =~ s{\.pm$}{};
421             $need{$mod}++;
422 0         0 };
423             eval { $orig->($self, @args) };
424 0     0   0 });
425 0         0 my(undef, undef, $build) = capture { $self->build };
426             print "$_\n" for sort keys %need;
427 0         0 return 0;
428 0         0 }
429 0         0  
430 0         0 if($self->precompile)
431 0         0 {
432 0         0 my %need;
433 0         0  
  0         0  
434 0         0 foreach my $line ($self->file->lines)
435 0     0   0 {
  0         0  
436 0         0 chomp $line;
437 0         0 if($line =~ /^\s*use\s+([A-Za-z_0-9]+(::[A-Za-z_0-9]+)*)/)
438             {
439             my $mod = $1;
440 5 50       135 eval qq{ use $mod () };
441             if($@) { $need{$mod}++ };
442 0         0 }
443             }
444 0         0 print "$_\n" for sort keys %need;
445             exit 0;
446 0         0 }
447 0 0       0  
448             my(undef,undef, $build) = capture { $self->build };
449 0         0  
450 0         0 my @reqs;
451 0 0       0 my %need;
  0         0  
452              
453             if($self->phase eq 'all')
454 0         0 {
455 0         0 $build->load_requires('configure');
456             capture { $build->probe };
457             @reqs = map { $build->requires($_) } qw( configure any share system );
458 5     5   82 @reqs = (
  5         4363  
459             $build->requires('configure'),
460 5         3556 $build->requires($build->install_type),
461             );
462             }
463 5 100       150 else
464             {
465 1         9 @reqs = ( $build->requires($self->phase) );
466 1     1   45 }
  1         1029  
467 1         2014  
  4         61  
468 1         29 foreach my $reqs (@reqs)
469             {
470             foreach my $module (sort keys %$reqs)
471             {
472             my $version = $reqs->{$module};
473             eval {
474             my $pm = $module . '.pm';
475 4         75 $pm =~ s/::/\//g;
476             require $pm;
477             !$version || $module->VERSION($version);
478 5         136 };
479             $need{$module} = 1 if $@
480 6         19 }
481             }
482 7         9  
483 7         8 say $_ for sort keys %need;
484 7         16  
485 7         20 0;
486 7         987 }
487 0 0       0  
488             __PACKAGE__->meta->make_immutable;
489 7 50       39 }
490              
491             use Moose;
492             use namespace::autoclean;
493 5         145  
494              
495 5         71 with 'App::af';
496              
497             has class => (
498             is => 'ro',
499             isa => 'Str',
500             traits => ['App::af::opt'],
501             short => 'c',
502 6     6   6923 opt_type => 's',
  6         164  
  6         41  
503 6     6   32996 );
  6         9  
  6         31  
504              
505             has $_ => (
506             is => 'ro',
507             isa => 'Int',
508             traits => ['App::af::opt'],
509             ) for qw( static cflags libs modversion bin_dir );
510              
511             my($self) = @_;
512              
513             unless($self->class)
514             {
515             say STDERR "You must specify a class.\n";
516             return 2;
517             }
518              
519             my $class = $self->class =~ /::/ ? $self->class : 'Alien::' . $self->class;
520              
521             {
522             my $pm = $class . '.pm';
523 8     8 0 14 $pm =~ s/::/\//g;
524             require $pm;
525 8 50       123 }
526             unless($class->can('runtime_prop'))
527 0         0 {
528 0         0 say STDERR "$class was not installed with Alien::Build";
529             return 2;
530             }
531 8 50       87  
532             my $prop = $class->runtime_prop;
533              
534 8         7 unless($prop)
  8         11  
535 8         22 {
536 8         444 say STDERR "$class was not installed with Alien::Build";
537             return 2;
538 8 50       49 }
539              
540 0         0 my $found = 0;
541 0         0  
542             if($self->cflags)
543             {
544 8         18 if($self->static)
545             {
546 8 50       16620 say $class->cflags_static;
547             }
548 0         0 else
549 0         0 {
550             say $class->cflags;
551             }
552 8         9 $found = 1;
553             }
554 8 100       111  
555             if($self->libs)
556 2 100       27 {
557             if($self->static)
558 1         7 {
559             say $class->libs_static;
560             }
561             else
562 1         8 {
563             say $class->libs;
564 2         404 }
565             $found = 1;
566             }
567 8 100       116  
568             if($self->bin_dir)
569 2 100       25 {
570             say $_ for $class->bin_dir;
571 1         10 $found = 1;
572             }
573              
574             if($self->modversion)
575 1         7 {
576             say $class->version // 'undef';
577 2         277 $found = 1;
578             }
579              
580 8 100       108 unless($found)
581             {
582 1         7 require YAML;
583 1         366 print YAML::Dump($prop);
584             }
585              
586 8 100       106 0;
587             }
588 1   50     10 __PACKAGE__->meta->make_immutable;
589 1         44 }
590              
591             use Moose;
592 8 100       16 use namespace::autoclean;
593             use Path::Tiny qw( path );
594 2         7 use Text::Table;
595 2         6  
596              
597             with 'App::af';
598 8         18415  
599             has long => (
600             is => 'ro',
601             isa => 'Int',
602             traits => ['App::af::opt'],
603             short => 'l',
604 6     6   9360 );
  6         10  
  6         26  
605 6     6   33232  
  6         11  
  6         30  
606 6     6   407 {
  6         9  
  6         278  
607 6     6   3727 my($self) = @_;
  6         90423  
  6         1542  
608              
609             my $table;
610             $table = Text::Table->new('name', 'install type', 'alien version', 'package version')
611             if $self->long;
612              
613             foreach my $inc (map { path($_)->absolute } @INC)
614             {
615             my $dist_root = $inc->child('auto/share/dist');
616             next unless -d $dist_root;
617              
618             foreach my $dist_dir ($dist_root->children)
619             {
620             next unless -f $dist_dir->child('_alien/alien.json');
621 2     2 0 6 my $dist = $dist_dir->basename;
622             my $class = $dist;
623 2         3 $class =~ s/-/::/g;
624 2 100       45  
625             unless($table)
626             {
627 2         1098 say $class;
  22         1025  
628             next;
629 22         655 }
630 22 100       674  
631             eval {
632 2         82 my $pm = $class . '.pm';
633             $pm =~ s/::/\//g;
634 2 50       314 require $pm;
635 2         124 };
636 2         50 if($@)
637 2         9 {
638             $table->add($class, '---', '---');
639 2 100       7 }
640             else
641 1         70 {
642 1         7 my $install_type = eval { $class->install_type } // '---';
643             my $perl_version = eval { $class->VERSION } // '---';
644             my $pkg_version = eval { $class->version } // '---';
645 1         6 $table->add($class, $install_type, $perl_version, $pkg_version);
646 1         2 }
647 1         4 }
648 1         486  
649             }
650 1 50       7  
651             print $table if defined $table;
652 0         0 0;
653             }
654              
655             __PACKAGE__->meta->make_immutable;
656 1   50     2 }
  1         9  
657 1   50     16649  
  1         29  
658 1   50     2 # for testing, allow us to do this file
  1         9  
659 1         25 # without running.
660             unless(caller)
661             {
662             my $class = App::af->compute_class;
663             unless(eval { $class->does('App::af') })
664             {
665 2 100       50 say STDERR "unknown subcommand";
666 2         4622 exit 2;
667             }
668             my $app = $class->new(@ARGV);
669             exit($app->main // 0);
670             }
671              
672              
673             =pod
674              
675             =encoding UTF-8
676              
677             =head1 NAME
678              
679             af - Command line tool for alienfile
680              
681             =head1 VERSION
682              
683             version 0.18
684              
685             =head1 SYNOPSIS
686              
687             af probe --help
688             af download --help
689             af install --help
690             af requires --help
691             af missing --help
692             af prop --help
693             af list --help
694              
695             =head1 DESCRIPTION
696              
697             The C<af> command is a command line interface to L<alienfile> and
698             L<Alien::Build>.
699              
700             =head3 options
701              
702             These options are available for all subcommands.
703              
704             =head4 --help
705              
706             Print the help for either C<af> as a whole, or the specific subcommand.
707              
708             =head4 --version
709              
710             Print the version of C<af> and exit.
711              
712             =head1 SUBCOMMANDS
713              
714             =head2 download
715              
716             =head3 Usage
717              
718             af download
719             [ ( -f | --file ) alienfile | ( -c | --class ) class ]
720             [ ( -l | --local ) directory ]
721              
722             =head3 description
723              
724             Download the external resource using the usual L<alienfile> logic. File
725             will be deposited in the directory indicated by the C<--local> (or C<-l>)
726             option, or the current working directory if not specified.
727              
728             =head3 options
729              
730             =head4 -f | --file
731              
732             The L<alienfile>. If neither this option, nor C<-c> is specified, then
733             C<alienfile> in the current directory will be assumed.
734              
735             =head4 -c | --class
736              
737             Get the L<alienfile> from the already installed Alien module. You may
738             omit the C<Alien::> prefix, so for example L<Alien::curl> may be specified
739             as simply C<curl>.
740              
741             =head4 -l | --local
742              
743             The location to store the downloaded resource. The current directory
744             if not specified.
745              
746             =head2 probe
747              
748             =head3 Usage
749              
750             af probe
751             [ ( -f | --file ) alienfile | ( -c | --class ) class ]
752             [ --root directory ]
753             [ --before hook command ] [ --after hook command ]
754             [ -I lib ] [ --blib ]
755              
756             =head3 description
757              
758             Probe system for existing library or tool using the given L<alienfile>.
759              
760             =head4 -f | --file
761              
762             The L<alienfile>. If neither this option, nor C<-c> is specified, then
763             C<alienfile> in the current directory will be assumed.
764              
765             =head4 -c | --class
766              
767             Get the L<alienfile> from the already installed Alien module. You may
768             omit the C<Alien::> prefix, so for example L<Alien::curl> may be specified
769             as simply C<curl>. If you do not specify the C<--prefix> option, the
770             package will replace the already installed one.
771              
772             =head4 --root
773              
774             Build in root
775              
776             =head4 -I
777              
778             Add directory to the Perl search lib (like -I on L<perl>).
779              
780             =head4 --blib
781              
782             Use the blib from the current directory.
783              
784             =head2 install
785              
786             =head3 Usage
787              
788             af install
789             [ ( -f | --file ) alienfile | ( -c | --class ) class ]
790             [ --prefix directory | --dry-run ] [ --stage directory ]
791             [ --type ( share | system ) ] [ --root directory ]
792             [ --before hook command ] [ --after hook command ]
793             [ -I lib ] [ --blib ]
794              
795             =head3 description
796              
797             Install or reinstall using the given L<alienfile> or already installed
798             L<Alien>.
799              
800             =head3 options
801              
802             =head4 -f | --file
803              
804             The L<alienfile>. If neither this option, nor C<-c> is specified, then
805             C<alienfile> in the current directory will be assumed.
806              
807             =head4 -c | --class
808              
809             Get the L<alienfile> from the already installed Alien module. You may
810             omit the C<Alien::> prefix, so for example L<Alien::curl> may be specified
811             as simply C<curl>. If you do not specify the C<--prefix> option, the
812             package will replace the already installed one.
813              
814             =head4 --stage
815              
816             The stage directory. By default this is a temporary directory that will
817             automatically be removed.
818              
819             =head4 --prefix
820              
821             The final install location to use. Required when using the C<-f> option,
822             but optional when using the C<-c> option.
823              
824             =head4 --type
825              
826             Override the install type. May be either C<share> or C<system>.
827              
828             =head4 --dry-run
829              
830             Do not install into the final location.
831              
832             =head4 --root
833              
834             Build in root
835              
836             =head4 --before
837              
838             Execute the given command before the given hook. Note that the same
839             hook my execute several times for a given recipe. Example, to open up
840             an interactive shell before the build has started, right after the
841             extraction:
842              
843             % af install --before build bash
844              
845             The build configuration is check pointed, so you can read the install
846             and runtime properties in the C<state.json> file in the build root.
847             Use * or % as the hook to run the command before all hooks. You can
848             use C<:repl> as the command to open up a Perl REPL (Read-Eval-Print-Loop)
849             to inspect the C<$build> and C<$meta> objects.
850              
851             =head4 --after
852              
853             Execute the given command after the given hook. Note that the same hook
854             my execute several times for a given recipe. Example, to open up an
855             interactive shell after the build has completed:
856              
857             % af install --after build bash
858              
859             The build configuration is check pointed, so you can read the install
860             and runtime properties in the C<state.json> file in the build root.
861             Use * or % as the hook to run the command before all hooks. You can
862             use C<:repl> as the command to open up a Perl REPL (Read-Eval-Print-Loop)
863             to inspect the C<$build> and C<$meta> objects.
864              
865             =head4 -I
866              
867             Add directory to the Perl search lib (like -I on L<perl>).
868              
869             =head4 --blib
870              
871             Use the blib from the current directory.
872              
873             =head2 requires
874              
875             =head3 Usage
876              
877             af requires
878             [ ( -f | --file ) alienfile | ( -c | --class ) class ]
879             [ ( -p | --phase ) ( configure | any | share | system ) ]
880              
881             =head3 description
882              
883             Print the requirements for the given phase in L<YAML> format. If the phase
884             is not provided, then requirements for all phases will be printed separately
885             in L<YAML> format.
886              
887             =head3 options
888              
889             =head4 -f | --file
890              
891             The L<alienfile>. If neither this option, nor C<-c> is specified, then
892             C<alienfile> in the current directory will be assumed.
893              
894             =head4 -c | --class
895              
896             Get the L<alienfile> from the already installed Alien module. You may
897             omit the C<Alien::> prefix, so for example L<Alien::curl> may be specified
898             as simply C<curl>.
899              
900             =head4 -p | --phase
901              
902             The phase of the requirement. Please refer to the L<Alien::Build> documentation
903             for the meaning of the various phases.
904              
905             =head2 missing
906              
907             =head3 Usage
908              
909             af missing
910             [ ( -f | --file ) alienfile | ( -c | --class ) class ]
911             [ ( -p | --phase ) ( configure | any | share | system ) ]
912             [ --plugin | --precompile ]
913              
914             =head3 description
915              
916             Print the requirements for the given phase in list format that are not
917             currently fulfilled. This output can be piped into L<cpanm> in order
918             to install any missing requirements:
919              
920             % af missing -p configure | cpanm
921             % af missing | cpanm
922              
923             If no phase is specified, then missing prereqs for configure, and either
924             share or system will be printed depending on what type of install is
925             detected (for this to work you may need to install the configure
926             prereqs, since the probe may use configure required modules).
927              
928             =head3 options
929              
930             =head4 -f | --file
931              
932             The L<alienfile>. If neither this option, nor C<-c> is specified, then
933             C<alienfile> in the current directory will be assumed.
934              
935             =head4 -c | --class
936              
937             Get the L<alienfile> from the already installed Alien module. You may
938             omit the C<Alien::> prefix, so for example L<Alien::curl> may be specified
939             as simply C<curl>.
940              
941             =head4 -p | --phase
942              
943             The phase of the requirement. Please refer to the L<Alien::Build>
944             documentation for the meaning of the various phases.
945              
946             =head4 --plugin
947              
948             Print out missing plugins. Caveat: to do this, C<af> mocks part of
949             L<Alien::Build::Meta>, which may or may not break in the future.
950              
951             =head2 --precompile
952              
953             Print out missing modules that are needed before the L<alienfile> is even
954             compiled. These are usually C<configure> time prereqs, but if they are
955             C<use>d in the L<alienfile> instead of being declared as a C<requires>, then
956             there is no way for L<Alien::Build> to query for them. Caveat: since
957             L<alienfile> is arbitrary Perl code, there may be corner cases not covered
958             by this option.
959              
960             =head2 prop
961              
962             =head3 Usage
963              
964             af prop
965             ( -c | --class ) class [ --cflags ] [ --libs ] [ --static ]
966             [ --modversion ] [ --bin-dir ]
967              
968             =head3 prop
969              
970             Print the runtime properties for the given L<Alien> class. You may
971             omit the C<Alien::> prefix, so for example L<Alien::curl> may be queried
972             as simply C<curl>. If no specific properties are requested then the
973             entire runtime property hash will be printed in L<YAML> format.
974              
975             =head3 options
976              
977             =head4 -c | --class
978              
979             The class to query for runtime properties. This option is required.
980              
981             =head4 --cflags
982              
983             Print the compiler flags
984              
985             =head4 --libs
986              
987             Print the linker flags
988              
989             =head4 --static
990              
991             For either the C<--cflags> or C<--libs> option print the static versions.
992              
993             =head4 --modversion
994              
995             Print the version of the Alienized package. This is not the version of
996             the L<Alien> module itself.
997              
998             =head4 --bin-dir
999              
1000             Print the list of directories bundled with a C<share> install.
1001              
1002             =head2 list
1003              
1004             =head3 Usage
1005              
1006             af list [ -l | --long ]
1007              
1008             =head3 prop
1009              
1010             Print list of L<Alien> modules already installed that used L<Alien::Build>
1011             as their installer.
1012              
1013             =head3 options
1014              
1015             =head4 -l | --long
1016              
1017             Also print the version number of the L<Alien> module, and the version of the
1018             alienized package.
1019              
1020             =head1 AUTHOR
1021              
1022             Author: Graham Ollis E<lt>plicease@cpan.orgE<gt>
1023              
1024             Contributors:
1025              
1026             Diab Jerius (DJERIUS)
1027              
1028             =head1 COPYRIGHT AND LICENSE
1029              
1030             This software is copyright (c) 2017-2022 by Graham Ollis.
1031              
1032             This is free software; you can redistribute it and/or modify it under
1033             the same terms as the Perl 5 programming language system itself.
1034              
1035             =cut