Commit | Line | Data |
---|---|---|
68dc0745 | 1 | package ExtUtils::MM_Win32; |
2 | ||
479d2113 MS |
3 | use strict; |
4 | ||
b75c8c73 | 5 | |
68dc0745 | 6 | =head1 NAME |
7 | ||
8 | ExtUtils::MM_Win32 - methods to override UN*X behaviour in ExtUtils::MakeMaker | |
9 | ||
10 | =head1 SYNOPSIS | |
11 | ||
12 | use ExtUtils::MM_Win32; # Done internally by ExtUtils::MakeMaker if needed | |
13 | ||
14 | =head1 DESCRIPTION | |
15 | ||
16 | See ExtUtils::MM_Unix for a documentation of the methods provided | |
17 | there. This package overrides the implementation of these methods, not | |
18 | the semantics. | |
19 | ||
68dc0745 | 20 | =cut |
21 | ||
7292dc67 | 22 | use ExtUtils::MakeMaker::Config; |
68dc0745 | 23 | use File::Basename; |
ecf68df6 | 24 | use File::Spec; |
f6d6199c | 25 | use ExtUtils::MakeMaker qw( neatvalue ); |
68dc0745 | 26 | |
479d2113 | 27 | use vars qw(@ISA $VERSION $BORLAND $GCC $DMAKE $NMAKE); |
f6d6199c MS |
28 | |
29 | require ExtUtils::MM_Any; | |
30 | require ExtUtils::MM_Unix; | |
31 | @ISA = qw( ExtUtils::MM_Any ExtUtils::MM_Unix ); | |
41e5fcb0 | 32 | $VERSION = '1.12'; |
68dc0745 | 33 | |
34 | $ENV{EMXSHELL} = 'sh'; # to run `commands` | |
68dc0745 | 35 | |
3e3baf6d | 36 | $BORLAND = 1 if $Config{'cc'} =~ /^bcc/i; |
5b0d9cbe | 37 | $GCC = 1 if $Config{'cc'} =~ /^gcc/i; |
3e3baf6d TB |
38 | $DMAKE = 1 if $Config{'make'} =~ /^dmake/i; |
39 | $NMAKE = 1 if $Config{'make'} =~ /^nmake/i; | |
479d2113 MS |
40 | |
41 | ||
42 | =head2 Overridden methods | |
43 | ||
44 | =over 4 | |
45 | ||
46 | =item B<dlsyms> | |
47 | ||
48 | =cut | |
3e3baf6d | 49 | |
68dc0745 | 50 | sub dlsyms { |
51 | my($self,%attribs) = @_; | |
52 | ||
53 | my($funcs) = $attribs{DL_FUNCS} || $self->{DL_FUNCS} || {}; | |
54 | my($vars) = $attribs{DL_VARS} || $self->{DL_VARS} || []; | |
762efda7 | 55 | my($funclist) = $attribs{FUNCLIST} || $self->{FUNCLIST} || []; |
68dc0745 | 56 | my($imports) = $attribs{IMPORTS} || $self->{IMPORTS} || {}; |
57 | my(@m); | |
68dc0745 | 58 | |
59 | if (not $self->{SKIPHASH}{'dynamic'}) { | |
60 | push(@m," | |
61 | $self->{BASEEXT}.def: Makefile.PL | |
62 | ", | |
f6d6199c | 63 | q! $(PERLRUN) -MExtUtils::Mksymlists \\ |
5e687e55 NK |
64 | -e "Mksymlists('NAME'=>\"!, $self->{NAME}, |
65 | q!\", 'DLBASE' => '!,$self->{DLBASE}, | |
66 | # The above two lines quoted differently to work around | |
67 | # a bug in the 4DOS/4NT command line interpreter. The visible | |
68 | # result of the bug was files named q('extension_name',) *with the | |
69 | # single quotes and the comma* in the extension build directories. | |
68dc0745 | 70 | q!', 'DL_FUNCS' => !,neatvalue($funcs), |
762efda7 | 71 | q!, 'FUNCLIST' => !,neatvalue($funclist), |
68dc0745 | 72 | q!, 'IMPORTS' => !,neatvalue($imports), |
73 | q!, 'DL_VARS' => !, neatvalue($vars), q!);" | |
74 | !); | |
75 | } | |
76 | join('',@m); | |
77 | } | |
78 | ||
479d2113 MS |
79 | =item replace_manpage_separator |
80 | ||
81 | Changes the path separator with . | |
82 | ||
83 | =cut | |
84 | ||
68dc0745 | 85 | sub replace_manpage_separator { |
86 | my($self,$man) = @_; | |
87 | $man =~ s,/+,.,g; | |
88 | $man; | |
89 | } | |
90 | ||
479d2113 MS |
91 | |
92 | =item B<maybe_command> | |
93 | ||
94 | Since Windows has nothing as simple as an executable bit, we check the | |
95 | file extension. | |
96 | ||
97 | The PATHEXT env variable will be used to get a list of extensions that | |
98 | might indicate a command, otherwise .com, .exe, .bat and .cmd will be | |
99 | used by default. | |
100 | ||
101 | =cut | |
102 | ||
68dc0745 | 103 | sub maybe_command { |
104 | my($self,$file) = @_; | |
846f184a GS |
105 | my @e = exists($ENV{'PATHEXT'}) |
106 | ? split(/;/, $ENV{PATHEXT}) | |
107 | : qw(.com .exe .bat .cmd); | |
108 | my $e = ''; | |
109 | for (@e) { $e .= "\Q$_\E|" } | |
110 | chop $e; | |
111 | # see if file ends in one of the known extensions | |
2b2708c8 | 112 | if ($file =~ /($e)$/i) { |
846f184a GS |
113 | return $file if -e $file; |
114 | } | |
115 | else { | |
116 | for (@e) { | |
117 | return "$file$_" if -e "$file$_"; | |
118 | } | |
119 | } | |
68dc0745 | 120 | return; |
121 | } | |
122 | ||
68dc0745 | 123 | |
479d2113 MS |
124 | =item B<init_DIRFILESEP> |
125 | ||
126 | Using \ for Windows. | |
127 | ||
128 | =cut | |
129 | ||
130 | sub init_DIRFILESEP { | |
131 | my($self) = shift; | |
132 | ||
dedf98bc MS |
133 | # The ^ makes sure its not interpreted as an escape in nmake |
134 | $self->{DIRFILESEP} = $NMAKE ? '^\\' : | |
135 | $DMAKE ? '\\\\' | |
136 | : '\\'; | |
68dc0745 | 137 | } |
138 | ||
479d2113 MS |
139 | =item B<init_others> |
140 | ||
141 | Override some of the Unix specific commands with portable | |
142 | ExtUtils::Command ones. | |
143 | ||
60537fc0 JH |
144 | Also provide defaults for LD and AR in case the %Config values aren't |
145 | set. | |
3e3baf6d | 146 | |
479d2113 | 147 | LDLOADLIBS's default is changed to $Config{libs}. |
3e3baf6d | 148 | |
479d2113 | 149 | Adjustments are made for Borland's quirks needing -L to come first. |
3e3baf6d TB |
150 | |
151 | =cut | |
152 | ||
479d2113 MS |
153 | sub init_others { |
154 | my ($self) = @_; | |
155 | ||
156 | # Used in favor of echo because echo won't strip quotes. :( | |
dedf98bc | 157 | $self->{ECHO} ||= $self->oneliner('print qq{@ARGV}', ['-l']); |
e3aa3ecb | 158 | $self->{ECHO_N} ||= $self->oneliner('print qq{@ARGV}'); |
dedf98bc | 159 | |
5dca256e RGS |
160 | $self->{TOUCH} ||= '$(ABSPERLRUN) -MExtUtils::Command -e touch'; |
161 | $self->{CHMOD} ||= '$(ABSPERLRUN) -MExtUtils::Command -e chmod'; | |
162 | $self->{CP} ||= '$(ABSPERLRUN) -MExtUtils::Command -e cp'; | |
163 | $self->{RM_F} ||= '$(ABSPERLRUN) -MExtUtils::Command -e rm_f'; | |
164 | $self->{RM_RF} ||= '$(ABSPERLRUN) -MExtUtils::Command -e rm_rf'; | |
165 | $self->{MV} ||= '$(ABSPERLRUN) -MExtUtils::Command -e mv'; | |
479d2113 | 166 | $self->{NOOP} ||= 'rem'; |
5dca256e | 167 | $self->{TEST_F} ||= '$(ABSPERLRUN) -MExtUtils::Command -e test_f'; |
479d2113 MS |
168 | $self->{DEV_NULL} ||= '> NUL'; |
169 | ||
7292dc67 | 170 | $self->{FIXIN} ||= $self->{PERL_CORE} ? |
6383bd23 | 171 | "\$(PERLRUN) $self->{PERL_SRC}/win32/bin/pl2bat.pl" : |
7292dc67 RGS |
172 | 'pl2bat.bat'; |
173 | ||
60537fc0 | 174 | $self->{LD} ||= $Config{ld} || 'link'; |
479d2113 MS |
175 | $self->{AR} ||= $Config{ar} || 'lib'; |
176 | ||
177 | $self->SUPER::init_others; | |
178 | ||
dedf98bc MS |
179 | # Setting SHELL from $Config{sh} can break dmake. Its ok without it. |
180 | delete $self->{SHELL}; | |
181 | ||
479d2113 MS |
182 | $self->{LDLOADLIBS} ||= $Config{libs}; |
183 | # -Lfoo must come first for Borland, so we put it in LDDLFLAGS | |
184 | if ($BORLAND) { | |
185 | my $libs = $self->{LDLOADLIBS}; | |
186 | my $libpath = ''; | |
187 | while ($libs =~ s/(?:^|\s)(("?)-L.+?\2)(?:\s|$)/ /) { | |
188 | $libpath .= ' ' if length $libpath; | |
189 | $libpath .= $1; | |
190 | } | |
191 | $self->{LDLOADLIBS} = $libs; | |
192 | $self->{LDDLFLAGS} ||= $Config{lddlflags}; | |
193 | $self->{LDDLFLAGS} .= " $libpath"; | |
3e3baf6d TB |
194 | } |
195 | ||
479d2113 MS |
196 | return 1; |
197 | } | |
3e3baf6d | 198 | |
3e3baf6d | 199 | |
7292dc67 | 200 | =item init_platform |
3e3baf6d | 201 | |
479d2113 | 202 | Add MM_Win32_VERSION. |
3e3baf6d | 203 | |
7292dc67 | 204 | =item platform_constants |
3e3baf6d | 205 | |
479d2113 | 206 | =cut |
3e3baf6d | 207 | |
479d2113 MS |
208 | sub init_platform { |
209 | my($self) = shift; | |
3e3baf6d | 210 | |
479d2113 MS |
211 | $self->{MM_Win32_VERSION} = $VERSION; |
212 | } | |
3e3baf6d | 213 | |
479d2113 MS |
214 | sub platform_constants { |
215 | my($self) = shift; | |
216 | my $make_frag = ''; | |
3e3baf6d | 217 | |
479d2113 MS |
218 | foreach my $macro (qw(MM_Win32_VERSION)) |
219 | { | |
220 | next unless defined $self->{$macro}; | |
221 | $make_frag .= "$macro = $self->{$macro}\n"; | |
222 | } | |
3e3baf6d | 223 | |
479d2113 MS |
224 | return $make_frag; |
225 | } | |
3e3baf6d | 226 | |
3e3baf6d | 227 | |
7292dc67 | 228 | =item special_targets |
3e3baf6d | 229 | |
479d2113 | 230 | Add .USESHELL target for dmake. |
3e3baf6d | 231 | |
479d2113 | 232 | =cut |
3e3baf6d | 233 | |
479d2113 MS |
234 | sub special_targets { |
235 | my($self) = @_; | |
3e3baf6d | 236 | |
479d2113 | 237 | my $make_frag = $self->SUPER::special_targets; |
3e3baf6d | 238 | |
479d2113 MS |
239 | $make_frag .= <<'MAKE_FRAG' if $DMAKE; |
240 | .USESHELL : | |
241 | MAKE_FRAG | |
3e3baf6d | 242 | |
479d2113 | 243 | return $make_frag; |
3e3baf6d TB |
244 | } |
245 | ||
246 | ||
7292dc67 | 247 | =item static_lib |
68dc0745 | 248 | |
479d2113 MS |
249 | Changes how to run the linker. |
250 | ||
251 | The rest is duplicate code from MM_Unix. Should move the linker code | |
252 | to its own method. | |
68dc0745 | 253 | |
254 | =cut | |
255 | ||
256 | sub static_lib { | |
257 | my($self) = @_; | |
68dc0745 | 258 | return '' unless $self->has_link_code; |
259 | ||
260 | my(@m); | |
261 | push(@m, <<'END'); | |
7292dc67 | 262 | $(INST_STATIC): $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)$(DFSEP).exists |
68dc0745 | 263 | $(RM_RF) $@ |
264 | END | |
479d2113 | 265 | |
022735b4 | 266 | # If this extension has its own library (eg SDBM_File) |
68dc0745 | 267 | # then copy that to $(INST_STATIC) and add $(OBJECT) into it. |
479d2113 MS |
268 | push @m, <<'MAKE_FRAG' if $self->{MYEXTLIB}; |
269 | $(CP) $(MYEXTLIB) $@ | |
270 | MAKE_FRAG | |
68dc0745 | 271 | |
272 | push @m, | |
910dfcc8 GS |
273 | q{ $(AR) }.($BORLAND ? '$@ $(OBJECT:^"+")' |
274 | : ($GCC ? '-ru $@ $(OBJECT)' | |
275 | : '-out:$@ $(OBJECT)')).q{ | |
479d2113 MS |
276 | $(CHMOD) $(PERM_RWX) $@ |
277 | $(NOECHO) $(ECHO) "$(EXTRALIBS)" > $(INST_ARCHAUTODIR)\extralibs.ld | |
68dc0745 | 278 | }; |
279 | ||
479d2113 MS |
280 | # Old mechanism - still available: |
281 | push @m, <<'MAKE_FRAG' if $self->{PERL_SRC} && $self->{EXTRALIBS}; | |
282 | $(NOECHO) $(ECHO) "$(EXTRALIBS)" >> $(PERL_SRC)\ext.libs | |
283 | MAKE_FRAG | |
68dc0745 | 284 | |
479d2113 | 285 | join('', @m); |
68dc0745 | 286 | } |
287 | ||
68dc0745 | 288 | |
7292dc67 | 289 | =item dynamic_lib |
68dc0745 | 290 | |
479d2113 | 291 | Complicated stuff for Win32 that I don't understand. :( |
68dc0745 | 292 | |
293 | =cut | |
294 | ||
295 | sub dynamic_lib { | |
296 | my($self, %attribs) = @_; | |
297 | return '' unless $self->needs_linking(); #might be because of a subdir | |
298 | ||
299 | return '' unless $self->has_link_code; | |
300 | ||
3e3baf6d | 301 | my($otherldflags) = $attribs{OTHERLDFLAGS} || ($BORLAND ? 'c0d32.obj': ''); |
68dc0745 | 302 | my($inst_dynamic_dep) = $attribs{INST_DYNAMIC_DEP} || ""; |
303 | my($ldfrom) = '$(LDFROM)'; | |
304 | my(@m); | |
7a958ec3 | 305 | |
5db10396 GS |
306 | # one thing for GCC/Mingw32: |
307 | # we try to overcome non-relocateable-DLL problems by generating | |
7a958ec3 BS |
308 | # a (hopefully unique) image-base from the dll's name |
309 | # -- BKS, 10-19-1999 | |
310 | if ($GCC) { | |
7a958ec3 BS |
311 | my $dllname = $self->{BASEEXT} . "." . $self->{DLEXT}; |
312 | $dllname =~ /(....)(.{0,4})/; | |
313 | my $baseaddr = unpack("n", $1 ^ $2); | |
314 | $otherldflags .= sprintf("-Wl,--image-base,0x%x0000 ", $baseaddr); | |
315 | } | |
316 | ||
68dc0745 | 317 | push(@m,' |
318 | # This section creates the dynamically loadable $(INST_DYNAMIC) | |
319 | # from $(OBJECT) and possibly $(MYEXTLIB). | |
320 | OTHERLDFLAGS = '.$otherldflags.' | |
321 | INST_DYNAMIC_DEP = '.$inst_dynamic_dep.' | |
322 | ||
7292dc67 | 323 | $(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP) $(INST_ARCHAUTODIR)$(DFSEP).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP) |
68dc0745 | 324 | '); |
5b0d9cbe NIS |
325 | if ($GCC) { |
326 | push(@m, | |
910dfcc8 GS |
327 | q{ dlltool --def $(EXPORT_LIST) --output-exp dll.exp |
328 | $(LD) -o $@ -Wl,--base-file -Wl,dll.base $(LDDLFLAGS) }.$ldfrom.q{ $(OTHERLDFLAGS) $(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) dll.exp | |
5b0d9cbe NIS |
329 | dlltool --def $(EXPORT_LIST) --base-file dll.base --output-exp dll.exp |
330 | $(LD) -o $@ $(LDDLFLAGS) }.$ldfrom.q{ $(OTHERLDFLAGS) $(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) dll.exp }); | |
dc0d354b GS |
331 | } elsif ($BORLAND) { |
332 | push(@m, | |
333 | q{ $(LD) $(LDDLFLAGS) $(OTHERLDFLAGS) }.$ldfrom.q{,$@,,} | |
334 | .($DMAKE ? q{$(PERL_ARCHIVE:s,/,\,) $(LDLOADLIBS:s,/,\,) } | |
335 | .q{$(MYEXTLIB:s,/,\,),$(EXPORT_LIST:s,/,\,)} | |
336 | : q{$(subst /,\,$(PERL_ARCHIVE)) $(subst /,\,$(LDLOADLIBS)) } | |
337 | .q{$(subst /,\,$(MYEXTLIB)),$(subst /,\,$(EXPORT_LIST))}) | |
338 | .q{,$(RESFILES)}); | |
339 | } else { # VC | |
340 | push(@m, | |
341 | q{ $(LD) -out:$@ $(LDDLFLAGS) }.$ldfrom.q{ $(OTHERLDFLAGS) } | |
342 | .q{$(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) -def:$(EXPORT_LIST)}); | |
5b0d9cbe | 343 | } |
68dc0745 | 344 | push @m, ' |
479d2113 | 345 | $(CHMOD) $(PERM_RWX) $@ |
68dc0745 | 346 | '; |
347 | ||
68dc0745 | 348 | join('',@m); |
349 | } | |
350 | ||
7292dc67 | 351 | =item extra_clean_files |
479d2113 MS |
352 | |
353 | Clean out some extra dll.{base,exp} files which might be generated by | |
354 | gcc. Otherwise, take out all *.pdb files. | |
355 | ||
356 | =cut | |
357 | ||
7292dc67 RGS |
358 | sub extra_clean_files { |
359 | my $self = shift; | |
562c1c19 | 360 | |
7292dc67 | 361 | return $GCC ? (qw(dll.base dll.exp)) : ('*.pdb'); |
562c1c19 NIS |
362 | } |
363 | ||
479d2113 | 364 | =item init_linker |
562c1c19 | 365 | |
479d2113 | 366 | =cut |
562c1c19 | 367 | |
479d2113 MS |
368 | sub init_linker { |
369 | my $self = shift; | |
68dc0745 | 370 | |
479d2113 MS |
371 | $self->{PERL_ARCHIVE} = "\$(PERL_INC)\\$Config{libperl}"; |
372 | $self->{PERL_ARCHIVE_AFTER} = ''; | |
373 | $self->{EXPORT_LIST} = '$(BASEEXT).def'; | |
68dc0745 | 374 | } |
375 | ||
45bc4d3a | 376 | |
68dc0745 | 377 | =item perl_script |
378 | ||
479d2113 | 379 | Checks for the perl program under several common perl extensions. |
68dc0745 | 380 | |
381 | =cut | |
382 | ||
383 | sub perl_script { | |
384 | my($self,$file) = @_; | |
cae6c631 | 385 | return $file if -r $file && -f _; |
479d2113 MS |
386 | return "$file.pl" if -r "$file.pl" && -f _; |
387 | return "$file.plx" if -r "$file.plx" && -f _; | |
cae6c631 | 388 | return "$file.bat" if -r "$file.bat" && -f _; |
68dc0745 | 389 | return; |
390 | } | |
391 | ||
3e3baf6d | 392 | |
7292dc67 | 393 | =item xs_o |
68dc0745 | 394 | |
479d2113 | 395 | This target is stubbed out. Not sure why. |
68dc0745 | 396 | |
397 | =cut | |
398 | ||
479d2113 MS |
399 | sub xs_o { |
400 | return '' | |
68dc0745 | 401 | } |
402 | ||
68dc0745 | 403 | |
7292dc67 | 404 | =item pasthru |
68dc0745 | 405 | |
479d2113 MS |
406 | All we send is -nologo to nmake to prevent it from printing its damned |
407 | banner. | |
68dc0745 | 408 | |
409 | =cut | |
410 | ||
479d2113 | 411 | sub pasthru { |
68dc0745 | 412 | my($self) = shift; |
071e6b84 JH |
413 | return "PASTHRU = " . ($NMAKE ? "-nologo" : ""); |
414 | } | |
68dc0745 | 415 | |
3e3baf6d | 416 | |
7292dc67 | 417 | =item oneliner |
3e3baf6d | 418 | |
479d2113 MS |
419 | These are based on what command.com does on Win98. They may be wrong |
420 | for other Windows shells, I don't know. | |
3e3baf6d TB |
421 | |
422 | =cut | |
423 | ||
479d2113 MS |
424 | sub oneliner { |
425 | my($self, $cmd, $switches) = @_; | |
426 | $switches = [] unless defined $switches; | |
3e3baf6d | 427 | |
479d2113 MS |
428 | # Strip leading and trailing newlines |
429 | $cmd =~ s{^\n+}{}; | |
430 | $cmd =~ s{\n+$}{}; | |
3e3baf6d | 431 | |
479d2113 MS |
432 | $cmd = $self->quote_literal($cmd); |
433 | $cmd = $self->escape_newlines($cmd); | |
3e3baf6d | 434 | |
479d2113 | 435 | $switches = join ' ', @$switches; |
3e3baf6d | 436 | |
5dca256e | 437 | return qq{\$(ABSPERLRUN) $switches -e $cmd}; |
3e3baf6d TB |
438 | } |
439 | ||
68dc0745 | 440 | |
479d2113 MS |
441 | sub quote_literal { |
442 | my($self, $text) = @_; | |
68dc0745 | 443 | |
479d2113 MS |
444 | # I don't know if this is correct, but it seems to work on |
445 | # Win98's command.com | |
446 | $text =~ s{"}{\\"}g; | |
68dc0745 | 447 | |
dedf98bc MS |
448 | # dmake eats '{' inside double quotes and leaves alone { outside double |
449 | # quotes; however it transforms {{ into { either inside and outside double | |
450 | # quotes. It also translates }} into }. The escaping below is not | |
451 | # 100% correct. | |
452 | if( $DMAKE ) { | |
453 | $text =~ s/{/{{/g; | |
454 | $text =~ s/}}/}}}/g; | |
455 | } | |
456 | ||
479d2113 | 457 | return qq{"$text"}; |
68dc0745 | 458 | } |
459 | ||
68dc0745 | 460 | |
479d2113 MS |
461 | sub escape_newlines { |
462 | my($self, $text) = @_; | |
68dc0745 | 463 | |
479d2113 MS |
464 | # Escape newlines |
465 | $text =~ s{\n}{\\\n}g; | |
68dc0745 | 466 | |
479d2113 | 467 | return $text; |
68dc0745 | 468 | } |
469 | ||
68dc0745 | 470 | |
7292dc67 RGS |
471 | =item cd |
472 | ||
473 | dmake can handle Unix style cd'ing but nmake (at least 1.5) cannot. It | |
474 | wants: | |
475 | ||
476 | cd dir | |
477 | command | |
478 | another_command | |
479 | cd .. | |
480 | ||
481 | B<NOTE> This cd can only go one level down. So far this sufficient for | |
482 | what MakeMaker needs. | |
483 | ||
484 | =cut | |
485 | ||
486 | sub cd { | |
487 | my($self, $dir, @cmds) = @_; | |
488 | ||
489 | return $self->SUPER::cd($dir, @cmds) unless $NMAKE; | |
490 | ||
491 | my $cmd = join "\n\t", map "$_", @cmds; | |
492 | ||
493 | # No leading tab and no trailing newline makes for easier embedding. | |
494 | my $make_frag = sprintf <<'MAKE_FRAG', $dir, $cmd; | |
495 | cd %s | |
496 | %s | |
497 | cd .. | |
498 | MAKE_FRAG | |
499 | ||
500 | chomp $make_frag; | |
501 | ||
502 | return $make_frag; | |
503 | } | |
504 | ||
505 | ||
479d2113 | 506 | =item max_exec_len |
68dc0745 | 507 | |
2c91f887 | 508 | nmake 1.50 limits command length to 2048 characters. |
68dc0745 | 509 | |
510 | =cut | |
511 | ||
479d2113 MS |
512 | sub max_exec_len { |
513 | my $self = shift; | |
514 | ||
2c91f887 | 515 | return $self->{_MAX_EXEC_LEN} ||= 2 * 1024; |
68dc0745 | 516 | } |
517 | ||
518 | ||
dedf98bc MS |
519 | =item os_flavor |
520 | ||
521 | Windows is Win32. | |
522 | ||
523 | =cut | |
524 | ||
525 | sub os_flavor { | |
526 | return('Win32'); | |
527 | } | |
528 | ||
529 | ||
68dc0745 | 530 | 1; |
531 | __END__ | |
532 | ||
533 | =back | |
534 | ||
535 | =cut | |
536 | ||
5b0d9cbe | 537 |