Skip to content

Commit ee88ab5

Browse files
committed
Split off L::B::Compile from L::B::Build
1 parent e7d7209 commit ee88ab5

File tree

4 files changed

+180
-155
lines changed

4 files changed

+180
-155
lines changed

MANIFEST

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ examples/game.C
99
inc/Library/Build.pm
1010
inc/Library/Build/Author.pm
1111
inc/Library/Build/Build.pm
12+
inc/Library/Build/Compile.pm
1213
inc/Library/Build/Config.pm
1314
inc/Library/Build/Install.pm
1415
inc/Library/Build/PL.pm

inc/Library/Build/Build.pm

+2-154
Original file line numberDiff line numberDiff line change
@@ -9,93 +9,10 @@ our $VERSION = '0.003';
99
use Carp 'croak';
1010
use Config;
1111
use File::Basename qw/basename dirname/;
12-
use File::Spec::Functions qw/catfile catdir splitdir/;
12+
use File::Spec::Functions qw/catfile splitdir/;
1313
use Pod::Man;
1414

15-
my $compiler = $Config{cc} eq 'cl' ? 'msvc' : 'gcc';
16-
17-
sub _compiler_flags {
18-
return ($compiler eq 'gcc') ? [ qw/--std=gnu++0x -ggdb3 -DDEBUG -Wall -Wshadow -Wnon-virtual-dtor -Wsign-promo -Wextra -Winvalid-pch/ ] :
19-
($compiler eq 'msvc') ? [ qw{/TP /EHsc /Wall} ] :
20-
[];
21-
}
22-
23-
sub _get_input_files {
24-
my ($input_files, $input_dir) = @_;
25-
if ($input_files) {
26-
if (ref $input_files) {
27-
return @{$input_files};
28-
}
29-
else {
30-
return $input_files;
31-
}
32-
}
33-
elsif ($input_dir) {
34-
opendir my ($dh), $input_dir or croak "Can't open input directory '$input_dir': $!";
35-
my @ret = grep { /^ .+ \. C $/xsm } readdir $dh;
36-
closedir $dh;
37-
return @ret;
38-
}
39-
croak 'Can\'t establish source files';
40-
}
41-
42-
sub _linker_flags {
43-
my ($libs, $libdirs, %options) = @_;
44-
my @elements;
45-
if ($compiler eq 'gcc') {
46-
push @elements, map { "-l$_" } @{$libs};
47-
push @elements, map { "-L$_" } @{$libdirs};
48-
if ($options{'C++'}) {
49-
push @elements, '-lstdc++';
50-
}
51-
}
52-
elsif ($compiler eq 'msvc') {
53-
push @elements, map { "$_.dll" } @{$libs};
54-
push @elements, map { qq{-libpath:"$_"} } @{$libdirs};
55-
if ($options{'C++'}) {
56-
push @elements, 'msvcprt.lib';
57-
}
58-
}
59-
push @elements, $options{append} if defined $options{append};
60-
return join ' ', @elements;
61-
}
62-
63-
*my_system = $^O eq 'MSWin32'
64-
? sub {
65-
my ($self, $exec, $input, $output) = @_;
66-
my $call = join ' ', @{$exec}, $input, '>', $output;
67-
print "$call\n" if $self->stash('verbose') >= 0;
68-
system $call and croak "Couldn't call system(): $!";
69-
return;
70-
}
71-
: sub {
72-
my ($self, $exec, $input, $output) = @_;
73-
my @call = (@{$exec}, $input);
74-
print "@call > $output\n" if $self->stash('verbose') >= 0;
75-
my $pid = fork;
76-
if ($pid) {
77-
waitpid $pid, 0;
78-
}
79-
else {
80-
open STDOUT, '>', $output or croak "Can't write to file '$output': $!";
81-
exec @call or croak "Couldn't exec: $!";
82-
}
83-
return;
84-
};
85-
8615
my %build_methods = (
87-
cbuilder => sub {
88-
my $self = shift;
89-
require ExtUtils::CBuilder;
90-
return $self->{builder} ||= ExtUtils::CBuilder->new(quiet => $self->stash('verbose') < 0)
91-
},
92-
create_by_system => sub {
93-
my ($self, $exec, $input, $output) = @_;
94-
if (not -e $output or -M $input < -M $output) {
95-
my_system($self, $exec, $input, $output);
96-
}
97-
return;
98-
},
9916
pod2man => sub {
10017
my ($self, $source, $dest) = @_;
10118
return if -e $dest and -M $source > -M $dest;
@@ -105,70 +22,6 @@ my %build_methods = (
10522
$self->{pod_parser}->parse_from_file($source, $dest);
10623
return;
10724
},
108-
build_objects => sub {
109-
my ($self, %args) = @_;
110-
111-
my $input_dir = $args{input_dir} || '.';
112-
my $tempdir = $args{temp_dir} || '_build';
113-
my @raw_files = _get_input_files(@args{qw/input_files input_dir/});
114-
my %object_for = map { (catfile($input_dir, $_) => catfile($tempdir, $self->cbuilder->object_file($_))) } @raw_files;
115-
my @input_dirs = ( (defined $self->stash('include_dir') ? @{ $self->stash('include_dir') } : ()), (defined $args{include_dirs} ? @{ $args{include_dirs} } : ()));
116-
117-
for my $source_file (sort keys %object_for) {
118-
my $object_file = $object_for{$source_file};
119-
next if -e $object_file and -M $source_file > -M $object_file;
120-
$self->create_dir(dirname($object_file));
121-
$self->cbuilder->compile(
122-
source => $source_file,
123-
object_file => $object_file,
124-
'C++' => $args{'C++'},
125-
include_dirs => \@input_dirs,
126-
extra_compiler_flags => $args{cc_flags} || _compiler_flags(),
127-
);
128-
}
129-
return values %object_for;
130-
},
131-
build_library => sub {
132-
my ($self, %args) = @_;
133-
134-
my @objects = $self->build_objects(%args);
135-
136-
my $output_dir = $args{output_dir} || 'blib';
137-
my $library_file = $args{libfile} || catfile($output_dir, 'so', 'lib' . $self->cbuilder->lib_file($args{name}));
138-
my $linker_flags = _linker_flags($args{libs}, $args{libdirs}, append => $args{linker_append}, 'C++' => $args{'C++'});
139-
$self->create_dir(dirname($library_file));
140-
$self->cbuilder->link(
141-
lib_file => $library_file,
142-
objects => \@objects,
143-
extra_linker_flags => $linker_flags,
144-
module_name => $args{name},
145-
) if not -e $library_file or grep { (-M $_ < -M $library_file ) } @objects;
146-
return;
147-
},
148-
build_executable => sub {
149-
my ($self, %args) = @_;
150-
151-
my @objects = $self->build_objects(%args);
152-
my $linker_flags = _linker_flags($args{libs}, $args{libdirs}, append => $args{linker_append}, 'C++' => $args{'C++'});
153-
$self->create_dir(dirname($args{output}));
154-
$self->cbuilder->link_executable(
155-
objects => \@objects,
156-
exe_file => $args{output},
157-
extra_linker_flags => $linker_flags,
158-
'C++' => $args{'C++'},
159-
) if not -e $args{output} or grep { (-M $_ < -M $args{output}) } @objects;
160-
return;
161-
},
162-
process_cpp => sub {
163-
my ($self, $input, $output) = @_;
164-
$self->create_by_system([ $Config{cpp}, split(/ /, $Config{ccflags}), '-I' . catdir($Config{archlibexp}, 'CORE') ], $input, $output);
165-
return;
166-
},
167-
process_perl => sub {
168-
my ($self, $input, $output) = @_;
169-
$self->create_by_system([ $^X, '-T' ], $input, $output);
170-
return;
171-
},
17225
);
17326

17427
my %build_actions = (
@@ -195,12 +48,7 @@ sub mixin {
19548

19649
$builder->inject_roles({ build => \%build_methods });
19750
$builder->register_actions(%build_actions);
198-
$builder->register_dirty(binary => [qw/blib _build/]);
199-
$builder->register_argument(include_dir => 2);
200-
$builder->register_paths(
201-
'so' => (split ' ', $Config{libpth})[0],
202-
'headers' => $Config{usrinc},
203-
);
51+
$builder->register_dirty(binary => [qw/blib/]);
20452
return;
20553
}
20654

inc/Library/Build/Compile.pm

+176
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
package Library::Build::Compile;
2+
3+
use 5.006;
4+
use strict;
5+
use warnings FATAL => 'all';
6+
7+
our $VERSION = '0.003';
8+
9+
use Carp 'croak';
10+
use Config;
11+
use File::Basename qw/basename dirname/;
12+
use File::Spec::Functions qw/catfile catdir splitdir/;
13+
14+
my $compiler = $Config{cc} eq 'cl' ? 'msvc' : 'gcc';
15+
16+
sub compiler_flags {
17+
return ($compiler eq 'gcc') ? [ qw/--std=gnu++0x -ggdb3 -DDEBUG -Wall -Wshadow -Wnon-virtual-dtor -Wsign-promo -Wextra -Winvalid-pch/ ] :
18+
($compiler eq 'msvc') ? [ qw{/TP /EHsc /Wall} ] :
19+
[];
20+
}
21+
22+
sub get_input_files {
23+
my ($input_files, $input_dir) = @_;
24+
if ($input_files) {
25+
if (ref $input_files) {
26+
return @{$input_files};
27+
}
28+
else {
29+
return $input_files;
30+
}
31+
}
32+
elsif ($input_dir) {
33+
opendir my ($dh), $input_dir or croak "Can't open input directory '$input_dir': $!";
34+
my @ret = grep { /^ .+ \. C $/xsm } readdir $dh;
35+
closedir $dh;
36+
return @ret;
37+
}
38+
croak 'Can\'t establish source files';
39+
}
40+
41+
sub linker_flags {
42+
my ($libs, $libdirs, %options) = @_;
43+
my @elements;
44+
if ($compiler eq 'gcc') {
45+
push @elements, map { "-l$_" } @{$libs};
46+
push @elements, map { "-L$_" } @{$libdirs};
47+
if ($options{'C++'}) {
48+
push @elements, '-lstdc++';
49+
}
50+
}
51+
elsif ($compiler eq 'msvc') {
52+
push @elements, map { "$_.dll" } @{$libs};
53+
push @elements, map { qq{-libpath:"$_"} } @{$libdirs};
54+
if ($options{'C++'}) {
55+
push @elements, 'msvcprt.lib';
56+
}
57+
}
58+
push @elements, $options{append} if defined $options{append};
59+
return join ' ', @elements;
60+
}
61+
62+
*my_system = $^O eq 'MSWin32'
63+
? sub {
64+
my ($self, $exec, $input, $output) = @_;
65+
my $call = join ' ', @{$exec}, $input, '>', $output;
66+
print "$call\n" if $self->stash('verbose') >= 0;
67+
system $call and croak "Couldn't call system(): $!";
68+
return;
69+
}
70+
: sub {
71+
my ($self, $exec, $input, $output) = @_;
72+
my @call = (@{$exec}, $input);
73+
print "@call > $output\n" if $self->stash('verbose') >= 0;
74+
my $pid = fork;
75+
if ($pid) {
76+
waitpid $pid, 0;
77+
}
78+
else {
79+
open STDOUT, '>', $output or croak "Can't write to file '$output': $!";
80+
exec @call or croak "Couldn't exec: $!";
81+
}
82+
return;
83+
};
84+
85+
my %compile_methods = (
86+
cbuilder => sub {
87+
my $self = shift;
88+
require ExtUtils::CBuilder;
89+
return $self->{builder} ||= ExtUtils::CBuilder->new(quiet => $self->stash('verbose') < 0)
90+
},
91+
create_by_system => sub {
92+
my ($self, $exec, $input, $output) = @_;
93+
if (not -e $output or -M $input < -M $output) {
94+
my_system($self, $exec, $input, $output);
95+
}
96+
return;
97+
},
98+
build_objects => sub {
99+
my ($self, %args) = @_;
100+
101+
my $input_dir = $args{input_dir} || '.';
102+
my $tempdir = $args{temp_dir} || '_build';
103+
my @raw_files = get_input_files(@args{qw/input_files input_dir/});
104+
my %object_for = map { (catfile($input_dir, $_) => catfile($tempdir, $self->cbuilder->object_file($_))) } @raw_files;
105+
my @input_dirs = ( (defined $self->stash('include_dir') ? @{ $self->stash('include_dir') } : ()), (defined $args{include_dirs} ? @{ $args{include_dirs} } : ()));
106+
107+
for my $source_file (sort keys %object_for) {
108+
my $object_file = $object_for{$source_file};
109+
next if -e $object_file and -M $source_file > -M $object_file;
110+
$self->create_dir(dirname($object_file));
111+
$self->cbuilder->compile(
112+
source => $source_file,
113+
object_file => $object_file,
114+
'C++' => $args{'C++'},
115+
include_dirs => \@input_dirs,
116+
extra_compiler_flags => $args{cc_flags} || compiler_flags(),
117+
);
118+
}
119+
return values %object_for;
120+
},
121+
build_library => sub {
122+
my ($self, %args) = @_;
123+
124+
my @objects = $self->build_objects(%args);
125+
126+
my $output_dir = $args{output_dir} || 'blib';
127+
my $library_file = $args{libfile} || catfile($output_dir, 'so', 'lib' . $self->cbuilder->lib_file($args{name}));
128+
my $linker_flags = linker_flags($args{libs}, $args{libdirs}, append => $args{linker_append}, 'C++' => $args{'C++'});
129+
$self->create_dir(dirname($library_file));
130+
$self->cbuilder->link(
131+
lib_file => $library_file,
132+
objects => \@objects,
133+
extra_linker_flags => $linker_flags,
134+
module_name => $args{name},
135+
) if not -e $library_file or grep { (-M $_ < -M $library_file ) } @objects;
136+
return;
137+
},
138+
build_executable => sub {
139+
my ($self, %args) = @_;
140+
141+
my @objects = $self->build_objects(%args);
142+
my $linker_flags = linker_flags($args{libs}, $args{libdirs}, append => $args{linker_append}, 'C++' => $args{'C++'});
143+
$self->create_dir(dirname($args{output}));
144+
$self->cbuilder->link_executable(
145+
objects => \@objects,
146+
exe_file => $args{output},
147+
extra_linker_flags => $linker_flags,
148+
'C++' => $args{'C++'},
149+
) if not -e $args{output} or grep { (-M $_ < -M $args{output}) } @objects;
150+
return;
151+
},
152+
process_cpp => sub {
153+
my ($self, $input, $output) = @_;
154+
$self->create_by_system([ $Config{cpp}, split(/ /, $Config{ccflags}), '-I' . catdir($Config{archlibexp}, 'CORE') ], $input, $output);
155+
return;
156+
},
157+
process_perl => sub {
158+
my ($self, $input, $output) = @_;
159+
$self->create_by_system([ $^X, '-T' ], $input, $output);
160+
return;
161+
},
162+
);
163+
164+
sub mixin {
165+
my $builder = shift;
166+
167+
$builder->inject_roles({ build => \%compile_methods });
168+
$builder->register_dirty(binary => [qw/_build/]);
169+
$builder->register_argument(include_dir => 2);
170+
$builder->register_paths(
171+
'so' => (split ' ', $Config{libpth})[0],
172+
'headers' => $Config{usrinc},
173+
);
174+
return;
175+
}
176+

inc/Library/Build/PL.pm

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ sub write_build {
4343

4444
print {$fh} "my \$builder = Library::Build->new('$self->{name}', '$self->{version}');\n";
4545
if (!$self->{skip_base}) {
46-
print {$fh} "\$builder->mixin('Library::Build::$_');\n" for qw/Util Install Build Test Author/;
46+
printf {$fh} "\$builder->mixin(%s);\n", join ',', map { "'Library::Build::$_'" } qw/Util Install Build Compile Test Author/;
4747
}
4848
printf {$fh} "\$builder->mixin(%s);\n", join ', ', Dumper(@{ $self->{mixin} }) if $self->{mixin};
4949
printf {$fh} "\$builder->parse({ argv => \\\@ARGV, cached => %s });\n", Dumper($self->{argv});

0 commit comments

Comments
 (0)