some more progress. All the initialization routines run and I can get some of the...
[kakapo:kakapo.git] / setup.nqp
1 #! /usr/bin/env parrot-nqp
2 # Copyright 2009-2010, Austin Hastings. See accompanying LICENSE file, or
3 # http://www.opensource.org/licenses/artistic-license-2.0.php for license.
4
5 # =head1 NAME
6 #
7 # setup.nqp - Configure and build the Kakapo library.
8 #
9 # =head1 USAGE
10 #
11 #     $ parrot-nqp setup.nqp build
12 #     $ parrot-nqp setup.nqp test
13 #     $ sudo parrot-nqp setup.nqp install
14
15 INIT {
16         pir::load_language('parrot');
17         pir::load_bytecode('distutils.pbc');
18
19         pir::load_bytecode('dumper.pir');
20 }
21
22 MAIN(get_args());
23
24 sub new_hash(*%hash) {
25         %hash;
26 }
27
28 sub MAIN(@argv) {
29
30         my %kakapo := new_hash(
31                 :name(          'Kakapo' ),
32                 :abstract(              'Run-time library for NQP programs on the Parrot VM' ),
33                 :authority(             'http://gitorious.org/austin' ),
34                 :copyright_holder(      'Austin Hastings' ),
35                 :doc_files(             <README CREDITS> ),
36                 :keywords(              < library  nqp  parrot  runtime  stand alone  xunit
37                                         unit testing  matcher  pmc  methods  >),
38                 :license_type(  'Artistic License 2.0' ),
39                 :license_uri(           'http://www.perlfoundation.org/artistic_license_2_0' ),
40                 :checkout_uri(  'git://gitorious.org/kakapo/kakapo.git' ),
41                 :browser_uri(   'http://code.google.com/p/kakapo-parrot/' ),
42                 :project_uri(           'git://gitorious.org/kakapo/kakapo.git' ),
43
44                 :harness_files(         pir::join(' ', <
45                         !t/test-data
46                         !t/Matchers/Tree.nqp
47                         !t/Pmc
48                         !t/Structure
49                         t
50                 >) ),
51
52                 :release_id(                    'release-10' ),
53                 :release_dir_format(    'released/%s'),
54                 :vdd_file(                      'vdd.txt' ),
55         );
56
57         %kakapo<copy_templates><library/krt0.pir>                       := <src/Internals/krt0.pir_tmpl>;
58         %kakapo<copy_templates><src/Internals/kakapo_bottom.pir> := <src/Internals/kakapo_bottom.pir_tmpl>;
59         %kakapo<copy_templates><src/Internals/kakapo_top.pir>   := <src/Internals/kakapo_top.pir_tmpl>;
60
61         %kakapo<pir_nqp-rx><src/Internals/Base.pir>     := <src/Internals/Base.nqp>;
62         %kakapo<pir_nqp-rx><src/Internals/Full.pir>     := <src/Internals/Full.nqp>;
63
64         my @base_pir_files := <
65                 src/Global.pir
66                 src/Pmc/Array.pir
67                 src/Pmc/common-methods.pir
68                 src/Syntax.pir
69
70                 src/Internals/Kakapo.pir
71
72                 src/Parrot/Constants.pir
73                 src/Parrot/Multisub.pir
74                 src/Parrot/Nqp.pir
75                 src/Parrot/Opcode.pir
76                 src/Parrot/Parrot.pir
77                 src/Parrot/Pir.pir
78
79
80                 src/Pmc/Class.pir
81
82                 src/Pmc/Exception.pir
83                 src/Exceptions.pir
84                 src/Pmc/File.pir
85                 src/Pmc/Hash.pir
86                 src/Pmc/Integer.pir
87                 src/Pmc/Key.pir
88                 src/Pmc/Namespace.pir
89                 src/Pmc/String.pir
90                 src/Pmc/Sub.pir
91                 src/Pmc/Undef.pir
92         >;
93
94         for @base_pir_files {
95                 %kakapo<pir_nqp-rx>{~ $_} := change_ext(~$_, :from('.pir'), :to('.nqp'));
96         }
97
98         %kakapo<build_libs><library/kakapo_base.pir> := <
99                 src/Internals/kakapo_top.pir
100                 src/Internals/Base.pir
101         >;
102         %kakapo<build_libs><library/kakapo_base.pir>.append( @base_pir_files );
103         %kakapo<build_libs><library/kakapo_base.pir>.push( <src/Internals/kakapo_bottom.pir>);
104
105         my @full_pir_files := <
106                 src/CallSignature.pir
107
108                 src/Classes/P6object.pir
109                 src/Classes/P6metaclass.pir
110
111                 src/ComponentMarshaller.pir
112
113                 src/Cuculinae/Antiphon.pir
114                 src/Cuculinae/Cuculus.pir
115                 src/Cuculinae/Cuckoo.pir
116                 src/Cuculinae/MockFS.pir
117                 src/Cuculinae/Ovum.pir
118                 src/Cuculinae/SigMatcher.pir
119                 src/Cuculinae/Verifier.pir
120
121                 src/DependencyQueue.pir
122                 src/FileSystem.pir
123                 src/Library.pir
124
125                 src/Matchers/CallSig.pir
126                 src/Matchers/Factory.pir
127                 src/Matchers/InstanceOf.pir
128                 src/Matchers/IsNull.pir
129                 src/Matchers/Matcher.pir
130                 src/Matchers/Not.pir
131                 src/Matchers/PassFail.pir
132                 src/Matchers/PctNodes.pir
133                 src/Matchers/TrueFalse.pir
134
135                 src/Path.pir
136                 src/Program.pir
137
138                 src/UnitTest/Assertions.pir
139                 src/UnitTest/Listeners.pir
140                 src/UnitTest/Loader.pir
141                 src/UnitTest/Result.pir
142                 src/UnitTest/Standalone.pir
143                 src/UnitTest/Suite.pir
144                 src/UnitTest/Testcase.pir
145         >;
146
147         for @full_pir_files {
148                 %kakapo<pir_nqp-rx>{~ $_} := change_ext(~$_, :from('.pir'), :to('.nqp'));
149         }
150
151         %kakapo<build_libs><library/kakapo_full.pir> := <
152                 src/Internals/kakapo_top.pir
153                 src/Internals/Full.pir
154         >;
155         %kakapo<build_libs><library/kakapo_full.pir>.append( @base_pir_files );
156         %kakapo<build_libs><library/kakapo_full.pir>.append( @full_pir_files );
157         %kakapo<build_libs><library/kakapo_full.pir>.push( <src/Internals/kakapo_bottom.pir>);
158
159         %kakapo<strip_annotations> := %kakapo<build_libs>;
160
161         %kakapo<pbc_pir><library/kakapo_base.pbc>       := <library/kakapo_base.pir>;
162         %kakapo<pbc_pir><library/kakapo_full.pbc>       := <library/kakapo_full.pir>;
163         %kakapo<pbc_pir><library/krt0.pbc>              := <library/krt0.pir>;
164
165         %kakapo<release_files><kakapo_base.pir> := <library/kakapo_base.pir>;
166         %kakapo<release_files><kakapo_base.pbc> := <library/kakapo_base.pbc>;
167         %kakapo<release_files><kakapo_full.pir> := <library/kakapo_full.pir>;
168         %kakapo<release_files><kakapo_full.pbc> := <library/kakapo_full.pbc>;
169         %kakapo<release_files><krt0.pir>                        := <library/krt0.pir>;
170         %kakapo<release_files><krt0.pbc>                := <library/krt0.pbc>;
171
172         # This test file needs compiling so the others can load it.
173         %kakapo<pir_nqp-rx><t/Pmc/common-methods.pir> := <t/Pmc/common-methods.nqp>;
174
175         %kakapo<inst_lib> := <
176                 library/kakapo_base.pbc
177                 library/kakapo_full.pbc
178                 library/krt0.pbc
179         >;
180
181         register_step_before('build', Setup::Step::copy_templates);
182         register_step_before('clean', Setup::Step::clean_templates);
183
184         #install_build_libs();
185         install_substep('build', Setup::Step::build_libs, :before('_build_pbc_pir'));
186         #install_substep('build', Setup::Step::strip_annotations, :before('_build_pbc_pir'));
187         register_step_before('clean', Setup::Step::clean_libs);
188
189         register_step('release', Setup::Step::make_release);
190
191         pir::shift(@argv);
192         setup_(@argv, %kakapo);
193 }
194
195 sub change_ext($file, :$from!, :$to!) {
196         my $len := pir::length__IS($file) - pir::length__IS($from);
197
198         unless pir::substr__SSI($file, $len) eq $from {
199                 pir::die("No matching extension '$from' on file: $file");
200         }
201
202         my $base := pir::substr__SSI($file, 0, $len);
203         $base ~ $to;
204 }
205
206 sub get_args() {
207         my $interp := pir::getinterp__P();
208         $interp[2];
209 }
210
211 sub install_substep($step, &func, :$before, :$after) {
212         my $target := $before // $after;
213         my @insert;
214         @insert.push(&func);
215
216         our %step;
217         my $index := ?$after;
218         for %step{$step} {
219                 if ~ $_ eq $target {
220                         pir::splice__vppii(%step{$step}, @insert, $index, 0);
221                         return 0;
222                 }
223
224                 $index++;
225         }
226
227         pir::die("Unable to insert substep &func into $step - could not find $target");
228 }
229
230
231 # distutils functions are not in a namespace, so Step:: methods can't address them
232 # directly.
233
234 sub needs_update($src, $dst, :$verbose) {
235
236         ! file_exists($dst) ||newer(~$src, $dst, :verbose($verbose));
237 }
238
239 sub setup_(@steps, %config) {
240         Q:PIR {
241                 $P0 = find_lex '@steps'
242                 $P1 = find_lex '%config'
243                 'setup'($P0 :flat, $P1 :flat :named)
244         };
245 }
246
247 module Setup::Step;
248
249 sub build_libs(*%config) {
250         my $output_file;
251         my @inputs;
252         my $needs_update;
253         my $command;
254
255         for %config<build_libs> {
256                 $output_file := ~ $_;
257                 @inputs := %config<build_libs>{$output_file};
258                 $needs_update := 0;
259
260                 unless newer(~$output_file, @inputs) {
261                         $command := 'cat '
262                                 ~ pir::join(' ', @inputs)
263                                 ~ ' > '
264                                 ~ $output_file;
265                         system($command, :verbose(1));
266                 }
267         }
268 }
269
270 sub clean_libs(*%config) {
271         clean_key(%config<build_libs>);
272 }
273
274 sub clean_templates(*%config) {
275         clean_key(%config<copy_templates>);
276 }
277
278 sub copy_templates(*%config) {
279         my %cfg := %config<copy_templates>;
280         for %cfg {
281                 my $src := %cfg{$_};
282                 my $dst := ~ $_;
283
284                 unless newer(~$dst, ~$src) {
285                         cp($src, $dst, :verbose(1));
286                 }
287         }
288 }
289
290 sub make_release(*%config) {
291         my $release_id := %config<release_id>;
292         unless $release_id {
293                 pir::die("Cannot release: <release_id> config not set");
294         }
295
296         my @args;
297         @args.push( $release_id );
298
299         my $release_dir := pir::sprintf__SSP(%config<release_dir_format>, @args);
300
301         if file_exists($release_dir) {
302                 pir::die("Cannot release: '$release_dir' already exists.");
303         }
304
305         my $vdd := %config<vdd_file>;
306
307         unless $vdd && file_exists($vdd) {
308                 pir::die("Cannot release: no Version Description Document provided. Set <vdd_file> config.");
309         }
310
311         my $fh := pir::new__PS("FileHandle");
312         $fh.open($vdd, 'r');
313         my $leader := $fh.readline;
314         $fh.close;
315
316         if pir::index__ISS($leader, $release_id) < 0 {
317                 pir::die("Cannot release: VDD file '$vdd' does not contain '$release_id' in line 1");
318         }
319
320         my %cfg := %config<release_files>;
321         my $installed_vdd := 0;
322
323         for %cfg {
324                 install(%cfg{~$_}, $release_dir ~ '/' ~$_, :verbose(1));
325
326                 if %cfg{~$_} eq $vdd {
327                         $installed_vdd++;
328                 }
329         }
330
331         unless $installed_vdd {
332                 install($vdd, $release_dir ~ '/VERSION', :verbose(1));
333         }
334
335         unlink($vdd, :verbose(1));
336 }
337
338 sub strip_annotations(*%config) {
339         for %config<strip_annotations> {
340                 if file_exists(~$_) {
341                         my $fh := pir::new__PS("FileHandle");
342                         $fh.open(~$_, 'r');
343                         my $body := $fh.readall();
344                         $fh.close;
345
346                         if pir::index__ISS($body, "\n.annotate ") >= 0 {
347                                 say("Removing annotations from $_");
348                                 $body.replace("\n.annotate ", "\n# .annotate ");
349                                 $fh := pir::new__PS("FileHandle");
350                                 $fh.open(~$_, 'w');
351                                 $fh.puts($body);
352                                 $fh.close;
353                         }
354                 }
355         }
356 }