Updated makefile template
[catagits/Catalyst-Runtime.git] / lib / Module / Install / Catalyst.pm
1 package Module::Install::Catalyst;
2
3 use strict;
4
5 our @ISA;
6 require Module::Install::Base;
7 @ISA = qw/Module::Install::Base/;
8
9 use File::Find;
10 use FindBin;
11 use File::Copy::Recursive 'rcopy';
12 use File::Spec ();
13
14 our @IGNORE =
15   qw/Build Build.PL Changes MANIFEST META.yml Makefile.PL Makefile README
16   _build blib lib script t inc/;
17 our @CLASSES   = ();
18 our $ENGINE    = 'CGI';
19 our $CORE      = 0;
20 our $MULTIARCH = 0;
21 our $SCRIPT;
22 our $USAGE;
23
24 =head1 NAME
25
26 Module::Install::Catalyst - Module::Install extension for Catalyst
27
28 =head1 SYNOPSIS
29
30 See L<Catalyst>
31
32 =head1 DESCRIPTION
33
34 L<Module::Install> extension for Catalyst.
35
36 =head1 METHODS
37
38 =head2 catalyst
39
40 =cut
41
42 sub catalyst {
43     my $self = shift;
44     $self->catalyst_files;
45     $self->catalyst_par;
46 }
47
48 =head2 catalyst_files
49
50 =cut
51
52 sub catalyst_files {
53     my $self = shift;
54
55     chdir $FindBin::Bin;
56
57     my @files;
58     opendir CATDIR, '.';
59   CATFILES: for my $name ( readdir CATDIR ) {
60         for my $ignore (@IGNORE) {
61             next CATFILES if $name =~ /^$ignore$/;
62             next CATFILES if $name !~ /\w/;
63         }
64         push @files, $name;
65     }
66     closedir CATDIR;
67     my @path = split '-', $self->name;
68     for my $orig (@files) {
69         my $path = File::Spec->catdir( 'blib', 'lib', @path, $orig );
70         rcopy( $orig, $path );
71     }
72 }
73
74 =head2 catalyst_ignore_all(\@ignore)
75
76 =cut
77
78 sub catalyst_ignore_all {
79     my ( $self, $ignore ) = @_;
80     @IGNORE = @$ignore;
81 }
82
83 =head2 catalyst_ignore(\@ignore)
84
85 =cut
86
87 sub catalyst_ignore {
88     my ( $self, @ignore ) = @_;
89     push @IGNORE, @ignore;
90 }
91
92 =head2 catalyst_par($name)
93
94 =cut
95
96 # Workaround for a namespace conflict
97 sub catalyst_par {
98     my ( $self, $par ) = @_;
99     print <<EOF;
100 *** Module::Install::Catalyst
101 EOF
102     my $name  = $self->name;
103     my $usage = $USAGE;
104     $usage =~ s/"/\\"/g;
105     my $class_string = join "', '", @CLASSES;
106     $class_string = "'$class_string'" if $class_string;
107     $self->postamble(<<EOF);
108 catalyst_par :: all
109 \t\$(NOECHO) \$(PERL) -Ilib -Minc::Module::Install -MModule::Install::Catalyst -e"Catalyst::Module::Install::_catalyst_par( '$par', '$name', { CLASSES => [$class_string], CORE => $CORE, ENGINE => '$ENGINE', MULTIARCH => $MULTIARCH, SCRIPT => '$SCRIPT', USAGE => q#$usage# } )"
110 EOF
111     print <<EOF;
112 Please run "make catalyst_par" to create the PAR package!
113 *** Module::Install::Catalyst finished.
114 EOF
115 }
116
117 =head2 catalyst_par_core($core)
118
119 =cut
120
121 sub catalyst_par_core {
122     my ( $self, $core ) = @_;
123     $core ? ( $CORE = $core ) : $CORE++;
124 }
125
126 =head2 catalyst_par_classes(@clases)
127
128 =cut
129
130 sub catalyst_par_classes {
131     my ( $self, @classes ) = @_;
132     push @CLASSES, @classes;
133 }
134
135 =head2 catalyst_par_engine($engine)
136
137 =cut
138
139 sub catalyst_par_engine {
140     my ( $self, $engine ) = @_;
141     $ENGINE = $engine;
142 }
143
144 =head2 catalyst_par_multiarch($multiarch)
145
146 =cut
147
148 sub catalyst_par_multiarch {
149     my ( $self, $multiarch ) = @_;
150     $multiarch ? ( $MULTIARCH = $multiarch ) : $MULTIARCH++;
151 }
152
153 =head2 catalyst_par_script($script)
154
155 =cut
156
157 sub catalyst_par_script {
158     my ( $self, $script ) = @_;
159     $SCRIPT = $script;
160 }
161
162 =head2 catalyst_par_usage($usage)
163
164 =cut
165
166 sub catalyst_par_usage {
167     my ( $self, $usage ) = @_;
168     $USAGE = $usage;
169 }
170
171 package Catalyst::Module::Install;
172
173 use strict;
174 use FindBin;
175 use File::Copy::Recursive 'rmove';
176 use File::Spec ();
177
178 sub _catalyst_par {
179     my ( $par, $class_name, $opts ) = @_;
180
181     my $ENGINE    = $opts->{ENGINE};
182     my $CLASSES   = $opts->{CLASSES} || [];
183     my $USAGE     = $opts->{USAGE};
184     my $SCRIPT    = $opts->{SCRIPT};
185     my $MULTIARCH = $opts->{MULTIARCH};
186     my $CORE      = $opts->{CORE};
187
188     my $name = $class_name;
189     $name =~ s/::/_/g;
190     $name = lc $name;
191     $par ||= "$name.par";
192     my $engine = $ENGINE || 'CGI';
193
194     # Check for PAR
195     eval "use PAR ()";
196     die "Please install PAR\n" if $@;
197     eval "use PAR::Packer ()";
198     die "Please install PAR::Packer\n" if $@;
199     eval "use App::Packer::PAR ()";
200     die "Please install App::Packer::PAR\n" if $@;
201     eval "use Module::ScanDeps ()";
202     die "Please install Module::ScanDeps\n" if $@;
203
204     my $root = $FindBin::Bin;
205     my $path = File::Spec->catfile( 'blib', 'lib', split( '::', $class_name ) );
206     $path .= '.pm';
207     unless ( -f $path ) {
208         print qq/Not writing PAR, "$path" doesn't exist\n/;
209         return 0;
210     }
211     print qq/Writing PAR "$par"\n/;
212     chdir File::Spec->catdir( $root, 'blib' );
213
214     my $par_pl = 'par.pl';
215     unlink $par_pl;
216
217     my $version = $Catalyst::VERSION;
218     my $class   = $class_name;
219
220     my $classes = '';
221     $classes .= "    require $_;\n" for @$CLASSES;
222
223     unlink $par_pl;
224
225     my $usage = $USAGE || <<"EOF";
226 Usage:
227     [parl] $name\[.par] [script] [arguments]
228
229   Examples:
230     parl $name.par $name\_server.pl -r
231     myapp $name\_cgi.pl
232 EOF
233
234     my $script   = $SCRIPT;
235     my $tmp_file = IO::File->new("> $par_pl ");
236     print $tmp_file <<"EOF";
237 if ( \$ENV{PAR_PROGNAME} ) {
238     my \$zip = \$PAR::LibCache{\$ENV{PAR_PROGNAME}}
239         || Archive::Zip->new(__FILE__);
240     my \$script = '$script';
241     \$ARGV[0] ||= \$script if \$script;
242     if ( ( \@ARGV == 0 ) || ( \$ARGV[0] eq '-h' ) || ( \$ARGV[0] eq '-help' )) {
243         my \@members = \$zip->membersMatching('.*script/.*\.pl');
244         my \$list = "  Available scripts:\\n";
245         for my \$member ( \@members ) {
246             my \$name = \$member->fileName;
247             \$name =~ /(\\w+\\.pl)\$/;
248             \$name = \$1;
249             next if \$name =~ /^main\.pl\$/;
250             next if \$name =~ /^par\.pl\$/;
251             \$list .= "    \$name\\n";
252         }
253         die <<"END";
254 $usage
255 \$list
256 END
257     }
258     my \$file = shift \@ARGV;
259     \$file =~ s/^.*[\\/\\\\]//;
260     \$file =~ s/\\.[^.]*\$//i;
261     my \$member = eval { \$zip->memberNamed("./script/\$file.pl") };
262     die qq/Can't open perl script "\$file"\n/ unless \$member;
263     PAR::_run_member( \$member, 1 );
264 }
265 else {
266     require lib;
267     import lib 'lib';
268     \$ENV{CATALYST_ENGINE} = '$engine';
269     require $class;
270     import $class;
271     require Catalyst::Helper;
272     require Catalyst::Test;
273     require Catalyst::Engine::HTTP;
274     require Catalyst::Engine::CGI;
275     require Catalyst::Controller;
276     require Catalyst::Model;
277     require Catalyst::View;
278     require Getopt::Long;
279     require Pod::Usage;
280     require Pod::Text;
281     $classes
282 }
283 EOF
284     $tmp_file->close;
285
286     # Create package
287     local $SIG{__WARN__} = sub { };
288     open my $olderr, '>&STDERR';
289     open STDERR, '>', File::Spec->devnull;
290     my %opt = (
291         'x' => 1,
292         'n' => 0,
293         'o' => $par,
294         'a' => [ grep( !/par.pl/, glob '.' ) ],
295         'p' => 1,
296         'B' => $CORE,
297         'm' => $MULTIARCH
298     );
299     App::Packer::PAR->new(
300         frontend  => 'Module::ScanDeps',
301         backend   => 'PAR::Packer',
302         frontopts => \%opt,
303         backopts  => \%opt,
304         args      => ['par.pl'],
305     )->go;
306
307     open STDERR, '>&', $olderr;
308
309     unlink $par_pl;
310     chdir $root;
311     rmove( File::Spec->catfile( 'blib', $par ), $par );
312     return 1;
313 }
314
315 =head1 AUTHOR
316
317 Sebastian Riedel, C<sri@oook.de>
318
319 =head1 LICENSE
320
321 This library is free software, you can redistribute it and/or modify it under
322 the same terms as Perl itself.
323
324 =cut
325
326 1;