File Coverage

blib/lib/Build/Hopen.pm
Criterion Covered Total %
statement 35 46 76.0
branch 7 20 35.0
condition 2 2 100.0
subroutine 13 14 92.8
pod 6 6 100.0
total 63 88 71.5


line stmt bran cond sub pod time code
1             #!perl
2             # lib/Build/Hopen.pm: utility routines for hopen(1). This file is also the
3             # source of the repo's README.md, which is autogenerated from this POD.
4              
5             package Build::Hopen;
6 15     15   81770 use Build::Hopen::Base;
  15         70  
  15         122  
7              
8 15     15   3415 use parent 'Exporter';
  15         31  
  15         88  
9             our (@EXPORT, @EXPORT_OK, %EXPORT_TAGS);
10             BEGIN {
11             # TODO move more of these to a separate utility package?
12             # Probably keep hnew, hlog, $VERBOSE, and $QUIET here.
13 15     15   1842 @EXPORT = qw(hnew hlog);
14 15         43 @EXPORT_OK = qw(loadfrom $VERBOSE $QUIET UNSPECIFIED NOTHING isMYH MYH);
15 15         497 %EXPORT_TAGS = (
16             default => [@EXPORT],
17             all => [@EXPORT, @EXPORT_OK]
18             );
19             }
20              
21 15     15   7255 use Build::Hopen::Util::NameSet;
  15         42  
  15         424  
22 15     15   13647 use Storable ();
  15         57737  
  15         1165  
23              
24             our $VERSION = '0.000008'; # TRIAL
25              
26             # Docs {{{1
27              
28             =head1 NAME
29              
30             Build::Hopen - A build generator with first-class edges and explicit dependencies
31              
32             =head1 SYNOPSIS
33              
34             hopen is a cross-platform software build generator. It makes files you can
35             pass to Make, Ninja, Visual Studio, or other build tools, to compile and
36             link your software. hopen gives you:
37              
38             =over
39              
40             =item *
41              
42             A full, Turing-complete, robust programming language to write your
43             build scripts (specifically, Perl 5.14+)
44              
45             =item *
46              
47             No hidden magic! All your data is visible and accessible in a build graph.
48              
49             =item *
50              
51             Context-sensitivity. Your users can tweak their own builds for their own
52             platforms without affecting your project.
53              
54             =back
55              
56             See L for details of the input format.
57              
58             Why Perl? Because (1) you probably already have it installed, and
59             (2) it is the original write-once, run-everywhere language!
60              
61             =head1 INSTALLATION
62              
63             Easiest: install C if you don't have it - see
64             L. Then run
65             C.
66              
67             Manually: clone or untar into a working directory. Then, in that directory,
68              
69             perl Makefile.PL
70             make
71             make test
72              
73             (you may need to install dependencies as well -
74             see L for resources).
75             If all the tests pass,
76              
77             make install
78              
79             If some of the tests fail, please check the issues and file a new one if
80             no one else has reported the problem yet.
81              
82             =head1 VARIABLES
83              
84             Not exported by default, except as noted.
85              
86             =head2 $VERBOSE
87              
88             Set to a positive integer to get debug output on stderr from hopen's internals.
89             The higher the value, the more output you are likely to get. See also L.
90              
91             =head2 $QUIET
92              
93             Set to truthy to suppress output. Quiet overrides L.
94              
95             =cut
96              
97             # }}}1
98              
99 15     15   549 our $VERBOSE; BEGIN { $VERBOSE = 0; }
100 15     15   355 our $QUIET; BEGIN { $QUIET = false; }
101              
102 15     15   98 use constant MYH => 'MY.hopen.pl';
  15         31  
  15         9156  
103              
104             =head1 FUNCTIONS
105              
106             All are exported by default unless indicated.
107              
108             =head2 hnew
109              
110             Creates a new Build::Hopen instance. For example:
111              
112             hnew DAG => 'foo';
113              
114             is the same as
115              
116             Build::Hopen::G::DAG->new( name => 'foo' );
117              
118             If the provided name does not include a double-colon, it is first tried after
119             C. It is then tried in C and as a
120             complete package name. The first one that succeeds is used.
121              
122             The first parameter must be a part of a class name, and the second parameter
123             must be the name of the new instance. All other parameters are passed
124             unchanged to the relevant constructor.
125              
126             =cut
127              
128             sub hnew {
129 6 50   6 1 2215 my $class = shift or croak 'Need a class';
130 6         21 my @stems = ('Build::Hopen::G::', 'Build::Hopen::', '');
131 6 100       28 shift @stems if $class =~ /::/;
132              
133 6         15 foreach my $stem (@stems) {
134 6         12 my $instance = eval {
135 6         428 eval "require $stem$class";
136 6         92 "$stem$class"->new('name', @_)
137             # put 'name' in front of the name parameter.
138             };
139 6 50       222 return $instance if $instance;
140             }
141              
142 0         0 croak "Could not find class for $class";
143             } #hnew()
144              
145             =head2 loadfrom
146              
147             (Not exported by default) Load a package given a list of stems. Usage:
148              
149             my $fullname = loadfrom($name[, @stems]);
150              
151             Returns the full name of the loaded package, or falsy on failure.
152              
153             =cut
154              
155             sub loadfrom {
156 0 0   0 1 0 my $class = shift or croak 'Need a class';
157              
158 0         0 foreach my $stem (@_) {
159 0         0 eval "require $stem$class";
160 0 0       0 return "$stem$class" unless $@;
161             }
162              
163 0         0 return undef;
164             } #loadfrom()
165              
166             =head2 hlog
167              
168             Log information if L is set. Usage:
169              
170             hlog { } [optional min verbosity level (default 1)];
171              
172             The items in the list are joined by C<' '> on output, and a C<'\n'> is added.
173             Each line is prefixed with C<'# '> for the benefit of test runs.
174              
175             The list is in C<{}> so that it won't be evaluated if logging is turned off.
176             It is a full block, so you can run arbitrary code to decide what to log.
177             If the block returns an empty list, hlog will not produce any output.
178              
179             The message will be output only if L is at least the given minimum
180             verbosity level (1 by default).
181              
182             =cut
183              
184             sub hlog (&;$) {
185 37 50   37 1 97 return if $QUIET;
186 37 50 100     169 return unless $VERBOSE >= ($_[1] // 1);
187              
188 0         0 my @log = &{$_[0]}();
  0         0  
189 0 0       0 return unless @log;
190              
191 0 0       0 chomp $log[$#log] if $log[$#log];
192             # TODO add an option to number the lines of the output
193 0         0 say STDERR (join(' ', @log)) =~ s/^/# /gmr;
194             } #hlog()
195              
196             =head2 isMYH
197              
198             Returns truthy if the given argument is the name of a C file.
199             See also L.
200              
201             =cut
202              
203             sub isMYH {
204 2 50   2 1 8 my $name = @_ ? $_[0] : $_;
205 2         4 return ($name =~ /\b\Q@{[MYH]}\E$/)
  2         84  
206             } #isMYH()
207              
208             =head1 CONSTANTS
209              
210             =head2 UNSPECIFIED
211              
212             A L that matches any non-empty string.
213             Always returns the same reference, so that it can be tested with C<==>.
214              
215             =cut
216              
217             my $_UNSPECIFIED = Build::Hopen::Util::NameSet->new(qr/.(*ACCEPT)/);
218 19     19 1 4020 sub UNSPECIFIED () { $_UNSPECIFIED };
219              
220             =head2 NOTHING
221              
222             A L that never matches. Always returns the
223             same reference, so that it can be tested with C<==>.
224              
225             =cut
226              
227             my $_NOTHING = Build::Hopen::Util::NameSet->new();
228 13     13 1 3388 sub NOTHING () { $_NOTHING };
229              
230             =head2 MYH
231              
232             The name C, centralized here. Not exported by default.
233              
234             =cut
235              
236             1; # End of Build::Hopen
237             __END__