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