#!/usr/bin/perl
package MooseX::Compile::CLI::Command::compile;
use Moose;
use Path::Class;
extends qw(
MooseX::Compile::Base
MooseX::Compile::CLI::Base
);
has compiler_class => (
documentation => "The compiler class to use",
isa => "Str",
is => "rw",
default => "MooseX::Compile::Compiler",
);
has compiler_args => (
documentation => "Additional arguments for the compiler",
isa => "ArrayRef",
is => "rw",
auto_deref => 1,
default => sub { [] },
);
has compiler => (
metaclass => "NoGetopt",
isa => "Object",
is => "rw",
lazy_build => 1,
);
has target_lib => (
documentation => "If supplied .pmcs will be written to this lib directory, instead of next to where the original .pm files are",
metaclass => "Getopt",
cmd_aliases => ["C"],
isa => "Str",
is => "rw",
);
sub _build_compiler {
my $self = shift;
my $class = $self->compiler_class;
$self->load_classes( $class );
$class->new( $self->compiler_args );
};
augment run => sub {
my ( $self, $opts, $args ) = @_;
$self->compile_all_classes;
};
augment build_from_opts => sub {
};
sub compile_all_classes {
my $self = shift;
$self->compile_classes( $self->all_files );
}
sub compile_classes {
my ( $self, @files ) = @_;
my %seen_out;
file: foreach my $file ( @files ) {
if ( my $seen = $seen_out{$file->{pmc_file}} ) {
warn "Class '$file->{class}' found in '$seen->{dir}' was already compiled into '$file->{pmc_file}', skipping the version in '$file->{dir}'\n" if $self->verbose;
next file;
} else {
$seen_out{$file->{pmc_file}} = $file;
}
$self->compile_class($file);
}
}
sub compile_class {
my ( $self, $file ) = @_;
# FIXME use $^X and a simpler compilation command?
if ( my $pid = fork ) { # clean env to load the module in
waitpid $pid, 0;
} else {
warn "Compiling class '$file->{class}'\n" if $self->verbose;
if ( eval {
local @INC = ( "$file->{dir}", @INC );
require $file->{rel};
} ) {
if ( eval { $file->{class}->meta->isa("Moose::Meta::Class") } ) {
$self->compiler->compile_class( %$file );
warn "Compiled '$file->{class}' from '$file->{dir}' into " . $file->{pmc_file}->relative($file->{dir}) . "\n";
} else {
warn "Skipping $file->{class}, it's not a Moose class\n" if $self->verbose;
}
} else {
my $f = quotemeta(__FILE__);
( my $e = $@ ) =~ s/ at $f line \d+\.\n$/./s;
warn "Loading of file '$file->{rel}' from '$file->{dir}' failed: $e\n";
}
exit;
}
}
sub filter_file {
my ( $self, $file ) = @_;
return $file if $file->basename =~ m/\.pm$/ and -f $file;
return;
}
override file_in_dir => sub {
my ( $self, %args ) = @_;
my $entry = super();
my ( $rel, $dir ) = @{ $entry }{qw(rel dir)};
$entry->{pmc_file} = file( "${rel}c" )->absolute( dir( $self->target_lib || $dir ) );
return $entry;
};
__PACKAGE__
__END__
=pod
=head1 NAME
MooseX::Compile::CLI::Command::compile - Compile Moose classes using MooseX::Compile::Compiler.
=head1 SYNOPSIS
# compile My::Class in lib/
> mxcompile compile -l My::Class
=head1 DESCRIPTION
This command is used to compile classes using L<MooseX::Compile::Compiler>.
=cut