]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - mkfiles.pl
'perl -w' safety in mkfiles.pl.
[PuTTY.git] / mkfiles.pl
1 #!/usr/bin/env perl -w
2 #
3 # Cross-platform Makefile generator.
4 #
5 # Reads the file `Recipe' to determine the list of generated
6 # executables and their component objects. Then reads the source
7 # files to compute #include dependencies. Finally, writes out the
8 # various target Makefiles.
9
10 # PuTTY specifics which could still do with removing:
11 #  - Mac makefile is not portabilised at all. Include directories
12 #    are hardwired, and also the libraries are fixed. This is
13 #    mainly because I was too scared to go anywhere near it.
14 #  - sbcsgen.pl is still run at startup.
15 #
16 # FIXME: no attempt made to handle !forceobj in the project files.
17
18 use FileHandle;
19 use Cwd;
20
21 open IN, "Recipe" or do {
22     # We want to deal correctly with being run from one of the
23     # subdirs in the source tree. So if we can't find Recipe here,
24     # try one level up.
25     chdir "..";
26     open IN, "Recipe" or die "unable to open Recipe file\n";
27 };
28
29 # HACK: One of the source files in `charset' is auto-generated by
30 # sbcsgen.pl. We need to generate that _now_, before attempting
31 # dependency analysis.
32 eval 'chdir "charset"; require "sbcsgen.pl"; chdir ".."';
33
34 @srcdirs = ("./");
35
36 $divert = undef; # ref to scalar in which text is currently being put
37 $help = ""; # list of newline-free lines of help text
38 $project_name = "project"; # this is a good enough default
39 %makefiles = (); # maps makefile types to output makefile pathnames
40 %makefile_extra = (); # maps makefile types to extra Makefile text
41 %programs = (); # maps prog name + type letter to listref of objects/resources
42 %groups = (); # maps group name to listref of objects/resources
43
44 while (<IN>) {
45   chomp;
46   @_ = split;
47
48   # If we're gathering help text, keep doing so.
49   if (defined $divert) {
50       if ((defined $_[0]) && $_[0] eq "!end") {
51           $divert = undef;
52       } else {
53           ${$divert} .= "$_\n";
54       }
55       next;
56   }
57   # Skip comments and blank lines.
58   next if /^\s*#/ or scalar @_ == 0;
59
60   if ($_[0] eq "!begin" and $_[1] eq "help") { $divert = \$help; next; }
61   if ($_[0] eq "!end") { $divert = undef; next; }
62   if ($_[0] eq "!name") { $project_name = $_[1]; next; }
63   if ($_[0] eq "!srcdir") { push @srcdirs, $_[1]; next; }
64   if ($_[0] eq "!makefile" and &mfval($_[1])) { $makefiles{$_[1]}=$_[2]; next;}
65   if ($_[0] eq "!specialobj" and &mfval($_[1])) { $specialobj{$_[1]}->{$_[2]} = 1; next;}
66   if ($_[0] eq "!forceobj") { $forceobj{$_[1]} = 1; next; }
67   if ($_[0] eq "!begin") {
68       if (&mfval($_[1])) {
69           $sect = $_[2] ? $_[2] : "end";
70           $divert = \($makefile_extra{$_[1]}->{$sect});
71       } else {
72           $dummy = '';
73           $divert = \$dummy;
74       }
75       next;
76   }
77   # If we're gathering help/verbatim text, keep doing so.
78   if (defined $divert) { ${$divert} .= "$_\n"; next; }
79   # Ignore blank lines.
80   next if scalar @_ == 0;
81
82   # Now we have an ordinary line. See if it's an = line, a : line
83   # or a + line.
84   @objs = @_;
85
86   if ($_[0] eq "+") {
87     $listref = $lastlistref;
88     $prog = undef;
89     die "$.: unexpected + line\n" if !defined $lastlistref;
90   } elsif ($_[1] eq "=") {
91     $groups{$_[0]} = [] if !defined $groups{$_[0]};
92     $listref = $groups{$_[0]};
93     $prog = undef;
94     shift @objs; # eat the group name
95   } elsif ($_[1] eq ":") {
96     $listref = [];
97     $prog = $_[0];
98     shift @objs; # eat the program name
99   } else {
100     die "$.: unrecognised line type\n";
101   }
102   shift @objs; # eat the +, the = or the :
103
104   while (scalar @objs > 0) {
105     $i = shift @objs;
106     if ($groups{$i}) {
107       foreach $j (@{$groups{$i}}) { unshift @objs, $j; }
108     } elsif (($i eq "[G]" or $i eq "[C]" or $i eq "[M]" or
109               $i eq "[X]" or $i eq "[U]" or $i eq "[MX]") and defined $prog) {
110       $type = substr($i,1,(length $i)-2);
111     } else {
112       push @$listref, $i;
113     }
114   }
115   if ($prog and $type) {
116     die "multiple program entries for $prog [$type]\n"
117         if defined $programs{$prog . "," . $type};
118     $programs{$prog . "," . $type} = $listref;
119   }
120   $lastlistref = $listref;
121 }
122
123 close IN;
124
125 # Now retrieve the complete list of objects and resource files, and
126 # construct dependency data for them. While we're here, expand the
127 # object list for each program, and complain if its type isn't set.
128 @prognames = sort keys %programs;
129 %depends = ();
130 @scanlist = ();
131 foreach $i (@prognames) {
132   ($prog, $type) = split ",", $i;
133   # Strip duplicate object names.
134   $prev = '';
135   @list = grep { $status = ($prev ne $_); $prev=$_; $status }
136           sort @{$programs{$i}};
137   $programs{$i} = [@list];
138   foreach $j (@list) {
139     # Dependencies for "x" start with "x.c" or "x.m" (depending on
140     # which one exists).
141     # Dependencies for "x.res" start with "x.rc".
142     # Dependencies for "x.rsrc" start with "x.r".
143     # Both types of file are pushed on the list of files to scan.
144     # Libraries (.lib) don't have dependencies at all.
145     if ($j =~ /^(.*)\.res$/) {
146       $file = "$1.rc";
147       $depends{$j} = [$file];
148       push @scanlist, $file;
149     } elsif ($j =~ /^(.*)\.rsrc$/) {
150       $file = "$1.r";
151       $depends{$j} = [$file];
152       push @scanlist, $file;
153     } elsif ($j !~ /\./) {
154       $file = "$j.c";
155       $file = "$j.m" unless &findfile($file);
156       $depends{$j} = [$file];
157       push @scanlist, $file;
158     }
159   }
160 }
161
162 # Scan each file on @scanlist and find further inclusions.
163 # Inclusions are given by lines of the form `#include "otherfile"'
164 # (system headers are automatically ignored by this because they'll
165 # be given in angle brackets). Files included by this method are
166 # added back on to @scanlist to be scanned in turn (if not already
167 # done).
168 #
169 # Resource scripts (.rc) can also include a file by means of:
170 #  - a line # ending `ICON "filename"';
171 #  - a line ending `RT_MANIFEST "filename"'.
172 # Files included by this method are not added to @scanlist because
173 # they can never include further files.
174 #
175 # In this pass we write out a hash %further which maps a source
176 # file name into a listref containing further source file names.
177
178 %further = ();
179 while (scalar @scanlist > 0) {
180   $file = shift @scanlist;
181   next if defined $further{$file}; # skip if we've already done it
182   $further{$file} = [];
183   $dirfile = &findfile($file);
184   open IN, "$dirfile" or die "unable to open source file $file\n";
185   while (<IN>) {
186     chomp;
187     /^\s*#include\s+\"([^\"]+)\"/ and do {
188       push @{$further{$file}}, $1;
189       push @scanlist, $1;
190       next;
191     };
192     /(RT_MANIFEST|ICON)\s+\"([^\"]+)\"\s*$/ and do {
193       push @{$further{$file}}, $2;
194       next;
195     }
196   }
197   close IN;
198 }
199
200 # Now we're ready to generate the final dependencies section. For
201 # each key in %depends, we must expand the dependencies list by
202 # iteratively adding entries from %further.
203 foreach $i (keys %depends) {
204   %dep = ();
205   @scanlist = @{$depends{$i}};
206   foreach $i (@scanlist) { $dep{$i} = 1; }
207   while (scalar @scanlist > 0) {
208     $file = shift @scanlist;
209     foreach $j (@{$further{$file}}) {
210       if (!$dep{$j}) {
211         $dep{$j} = 1;
212         push @{$depends{$i}}, $j;
213         push @scanlist, $j;
214       }
215     }
216   }
217 #  printf "%s: %s\n", $i, join ' ',@{$depends{$i}};
218 }
219
220 # Validation of input.
221
222 sub mfval($) {
223     my ($type) = @_;
224     # Returns true if the argument is a known makefile type. Otherwise,
225     # prints a warning and returns false;
226     if (grep { $type eq $_ }
227         ("vc","vcproj","cygwin","borland","lcc","devcppproj","gtk","unix",
228          "ac","mpw","osx",)) {
229             return 1;
230         }
231     warn "$.:unknown makefile type '$type'\n";
232     return 0;
233 }
234
235 # Utility routines while writing out the Makefiles.
236
237 sub def {
238     my ($x) = shift @_;
239     return (defined $x) ? $x : "";
240 }
241
242 sub dirpfx {
243     my ($path) = shift @_;
244     my ($sep) = shift @_;
245     my $ret = "";
246     my $i;
247
248     while (($i = index $path, $sep) >= 0 ||
249            ($j = index $path, "/") >= 0) {
250         if ($i >= 0 and ($j < 0 or $i < $j)) {
251             $path = substr $path, ($i + length $sep);
252         } else {
253             $path = substr $path, ($j + 1);
254         }
255         $ret .= "..$sep";
256     }
257     return $ret;
258 }
259
260 sub findfile {
261   my ($name) = @_;
262   my $dir = '';
263   my $i;
264   my $outdir = undef;
265   unless (defined $findfilecache{$name}) {
266     $i = 0;
267     foreach $dir (@srcdirs) {
268       if (-f "$dir$name") {
269         $outdir = $dir;
270         $i++;
271         $outdir =~ s/^\.\///;
272       }
273     }
274     die "multiple instances of source file $name\n" if $i > 1;
275     $findfilecache{$name} = (defined $outdir ? $outdir . $name : undef);
276   }
277   return $findfilecache{$name};
278 }
279
280 sub objects {
281   my ($prog, $otmpl, $rtmpl, $ltmpl, $prefix, $dirsep) = @_;
282   my @ret;
283   my ($i, $x, $y);
284   ($otmpl, $rtmpl, $ltmpl) = map { defined $_ ? $_ : "" } ($otmpl, $rtmpl, $ltmpl);
285   @ret = ();
286   foreach $i (@{$programs{$prog}}) {
287     $x = "";
288     if ($i =~ /^(.*)\.(res|rsrc)/) {
289       $y = $1;
290       ($x = $rtmpl) =~ s/X/$y/;
291     } elsif ($i =~ /^(.*)\.lib/) {
292       $y = $1;
293       ($x = $ltmpl) =~ s/X/$y/;
294     } elsif ($i !~ /\./) {
295       ($x = $otmpl) =~ s/X/$i/;
296     }
297     push @ret, $x if $x ne "";
298   }
299   return join " ", @ret;
300 }
301
302 sub special {
303   my ($prog, $suffix) = @_;
304   my @ret;
305   my ($i, $x, $y);
306   ($otmpl, $rtmpl, $ltmpl) = map { defined $_ ? $_ : "" } ($otmpl, $rtmpl, $ltmpl);
307   @ret = ();
308   foreach $i (@{$programs{$prog}}) {
309     if (substr($i, (length $i) - (length $suffix)) eq $suffix) {
310       push @ret, $i;
311     }
312   }
313   return (scalar @ret) ? (join " ", @ret) : undef;
314 }
315
316 sub splitline {
317   my ($line, $width, $splitchar) = @_;
318   my $result = "";
319   my $len;
320   $len = (defined $width ? $width : 76);
321   $splitchar = (defined $splitchar ? $splitchar : '\\');
322   while (length $line > $len) {
323     $line =~ /^(.{0,$len})\s(.*)$/ or $line =~ /^(.{$len,}?\s(.*)$/;
324     $result .= $1;
325     $result .= " ${splitchar}\n\t\t" if $2 ne '';
326     $line = $2;
327     $len = 60;
328   }
329   return $result . $line;
330 }
331
332 sub deps {
333   my ($otmpl, $rtmpl, $prefix, $dirsep, $mftyp, $depchar, $splitchar) = @_;
334   my ($i, $x, $y);
335   my @deps;
336   my @ret;
337   @ret = ();
338   $depchar ||= ':';
339   foreach $i (sort keys %depends) {
340     next if $specialobj{$mftyp}->{$i};
341     if ($i =~ /^(.*)\.(res|rsrc)/) {
342       next if !defined $rtmpl;
343       $y = $1;
344       ($x = $rtmpl) =~ s/X/$y/;
345     } else {
346       ($x = $otmpl) =~ s/X/$i/;
347     }
348     @deps = @{$depends{$i}};
349     @deps = map {
350       $_ = &findfile($_);
351       s/\//$dirsep/g;
352       $_ = $prefix . $_;
353     } @deps;
354     push @ret, {obj => $x, obj_orig => $i, deps => [@deps]};
355   }
356   return @ret;
357 }
358
359 sub prognames {
360   my ($types) = @_;
361   my ($n, $prog, $type);
362   my @ret;
363   @ret = ();
364   foreach $n (@prognames) {
365     ($prog, $type) = split ",", $n;
366     push @ret, $n if index(":$types:", ":$type:") >= 0;
367   }
368   return @ret;
369 }
370
371 sub progrealnames {
372   my ($types) = @_;
373   my ($n, $prog, $type);
374   my @ret;
375   @ret = ();
376   foreach $n (@prognames) {
377     ($prog, $type) = split ",", $n;
378     push @ret, $prog if index(":$types:", ":$type:") >= 0;
379   }
380   return @ret;
381 }
382
383 sub manpages {
384   my ($types,$suffix) = @_;
385
386   # assume that all UNIX programs have a man page
387   if($suffix eq "1" && $types =~ /:X:/) {
388     return map("$_.1", &progrealnames($types));
389   }
390   return ();
391 }
392
393 # Now we're ready to output the actual Makefiles.
394
395 if (defined $makefiles{'cygwin'}) {
396     $dirpfx = &dirpfx($makefiles{'cygwin'}, "/");
397
398     ##-- CygWin makefile
399     open OUT, ">$makefiles{'cygwin'}"; select OUT;
400     print
401     "# Makefile for $project_name under cygwin.\n".
402     "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n".
403     "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n";
404     # gcc command line option is -D not /D
405     ($_ = $help) =~ s/([=" ])\/D/$1-D/gs;
406     print $_;
407     print
408     "\n".
409     "# You can define this path to point at your tools if you need to\n".
410     "# TOOLPATH = c:\\cygwin\\bin\\ # or similar, if you're running Windows\n".
411     "# TOOLPATH = /pkg/mingw32msvc/i386-mingw32msvc/bin/\n".
412     "CC = \$(TOOLPATH)gcc\n".
413     "RC = \$(TOOLPATH)windres\n".
414     "# Uncomment the following two lines to compile under Winelib\n".
415     "# CC = winegcc\n".
416     "# RC = wrc\n".
417     "# You may also need to tell windres where to find include files:\n".
418     "# RCINC = --include-dir c:\\cygwin\\include\\\n".
419     "\n".
420     &splitline("CFLAGS = -mno-cygwin -Wall -O2 -D_WINDOWS -DDEBUG -DWIN32S_COMPAT".
421       " -D_NO_OLDNAMES -DNO_MULTIMON -DNO_HTMLHELP " .
422                (join " ", map {"-I$dirpfx$_"} @srcdirs)) .
423                "\n".
424     "LDFLAGS = -mno-cygwin -s\n".
425     &splitline("RCFLAGS = \$(RCINC) --define WIN32=1 --define _WIN32=1".
426       " --define WINVER=0x0400")."\n".
427     "\n".
428     $makefile_extra{'cygwin'}->{'vars'} .
429     "\n".
430     ".SUFFIXES:\n".
431     "\n";
432     print &splitline("all:" . join "", map { " $_.exe" } &progrealnames("G:C"));
433     print "\n\n";
434     foreach $p (&prognames("G:C")) {
435       ($prog, $type) = split ",", $p;
436       $objstr = &objects($p, "X.o", "X.res.o", undef);
437       print &splitline($prog . ".exe: " . $objstr), "\n";
438       my $mw = $type eq "G" ? " -mwindows" : "";
439       $libstr = &objects($p, undef, undef, "-lX");
440       print &splitline("\t\$(CC)" . $mw . " \$(LDFLAGS) -o \$@ " .
441                        "-Wl,-Map,$prog.map " .
442                        $objstr . " $libstr", 69), "\n\n";
443     }
444     foreach $d (&deps("X.o", "X.res.o", $dirpfx, "/", "cygwin")) {
445       if ($forceobj{$d->{obj_orig}}) {
446         printf ("%s: FORCE\n", $d->{obj});
447       } else {
448         print &splitline(sprintf("%s: %s", $d->{obj},
449                          join " ", @{$d->{deps}})), "\n";
450       }
451       if ($d->{obj} =~ /\.res\.o$/) {
452           print "\t\$(RC) \$(RCFL) \$(RCFLAGS) ".$d->{deps}->[0]." ".$d->{obj}."\n\n";
453       } else {
454           print "\t\$(CC) \$(COMPAT) \$(CFLAGS) \$(XFLAGS) -c ".$d->{deps}->[0]."\n\n";
455       }
456     }
457     print "\n";
458     print $makefile_extra{'cygwin'}->{'end'};
459     print "\nclean:\n".
460     "\trm -f *.o *.exe *.res.o *.map\n".
461     "\n".
462     "FORCE:\n";
463     select STDOUT; close OUT;
464
465 }
466
467 ##-- Borland makefile
468 if (defined $makefiles{'borland'}) {
469     $dirpfx = &dirpfx($makefiles{'borland'}, "\\");
470
471     %stdlibs = (  # Borland provides many Win32 API libraries intrinsically
472       "advapi32" => 1,
473       "comctl32" => 1,
474       "comdlg32" => 1,
475       "gdi32" => 1,
476       "imm32" => 1,
477       "shell32" => 1,
478       "user32" => 1,
479       "winmm" => 1,
480       "winspool" => 1,
481       "wsock32" => 1,
482     );
483     open OUT, ">$makefiles{'borland'}"; select OUT;
484     print
485     "# Makefile for $project_name under Borland C.\n".
486     "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n".
487     "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n";
488     # bcc32 command line option is -D not /D
489     ($_ = $help) =~ s/([=" ])\/D/$1-D/gs;
490     print $_;
491     print
492     "\n".
493     "# If you rename this file to `Makefile', you should change this line,\n".
494     "# so that the .rsp files still depend on the correct makefile.\n".
495     "MAKEFILE = Makefile.bor\n".
496     "\n".
497     "# C compilation flags\n".
498     "CFLAGS = -D_WINDOWS -DWINVER=0x0500\n".
499     "# Resource compilation flags\n".
500     "RCFLAGS = -DNO_WINRESRC_H -DWIN32 -D_WIN32 -DWINVER=0x0401\n".
501     "\n".
502     "# Get include directory for resource compiler\n".
503     "!if !\$d(BCB)\n".
504     "BCB = \$(MAKEDIR)\\..\n".
505     "!endif\n".
506     "\n".
507     $makefile_extra{'borland'}->{'vars'} .
508     "\n".
509     ".c.obj:\n".
510     &splitline("\tbcc32 -w-aus -w-ccc -w-par -w-pia \$(COMPAT)".
511                " \$(CFLAGS) \$(XFLAGS) ".
512                (join " ", map {"-I$dirpfx$_"} @srcdirs) .
513                " /c \$*.c",69)."\n".
514     ".rc.res:\n".
515     &splitline("\tbrcc32 \$(RCFL) -i \$(BCB)\\include -r".
516       " \$(RCFLAGS) \$*.rc",69)."\n".
517     "\n";
518     print &splitline("all:" . join "", map { " $_.exe" } &progrealnames("G:C"));
519     print "\n\n";
520     foreach $p (&prognames("G:C")) {
521       ($prog, $type) = split ",", $p;
522       $objstr =  &objects($p, "X.obj", "X.res", undef);
523       print &splitline("$prog.exe: " . $objstr . " $prog.rsp"), "\n";
524       my $ap = ($type eq "G") ? "-aa" : "-ap";
525       print "\tilink32 $ap -Gn -L\$(BCB)\\lib \@$prog.rsp\n\n";
526     }
527     foreach $p (&prognames("G:C")) {
528       ($prog, $type) = split ",", $p;
529       print $prog, ".rsp: \$(MAKEFILE)\n";
530       $objstr = &objects($p, "X.obj", undef, undef);
531       @objlist = split " ", $objstr;
532       @objlines = ("");
533       foreach $i (@objlist) {
534         if (length($objlines[$#objlines] . " $i") > 50) {
535           push @objlines, "";
536         }
537         $objlines[$#objlines] .= " $i";
538       }
539       $c0w = ($type eq "G") ? "c0w32" : "c0x32";
540       print "\techo $c0w + > $prog.rsp\n";
541       for ($i=0; $i<=$#objlines; $i++) {
542         $plus = ($i < $#objlines ? " +" : "");
543         print "\techo$objlines[$i]$plus >> $prog.rsp\n";
544       }
545       print "\techo $prog.exe >> $prog.rsp\n";
546       $objstr = &objects($p, "X.obj", "X.res", undef);
547       @libs = split " ", &objects($p, undef, undef, "X");
548       @libs = grep { !$stdlibs{$_} } @libs;
549       unshift @libs, "cw32", "import32";
550       $libstr = join ' ', @libs;
551       print "\techo nul,$libstr, >> $prog.rsp\n";
552       print "\techo " . &objects($p, undef, "X.res", undef) . " >> $prog.rsp\n";
553       print "\n";
554     }
555     foreach $d (&deps("X.obj", "X.res", $dirpfx, "\\", "borland")) {
556       if ($forceobj{$d->{obj_orig}}) {
557         printf("%s: FORCE\n", $d->{obj});
558       } else {
559         print &splitline(sprintf("%s: %s", $d->{obj},
560                                  join " ", @{$d->{deps}})), "\n";
561       }
562     }
563     print "\n";
564     print $makefile_extra{'borland'}->{'end'};
565     print "\nclean:\n".
566     "\t-del *.obj\n".
567     "\t-del *.exe\n".
568     "\t-del *.res\n".
569     "\t-del *.pch\n".
570     "\t-del *.aps\n".
571     "\t-del *.il*\n".
572     "\t-del *.pdb\n".
573     "\t-del *.rsp\n".
574     "\t-del *.tds\n".
575     "\t-del *.\$\$\$\$\$\$\n".
576     "\n".
577     "FORCE:\n".
578     "\t-rem dummy command\n";
579     select STDOUT; close OUT;
580 }
581
582 if (defined $makefiles{'vc'}) {
583     $dirpfx = &dirpfx($makefiles{'vc'}, "\\");
584
585     ##-- Visual C++ makefile
586     open OUT, ">$makefiles{'vc'}"; select OUT;
587     print
588       "# Makefile for $project_name under Visual C.\n".
589       "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n".
590       "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n";
591     print $help;
592     print
593       "\n".
594       "# If you rename this file to `Makefile', you should change this line,\n".
595       "# so that the .rsp files still depend on the correct makefile.\n".
596       "MAKEFILE = Makefile.vc\n".
597       "\n".
598       "# C compilation flags\n".
599       "CFLAGS = /nologo /W3 /O1 " .
600       (join " ", map {"-I$dirpfx$_"} @srcdirs) .
601       " /D_WINDOWS /D_WIN32_WINDOWS=0x500 /DWINVER=0x500\n".
602       "LFLAGS = /incremental:no /fixed\n".
603       "RCFLAGS = -DWIN32 -D_WIN32 -DWINVER=0x0400\n".
604       "\n".
605       $makefile_extra{'vc'}->{'vars'} .
606       "\n".
607       "\n";
608     print &splitline("all:" . join "", map { " $_.exe" } &progrealnames("G:C"));
609     print "\n\n";
610     foreach $p (&prognames("G:C")) {
611         ($prog, $type) = split ",", $p;
612         $objstr = &objects($p, "X.obj", "X.res", undef);
613         print &splitline("$prog.exe: " . $objstr . " $prog.rsp"), "\n";
614         print "\tlink \$(LFLAGS) -out:$prog.exe -map:$prog.map \@$prog.rsp\n\n";
615     }
616     foreach $p (&prognames("G:C")) {
617         ($prog, $type) = split ",", $p;
618         print $prog, ".rsp: \$(MAKEFILE)\n";
619         $objstr = &objects($p, "X.obj", "X.res", "X.lib");
620         @objlist = split " ", $objstr;
621         @objlines = ("");
622         foreach $i (@objlist) {
623             if (length($objlines[$#objlines] . " $i") > 50) {
624                 push @objlines, "";
625             }
626             $objlines[$#objlines] .= " $i";
627         }
628         $subsys = ($type eq "G") ? "windows" : "console";
629         print "\techo /nologo /subsystem:$subsys > $prog.rsp\n";
630         for ($i=0; $i<=$#objlines; $i++) {
631             print "\techo$objlines[$i] >> $prog.rsp\n";
632         }
633         print "\n";
634     }
635     foreach $d (&deps("X.obj", "X.res", $dirpfx, "\\", "vc")) {
636         $extradeps = $forceobj{$d->{obj_orig}} ? ["*.c","*.h","*.rc"] : [];
637         print &splitline(sprintf("%s: %s", $d->{obj},
638                                  join " ", @$extradeps, @{$d->{deps}})), "\n";
639         if ($d->{obj} =~ /.obj$/) {
640             print "\tcl \$(COMPAT) \$(CFLAGS) \$(XFLAGS) /c ".$d->{deps}->[0],"\n\n";
641         } else {
642             print "\trc \$(RCFL) -r \$(RCFLAGS) ".$d->{deps}->[0],"\n\n";
643         }
644     }
645     print "\n";
646     print $makefile_extra{'vc'}->{'end'};
647     print "\nclean: tidy\n".
648       "\t-del *.exe\n\n".
649       "tidy:\n".
650       "\t-del *.obj\n".
651       "\t-del *.res\n".
652       "\t-del *.pch\n".
653       "\t-del *.aps\n".
654       "\t-del *.ilk\n".
655       "\t-del *.pdb\n".
656       "\t-del *.rsp\n".
657       "\t-del *.dsp\n".
658       "\t-del *.dsw\n".
659       "\t-del *.ncb\n".
660       "\t-del *.opt\n".
661       "\t-del *.plg\n".
662       "\t-del *.map\n".
663       "\t-del *.idb\n".
664       "\t-del debug.log\n";
665     select STDOUT; close OUT;
666 }
667
668 if (defined $makefiles{'vcproj'}) {
669     $dirpfx = &dirpfx($makefiles{'vcproj'}, "\\");
670
671     $orig_dir = cwd;
672
673     ##-- MSVC 6 Workspace and projects
674     #
675     # Note: All files created in this section are written in binary
676     # mode, because although MSVC's command-line make can deal with
677     # LF-only line endings, MSVC project files really _need_ to be
678     # CRLF. Hence, in order for mkfiles.pl to generate usable project
679     # files even when run from Unix, I make sure all files are binary
680     # and explicitly write the CRLFs.
681     #
682     # Create directories if necessary
683     mkdir $makefiles{'vcproj'}
684         if(! -d $makefiles{'vcproj'});
685     chdir $makefiles{'vcproj'};
686     @deps = &deps("X.obj", "X.res", $dirpfx, "\\", "vcproj");
687     %all_object_deps = map {$_->{obj} => $_->{deps}} @deps;
688     # Create the project files
689     # Get names of all Windows projects (GUI and console)
690     my @prognames = &prognames("G:C");
691     foreach $progname (@prognames) {
692       create_vc_project(\%all_object_deps, $progname);
693     }
694     # Create the workspace file
695     open OUT, ">$project_name.dsw"; binmode OUT; select OUT;
696     print
697     "Microsoft Developer Studio Workspace File, Format Version 6.00\r\n".
698     "# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r\n".
699     "\r\n".
700     "###############################################################################\r\n".
701     "\r\n";
702     # List projects
703     foreach $progname (@prognames) {
704       ($windows_project, $type) = split ",", $progname;
705         print "Project: \"$windows_project\"=\".\\$windows_project\\$windows_project.dsp\" - Package Owner=<4>\r\n";
706     }
707     print
708     "\r\n".
709     "Package=<5>\r\n".
710     "{{{\r\n".
711     "}}}\r\n".
712     "\r\n".
713     "Package=<4>\r\n".
714     "{{{\r\n".
715     "}}}\r\n".
716     "\r\n".
717     "###############################################################################\r\n".
718     "\r\n".
719     "Global:\r\n".
720     "\r\n".
721     "Package=<5>\r\n".
722     "{{{\r\n".
723     "}}}\r\n".
724     "\r\n".
725     "Package=<3>\r\n".
726     "{{{\r\n".
727     "}}}\r\n".
728     "\r\n".
729     "###############################################################################\r\n".
730     "\r\n";
731     select STDOUT; close OUT;
732     chdir $orig_dir;
733
734     sub create_vc_project {
735         my ($all_object_deps, $progname) = @_;
736         # Construct program's dependency info
737         %seen_objects = ();
738         %lib_files = ();
739         %source_files = ();
740         %header_files = ();
741         %resource_files = ();
742         @object_files = split " ", &objects($progname, "X.obj", "X.res", "X.lib");
743         foreach $object_file (@object_files) {
744             next if defined $seen_objects{$object_file};
745             $seen_objects{$object_file} = 1;
746             if($object_file =~ /\.lib$/io) {
747                 $lib_files{$object_file} = 1;
748                 next;
749             }
750             $object_deps = $all_object_deps{$object_file};
751             foreach $object_dep (@$object_deps) {
752                 if($object_dep =~ /\.c$/io) {
753                     $source_files{$object_dep} = 1;
754                     next;
755                 }
756                 if($object_dep =~ /\.h$/io) {
757                     $header_files{$object_dep} = 1;
758                     next;
759                 }
760                 if($object_dep =~ /\.(rc|ico)$/io) {
761                     $resource_files{$object_dep} = 1;
762                     next;
763                 }
764             }
765         }
766         $libs = join " ", sort keys %lib_files;
767         @source_files = sort keys %source_files;
768         @header_files = sort keys %header_files;
769         @resources = sort keys %resource_files;
770         ($windows_project, $type) = split ",", $progname;
771         mkdir $windows_project
772             if(! -d $windows_project);
773         chdir $windows_project;
774         $subsys = ($type eq "G") ? "windows" : "console";
775         open OUT, ">$windows_project.dsp"; binmode OUT; select OUT;
776         print
777         "# Microsoft Developer Studio Project File - Name=\"$windows_project\" - Package Owner=<4>\r\n".
778         "# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n".
779         "# ** DO NOT EDIT **\r\n".
780         "\r\n".
781         "# TARGTYPE \"Win32 (x86) Application\" 0x0101\r\n".
782         "\r\n".
783         "CFG=$windows_project - Win32 Debug\r\n".
784         "!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n".
785         "!MESSAGE use the Export Makefile command and run\r\n".
786         "!MESSAGE \r\n".
787         "!MESSAGE NMAKE /f \"$windows_project.mak\".\r\n".
788         "!MESSAGE \r\n".
789         "!MESSAGE You can specify a configuration when running NMAKE\r\n".
790         "!MESSAGE by defining the macro CFG on the command line. For example:\r\n".
791         "!MESSAGE \r\n".
792         "!MESSAGE NMAKE /f \"$windows_project.mak\" CFG=\"$windows_project - Win32 Debug\"\r\n".
793         "!MESSAGE \r\n".
794         "!MESSAGE Possible choices for configuration are:\r\n".
795         "!MESSAGE \r\n".
796         "!MESSAGE \"$windows_project - Win32 Release\" (based on \"Win32 (x86) Application\")\r\n".
797         "!MESSAGE \"$windows_project - Win32 Debug\" (based on \"Win32 (x86) Application\")\r\n".
798         "!MESSAGE \r\n".
799         "\r\n".
800         "# Begin Project\r\n".
801         "# PROP AllowPerConfigDependencies 0\r\n".
802         "# PROP Scc_ProjName \"\"\r\n".
803         "# PROP Scc_LocalPath \"\"\r\n".
804         "CPP=cl.exe\r\n".
805         "MTL=midl.exe\r\n".
806         "RSC=rc.exe\r\n".
807         "\r\n".
808         "!IF  \"\$(CFG)\" == \"$windows_project - Win32 Release\"\r\n".
809         "\r\n".
810         "# PROP BASE Use_MFC 0\r\n".
811         "# PROP BASE Use_Debug_Libraries 0\r\n".
812         "# PROP BASE Output_Dir \"Release\"\r\n".
813         "# PROP BASE Intermediate_Dir \"Release\"\r\n".
814         "# PROP BASE Target_Dir \"\"\r\n".
815         "# PROP Use_MFC 0\r\n".
816         "# PROP Use_Debug_Libraries 0\r\n".
817         "# PROP Output_Dir \"Release\"\r\n".
818         "# PROP Intermediate_Dir \"Release\"\r\n".
819         "# PROP Ignore_Export_Lib 0\r\n".
820         "# PROP Target_Dir \"\"\r\n".
821         "# ADD BASE CPP /nologo /W3 /GX /O2 ".
822           (join " ", map {"/I \"..\\..\\$dirpfx$_\""} @srcdirs) .
823           " /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /c\r\n".
824         "# ADD CPP /nologo /W3 /GX /O2 ".
825           (join " ", map {"/I \"..\\..\\$dirpfx$_\""} @srcdirs) .
826           " /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /c\r\n".
827         "# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n".
828         "# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n".
829         "# ADD BASE RSC /l 0x809 /d \"NDEBUG\"\r\n".
830         "# ADD RSC /l 0x809 /d \"NDEBUG\"\r\n".
831         "BSC32=bscmake.exe\r\n".
832         "# ADD BASE BSC32 /nologo\r\n".
833         "# ADD BSC32 /nologo\r\n".
834         "LINK32=link.exe\r\n".
835         "# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:$subsys /machine:I386\r\n".
836         "# ADD LINK32 $libs /nologo /subsystem:$subsys /machine:I386\r\n".
837         "# SUBTRACT LINK32 /pdb:none\r\n".
838         "\r\n".
839         "!ELSEIF  \"\$(CFG)\" == \"$windows_project - Win32 Debug\"\r\n".
840         "\r\n".
841         "# PROP BASE Use_MFC 0\r\n".
842         "# PROP BASE Use_Debug_Libraries 1\r\n".
843         "# PROP BASE Output_Dir \"Debug\"\r\n".
844         "# PROP BASE Intermediate_Dir \"Debug\"\r\n".
845         "# PROP BASE Target_Dir \"\"\r\n".
846         "# PROP Use_MFC 0\r\n".
847         "# PROP Use_Debug_Libraries 1\r\n".
848         "# PROP Output_Dir \"Debug\"\r\n".
849         "# PROP Intermediate_Dir \"Debug\"\r\n".
850         "# PROP Ignore_Export_Lib 0\r\n".
851         "# PROP Target_Dir \"\"\r\n".
852         "# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od ".
853           (join " ", map {"/I \"..\\..\\$dirpfx$_\""} @srcdirs) .
854           " /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /GZ /c\r\n".
855         "# ADD CPP /nologo /W3 /Gm /GX /ZI /Od ".
856           (join " ", map {"/I \"..\\..\\$dirpfx$_\""} @srcdirs) .
857           " /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /GZ /c\r\n".
858         "# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\r\n".
859         "# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\r\n".
860         "# ADD BASE RSC /l 0x809 /d \"_DEBUG\"\r\n".
861         "# ADD RSC /l 0x809 /d \"_DEBUG\"\r\n".
862         "BSC32=bscmake.exe\r\n".
863         "# ADD BASE BSC32 /nologo\r\n".
864         "# ADD BSC32 /nologo\r\n".
865         "LINK32=link.exe\r\n".
866         "# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:$subsys /debug /machine:I386 /pdbtype:sept\r\n".
867         "# ADD LINK32 $libs /nologo /subsystem:$subsys /debug /machine:I386 /pdbtype:sept\r\n".
868         "# SUBTRACT LINK32 /pdb:none\r\n".
869         "\r\n".
870         "!ENDIF \r\n".
871         "\r\n".
872         "# Begin Target\r\n".
873         "\r\n".
874         "# Name \"$windows_project - Win32 Release\"\r\n".
875         "# Name \"$windows_project - Win32 Debug\"\r\n".
876         "# Begin Group \"Source Files\"\r\n".
877         "\r\n".
878         "# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n";
879         foreach $source_file (@source_files) {
880             print
881               "# Begin Source File\r\n".
882               "\r\n".
883               "SOURCE=..\\..\\$source_file\r\n";
884             if($source_file =~ /ssh\.c/io) {
885                 # Disable 'Edit and continue' as Visual Studio can't handle the macros
886                 print
887                   "\r\n".
888                   "!IF  \"\$(CFG)\" == \"$windows_project - Win32 Release\"\r\n".
889                   "\r\n".
890                   "!ELSEIF  \"\$(CFG)\" == \"$windows_project - Win32 Debug\"\r\n".
891                   "\r\n".
892                   "# ADD CPP /Zi\r\n".
893                   "\r\n".
894                   "!ENDIF \r\n".
895                   "\r\n";
896             }
897             print "# End Source File\r\n";
898         }
899         print
900         "# End Group\r\n".
901         "# Begin Group \"Header Files\"\r\n".
902         "\r\n".
903         "# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n";
904         foreach $header_file (@header_files) {
905             print
906               "# Begin Source File\r\n".
907               "\r\n".
908               "SOURCE=..\\..\\$header_file\r\n".
909               "# End Source File\r\n";
910         }
911         print
912         "# End Group\r\n".
913         "# Begin Group \"Resource Files\"\r\n".
914         "\r\n".
915         "# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n";
916         foreach $resource_file (@resources) {
917             print
918               "# Begin Source File\r\n".
919               "\r\n".
920               "SOURCE=..\\..\\$resource_file\r\n".
921               "# End Source File\r\n";
922         }
923         print
924         "# End Group\r\n".
925         "# End Target\r\n".
926         "# End Project\r\n";
927         select STDOUT; close OUT;
928         chdir "..";
929     }
930 }
931
932 if (defined $makefiles{'gtk'}) {
933     $dirpfx = &dirpfx($makefiles{'gtk'}, "/");
934
935     ##-- X/GTK/Unix makefile
936     open OUT, ">$makefiles{'gtk'}"; select OUT;
937     print
938     "# Makefile for $project_name under X/GTK and Unix.\n".
939     "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n".
940     "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n";
941     # gcc command line option is -D not /D
942     ($_ = $help) =~ s/([=" ])\/D/$1-D/gs;
943     print $_;
944     print
945     "\n".
946     "# You can define this path to point at your tools if you need to\n".
947     "# TOOLPATH = /opt/gcc/bin\n".
948     "CC = \$(TOOLPATH)cc\n".
949     "# If necessary set the path to krb5-config here\n".
950     "KRB5CONFIG=krb5-config\n".
951     "# You can manually set this to `gtk-config' or `pkg-config gtk+-1.2'\n".
952     "# (depending on what works on your system) if you want to enforce\n".
953     "# building with GTK 1.2, or you can set it to `pkg-config gtk+-2.0 x11'\n".
954     "# if you want to enforce 2.0. The default is to try 2.0 and fall back\n".
955     "# to 1.2 if it isn't found.\n".
956     "GTK_CONFIG = sh -c 'pkg-config gtk+-2.0 x11 \$\$0 2>/dev/null || gtk-config \$\$0'\n".
957     "\n".
958     "-include Makefile.local\n".
959     "\n".
960     "unexport CFLAGS # work around a weird issue with krb5-config\n".
961     "\n".
962     &splitline("CFLAGS = -O2 -Wall -Werror -g " .
963                (join " ", map {"-I$dirpfx$_"} @srcdirs) .
964                " \$(shell \$(GTK_CONFIG) --cflags)").
965                  " -D _FILE_OFFSET_BITS=64\n".
966     "XLDFLAGS = \$(LDFLAGS) \$(shell \$(GTK_CONFIG) --libs)\n".
967     "ULDFLAGS = \$(LDFLAGS)\n".
968     "ifeq (,\$(findstring NO_GSSAPI,\$(COMPAT)))\n".
969     "ifeq (,\$(findstring STATIC_GSSAPI,\$(COMPAT)))\n".
970     "XLDFLAGS+= -ldl\n".
971     "ULDFLAGS+= -ldl\n".
972     "else\n".
973     "CFLAGS+= -DNO_LIBDL \$(shell \$(KRB5CONFIG) --cflags gssapi)\n".
974     "XLDFLAGS+= \$(shell \$(KRB5CONFIG) --libs gssapi)\n".
975     "ULDFLAGS+= \$(shell \$(KRB5CONFIG) --libs gssapi)\n".
976     "endif\n".
977     "endif\n".
978     "INSTALL=install\n".
979     "INSTALL_PROGRAM=\$(INSTALL)\n".
980     "INSTALL_DATA=\$(INSTALL)\n".
981     "prefix=/usr/local\n".
982     "exec_prefix=\$(prefix)\n".
983     "bindir=\$(exec_prefix)/bin\n".
984     "mandir=\$(prefix)/man\n".
985     "man1dir=\$(mandir)/man1\n".
986     "\n".
987     &def($makefile_extra{'gtk'}->{'vars'}) .
988     "\n".
989     ".SUFFIXES:\n".
990     "\n".
991     "\n";
992     print &splitline("all:" . join "", map { " $_" } &progrealnames("X:U"));
993     print "\n\n";
994     foreach $p (&prognames("X:U")) {
995       ($prog, $type) = split ",", $p;
996       $objstr = &objects($p, "X.o", undef, undef);
997       print &splitline($prog . ": " . $objstr), "\n";
998       $libstr = &objects($p, undef, undef, "-lX");
999       print &splitline("\t\$(CC) -o \$@ " .
1000                        $objstr . " \$(${type}LDFLAGS) $libstr", 69), "\n\n";
1001     }
1002     foreach $d (&deps("X.o", undef, $dirpfx, "/", "gtk")) {
1003       if ($forceobj{$d->{obj_orig}}) {
1004         printf("%s: FORCE\n", $d->{obj});
1005       } else {
1006         print &splitline(sprintf("%s: %s", $d->{obj},
1007                                  join " ", @{$d->{deps}})), "\n";
1008       }
1009       print &splitline("\t\$(CC) \$(COMPAT) \$(CFLAGS) \$(XFLAGS) -c $d->{deps}->[0]\n");
1010     }
1011     print "\n";
1012     print $makefile_extra{'gtk'}->{'end'};
1013     print "\nclean:\n".
1014     "\trm -f *.o". (join "", map { " $_" } &progrealnames("X:U")) . "\n";
1015     print "\nFORCE:\n";
1016     select STDOUT; close OUT;
1017 }
1018
1019 if (defined $makefiles{'unix'}) {
1020     $dirpfx = &dirpfx($makefiles{'unix'}, "/");
1021
1022     ##-- GTK-free pure-Unix makefile for non-GUI apps only
1023     open OUT, ">$makefiles{'unix'}"; select OUT;
1024     print
1025     "# Makefile for $project_name under Unix.\n".
1026     "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n".
1027     "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n";
1028     # gcc command line option is -D not /D
1029     ($_ = $help) =~ s/([=" ])\/D/$1-D/gs;
1030     print $_;
1031     print
1032     "\n".
1033     "# You can define this path to point at your tools if you need to\n".
1034     "# TOOLPATH = /opt/gcc/bin\n".
1035     "CC = \$(TOOLPATH)cc\n".
1036     "\n".
1037     "-include Makefile.local\n".
1038     "\n".
1039     "unexport CFLAGS # work around a weird issue with krb5-config\n".
1040     "\n".
1041     &splitline("CFLAGS = -O2 -Wall -Werror -g " .
1042                (join " ", map {"-I$dirpfx$_"} @srcdirs)).
1043                  " -D _FILE_OFFSET_BITS=64\n".
1044     "ULDFLAGS = \$(LDFLAGS)\n".
1045     "INSTALL=install\n".
1046     "INSTALL_PROGRAM=\$(INSTALL)\n".
1047     "INSTALL_DATA=\$(INSTALL)\n".
1048     "prefix=/usr/local\n".
1049     "exec_prefix=\$(prefix)\n".
1050     "bindir=\$(exec_prefix)/bin\n".
1051     "mandir=\$(prefix)/man\n".
1052     "man1dir=\$(mandir)/man1\n".
1053     "\n".
1054     &def($makefile_extra{'unix'}->{'vars'}) .
1055     "\n".
1056     ".SUFFIXES:\n".
1057     "\n".
1058     "\n";
1059     print &splitline("all:" . join "", map { " $_" } &progrealnames("U"));
1060     print "\n\n";
1061     foreach $p (&prognames("U")) {
1062       ($prog, $type) = split ",", $p;
1063       $objstr = &objects($p, "X.o", undef, undef);
1064       print &splitline($prog . ": " . $objstr), "\n";
1065       $libstr = &objects($p, undef, undef, "-lX");
1066       print &splitline("\t\$(CC) -o \$@ " .
1067                        $objstr . " \$(${type}LDFLAGS) $libstr", 69), "\n\n";
1068     }
1069     foreach $d (&deps("X.o", undef, $dirpfx, "/", "unix")) {
1070       if ($forceobj{$d->{obj_orig}}) {
1071         printf("%s: FORCE\n", $d->{obj});
1072       } else {
1073         print &splitline(sprintf("%s: %s", $d->{obj},
1074                                  join " ", @{$d->{deps}})), "\n";
1075       }
1076       print &splitline("\t\$(CC) \$(COMPAT) \$(CFLAGS) \$(XFLAGS) -c $d->{deps}->[0]\n");
1077     }
1078     print "\n";
1079     print &def($makefile_extra{'unix'}->{'end'});
1080     print "\nclean:\n".
1081     "\trm -f *.o". (join "", map { " $_" } &progrealnames("U")) . "\n";
1082     print "\nFORCE:\n";
1083     select STDOUT; close OUT;
1084 }
1085
1086 if (defined $makefiles{'ac'}) {
1087     $dirpfx = &dirpfx($makefiles{'ac'}, "/");
1088
1089     ##-- Unix/autoconf makefile
1090     open OUT, ">$makefiles{'ac'}"; select OUT;
1091     print
1092     "# Makefile.in for $project_name under Unix with Autoconf.\n".
1093     "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n".
1094     "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n";
1095     # gcc command line option is -D not /D
1096     ($_ = $help) =~ s/([=" ])\/D/$1-D/gs;
1097     print $_;
1098     print
1099     "\n".
1100     "CC = \@CC\@\n".
1101     "\n".
1102     &splitline("CFLAGS = \@CFLAGS\@ \@PUTTYCFLAGS\@ \@CPPFLAGS\@ " .
1103                "\@DEFS\@ \@GTK_CFLAGS\@ " .
1104                (join " ", map {"-I$dirpfx$_"} @srcdirs))."\n".
1105     "XLDFLAGS = \@LDFLAGS\@ \@LIBS\@ \@GTK_LIBS\@\n".
1106     "ULDFLAGS = \@LDFLAGS\@ \@LIBS\@\n".
1107     "INSTALL=\@INSTALL\@\n".
1108     "INSTALL_PROGRAM=\$(INSTALL)\n".
1109     "INSTALL_DATA=\$(INSTALL)\n".
1110     "prefix=\@prefix\@\n".
1111     "exec_prefix=\@exec_prefix\@\n".
1112     "bindir=\@bindir\@\n".
1113     "datarootdir=\@datarootdir\@\n".
1114     "mandir=\@mandir\@\n".
1115     "man1dir=\$(mandir)/man1\n".
1116     "\n".
1117     &def($makefile_extra{'gtk'}->{'vars'}) .
1118     "\n".
1119     ".SUFFIXES:\n".
1120     "\n".
1121     "\n".
1122     "all: \@all_targets\@\n".
1123     &splitline("all-cli:" . join "", map { " $_" } &progrealnames("U"))."\n".
1124     &splitline("all-gtk:" . join "", map { " $_" } &progrealnames("X"))."\n";
1125     print "\n";
1126     foreach $p (&prognames("X:U")) {
1127       ($prog, $type) = split ",", $p;
1128       $objstr = &objects($p, "X.o", undef, undef);
1129       print &splitline($prog . ": " . $objstr), "\n";
1130       $libstr = &objects($p, undef, undef, "-lX");
1131       print &splitline("\t\$(CC) -o \$@ " .
1132                        $objstr . " \$(${type}LDFLAGS) $libstr", 69), "\n\n";
1133     }
1134     foreach $d (&deps("X.o", undef, $dirpfx, "/", "gtk")) {
1135       if ($forceobj{$d->{obj_orig}}) {
1136         printf("%s: FORCE\n", $d->{obj});
1137       } else {
1138         print &splitline(sprintf("%s: %s", $d->{obj},
1139                                  join " ", @{$d->{deps}})), "\n";
1140       }
1141       print &splitline("\t\$(CC) \$(COMPAT) \$(CFLAGS) \$(XFLAGS) -c $d->{deps}->[0]\n");
1142     }
1143     print "\n";
1144     print $makefile_extra{'gtk'}->{'end'};
1145     print "\nclean:\n".
1146     "\trm -f *.o". (join "", map { " $_" } &progrealnames("X:U")) . "\n";
1147     print "\ndistclean: clean\n".
1148     "\t". &splitline("rm -f config.status config.cache config.log ".
1149                      "configure.lineno config.status.lineno Makefile") . "\n";
1150     print "\nFORCE:\n";
1151     select STDOUT; close OUT;
1152 }
1153
1154 if (defined $makefiles{'mpw'}) {
1155     ##-- MPW Makefile
1156     open OUT, ">$makefiles{'mpw'}"; select OUT;
1157     print
1158     "# Makefile for $project_name under MPW.\n#\n".
1159     "# This file was created by `mkfiles.pl' from the `Recipe' file.\n".
1160     "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n";
1161     # MPW command line option is -d not /D (FIXME further massaging?)
1162     ($_ = $help) =~ s/([=" ])\/D/$1-d /gs;
1163     print $_;
1164     print "\n\n".
1165     "ROptions     = `Echo \"{VER}\" | StreamEdit -e \"1,\$ replace /=(\xc5)\xa81\xb0/ 'STR=\xb6\xb6\xb6\xb6\xb6\"' \xa81 '\xb6\xb6\xb6\xb6\xb6\"'\"`".
1166     "\n".
1167     "C_68K = {C}\n".
1168     "C_CFM68K = {C}\n".
1169     "C_PPC = {PPCC}\n".
1170     "C_Carbon = {PPCC}\n".
1171     "\n".
1172     "# -w 35 disables \"unused parameter\" warnings\n".
1173     "COptions     = -i : -i :: -i ::charset -w 35 -w err -proto strict -ansi on \xb6\n".
1174     "          -notOnce\n".
1175     "COptions_68K = {COptions} -model far -opt time\n".
1176     "# Enabling \"-opt space\" for CFM-68K gives me undefined references to\n".
1177     "# _\$LDIVT and _\$LMODT.\n".
1178     "COptions_CFM68K = {COptions} -model cfmSeg -opt time\n".
1179     "COptions_PPC = {COptions} -opt size -traceback\n".
1180     "COptions_Carbon = {COptions} -opt size -traceback -d TARGET_API_MAC_CARBON\n".
1181     "\n".
1182     "Link_68K = ILink\n".
1183     "Link_CFM68K = ILink\n".
1184     "Link_PPC = PPCLink\n".
1185     "Link_Carbon = PPCLink\n".
1186     "\n".
1187     "LinkOptions = -c 'pTTY'\n".
1188     "LinkOptions_68K = {LinkOptions} -br 68k -model far -compact\n".
1189     "LinkOptions_CFM68K = {LinkOptions} -br 020 -model cfmseg -compact\n".
1190     "LinkOptions_PPC = {LinkOptions}\n".
1191     "LinkOptions_Carbon = -m __appstart -w {LinkOptions}\n".
1192     "\n".
1193     "Libs_68K = \"{CLibraries}StdCLib.far.o\" \xb6\n".
1194     "           \"{Libraries}MacRuntime.o\" \xb6\n".
1195     "           \"{Libraries}MathLib.far.o\" \xb6\n".
1196     "           \"{Libraries}IntEnv.far.o\" \xb6\n".
1197     "           \"{Libraries}Interface.o\" \xb6\n".
1198     "           \"{Libraries}Navigation.far.o\" \xb6\n".
1199     "           \"{Libraries}OpenTransport.o\" \xb6\n".
1200     "           \"{Libraries}OpenTransportApp.o\" \xb6\n".
1201     "           \"{Libraries}OpenTptInet.o\" \xb6\n".
1202     "           \"{Libraries}UnicodeConverterLib.far.o\"\n".
1203     "\n".
1204     "Libs_CFM = \"{SharedLibraries}InterfaceLib\" \xb6\n".
1205     "           \"{SharedLibraries}StdCLib\" \xb6\n".
1206     "           \"{SharedLibraries}AppearanceLib\" \xb6\n".
1207     "                   -weaklib AppearanceLib \xb6\n".
1208     "           \"{SharedLibraries}NavigationLib\" \xb6\n".
1209     "                   -weaklib NavigationLib \xb6\n".
1210     "           \"{SharedLibraries}TextCommon\" \xb6\n".
1211     "                   -weaklib TextCommon \xb6\n".
1212     "           \"{SharedLibraries}UnicodeConverter\" \xb6\n".
1213     "                   -weaklib UnicodeConverter\n".
1214     "\n".
1215     "Libs_CFM68K =      {Libs_CFM} \xb6\n".
1216     "           \"{CFM68KLibraries}NuMacRuntime.o\"\n".
1217     "\n".
1218     "Libs_PPC = {Libs_CFM} \xb6\n".
1219     "           \"{SharedLibraries}ControlsLib\" \xb6\n".
1220     "                   -weaklib ControlsLib \xb6\n".
1221     "           \"{SharedLibraries}WindowsLib\" \xb6\n".
1222     "                   -weaklib WindowsLib \xb6\n".
1223     "           \"{SharedLibraries}OpenTransportLib\" \xb6\n".
1224     "                   -weaklib OTClientLib \xb6\n".
1225     "                   -weaklib OTClientUtilLib \xb6\n".
1226     "           \"{SharedLibraries}OpenTptInternetLib\" \xb6\n".
1227     "                   -weaklib OTInetClientLib \xb6\n".
1228     "           \"{PPCLibraries}StdCRuntime.o\" \xb6\n".
1229     "           \"{PPCLibraries}PPCCRuntime.o\" \xb6\n".
1230     "           \"{PPCLibraries}CarbonAccessors.o\" \xb6\n".
1231     "           \"{PPCLibraries}OpenTransportAppPPC.o\" \xb6\n".
1232     "           \"{PPCLibraries}OpenTptInetPPC.o\"\n".
1233     "\n".
1234     "Libs_Carbon =      \"{PPCLibraries}CarbonStdCLib.o\" \xb6\n".
1235     "           \"{PPCLibraries}StdCRuntime.o\" \xb6\n".
1236     "           \"{PPCLibraries}PPCCRuntime.o\" \xb6\n".
1237     "           \"{SharedLibraries}CarbonLib\" \xb6\n".
1238     "           \"{SharedLibraries}StdCLib\"\n".
1239     "\n";
1240     print &splitline("all \xc4 " . join(" ", &progrealnames("M")), undef, "\xb6");
1241     print "\n\n";
1242     foreach $p (&prognames("M")) {
1243       ($prog, $type) = split ",", $p;
1244
1245       print &splitline("$prog \xc4 $prog.68k $prog.ppc $prog.carbon",
1246                    undef, "\xb6"), "\n\n";
1247
1248       $rsrc = &objects($p, "", "X.rsrc", undef);
1249
1250       foreach $arch (qw(68K CFM68K PPC Carbon)) {
1251           $objstr = &objects($p, "X.\L$arch\E.o", "", undef);
1252           print &splitline("$prog.\L$arch\E \xc4 $objstr $rsrc", undef, "\xb6");
1253           print "\n";
1254           print &splitline("\tDuplicate -y $rsrc {Targ}", 69, "\xb6"), "\n";
1255           print &splitline("\t{Link_$arch} -o {Targ} -fragname $prog " .
1256                        "{LinkOptions_$arch} " .
1257                        $objstr . " {Libs_$arch}", 69, "\xb6"), "\n";
1258           print &splitline("\tSetFile -a BMi {Targ}", 69, "\xb6"), "\n\n";
1259       }
1260
1261     }
1262     foreach $d (&deps("", "X.rsrc", "::", ":", "mpw")) {
1263       next unless $d->{obj};
1264       print &splitline(sprintf("%s \xc4 %s", $d->{obj}, join " ", @{$d->{deps}}),
1265                    undef, "\xb6"), "\n";
1266       print "\tRez ", $d->{deps}->[0], " -o {Targ} {ROptions}\n\n";
1267     }
1268     foreach $arch (qw(68K CFM68K)) {
1269         foreach $d (&deps("X.\L$arch\E.o", "", "::", ":", "mpw")) {
1270          next unless $d->{obj};
1271         print &splitline(sprintf("%s \xc4 %s", $d->{obj},
1272                                  join " ", @{$d->{deps}}),
1273                          undef, "\xb6"), "\n";
1274          print "\t{C_$arch} ", $d->{deps}->[0],
1275                " -o {Targ} {COptions_$arch}\n\n";
1276          }
1277     }
1278     foreach $arch (qw(PPC Carbon)) {
1279         foreach $d (&deps("X.\L$arch\E.o", "", "::", ":", "mpw")) {
1280          next unless $d->{obj};
1281         print &splitline(sprintf("%s \xc4 %s", $d->{obj},
1282                                  join " ", @{$d->{deps}}),
1283                          undef, "\xb6"), "\n";
1284          # The odd stuff here seems to stop afpd getting confused.
1285          print "\techo -n > {Targ}\n";
1286          print "\tsetfile -t XCOF {Targ}\n";
1287          print "\t{C_$arch} ", $d->{deps}->[0],
1288                " -o {Targ} {COptions_$arch}\n\n";
1289          }
1290     }
1291     select STDOUT; close OUT;
1292 }
1293
1294 if (defined $makefiles{'lcc'}) {
1295     $dirpfx = &dirpfx($makefiles{'lcc'}, "\\");
1296
1297     ##-- lcc makefile
1298     open OUT, ">$makefiles{'lcc'}"; select OUT;
1299     print
1300     "# Makefile for $project_name under lcc.\n".
1301     "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n".
1302     "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n";
1303     # lcc command line option is -D not /D
1304     ($_ = $help) =~ s/([=" ])\/D/$1-D/gs;
1305     print $_;
1306     print
1307     "\n".
1308     "# If you rename this file to `Makefile', you should change this line,\n".
1309     "# so that the .rsp files still depend on the correct makefile.\n".
1310     "MAKEFILE = Makefile.lcc\n".
1311     "\n".
1312     "# C compilation flags\n".
1313     "CFLAGS = -D_WINDOWS " .
1314       (join " ", map {"-I$dirpfx$_"} @srcdirs) .
1315       "\n".
1316     "# Resource compilation flags\n".
1317     "RCFLAGS = \n".
1318     "\n".
1319     "# Get include directory for resource compiler\n".
1320     "\n".
1321     $makefile_extra{'lcc'}->{'vars'} .
1322     "\n";
1323     print &splitline("all:" . join "", map { " $_.exe" } &progrealnames("G:C"));
1324     print "\n\n";
1325     foreach $p (&prognames("G:C")) {
1326       ($prog, $type) = split ",", $p;
1327       $objstr = &objects($p, "X.obj", "X.res", undef);
1328       print &splitline("$prog.exe: " . $objstr ), "\n";
1329       $subsystemtype = '';
1330       if ($type eq "G") { $subsystemtype = "-subsystem  windows"; }
1331       my $libss = "shell32.lib wsock32.lib ws2_32.lib winspool.lib winmm.lib imm32.lib";
1332       print &splitline("\tlcclnk $subsystemtype -o $prog.exe $objstr $libss");
1333       print "\n\n";
1334     }
1335
1336     foreach $d (&deps("X.obj", "X.res", $dirpfx, "\\", "lcc")) {
1337       if ($forceobj{$d->{obj_orig}}) {
1338          printf("%s: FORCE\n", $d->{obj});
1339       } else {
1340          print &splitline(sprintf("%s: %s", $d->{obj},
1341                           join " ", @{$d->{deps}})), "\n";
1342       }
1343       if ($d->{obj} =~ /\.obj$/) {
1344           print &splitline("\tlcc -O -p6 \$(COMPAT)".
1345                            " \$(CFLAGS) \$(XFLAGS) ".$d->{deps}->[0],69)."\n";
1346       } else {
1347           print &splitline("\tlrc \$(RCFL) -r \$(RCFLAGS) ".
1348                            $d->{deps}->[0],69)."\n";
1349       }
1350     }
1351     print "\n";
1352     print $makefile_extra{'lcc'}->{'end'};
1353     print "\nclean:\n".
1354     "\t-del *.obj\n".
1355     "\t-del *.exe\n".
1356     "\t-del *.res\n".
1357     "\n".
1358     "FORCE:\n";
1359
1360     select STDOUT; close OUT;
1361 }
1362
1363 if (defined $makefiles{'osx'}) {
1364     $dirpfx = &dirpfx($makefiles{'osx'}, "/");
1365
1366     ##-- Mac OS X makefile
1367     open OUT, ">$makefiles{'osx'}"; select OUT;
1368     print
1369     "# Makefile for $project_name under Mac OS X.\n".
1370     "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n".
1371     "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n";
1372     # gcc command line option is -D not /D
1373     ($_ = $help) =~ s/([=" ])\/D/$1-D/gs;
1374     print $_;
1375     print
1376     "CC = \$(TOOLPATH)gcc\n".
1377     "\n".
1378     &splitline("CFLAGS = -O2 -Wall -Werror -g " .
1379                (join " ", map {"-I$dirpfx$_"} @srcdirs))."\n".
1380     "MLDFLAGS = -framework Cocoa\n".
1381     "ULDFLAGS =\n".
1382     "\n" .
1383     $makefile_extra{'osx'}->{'vars'} .
1384     "\n" .
1385     &splitline("all:" . join "", map { " $_" } &progrealnames("MX:U")) .
1386     "\n";
1387     foreach $p (&prognames("MX")) {
1388       ($prog, $type) = split ",", $p;
1389       $objstr = &objects($p, "X.o", undef, undef);
1390       $icon = &special($p, ".icns");
1391       $infoplist = &special($p, "info.plist");
1392       print "${prog}.app:\n\tmkdir -p \$\@\n";
1393       print "${prog}.app/Contents: ${prog}.app\n\tmkdir -p \$\@\n";
1394       print "${prog}.app/Contents/MacOS: ${prog}.app/Contents\n\tmkdir -p \$\@\n";
1395       $targets = "${prog}.app/Contents/MacOS/$prog";
1396       if (defined $icon) {
1397         print "${prog}.app/Contents/Resources: ${prog}.app/Contents\n\tmkdir -p \$\@\n";
1398         print "${prog}.app/Contents/Resources/${prog}.icns: ${prog}.app/Contents/Resources $icon\n\tcp $icon \$\@\n";
1399         $targets .= " ${prog}.app/Contents/Resources/${prog}.icns";
1400       }
1401       if (defined $infoplist) {
1402         print "${prog}.app/Contents/Info.plist: ${prog}.app/Contents/Resources $infoplist\n\tcp $infoplist \$\@\n";
1403         $targets .= " ${prog}.app/Contents/Info.plist";
1404       }
1405       $targets .= " \$(${prog}_extra)";
1406       print &splitline("${prog}: $targets", 69) . "\n\n";
1407       print &splitline("${prog}.app/Contents/MacOS/$prog: ".
1408                        "${prog}.app/Contents/MacOS " . $objstr), "\n";
1409       $libstr = &objects($p, undef, undef, "-lX");
1410       print &splitline("\t\$(CC) \$(MLDFLAGS) -o \$@ " .
1411                        $objstr . " $libstr", 69), "\n\n";
1412     }
1413     foreach $p (&prognames("U")) {
1414       ($prog, $type) = split ",", $p;
1415       $objstr = &objects($p, "X.o", undef, undef);
1416       print &splitline($prog . ": " . $objstr), "\n";
1417       $libstr = &objects($p, undef, undef, "-lX");
1418       print &splitline("\t\$(CC) \$(ULDFLAGS) -o \$@ " .
1419                        $objstr . " $libstr", 69), "\n\n";
1420     }
1421     foreach $d (&deps("X.o", undef, $dirpfx, "/", "osx")) {
1422       if ($forceobj{$d->{obj_orig}}) {
1423          printf("%s: FORCE\n", $d->{obj});
1424       } else {
1425          print &splitline(sprintf("%s: %s", $d->{obj},
1426                                   join " ", @{$d->{deps}})), "\n";
1427       }
1428       $firstdep = $d->{deps}->[0];
1429       if ($firstdep =~ /\.c$/) {
1430           print "\t\$(CC) \$(COMPAT) \$(FWHACK) \$(CFLAGS) \$(XFLAGS) -c \$<\n";
1431       } elsif ($firstdep =~ /\.m$/) {
1432           print "\t\$(CC) -x objective-c \$(COMPAT) \$(FWHACK) \$(CFLAGS) \$(XFLAGS) -c \$<\n";
1433       }
1434     }
1435     print "\n".&def($makefile_extra{'osx'}->{'end'});
1436     print "\nclean:\n".
1437     "\trm -f *.o *.dmg". (join "", map { " $_" } &progrealnames("U")) . "\n".
1438     "\trm -rf *.app\n".
1439     "\n".
1440     "FORCE:\n";
1441     select STDOUT; close OUT;
1442 }
1443
1444 if (defined $makefiles{'devcppproj'}) {
1445     $dirpfx = &dirpfx($makefiles{'devcppproj'}, "\\");
1446     $orig_dir = cwd;
1447
1448     ##-- Dev-C++ 5 projects
1449     #
1450     # Note: All files created in this section are written in binary
1451     # mode to prevent any posibility of misinterpreted line endings.
1452     # I don't know if Dev-C++ is as touchy as MSVC with LF-only line
1453     # endings. But however, CRLF line endings are the common way on
1454     # Win32 machines where Dev-C++ is running.
1455     # Hence, in order for mkfiles.pl to generate CRLF project files
1456     # even when run from Unix, I make sure all files are binary and
1457     # explicitly write the CRLFs.
1458     #
1459     # Create directories if necessary
1460     mkdir $makefiles{'devcppproj'}
1461         if(! -d $makefiles{'devcppproj'});
1462     chdir $makefiles{'devcppproj'};
1463     @deps = &deps("X.obj", "X.res", $dirpfx, "\\", "devcppproj");
1464     %all_object_deps = map {$_->{obj} => $_->{deps}} @deps;
1465     # Make dir names FAT/NTFS compatible
1466     my @srcdirs = @srcdirs;
1467     for ($i=0; $i<@srcdirs; $i++) {
1468       $srcdirs[$i] =~ s/\//\\/g;
1469       $srcdirs[$i] =~ s/\\$//;
1470     }
1471     # Create the project files
1472     # Get names of all Windows projects (GUI and console)
1473     my @prognames = &prognames("G:C");
1474     foreach $progname (@prognames) {
1475       create_devcpp_project(\%all_object_deps, $progname);
1476     }
1477
1478     sub create_devcpp_project {
1479       my ($all_object_deps, $progname) = @_;
1480       # Construct program's dependency info (Taken from 'vcproj', seems to work right here, too.)
1481       %seen_objects = ();
1482       %lib_files = ();
1483       %source_files = ();
1484       %header_files = ();
1485       %resource_files = ();
1486       @object_files = split " ", &objects($progname, "X.obj", "X.res", "X.lib");
1487       foreach $object_file (@object_files) {
1488       next if defined $seen_objects{$object_file};
1489       $seen_objects{$object_file} = 1;
1490       if($object_file =~ /\.lib$/io) {
1491     $lib_files{$object_file} = 1;
1492     next;
1493       }
1494       $object_deps = $all_object_deps{$object_file};
1495       foreach $object_dep (@$object_deps) {
1496     if($object_dep =~ /\.c$/io) {
1497         $source_files{$object_dep} = 1;
1498         next;
1499     }
1500     if($object_dep =~ /\.h$/io) {
1501         $header_files{$object_dep} = 1;
1502         next;
1503     }
1504     if($object_dep =~ /\.(rc|ico)$/io) {
1505         $resource_files{$object_dep} = 1;
1506         next;
1507     }
1508       }
1509       }
1510       $libs = join " ", sort keys %lib_files;
1511       @source_files = sort keys %source_files;
1512       @header_files = sort keys %header_files;
1513       @resources = sort keys %resource_files;
1514   ($windows_project, $type) = split ",", $progname;
1515       mkdir $windows_project
1516       if(! -d $windows_project);
1517       chdir $windows_project;
1518
1519   $subsys = ($type eq "G") ? "0" : "1";  # 0 = Win32 GUI, 1 = Win32 Console
1520       open OUT, ">$windows_project.dev"; binmode OUT; select OUT;
1521       print
1522       "# DEV-C++ 5 Project File - $windows_project.dev\r\n".
1523       "# ** DO NOT EDIT **\r\n".
1524       "\r\n".
1525       # No difference between DEBUG and RELEASE here as in 'vcproj', because
1526       # Dev-C++ does not support mutiple compilation profiles in one single project.
1527       # (At least I can say this for Dev-C++ 5 Beta)
1528       "[Project]\r\n".
1529       "FileName=$windows_project.dev\r\n".
1530       "Name=$windows_project\r\n".
1531       "Ver=1\r\n".
1532       "IsCpp=1\r\n".
1533       "Type=$subsys\r\n".
1534       # Multimon is disabled here, as Dev-C++ (Version 5 Beta) does not have multimon.h
1535       "Compiler=-W -D__GNUWIN32__ -DWIN32 -DNDEBUG -D_WINDOWS -DNO_MULTIMON -D_MBCS_\@\@_\r\n".
1536       "CppCompiler=-W -D__GNUWIN32__ -DWIN32 -DNDEBUG -D_WINDOWS -DNO_MULTIMON -D_MBCS_\@\@_\r\n".
1537       "Includes=" . (join ";", map {"..\\..\\$dirpfx$_"} @srcdirs) . "\r\n".
1538       "Linker=-ladvapi32 -lcomctl32 -lcomdlg32 -lgdi32 -limm32 -lshell32 -luser32 -lwinmm -lwinspool_\@\@_\r\n".
1539       "Libs=\r\n".
1540       "UnitCount=" . (@source_files + @header_files + @resources) . "\r\n".
1541       "Folders=\"Header Files\",\"Resource Files\",\"Source Files\"\r\n".
1542       "ObjFiles=\r\n".
1543       "PrivateResource=${windows_project}_private.rc\r\n".
1544       "ResourceIncludes=..\\..\\..\\WINDOWS\r\n".
1545       "MakeIncludes=\r\n".
1546       "Icon=\r\n". # It's ok to leave this blank.
1547       "ExeOutput=\r\n".
1548       "ObjectOutput=\r\n".
1549       "OverrideOutput=0\r\n".
1550       "OverrideOutputName=$windows_project.exe\r\n".
1551       "HostApplication=\r\n".
1552       "CommandLine=\r\n".
1553       "UseCustomMakefile=0\r\n".
1554       "CustomMakefile=\r\n".
1555       "IncludeVersionInfo=0\r\n".
1556       "SupportXPThemes=0\r\n".
1557       "CompilerSet=0\r\n".
1558       "CompilerSettings=0000000000000000000000\r\n".
1559       "\r\n";
1560       $unit_count = 1;
1561       foreach $source_file (@source_files) {
1562       print
1563         "[Unit$unit_count]\r\n".
1564         "FileName=..\\..\\$source_file\r\n".
1565         "Folder=Source Files\r\n".
1566         "Compile=1\r\n".
1567         "CompileCpp=0\r\n".
1568         "Link=1\r\n".
1569         "Priority=1000\r\n".
1570         "OverrideBuildCmd=0\r\n".
1571         "BuildCmd=\r\n".
1572         "\r\n";
1573       $unit_count++;
1574   }
1575       foreach $header_file (@header_files) {
1576       print
1577         "[Unit$unit_count]\r\n".
1578         "FileName=..\\..\\$header_file\r\n".
1579         "Folder=Header Files\r\n".
1580         "Compile=1\r\n".
1581         "CompileCpp=1\r\n". # Dev-C++ want's to compile all header files with both compilers C and C++. It does not hurt.
1582         "Link=1\r\n".
1583         "Priority=1000\r\n".
1584         "OverrideBuildCmd=0\r\n".
1585         "BuildCmd=\r\n".
1586         "\r\n";
1587       $unit_count++;
1588   }
1589       foreach $resource_file (@resources) {
1590       if ($resource_file =~ /.*\.(ico|cur|bmp|dlg|rc2|rct|bin|rgs|gif|jpg|jpeg|jpe)/io) { # Default filter as in 'vcproj'
1591         $Compile = "0";    # Don't compile images and other binary resource files
1592         $CompileCpp = "0";
1593       } else {
1594         $Compile = "1";
1595         $CompileCpp = "1"; # Dev-C++ want's to compile all .rc files with both compilers C and C++. It does not hurt.
1596       }
1597       print
1598         "[Unit$unit_count]\r\n".
1599         "FileName=..\\..\\$resource_file\r\n".
1600         "Folder=Resource Files\r\n".
1601         "Compile=$Compile\r\n".
1602         "CompileCpp=$CompileCpp\r\n".
1603         "Link=0\r\n".
1604         "Priority=1000\r\n".
1605         "OverrideBuildCmd=0\r\n".
1606         "BuildCmd=\r\n".
1607         "\r\n";
1608       $unit_count++;
1609   }
1610       #Note: By default, [VersionInfo] is not used.
1611       print
1612       "[VersionInfo]\r\n".
1613       "Major=0\r\n".
1614       "Minor=0\r\n".
1615       "Release=1\r\n".
1616       "Build=1\r\n".
1617       "LanguageID=1033\r\n".
1618       "CharsetID=1252\r\n".
1619       "CompanyName=\r\n".
1620       "FileVersion=0.1\r\n".
1621       "FileDescription=\r\n".
1622       "InternalName=\r\n".
1623       "LegalCopyright=\r\n".
1624       "LegalTrademarks=\r\n".
1625       "OriginalFilename=$windows_project.exe\r\n".
1626       "ProductName=$windows_project\r\n".
1627       "ProductVersion=0.1\r\n".
1628       "AutoIncBuildNr=0\r\n";
1629       select STDOUT; close OUT;
1630       chdir "..";
1631     }
1632 }