Commit | Line | Data |
---|---|---|
27da23d5 JH |
1 | #!/usr/bin/perl -w |
2 | ||
3 | use strict; | |
4 | ||
5 | use Getopt::Long; | |
6 | use File::Basename; | |
7 | use Cwd; | |
8 | ||
9 | do "sanity.pl"; | |
10 | ||
11 | my $CoreBuild = -d "ext" && -f "perl.h" && -d "symbian" && -f "perl.c"; | |
12 | ||
13 | my $SymbianVersion = $ENV{XSBUILD_SYMBIAN_VERSION}; | |
14 | my $PerlVersion = $ENV{XSBUILD_PERL_VERSION}; | |
15 | my $CSuffix = '.c'; | |
16 | my $CPlusPlus; | |
17 | my $Config; | |
18 | my $Build; | |
19 | my $Clean; | |
20 | my $DistClean; | |
21 | my $Sis; | |
22 | ||
23 | sub usage { | |
24 | die <<__EOF__; | |
25 | $0: Usage: $0 [--symbian=version] [--perl=version] | |
26 | [--csuffix=csuffix] [--cplusplus] | |
27 | [--win=win] [--arm=arm] | |
28 | [--config|--build|--clean|--distclean|--sis] ext | |
29 | __EOF__ | |
30 | } | |
31 | ||
32 | my $CWD; | |
33 | my $SDK; | |
34 | my $VERSION; | |
35 | my $R_V_SV; | |
36 | my $PERLSDK; | |
c8f896e5 JH |
37 | my $WIN = 'wins'; |
38 | my $ARM = 'thumb'; | |
c1c0c258 | 39 | my $BUILDROOT = getcwd(); |
27da23d5 JH |
40 | |
41 | if ( !defined $PerlVersion && $0 =~ m:\\symbian\\perl\\(.+)\\bin\\xsbuild.pl:i ) | |
42 | { | |
43 | $PerlVersion = $1; | |
44 | } | |
45 | ||
46 | if ( !defined $SymbianVersion) { | |
47 | ($SymbianVersion) = ($ENV{PATH} =~ m!C:\\Symbian\\(.+?)\\!i); | |
48 | } | |
49 | ||
50 | my $S60SDK; | |
51 | ||
52 | if ($CoreBuild) { | |
53 | unshift @INC, "symbian"; | |
54 | do "sanity.pl"; | |
55 | my %VERSION = %{ do "version.pl" }; | |
56 | $SDK = do "sdk.pl"; | |
57 | $VERSION = "$VERSION{REVISION}$VERSION{VERSION}$VERSION{SUBVERSION}"; | |
58 | $R_V_SV = "$VERSION{REVISION}.$VERSION{VERSION}.$VERSION{SUBVERSION}"; | |
c1c0c258 | 59 | $BUILDROOT = do "cwd.pl"; |
27da23d5 JH |
60 | $SymbianVersion = $1 if $SDK =~ m:\\Symbian\\([^\\]+):; |
61 | $PerlVersion = $R_V_SV; | |
62 | $S60SDK = $ENV{S60SDK}; # from sdk.pl | |
63 | } | |
64 | ||
65 | usage() | |
66 | unless GetOptions( | |
67 | 'symbian=s' => \$SymbianVersion, | |
68 | 'perl=s' => \$PerlVersion, | |
69 | 'csuffix=s' => \$CSuffix, | |
70 | 'cplusplus' => \$CPlusPlus, | |
71 | 'win=s' => \$WIN, | |
72 | 'arm=s' => \$ARM, | |
73 | 'config' => \$Config, | |
74 | 'build' => \$Build, | |
75 | 'clean' => \$Clean, | |
76 | 'distclean' => \$DistClean, | |
77 | 'sis' => \$Sis | |
78 | ); | |
79 | ||
80 | usage() unless @ARGV; | |
81 | ||
82 | $CSuffix = '.cpp' if $CPlusPlus; | |
83 | $Build = !( $Config || $Clean || $DistClean ) || $Sis unless defined $Build; | |
84 | ||
85 | die "$0: Symbian version undefined\n" unless defined $SymbianVersion; | |
86 | ||
87 | $SymbianVersion =~ s:/:\\:g; | |
88 | ||
89 | die "$0: Symbian version '$SymbianVersion' not found\n" | |
90 | unless -d "\\Symbian\\$SymbianVersion"; | |
91 | ||
92 | die "$0: Perl version undefined\n" unless defined $PerlVersion; | |
93 | ||
94 | die "$0: Perl version '$PerlVersion' not found\n" | |
95 | if !$CoreBuild && !-d "\\Symbian\\Perl\\$PerlVersion"; | |
96 | ||
97 | print "Configuring with Symbian $SymbianVersion and Perl $PerlVersion...\n"; | |
98 | ||
99 | $SDK = "\\Symbian\\$SymbianVersion" unless defined $SDK; | |
100 | $PERLSDK = "\\Symbian\\Perl\\$PerlVersion"; | |
101 | ||
102 | $R_V_SV = $PerlVersion; | |
103 | ||
c8f896e5 JH |
104 | $VERSION = $PerlVersion unless defined $VERSION; |
105 | ||
106 | $VERSION =~ tr/.//d if defined $VERSION; | |
27da23d5 JH |
107 | |
108 | $ENV{SDK} = $SDK; # For the Errno extension | |
109 | $ENV{CROSS} = 1; # For the Encode extension | |
110 | ||
c8f896e5 JH |
111 | my $UARM = 'urel'; |
112 | my $UREL = "$SDK\\epoc32\\release\\-ARM-\\$UARM"; | |
113 | my $SRCDBG; | |
114 | if (exists $ENV{UREL}) { | |
115 | $UREL = $ENV{UREL}; # from sdk.pl | |
116 | $UREL =~ s/-ARM-/$ARM/; | |
117 | $UARM = $ENV{UARM}; # from sdk.pl | |
118 | $SRCDBG = $UARM eq 'udeb' ? "SRCDBG" : ""; | |
119 | } | |
27da23d5 JH |
120 | |
121 | my %CONF; | |
122 | my %EXTCFG; | |
123 | ||
124 | sub write_bld_inf { | |
125 | my ($base) = @_; | |
126 | print "\tbld.inf\n"; | |
127 | open( BLD_INF, ">bld.inf" ) or die "$0: bld.inf: $!\n"; | |
128 | print BLD_INF <<__EOF__; | |
129 | PRJ_MMPFILES | |
130 | $base.mmp | |
131 | PRJ_PLATFORMS | |
132 | $WIN $ARM | |
133 | __EOF__ | |
134 | close(BLD_INF); | |
135 | } | |
136 | ||
137 | sub system_echo { | |
138 | my $cmd = shift; | |
139 | print "xsbuild: ", $cmd, "\n"; | |
140 | return system($cmd); | |
141 | } | |
142 | ||
143 | sub run_PL { | |
144 | my ( $PL, $dir, $file ) = @_; | |
145 | if ( defined $file ) { | |
146 | print "\t(Running $dir\\$PL to create $file)\n"; | |
147 | unlink($file); | |
148 | } | |
149 | else { | |
150 | print "\t(Running $dir\\$PL)\n"; | |
151 | } | |
152 | my $cmd; | |
153 | if ($CoreBuild) { | |
c1c0c258 | 154 | # Problem: the Config.pm we have in $BUILDROOT\\lib carries the |
27da23d5 JH |
155 | # version number of the Perl we are building, while the Perl |
156 | # we are running might have some other version. Solution: | |
157 | # temporarily replace the Config.pm with a patched version. | |
158 | my $V = sprintf "%vd", $^V; | |
c1c0c258 JH |
159 | unlink("$BUILDROOT\\lib\\Config.pm.bak"); |
160 | print "(patching $BUILDROOT\\lib\\Config.pm)\n"; | |
161 | system_echo("perl -pi.bak -e \"s:\\Q$R_V_SV:$V:\" $BUILDROOT\\lib\\Config.pm"); | |
27da23d5 | 162 | } |
c1c0c258 | 163 | system_echo("perl -I$BUILDROOT\\lib -I$BUILDROOT\\xlib\\symbian $PL") == 0 |
27da23d5 JH |
164 | or warn "$0: $PL failed.\n"; |
165 | if ($CoreBuild) { | |
c1c0c258 | 166 | system_echo("copy $BUILDROOT\\lib\\Config.pm.bak $BUILDROOT\\lib\\Config.pm"); |
27da23d5 JH |
167 | } |
168 | if ( defined $file ) { -s $file or die "$0: No $file created.\n" } | |
169 | } | |
170 | ||
171 | sub read_old_multi { | |
172 | my ( $conf, $k ) = @_; | |
173 | push @{ $conf->{$k} }, split( ' ', $1 ) if /^$k\s(.+)$/; | |
174 | } | |
175 | ||
176 | sub uniquefy_filenames { | |
177 | my $b = []; | |
178 | my %c = (); | |
179 | for my $i (@{$_[0]}) { | |
180 | $i =~ s!/!\\!g; | |
181 | $i = lc $i if $i =~ m!\\!; | |
182 | $i =~ s!^c:!!; | |
183 | push @$b, $i unless $c{$i}++; | |
184 | } | |
185 | return $b; | |
186 | } | |
187 | ||
188 | sub read_mmp { | |
189 | my ( $conf, $mmp ) = @_; | |
190 | if ( -r $mmp && open( MMP, "<$mmp" ) ) { | |
191 | print "\tReading $mmp...\n"; | |
192 | while (<MMP>) { | |
193 | chomp; | |
194 | $conf->{TARGET} = $1 if /^TARGET\s+(.+)$/; | |
195 | $conf->{TARGETPATH} = $1 if /^TARGETPATH\s+(.+)$/; | |
196 | $conf->{EXTVERSION} = $1 if /^EXTVERSION\s+(.+)$/; | |
197 | read_old_multi( $conf, "SOURCE" ); | |
198 | read_old_multi( $conf, "SOURCEPATH" ); | |
199 | read_old_multi( $conf, "USERINCLUDE" ); | |
200 | read_old_multi( $conf, "SYSTEMINCLUDE" ); | |
201 | read_old_multi( $conf, "LIBRARY" ); | |
202 | read_old_multi( $conf, "MACRO" ); | |
203 | } | |
204 | close(MMP); | |
205 | } | |
206 | } | |
207 | ||
208 | sub write_mmp { | |
209 | my ( $base, $userinclude, @src ) = @_; | |
210 | ||
211 | print "\t$base.mmp\n"; | |
212 | $CONF{TARGET} = "$base.dll"; | |
213 | $CONF{TARGETPATH} = "\\System\\Libs\\Perl\\$R_V_SV"; | |
214 | $CONF{SOURCE} = [@src]; | |
c1c0c258 JH |
215 | $CONF{SOURCEPATH} = [ $CWD, $BUILDROOT ]; |
216 | $CONF{USERINCLUDE} = [ $CWD, $BUILDROOT ]; | |
27da23d5 | 217 | $CONF{SYSTEMINCLUDE} = ["$PERLSDK\\include"] unless $CoreBuild; |
c1c0c258 | 218 | $CONF{SYSTEMINCLUDE} = [ $BUILDROOT ] if $CoreBuild; |
27da23d5 JH |
219 | $CONF{LIBRARY} = []; |
220 | $CONF{MACRO} = []; | |
221 | read_mmp( \%CONF, "_init.mmp" ); | |
222 | read_mmp( \%CONF, "$base.mmp" ); | |
223 | ||
0added8b JH |
224 | if ($base eq 'Zlib') { |
225 | push @{$CONF{USERINCLUDE}}, "$CWD\\zlib-src"; | |
226 | } | |
227 | ||
27da23d5 JH |
228 | for my $ui ( @{$userinclude} ) { |
229 | $ui =~ s!/!\\!g; | |
230 | if ( $ui =~ m!^(?:[CD]:)?\\! ) { | |
231 | push @{ $CONF{USERINCLUDE} }, $ui; | |
232 | } | |
233 | else { | |
c1c0c258 | 234 | push @{ $CONF{USERINCLUDE} }, "$BUILDROOT\\$ui"; |
27da23d5 JH |
235 | } |
236 | } | |
237 | push @{ $CONF{SYSTEMINCLUDE} }, "\\epoc32\\include"; | |
238 | push @{ $CONF{SYSTEMINCLUDE} }, "\\epoc32\\include\\libc"; | |
239 | push @{ $CONF{LIBRARY} }, "euser.lib"; | |
240 | push @{ $CONF{LIBRARY} }, "estlib.lib"; | |
241 | push @{ $CONF{LIBRARY} }, "perl$VERSION.lib"; | |
242 | push @{ $CONF{MACRO} }, "SYMBIAN" unless $CoreBuild; | |
243 | push @{ $CONF{MACRO} }, "PERL_EXT" if $CoreBuild; | |
244 | push @{ $CONF{MACRO} }, "MULTIPLICITY"; | |
245 | push @{ $CONF{MACRO} }, "PERL_IMPLICIT_CONTEXT"; | |
246 | push @{ $CONF{MACRO} }, "PERL_GLOBAL_STRUCT"; | |
247 | push @{ $CONF{MACRO} }, "PERL_GLOBAL_STRUCT_PRIVATE"; | |
248 | ||
249 | for my $u (qw(SOURCE SOURCEPATH SYSTEMINCLUDE USERINCLUDE LIBRARY MACRO)) { | |
250 | $CONF{$u} = uniquefy_filenames( $CONF{$u} ); | |
251 | } | |
252 | open( BASE_MMP, ">$base.mmp" ) or die "$0: $base.mmp: $!\n"; | |
253 | ||
254 | print BASE_MMP <<__EOF__; | |
255 | TARGET $CONF{TARGET} | |
256 | TARGETTYPE dll | |
257 | TARGETPATH $CONF{TARGETPATH} | |
258 | SOURCE @{$CONF{SOURCE}} | |
259 | $SRCDBG | |
260 | __EOF__ | |
261 | for my $u (qw(SOURCEPATH SYSTEMINCLUDE USERINCLUDE)) { | |
262 | for my $v ( @{ $CONF{$u} } ) { | |
263 | print BASE_MMP "$u\t$v\n"; | |
264 | } | |
265 | } | |
266 | # OPTION does not work in MMPs for pre-2.0 SDKs? | |
267 | print BASE_MMP <<__EOF__; | |
268 | LIBRARY @{$CONF{LIBRARY}} | |
269 | MACRO @{$CONF{MACRO}} | |
270 | // OPTION MSVC /P | |
271 | // OPTION GCC -E | |
272 | __EOF__ | |
273 | close(BASE_MMP); | |
274 | ||
275 | } | |
276 | ||
277 | sub write_makefile { | |
278 | my ( $base, $build ) = @_; | |
279 | ||
280 | print "\tMakefile\n"; | |
281 | ||
282 | my $windef1 = "$SDK\\Epoc32\\Build$CWD\\$base\\$WIN\\$base.def"; | |
283 | my $windef2 = "..\\BWINS\\${base}u.def"; | |
284 | my $armdef1 = "$SDK\\Epoc32\\Build$CWD\\$base\\$ARM\\$base.def"; | |
285 | my $armdef2 = "..\\BMARM\\${base}u.def"; | |
286 | ||
287 | my $wrap = $SDK && $S60SDK eq '1.2' && $SDK !~ /_CW$/; | |
288 | my $ABLD = $wrap ? 'perl b.pl' : 'abld'; | |
289 | ||
290 | open( MAKEFILE, ">Makefile" ) or die "$0: Makefile: $!\n"; | |
291 | print MAKEFILE <<__EOF__; | |
292 | WIN = $WIN | |
293 | ARM = $ARM | |
294 | ABLD = $ABLD | |
295 | ||
296 | all: build freeze | |
297 | ||
298 | sis: build_arm freeze_arm | |
299 | ||
300 | build: abld.bat build_win build_arm | |
301 | ||
302 | abld.bat: | |
303 | bldmake bldfiles | |
304 | ||
305 | build_win: abld.bat | |
306 | bldmake bldfiles | |
307 | \$(ABLD) build \$(WIN) udeb | |
308 | ||
309 | build_arm: abld.bat | |
310 | bldmake bldfiles | |
311 | \$(ABLD) build \$(ARM) $UARM | |
312 | ||
313 | win: build_win freeze_win | |
314 | ||
315 | arm: build_arm freeze_arm | |
316 | ||
317 | freeze: freeze_win freeze_arm | |
318 | ||
319 | freeze_win: | |
320 | bldmake bldfiles | |
321 | \$(ABLD) freeze \$(WIN) $base | |
322 | ||
323 | freeze_arm: | |
324 | bldmake bldfiles | |
325 | \$(ABLD) freeze \$(ARM) $base | |
326 | ||
327 | defrost: defrost_win defrost_arm | |
328 | ||
329 | defrost_win: | |
330 | -del /f $windef1 | |
331 | -del /f $windef2 | |
332 | ||
333 | defrost_arm: | |
334 | -del /f $armdef1 | |
335 | -del /f $armdef2 | |
336 | ||
337 | clean: clean_win clean_arm | |
338 | ||
339 | clean_win: | |
340 | \$(ABLD) clean \$(WIN) | |
341 | ||
342 | clean_arm: | |
343 | \$(ABLD) clean \$(ARM) | |
344 | ||
345 | realclean: clean realclean_win realclean_arm | |
346 | -del /f _init.c b.pl | |
347 | -del /f $base.c $base.mmp | |
348 | ||
349 | realclean_win: | |
350 | \$(ABLD) reallyclean \$(WIN) | |
351 | ||
352 | realclean_arm: | |
353 | \$(ABLD) reallyclean \$(ARM) | |
354 | ||
355 | distclean: defrost realclean | |
356 | -rmdir ..\\BWINS ..\\BMARM | |
357 | -del /f const-c.inc const-xs.inc | |
358 | -del /f Makefile abld.bat bld.inf | |
359 | __EOF__ | |
360 | close(MAKEFILE); | |
361 | if ($wrap) { | |
362 | if(open(B,">b.pl")) { | |
363 | print B <<'__EOF__'; | |
364 | # abld.pl wrapper. | |
365 | ||
366 | # nmake doesn't like MFLAGS and MAKEFLAGS being set to -w and w. | |
367 | delete $ENV{MFLAGS}; | |
368 | delete $ENV{MAKEFLAGS}; | |
369 | ||
370 | print "abld @ARGV\n"; | |
c1c0c258 | 371 | system_echo("abld @ARGV"); |
27da23d5 JH |
372 | __EOF__ |
373 | close(B); | |
374 | } else { | |
375 | warn "$0: failed to create b.pl: $!\n"; | |
376 | } | |
377 | } | |
378 | } | |
379 | ||
380 | sub update_dir { | |
381 | print "[chdir from ", getcwd(), " to "; | |
382 | chdir(shift) or return; | |
383 | update_cwd(); | |
384 | print getcwd(), "]\n"; | |
385 | } | |
386 | ||
387 | sub xsconfig { | |
388 | my ( $ext, $dir ) = @_; | |
c8f896e5 | 389 | print "Configuring for $ext, directory '$dir'...\n"; |
c1c0c258 | 390 | my $extu = $CoreBuild ? "$BUILDROOT\\lib\\ExtUtils" : "$PERLSDK\\lib\\ExtUtils"; |
27da23d5 JH |
391 | update_dir($dir) or die "$0: chdir '$dir': $!\n"; |
392 | my $build = dirname($ext); | |
393 | my $base = basename($ext); | |
394 | my $basexs = "$base.xs"; | |
395 | my $basepm = "$base.pm"; | |
396 | my $basec = "$base$CSuffix"; | |
397 | my $extdir = "."; | |
398 | if ( $dir =~ m:^ext\\(.+): ) { | |
399 | $extdir = $1; | |
400 | } | |
401 | elsif ( $dir ne "." ) { | |
402 | $extdir = $dir; | |
403 | } | |
404 | my $extdirdir = dirname($extdir); | |
405 | my $targetroot = "\\System\\Libs\\Perl\\$R_V_SV"; | |
406 | write_bld_inf($base) if -f $basexs; | |
407 | ||
408 | my %src; | |
409 | $src{$basec}++; | |
410 | ||
411 | $extdirdir = $extdirdir eq "." ? "" : "$extdirdir\\"; | |
412 | ||
413 | my %lst; | |
414 | $lst{"$UREL\\$base.dll"} = | |
415 | "$targetroot\\$ARM-symbian\\$base.dll" | |
416 | if -f $basexs; | |
417 | $lst{"$dir\\$base.pm"} = "$targetroot\\$extdirdir$base.pm" | |
418 | if -f $basepm && $base ne 'XSLoader'; | |
419 | ||
420 | my %incdir; | |
421 | my $ran_PL; | |
422 | if ( -d 'lib' ) { | |
423 | use File::Find; | |
424 | my @found; | |
425 | find( sub { push @found, $File::Find::name if -f $_ }, 'lib' ); | |
426 | for my $found (@found) { | |
427 | my ($short) = ( $found =~ m/^lib.(.+)/ ); | |
428 | $short =~ s!/!\\!g; | |
429 | $found =~ s!/!\\!g; | |
430 | $lst{"$dir\\$found"} = "$targetroot\\$short"; | |
431 | } | |
432 | } | |
433 | if ( my @pm = glob("*.pm */*.pm") ) { | |
434 | for my $pm (@pm) { | |
435 | next if $pm =~ m:^t/:; | |
436 | $pm =~ s:/:\\:g; | |
437 | $lst{"$dir\\$pm"} = "$targetroot\\$extdirdir$pm"; | |
438 | } | |
439 | } | |
440 | if ( my @c = glob("*.c *.cpp */*.c */*.cpp") ) { | |
0added8b | 441 | @c = grep { ! m:^zlib-src/: } @c if $ext eq 'ext\Compress\Zlib'; |
27da23d5 JH |
442 | for my $c (@c) { |
443 | $c =~ s:/:\\:g; | |
444 | $src{$c}++; | |
445 | } | |
446 | } | |
447 | if ( my @h = glob("*.h */*.h") ) { | |
c042ae3a | 448 | @h = grep { ! m:^zlib-src/: } @h if $ext eq 'ext\Compress\Zlib'; |
27da23d5 JH |
449 | for my $h (@h) { |
450 | $h =~ s:/:\\:g; | |
451 | $h = dirname($h); | |
452 | $incdir{"$dir\\$h"}++ unless $h eq "."; | |
453 | } | |
454 | } | |
455 | if ( exists $EXTCFG{$ext} ) { | |
456 | for my $cfg ( @{ $EXTCFG{$ext} } ) { | |
457 | if ( $cfg =~ /^([-+])?(.+\.(c|cpp|h))$/ ) { | |
458 | my $o = defined $1 ? $1 : '+'; | |
459 | my $f = $2; | |
460 | $f =~ s:/:\\:g; | |
461 | for my $f ( glob($f) ) { | |
462 | if ( $o eq '+' ) { | |
463 | warn "$0: no source file $dir\\$f\n" unless -f $f; | |
464 | $src{$f}++ unless $cfg =~ /\.h$/; | |
465 | if ( $f =~ m:^(.+)\\[^\\]+$: ) { | |
466 | $incdir{$1}++; | |
467 | } | |
468 | } | |
469 | elsif ( $o eq '-' ) { | |
470 | delete $src{$f}; | |
471 | } | |
472 | } | |
473 | } | |
474 | if ( $cfg =~ /^([-+])?(.+\.(pm|pl|inc))$/ ) { | |
475 | my $o = defined $1 ? $1 : '+'; | |
476 | my $f = $2; | |
477 | $f =~ s:/:\\:g; | |
478 | for my $f ( glob($f) ) { | |
479 | if ( $o eq '+' ) { | |
480 | warn "$0: no Perl file $dir\\$f\n" unless -f $f; | |
481 | $lst{"$dir\\$f"} = "$targetroot\\$extdir\\$f"; | |
482 | } | |
483 | elsif ( $o eq '-' ) { | |
484 | delete $lst{"$dir\\$f"}; | |
485 | } | |
486 | } | |
487 | } | |
488 | if ( $cfg eq 'CONST' && !$ran_PL++ ) { | |
489 | run_PL( "Makefile.PL", $dir, "const-xs.inc" ); | |
490 | } | |
491 | } | |
492 | } | |
493 | unless ( $ran_PL++ ) { | |
494 | run_PL( "Makefile.PL", $dir ) if -f "Makefile.PL"; | |
495 | } | |
496 | if ( $dir eq "ext\\Errno" ) { | |
497 | run_PL( "Errno_pm.PL", $dir, "Errno.pm" ); | |
498 | $lst{"$dir\\Errno.pm"} = "$targetroot\\Errno.pm"; | |
499 | } | |
500 | elsif ( $dir eq "ext\\Devel\\PPPort" ) { | |
501 | run_PL( "ppport_h.PL", $dir, "ppport.h" ); | |
502 | } | |
503 | elsif ( $dir eq "ext\\DynaLoader" ) { | |
504 | run_PL( "XSLoader_pm.PL", $dir, "XSLoader.pm" ); | |
505 | $lst{"ext\\DynaLoader\\XSLoader.pm"} = "$targetroot\\XSLoader.pm"; | |
506 | } | |
507 | elsif ( $dir eq "ext\\Encode" ) { | |
508 | system_echo("perl bin\\enc2xs -Q -O -o def_t.c -f def_t.fnm") == 0 | |
509 | or die "$0: running enc2xs failed: $!\n"; | |
510 | } | |
511 | ||
512 | my @lst = sort keys %lst; | |
513 | ||
514 | read_mmp( \%CONF, "_init.mmp" ); | |
515 | read_mmp( \%CONF, "$base.mmp" ); | |
516 | ||
517 | if ( -f $basexs ) { | |
518 | my %MM; # MakeMaker results | |
519 | my @MM = qw(VERSION XS_VERSION); | |
520 | if ( -f "Makefile" ) { | |
521 | print "\tReading MakeMaker Makefile...\n"; | |
522 | if ( open( MAKEFILE, "Makefile" ) ) { | |
523 | while (<MAKEFILE>) { | |
524 | for my $m (@MM) { | |
525 | if (m!^$m = (.+)!) { | |
526 | $MM{$m} = $1; | |
527 | print "\t$m = $1\n"; | |
528 | } | |
529 | } | |
530 | } | |
531 | close(MAKEFILE); | |
532 | } | |
533 | else { | |
534 | warn "$0: Makefile: $!"; | |
535 | } | |
536 | print "\tDeleting MakeMaker Makefile.\n"; | |
537 | unlink("Makefile"); | |
538 | } | |
539 | ||
540 | unlink($basec); | |
541 | print "\t$basec\n"; | |
542 | if ( defined $CONF{EXTVERSION} ) { | |
543 | my $EXTVERSION = $CONF{EXTVERSION}; | |
544 | print "\tUsing $EXTVERSION for version...\n"; | |
545 | $MM{VERSION} = $MM{XS_VERSION} = $EXTVERSION; | |
546 | } | |
547 | die "VERSION or XS_VERSION undefined\n" | |
548 | unless defined $MM{VERSION} && defined $MM{XS_VERSION}; | |
549 | if ( open( BASE_C, ">$basec" ) ) { | |
550 | print BASE_C <<__EOF__; | |
551 | #ifndef VERSION | |
552 | #define VERSION "$MM{VERSION}" | |
553 | #endif | |
554 | #ifndef XS_VERSION | |
555 | #define XS_VERSION "$MM{XS_VERSION}" | |
556 | #endif | |
557 | __EOF__ | |
558 | close(BASE_C); | |
559 | } | |
560 | else { | |
561 | warn "$0: $basec: $!"; | |
562 | } | |
563 | unless ( | |
c1c0c258 JH |
564 | system_echo( |
565 | "perl -I$BUILDROOT\\lib -I$PERLSDK\\lib $extu\\xsubpp -csuffix .cpp -typemap $extu\\typemap -noprototypes $basexs >> $basec" | |
27da23d5 JH |
566 | ) == 0 |
567 | && -s $basec | |
568 | ) | |
569 | { | |
570 | die "$0: perl xsubpp failed: $!\n"; | |
571 | } | |
572 | ||
573 | print "\t_init.c\n"; | |
574 | open( _INIT_C, ">_init.c" ) or die "$!: _init.c: $!\n"; | |
575 | print _INIT_C <<__EOF__; | |
576 | #include "EXTERN.h" | |
577 | #include "perl.h" | |
578 | EXPORT_C void _init(void *handle) { | |
579 | } | |
580 | __EOF__ | |
581 | close(_INIT_C); | |
582 | ||
583 | my @src = ( "_init.c", sort keys %src ); | |
584 | ||
585 | if ( $base eq "Encode" ) { # Currently unused. | |
586 | for my $submf ( glob("*/Makefile") ) { | |
587 | my $d = dirname($submf); | |
588 | print "Configuring Encode::$d...\n"; | |
589 | if ( open( SUBMF, $submf ) ) { | |
590 | if ( update_dir($d) ) { | |
591 | my @subsrc; | |
592 | while (<SUBMF>) { | |
593 | next if 1 .. /postamble/; | |
594 | if (m!^(\w+_t)\.c : !) { | |
c1c0c258 | 595 | system_echo( |
27da23d5 JH |
596 | "perl ..\\bin\\enc2xs -Q -o $1.c -f $1.fnm") |
597 | == 0 | |
598 | or warn "$0: enc2xs: $!\n"; | |
599 | push @subsrc, "$1.c"; | |
600 | } | |
601 | } | |
602 | close(SUBMF); | |
603 | unlink($submf); | |
604 | my $subbase = $d; | |
605 | $subbase =~ s!/!::!g; | |
606 | write_mmp( $subbase, ["..\\Encode"], "$subbase.c", | |
607 | @subsrc ); | |
608 | write_makefile( $subbase, $build ); | |
609 | write_bld_inf($subbase); | |
610 | ||
611 | unless ( | |
c1c0c258 JH |
612 | system_echo( |
613 | "perl -I$BUILDROOT\\lib ..\\$extu\\xsubpp -csuffix .cpp -typemap ..\\$extu\\typemap -noprototypes $subbase.xs > $subbase.c" | |
27da23d5 JH |
614 | ) == 0 |
615 | && -s "$subbase.c" | |
616 | ) | |
617 | { | |
618 | die "$0: perl xsubpp failed: $!\n"; | |
619 | } | |
620 | update_dir(".."); | |
621 | } | |
622 | else { | |
623 | warn "$0: chdir $d: $!\n"; | |
624 | } | |
625 | } | |
626 | else { | |
627 | warn "$0: $submf: $!"; | |
628 | } | |
629 | } | |
630 | print "Configuring Encode...\n"; | |
631 | } | |
632 | ||
633 | write_mmp( $base, [ keys %incdir ], @src ); | |
634 | write_makefile( $base, $build ); | |
635 | } | |
636 | my $lstname = $ext; | |
637 | $lstname =~ s:^ext\\::; | |
638 | $lstname =~ s:\\:-:g; | |
639 | print "\t$lstname.lst\n"; | |
640 | my $lstout = | |
c1c0c258 | 641 | $CoreBuild ? "$BUILDROOT/symbian/$lstname.lst" : "$BUILDROOT/$lstname.lst"; |
27da23d5 JH |
642 | if ( open( my $lst, ">$lstout" ) ) { |
643 | for my $f (@lst) { print $lst qq["$f"-"!:$lst{$f}"\n] } | |
644 | close($lst); | |
645 | } | |
646 | else { | |
647 | die "$0: $lstout: $!\n"; | |
648 | } | |
c1c0c258 | 649 | update_dir($BUILDROOT); |
27da23d5 JH |
650 | } |
651 | ||
652 | sub update_cwd { | |
653 | $CWD = getcwd(); | |
654 | $CWD =~ s!^[CD]:!!i; | |
655 | $CWD =~ s!/!\\!g; | |
656 | } | |
657 | ||
658 | for my $ext (@ARGV) { | |
659 | ||
660 | $ext =~ s!::!\\!g; | |
661 | $ext =~ s!/!\\!g; | |
662 | ||
663 | my $cfg; | |
664 | ||
665 | $cfg = $2 if $ext =~ s/(.+?),(.+)/$1/; | |
666 | ||
667 | my $dir; | |
668 | ||
669 | unless ( -e $ext ) { | |
670 | if ( $ext =~ /\.xs$/ && !-f $ext ) { | |
671 | if ( -f "ext\\$ext" ) { | |
672 | $ext = "ext\\$ext"; | |
673 | $dir = dirname($ext); | |
674 | } | |
675 | } | |
676 | elsif ( !-d $ext ) { | |
677 | if ( -d "ext\\$ext" ) { | |
678 | $ext = "ext\\$ext"; | |
679 | $dir = $ext; | |
680 | } | |
681 | } | |
682 | $dir = "." unless defined $dir; | |
683 | } | |
684 | else { | |
685 | if ( $ext =~ /\.xs$/ && -f $ext ) { | |
686 | $ext = dirname($ext); | |
687 | $dir = $ext; | |
688 | } | |
689 | elsif ( -d $ext ) { | |
690 | $dir = $ext; | |
691 | } | |
692 | } | |
693 | ||
694 | if ( $ext eq "XSLoader" ) { | |
695 | $ext = "ext\\XSLoader"; | |
696 | } | |
697 | if ( $ext eq "ext\\XSLoader" ) { | |
698 | $dir = "ext\\DynaLoader"; | |
699 | } | |
700 | ||
701 | $EXTCFG{$ext} = [ split( /,/, $cfg ) ] if defined $cfg; | |
702 | ||
703 | die "$0: no lib\\Config.pm\n" | |
704 | if $CoreBuild && $Build && !-f "lib\\Config.pm"; | |
705 | ||
706 | if ($CoreBuild) { | |
707 | open( my $cfg, "symbian/install.cfg" ) | |
708 | or die "$0: symbian/install.cfg: $!\n"; | |
709 | my $extdir = $dir; | |
710 | $extdir =~ s:^ext\\::; | |
711 | while (<$cfg>) { | |
712 | next unless /^ext\s+(.+)/; | |
713 | chomp; | |
714 | my $ext = $1; | |
715 | my @ext = split( ' ', $ext ); | |
716 | $EXTCFG{"ext\\$ext[0]"} = [@ext]; | |
717 | } | |
718 | close($cfg); | |
719 | } | |
720 | ||
721 | if ( $Config || $Build ) { | |
722 | xsconfig( $ext, $dir ) or die "$0: xsconfig '$ext' failed\n"; | |
723 | next if $Config; | |
724 | } | |
725 | ||
726 | my $chdir = $ext eq "ext\\XSLoader" ? "ext\\DynaLoader" : $dir; | |
727 | die "$0: no directory '$chdir'\n" unless -d $chdir; | |
728 | update_dir($chdir) or die "$0: chdir '$chdir' failed: $!\n"; | |
729 | ||
730 | my %CONF; | |
731 | ||
732 | my @ext = split( /\\/, $ext ); | |
733 | my $base = $ext[-1]; | |
734 | ||
735 | if ( $Clean || $DistClean ) { | |
736 | print "Cleaning $ext...\n"; | |
737 | unlink("bld.inf"); | |
738 | unlink("$base.mmp"); | |
739 | unlink("_init.c"); | |
740 | unlink("const-c.inc"); | |
741 | unlink("const-xs.inc"); | |
742 | rmdir("..\\bmarm"); | |
743 | } | |
744 | ||
745 | if ( $Build && $ext ne "ext\\XSLoader" && $ext ne "ext\\Errno" ) { | |
746 | ||
747 | # We compile the extension three (3) times. | |
748 | # (1) Only the _init.c to get _init() as the ordinal 1 function in the DLL. | |
749 | # (2) With the rest and the _init.c to get ordinals for the rest. | |
750 | # (3) With an updated _init.c that carries the symbols from step (2). | |
751 | ||
c1c0c258 | 752 | system_echo("make clean"); |
c8f896e5 | 753 | system_echo("make defrost") == 0 or warn "$0: make defrost failed\n"; |
27da23d5 JH |
754 | |
755 | my @TARGET; | |
756 | ||
757 | push @TARGET, 'sis' if $Sis; | |
758 | ||
759 | # Compile #1. | |
760 | # Hide all but the _init.c. | |
761 | print "\n*** $ext - Compile 1 of 3.\n\n"; | |
c1c0c258 | 762 | print "(patching $base.mmp)\n"; |
27da23d5 JH |
763 | system( |
764 | "perl -pi.bak -e \"s:^SOURCE\\s+_init.c:SOURCE\\t_init.c // :\" $base.mmp" | |
765 | ); | |
c1c0c258 JH |
766 | system_echo("bldmake bldfiles"); |
767 | system_echo("make @TARGET") == 0 or die "$0: make #1 failed\n"; | |
27da23d5 JH |
768 | |
769 | # Compile #2. | |
770 | # Reveal the rest again. | |
771 | print "\n*** $ext - Compile 2 of 3.\n\n"; | |
c1c0c258 | 772 | print "(patching $base.mmp)\n"; |
27da23d5 JH |
773 | system( |
774 | "perl -pi.bak -e \"s:^SOURCE\\t_init.c // :SOURCE\\t_init.c :\" $base.mmp" | |
775 | ); | |
c1c0c258 | 776 | system_echo("make @TARGET") == 0 or die "$0: make #2 failed\n"; |
27da23d5 JH |
777 | unlink("$base.mmp.bak"); |
778 | ||
779 | open( _INIT_C, ">_init.c" ) or die "$0: _init.c: $!\n"; | |
780 | print _INIT_C <<'__EOF__'; | |
781 | #include "EXTERN.h" | |
782 | #include "perl.h" | |
783 | ||
784 | /* This is a different but matching definition from in dl_symbian.xs. */ | |
785 | typedef struct { | |
786 | void* handle; | |
787 | int error; | |
788 | HV* symbols; | |
789 | } PerlSymbianLibHandle; | |
790 | ||
791 | EXPORT_C void _init(void* handle) { | |
792 | __EOF__ | |
793 | ||
794 | my %symbol; | |
795 | my $def; | |
796 | my $basef; | |
797 | for my $f ("$SDK\\Epoc32\\Build$CWD\\$base\\WINS\\$base.def", | |
798 | "..\\BMARM\\${base}u.def") { | |
799 | print "\t($f - "; | |
800 | if ( open( $def, $f ) ) { | |
801 | print "OK)\n"; | |
802 | $basef = $f; | |
803 | last; | |
804 | } else { | |
805 | print "no)\n"; | |
806 | } | |
807 | } | |
808 | unless (defined $basef) { | |
809 | die "$0: failed to find .def for $base\n"; | |
810 | } | |
811 | while (<$def>) { | |
812 | next while 1 .. /^EXPORTS/; | |
813 | if (/^\s*(\w+) \@ (\d+) /) { | |
814 | $symbol{$1} = $2; | |
815 | } | |
816 | } | |
817 | close($def); | |
818 | ||
819 | my @symbol = sort keys %symbol; | |
820 | if (@symbol) { | |
821 | print _INIT_C <<'__EOF__'; | |
822 | dTHX; | |
823 | PerlSymbianLibHandle* h = (PerlSymbianLibHandle*)handle; | |
824 | if (!h->symbols) | |
825 | h->symbols = newHV(); | |
826 | if (h->symbols) { | |
827 | __EOF__ | |
828 | for my $sym (@symbol) { | |
829 | my $len = length($sym); | |
830 | print _INIT_C <<__EOF__; | |
831 | hv_store(h->symbols, "$sym", $len, newSViv($symbol{$sym}), 0); | |
832 | __EOF__ | |
833 | } | |
834 | } | |
835 | else { | |
836 | die "$0: $basef: no exports found\n"; | |
837 | } | |
838 | ||
839 | print _INIT_C <<'__EOF__'; | |
840 | } | |
841 | } | |
842 | __EOF__ | |
843 | close(_INIT_C); | |
844 | ||
845 | # Compile #3. This is for real. | |
846 | print "\n*** $ext - Compile 3 of 3.\n\n"; | |
c1c0c258 | 847 | system_echo("make @TARGET") == 0 or die "$0: make #3 failed\n"; |
27da23d5 JH |
848 | |
849 | } | |
850 | elsif ( $Clean || $DistClean ) { | |
851 | if ( $ext eq "ext\\Errno" ) { | |
852 | unlink( "Errno.pm", "Makefile" ); | |
853 | } | |
854 | else { | |
855 | if ( -f "Makefile" ) { | |
856 | if ($Clean) { | |
c1c0c258 | 857 | system_echo("make clean") == 0 or die "$0: make clean failed\n"; |
27da23d5 JH |
858 | } |
859 | elsif ($DistClean) { | |
c1c0c258 | 860 | system_echo("make distclean") == 0 |
27da23d5 JH |
861 | or die "$0: make distclean failed\n"; |
862 | } | |
863 | } | |
864 | if ( $ext eq "ext\\Devel\\PPPort" ) { | |
865 | unlink("ppport.h"); | |
866 | } | |
867 | } | |
868 | my @B = glob("ext/BWINS ext/BMARM ext/*/BWINS ext/*/BMARM Makefile"); | |
869 | rmdir(@B) if @B; | |
870 | } | |
871 | ||
c1c0c258 | 872 | update_dir($BUILDROOT); |
27da23d5 JH |
873 | |
874 | } # for my $ext | |
875 | ||
876 | exit(0); | |
877 |