Commit | Line | Data |
27da23d5 |
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; |
37 | my $WIN; |
38 | my $ARM; |
c1c0c258 |
39 | my $BUILDROOT = getcwd(); |
27da23d5 |
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 |
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 | |
104 | $VERSION =~ tr/.//d; |
105 | |
106 | $ENV{SDK} = $SDK; # For the Errno extension |
107 | $ENV{CROSS} = 1; # For the Encode extension |
108 | |
109 | my $UREL = $ENV{UREL}; # from sdk.pl |
110 | $UREL =~ s/-ARM-/$ARM/; |
111 | my $UARM = $ENV{UARM}; # from sdk.pl |
112 | my $SRCDBG = $UARM eq 'udeb' ? "SRCDBG" : ""; |
113 | |
114 | my %CONF; |
115 | my %EXTCFG; |
116 | |
117 | sub 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__; |
122 | PRJ_MMPFILES |
123 | $base.mmp |
124 | PRJ_PLATFORMS |
125 | $WIN $ARM |
126 | __EOF__ |
127 | close(BLD_INF); |
128 | } |
129 | |
130 | sub system_echo { |
131 | my $cmd = shift; |
132 | print "xsbuild: ", $cmd, "\n"; |
133 | return system($cmd); |
134 | } |
135 | |
136 | sub 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 | |
164 | sub read_old_multi { |
165 | my ( $conf, $k ) = @_; |
166 | push @{ $conf->{$k} }, split( ' ', $1 ) if /^$k\s(.+)$/; |
167 | } |
168 | |
169 | sub 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 | |
181 | sub 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 | |
201 | sub 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__; |
244 | TARGET $CONF{TARGET} |
245 | TARGETTYPE dll |
246 | TARGETPATH $CONF{TARGETPATH} |
247 | SOURCE @{$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__; |
257 | LIBRARY @{$CONF{LIBRARY}} |
258 | MACRO @{$CONF{MACRO}} |
259 | // OPTION MSVC /P |
260 | // OPTION GCC -E |
261 | __EOF__ |
262 | close(BASE_MMP); |
263 | |
264 | } |
265 | |
266 | sub 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__; |
281 | WIN = $WIN |
282 | ARM = $ARM |
283 | ABLD = $ABLD |
284 | |
285 | all: build freeze |
286 | |
287 | sis: build_arm freeze_arm |
288 | |
289 | build: abld.bat build_win build_arm |
290 | |
291 | abld.bat: |
292 | bldmake bldfiles |
293 | |
294 | build_win: abld.bat |
295 | bldmake bldfiles |
296 | \$(ABLD) build \$(WIN) udeb |
297 | |
298 | build_arm: abld.bat |
299 | bldmake bldfiles |
300 | \$(ABLD) build \$(ARM) $UARM |
301 | |
302 | win: build_win freeze_win |
303 | |
304 | arm: build_arm freeze_arm |
305 | |
306 | freeze: freeze_win freeze_arm |
307 | |
308 | freeze_win: |
309 | bldmake bldfiles |
310 | \$(ABLD) freeze \$(WIN) $base |
311 | |
312 | freeze_arm: |
313 | bldmake bldfiles |
314 | \$(ABLD) freeze \$(ARM) $base |
315 | |
316 | defrost: defrost_win defrost_arm |
317 | |
318 | defrost_win: |
319 | -del /f $windef1 |
320 | -del /f $windef2 |
321 | |
322 | defrost_arm: |
323 | -del /f $armdef1 |
324 | -del /f $armdef2 |
325 | |
326 | clean: clean_win clean_arm |
327 | |
328 | clean_win: |
329 | \$(ABLD) clean \$(WIN) |
330 | |
331 | clean_arm: |
332 | \$(ABLD) clean \$(ARM) |
333 | |
334 | realclean: clean realclean_win realclean_arm |
335 | -del /f _init.c b.pl |
336 | -del /f $base.c $base.mmp |
337 | |
338 | realclean_win: |
339 | \$(ABLD) reallyclean \$(WIN) |
340 | |
341 | realclean_arm: |
342 | \$(ABLD) reallyclean \$(ARM) |
343 | |
344 | distclean: 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. |
356 | delete $ENV{MFLAGS}; |
357 | delete $ENV{MAKEFLAGS}; |
358 | |
359 | print "abld @ARGV\n"; |
c1c0c258 |
360 | system_echo("abld @ARGV"); |
27da23d5 |
361 | __EOF__ |
362 | close(B); |
363 | } else { |
364 | warn "$0: failed to create b.pl: $!\n"; |
365 | } |
366 | } |
367 | } |
368 | |
369 | sub update_dir { |
370 | print "[chdir from ", getcwd(), " to "; |
371 | chdir(shift) or return; |
372 | update_cwd(); |
373 | print getcwd(), "]\n"; |
374 | } |
375 | |
376 | sub 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 | |
645 | sub update_cwd { |
646 | $CWD = getcwd(); |
647 | $CWD =~ s!^[CD]:!!i; |
648 | $CWD =~ s!/!\\!g; |
649 | } |
650 | |
651 | for 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. */ |
778 | typedef struct { |
779 | void* handle; |
780 | int error; |
781 | HV* symbols; |
782 | } PerlSymbianLibHandle; |
783 | |
784 | EXPORT_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 | |
869 | exit(0); |
870 | |