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