Add built local::lib
[catagits/Gitalist.git] / local-lib5 / lib / perl5 / ExtUtils / CBuilder / Platform / Windows.pm
CommitLineData
3fea05b9 1package ExtUtils::CBuilder::Platform::Windows;
2
3use strict;
4use warnings;
5
6use File::Basename;
7use File::Spec;
8
9use ExtUtils::CBuilder::Base;
10use IO::File;
11
12use vars qw($VERSION @ISA);
13$VERSION = '0.27';
14@ISA = qw(ExtUtils::CBuilder::Base);
15
16=begin comment
17
18The compiler-specific packages implement functions for generating properly
19formatted commandlines for the compiler being used. Each package
20defines two primary functions 'format_linker_cmd()' &
21'format_compiler_cmd()' that accepts a list of named arguments (a
22hash) and returns a list of formatted options suitable for invoking the
23compiler. By default, if the compiler supports scripting of its
24operation then a script file is built containing the options while
25those options are removed from the commandline, and a reference to the
26script is pushed onto the commandline in their place. Scripting the
27compiler in this way helps to avoid the problems associated with long
28commandlines under some shells.
29
30=end comment
31
32=cut
33
34sub new {
35 my $class = shift;
36 my $self = $class->SUPER::new(@_);
37 my $cf = $self->{config};
38
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;
43
44 return $self;
45}
46
47sub _compiler_type {
48 my $self = shift;
49 my $cc = $self->{config}{cc};
50
51 return ( $cc =~ /cl(\.exe)?$/ ? 'MSVC'
52 : $cc =~ /bcc32(\.exe)?$/ ? 'BCC'
53 : 'GCC');
54}
55
56sub 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 $_) = @_;
61
62 return @$_ if defined() && UNIVERSAL::isa($_, 'ARRAY');
63 return unless defined() && length();
64 return ($_);
65}
66
67sub do_system {
68 # See above
69 my $self = shift;
70 my $cmd = join(" ",
71 grep length,
72 map {$a=$_;$a=~s/\t/ /g;$a=~s/^\s+|\s+$//;$a}
73 grep defined, @_);
74 return $self->SUPER::do_system($cmd);
75}
76
77sub arg_defines {
78 my ($self, %args) = @_;
79 s/"/\\"/g foreach values %args;
80 return map qq{"-D$_=$args{$_}"}, keys %args;
81}
82
83sub compile {
84 my ($self, %args) = @_;
85 my $cf = $self->{config};
86
87 die "Missing 'source' argument to compile()" unless defined $args{source};
88
89 my ($basename, $srcdir) =
90 ( File::Basename::fileparse($args{source}, '\.[^.]+$') )[0,1];
91
92 $srcdir ||= File::Spec->curdir();
93
94 my @defines = $self->arg_defines( %{ $args{defines} || {} } );
95
96 my %spec = (
97 srcdir => $srcdir,
98 builddir => $srcdir,
99 basename => $basename,
100 source => $args{source},
101 output => File::Spec->catfile($srcdir, $basename) . $cf->{obj_ext},
102 cc => $cf->{cc},
103 cflags => [
104 $self->split_like_shell($cf->{ccflags}),
105 $self->split_like_shell($cf->{cccdlflags}),
106 $self->split_like_shell($args{extra_compiler_flags}),
107 ],
108 optimize => [ $self->split_like_shell($cf->{optimize}) ],
109 defines => \@defines,
110 includes => [ @{$args{include_dirs} || []} ],
111 perlinc => [
112 $self->perl_inc(),
113 $self->split_like_shell($cf->{incpath}),
114 ],
115 use_scripts => 1, # XXX provide user option to change this???
116 );
117
118 $self->normalize_filespecs(
119 \$spec{source},
120 \$spec{output},
121 $spec{includes},
122 $spec{perlinc},
123 );
124
125 my @cmds = $self->format_compiler_cmd(%spec);
126 while ( my $cmd = shift @cmds ) {
127 $self->do_system( @$cmd )
128 or die "error building $cf->{dlext} file from '$args{source}'";
129 }
130
131 (my $out = $spec{output}) =~ tr/'"//d;
132 return $out;
133}
134
135sub need_prelink { 1 }
136
137sub link {
138 my ($self, %args) = @_;
139 my $cf = $self->{config};
140
141 my @objects = ( ref $args{objects} eq 'ARRAY' ? @{$args{objects}} : $args{objects} );
142 my $to = join '', (File::Spec->splitpath($objects[0]))[0,1];
143 $to ||= File::Spec->curdir();
144
145 (my $file_base = $args{module_name}) =~ s/.*:://;
146 my $output = $args{lib_file} ||
147 File::Spec->catfile($to, "$file_base.$cf->{dlext}");
148
149 # if running in perl source tree, look for libs there, not installed
150 my $lddlflags = $cf->{lddlflags};
151 my $perl_src = $self->perl_src();
152 $lddlflags =~ s/\Q$cf->{archlibexp}\E[\\\/]CORE/$perl_src/ if $perl_src;
153
154 my %spec = (
155 srcdir => $to,
156 builddir => $to,
157 startup => [ ],
158 objects => \@objects,
159 libs => [ ],
160 output => $output,
161 ld => $cf->{ld},
162 libperl => $cf->{libperl},
163 perllibs => [ $self->split_like_shell($cf->{perllibs}) ],
164 libpath => [ $self->split_like_shell($cf->{libpth}) ],
165 lddlflags => [ $self->split_like_shell($lddlflags) ],
166 other_ldflags => [ $self->split_like_shell($args{extra_linker_flags} || '') ],
167 use_scripts => 1, # XXX provide user option to change this???
168 );
169
170 unless ( $spec{basename} ) {
171 ($spec{basename} = $args{module_name}) =~ s/.*:://;
172 }
173
174 $spec{srcdir} = File::Spec->canonpath( $spec{srcdir} );
175 $spec{builddir} = File::Spec->canonpath( $spec{builddir} );
176
177 $spec{output} ||= File::Spec->catfile( $spec{builddir},
178 $spec{basename} . '.'.$cf->{dlext} );
179 $spec{manifest} ||= File::Spec->catfile( $spec{builddir},
180 $spec{basename} . '.'.$cf->{dlext}.'.manifest');
181 $spec{implib} ||= File::Spec->catfile( $spec{builddir},
182 $spec{basename} . $cf->{lib_ext} );
183 $spec{explib} ||= File::Spec->catfile( $spec{builddir},
184 $spec{basename} . '.exp' );
185 if ($cf->{cc} eq 'cl') {
186 $spec{dbg_file} ||= File::Spec->catfile( $spec{builddir},
187 $spec{basename} . '.pdb' );
188 }
189 elsif ($cf->{cc} eq 'bcc32') {
190 $spec{dbg_file} ||= File::Spec->catfile( $spec{builddir},
191 $spec{basename} . '.tds' );
192 }
193 $spec{def_file} ||= File::Spec->catfile( $spec{srcdir} ,
194 $spec{basename} . '.def' );
195 $spec{base_file} ||= File::Spec->catfile( $spec{srcdir} ,
196 $spec{basename} . '.base' );
197
198 $self->add_to_cleanup(
199 grep defined,
200 @{[ @spec{qw(manifest implib explib dbg_file def_file base_file map_file)} ]}
201 );
202
203 foreach my $opt ( qw(output manifest implib explib dbg_file def_file map_file base_file) ) {
204 $self->normalize_filespecs( \$spec{$opt} );
205 }
206
207 foreach my $opt ( qw(libpath startup objects) ) {
208 $self->normalize_filespecs( $spec{$opt} );
209 }
210
211 (my $def_base = $spec{def_file}) =~ tr/'"//d;
212 $def_base =~ s/\.def$//;
213 $self->prelink( dl_name => $args{module_name},
214 dl_file => $def_base,
215 dl_base => $spec{basename} );
216
217 my @cmds = $self->format_linker_cmd(%spec);
218 while ( my $cmd = shift @cmds ) {
219 $self->do_system( @$cmd );
220 }
221
222 $spec{output} =~ tr/'"//d;
223 return wantarray
224 ? grep defined, @spec{qw[output manifest implib explib dbg_file def_file map_file base_file]}
225 : $spec{output};
226}
227
228# canonize & quote paths
229sub normalize_filespecs {
230 my ($self, @specs) = @_;
231 foreach my $spec ( grep defined, @specs ) {
232 if ( ref $spec eq 'ARRAY') {
233 $self->normalize_filespecs( map {\$_} grep defined, @$spec )
234 } elsif ( ref $spec eq 'SCALAR' ) {
235 $$spec =~ tr/"//d if $$spec;
236 next unless $$spec;
237 $$spec = '"' . File::Spec->canonpath($$spec) . '"';
238 } elsif ( ref $spec eq '' ) {
239 $spec = '"' . File::Spec->canonpath($spec) . '"';
240 } else {
241 die "Don't know how to normalize " . (ref $spec || $spec) . "\n";
242 }
243 }
244}
245
246# directory of perl's include files
247sub perl_inc {
248 my $self = shift;
249
250 my $perl_src = $self->perl_src();
251
252 if ($perl_src) {
253 File::Spec->catdir($perl_src, "lib", "CORE");
254 } else {
255 File::Spec->catdir($self->{config}{archlibexp},"CORE");
256 }
257}
258
2591;
260
261__END__
262
263=head1 NAME
264
265ExtUtils::CBuilder::Platform::Windows - Builder class for Windows platforms
266
267=head1 DESCRIPTION
268
269This module implements the Windows-specific parts of ExtUtils::CBuilder.
270Most of the Windows-specific stuff has to do with compiling and
271linking C code. Currently we support the 3 compilers perl itself
272supports: MSVC, BCC, and GCC.
273
274This module inherits from C<ExtUtils::CBuilder::Base>, so any functionality
275not implemented here will be implemented there. The interfaces are
276defined by the L<ExtUtils::CBuilder> documentation.
277
278=head1 AUTHOR
279
280Ken Williams <ken@mathforum.org>
281
282Most of the code here was written by Randy W. Sims <RandyS@ThePierianSpring.org>.
283
284=head1 SEE ALSO
285
286perl(1), ExtUtils::CBuilder(3), ExtUtils::MakeMaker(3)
287
288=cut