This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
hints/aix_4.sh to allow build on aix 4.2
[perl5.git] / lib / ExtUtils / CBuilder / Platform / Windows.pm
CommitLineData
6b09c160
YST
1package ExtUtils::CBuilder::Platform::Windows;
2
3use strict;
4use warnings;
5
6use File::Basename;
7use File::Spec;
8
9use ExtUtils::CBuilder::Base;
10
11use vars qw($VERSION @ISA);
8a6e5c04 12$VERSION = '0.21';
6b09c160
YST
13@ISA = qw(ExtUtils::CBuilder::Base);
14
15sub new {
16 my $class = shift;
17 my $self = $class->SUPER::new(@_);
18 my $cf = $self->{config};
19
20 # Inherit from an appropriate compiler driver class
21 unshift @ISA, "ExtUtils::CBuilder::Platform::Windows::" . $self->_compiler_type;
22
23 return $self;
24}
25
26sub _compiler_type {
27 my $self = shift;
28 my $cc = $self->{config}{cc};
29
30 return ( $cc =~ /cl(\.exe)?$/ ? 'MSVC'
31 : $cc =~ /bcc32(\.exe)?$/ ? 'BCC'
32 : 'GCC');
33}
34
35sub split_like_shell {
36 # As it turns out, Windows command-parsing is very different from
37 # Unix command-parsing. Double-quotes mean different things,
38 # backslashes don't necessarily mean escapes, and so on. So we
39 # can't use Text::ParseWords::shellwords() to break a command string
40 # into words. The algorithm below was bashed out by Randy and Ken
41 # (mostly Randy), and there are a lot of regression tests, so we
42 # should feel free to adjust if desired.
43
44 (my $self, local $_) = @_;
45
46 return @$_ if defined() && UNIVERSAL::isa($_, 'ARRAY');
47
48 my @argv;
49 return @argv unless defined() && length();
50
51 my $arg = '';
52 my( $i, $quote_mode ) = ( 0, 0 );
53
54 while ( $i < length() ) {
55
56 my $ch = substr( $_, $i , 1 );
57 my $next_ch = substr( $_, $i+1, 1 );
58
59 if ( $ch eq '\\' && $next_ch eq '"' ) {
60 $arg .= '"';
61 $i++;
62 } elsif ( $ch eq '\\' && $next_ch eq '\\' ) {
63 $arg .= '\\';
64 $i++;
65 } elsif ( $ch eq '"' && $next_ch eq '"' && $quote_mode ) {
66 $quote_mode = !$quote_mode;
67 $arg .= '"';
68 $i++;
69 } elsif ( $ch eq '"' && $next_ch eq '"' && !$quote_mode &&
70 ( $i + 2 == length() ||
71 substr( $_, $i + 2, 1 ) eq ' ' )
72 ) { # for cases like: a"" => [ 'a' ]
73 push( @argv, $arg );
74 $arg = '';
75 $i += 2;
76 } elsif ( $ch eq '"' ) {
77 $quote_mode = !$quote_mode;
78 } elsif ( $ch eq ' ' && !$quote_mode ) {
79 push( @argv, $arg ) if $arg;
80 $arg = '';
81 ++$i while substr( $_, $i + 1, 1 ) eq ' ';
82 } else {
83 $arg .= $ch;
84 }
85
86 $i++;
87 }
88
89 push( @argv, $arg ) if defined( $arg ) && length( $arg );
90 return @argv;
91}
92
d1cf867f
SP
93sub arg_defines {
94 my ($self, %args) = @_;
95 s/"/\\"/g foreach values %args;
ea2e6518 96 return map qq{"-D$_=$args{$_}"}, keys %args;
d1cf867f
SP
97}
98
6b09c160
YST
99sub compile {
100 my ($self, %args) = @_;
101 my $cf = $self->{config};
102
103 die "Missing 'source' argument to compile()" unless defined $args{source};
104
105 my ($basename, $srcdir) =
106 ( File::Basename::fileparse($args{source}, '\.[^.]+$') )[0,1];
107
108 $srcdir ||= File::Spec->curdir();
109
d1cf867f
SP
110 my @defines = $self->arg_defines( %{ $args{defines} || {} } );
111
6b09c160
YST
112 my %spec = (
113 srcdir => $srcdir,
114 builddir => $srcdir,
115 basename => $basename,
116 source => $args{source},
117 output => File::Spec->catfile($srcdir, $basename) . $cf->{obj_ext},
118 cc => $cf->{cc},
119 cflags => [
120 $self->split_like_shell($cf->{ccflags}),
121 $self->split_like_shell($cf->{cccdlflags}),
d1cf867f 122 $self->split_like_shell($cf->{extra_compiler_flags}),
6b09c160
YST
123 ],
124 optimize => [ $self->split_like_shell($cf->{optimize}) ],
d1cf867f 125 defines => \@defines,
6b09c160
YST
126 includes => [ @{$args{include_dirs} || []} ],
127 perlinc => [
128 $self->perl_inc(),
129 $self->split_like_shell($cf->{incpath}),
130 ],
131 use_scripts => 1, # XXX provide user option to change this???
132 );
133
6b09c160
YST
134 $self->normalize_filespecs(
135 \$spec{source},
136 \$spec{output},
137 $spec{includes},
138 $spec{perlinc},
139 );
140
141 my @cmds = $self->format_compiler_cmd(%spec);
142 while ( my $cmd = shift @cmds ) {
143 $self->do_system( @$cmd )
144 or die "error building $cf->{dlext} file from '$args{source}'";
145 }
146
147 (my $out = $spec{output}) =~ tr/'"//d;
148 return $out;
149}
150
151sub need_prelink { 1 }
152
153sub link {
154 my ($self, %args) = @_;
155 my $cf = $self->{config};
156
157 my @objects = ( ref $args{objects} eq 'ARRAY' ? @{$args{objects}} : $args{objects} );
158 my $to = join '', (File::Spec->splitpath($objects[0]))[0,1];
159 $to ||= File::Spec->curdir();
160
161 (my $file_base = $args{module_name}) =~ s/.*:://;
162 my $output = $args{lib_file} ||
163 File::Spec->catfile($to, "$file_base.$cf->{dlext}");
164
165 # if running in perl source tree, look for libs there, not installed
166 my $lddlflags = $cf->{lddlflags};
167 my $perl_src = $self->perl_src();
345dbb93 168 $lddlflags =~ s/\Q$cf->{archlibexp}\E[\\\/]CORE/$perl_src/ if $perl_src;
6b09c160
YST
169
170 my %spec = (
171 srcdir => $to,
172 builddir => $to,
173 startup => [ ],
174 objects => \@objects,
175 libs => [ ],
176 output => $output,
177 ld => $cf->{ld},
178 libperl => $cf->{libperl},
179 perllibs => [ $self->split_like_shell($cf->{perllibs}) ],
180 libpath => [ $self->split_like_shell($cf->{libpth}) ],
181 lddlflags => [ $self->split_like_shell($lddlflags) ],
182 other_ldflags => [ $self->split_like_shell($args{extra_linker_flags} || '') ],
183 use_scripts => 1, # XXX provide user option to change this???
184 );
185
186 unless ( $spec{basename} ) {
187 ($spec{basename} = $args{module_name}) =~ s/.*:://;
188 }
189
190 $spec{srcdir} = File::Spec->canonpath( $spec{srcdir} );
191 $spec{builddir} = File::Spec->canonpath( $spec{builddir} );
192
193 $spec{output} ||= File::Spec->catfile( $spec{builddir},
194 $spec{basename} . '.'.$cf->{dlext} );
3172152a
SH
195 $spec{manifest} ||= File::Spec->catfile( $spec{builddir},
196 $spec{basename} . '.'.$cf->{dlext}.'.manifest');
6b09c160
YST
197 $spec{implib} ||= File::Spec->catfile( $spec{builddir},
198 $spec{basename} . $cf->{lib_ext} );
199 $spec{explib} ||= File::Spec->catfile( $spec{builddir},
200 $spec{basename} . '.exp' );
ea4d13ef
SH
201 if ($cf->{cc} eq 'cl') {
202 $spec{dbg_file} ||= File::Spec->catfile( $spec{builddir},
203 $spec{basename} . '.pdb' );
204 }
205 elsif ($cf->{cc} eq 'bcc32') {
206 $spec{dbg_file} ||= File::Spec->catfile( $spec{builddir},
207 $spec{basename} . '.tds' );
208 }
6b09c160
YST
209 $spec{def_file} ||= File::Spec->catfile( $spec{srcdir} ,
210 $spec{basename} . '.def' );
211 $spec{base_file} ||= File::Spec->catfile( $spec{srcdir} ,
212 $spec{basename} . '.base' );
213
214 $self->add_to_cleanup(
215 grep defined,
ea4d13ef 216 @{[ @spec{qw(manifest implib explib dbg_file def_file base_file map_file)} ]}
6b09c160
YST
217 );
218
ea4d13ef 219 foreach my $opt ( qw(output manifest implib explib dbg_file def_file map_file base_file) ) {
6b09c160
YST
220 $self->normalize_filespecs( \$spec{$opt} );
221 }
222
223 foreach my $opt ( qw(libpath startup objects) ) {
224 $self->normalize_filespecs( $spec{$opt} );
225 }
226
227 (my $def_base = $spec{def_file}) =~ tr/'"//d;
228 $def_base =~ s/\.def$//;
229 $self->prelink( dl_name => $args{module_name},
230 dl_file => $def_base,
231 dl_base => $spec{basename} );
232
233 my @cmds = $self->format_linker_cmd(%spec);
234 while ( my $cmd = shift @cmds ) {
235 $self->do_system( @$cmd );
236 }
237
238 $spec{output} =~ tr/'"//d;
239 return wantarray
ea4d13ef 240 ? grep defined, @spec{qw[output manifest implib explib dbg_file def_file map_file base_file]}
6b09c160
YST
241 : $spec{output};
242}
243
244# canonize & quote paths
245sub normalize_filespecs {
246 my ($self, @specs) = @_;
247 foreach my $spec ( grep defined, @specs ) {
248 if ( ref $spec eq 'ARRAY') {
249 $self->normalize_filespecs( map {\$_} grep defined, @$spec )
250 } elsif ( ref $spec eq 'SCALAR' ) {
251 $$spec =~ tr/"//d if $$spec;
252 next unless $$spec;
253 $$spec = '"' . File::Spec->canonpath($$spec) . '"';
254 } elsif ( ref $spec eq '' ) {
255 $spec = '"' . File::Spec->canonpath($spec) . '"';
256 } else {
257 die "Don't know how to normalize " . (ref $spec || $spec) . "\n";
258 }
259 }
260}
261
262# directory of perl's include files
263sub perl_inc {
264 my $self = shift;
265
266 my $perl_src = $self->perl_src();
267
268 if ($perl_src) {
269 File::Spec->catdir($perl_src, "lib", "CORE");
270 } else {
271 File::Spec->catdir($self->{config}{archlibexp},"CORE");
272 }
273}
274
2751;
276
277########################################################################
278
279=begin comment
280
281The packages below implement functions for generating properly
3c4b39be 282formatted commandlines for the compiler being used. Each package
6b09c160
YST
283defines two primary functions 'format_linker_cmd()' &
284'format_compiler_cmd()' that accepts a list of named arguments (a
3c4b39be 285hash) and returns a list of formatted options suitable for invoking the
6b09c160
YST
286compiler. By default, if the compiler supports scripting of its
287operation then a script file is built containing the options while
288those options are removed from the commandline, and a reference to the
289script is pushed onto the commandline in their place. Scripting the
290compiler in this way helps to avoid the problems associated with long
291commandlines under some shells.
292
293=end comment
294
295=cut
296
297########################################################################
298package ExtUtils::CBuilder::Platform::Windows::MSVC;
299
300sub format_compiler_cmd {
301 my ($self, %spec) = @_;
302
303 foreach my $path ( @{ $spec{includes} || [] },
304 @{ $spec{perlinc} || [] } ) {
305 $path = '-I' . $path;
306 }
307
308 %spec = $self->write_compiler_script(%spec)
309 if $spec{use_scripts};
310
311 return [ grep {defined && length} (
312 $spec{cc},'-nologo','-c',
313 @{$spec{includes}} ,
314 @{$spec{cflags}} ,
315 @{$spec{optimize}} ,
316 @{$spec{defines}} ,
317 @{$spec{perlinc}} ,
318 "-Fo$spec{output}" ,
319 $spec{source} ,
320 ) ];
321}
322
323sub write_compiler_script {
324 my ($self, %spec) = @_;
325
326 my $script = File::Spec->catfile( $spec{srcdir},
327 $spec{basename} . '.ccs' );
328
329 $self->add_to_cleanup($script);
6b09c160
YST
330 print "Generating script '$script'\n" if !$self->{quiet};
331
332 open( SCRIPT, ">$script" )
333 or die( "Could not create script '$script': $!" );
334
335 print SCRIPT join( "\n",
336 map { ref $_ ? @{$_} : $_ }
337 grep defined,
338 delete(
339 @spec{ qw(includes cflags optimize defines perlinc) } )
340 );
341
342 close SCRIPT;
343
344 push @{$spec{includes}}, '@"' . $script . '"';
345
346 return %spec;
347}
348
349sub format_linker_cmd {
350 my ($self, %spec) = @_;
3172152a 351 my $cf = $self->{config};
6b09c160
YST
352
353 foreach my $path ( @{$spec{libpath}} ) {
354 $path = "-libpath:$path";
355 }
356
3172152a
SH
357 my $output = $spec{output};
358
359 $spec{def_file} &&= '-def:' . $spec{def_file};
360 $spec{output} &&= '-out:' . $spec{output};
361 $spec{manifest} &&= '-manifest ' . $spec{manifest};
362 $spec{implib} &&= '-implib:' . $spec{implib};
363 $spec{map_file} &&= '-map:' . $spec{map_file};
6b09c160
YST
364
365 %spec = $self->write_linker_script(%spec)
366 if $spec{use_scripts};
367
3172152a
SH
368 my @cmds; # Stores the series of commands needed to build the module.
369
370 push @cmds, [ grep {defined && length} (
6b09c160
YST
371 $spec{ld} ,
372 @{$spec{lddlflags}} ,
373 @{$spec{libpath}} ,
374 @{$spec{other_ldflags}} ,
375 @{$spec{startup}} ,
376 @{$spec{objects}} ,
377 $spec{map_file} ,
378 $spec{libperl} ,
379 @{$spec{perllibs}} ,
380 $spec{def_file} ,
381 $spec{implib} ,
382 $spec{output} ,
383 ) ];
3172152a 384
f6397ea5
JD
385 # Embed the manifest file for VC 2005 (aka VC 8) or higher, but not for the 64-bit Platform SDK compiler
386 if ($cf->{ivsize} == 4 && $cf->{cc} eq 'cl' and $cf->{ccversion} =~ /^(\d+)/ and $1 >= 14) {
3172152a
SH
387 push @cmds, [
388 'mt', '-nologo', $spec{manifest}, '-outputresource:' . "$output;2"
389 ];
390 }
391
392 return @cmds;
6b09c160
YST
393}
394
395sub write_linker_script {
396 my ($self, %spec) = @_;
397
398 my $script = File::Spec->catfile( $spec{srcdir},
399 $spec{basename} . '.lds' );
400
401 $self->add_to_cleanup($script);
402
403 print "Generating script '$script'\n" if !$self->{quiet};
404
405 open( SCRIPT, ">$script" )
406 or die( "Could not create script '$script': $!" );
407
408 print SCRIPT join( "\n",
409 map { ref $_ ? @{$_} : $_ }
410 grep defined,
411 delete(
412 @spec{ qw(lddlflags libpath other_ldflags
413 startup objects libperl perllibs
414 def_file implib map_file) } )
415 );
416
417 close SCRIPT;
418
419 push @{$spec{lddlflags}}, '@"' . $script . '"';
420
421 return %spec;
422}
423
4241;
425
426########################################################################
427package ExtUtils::CBuilder::Platform::Windows::BCC;
428
429sub format_compiler_cmd {
430 my ($self, %spec) = @_;
431
432 foreach my $path ( @{ $spec{includes} || [] },
433 @{ $spec{perlinc} || [] } ) {
434 $path = '-I' . $path;
435 }
436
437 %spec = $self->write_compiler_script(%spec)
438 if $spec{use_scripts};
439
440 return [ grep {defined && length} (
441 $spec{cc}, '-c' ,
442 @{$spec{includes}} ,
443 @{$spec{cflags}} ,
444 @{$spec{optimize}} ,
445 @{$spec{defines}} ,
446 @{$spec{perlinc}} ,
447 "-o$spec{output}" ,
448 $spec{source} ,
449 ) ];
450}
451
452sub write_compiler_script {
453 my ($self, %spec) = @_;
454
455 my $script = File::Spec->catfile( $spec{srcdir},
456 $spec{basename} . '.ccs' );
457
458 $self->add_to_cleanup($script);
459
460 print "Generating script '$script'\n" if !$self->{quiet};
461
462 open( SCRIPT, ">$script" )
463 or die( "Could not create script '$script': $!" );
464
3b91ae7a
RS
465 # XXX Borland "response files" seem to be unable to accept macro
466 # definitions containing quoted strings. Escaping strings with
467 # backslash doesn't work, and any level of quotes are stripped. The
468 # result is is a floating point number in the source file where a
469 # string is expected. So we leave the macros on the command line.
6b09c160
YST
470 print SCRIPT join( "\n",
471 map { ref $_ ? @{$_} : $_ }
472 grep defined,
473 delete(
3b91ae7a 474 @spec{ qw(includes cflags optimize perlinc) } )
6b09c160
YST
475 );
476
477 close SCRIPT;
478
479 push @{$spec{includes}}, '@"' . $script . '"';
480
481 return %spec;
482}
483
484sub format_linker_cmd {
485 my ($self, %spec) = @_;
486
487 foreach my $path ( @{$spec{libpath}} ) {
488 $path = "-L$path";
489 }
490
491 push( @{$spec{startup}}, 'c0d32.obj' )
492 unless ( $spec{starup} && @{$spec{startup}} );
493
494 %spec = $self->write_linker_script(%spec)
495 if $spec{use_scripts};
496
497 return [ grep {defined && length} (
498 $spec{ld} ,
499 @{$spec{lddlflags}} ,
500 @{$spec{libpath}} ,
501 @{$spec{other_ldflags}} ,
502 @{$spec{startup}} ,
503 @{$spec{objects}} , ',',
504 $spec{output} , ',',
505 $spec{map_file} , ',',
506 $spec{libperl} ,
507 @{$spec{perllibs}} , ',',
508 $spec{def_file}
509 ) ];
510}
511
512sub write_linker_script {
513 my ($self, %spec) = @_;
514
515 # To work around Borlands "unique" commandline syntax,
516 # two scripts are used:
517
518 my $ld_script = File::Spec->catfile( $spec{srcdir},
519 $spec{basename} . '.lds' );
520 my $ld_libs = File::Spec->catfile( $spec{srcdir},
521 $spec{basename} . '.lbs' );
522
523 $self->add_to_cleanup($ld_script, $ld_libs);
524
525 print "Generating scripts '$ld_script' and '$ld_libs'.\n" if !$self->{quiet};
526
527 # Script 1: contains options & names of object files.
528 open( LD_SCRIPT, ">$ld_script" )
529 or die( "Could not create linker script '$ld_script': $!" );
530
531 print LD_SCRIPT join( " +\n",
532 map { @{$_} }
533 grep defined,
534 delete(
535 @spec{ qw(lddlflags libpath other_ldflags startup objects) } )
536 );
537
538 close LD_SCRIPT;
539
540 # Script 2: contains name of libs to link against.
541 open( LD_LIBS, ">$ld_libs" )
542 or die( "Could not create linker script '$ld_libs': $!" );
543
544 print LD_LIBS join( " +\n",
545 (delete $spec{libperl} || ''),
546 @{delete $spec{perllibs} || []},
547 );
548
549 close LD_LIBS;
550
551 push @{$spec{lddlflags}}, '@"' . $ld_script . '"';
552 push @{$spec{perllibs}}, '@"' . $ld_libs . '"';
553
554 return %spec;
555}
556
5571;
558
559########################################################################
560package ExtUtils::CBuilder::Platform::Windows::GCC;
561
562sub format_compiler_cmd {
563 my ($self, %spec) = @_;
564
565 foreach my $path ( @{ $spec{includes} || [] },
566 @{ $spec{perlinc} || [] } ) {
567 $path = '-I' . $path;
568 }
569
570 # split off any -arguments included in cc
571 my @cc = split / (?=-)/, $spec{cc};
572
573 return [ grep {defined && length} (
574 @cc, '-c' ,
575 @{$spec{includes}} ,
576 @{$spec{cflags}} ,
577 @{$spec{optimize}} ,
578 @{$spec{defines}} ,
579 @{$spec{perlinc}} ,
580 '-o', $spec{output} ,
581 $spec{source} ,
582 ) ];
583}
584
585sub format_linker_cmd {
586 my ($self, %spec) = @_;
587
588 # The Config.pm variable 'libperl' is hardcoded to the full name
589 # of the perl import library (i.e. 'libperl56.a'). GCC will not
590 # find it unless the 'lib' prefix & the extension are stripped.
591 $spec{libperl} =~ s/^(?:lib)?([^.]+).*$/-l$1/;
592
593 unshift( @{$spec{other_ldflags}}, '-nostartfiles' )
594 if ( $spec{startup} && @{$spec{startup}} );
595
596 # From ExtUtils::MM_Win32:
597 #
598 ## one thing for GCC/Mingw32:
599 ## we try to overcome non-relocateable-DLL problems by generating
600 ## a (hopefully unique) image-base from the dll's name
601 ## -- BKS, 10-19-1999
602 File::Basename::basename( $spec{output} ) =~ /(....)(.{0,4})/;
603 $spec{image_base} = sprintf( "0x%x0000", unpack('n', $1 ^ $2) );
604
605 %spec = $self->write_linker_script(%spec)
606 if $spec{use_scripts};
607
608 foreach my $path ( @{$spec{libpath}} ) {
609 $path = "-L$path";
610 }
611
612 my @cmds; # Stores the series of commands needed to build the module.
613
614 push @cmds, [
615 'dlltool', '--def' , $spec{def_file},
616 '--output-exp' , $spec{explib}
617 ];
618
619 # split off any -arguments included in ld
620 my @ld = split / (?=-)/, $spec{ld};
621
622 push @cmds, [ grep {defined && length} (
623 @ld ,
624 '-o', $spec{output} ,
625 "-Wl,--base-file,$spec{base_file}" ,
626 "-Wl,--image-base,$spec{image_base}" ,
627 @{$spec{lddlflags}} ,
628 @{$spec{libpath}} ,
629 @{$spec{startup}} ,
630 @{$spec{objects}} ,
631 @{$spec{other_ldflags}} ,
632 $spec{libperl} ,
633 @{$spec{perllibs}} ,
634 $spec{explib} ,
635 $spec{map_file} ? ('-Map', $spec{map_file}) : ''
636 ) ];
637
638 push @cmds, [
639 'dlltool', '--def' , $spec{def_file},
640 '--output-exp' , $spec{explib},
641 '--base-file' , $spec{base_file}
642 ];
643
644 push @cmds, [ grep {defined && length} (
645 @ld ,
646 '-o', $spec{output} ,
647 "-Wl,--image-base,$spec{image_base}" ,
648 @{$spec{lddlflags}} ,
649 @{$spec{libpath}} ,
650 @{$spec{startup}} ,
651 @{$spec{objects}} ,
652 @{$spec{other_ldflags}} ,
653 $spec{libperl} ,
654 @{$spec{perllibs}} ,
655 $spec{explib} ,
656 $spec{map_file} ? ('-Map', $spec{map_file}) : ''
657 ) ];
658
659 return @cmds;
660}
661
662sub write_linker_script {
663 my ($self, %spec) = @_;
664
665 my $script = File::Spec->catfile( $spec{srcdir},
666 $spec{basename} . '.lds' );
667
668 $self->add_to_cleanup($script);
669
670 print "Generating script '$script'\n" if !$self->{quiet};
671
672 open( SCRIPT, ">$script" )
673 or die( "Could not create script '$script': $!" );
674
675 print( SCRIPT 'SEARCH_DIR(' . $_ . ")\n" )
676 for @{delete $spec{libpath} || []};
677
678 # gcc takes only one startup file, so the first object in startup is
679 # specified as the startup file and any others are shifted into the
680 # beginning of the list of objects.
681 if ( $spec{startup} && @{$spec{startup}} ) {
682 print SCRIPT 'STARTUP(' . shift( @{$spec{startup}} ) . ")\n";
683 unshift @{$spec{objects}},
684 @{delete $spec{startup} || []};
685 }
686
687 print SCRIPT 'INPUT(' . join( ',',
688 @{delete $spec{objects} || []}
689 ) . ")\n";
690
691 print SCRIPT 'INPUT(' . join( ' ',
692 (delete $spec{libperl} || ''),
693 @{delete $spec{perllibs} || []},
694 ) . ")\n";
695
696 close SCRIPT;
697
698 push @{$spec{other_ldflags}}, '"' . $script . '"';
699
700 return %spec;
701}
702
7031;
704
705__END__
706
707=head1 NAME
708
709ExtUtils::CBuilder::Platform::Windows - Builder class for Windows platforms
710
711=head1 DESCRIPTION
712
713This module implements the Windows-specific parts of ExtUtils::CBuilder.
714Most of the Windows-specific stuff has to do with compiling and
715linking C code. Currently we support the 3 compilers perl itself
716supports: MSVC, BCC, and GCC.
717
718This module inherits from C<ExtUtils::CBuilder::Base>, so any functionality
719not implemented here will be implemented there. The interfaces are
720defined by the L<ExtUtils::CBuilder> documentation.
721
722=head1 AUTHOR
723
724Ken Williams <ken@mathforum.org>
725
726Most of the code here was written by Randy W. Sims <RandyS@ThePierianSpring.org>.
727
728=head1 SEE ALSO
729
730perl(1), ExtUtils::CBuilder(3), ExtUtils::MakeMaker(3)
731
732=cut