1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

Completely revamped mkfiles.pl which incorporates dependency

analysis (for both .c and .rc files). Generates the VC++ makefile as
well as the other two; the authoritative source is now the new file
`Recipe' rather than any particular Makefile. Note that `Makefile'
is still here as a relic of the old way until we stop the nightly
builds using it, but it'll be gone soon.

[originally from svn r1592]
This commit is contained in:
Simon Tatham 2002-03-16 15:49:28 +00:00
parent 6bc827158f
commit a011a5edba
3 changed files with 484 additions and 104 deletions

41
README
View File

@ -1,16 +1,28 @@
This is the README for PuTTY, a free Win32 Telnet and SSH client.
The provided Makefile is for MS Visual C++ systems. Type `nmake' to
build both putty.exe (the main program) and pscp.exe (an SCP
client). The comment at the top of the Makefile gives extra build
options you can use to build in limited Win32s compatibility, a hack
to pass SSH through some types of firewall, and `official' version
numbers.
If you want to rebuild PuTTY from source, we provide three
Makefiles:
MS Visual Studio version 6 falls over on the nasty macros in ssh.c.
This is a bug in Visual Studio. The culprit is the /ZI compiler
option (debug info generation: Edit and Continue). To avoid this
problem while compiling PuTTY under VS6, you should:
- Makefile.vc is for MS Visual C++ systems. Type `nmake -f
Makefile.vc' to build all the PuTTY binaries.
- Makefile.bor is for the Borland C compiler. Type `make -f
Makefile.bor' to build all the PuTTY binaries.
- Makefile.cyg is for Cygwin / mingw32 installations. Type `make -f
Makefile.cyg' to build all the PuTTY binaries. Note that by
default the Pageant WinNT security features and the multiple
monitor support are excluded from the Cygwin build, since at the
time of writing this Cygwin doesn't include the necessary
headers.
If you have MS Visual Studio version 6 and you want to build a
DevStudio project for GUI editing and debugging, you should be aware
that the default GUI configuration of the compiler falls over on the
nasty macros in ssh.c. This is a bug in Visual Studio. The culprit
is the /ZI compiler option (debug info generation: Edit and
Continue). To avoid this problem while compiling PuTTY under VS6,
you should:
- right-click ssh.c in the FileView
- click Settings
- select the C/C++ tab and the General category
@ -19,11 +31,10 @@ problem while compiling PuTTY under VS6, you should:
Alternatively disable the /ZI option, replacing it with a saner
value, such as /Zi.
For other compilers, some alternative Makefiles are provided. These
Makefiles are generated automatically from the master `Makefile' by
the Perl script `mkfiles.pl'. Additions and corrections to the
script are more useful than additions and corrections to the
alternative Makefiles themselves.
All of the Makefiles are generated automatically from the file
`Recipe' by the Perl script `mkfiles.pl'. Additions and corrections
to Recipe and the mkfiles.pl are much more useful than additions and
corrections to the alternative Makefiles themselves.
The PuTTY home web site is

131
Recipe Normal file
View File

@ -0,0 +1,131 @@
# -*- makefile -*-
#
# This file describes which PuTTY programs are made up from which
# object and resource files. It is processed into the various
# Makefiles by means of a Perl script. Makefile changes should
# really be made by editing this file and/or the Perl script, not
# by editing the actual Makefiles.
# Help text added to the top of each Makefile, with /D converted
# into -D as appropriate for the particular Makefile.
!begin help
#
# Extra options you can set:
#
# - FWHACK=/DFWHACK
# Enables a hack that tunnels through some firewall proxies.
#
# - VER=/DSNAPSHOT=1999-01-25
# Generates executables whose About box report them as being a
# development snapshot.
#
# - VER=/DRELEASE=0.43
# Generates executables whose About box report them as being a
# release version.
#
# - COMPAT=/DAUTO_WINSOCK
# Causes PuTTY to assume that <windows.h> includes its own WinSock
# header file, so that it won't try to include <winsock.h>.
#
# - COMPAT=/DWINSOCK_TWO
# Causes the PuTTY utilities to include <winsock2.h> instead of
# <winsock.h>, except Plink which _needs_ WinSock 2 so it already
# does this.
#
# - COMPAT=/DNO_SECURITY
# Disables Pageant's use of <aclapi.h>, which is not available
# with some development environments. This means that Pageant
# won't care about the local user ID of processes accessing it; a
# version of Pageant built with this option will therefore refuse
# to run under NT-series OSes on security grounds (although it
# will run fine on Win95-series OSes where there is no access
# control anyway).
#
# Note that this definition is always enabled in the Cygwin
# build, since at the time of writing this <aclapi.h> is known
# not to be available in Cygwin.
#
# - COMPAT=/DNO_MULTIMON
# Disables PuTTY's use of <multimon.h>, which is not available
# with some development environments. This means that PuTTY's
# full-screen mode (configurable to work on Alt-Enter) will
# not behave usefully in a multi-monitor environment.
#
# Note that this definition is always enabled in the Cygwin
# build, since at the time of writing this <multimon.h> is
# known not to be available in Cygwin.
#
# - COMPAT=/DMSVC4
# - RCFL=/DMSVC4
# Makes a couple of minor changes so that PuTTY compiles using
# MSVC 4. You will also need /DNO_SECURITY and /DNO_MULTIMON.
#
# - RCFL=/DASCIICTLS
# Uses ASCII rather than Unicode to specify the tab control in
# the resource file. Probably most useful when compiling with
# Cygnus/mingw32, whose resource compiler may have less of a
# problem with it.
#
# - XFLAGS=/DDEBUG
# Causes PuTTY to enable internal debugging.
#
# - XFLAGS=/DMALLOC_LOG
# Causes PuTTY to emit a file called putty_mem.log, logging every
# memory allocation and free, so you can track memory leaks.
#
# - XFLAGS=/DMINEFIELD
# Causes PuTTY to use a custom memory allocator, similar in
# concept to Electric Fence, in place of regular malloc(). Wastes
# huge amounts of RAM, but should cause heap-corruption bugs to
# show up as GPFs at the point of failure rather than appearing
# later on as second-level damage.
#
!end
# Definitions of object groups. A group name, followed by an =,
# followed by any number of objects or other already-defined group
# names. A line beginning `+' is assumed to continue the previous
# line.
# GUI front end and terminal emulator (putty, puttytel).
GUITERM = window windlg winctrls terminal sizetip wcwidth unicode
+ logging printing
# Non-SSH back ends (putty, puttytel, plink).
NONSSH = telnet raw rlogin ldisc
# SSH back end (putty, plink, pscp, psftp).
SSH = ssh sshcrc sshdes sshmd5 sshrsa sshrand sshsha sshblowf noise
+ sshdh sshcrcda sshpubk pageantc sshzlib sshdss x11fwd portfwd
+ sshaes sshsh512 sshbn
# SFTP implementation (pscp, psftp).
SFTP = sftp int64 logging
# Miscellaneous objects appearing in all the network utilities (not
# Pageant or PuTTYgen).
MISC = misc version winstore settings tree234 winnet
# Standard libraries, and the same with WinSocks 1 and 2.
LIBS = advapi32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib
+ shell32.lib winmm.lib imm32.lib winspool.lib
LIBS1 = LIBS wsock32.lib
LIBS2 = LIBS ws2_32.lib
# Definitions of actual programs. The program name, followed by a
# colon, followed by a list of objects. Also in the list may be the
# keywords [G] for GUI or [C] for Console application.
putty : [G] GUITERM NONSSH SSH be_all MISC win_res.res LIBS1
puttytel : [G] GUITERM NONSSH be_nossh MISC win_res.res LIBS1
plink : [C] plink console NONSSH SSH be_all logging MISC plink.res LIBS2
pscp : [C] scp console SSH be_none SFTP wildcard MISC scp.res LIBS1
psftp : [C] psftp console SSH be_none SFTP MISC scp.res LIBS1
pageant : [G] pageant sshrsa sshpubk sshdes sshbn sshmd5 version tree234
+ misc sshaes sshsha pageantc sshdss sshsh512 pageant.res LIBS
puttygen : [G] puttygen sshrsag sshdssg sshprime sshdes sshbn sshmd5 version
+ sshrand noise sshsha winstore misc winctrls sshrsa sshdss
+ sshpubk sshaes sshsh512 puttygen.res LIBS

View File

@ -1,70 +1,220 @@
#!/usr/bin/env perl
#
# Makefile generator.
# Produces the other PuTTY makefiles from the master one.
# Makefile generator for PuTTY.
#
# Reads the file `Recipe' to determine the list of generated
# executables and their component objects. Then reads the source
# files to compute #include dependencies. Finally, writes out the
# various target Makefiles.
open IN, "Recipe" or die "unable to open Recipe file\n";
$help = ""; # list of newline-free lines of help text
%programs = (); # maps program name to listref of objects/resources
%types = (); # maps program name to "G" or "C"
%groups = (); # maps group name to listref of objects/resources
open IN,"Makefile";
@current = ();
while (<IN>) {
# Skip comments (unless the comments belong, for example because
# they're part of the help text).
next if /^\s*#/ and !$in_help;
chomp;
if (/^##--/) {
@words = split /\s+/,$_;
shift @words; # remove ##--
$i = shift @words; # first word
if (!defined $i) { # no words
@current = ();
} elsif (!defined $words[0]) { # only one word
@current = ($i);
} else { # at least two words
@current = map { $i . "." . $_ } @words;
foreach $i (@words) { $projects{$i} = $i; }
push @current, "objdefs";
}
split;
if ($_[0] eq "!begin" and $_[1] eq "help") { $in_help = 1; next; }
if ($_[0] eq "!end" and $in_help) { $in_help = 0; next; }
# If we're gathering help text, keep doing so.
if ($in_help) { $help .= "$_\n"; next; }
# Ignore blank lines.
next if scalar @_ == 0;
# Now we have an ordinary line. See if it's an = line, a : line
# or a + line.
@objs = @_;
if ($_[0] eq "+") {
$listref = $lastlistref;
$prog = undef;
die "$.: unexpected + line\n" if !defined $lastlistref;
} elsif ($_[1] eq "=") {
$groups{$_[0]} = [] if !defined $groups{$_[0]};
$listref = $groups{$_[0]};
$prog = undef;
shift @objs; # eat the group name
} elsif ($_[1] eq ":") {
$programs{$_[0]} = [] if !defined $programs{$_[0]};
$listref = $programs{$_[0]};
$prog = $_[0];
shift @objs; # eat the program name
} else {
foreach $i (@current) { $store{$i} .= $_ . "\n"; }
die "$.: unrecognised line type\n";
}
shift @objs; # eat the +, the = or the :
while (scalar @objs > 0) {
$i = shift @objs;
if ($groups{$i}) {
foreach $j (@{$groups{$i}}) { unshift @objs, $j; }
} elsif (($i eq "[G]" or $i eq "[C]") and defined $prog) {
$types{$prog} = substr($i,1,1);
} else {
push @$listref, $i;
}
}
$lastlistref = $listref;
}
close IN;
# Now retrieve the complete list of objects and resource files, and
# construct dependency data for them. While we're here, expand the
# object list for each program, and complain if its type isn't set.
@prognames = sort keys %programs;
%depends = ();
@scanlist = ();
foreach $i (@prognames) {
if (!defined $types{$i}) { die "type not set for program $i\n"; }
# Strip duplicate object names.
$prev = undef;
@list = grep { $status = ($prev ne $_); $prev=$_; $status }
sort @{$programs{$i}};
$programs{$i} = [@list];
foreach $j (@list) {
# Dependencies for "x" start with "x.c".
# Dependencies for "x.res" start with "x.rc".
# Both types of file are pushed on the list of files to scan.
# Libraries (.lib) don't have dependencies at all.
if ($j =~ /^(.*)\.res$/) {
$file = "$1.rc";
$depends{$j} = [$file];
push @scanlist, $file;
} elsif ($j =~ /\.lib$/) {
# libraries don't have dependencies
} else {
$file = "$j.c";
$depends{$j} = [$file];
push @scanlist, $file;
}
}
}
close IN;
@projects = keys %projects;
foreach $i (split '\n',$store{'gui-apps'}) {
$i =~ s/^# //;
$speciallibs = [split ' ', $i];
$i = shift @$speciallibs; # take off project name
$gui{$i} = 1;
$libs{$i} = $speciallibs;
# Scan each file on @scanlist and find further inclusions.
# Inclusions are given by lines of the form `#include "otherfile"'
# (system headers are automatically ignored by this because they'll
# be given in angle brackets). Files included by this method are
# added back on to @scanlist to be scanned in turn (if not already
# done).
#
# Resource scripts (.rc) can also include a file by means of a line
# ending `ICON "filename"'. Files included by this method are not
# added to @scanlist because they can never include further files.
#
# In this pass we write out a hash %further which maps a source
# file name into a listref containing further source file names.
%further = ();
while (scalar @scanlist > 0) {
$file = shift @scanlist;
next if defined $further{$file}; # skip if we've already done it
$resource = ($file =~ /\.rc$/ ? 1 : 0);
$further{$file} = [];
open IN, $file or die "unable to open source file $file\n";
while (<IN>) {
chomp;
/^\s*#include\s+\"([^\"]+)\"/ and do {
push @{$further{$file}}, $1;
push @scanlist, $1;
next;
};
/ICON\s+\"([^\"]+)\"\s*$/ and do {
push @{$further{$file}}, $1;
next;
}
}
close IN;
}
foreach $i (split '\n',$store{'console-apps'}) {
$i =~ s/^# //;
$speciallibs = [split ' ', $i];
$i = shift @$speciallibs; # take off project name
$gui{$i} = 0;
$libs{$i} = $speciallibs;
# Now we're ready to generate the final dependencies section. For
# each key in %depends, we must expand the dependencies list by
# iteratively adding entries from %further.
foreach $i (keys %depends) {
%dep = ();
@scanlist = @{$depends{$i}};
foreach $i (@scanlist) { $dep{$i} = 1; }
while (scalar @scanlist > 0) {
$file = shift @scanlist;
foreach $j (@{$further{$file}}) {
if ($dep{$j} != 1) {
$dep{$j} = 1;
push @{$depends{$i}}, $j;
push @scanlist, $j;
}
}
}
# printf "%s: %s\n", $i, join ' ',@{$depends{$i}};
}
sub project {
my ($p) = @_;
my ($q) = $store{"$p"} . $store{"objects.$p"} . $store{"resources.$p"};
$q =~ s/(\S+)\s[^\n]*\n/\$($1) /gs;
$q =~ s/ $//;
$q;
# Utility routines while writing out the Makefiles.
sub objects {
my ($prog, $otmpl, $rtmpl, $ltmpl) = @_;
my @ret;
my ($i, $x, $y);
@ret = ();
foreach $i (@{$programs{$prog}}) {
if ($i =~ /^(.*)\.res/) {
$y = $1;
($x = $rtmpl) =~ s/X/$y/;
push @ret, $x if $x ne "";
} elsif ($i =~ /^(.*)\.lib/) {
$y = $1;
($x = $ltmpl) =~ s/X/$y/;
push @ret, $x if $x ne "";
} else {
($x = $otmpl) =~ s/X/$i/;
push @ret, $x if $x ne "";
}
}
return join " ", @ret;
}
sub projlist {
my ($p) = @_;
my ($q) = $store{"$p"} . $store{"objects.$p"} . $store{"resources.$p"};
$q =~ s/(\S+)\s[^\n]*\n/$1 /gs;
my (@q) = split ' ',$q;
@q;
sub splitline {
my ($line, $width) = @_;
my ($result, $len);
$len = (defined $width ? $width : 76);
while (length $line > $len) {
$line =~ /^(.{0,$len})\s(.*)$/ or $line =~ /^(.{$len,}?\s(.*)$/;
$result .= $1 . " \\\n\t\t";
$line = $2;
$len = 60;
}
return $result . $line;
}
sub deps {
my ($otmpl, $rtmpl) = @_;
my ($i, $x, $y);
foreach $i (sort keys %depends) {
if ($i =~ /^(.*)\.res/) {
$y = $1;
($x = $rtmpl) =~ s/X/$y/;
} else {
($x = $otmpl) =~ s/X/$i/;
}
print &splitline(sprintf "%s: %s", $x, join " ", @{$depends{$i}}), "\n";
}
}
# Now we're ready to output the actual Makefiles.
##-- CygWin makefile
open OUT, ">Makefile.cyg"; select OUT;
print
"# Makefile for PuTTY under cygwin.\n";
"# Makefile for PuTTY under cygwin.\n".
"#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n".
"# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n";
# gcc command line option is -D not /D
($_ = $store{"help"}) =~ s/=\/D/=-D/gs;
($_ = $help) =~ s/=\/D/=-D/gs;
print $_;
print
"\n".
@ -76,16 +226,11 @@ print
"# You may also need to tell windres where to find include files:\n".
"# RCINC = --include-dir c:\\cygwin\\include\\\n".
"\n".
"CFLAGS = -mno-cygwin -Wall -O2 -D_WINDOWS -DDEBUG -DWIN32S_COMPAT".
" -DNO_SECURITY -D_NO_OLDNAMES -I.\n".
&splitline("CFLAGS = -mno-cygwin -Wall -O2 -D_WINDOWS -DDEBUG -DWIN32S_COMPAT".
" -DNO_SECURITY -D_NO_OLDNAMES -DNO_MULTIMON -I.")."\n".
"LDFLAGS = -mno-cygwin -s\n".
"RCFLAGS = \$(RCINC) --define WIN32=1 --define _WIN32=1 --define WINVER=0x0400 --define MINGW32_FIX=1\n".
"LIBS = -ladvapi32 -luser32 -lgdi32 -lwsock32 -lcomctl32 -lcomdlg32 -lwinmm -limm32 -lwinspool\n".
"OBJ=o\n".
"RES=res.o\n".
"\n";
print $store{"objdefs"};
print
&splitline("RCFLAGS = \$(RCINC) --define WIN32=1 --define _WIN32=1".
" --define WINVER=0x0400 --define MINGW32_FIX=1")."\n".
"\n".
".SUFFIXES:\n".
"\n".
@ -95,34 +240,48 @@ print
"%.res.o: %.rc\n".
"\t\$(RC) \$(FWHACK) \$(RCFL) \$(RCFLAGS) \$< \$\@\n".
"\n";
print "all:";
print map { " $_.exe" } @projects;
print &splitline("all:" . join "", map { " $_.exe" } @prognames);
print "\n\n";
foreach $p (@projects) {
print $p, ".exe: ", &project($p), "\n";
my $mw = $gui{$p} ? " -mwindows" : "";
$libstr = "";
foreach $lib (@{$libs{$p}}) { $libstr .= " -l$lib"; }
print "\t\$(CC)" . $mw . " \$(LDFLAGS) -o \$@ " . &project($p), " \$(LIBS)$libstr\n\n";
foreach $p (@prognames) {
$objstr = &objects($p, "X.o", "X.res.o", undef);
print &splitline($p . ".exe: " . $objstr), "\n";
my $mw = $types{$p} eq "G" ? " -mwindows" : "";
$libstr = &objects($p, undef, undef, "-lX");
print &splitline("\t\$(CC)" . $mw . " \$(LDFLAGS) -o \$@ " .
$objstr . " $libstr", 69), "\n\n";
}
print $store{"dependencies"};
&deps("X.o", "X.res.o");
print
"\n".
"version.o: FORCE;\n".
"# Hack to force version.o to be rebuilt always\n".
"FORCE:\n".
"\t\$(CC) \$(FWHACK) \$(CFLAGS) \$(VER) -c version.c\n\n".
"\t\$(CC) \$(COMPAT) \$(FWHACK) \$(XFLAGS) \$(CFLAGS) \$(VER) -c version.c\n".
"clean:\n".
"\trm -f *.o *.exe *.res\n".
"\trm -f *.o *.exe *.res.o\n".
"\n";
select STDOUT; close OUT;
##-- Borland makefile
%stdlibs = ( # Borland provides many Win32 API libraries intrinsically
"advapi32" => 1,
"comctl32" => 1,
"comdlg32" => 1,
"gdi32" => 1,
"imm32" => 1,
"shell32" => 1,
"user32" => 1,
"winmm" => 1,
"winspool" => 1,
"wsock32" => 1,
);
open OUT, ">Makefile.bor"; select OUT;
print
"# Makefile for PuTTY under Borland C++.\n";
"# Makefile for PuTTY under Borland C.\n".
"#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n".
"# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n";
# bcc32 command line option is -D not /D
($_ = $store{"help"}) =~ s/=\/D/=-D/gs;
($_ = $help) =~ s/=\/D/=-D/gs;
print $_;
print
"\n".
@ -139,42 +298,48 @@ print
"!endif\n".
"\n".
".c.obj:\n".
"\tbcc32 -w-aus -w-ccc -w-par \$(COMPAT) \$(FWHACK) \$(XFLAGS) \$(CFLAGS) /c \$*.c\n".
&splitline("\tbcc32 -w-aus -w-ccc -w-par \$(COMPAT) \$(FWHACK)".
" \$(XFLAGS) \$(CFLAGS) /c \$*.c",69)."\n".
".rc.res:\n".
"\tbrcc32 \$(FWHACK) \$(RCFL) -i \$(BCB)\\include \\\n".
"\t\t-r -DNO_WINRESRC_H -DWIN32 -D_WIN32 -DWINVER=0x0401 \$*.rc\n".
"\n".
"OBJ=obj\n".
"RES=res\n".
&splitline("\tbrcc32 \$(FWHACK) \$(RCFL) -i \$(BCB)\\include -r".
" -DNO_WINRESRC_H -DWIN32 -D_WIN32 -DWINVER=0x0401 \$*.rc",69)."\n".
"\n";
print $store{"objdefs"};
print "\n";
print "all:";
print map { " $_.exe" } @projects;
print &splitline("all:" . join "", map { " $_.exe" } @prognames);
print "\n\n";
foreach $p (@projects) {
print $p, ".exe: ", &project($p), " $p.rsp\n";
$ap = $gui{$p} ? " -aa" : " -ap";
print "\tilink32$ap -Gn -L\$(BCB)\\lib \@$p.rsp\n\n";
foreach $p (@prognames) {
$objstr = &objects($p, "X.obj", "X.res", undef);
print &splitline("$p.exe: " . $objstr . " $p.rsp"), "\n";
my $ap = ($types{$p} eq "G") ? "-aa" : "-ap";
print "\tilink32 $ap -Gn -L\$(BCB)\\lib \@$p.rsp\n\n";
}
foreach $p (@projects) {
foreach $p (@prognames) {
print $p, ".rsp: \$(MAKEFILE)\n";
$c0w = $gui{$p} ? "c0w32" : "c0x32";
$objstr = &objects($p, "X.obj", undef, undef);
@objlist = split " ", $objstr;
@objlines = ("");
foreach $i (@objlist) {
if (length($objlines[$#objlines] . " $i") > 50) {
push @objlines, "";
}
$objlines[$#objlines] .= " $i";
}
$c0w = ($types{$p} eq "G") ? "c0w32" : "c0x32";
print "\techo $c0w + > $p.rsp\n";
@objlines = &projlist("objects.$p");
for ($i=0; $i<=$#objlines; $i++) {
$plus = ($i < $#objlines ? " +" : "");
print "\techo \$($objlines[$i])$plus >> $p.rsp\n";
print "\techo$objlines[$i]$plus >> $p.rsp\n";
}
print "\techo $p.exe >> $p.rsp\n";
@libs = @{$libs{$p}};
$objstr = &objects($p, "X.obj", "X.res", undef);
@libs = split " ", &objects($p, undef, undef, "X");
@libs = grep { !$stdlibs{$_} } @libs;
unshift @libs, "cw32", "import32";
$libstr = join ' ', @libs;
print "\techo nul,$libstr, >> $p.rsp\n";
print "\techo " . (join " ", &project("resources.$p")) . " >> $p.rsp\n";
print "\techo " . &objects($p, undef, "X.res", undef) . " >> $p.rsp\n";
print "\n";
}
print $store{"dependencies"};
&deps("X.obj", "X.res");
print
"\n".
"version.o: FORCE\n".
@ -193,3 +358,76 @@ print
"\t-del *.tds\n".
"\t-del *.\$\$\$\$\$\$\n";
select STDOUT; close OUT;
##-- Visual C++ makefile
open OUT, ">Makefile.vc"; select OUT;
print
"# Makefile for PuTTY under Visual C.\n".
"#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n".
"# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n";
print $help;
print
"\n".
"# If you rename this file to `Makefile', you should change this line,\n".
"# so that the .rsp files still depend on the correct makefile.\n".
"MAKEFILE = Makefile.vc\n".
"\n".
"# C compilation flags\n".
"CFLAGS = /nologo /W3 /O1 /D_WINDOWS /D_WIN32_WINDOWS=0x401 /DWINVER=0x401\n".
"LFLAGS = /incremental:no /fixed\n".
"\n".
".c.obj:\n".
"\tcl \$(COMPAT) \$(FWHACK) \$(XFLAGS) \$(CFLAGS) /c \$*.c\n".
".rc.res:\n".
"\trc \$(FWHACK) \$(RCFL) -r -DWIN32 -D_WIN32 -DWINVER=0x0400 \$*.rc\n".
"\n";
print &splitline("all:" . join "", map { " $_.exe" } @prognames);
print "\n\n";
foreach $p (@prognames) {
$objstr = &objects($p, "X.obj", "X.res", undef);
print &splitline("$p.exe: " . $objstr . " $p.rsp"), "\n";
print "\tlink \$(LFLAGS) -out:$p.exe -map:$p.map \@$p.rsp\n\n";
}
foreach $p (@prognames) {
print $p, ".rsp: \$(MAKEFILE)\n";
$objstr = &objects($p, "X.obj", "X.res", "X.lib");
@objlist = split " ", $objstr;
@objlines = ("");
foreach $i (@objlist) {
if (length($objlines[$#objlines] . " $i") > 50) {
push @objlines, "";
}
$objlines[$#objlines] .= " $i";
}
$subsys = ($types{$p} eq "G") ? "windows" : "console";
print "\techo /nologo /subsystem:$subsys > $p.rsp\n";
for ($i=0; $i<=$#objlines; $i++) {
print "\techo$objlines[$i] >> $p.rsp\n";
}
print "\n";
}
&deps("X.obj", "X.res");
print
"\n".
"# Hack to force version.o to be rebuilt always\n".
"version.obj: *.c *.h *.rc\n".
"\tcl \$(FWHACK) \$(VER) \$(CFLAGS) /c version.c\n\n".
"clean: tidy\n".
"\t-del *.exe\n\n".
"tidy:\n".
"\t-del *.obj\n".
"\t-del *.res\n".
"\t-del *.pch\n".
"\t-del *.aps\n".
"\t-del *.ilk\n".
"\t-del *.pdb\n".
"\t-del *.rsp\n".
"\t-del *.dsp\n".
"\t-del *.dsw\n".
"\t-del *.ncb\n".
"\t-del *.opt\n".
"\t-del *.plg\n".
"\t-del *.map\n".
"\t-del *.idb\n".
"\t-del debug.log\n";
select STDOUT; close OUT;