line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Module::Build::WithXSpp; |
2
|
1
|
|
|
1
|
|
1034
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
40
|
|
3
|
1
|
|
|
1
|
|
7
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
46
|
|
4
|
|
|
|
|
|
|
|
5
|
1
|
|
|
1
|
|
937
|
use Module::Build; |
|
1
|
|
|
|
|
138034
|
|
|
1
|
|
|
|
|
34
|
|
6
|
1
|
|
|
1
|
|
880
|
use ExtUtils::CppGuess (); |
|
1
|
|
|
|
|
23362
|
|
|
1
|
|
|
|
|
3595
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our @ISA = qw(Module::Build); |
9
|
|
|
|
|
|
|
our $VERSION = '0.14'; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
# TODO |
12
|
|
|
|
|
|
|
# - configurable set of xsp and xspt files (and XS typemaps?) |
13
|
|
|
|
|
|
|
# => works via directories for now. |
14
|
|
|
|
|
|
|
# - configurable includes/C-preamble for the XS? |
15
|
|
|
|
|
|
|
# => Works in the .xsp files, but the order of XS++ inclusion |
16
|
|
|
|
|
|
|
# is undefined. |
17
|
|
|
|
|
|
|
# - configurable C++ source folder(s) (works, needs docs) |
18
|
|
|
|
|
|
|
# => to be documented another time. This is really not a feature that |
19
|
|
|
|
|
|
|
# should be commonly used. |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
sub new { |
22
|
0
|
|
|
0
|
0
|
|
my $proto = shift; |
23
|
0
|
|
0
|
|
|
|
my $class = ref($proto) || $proto; |
24
|
0
|
|
|
|
|
|
my %args = @_; |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
# This gives us the correct settings for the C++ compile (hopefully) |
27
|
0
|
|
|
|
|
|
my $guess = ExtUtils::CppGuess->new(); |
28
|
0
|
0
|
|
|
|
|
if (defined $args{extra_compiler_flags}) { |
29
|
0
|
0
|
|
|
|
|
if (ref($args{extra_compiler_flags})) { |
30
|
0
|
|
|
|
|
|
$guess->add_extra_compiler_flags($_) for @{$args{extra_compiler_flags}}; |
|
0
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
} |
32
|
|
|
|
|
|
|
else { |
33
|
0
|
|
|
|
|
|
$guess->add_extra_compiler_flags($args{extra_compiler_flags}) |
34
|
|
|
|
|
|
|
} |
35
|
0
|
|
|
|
|
|
delete $args{extra_compiler_flags}; |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
0
|
0
|
|
|
|
|
if (defined $args{extra_linker_flags}) { |
39
|
0
|
0
|
|
|
|
|
if (ref($args{extra_linker_flags})) { |
40
|
0
|
|
|
|
|
|
$guess->add_extra_linker_flags($_) for @{$args{extra_linker_flags}}; |
|
0
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
} |
42
|
|
|
|
|
|
|
else { |
43
|
0
|
|
|
|
|
|
$guess->add_extra_linker_flags($args{extra_linker_flags}) |
44
|
|
|
|
|
|
|
} |
45
|
0
|
|
|
|
|
|
delete $args{extra_linker_flags}; |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
# add the typemap modules to the build dependencies |
49
|
0
|
|
0
|
|
|
|
my $build_requires = $args{build_requires}||{}; |
50
|
0
|
|
0
|
|
|
|
my $extra_typemap_modules = $args{extra_typemap_modules}||{}; |
51
|
|
|
|
|
|
|
# FIXME: This prevents any potential subclasses from fudging with the extra typemaps? |
52
|
0
|
|
|
|
|
|
foreach my $module (keys %$extra_typemap_modules) { |
53
|
0
|
0
|
0
|
|
|
|
if (not defined $build_requires->{$module} |
|
|
|
0
|
|
|
|
|
54
|
|
|
|
|
|
|
or defined($extra_typemap_modules->{$module}) |
55
|
|
|
|
|
|
|
&& $build_requires->{$module} < $extra_typemap_modules->{$module}) |
56
|
|
|
|
|
|
|
{ |
57
|
0
|
|
|
|
|
|
$build_requires->{$module} = $extra_typemap_modules->{$module}; |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
} |
60
|
0
|
|
|
|
|
|
$args{build_requires} = $build_requires; |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
# Construct object using C++ options guess |
63
|
0
|
|
|
|
|
|
my $self = $class->SUPER::new( |
64
|
|
|
|
|
|
|
%args, |
65
|
|
|
|
|
|
|
$guess->module_build_options # FIXME find a way to let the user override this |
66
|
|
|
|
|
|
|
); |
67
|
|
|
|
|
|
|
|
68
|
0
|
0
|
|
|
|
|
push @{$self->extra_compiler_flags}, |
|
0
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
map "-I$_", |
70
|
0
|
|
|
|
|
|
(@{$self->cpp_source_dirs||[]}, $self->build_dir); |
71
|
|
|
|
|
|
|
|
72
|
0
|
|
|
|
|
|
$self->_init(\%args); |
73
|
|
|
|
|
|
|
|
74
|
0
|
|
|
|
|
|
return $self; |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub _init { |
78
|
0
|
|
|
0
|
|
|
my $self = shift; |
79
|
0
|
|
|
|
|
|
my $args = shift; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
sub auto_require { |
83
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
84
|
0
|
|
|
|
|
|
my $p = $self->{properties}; |
85
|
|
|
|
|
|
|
|
86
|
0
|
0
|
0
|
|
|
|
if ($self->dist_name ne 'Module-Build-WithXSpp' |
87
|
|
|
|
|
|
|
and $self->auto_configure_requires) |
88
|
|
|
|
|
|
|
{ |
89
|
0
|
0
|
|
|
|
|
if (not exists $p->{configure_requires}{'Module::Build::WithXSpp'}) { |
90
|
0
|
|
|
|
|
|
(my $ver = $VERSION) =~ s/^(\d+\.\d\d).*$/$1/; # last major release only |
91
|
0
|
|
|
|
|
|
$self->_add_prereq('configure_requires', 'Module::Build::WithXSpp', $ver); |
92
|
|
|
|
|
|
|
} |
93
|
0
|
0
|
|
|
|
|
if (not exists $p->{configure_requires}{'ExtUtils::CppGuess'}) { |
94
|
0
|
|
|
|
|
|
(my $ver = $ExtUtils::CppGuess::VERSION) =~ s/^(\d+\.\d\d).*$/$1/; # last major release only |
95
|
0
|
|
|
|
|
|
$self->_add_prereq('configure_requires', 'ExtUtils::CppGuess', $ver); |
96
|
|
|
|
|
|
|
} |
97
|
0
|
0
|
0
|
|
|
|
if (not exists $p->{build_requires}{'ExtUtils::CppGuess'} |
|
|
|
0
|
|
|
|
|
98
|
|
|
|
|
|
|
and eval("require ExtUtils::XSpp;") |
99
|
|
|
|
|
|
|
and defined $ExtUtils::XSpp::VERSION) |
100
|
|
|
|
|
|
|
{ |
101
|
0
|
|
|
|
|
|
(my $ver = $ExtUtils::XSpp::VERSION) =~ s/^(\d+\.\d\d).*$/$1/; # last major release only |
102
|
0
|
|
|
|
|
|
$self->_add_prereq('build_requires', 'ExtUtils::XSpp', $ver); |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
|
106
|
0
|
|
|
|
|
|
$self->SUPER::auto_require(); |
107
|
|
|
|
|
|
|
|
108
|
0
|
|
|
|
|
|
return; |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
sub ACTION_create_buildarea { |
112
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
113
|
0
|
|
|
|
|
|
mkdir($self->build_dir); |
114
|
0
|
|
|
|
|
|
$self->add_to_cleanup($self->build_dir); |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
sub ACTION_code { |
118
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
119
|
0
|
|
|
|
|
|
$self->depends_on('create_buildarea'); |
120
|
0
|
|
|
|
|
|
$self->depends_on('generate_typemap'); |
121
|
0
|
|
|
|
|
|
$self->depends_on('generate_main_xs'); |
122
|
|
|
|
|
|
|
|
123
|
0
|
|
|
|
|
|
my $files = {}; |
124
|
0
|
|
|
|
|
|
foreach my $file (@{$self->cpp_source_files}) { |
|
0
|
|
|
|
|
|
|
125
|
0
|
|
|
|
|
|
$files->{$file} = undef; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
0
|
|
|
|
|
|
foreach my $ext (qw(c cc cxx cpp C)) { |
129
|
0
|
0
|
|
|
|
|
foreach my $dir (@{$self->cpp_source_dirs||[]}) { |
|
0
|
|
|
|
|
|
|
130
|
0
|
|
|
|
|
|
my $this = $self->_find_file_by_type($ext, $dir); |
131
|
0
|
|
|
|
|
|
$files = $self->_merge_hashes($files, $this); |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
0
|
|
|
|
|
|
my @objects; |
136
|
0
|
|
|
|
|
|
foreach my $file (keys %$files) { |
137
|
0
|
|
|
|
|
|
my $obj = $self->compile_c($file); |
138
|
0
|
|
|
|
|
|
push @objects, $obj; |
139
|
0
|
|
|
|
|
|
$self->add_to_cleanup($obj); |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
|
142
|
0
|
|
0
|
|
|
|
$self->{properties}{objects} ||= []; |
143
|
0
|
|
|
|
|
|
push @{$self->{properties}{objects}}, @objects; |
|
0
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
|
145
|
0
|
|
|
|
|
|
return $self->SUPER::ACTION_code(@_); |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# I guess I should use a module here. |
149
|
|
|
|
|
|
|
sub _naive_shell_escape { |
150
|
0
|
|
|
0
|
|
|
my $s = shift; |
151
|
0
|
|
|
|
|
|
$s =~ s/\\/\\\\/g; |
152
|
0
|
|
|
|
|
|
$s =~ s/"/\\"/g; |
153
|
0
|
|
|
|
|
|
$s |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub ACTION_generate_main_xs { |
157
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
158
|
|
|
|
|
|
|
|
159
|
0
|
|
|
|
|
|
my $xs_files = $self->find_xs_files; |
160
|
0
|
|
|
|
|
|
my $main_xs_file = File::Spec->catfile($self->build_dir, 'main.xs'); |
161
|
|
|
|
|
|
|
|
162
|
0
|
0
|
|
|
|
|
if (keys(%$xs_files) > 1) { |
163
|
|
|
|
|
|
|
# user knows what she's doing, do not generate XS |
164
|
0
|
|
|
|
|
|
$self->log_info("Found custom XS files. Not auto-generating main XS file...\n"); |
165
|
0
|
|
|
|
|
|
return 1; |
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
|
168
|
0
|
|
|
|
|
|
my $xsp_files = $self->find_xsp_files; |
169
|
0
|
|
|
|
|
|
my $xspt_files = $self->find_xsp_typemaps; |
170
|
|
|
|
|
|
|
|
171
|
0
|
|
|
|
|
|
my $newest = $self->_calc_newest( |
172
|
|
|
|
|
|
|
keys(%$xsp_files), |
173
|
|
|
|
|
|
|
keys(%$xspt_files), |
174
|
|
|
|
|
|
|
'Build.PL', |
175
|
|
|
|
|
|
|
# Commented out: Do not include generated typemap in -M check |
176
|
|
|
|
|
|
|
# because -M granularity causes unnecessary regens. |
177
|
|
|
|
|
|
|
# See "_mbwxspp_force_xs_regen" |
178
|
|
|
|
|
|
|
#File::Spec->catdir($self->build_dir, 'typemap'), |
179
|
|
|
|
|
|
|
); |
180
|
|
|
|
|
|
|
|
181
|
0
|
|
|
|
|
|
my $main_time = 1e99; |
182
|
0
|
0
|
0
|
|
|
|
$main_time = -M $main_xs_file |
183
|
|
|
|
|
|
|
if defined $main_xs_file and -e $main_xs_file; |
184
|
|
|
|
|
|
|
|
185
|
0
|
0
|
0
|
|
|
|
if (keys(%$xs_files) == 1 |
186
|
|
|
|
|
|
|
&& (values(%$xs_files))[0] =~ /\Q$main_xs_file\E$/) |
187
|
|
|
|
|
|
|
{ |
188
|
|
|
|
|
|
|
# is main xs file still current? |
189
|
0
|
0
|
0
|
|
|
|
if (!$self->{_mbwxspp_force_xs_regen} && $main_time < $newest) { |
190
|
0
|
|
|
|
|
|
return 1; |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
|
194
|
0
|
|
|
|
|
|
delete $self->{_mbwxspp_force_xs_regen}; # done its job |
195
|
0
|
|
|
|
|
|
$self->log_info("Generating main XS file...\n"); |
196
|
|
|
|
|
|
|
|
197
|
0
|
|
|
|
|
|
my $early_includes = join "\n", |
198
|
|
|
|
|
|
|
map { |
199
|
0
|
0
|
|
|
|
|
s/^\s*#\s*include\s*//i; |
200
|
0
|
0
|
|
|
|
|
/^"/ or $_ = "<$_>"; |
201
|
0
|
|
|
|
|
|
"#include $_" |
202
|
|
|
|
|
|
|
} |
203
|
0
|
|
|
|
|
|
@{ $self->early_includes || [] }; |
204
|
|
|
|
|
|
|
|
205
|
0
|
|
|
|
|
|
my $module_name = $self->module_name; |
206
|
0
|
|
|
|
|
|
my $xs_code = <<"HERE"; |
207
|
|
|
|
|
|
|
/* |
208
|
|
|
|
|
|
|
* WARNING: This file was auto-generated. Changes will be lost! |
209
|
|
|
|
|
|
|
*/ |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
$early_includes |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
#ifdef __cplusplus |
214
|
|
|
|
|
|
|
extern "C" { |
215
|
|
|
|
|
|
|
#endif |
216
|
|
|
|
|
|
|
#include "EXTERN.h" |
217
|
|
|
|
|
|
|
#include "perl.h" |
218
|
|
|
|
|
|
|
#include "XSUB.h" |
219
|
|
|
|
|
|
|
#include "ppport.h" |
220
|
|
|
|
|
|
|
#undef do_open |
221
|
|
|
|
|
|
|
#undef do_close |
222
|
|
|
|
|
|
|
#ifdef __cplusplus |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
#endif |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
MODULE = $module_name PACKAGE = $module_name |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
HERE |
229
|
|
|
|
|
|
|
|
230
|
0
|
|
|
|
|
|
my $typemap_args = ''; |
231
|
0
|
|
|
|
|
|
$typemap_args .= '-t "' . _naive_shell_escape(Cwd::abs_path($_)) . '" ' foreach keys %$xspt_files; |
232
|
|
|
|
|
|
|
|
233
|
0
|
|
|
|
|
|
foreach my $xsp_file (keys %$xsp_files) { |
234
|
0
|
|
|
|
|
|
my $full_path_file = _naive_shell_escape( Cwd::abs_path($xsp_file) ); |
235
|
0
|
|
|
|
|
|
my $cmd = qq{INCLUDE_COMMAND: \$^X -MExtUtils::XSpp::Cmd -e xspp -- $typemap_args "$full_path_file"\n\n}; |
236
|
0
|
|
|
|
|
|
$xs_code .= $cmd; |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
|
239
|
0
|
|
|
|
|
|
my $outfile = File::Spec->catdir($self->build_dir, 'main.xs'); |
240
|
0
|
0
|
|
|
|
|
open my $fh, '>', $outfile |
241
|
|
|
|
|
|
|
or die "Could not open '$outfile' for writing: $!"; |
242
|
0
|
|
|
|
|
|
print $fh $xs_code; |
243
|
0
|
|
|
|
|
|
close $fh; |
244
|
|
|
|
|
|
|
|
245
|
0
|
|
|
|
|
|
return 1; |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
sub _load_extra_typemap_modules { |
249
|
0
|
|
|
0
|
|
|
my $self = shift; |
250
|
|
|
|
|
|
|
|
251
|
0
|
|
|
|
|
|
require ExtUtils::Typemaps; |
252
|
0
|
|
0
|
|
|
|
my $extra_modules = $self->extra_typemap_modules||{}; |
253
|
|
|
|
|
|
|
|
254
|
0
|
|
|
|
|
|
foreach my $module (keys %$extra_modules) { |
255
|
0
|
0
|
|
|
|
|
my $str = $extra_modules->{$module} |
256
|
|
|
|
|
|
|
? "$module $extra_modules->{$module}" |
257
|
|
|
|
|
|
|
: $module; |
258
|
0
|
0
|
|
|
|
|
if (not eval "use $str;1;") { |
259
|
0
|
|
|
|
|
|
$self->log_warn(<
|
260
|
|
|
|
|
|
|
ERROR: Required typemap module '$module' version $extra_modules->{$module} not found. |
261
|
|
|
|
|
|
|
Error message: |
262
|
|
|
|
|
|
|
$@ |
263
|
|
|
|
|
|
|
HERE |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
sub ACTION_generate_typemap { |
269
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
270
|
0
|
|
|
|
|
|
$self->depends_on('create_buildarea'); |
271
|
|
|
|
|
|
|
|
272
|
0
|
|
|
|
|
|
require File::Spec; |
273
|
|
|
|
|
|
|
|
274
|
0
|
|
|
|
|
|
my $files = $self->find_map_files; |
275
|
|
|
|
|
|
|
|
276
|
0
|
|
|
|
|
|
$self->_load_extra_typemap_modules(); |
277
|
0
|
|
0
|
|
|
|
my $extra_modules = $self->extra_typemap_modules||{}; |
278
|
|
|
|
|
|
|
|
279
|
0
|
|
|
|
|
|
my $newest = $self->_calc_newest( |
280
|
|
|
|
|
|
|
keys(%$files), |
281
|
|
|
|
|
|
|
'Build.PL', |
282
|
|
|
|
|
|
|
); |
283
|
|
|
|
|
|
|
|
284
|
0
|
|
|
|
|
|
my $out_map_file = File::Spec->catfile($self->build_dir, 'typemap'); |
285
|
0
|
0
|
0
|
|
|
|
if (-f $out_map_file and -M $out_map_file < $newest) { |
286
|
0
|
|
|
|
|
|
return 1; |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
|
289
|
0
|
|
|
|
|
|
$self->log_info("Processing XS typemap files...\n"); |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
# merge all typemaps into 'buildtmp/typemap' |
292
|
|
|
|
|
|
|
# creates empty typemap file if there are no files to merge |
293
|
0
|
|
|
|
|
|
my $merged = ExtUtils::Typemaps->new; |
294
|
0
|
|
|
|
|
|
$merged->merge(typemap => $_->new) for keys %$extra_modules; |
295
|
|
|
|
|
|
|
|
296
|
0
|
|
|
|
|
|
foreach my $file (keys %$files) { |
297
|
0
|
|
|
|
|
|
$merged->merge(typemap => ExtUtils::Typemaps->new(file => $file)); |
298
|
|
|
|
|
|
|
} |
299
|
0
|
|
|
|
|
|
$merged->write(file => $out_map_file); |
300
|
|
|
|
|
|
|
|
301
|
0
|
|
|
|
|
|
$self->{_mbwxspp_force_xs_regen} = 1; |
302
|
|
|
|
|
|
|
} |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
sub find_map_files { |
305
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
306
|
0
|
|
|
|
|
|
my $files = $self->_find_file_by_type('map', 'lib'); |
307
|
0
|
0
|
|
|
|
|
my @extra_files = map glob($_), |
308
|
|
|
|
|
|
|
map File::Spec->catfile($_, '*.map'), |
309
|
0
|
|
|
|
|
|
(@{$self->extra_xs_dirs||[]}); |
310
|
|
|
|
|
|
|
|
311
|
0
|
|
|
|
|
|
$files->{$_} = $_ foreach map $self->localize_file_path($_), |
312
|
|
|
|
|
|
|
@extra_files; |
313
|
|
|
|
|
|
|
|
314
|
0
|
0
|
|
|
|
|
$files->{'typemap'} = 'typemap' if -f 'typemap'; |
315
|
|
|
|
|
|
|
|
316
|
0
|
|
|
|
|
|
return $files; |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
sub find_xsp_files { |
321
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
322
|
|
|
|
|
|
|
|
323
|
0
|
0
|
|
|
|
|
my @extra_files = map glob($_), |
324
|
|
|
|
|
|
|
map File::Spec->catfile($_, '*.xsp'), |
325
|
0
|
|
|
|
|
|
(@{$self->extra_xs_dirs||[]}); |
326
|
|
|
|
|
|
|
|
327
|
0
|
|
|
|
|
|
my $files = $self->_find_file_by_type('xsp', 'lib'); |
328
|
0
|
|
|
|
|
|
$files->{$_} = $_ foreach map $self->localize_file_path($_), |
329
|
|
|
|
|
|
|
@extra_files; |
330
|
|
|
|
|
|
|
|
331
|
0
|
|
|
|
|
|
require File::Basename; |
332
|
|
|
|
|
|
|
# XS++ typemaps aren't XSP files in this regard |
333
|
0
|
|
|
|
|
|
foreach my $file (keys %$files) { |
334
|
0
|
0
|
|
|
|
|
delete $files->{$file} |
335
|
|
|
|
|
|
|
if File::Basename::basename($file) eq 'typemap.xsp'; |
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
|
338
|
0
|
|
|
|
|
|
return $files; |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
sub find_xsp_typemaps { |
342
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
343
|
|
|
|
|
|
|
|
344
|
0
|
|
|
|
|
|
my $xsp_files = $self->_find_file_by_type('xsp', 'lib'); |
345
|
0
|
|
|
|
|
|
my $xspt_files = $self->_find_file_by_type('xspt', 'lib'); |
346
|
|
|
|
|
|
|
|
347
|
0
|
|
|
|
|
|
foreach (keys %$xsp_files) { # merge over 'typemap.xsp's |
348
|
0
|
0
|
|
|
|
|
next unless File::Basename::basename($_) eq 'typemap.xsp'; |
349
|
0
|
|
|
|
|
|
$xspt_files->{$_} = $_ |
350
|
|
|
|
|
|
|
} |
351
|
|
|
|
|
|
|
|
352
|
0
|
|
|
|
|
|
my @extra_files = grep -e $_, |
353
|
|
|
|
|
|
|
map glob($_), |
354
|
|
|
|
|
|
|
grep defined $_ && /\S/, |
355
|
0
|
0
|
|
|
|
|
map { ( File::Spec->catfile($_, 'typemap.xsp'), |
356
|
|
|
|
|
|
|
File::Spec->catfile($_, '*.xspt') ) } |
357
|
0
|
|
0
|
|
|
|
@{$self->extra_xs_dirs||[]}; |
358
|
0
|
|
|
|
|
|
$xspt_files->{$_} = $_ foreach map $self->localize_file_path($_), |
359
|
|
|
|
|
|
|
@extra_files; |
360
|
0
|
|
|
|
|
|
return $xspt_files; |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
# This overrides the equivalent in the base class to add the buildtmp and |
365
|
|
|
|
|
|
|
# the main directory |
366
|
|
|
|
|
|
|
sub find_xs_files { |
367
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
368
|
0
|
|
|
|
|
|
my $xs_files = $self->SUPER::find_xs_files; |
369
|
|
|
|
|
|
|
|
370
|
0
|
0
|
|
|
|
|
my @extra_files = map glob($_), |
371
|
|
|
|
|
|
|
map File::Spec->catfile($_, '*.xs'), |
372
|
0
|
|
|
|
|
|
@{$self->extra_xs_dirs||[]}; |
373
|
|
|
|
|
|
|
|
374
|
0
|
|
|
|
|
|
$xs_files->{$_} = $_ foreach map $self->localize_file_path($_), |
375
|
|
|
|
|
|
|
@extra_files; |
376
|
|
|
|
|
|
|
|
377
|
0
|
|
|
|
|
|
my $auto_gen_file = File::Spec->catfile($self->build_dir, 'main.xs'); |
378
|
0
|
0
|
|
|
|
|
if (-e $auto_gen_file) { |
379
|
0
|
|
|
|
|
|
$xs_files->{$auto_gen_file} = $self->localize_file_path($auto_gen_file); |
380
|
|
|
|
|
|
|
} |
381
|
0
|
|
|
|
|
|
return $xs_files; |
382
|
|
|
|
|
|
|
} |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
# overridden from original. We really require |
386
|
|
|
|
|
|
|
# EU::ParseXS, so the "if (eval{require EU::PXS})" is gone. |
387
|
|
|
|
|
|
|
sub compile_xs { |
388
|
0
|
|
|
0
|
0
|
|
my ($self, $file, %args) = @_; |
389
|
0
|
|
|
|
|
|
$self->log_verbose("$file -> $args{outfile}\n"); |
390
|
|
|
|
|
|
|
|
391
|
0
|
|
|
|
|
|
require ExtUtils::ParseXS; |
392
|
|
|
|
|
|
|
|
393
|
0
|
|
|
|
|
|
my $main_dir = Cwd::abs_path( Cwd::cwd() ); |
394
|
0
|
|
|
|
|
|
my $build_dir = Cwd::abs_path( $self->build_dir ); |
395
|
0
|
|
|
|
|
|
ExtUtils::ParseXS::process_file( |
396
|
|
|
|
|
|
|
filename => $file, |
397
|
|
|
|
|
|
|
prototypes => 0, |
398
|
|
|
|
|
|
|
output => $args{outfile}, |
399
|
|
|
|
|
|
|
# not default: |
400
|
|
|
|
|
|
|
'C++' => 1, |
401
|
|
|
|
|
|
|
hiertype => 1, |
402
|
|
|
|
|
|
|
typemap => File::Spec->catfile($build_dir, 'typemap'), |
403
|
|
|
|
|
|
|
); |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
# modified from orinal M::B (FIXME: shouldn't do this with private methods) |
407
|
|
|
|
|
|
|
# Changes from the original: |
408
|
|
|
|
|
|
|
# - If we're looking at the "main.xs" file in the build |
409
|
|
|
|
|
|
|
# directory, override the TARGET paths with the real |
410
|
|
|
|
|
|
|
# module name. |
411
|
|
|
|
|
|
|
# - In that case, also override the file basename for further |
412
|
|
|
|
|
|
|
# build products (maybe this should only be done on installation |
413
|
|
|
|
|
|
|
# into blib/.../?) |
414
|
|
|
|
|
|
|
sub _infer_xs_spec { |
415
|
0
|
|
|
0
|
|
|
my $self = shift; |
416
|
0
|
|
|
|
|
|
my $file = shift; |
417
|
|
|
|
|
|
|
|
418
|
0
|
|
|
|
|
|
my $cf = $self->{config}; |
419
|
|
|
|
|
|
|
|
420
|
0
|
|
|
|
|
|
my %spec; |
421
|
|
|
|
|
|
|
|
422
|
0
|
|
|
|
|
|
my( $v, $d, $f ) = File::Spec->splitpath( $file ); |
423
|
0
|
|
|
|
|
|
my @d = File::Spec->splitdir( $d ); |
424
|
0
|
|
|
|
|
|
(my $file_base = $f) =~ s/\.[^.]+$//i; |
425
|
|
|
|
|
|
|
|
426
|
0
|
|
|
|
|
|
my $build_folder = $self->build_dir; |
427
|
0
|
0
|
0
|
|
|
|
if ($d =~ /\Q$build_folder\E/ && $file_base eq 'main') { |
428
|
0
|
|
|
|
|
|
my $name = $self->module_name; |
429
|
0
|
|
|
|
|
|
@d = split /::/, $name; |
430
|
0
|
|
|
|
|
|
$file_base = $d[-1]; |
431
|
0
|
0
|
|
|
|
|
pop @d if @d; |
432
|
|
|
|
|
|
|
} |
433
|
|
|
|
|
|
|
else { |
434
|
|
|
|
|
|
|
# the module name |
435
|
0
|
|
0
|
|
|
|
shift( @d ) while @d && ($d[0] eq 'lib' || $d[0] eq ''); |
|
|
|
0
|
|
|
|
|
436
|
0
|
|
0
|
|
|
|
pop( @d ) while @d && $d[-1] eq ''; |
437
|
|
|
|
|
|
|
} |
438
|
|
|
|
|
|
|
|
439
|
0
|
|
|
|
|
|
$spec{base_name} = $file_base; |
440
|
|
|
|
|
|
|
|
441
|
0
|
|
|
|
|
|
$spec{src_dir} = File::Spec->catpath( $v, $d, '' ); |
442
|
|
|
|
|
|
|
|
443
|
0
|
|
|
|
|
|
$spec{module_name} = join( '::', (@d, $file_base) ); |
444
|
|
|
|
|
|
|
|
445
|
0
|
|
|
|
|
|
$spec{archdir} = File::Spec->catdir($self->blib, 'arch', 'auto', |
446
|
|
|
|
|
|
|
@d, $file_base); |
447
|
|
|
|
|
|
|
|
448
|
0
|
|
|
|
|
|
$spec{bs_file} = File::Spec->catfile($spec{archdir}, "${file_base}.bs"); |
449
|
|
|
|
|
|
|
|
450
|
0
|
|
|
|
|
|
$spec{lib_file} = File::Spec->catfile($spec{archdir}, |
451
|
|
|
|
|
|
|
"${file_base}.".$cf->get('dlext')); |
452
|
|
|
|
|
|
|
|
453
|
0
|
|
|
|
|
|
$spec{c_file} = File::Spec->catfile( $spec{src_dir}, |
454
|
|
|
|
|
|
|
"${file_base}.c" ); |
455
|
|
|
|
|
|
|
|
456
|
0
|
|
|
|
|
|
$spec{obj_file} = File::Spec->catfile( $spec{src_dir}, |
457
|
|
|
|
|
|
|
"${file_base}".$cf->get('obj_ext') ); |
458
|
|
|
|
|
|
|
|
459
|
0
|
|
|
|
|
|
return \%spec; |
460
|
|
|
|
|
|
|
} |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
__PACKAGE__->add_property( 'cpp_source_files' => [] ); |
463
|
|
|
|
|
|
|
__PACKAGE__->add_property( 'cpp_source_dirs' => ['src'] ); |
464
|
|
|
|
|
|
|
__PACKAGE__->add_property( 'build_dir' => 'buildtmp' ); |
465
|
|
|
|
|
|
|
__PACKAGE__->add_property( 'extra_xs_dirs' => [".", grep { -d $_ and /^xsp?$/i } glob("*")] ); |
466
|
|
|
|
|
|
|
__PACKAGE__->add_property( 'extra_typemap_modules' => {} ); |
467
|
|
|
|
|
|
|
__PACKAGE__->add_property( 'early_includes' => [] ); |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
sub _merge_hashes { |
471
|
0
|
|
|
0
|
|
|
my $self = shift; |
472
|
0
|
|
|
|
|
|
my %h; |
473
|
0
|
|
|
|
|
|
foreach my $m (@_) { |
474
|
0
|
|
|
|
|
|
$h{$_} = $m->{$_} foreach keys %$m; |
475
|
|
|
|
|
|
|
} |
476
|
0
|
|
|
|
|
|
return \%h; |
477
|
|
|
|
|
|
|
} |
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
sub _calc_newest { |
480
|
0
|
|
|
0
|
|
|
my $self = shift; |
481
|
0
|
|
|
|
|
|
my $newest = 1.e99; |
482
|
0
|
|
|
|
|
|
foreach my $file (@_) { |
483
|
0
|
0
|
|
|
|
|
next if not defined $file; |
484
|
0
|
|
|
|
|
|
my $age = -M $file; |
485
|
0
|
0
|
0
|
|
|
|
$newest = $age if defined $age and $age < $newest; |
486
|
|
|
|
|
|
|
} |
487
|
0
|
|
|
|
|
|
return $newest; |
488
|
|
|
|
|
|
|
} |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
1; |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
__END__ |