File Coverage

blib/lib/SPVM/Dist.pm
Criterion Covered Total %
statement 64 392 16.3
branch 12 124 9.6
condition 2 21 9.5
subroutine 16 45 35.5
pod 0 34 0.0
total 94 616 15.2


line stmt bran cond sub pod time code
1             package SPVM::Dist;
2              
3 1     1   69497 use strict;
  1         10  
  1         30  
4 1     1   6 use warnings;
  1         2  
  1         25  
5 1     1   5 use Carp 'confess';
  1         2  
  1         46  
6              
7 1     1   502 use File::Copy 'copy', 'move';
  1         5026  
  1         63  
8 1     1   8 use File::Path 'mkpath';
  1         3  
  1         60  
9 1     1   7 use File::Find 'find';
  1         2  
  1         82  
10 1     1   8 use File::Basename 'dirname', 'basename';
  1         2  
  1         77  
11 1     1   473 use SPVM::Builder::Util;
  1         3  
  1         35  
12 1     1   7 use Getopt::Long 'GetOptions';
  1         2  
  1         6  
13 1     1   634 use Time::Piece();
  1         9964  
  1         3734  
14              
15             # Field metods
16             sub force {
17 0     0 0 0 my $self = shift;
18 0 0       0 if (@_) {
19 0         0 $self->{force} = $_[0];
20 0         0 return $self;
21             }
22             else {
23 0         0 return $self->{force};
24             }
25             }
26              
27             sub class_name {
28 6     6 0 10 my $self = shift;
29 6 50       15 if (@_) {
30 0         0 $self->{class_name} = $_[0];
31 0         0 return $self;
32             }
33             else {
34 6         18 return $self->{class_name};
35             }
36             }
37              
38             sub output_dir {
39 4     4 0 7 my $self = shift;
40 4 100       8 if (@_) {
41 2         4 $self->{output_dir} = $_[0];
42 2         3 return $self;
43             }
44             else {
45 2         7 return $self->{output_dir};
46             }
47             }
48              
49             sub native {
50 2     2 0 4 my $self = shift;
51 2 50       6 if (@_) {
52 0         0 $self->{native} = $_[0];
53 0         0 return $self;
54             }
55             else {
56 2         4 return $self->{native};
57             }
58             }
59              
60             sub precompile {
61 0     0 0 0 my $self = shift;
62 0 0       0 if (@_) {
63 0         0 $self->{precompile} = $_[0];
64 0         0 return $self;
65             }
66             else {
67 0         0 return $self->{precompile};
68             }
69             }
70              
71             sub resource {
72 2     2 0 2 my $self = shift;
73 2 50       5 if (@_) {
74 0         0 $self->{resource} = $_[0];
75 0         0 return $self;
76             }
77             else {
78 2         4 return $self->{resource};
79             }
80             }
81              
82             sub interface {
83 0     0 0 0 my $self = shift;
84 0 0       0 if (@_) {
85 0         0 $self->{interface} = $_[0];
86 0         0 return $self;
87             }
88             else {
89 0         0 return $self->{interface};
90             }
91             }
92              
93             sub only_lib_files {
94 0     0 0 0 my $self = shift;
95 0 0       0 if (@_) {
96 0         0 $self->{only_lib_files} = $_[0];
97 0         0 return $self;
98             }
99             else {
100 0         0 return $self->{only_lib_files};
101             }
102             }
103              
104             sub no_pm_file {
105 0     0 0 0 my $self = shift;
106 0 0       0 if (@_) {
107 0         0 $self->{no_pm_file} = $_[0];
108 0         0 return $self;
109             }
110             else {
111 0         0 return $self->{no_pm_file};
112             }
113             }
114              
115             sub lib_dir {
116 0     0 0 0 my $self = shift;
117 0 0       0 if (@_) {
118 0         0 $self->{lib_dir} = $_[0];
119 0         0 return $self;
120             }
121             else {
122 0         0 return $self->{lib_dir};
123             }
124             }
125              
126             sub user_name {
127 0     0 0 0 my $self = shift;
128 0 0       0 if (@_) {
129 0         0 $self->{user_name} = $_[0];
130 0         0 return $self;
131             }
132             else {
133 0         0 return $self->{user_name};
134             }
135             }
136              
137             sub user_email {
138 0     0 0 0 my $self = shift;
139 0 0       0 if (@_) {
140 0         0 $self->{user_email} = $_[0];
141 0         0 return $self;
142             }
143             else {
144 0         0 return $self->{user_email};
145             }
146             }
147              
148             # Class methods
149             sub new {
150 2     2 0 1125 my $class = shift;
151            
152 2         7 my $self = {@_};
153            
154 2         5 bless $self, $class;
155              
156 2         6 my $basic_type_name = $self->class_name;
157 2 50       5 unless (defined $self->class_name) {
158 0         0 confess "A class name must be specified";
159             }
160            
161 2 50       5 if (defined $self->output_dir) {
162             # Remove tailing / or \
163 0         0 my $output_dir = $self->output_dir;
164 0         0 $output_dir =~ s|[/\\]$||;
165 0         0 $self->output_dir($output_dir);
166             }
167             else {
168 2         5 my $default_output_dir = "SPVM::$basic_type_name";
169 2         9 $default_output_dir =~ s/::/-/g;
170 2         5 $self->output_dir($default_output_dir);
171             }
172            
173 2         5 my $native = $self->native;
174 2 50 0     6 if (defined $native && !($native eq 'c' || $native eq 'c++')) {
      33        
175 0         0 confess "Can't support native \"$native\"";
176             }
177            
178 2         6 my $resource = $self->resource;
179 2 50 33     5 if ($resource && !defined $native) {
180 0         0 $self->native('c');
181             }
182            
183 2         7 return $self;
184             }
185              
186             # Instance methods
187             sub create_path {
188 0     0 0 0 my ($self, $file_base_name) = @_;
189            
190 0         0 my $output_dir = $self->output_dir;
191            
192 0         0 my $path;
193 0 0       0 if (defined $output_dir) {
194 0         0 $path = "$output_dir/$file_base_name";
195             }
196             else {
197 0         0 $path = $file_base_name;
198             }
199            
200 0         0 return $path;
201             }
202              
203             sub create_lib_rel_file {
204 0     0 0 0 my ($self, $file_base_name) = @_;
205            
206 0         0 my $lib_rel_file;
207            
208 0         0 my $only_lib_files = $self->only_lib_files;
209 0 0       0 if ($only_lib_files) {
210 0         0 $lib_rel_file = $file_base_name;
211             }
212             else {
213 0         0 $lib_rel_file = "lib/$file_base_name";
214             }
215            
216 0         0 return $lib_rel_file;
217             }
218              
219             sub generate_file {
220 0     0 0 0 my ($self, $rel_file, $content) = @_;
221            
222 0         0 my $file = $self->create_path($rel_file);
223 0         0 my $dir = dirname $file;
224            
225 0         0 $self->generate_dir($dir);
226            
227 0         0 my $force = $self->force;
228 0 0 0     0 if ($force || !-f $file) {
229 0         0 print " [write]$file\n";
230 0         0 SPVM::Builder::Util::spurt_binary($file, $content);
231             }
232             else {
233 0         0 print " [exists]$file\n";
234             }
235             }
236              
237             sub generate_dir {
238 0     0 0 0 my ($self, $rel_dir, $content) = @_;
239            
240 0         0 my @created = mkpath $rel_dir;
241 0 0       0 if (@created) {
242 0         0 print " [mkdir]$rel_dir\n";
243             }
244             }
245              
246             sub generate_spvm_class_file {
247 0     0 0 0 my ($self) = @_;
248            
249 0         0 my $basic_type_name = $self->class_name;
250            
251             # User name
252 0         0 my $user_name = $self->user_name;
253 0 0       0 unless (defined $user_name) {
254 0         0 $user_name = '[--user-name]'
255             }
256            
257             # Year
258 0         0 my $year = $self->_year;
259              
260 0         0 my $interface = $self->interface;
261            
262 0         0 my $attributes = "";
263 0 0       0 if ($interface) {
264 0         0 $attributes = ": interface_t ";
265             }
266              
267 0         0 my $version_decl = 'version "0.001";';
268            
269 0         0 my $only_lib_files = $self->only_lib_files;
270 0 0       0 if ($only_lib_files) {
271 0         0 $version_decl = '';
272             }
273            
274 0         0 my $spvm_class_content = <<"EOS";
275             # Copyright (c) $year $user_name
276             # MIT License
277              
278             class $basic_type_name ${attributes}{
279             $version_decl
280             }
281             EOS
282            
283             # Generate file
284 0         0 my $spvm_class_rel_file = SPVM::Builder::Util::convert_basic_type_name_to_rel_file($basic_type_name, 'spvm');
285 0         0 my $lib_dir = $self->lib_dir;
286 0         0 $spvm_class_rel_file = $self->create_lib_rel_file($spvm_class_rel_file);
287 0         0 $self->generate_file($spvm_class_rel_file, $spvm_class_content);
288             }
289              
290             sub generate_perl_class_file {
291 0     0 0 0 my ($self) = @_;
292            
293 0         0 my $basic_type_name = $self->class_name;
294            
295             # Year
296 0         0 my $year = $self->_year;
297            
298             # User name
299 0         0 my $user_name = $self->user_name;
300 0 0       0 unless (defined $user_name) {
301 0         0 $user_name = '[--user-name]'
302             }
303            
304             # User email
305 0         0 my $user_email = $self->user_email;
306 0 0       0 unless (defined $user_email) {
307 0         0 $user_email = '[--user-email]'
308             }
309              
310 0         0 my $interface = $self->interface;
311 0         0 my $resource = $self->resource;
312            
313             # Description
314 0         0 my $description;
315             my $main_doc;
316 0 0       0 if ($interface) {
    0          
317 0         0 $description = "$basic_type_name interface of L has interface methods for someting.";
318 0         0 $main_doc = <<"EOS";
319             =head1 Usage
320              
321             interface $basic_type_name;
322              
323             =head1 Interface Methods
324              
325              
326              
327             EOS
328             }
329             elsif ($resource) {
330 0         0 $description = "$basic_type_name resource of L is a L for someting.";
331            
332 0         0 my $native = $self->native;
333 0         0 my $new_method;
334 0 0       0 if ($native eq 'c') {
    0          
335 0         0 $new_method = 'new_gnu99';
336             }
337             elsif ($native eq 'c++') {
338 0         0 $new_method = 'new_cpp';
339             }
340            
341 0         0 my $native_module_ext;
342 0 0       0 if (defined $native) {
343 0 0       0 if ($native eq 'c') {
    0          
344 0         0 $native_module_ext = 'c';
345             }
346             elsif ($native eq 'c++') {
347 0         0 $native_module_ext = 'cpp';
348             }
349             }
350            
351             # extern C for C++
352 0         0 my $extern_c_start;
353             my $extern_c_end;
354 0 0       0 if ($native eq 'c++') {
355 0         0 $extern_c_start = qq(extern "C" {);
356 0         0 $extern_c_end = "}";
357             }
358             else {
359 0         0 $extern_c_start = '';
360 0         0 $extern_c_end = '';
361             }
362            
363 0         0 $main_doc = <<"EOS";
364             =head1 Usage
365              
366             MyClass.config:
367            
368             my \$config = SPVM::Builder::Config->$new_method(file => __FILE__);
369            
370             \$config->use_resource('$basic_type_name');
371            
372             \$config;
373              
374             MyClass.$native_module_ext:
375              
376             #include "spvm_native.h"
377             #include "foo.h"
378            
379             $extern_c_start
380            
381             int32_t SPVM__MyClass__test(SPVM_ENV* env, SPVM_VALUE* stack) {
382            
383             // Use functions in foo.h
384            
385             return 0;
386             }
387            
388             $extern_c_end
389            
390             =head1 Original Product
391              
392              
393              
394             =head1 Original Product Version
395              
396              
397              
398             =head1 Language
399              
400              
401              
402             =head1 Language Specification
403              
404              
405              
406             =head1 Required Libraries
407              
408              
409              
410             =head1 Required Linker Flags
411              
412              
413              
414             =head1 Required Resources
415              
416              
417              
418             =head1 Header Files
419              
420              
421              
422             =head1 Source Files
423              
424              
425              
426             =head1 Compiler Flags
427              
428              
429              
430             =head1 How to Create Resource
431              
432              
433              
434             =head2 Donwload
435              
436              
437              
438             =head2 Extracting Source Files
439              
440              
441              
442             =head2 Extracting Header Files
443              
444              
445              
446             EOS
447             }
448             else {
449 0         0 $description = "$basic_type_name class of L has methods for someting.";
450 0         0 $main_doc = <<"EOS";
451             =head1 Usage
452              
453             use $basic_type_name;
454              
455             =head1 Fields
456              
457              
458              
459             =head1 Class Methods
460              
461              
462              
463             =head1 Instance Methods
464              
465              
466              
467             EOS
468             }
469            
470 0         0 my $version_decl = 'our $VERSION = "0.001";';
471            
472 0         0 my $only_lib_files = $self->only_lib_files;
473 0 0       0 if ($only_lib_files) {
474 0         0 $version_decl = '';
475             }
476            
477             # Content
478 0         0 my $perl_class_content = "";
479 0         0 $perl_class_content = <<"EOS";
480             package SPVM::$basic_type_name;
481              
482             $version_decl
483              
484             1;
485              
486             =head1 Name
487              
488             SPVM::$basic_type_name - Short Description
489              
490             =head1 Description
491              
492             $description
493              
494             $main_doc
495             =head1 Repository
496              
497              
498              
499             =head1 Author
500              
501             $user_name C<$user_email>
502              
503             =head1 Copyright & License
504              
505             Copyright (c) $year $user_name
506              
507             MIT License
508              
509             EOS
510              
511             # Generate file
512 0         0 my $perl_class_rel_file = SPVM::Builder::Util::convert_basic_type_name_to_rel_file($basic_type_name, 'pm');
513 0         0 $perl_class_rel_file = $self->create_lib_rel_file($perl_class_rel_file);
514 0         0 $self->generate_file($perl_class_rel_file, $perl_class_content);
515             }
516              
517             sub generate_native_config_file {
518 0     0 0 0 my ($self) = @_;
519            
520 0         0 my $basic_type_name = $self->class_name;
521            
522             # C or C++
523 0         0 my $native = $self->native;
524 0         0 my $new_method;
525 0 0       0 if ($native eq 'c') {
    0          
526 0         0 $new_method = 'new_gnu99';
527             }
528             elsif ($native eq 'c++') {
529 0         0 $new_method = 'new_cpp';
530             }
531            
532             # User name
533 0         0 my $user_name = $self->user_name;
534 0 0       0 unless (defined $user_name) {
535 0         0 $user_name = '[--user-name]'
536             }
537            
538             # Year
539 0         0 my $year = $self->_year;
540            
541             # Content
542 0         0 my $native_config_content = <<"EOS";
543             # Copyright (c) $year $user_name
544             # MIT License
545              
546             use strict;
547             use warnings;
548             use SPVM::Builder::Config;
549              
550             my \$config = SPVM::Builder::Config->$new_method(file => __FILE__);
551              
552             \$config;
553             EOS
554              
555             # Generate file
556 0         0 my $native_config_rel_file = SPVM::Builder::Util::convert_basic_type_name_to_rel_file($basic_type_name, 'config');
557 0         0 $native_config_rel_file = $self->create_lib_rel_file($native_config_rel_file);
558 0         0 $self->generate_file($native_config_rel_file, $native_config_content);
559             }
560              
561             sub generate_native_class_file {
562 0     0 0 0 my ($self) = @_;
563              
564 0         0 my $basic_type_name = $self->class_name;
565            
566             # extern C for C++
567 0         0 my $native = $self->native;
568 0         0 my $extern_c_start;
569             my $extern_c_end;
570 0 0       0 if ($native eq 'c++') {
571 0         0 $extern_c_start = qq(extern "C" {);
572 0         0 $extern_c_end = "}";
573             }
574             else {
575 0         0 $extern_c_start = '';
576 0         0 $extern_c_end = '';
577             }
578              
579             # Generate file
580 0         0 my $native_module_ext;
581 0 0       0 if (defined $native) {
582 0 0       0 if ($native eq 'c') {
    0          
583 0         0 $native_module_ext = 'c';
584             }
585             elsif ($native eq 'c++') {
586 0         0 $native_module_ext = 'cpp';
587             }
588             }
589            
590             # Content
591 0         0 my $native_basic_type_name = $basic_type_name;
592 0         0 $native_basic_type_name =~ s/::/__/g;
593 0         0 my $native_class_file = $basic_type_name;
594 0         0 $native_class_file =~ s/::/\//g;
595 0         0 $native_class_file .= ".$native_module_ext";
596              
597             # User name
598 0         0 my $user_name = $self->user_name;
599 0 0       0 unless (defined $user_name) {
600 0         0 $user_name = '[--user-name]'
601             }
602            
603             # Year
604 0         0 my $year = $self->_year;
605            
606 0         0 my $native_class_content = <<"EOS";
607             // Copyright (c) $year $user_name
608             // MIT License
609              
610             #include "spvm_native.h"
611              
612             $extern_c_start
613              
614             static const char* FILE_NAME = "$native_class_file";
615              
616             int32_t SPVM__${native_basic_type_name}__foo(SPVM_ENV* env, SPVM_VALUE* stack) {
617            
618             return 0;
619             }
620              
621             $extern_c_end
622             EOS
623            
624 0         0 my $native_class_rel_file = SPVM::Builder::Util::convert_basic_type_name_to_rel_file($basic_type_name, $native_module_ext);
625 0         0 $native_class_rel_file = $self->create_lib_rel_file($native_class_rel_file);
626 0         0 $self->generate_file($native_class_rel_file, $native_class_content);
627             }
628              
629             sub generate_gitkeep_file_for_native_module_include_dir {
630 0     0 0 0 my ($self) = @_;
631              
632 0         0 my $basic_type_name = $self->class_name;
633            
634             # Generate file
635 0         0 my $gitkeep_rel_file_for_native_module_include_dir = SPVM::Builder::Util::convert_basic_type_name_to_rel_file($basic_type_name, 'native');
636 0         0 $gitkeep_rel_file_for_native_module_include_dir .= '/include/.gitkeep';
637 0         0 $gitkeep_rel_file_for_native_module_include_dir = $self->create_lib_rel_file($gitkeep_rel_file_for_native_module_include_dir);
638 0         0 $self->generate_file($gitkeep_rel_file_for_native_module_include_dir, '');
639             }
640              
641             sub generate_gitkeep_file_for_native_module_src_dir {
642 0     0 0 0 my ($self) = @_;
643              
644 0         0 my $basic_type_name = $self->class_name;
645            
646             # Generate file
647 0         0 my $gitkeep_rel_file_for_native_module_include_dir = SPVM::Builder::Util::convert_basic_type_name_to_rel_file($basic_type_name, 'native');
648 0         0 $gitkeep_rel_file_for_native_module_include_dir .= '/src/.gitkeep';
649 0         0 $gitkeep_rel_file_for_native_module_include_dir = $self->create_lib_rel_file($gitkeep_rel_file_for_native_module_include_dir);
650 0         0 $self->generate_file($gitkeep_rel_file_for_native_module_include_dir, '');
651             }
652              
653             sub generate_gitignore_file {
654 0     0 0 0 my ($self) = @_;
655            
656 0         0 my $gitignore_content = <<'EOS';
657             /blib/*
658             /Makefile
659             /Makefile.old
660             /MYMETA.yml
661             /MYMETA.json
662             /pm_to_blib
663             /SPVM-*
664             .spvm_build
665             core.*
666             core
667             *.bak
668             *.BAK
669             *.tmp
670             *.o
671             *.bs
672             EOS
673            
674             # Generate file
675 0         0 my $gitignore_rel_file = '.gitignore';
676 0         0 $self->generate_file($gitignore_rel_file, $gitignore_content);
677             }
678              
679             sub generate_manifest_skip_file {
680 0     0 0 0 my ($self) = @_;
681            
682             # Content
683 0         0 my $manifest_skip_content = <<'EOS';
684             (^|\/)blib/
685             (^|\/)Makefile$
686             (^|\/)Makefile.old$
687             (^|\/)MYMETA.yml$
688             (^|\/)MYMETA.json$
689             (^|\/)pm_to_blib$
690             (^|\/).spvm_build/
691             (^|\/)t/.spvm_build/
692             (^|\/)SPVM-
693             (^|\/)core\.
694             (^|\/)core$
695             (^|\/)\.git/
696             \.bak$
697             \.tmp$
698             \.tmp/
699             \.BAK$
700             \.o$
701             \.bs$
702             EOS
703              
704             # Generate file
705 0         0 my $manifest_skip_rel_file = 'MANIFEST.SKIP';
706 0         0 $self->generate_file($manifest_skip_rel_file, $manifest_skip_content);
707             }
708              
709             sub generate_changes_file {
710 0     0 0 0 my ($self) = @_;
711              
712             # Year
713 0         0 my $today_tp = Time::Piece::localtime;
714 0         0 my $today = $today_tp->strftime('%Y-%m-%d');
715            
716             # Content
717 0         0 my $changes_content = <<"EOS";
718             0.01 $today
719             [Changes]
720             * First release.
721            
722             EOS
723              
724             # Generate file
725 0         0 my $changes_rel_file = 'Changes';
726 0         0 $self->generate_file($changes_rel_file, $changes_content);
727             }
728              
729              
730             sub generate_readme_markdown_file {
731 0     0 0 0 my ($self) = @_;
732            
733 0         0 my $basic_type_name = $self->class_name;
734            
735             # Content
736 0         0 my $readme_markdown_content = <<"EOS";
737             # SPVM::$basic_type_name
738              
739             SPVM::$basic_type_name
740              
741             EOS
742            
743             # Generate file
744 0         0 my $readme_markdown_rel_file = 'README.md';
745 0         0 $self->generate_file($readme_markdown_rel_file, $readme_markdown_content);
746             }
747              
748             sub generate_makefile_pl_file {
749 0     0 0 0 my ($self) = @_;
750            
751 0         0 my $basic_type_name = $self->class_name;
752            
753             # Resource
754 0         0 my $resource = $self->resource;
755            
756             # Native make rule
757 0 0 0     0 my $make_rule_native = $self->native && !$resource ? "\$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('$basic_type_name');" : '';
758            
759             # Precompile make rule
760 0 0 0     0 my $make_rule_precompile = $self->precompile && !$resource ? "\$make_rule .= SPVM::Builder::Util::API::create_make_rule_precompile('$basic_type_name');" : '';
761              
762 0         0 my $perl_class_rel_file = SPVM::Builder::Util::convert_basic_type_name_to_rel_file($basic_type_name, 'pm');
763 0         0 $perl_class_rel_file = $self->create_lib_rel_file($perl_class_rel_file);
764              
765 0         0 my $spvm_class_rel_file = SPVM::Builder::Util::convert_basic_type_name_to_rel_file($basic_type_name, 'spvm');
766 0         0 $spvm_class_rel_file = $self->create_lib_rel_file($spvm_class_rel_file);
767            
768             # User name
769 0         0 my $user_name = $self->user_name;
770 0 0       0 unless (defined $user_name) {
771 0         0 $user_name = '[--user-name]'
772             }
773            
774             # User email
775 0         0 my $user_email = $self->user_email;
776 0 0       0 unless (defined $user_email) {
777 0         0 $user_email = '[--user-email]'
778             }
779            
780             # "Makefile.PL" content
781 0         0 my $makefile_pl_content = <<"EOS";
782             use 5.008_007;
783             use ExtUtils::MakeMaker;
784             use strict;
785             use warnings;
786             use Config;
787             use Getopt::Long 'GetOptions';
788              
789             GetOptions(
790             'meta' => \\my \$meta,
791             'no-build-spvm-modules' => \\my \$no_build_spvm_modules,
792             );
793              
794             if (\$meta) {
795             \$no_build_spvm_modules = 1;
796             }
797              
798             unless (\$meta) {
799             # Do something such as environment check.
800             }
801              
802             my \%configure_and_runtime_requires = ('SPVM' => '$SPVM::VERSION');
803             WriteMakefile(
804             NAME => 'SPVM::$basic_type_name',
805             VERSION_FROM => '$perl_class_rel_file',
806             LICENSE => 'mit',
807             (\$] >= 5.005 ?
808             (ABSTRACT_FROM => '$perl_class_rel_file',
809             AUTHOR => '$user_name<$user_email>') : ()),
810             test => {TESTS => 't/*.t t/*/*.t t/*/*/*.t'},
811             clean => {FILES => ['.spvm_build', 't/.spvm_build']},
812             META_MERGE => {
813             'meta-spec' => { version => 2 },
814             resources => {
815             repository => {
816             type => 'git',
817             url => '',
818             web => '',
819             },
820             },
821             no_index => {
822             directory => [],
823             }
824             },
825             NORECURS => 1,
826             CONFIGURE_REQUIRES => {
827             \%configure_and_runtime_requires,
828             },
829             PREREQ_PM => {
830             \%configure_and_runtime_requires,
831             },
832             TEST_REQUIRES => {
833            
834             },
835             );
836              
837             sub MY::postamble {
838              
839             my \$make_rule = '';
840            
841             unless (\$no_build_spvm_modules) {
842             require SPVM::Builder::Util::API;
843            
844             $make_rule_native
845             $make_rule_precompile
846             }
847            
848             return \$make_rule;
849             }
850              
851             1;
852             EOS
853              
854             # Generate file
855 0         0 my $makefile_pl_rel_file = 'Makefile.PL';
856 0         0 $self->generate_file($makefile_pl_rel_file, $makefile_pl_content);
857             }
858              
859             sub generate_basic_test_file {
860 0     0 0 0 my ($self) = @_;
861            
862 0         0 my $basic_type_name = $self->class_name;
863            
864 0         0 my $spvm_class_rel_file = SPVM::Builder::Util::convert_basic_type_name_to_rel_file($basic_type_name, 'spvm');
865 0         0 $spvm_class_rel_file = $self->create_lib_rel_file($spvm_class_rel_file);
866            
867             # Content
868 0         0 my $basic_test_content = <<"EOS";
869             use Test::More;
870              
871             use strict;
872             use warnings;
873             use FindBin;
874             use lib "\$FindBin::Bin/lib";
875             BEGIN { \$ENV{SPVM_BUILD_DIR} = "\$FindBin::Bin/.spvm_build"; }
876              
877             use SPVM 'TestCase::$basic_type_name';
878              
879             use SPVM '$basic_type_name';
880             use SPVM::$basic_type_name;
881             use SPVM 'Fn';
882              
883             ok(SPVM::TestCase::$basic_type_name->test);
884              
885             # Version
886             {
887             my \$version_string = SPVM::Fn->get_version_string("$basic_type_name");
888             is(\$SPVM::${basic_type_name}::VERSION, \$version_string);
889             }
890              
891             done_testing;
892             EOS
893            
894             # Generate file
895 0         0 my $basic_test_rel_file = 't/basic.t';
896 0         0 $self->generate_file($basic_test_rel_file, $basic_test_content);
897             }
898              
899             sub generate_license_file {
900 0     0 0 0 my ($self) = @_;
901            
902 0         0 my $basic_type_name = $self->class_name;
903            
904             # User name
905 0         0 my $user_name = $self->user_name;
906 0 0       0 unless (defined $user_name) {
907 0         0 $user_name = '[--user-name]'
908             }
909            
910             # Year
911 0         0 my $year = $self->_year;
912            
913             # Content
914 0         0 my $license_content = <<"EOS";
915             MIT License
916              
917             Copyright (c) $year $user_name
918              
919             Permission is hereby granted, free of charge, to any person obtaining a copy
920             of this software and associated documentation files (the "Software"), to deal
921             in the Software without restriction, including without limitation the rights
922             to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
923             copies of the Software, and to permit persons to whom the Software is
924             furnished to do so, subject to the following conditions:
925              
926             The above copyright notice and this permission notice shall be included in all
927             copies or substantial portions of the Software.
928              
929             THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
930             IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
931             FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
932             AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
933             LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
934             OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
935             SOFTWARE.
936             EOS
937            
938             # Generate file
939 0         0 my $license_rel_file = 'LICENSE';
940 0         0 $self->generate_file($license_rel_file, $license_content);
941             }
942              
943             sub generate_basic_test_spvm_class_file {
944 0     0 0 0 my ($self) = @_;
945            
946 0         0 my $basic_type_name = $self->class_name;
947            
948             # Resource
949 0         0 my $resource = $self->resource;
950            
951             # Content
952 0         0 my $basic_test_spvm_class_content;
953            
954 0 0       0 if ($resource) {
955 0         0 $basic_test_spvm_class_content = <<"EOS";
956             class TestCase::$basic_type_name {
957             native static method test : int ();
958             }
959             EOS
960             }
961             else {
962 0         0 $basic_test_spvm_class_content = <<"EOS";
963             class TestCase::$basic_type_name {
964             use $basic_type_name;
965             static method test : int () {
966            
967             return 1;
968             }
969             }
970             EOS
971             }
972            
973             # Generate file
974 0         0 my $basic_test_spvm_class_rel_file = SPVM::Builder::Util::convert_basic_type_name_to_rel_file("TestCase::$basic_type_name", 'spvm');
975 0         0 $basic_test_spvm_class_rel_file = "t/lib/$basic_test_spvm_class_rel_file";
976 0         0 $self->generate_file($basic_test_spvm_class_rel_file, $basic_test_spvm_class_content);
977             }
978              
979             sub generate_basic_test_native_config_file {
980 0     0 0 0 my ($self) = @_;
981            
982 0         0 my $basic_type_name = $self->class_name;
983            
984             # Resource
985 0         0 my $resource = $self->resource;
986              
987             # C or C++
988 0         0 my $native = $self->native;
989 0         0 my $new_method;
990 0 0       0 if ($native eq 'c') {
    0          
991 0         0 $new_method = 'new_gnu99';
992             }
993             elsif ($native eq 'c++') {
994 0         0 $new_method = 'new_cpp';
995             }
996            
997             # Content
998 0         0 my $basic_test_native_config_content = <<"EOS";
999             use strict;
1000             use warnings;
1001              
1002             my \$config = SPVM::Builder::Config->$new_method(file => __FILE__);
1003              
1004             \$config->use_resource('$basic_type_name');
1005              
1006             \$config;
1007             EOS
1008            
1009             # Generate file
1010 0         0 my $basic_test_native_config_rel_file = SPVM::Builder::Util::convert_basic_type_name_to_rel_file("TestCase::$basic_type_name", 'config');
1011 0         0 $basic_test_native_config_rel_file = "t/lib/$basic_test_native_config_rel_file";
1012 0         0 $self->generate_file($basic_test_native_config_rel_file, $basic_test_native_config_content);
1013             }
1014              
1015             sub generate_basic_test_native_class_file {
1016 0     0 0 0 my ($self) = @_;
1017            
1018 0         0 my $basic_type_name = $self->class_name;
1019            
1020             # Resource
1021 0         0 my $resource = $self->resource;
1022              
1023             # extern C for C++
1024 0         0 my $native = $self->native;
1025 0         0 my $extern_c_start;
1026             my $extern_c_end;
1027 0 0       0 if ($native eq 'c++') {
1028 0         0 $extern_c_start = qq(extern "C" {);
1029 0         0 $extern_c_end = "}";
1030             }
1031             else {
1032 0         0 $extern_c_start = '';
1033 0         0 $extern_c_end = '';
1034             }
1035            
1036             # Content
1037 0         0 my $native_basic_type_name = $basic_type_name;
1038 0         0 $native_basic_type_name =~ s/::/__/g;
1039 0         0 my $basic_test_native_class_content = <<"EOS";
1040             #include "spvm_native.h"
1041              
1042             $extern_c_start
1043              
1044             int32_t SPVM__TestCase__${native_basic_type_name}__test(SPVM_ENV* env, SPVM_VALUE* stack) {
1045            
1046             stack[0].ival = 1;
1047            
1048             return 0;
1049             }
1050              
1051             $extern_c_end
1052             EOS
1053            
1054             # Generate file
1055 0         0 my $native_module_ext;
1056 0 0       0 if (defined $native) {
1057 0 0       0 if ($native eq 'c') {
    0          
1058 0         0 $native_module_ext = 'c';
1059             }
1060             elsif ($native eq 'c++') {
1061 0         0 $native_module_ext = 'cpp';
1062             }
1063             }
1064 0         0 my $basic_test_native_class_rel_file = SPVM::Builder::Util::convert_basic_type_name_to_rel_file("TestCase::$basic_type_name", $native_module_ext);
1065 0         0 $basic_test_native_class_rel_file = "t/lib/$basic_test_native_class_rel_file";
1066 0         0 $self->generate_file($basic_test_native_class_rel_file, $basic_test_native_class_content);
1067             }
1068              
1069             sub generate_dist {
1070 2     2 0 14 my ($self) = @_;
1071            
1072 2         4 my $basic_type_name = $self->class_name;
1073            
1074 2 100       21 unless (length $basic_type_name) {
1075 1         252 confess "The class name must be specified";
1076             }
1077            
1078 1 50       14 if ($basic_type_name =~ /-/) {
1079 1         111 confess "The class name cannnot contain \"-\"";
1080             }
1081            
1082 0           my $native = $self->native;
1083 0           my $interface = $self->interface;
1084 0           my $resource = $self->resource;
1085            
1086 0 0 0       if ($interface && $resource) {
1087 0           die "The --interface option and the --resource option cannot be specified at the same time"
1088             }
1089            
1090 0           my $basic_type_name_rel_file = $basic_type_name;
1091 0           $basic_type_name_rel_file =~ s|::|/|g;
1092            
1093             # Generate output directory
1094 0           my $output_dir = $self->output_dir;
1095 0           $self->generate_dir($output_dir);
1096            
1097             # Generate SPVM class file
1098 0           $self->generate_spvm_class_file;
1099            
1100             # Generate Perl class file
1101 0           my $no_pm_file = $self->no_pm_file;
1102 0 0         unless ($no_pm_file) {
1103 0           $self->generate_perl_class_file;
1104             }
1105            
1106 0 0         if ($native) {
1107             # Generate native config file
1108 0           $self->generate_native_config_file;
1109            
1110             # Generate native class file
1111 0 0         unless ($resource) {
1112 0           $self->generate_native_class_file;
1113             }
1114            
1115             # Generate ".gitkeep" file for native class include directory
1116 0           $self->generate_gitkeep_file_for_native_module_include_dir;
1117            
1118             # Generate ".gitkeep" file for native class src directory
1119 0           $self->generate_gitkeep_file_for_native_module_src_dir;
1120             }
1121            
1122 0           my $only_lib_files = $self->only_lib_files;
1123 0 0         unless ($only_lib_files) {
1124             # Generate .gitignore file
1125 0           $self->generate_gitignore_file;
1126            
1127             # Generate MANIFEST.SKIP file
1128 0           $self->generate_manifest_skip_file;
1129            
1130             # Generate Changes file
1131 0           $self->generate_changes_file;
1132            
1133             # Generate README.md file
1134 0           $self->generate_readme_markdown_file;
1135            
1136             # Generate Makefile.PL file
1137 0           $self->generate_makefile_pl_file;
1138            
1139             # Generate t/basic.t file
1140 0           $self->generate_basic_test_file;
1141              
1142             # Generate basic test SPVM class file
1143 0           $self->generate_basic_test_spvm_class_file;
1144              
1145             # Generate license file
1146 0           $self->generate_license_file;
1147            
1148 0 0         if ($resource) {
1149             # Generate basic test native class file
1150 0           $self->generate_basic_test_native_class_file;
1151              
1152             # Generate basic test native config file
1153 0           $self->generate_basic_test_native_config_file;
1154             }
1155             }
1156             }
1157              
1158             sub _year {
1159 0     0     my ($self) = @_;
1160            
1161             # Year
1162 0           my $today_tp = Time::Piece::localtime;
1163 0           my $year = $today_tp->year;
1164            
1165 0           return $year;
1166             }
1167              
1168             1;
1169              
1170             =head1 Name
1171              
1172             SPVM::Dist - Generating SPVM Distrubution
1173              
1174             =head2 Description
1175              
1176             The SPVM::Dist class has methods to generate a SPVM Distrubution.
1177              
1178             =head2 Usage
1179              
1180             my $dist = SPVM::Dist->new(
1181             class_name => 'Math',
1182             );
1183            
1184             $dist->generate_dist;
1185              
1186             =head1 Copyright & License
1187              
1188             Copyright (c) 2023 Yuki Kimoto
1189              
1190             MIT License