1 package ExtUtils::CBuilder::Platform::Windows;
9 use ExtUtils::CBuilder::Base;
12 use vars qw($VERSION @ISA);
13 $VERSION = '0.280212';
14 @ISA = qw(ExtUtils::CBuilder::Base);
18 The compiler-specific packages implement functions for generating properly
19 formatted commandlines for the compiler being used. Each package
20 defines two primary functions 'format_linker_cmd()' &
21 'format_compiler_cmd()' that accepts a list of named arguments (a
22 hash) and returns a list of formatted options suitable for invoking the
23 compiler. By default, if the compiler supports scripting of its
24 operation then a script file is built containing the options while
25 those options are removed from the commandline, and a reference to the
26 script is pushed onto the commandline in their place. Scripting the
27 compiler in this way helps to avoid the problems associated with long
28 commandlines under some shells.
36 my $self = $class->SUPER::new(@_);
37 my $cf = $self->{config};
39 # Inherit from an appropriate compiler driver class
40 my $driver = "ExtUtils::CBuilder::Platform::Windows::" . $self->_compiler_type;
41 eval "require $driver" or die "Could not load compiler driver: $@";
42 unshift @ISA, $driver;
49 my $cc = $self->{config}{cc};
51 return ( $cc =~ /cl(\.exe)?$/ ? 'MSVC'
52 : $cc =~ /bcc32(\.exe)?$/ ? 'BCC'
56 sub split_like_shell {
57 # Since Windows will pass the whole command string (not an argument
58 # array) to the target program and make the program parse it itself,
59 # we don't actually need to do any processing here.
60 (my $self, local $_) = @_;
62 return @$_ if defined() && UNIVERSAL::isa($_, 'ARRAY');
63 return unless defined() && length();
72 map {$a=$_;$a=~s/\t/ /g;$a=~s/^\s+|\s+$//;$a}
74 return $self->SUPER::do_system($cmd);
78 my ($self, %args) = @_;
79 s/"/\\"/g foreach values %args;
80 return map qq{"-D$_=$args{$_}"}, keys %args;
84 my ($self, %args) = @_;
85 my $cf = $self->{config};
87 die "Missing 'source' argument to compile()" unless defined $args{source};
89 $args{include_dirs} = [ $args{include_dirs} ]
90 if exists($args{include_dirs}) && ref($args{include_dirs}) ne "ARRAY";
92 my ($basename, $srcdir) =
93 ( File::Basename::fileparse($args{source}, '\.[^.]+$') )[0,1];
95 $srcdir ||= File::Spec->curdir();
97 my @defines = $self->arg_defines( %{ $args{defines} || {} } );
102 basename => $basename,
103 source => $args{source},
104 output => $args{object_file} || File::Spec->catfile($srcdir, $basename) . $cf->{obj_ext},
107 $self->split_like_shell($cf->{ccflags}),
108 $self->split_like_shell($cf->{cccdlflags}),
109 $self->split_like_shell($args{extra_compiler_flags}),
111 optimize => [ $self->split_like_shell($cf->{optimize}) ],
112 defines => \@defines,
113 includes => [ @{$args{include_dirs} || []} ],
116 $self->split_like_shell($cf->{incpath}),
118 use_scripts => 1, # XXX provide user option to change this???
121 $self->normalize_filespecs(
128 my @cmds = $self->format_compiler_cmd(%spec);
129 while ( my $cmd = shift @cmds ) {
130 $self->do_system( @$cmd )
131 or die "error building $cf->{dlext} file from '$args{source}'";
134 (my $out = $spec{output}) =~ tr/'"//d;
138 sub need_prelink { 1 }
141 my ($self, %args) = @_;
142 my $cf = $self->{config};
144 my @objects = ( ref $args{objects} eq 'ARRAY' ? @{$args{objects}} : $args{objects} );
145 my $to = join '', (File::Spec->splitpath($objects[0]))[0,1];
146 $to ||= File::Spec->curdir();
148 (my $file_base = $args{module_name}) =~ s/.*:://;
149 my $output = $args{lib_file} ||
150 File::Spec->catfile($to, "$file_base.$cf->{dlext}");
152 # if running in perl source tree, look for libs there, not installed
153 my $lddlflags = $cf->{lddlflags};
154 my $perl_src = $self->perl_src();
155 $lddlflags =~ s/\Q$cf->{archlibexp}\E[\\\/]CORE/$perl_src/ if $perl_src;
161 objects => \@objects,
165 libperl => $cf->{libperl},
166 perllibs => [ $self->split_like_shell($cf->{perllibs}) ],
167 libpath => [ $self->split_like_shell($cf->{libpth}) ],
168 lddlflags => [ $self->split_like_shell($lddlflags) ],
169 other_ldflags => [ $self->split_like_shell($args{extra_linker_flags} || '') ],
170 use_scripts => 1, # XXX provide user option to change this???
173 unless ( $spec{basename} ) {
174 ($spec{basename} = $args{module_name}) =~ s/.*:://;
177 $spec{srcdir} = File::Spec->canonpath( $spec{srcdir} );
178 $spec{builddir} = File::Spec->canonpath( $spec{builddir} );
180 $spec{output} ||= File::Spec->catfile( $spec{builddir},
181 $spec{basename} . '.'.$cf->{dlext} );
182 $spec{manifest} ||= $spec{output} . '.manifest';
183 $spec{implib} ||= File::Spec->catfile( $spec{builddir},
184 $spec{basename} . $cf->{lib_ext} );
185 $spec{explib} ||= File::Spec->catfile( $spec{builddir},
186 $spec{basename} . '.exp' );
187 if ($cf->{cc} eq 'cl') {
188 $spec{dbg_file} ||= File::Spec->catfile( $spec{builddir},
189 $spec{basename} . '.pdb' );
191 elsif ($cf->{cc} eq 'bcc32') {
192 $spec{dbg_file} ||= File::Spec->catfile( $spec{builddir},
193 $spec{basename} . '.tds' );
195 $spec{def_file} ||= File::Spec->catfile( $spec{srcdir} ,
196 $spec{basename} . '.def' );
197 $spec{base_file} ||= File::Spec->catfile( $spec{srcdir} ,
198 $spec{basename} . '.base' );
200 $self->add_to_cleanup(
202 @{[ @spec{qw(manifest implib explib dbg_file def_file base_file map_file)} ]}
205 foreach my $opt ( qw(output manifest implib explib dbg_file def_file map_file base_file) ) {
206 $self->normalize_filespecs( \$spec{$opt} );
209 foreach my $opt ( qw(libpath startup objects) ) {
210 $self->normalize_filespecs( $spec{$opt} );
213 (my $def_base = $spec{def_file}) =~ tr/'"//d;
214 $def_base =~ s/\.def$//;
215 $self->prelink( %args,
216 dl_name => $args{module_name},
217 dl_file => $def_base,
218 dl_base => $spec{basename} );
220 my @cmds = $self->format_linker_cmd(%spec);
221 while ( my $cmd = shift @cmds ) {
222 $self->do_system( @$cmd );
225 $spec{output} =~ tr/'"//d;
227 ? grep defined, @spec{qw[output manifest implib explib dbg_file def_file map_file base_file]}
231 # canonize & quote paths
232 sub normalize_filespecs {
233 my ($self, @specs) = @_;
234 foreach my $spec ( grep defined, @specs ) {
235 if ( ref $spec eq 'ARRAY') {
236 $self->normalize_filespecs( map {\$_} grep defined, @$spec )
237 } elsif ( ref $spec eq 'SCALAR' ) {
238 $$spec =~ tr/"//d if $$spec;
240 $$spec = '"' . File::Spec->canonpath($$spec) . '"';
241 } elsif ( ref $spec eq '' ) {
242 $spec = '"' . File::Spec->canonpath($spec) . '"';
244 die "Don't know how to normalize " . (ref $spec || $spec) . "\n";
249 # directory of perl's include files
253 my $perl_src = $self->perl_src();
256 File::Spec->catdir($perl_src, "lib", "CORE");
258 File::Spec->catdir($self->{config}{archlibexp},"CORE");
268 ExtUtils::CBuilder::Platform::Windows - Builder class for Windows platforms
272 This module implements the Windows-specific parts of ExtUtils::CBuilder.
273 Most of the Windows-specific stuff has to do with compiling and
274 linking C code. Currently we support the 3 compilers perl itself
275 supports: MSVC, BCC, and GCC.
277 This module inherits from C<ExtUtils::CBuilder::Base>, so any functionality
278 not implemented here will be implemented there. The interfaces are
279 defined by the L<ExtUtils::CBuilder> documentation.
283 Ken Williams <ken@mathforum.org>
285 Most of the code here was written by Randy W. Sims <RandyS@ThePierianSpring.org>.
289 perl(1), ExtUtils::CBuilder(3), ExtUtils::MakeMaker(3)