This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
blead@25775 Symbian update
[perl5.git] / symbian / xsbuild.pl
CommitLineData
27da23d5
JH
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;
c8f896e5
JH
37my $WIN = 'wins';
38my $ARM = 'thumb';
c1c0c258 39my $BUILDROOT = getcwd();
27da23d5
JH
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
JH
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
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
111my $UARM = 'urel';
112my $UREL = "$SDK\\epoc32\\release\\-ARM-\\$UARM";
113my $SRCDBG;
114if (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
121my %CONF;
122my %EXTCFG;
123
124sub 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__;
129PRJ_MMPFILES
130$base.mmp
131PRJ_PLATFORMS
132$WIN $ARM
133__EOF__
134 close(BLD_INF);
135}
136
137sub system_echo {
138 my $cmd = shift;
139 print "xsbuild: ", $cmd, "\n";
140 return system($cmd);
141}
142
143sub 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
171sub read_old_multi {
172 my ( $conf, $k ) = @_;
173 push @{ $conf->{$k} }, split( ' ', $1 ) if /^$k\s(.+)$/;
174}
175
176sub 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
188sub 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
208sub 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__;
255TARGET $CONF{TARGET}
256TARGETTYPE dll
257TARGETPATH $CONF{TARGETPATH}
258SOURCE @{$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__;
268LIBRARY @{$CONF{LIBRARY}}
269MACRO @{$CONF{MACRO}}
270// OPTION MSVC /P
271// OPTION GCC -E
272__EOF__
273 close(BASE_MMP);
274
275}
276
277sub 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__;
292WIN = $WIN
293ARM = $ARM
294ABLD = $ABLD
295
296all: build freeze
297
298sis: build_arm freeze_arm
299
300build: abld.bat build_win build_arm
301
302abld.bat:
303 bldmake bldfiles
304
305build_win: abld.bat
306 bldmake bldfiles
307 \$(ABLD) build \$(WIN) udeb
308
309build_arm: abld.bat
310 bldmake bldfiles
311 \$(ABLD) build \$(ARM) $UARM
312
313win: build_win freeze_win
314
315arm: build_arm freeze_arm
316
317freeze: freeze_win freeze_arm
318
319freeze_win:
320 bldmake bldfiles
321 \$(ABLD) freeze \$(WIN) $base
322
323freeze_arm:
324 bldmake bldfiles
325 \$(ABLD) freeze \$(ARM) $base
326
327defrost: defrost_win defrost_arm
328
329defrost_win:
330 -del /f $windef1
331 -del /f $windef2
332
333defrost_arm:
334 -del /f $armdef1
335 -del /f $armdef2
336
337clean: clean_win clean_arm
338
339clean_win:
340 \$(ABLD) clean \$(WIN)
341
342clean_arm:
343 \$(ABLD) clean \$(ARM)
344
345realclean: clean realclean_win realclean_arm
346 -del /f _init.c b.pl
347 -del /f $base.c $base.mmp
348
349realclean_win:
350 \$(ABLD) reallyclean \$(WIN)
351
352realclean_arm:
353 \$(ABLD) reallyclean \$(ARM)
354
355distclean: 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.
367delete $ENV{MFLAGS};
368delete $ENV{MAKEFLAGS};
369
370print "abld @ARGV\n";
c1c0c258 371system_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
380sub update_dir {
381 print "[chdir from ", getcwd(), " to ";
382 chdir(shift) or return;
383 update_cwd();
384 print getcwd(), "]\n";
385}
386
387sub 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
652sub update_cwd {
653 $CWD = getcwd();
654 $CWD =~ s!^[CD]:!!i;
655 $CWD =~ s!/!\\!g;
656}
657
658for 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. */
785typedef struct {
786 void* handle;
787 int error;
788 HV* symbols;
789} PerlSymbianLibHandle;
790
791EXPORT_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
876exit(0);
877