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$VERBOSE>. |
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$VERBOSE> 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$VERBOSE> 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__ |