File Coverage

blib/lib/App/hopen/Gen/Ninja.pm
Criterion Covered Total %
statement 71 97 73.2
branch 4 18 22.2
condition 1 6 16.6
subroutine 21 28 75.0
pod 4 4 100.0
total 101 153 66.0


line stmt bran cond sub pod time code
1             # App::hopen::Gen::Ninja - generator for ninja(1).
2             package App::hopen::Gen::Ninja;
3 1     1   634 use strict; use warnings;
  1     1   2  
  1         39  
  1         4  
  1         3  
  1         35  
4 1     1   5 use Data::Hopen::Base;
  1         2  
  1         8  
5              
6             # TODO reduce code duplication between this and Gen::Make
7             # TODO here and in Gen::Make, remove the need for AssetGraphVisitor by
8             # creating an extra AssetGraphNode to represent the goal.
9              
10             our $VERSION = '0.000012'; # TRIAL
11              
12 1     1   1465 use parent 'App::hopen::Gen';
  1         2  
  1         8  
13 1     1   68 use Class::Tiny;
  1         3  
  1         7  
14              
15 1     1   41 use App::hopen::BuildSystemGlobals;
  1         2  
  1         122  
16 1     1   7 use App::hopen::Phases qw(is_last_phase);
  1         3  
  1         47  
17 1     1   5 use Data::Hopen qw(:default getparameters $QUIET);
  1         2  
  1         119  
18 1     1   9 use Data::Hopen::Scope::Hash;
  1         2  
  1         56  
19 1     1   8 use Data::Hopen::Util::Data qw(forward_opts);
  1         2  
  1         48  
20 1     1   6 use File::Which;
  1         2  
  1         55  
21 1     1   8 use Hash::Ordered;
  1         2  
  1         34  
22 1     1   8 use Path::Class;
  1         2  
  1         44  
23 1     1   5 use Quote::Code;
  1         2  
  1         8  
24              
25 1     1   540 use App::hopen::Gen::Ninja::AssetGraphNode; # for $OUTPUT
  1         3  
  1         45  
26 1     1   479 use App::hopen::Gen::Ninja::AssetGraphVisitor;
  1         3  
  1         1038  
27              
28             # Docs {{{1
29              
30             =head1 NAME
31              
32             Data::Hopen::Gen::Ninja - hopen generator for simple Ninja files
33              
34             =head1 SYNOPSIS
35              
36             This generator makes a build.ninja file.
37              
38             =head1 FUNCTIONS
39              
40             =cut
41              
42             # }}}1
43              
44             =head2 visit_goal
45              
46             Add a target corresponding to the name of the goal. Usage:
47              
48             $Generator->visit_goal($node, $node_inputs);
49              
50             This happens while the command graph is being run.
51              
52             =cut
53              
54             sub visit_goal {
55 1     1 1 4062 my ($self, %args) = getparameters('self', [qw(goal node_inputs)], @_);
56              
57             # --- Add the goal to the asset graph ---
58              
59 1         94 my $asset_goal = $self->_assets->goal($args{goal}->name);
60              
61             # Pull the inputs. TODO refactor out the code in common with
62             # AhG::Cmd::input_assets().
63             my $hrSourceFiles =
64 1   50     1848 $args{node_inputs}->find(-name => 'made',
65             -set => '*', -levels => 'local') // {};
66             die 'No input files to goal ' . $args{goal}->name
67 1 50       220 unless scalar keys %$hrSourceFiles;
68              
69 1         5 my $lrSourceFiles = $hrSourceFiles->{(keys %$hrSourceFiles)[0]};
70 1     0   34 hlog { 'found inputs to goal', $args{goal}->name, Dumper($lrSourceFiles) } 2;
  0         0  
71              
72             # TODO? verify that all the assets are actually in the graph first?
73 1         15 $self->connect($_, $asset_goal) foreach @$lrSourceFiles;
74              
75             } #visit_goal()
76              
77             =head2 finalize
78              
79             Write out the Ninja file.
80              
81             =cut
82              
83             sub finalize {
84 2     2 1 11 my ($self, %args) = getparameters('self', [qw(phase dag data)], @_);
85 2     0   241 hlog { Finalizing => __PACKAGE__ , '- phase', $args{phase} };
  0         0  
86 2 100       20 return unless is_last_phase $args{phase};
87              
88 1     0   7 hlog { __PACKAGE__, 'Asset graph', '' . $self->_assets->_graph } 3;
  0         0  
89              
90             # During the Gen phase, create the Ninja file
91 1 50       34 open my $fh, '>', $self->dest_dir->file('build.ninja')
92             or die "Couldn't create Ninjafile";
93             print $fh qc_to <<"EOT";
94 1         14 # Ninja file generated by hopen (https://github.com/hopenbuild/App-hopen)
95 1         360 # at #{gmtime} GMT
  1         31  
  1         176  
96             # From ``#{$self->proj_dir->absolute}'' into ``#{$self->dest_dir->absolute}''
97              
98             EOT
99              
100 1         166 my $context = Data::Hopen::Scope::Hash->new;
101 1         25 $context->put(App::hopen::Gen::Ninja::AssetGraphNode::OUTPUT, $fh);
102              
103             # Write the Ninja file. TODO? flip the order?
104              
105 1         62 $self->_assets->run(-context => $context,
106             -visitor => App::hopen::Gen::Ninja::AssetGraphVisitor->new,
107             forward_opts(\%args, {'-'=>1}, qw(phase))
108             );
109              
110 1         143 close $fh;
111             } #finalize()
112              
113             =head2 default_toolset
114              
115             Returns the package name of the default toolset for this generator,
116             which is C<Gnu> (i.e., L<Data::Hopen::T::Gnu>).
117              
118             =cut
119              
120 2     2 1 10 sub default_toolset { 'Gnu' }
121              
122             =head2 _assetop_class
123              
124             The class of asset-graph operations, which in this case is
125             L<App::hopen::Gen::Ninja::AssetGraphNode>.
126              
127             =cut
128              
129 3     3   9 sub _assetop_class { 'App::hopen::Gen::Ninja::AssetGraphNode' }
130              
131             =head2 _run_build
132              
133             Implementation of L<App::hopen::Gen/run_build>.
134              
135             =cut
136              
137             sub _run_build {
138             # Look for the make(1) executable. Listing make before gmake since a
139             # system with both Cygwin and Strawberry Perl installed has cygwin's
140             # make(1) and Strawberry's gmake(1).
141 0     0   0 my $path = File::Which::which('ninja');
142 0 0       0 if(defined $path) {
143 0     0   0 hlog { Running => $path };
  0         0  
144 0         0 system $path, ();
145             } else {
146 0         0 warn "Could not find the 'ninja' program";
147             }
148             } #_run_build()
149              
150             =head1 INTERNALS
151              
152             =head2 _expand
153              
154             Produce the command line or lines associated with a work item. Used by
155             L</finalize>.
156              
157             =cut
158              
159             sub _expand {
160 0 0   0   0 my $item = shift or croak 'Need a work item';
161 0     0   0 hlog { __PACKAGE__ . '::_expand()', Dumper($item) } 2;
  0         0  
162 0 0       0 my $retval = $item->{how} or return ''; # no `how` => no output; not an error
163 0 0       0 $retval = $retval->[0] if ref $retval eq 'ARRAY';
164              
165 0         0 my $first = $item->{from}->[0];
166 0 0       0 $first = $first->orig->relative($DestDir)
167             if $first->DOES('App::hopen::Util::BasedPath');
168              
169 0         0 my $out = $item->{to}->[0];
170 0 0       0 $out = $out->orig->relative($DestDir)
171             if $out->DOES('App::hopen::Util::BasedPath');
172              
173 0   0     0 $retval =~ s{#first\b}{$first // ''}ge; # first input
  0         0  
174 0         0 $retval =~ s{#all\b}{join(' ', @{$item->{from}})}ge; # all inputs
  0         0  
  0         0  
175 0   0     0 $retval =~ s{#out\b}{$out // ''}ge;
  0         0  
176              
177 0         0 return $retval;
178             } #_expand()
179              
180             =head2 BUILD
181              
182             Constructor
183              
184             =cut
185              
186             sub BUILD {
187 2     2 1 2421 my ($self, $hrArgs) = @_;
188             } #BUILD()
189              
190              
191             1;
192             __END__
193             # vi: set fdm=marker: #