putty/mkfiles.pl

1994 строки
75 KiB
Perl
Исходник Обычный вид История

#!/usr/bin/env perl
#
# Cross-platform Makefile generator.
#
# 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.
# PuTTY specifics which could still do with removing:
# - Mac makefile is not portabilised at all. Include directories
# are hardwired, and also the libraries are fixed. This is
# mainly because I was too scared to go anywhere near it.
# - sbcsgen.pl is still run at startup.
#
# FIXME: no attempt made to handle !forceobj in the project files.
use warnings;
use FileHandle;
use File::Basename;
use Cwd;
use Digest::SHA qw(sha512_hex);
if ($#ARGV >= 0 and ($ARGV[0] eq "-u" or $ARGV[0] eq "-U")) {
# Convenience for Unix users: -u means that after we finish what
# we're doing here, we also run mkauto.sh and then 'configure' in
# the Unix subdirectory. So it's a one-stop shop for regenerating
# the actual end-product Unix makefile.
#
# Arguments supplied after -u go to configure.
#
# -U is identical, but runs 'configure' at the _top_ level, for
# people who habitually do that.
$do_unix = ($ARGV[0] eq "-U" ? 2 : 1);
shift @ARGV;
@confargs = @ARGV;
}
open IN, "Recipe" or do {
# We want to deal correctly with being run from one of the
# subdirs in the source tree. So if we can't find Recipe here,
# try one level up.
chdir "..";
open IN, "Recipe" or die "unable to open Recipe file\n";
};
# HACK: One of the source files in `charset' is auto-generated by
# sbcsgen.pl. We need to generate that _now_, before attempting
# dependency analysis.
eval 'chdir "charset"; require "sbcsgen.pl"; chdir ".."; select STDOUT;';
@srcdirs = ("./");
$divert = undef; # ref to scalar in which text is currently being put
$help = ""; # list of newline-free lines of help text
$project_name = "project"; # this is a good enough default
%makefiles = (); # maps makefile types to output makefile pathnames
%makefile_extra = (); # maps makefile types to extra Makefile text
%programs = (); # maps prog name + type letter to listref of objects/resources
%groups = (); # maps group name to listref of objects/resources
while (<IN>) {
chomp;
@_ = split;
# If we're gathering help text, keep doing so.
if (defined $divert) {
if ((defined $_[0]) && $_[0] eq "!end") {
$divert = undef;
} else {
${$divert} .= "$_\n";
}
next;
}
# Skip comments and blank lines.
next if /^\s*#/ or scalar @_ == 0;
if ($_[0] eq "!begin" and $_[1] eq "help") { $divert = \$help; next; }
if ($_[0] eq "!end") { $divert = undef; next; }
if ($_[0] eq "!name") { $project_name = $_[1]; next; }
if ($_[0] eq "!srcdir") { push @srcdirs, $_[1]; next; }
if ($_[0] eq "!makefile" and &mfval($_[1])) { $makefiles{$_[1]}=$_[2]; next;}
if ($_[0] eq "!specialobj" and &mfval($_[1])) { $specialobj{$_[1]}->{$_[2]} = 1; next;}
if ($_[0] eq "!cflags" and &mfval($_[1])) {
($rest = $_) =~ s/^\s*\S+\s+\S+\s+\S+\s*//; # find rest of input line
$rest = 1 if $rest eq "";
$cflags{$_[1]}->{$_[2]} = $rest;
next;
}
if ($_[0] eq "!forceobj") { $forceobj{$_[1]} = 1; next; }
if ($_[0] eq "!begin") {
if ($_[1] =~ /^>(.*)/) {
$divert = \$auxfiles{$1};
} elsif (&mfval($_[1])) {
$sect = $_[2] ? $_[2] : "end";
$divert = \($makefile_extra{$_[1]}->{$sect});
} else {
$dummy = '';
$divert = \$dummy;
}
next;
}
# If we're gathering help/verbatim text, keep doing so.
if (defined $divert) { ${$divert} .= "$_\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 ":") {
$listref = [];
$prog = $_[0];
shift @objs; # eat the program name
} else {
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]" or $i eq "[M]" or
$i eq "[X]" or $i eq "[U]" or $i eq "[MX]") and defined $prog) {
$type = substr($i,1,(length $i)-2);
} else {
push @$listref, $i;
}
}
if ($prog and $type) {
die "multiple program entries for $prog [$type]\n"
if defined $programs{$prog . "," . $type};
$programs{$prog . "," . $type} = $listref;
}
$lastlistref = $listref;
}
close IN;
foreach $aux (sort keys %auxfiles) {
open AUX, ">$aux";
print AUX $auxfiles{$aux};
close AUX;
}
# 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) {
($prog, $type) = split ",", $i;
# Strip duplicate object names.
$prev = '';
@list = grep { $status = ($prev ne $_); $prev=$_; $status }
sort @{$programs{$i}};
$programs{$i} = [@list];
foreach $j (@list) {
# Dependencies for "x" start with "x.c" or "x.m" (depending on
# which one exists).
# Dependencies for "x.res" start with "x.rc".
# Dependencies for "x.rsrc" start with "x.r".
# 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 =~ /^(.*)\.rsrc$/) {
$file = "$1.r";
$depends{$j} = [$file];
push @scanlist, $file;
} elsif ($j !~ /\./) {
$file = "$j.c";
$file = "$j.m" unless &findfile($file);
$depends{$j} = [$file];
push @scanlist, $file;
}
}
}
# 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"';
# - a line ending `RT_MANIFEST "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 = ();
%allsourcefiles = (); # this is wanted by some makefiles
while (scalar @scanlist > 0) {
$file = shift @scanlist;
next if defined $further{$file}; # skip if we've already done it
$further{$file} = [];
$dirfile = &findfile($file);
$allsourcefiles{$dirfile} = 1;
open IN, "$dirfile" 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;
};
/(RT_MANIFEST|ICON)\s+\"([^\"]+)\"\s*$/ and do {
push @{$further{$file}}, $2;
next;
}
}
close IN;
}
# 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}) {
$dep{$j} = 1;
push @{$depends{$i}}, $j;
push @scanlist, $j;
}
}
}
# printf "%s: %s\n", $i, join ' ',@{$depends{$i}};
}
# Validation of input.
sub mfval($) {
my ($type) = @_;
# Returns true if the argument is a known makefile type. Otherwise,
# prints a warning and returns false;
if (grep { $type eq $_ }
("vc","vcproj","cygwin","borland","lcc","devcppproj","gtk","unix",
"am","osx","vstudio10","vstudio12")) {
return 1;
}
warn "$.:unknown makefile type '$type'\n";
return 0;
}
# Utility routines while writing out the Makefiles.
sub def {
my ($x) = shift @_;
return (defined $x) ? $x : "";
}
sub dirpfx {
my ($path) = shift @_;
my ($sep) = shift @_;
my $ret = "";
my $i;
while (($i = index $path, $sep) >= 0 ||
($j = index $path, "/") >= 0) {
if ($i >= 0 and ($j < 0 or $i < $j)) {
$path = substr $path, ($i + length $sep);
} else {
$path = substr $path, ($j + 1);
}
$ret .= "..$sep";
}
return $ret;
}
sub findfile {
my ($name) = @_;
my $dir = '';
my $i;
my $outdir = undef;
unless (defined $findfilecache{$name}) {
$i = 0;
foreach $dir (@srcdirs) {
if (-f "$dir$name") {
$outdir = $dir;
$i++;
$outdir =~ s/^\.\///;
}
}
die "multiple instances of source file $name\n" if $i > 1;
$findfilecache{$name} = (defined $outdir ? $outdir . $name : undef);
}
return $findfilecache{$name};
}
sub objects {
my ($prog, $otmpl, $rtmpl, $ltmpl, $prefix, $dirsep) = @_;
my @ret;
my ($i, $x, $y);
($otmpl, $rtmpl, $ltmpl) = map { defined $_ ? $_ : "" } ($otmpl, $rtmpl, $ltmpl);
@ret = ();
foreach $i (@{$programs{$prog}}) {
$x = "";
if ($i =~ /^(.*)\.(res|rsrc)/) {
$y = $1;
($x = $rtmpl) =~ s/X/$y/;
} elsif ($i =~ /^(.*)\.lib/) {
$y = $1;
($x = $ltmpl) =~ s/X/$y/;
} elsif ($i !~ /\./) {
($x = $otmpl) =~ s/X/$i/;
}
push @ret, $x if $x ne "";
}
return join " ", @ret;
}
sub special {
my ($prog, $suffix) = @_;
my @ret;
my ($i, $x, $y);
($otmpl, $rtmpl, $ltmpl) = map { defined $_ ? $_ : "" } ($otmpl, $rtmpl, $ltmpl);
@ret = ();
foreach $i (@{$programs{$prog}}) {
if (substr($i, (length $i) - (length $suffix)) eq $suffix) {
push @ret, $i;
}
}
return (scalar @ret) ? (join " ", @ret) : undef;
}
sub splitline {
my ($line, $width, $splitchar) = @_;
my $result = "";
my $len;
$len = (defined $width ? $width : 76);
$splitchar = (defined $splitchar ? $splitchar : '\\');
while (length $line > $len) {
$line =~ /^(.{0,$len})\s(.*)$/ or $line =~ /^(.{$len,}?\s(.*)$/;
$result .= $1;
$result .= " ${splitchar}\n\t\t" if $2 ne '';
$line = $2;
$len = 60;
}
return $result . $line;
}
sub deps {
my ($otmpl, $rtmpl, $prefix, $dirsep, $mftyp, $depchar, $splitchar) = @_;
my ($i, $x, $y);
my @deps;
my @ret;
@ret = ();
$depchar ||= ':';
foreach $i (sort keys %depends) {
next if $specialobj{$mftyp}->{$i};
if ($i =~ /^(.*)\.(res|rsrc)/) {
next if !defined $rtmpl;
$y = $1;
($x = $rtmpl) =~ s/X/$y/;
} else {
($x = $otmpl) =~ s/X/$i/;
}
@deps = @{$depends{$i}};
@deps = map {
$_ = &findfile($_);
s/\//$dirsep/g;
$_ = $prefix . $_;
} @deps;
push @ret, {obj => $x, obj_orig => $i, deps => [@deps]};
}
return @ret;
}
sub prognames {
my ($types) = @_;
my ($n, $prog, $type);
my @ret;
@ret = ();
foreach $n (@prognames) {
($prog, $type) = split ",", $n;
push @ret, $n if index(":$types:", ":$type:") >= 0;
}
return @ret;
}
sub progrealnames {
my ($types) = @_;
my ($n, $prog, $type);
my @ret;
@ret = ();
foreach $n (@prognames) {
($prog, $type) = split ",", $n;
push @ret, $prog if index(":$types:", ":$type:") >= 0;
}
return @ret;
}
sub manpages {
my ($types,$suffix) = @_;
# assume that all UNIX programs have a man page
if($suffix eq "1" && $types =~ /:X:/) {
return map("$_.1", &progrealnames($types));
}
return ();
}
$orig_dir = cwd;
# Now we're ready to output the actual Makefiles.
if (defined $makefiles{'cygwin'}) {
$dirpfx = &dirpfx($makefiles{'cygwin'}, "/");
##-- CygWin makefile
open OUT, ">$makefiles{'cygwin'}"; select OUT;
print
"# Makefile for $project_name under Cygwin, MinGW, or Winelib.\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
($_ = $help) =~ s/([=" ])\/D/$1-D/gs;
print $_;
print
"\n".
"# You can define this path to point at your tools if you need to\n".
"# TOOLPATH = c:\\cygwin\\bin\\ # or similar, if you're running Windows\n".
"# TOOLPATH = /pkg/mingw32msvc/i386-mingw32msvc/bin/\n".
"CC = \$(TOOLPATH)gcc\n".
"RC = \$(TOOLPATH)windres\n".
"# Uncomment the following two lines to compile under Winelib\n".
"# CC = winegcc\n".
"# RC = wrc\n".
"# You may also need to tell windres where to find include files:\n".
"# RCINC = --include-dir c:\\cygwin\\include\\\n".
"\n".
&splitline("CFLAGS = -mno-cygwin -Wall -O2 -D_WINDOWS -DDEBUG -DWIN32S_COMPAT".
" -D_NO_OLDNAMES -DNO_MULTIMON -DNO_HTMLHELP -DNO_SECUREZEROMEMORY " .
(join " ", map {"-I$dirpfx$_"} @srcdirs)) .
"\n".
"LDFLAGS = -mno-cygwin -s\n".
&splitline("RCFLAGS = \$(RCINC) --define WIN32=1 --define _WIN32=1 ".
"--define WINVER=0x0400 ".(join " ", map {"-I$dirpfx$_"} @srcdirs))."\n".
"\n".
$makefile_extra{'cygwin'}->{'vars'} .
"\n".
".SUFFIXES:\n".
"\n";
print &splitline("all:" . join "", map { " $_.exe" } &progrealnames("G:C"));
print "\n\n";
foreach $p (&prognames("G:C")) {
($prog, $type) = split ",", $p;
$objstr = &objects($p, "X.o", "X.res.o", undef);
print &splitline($prog . ".exe: " . $objstr), "\n";
my $mw = $type eq "G" ? " -mwindows" : "";
$libstr = &objects($p, undef, undef, "-lX");
print &splitline("\t\$(CC)" . $mw . " \$(LDFLAGS) -o \$@ " .
"-Wl,-Map,$prog.map " .
$objstr . " $libstr", 69), "\n\n";
}
foreach $d (&deps("X.o", "X.res.o", $dirpfx, "/", "cygwin")) {
if ($forceobj{$d->{obj_orig}}) {
printf ("%s: FORCE\n", $d->{obj});
} else {
print &splitline(sprintf("%s: %s", $d->{obj},
join " ", @{$d->{deps}})), "\n";
}
if ($d->{obj} =~ /\.res\.o$/) {
print "\t\$(RC) \$(RCFL) \$(RCFLAGS) ".$d->{deps}->[0]." -o ".$d->{obj}."\n\n";
} else {
print "\t\$(CC) \$(COMPAT) \$(CFLAGS) \$(XFLAGS) -c ".$d->{deps}->[0]."\n\n";
}
}
print "\n";
print $makefile_extra{'cygwin'}->{'end'} if defined $makefile_extra{'cygwin'}->{'end'};
print "\nclean:\n".
"\trm -f *.o *.exe *.res.o *.so *.map\n".
"\n".
"FORCE:\n";
select STDOUT; close OUT;
}
##-- Borland makefile
if (defined $makefiles{'borland'}) {
$dirpfx = &dirpfx($makefiles{'borland'}, "\\");
%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, ">$makefiles{'borland'}"; select OUT;
print
"# Makefile for $project_name 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
($_ = $help) =~ s/([=" ])\/D/$1-D/gs;
print $_;
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.bor\n".
"\n".
"# C compilation flags\n".
"CFLAGS = -D_WINDOWS -DWINVER=0x0500\n".
"# Resource compilation flags\n".
"RCFLAGS = -DNO_WINRESRC_H -DWIN32 -D_WIN32 -DWINVER=0x0401\n".
"\n".
"# Get include directory for resource compiler\n".
"!if !\$d(BCB)\n".
"BCB = \$(MAKEDIR)\\..\n".
"!endif\n".
"\n".
$makefile_extra{'borland'}->{'vars'} .
"\n".
".c.obj:\n".
&splitline("\tbcc32 -w-aus -w-ccc -w-par -w-pia \$(COMPAT)".
" \$(CFLAGS) \$(XFLAGS) ".
(join " ", map {"-I$dirpfx$_"} @srcdirs) .
" /c \$*.c",69)."\n".
".rc.res:\n".
&splitline("\tbrcc32 \$(RCFL) -i \$(BCB)\\include -r".
" \$(RCFLAGS) \$*.rc",69)."\n".
"\n";
print &splitline("all:" . join "", map { " $_.exe" } &progrealnames("G:C"));
print "\n\n";
foreach $p (&prognames("G:C")) {
($prog, $type) = split ",", $p;
$objstr = &objects($p, "X.obj", "X.res", undef);
print &splitline("$prog.exe: " . $objstr . " $prog.rsp"), "\n";
my $ap = ($type eq "G") ? "-aa" : "-ap";
print "\tilink32 $ap -Gn -L\$(BCB)\\lib \@$prog.rsp\n\n";
}
foreach $p (&prognames("G:C")) {
($prog, $type) = split ",", $p;
print $prog, ".rsp: \$(MAKEFILE)\n";
$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 = ($type eq "G") ? "c0w32" : "c0x32";
print "\techo $c0w + > $prog.rsp\n";
for ($i=0; $i<=$#objlines; $i++) {
$plus = ($i < $#objlines ? " +" : "");
print "\techo$objlines[$i]$plus >> $prog.rsp\n";
}
print "\techo $prog.exe >> $prog.rsp\n";
$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, >> $prog.rsp\n";
print "\techo " . &objects($p, undef, "X.res", undef) . " >> $prog.rsp\n";
print "\n";
}
foreach $d (&deps("X.obj", "X.res", $dirpfx, "\\", "borland")) {
if ($forceobj{$d->{obj_orig}}) {
printf("%s: FORCE\n", $d->{obj});
} else {
print &splitline(sprintf("%s: %s", $d->{obj},
join " ", @{$d->{deps}})), "\n";
}
}
print "\n";
print $makefile_extra{'borland'}->{'end'} if defined $makefile_extra{'borland'}->{'end'};
print "\nclean:\n".
"\t-del *.obj\n".
"\t-del *.exe\n".
"\t-del *.res\n".
"\t-del *.pch\n".
"\t-del *.aps\n".
"\t-del *.il*\n".
"\t-del *.pdb\n".
"\t-del *.rsp\n".
"\t-del *.tds\n".
"\t-del *.\$\$\$\$\$\$\n".
"\n".
"FORCE:\n".
"\t-rem dummy command\n";
select STDOUT; close OUT;
}
if (defined $makefiles{'vc'}) {
$dirpfx = &dirpfx($makefiles{'vc'}, "\\");
##-- Visual C++ makefile
open OUT, ">$makefiles{'vc'}"; select OUT;
print
"# Makefile for $project_name 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 " .
(join " ", map {"-I$dirpfx$_"} @srcdirs) .
" /D_WINDOWS /D_WIN32_WINDOWS=0x500 /DWINVER=0x500\n".
"LFLAGS = /incremental:no /fixed\n".
"RCFLAGS = ".(join " ", map {"-I$dirpfx$_"} @srcdirs).
" -DWIN32 -D_WIN32 -DWINVER=0x0400\n".
"\n".
$makefile_extra{'vc'}->{'vars'} .
"\n".
"\n";
print &splitline("all:" . join "", map { " $_.exe" } &progrealnames("G:C"));
print "\n\n";
foreach $p (&prognames("G:C")) {
($prog, $type) = split ",", $p;
$objstr = &objects($p, "X.obj", "X.res", undef);
print &splitline("$prog.exe: " . $objstr . " $prog.rsp"), "\n";
print "\tlink \$(LFLAGS) \$(XLFLAGS) -out:$prog.exe -map:$prog.map \@$prog.rsp\n\n";
}
foreach $p (&prognames("G:C")) {
($prog, $type) = split ",", $p;
print $prog, ".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 = ($type eq "G") ? "windows" : "console";
print "\techo /nologo /subsystem:$subsys > $prog.rsp\n";
for ($i=0; $i<=$#objlines; $i++) {
print "\techo$objlines[$i] >> $prog.rsp\n";
}
print "\n";
}
foreach $d (&deps("X.obj", "X.res", $dirpfx, "\\", "vc")) {
$extradeps = $forceobj{$d->{obj_orig}} ? ["*.c","*.h","*.rc"] : [];
print &splitline(sprintf("%s: %s", $d->{obj},
join " ", @$extradeps, @{$d->{deps}})), "\n";
if ($d->{obj} =~ /.obj$/) {
print "\tcl \$(COMPAT) \$(CFLAGS) \$(XFLAGS) /c ".$d->{deps}->[0],"\n\n";
} else {
print "\trc \$(RCFL) -r \$(RCFLAGS) ".$d->{deps}->[0],"\n\n";
}
}
print "\n";
print $makefile_extra{'vc'}->{'end'} if defined $makefile_extra{'vc'}->{'end'};
print "\nclean: 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;
}
if (defined $makefiles{'vcproj'}) {
$dirpfx = &dirpfx($makefiles{'vcproj'}, "\\");
##-- MSVC 6 Workspace and projects
#
# Note: All files created in this section are written in binary
# mode, because although MSVC's command-line make can deal with
# LF-only line endings, MSVC project files really _need_ to be
# CRLF. Hence, in order for mkfiles.pl to generate usable project
# files even when run from Unix, I make sure all files are binary
# and explicitly write the CRLFs.
#
# Create directories if necessary
mkdir $makefiles{'vcproj'}
if(! -d $makefiles{'vcproj'});
chdir $makefiles{'vcproj'};
@deps = &deps("X.obj", "X.res", $dirpfx, "\\", "vcproj");
%all_object_deps = map {$_->{obj} => $_->{deps}} @deps;
# Create the project files
# Get names of all Windows projects (GUI and console)
my @prognames = &prognames("G:C");
foreach $progname (@prognames) {
create_vc_project(\%all_object_deps, $progname);
}
# Create the workspace file
open OUT, ">$project_name.dsw"; binmode OUT; select OUT;
print
"Microsoft Developer Studio Workspace File, Format Version 6.00\r\n".
"# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r\n".
"\r\n".
"###############################################################################\r\n".
"\r\n";
# List projects
foreach $progname (@prognames) {
($windows_project, $type) = split ",", $progname;
print "Project: \"$windows_project\"=\".\\$windows_project\\$windows_project.dsp\" - Package Owner=<4>\r\n";
}
print
"\r\n".
"Package=<5>\r\n".
"{{{\r\n".
"}}}\r\n".
"\r\n".
"Package=<4>\r\n".
"{{{\r\n".
"}}}\r\n".
"\r\n".
"###############################################################################\r\n".
"\r\n".
"Global:\r\n".
"\r\n".
"Package=<5>\r\n".
"{{{\r\n".
"}}}\r\n".
"\r\n".
"Package=<3>\r\n".
"{{{\r\n".
"}}}\r\n".
"\r\n".
"###############################################################################\r\n".
"\r\n";
select STDOUT; close OUT;
chdir $orig_dir;
sub create_vc_project {
my ($all_object_deps, $progname) = @_;
# Construct program's dependency info
%seen_objects = ();
%lib_files = ();
%source_files = ();
%header_files = ();
%resource_files = ();
@object_files = split " ", &objects($progname, "X.obj", "X.res", "X.lib");
foreach $object_file (@object_files) {
next if defined $seen_objects{$object_file};
$seen_objects{$object_file} = 1;
if($object_file =~ /\.lib$/io) {
$lib_files{$object_file} = 1;
next;
}
$object_deps = $all_object_deps{$object_file};
foreach $object_dep (@$object_deps) {
if($object_dep =~ /\.c$/io) {
$source_files{$object_dep} = 1;
next;
}
if($object_dep =~ /\.h$/io) {
$header_files{$object_dep} = 1;
next;
}
if($object_dep =~ /\.(rc|ico)$/io) {
$resource_files{$object_dep} = 1;
next;
}
}
}
$libs = join " ", sort keys %lib_files;
@source_files = sort keys %source_files;
@header_files = sort keys %header_files;
@resources = sort keys %resource_files;
($windows_project, $type) = split ",", $progname;
mkdir $windows_project
if(! -d $windows_project);
chdir $windows_project;
$subsys = ($type eq "G") ? "windows" : "console";
open OUT, ">$windows_project.dsp"; binmode OUT; select OUT;
print
"# Microsoft Developer Studio Project File - Name=\"$windows_project\" - Package Owner=<4>\r\n".
"# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n".
"# ** DO NOT EDIT **\r\n".
"\r\n".
"# TARGTYPE \"Win32 (x86) Application\" 0x0101\r\n".
"\r\n".
"CFG=$windows_project - Win32 Debug\r\n".
"!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n".
"!MESSAGE use the Export Makefile command and run\r\n".
"!MESSAGE \r\n".
"!MESSAGE NMAKE /f \"$windows_project.mak\".\r\n".
"!MESSAGE \r\n".
"!MESSAGE You can specify a configuration when running NMAKE\r\n".
"!MESSAGE by defining the macro CFG on the command line. For example:\r\n".
"!MESSAGE \r\n".
"!MESSAGE NMAKE /f \"$windows_project.mak\" CFG=\"$windows_project - Win32 Debug\"\r\n".
"!MESSAGE \r\n".
"!MESSAGE Possible choices for configuration are:\r\n".
"!MESSAGE \r\n".
"!MESSAGE \"$windows_project - Win32 Release\" (based on \"Win32 (x86) Application\")\r\n".
"!MESSAGE \"$windows_project - Win32 Debug\" (based on \"Win32 (x86) Application\")\r\n".
"!MESSAGE \r\n".
"\r\n".
"# Begin Project\r\n".
"# PROP AllowPerConfigDependencies 0\r\n".
"# PROP Scc_ProjName \"\"\r\n".
"# PROP Scc_LocalPath \"\"\r\n".
"CPP=cl.exe\r\n".
"MTL=midl.exe\r\n".
"RSC=rc.exe\r\n".
"\r\n".
"!IF \"\$(CFG)\" == \"$windows_project - Win32 Release\"\r\n".
"\r\n".
"# PROP BASE Use_MFC 0\r\n".
"# PROP BASE Use_Debug_Libraries 0\r\n".
"# PROP BASE Output_Dir \"Release\"\r\n".
"# PROP BASE Intermediate_Dir \"Release\"\r\n".
"# PROP BASE Target_Dir \"\"\r\n".
"# PROP Use_MFC 0\r\n".
"# PROP Use_Debug_Libraries 0\r\n".
"# PROP Output_Dir \"Release\"\r\n".
"# PROP Intermediate_Dir \"Release\"\r\n".
"# PROP Ignore_Export_Lib 0\r\n".
"# PROP Target_Dir \"\"\r\n".
"# ADD BASE CPP /nologo /W3 /GX /O2 ".
(join " ", map {"/I \"..\\..\\$dirpfx$_\""} @srcdirs) .
" /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /c\r\n".
"# ADD CPP /nologo /W3 /GX /O2 ".
(join " ", map {"/I \"..\\..\\$dirpfx$_\""} @srcdirs) .
" /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /c\r\n".
"# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n".
"# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n".
"# ADD BASE RSC /l 0x809 /d \"NDEBUG\"\r\n".
"# ADD RSC /l 0x809 /d \"NDEBUG\"\r\n".
"BSC32=bscmake.exe\r\n".
"# ADD BASE BSC32 /nologo\r\n".
"# ADD BSC32 /nologo\r\n".
"LINK32=link.exe\r\n".
"# 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".
"# ADD LINK32 $libs /nologo /subsystem:$subsys /machine:I386\r\n".
"# SUBTRACT LINK32 /pdb:none\r\n".
"\r\n".
"!ELSEIF \"\$(CFG)\" == \"$windows_project - Win32 Debug\"\r\n".
"\r\n".
"# PROP BASE Use_MFC 0\r\n".
"# PROP BASE Use_Debug_Libraries 1\r\n".
"# PROP BASE Output_Dir \"Debug\"\r\n".
"# PROP BASE Intermediate_Dir \"Debug\"\r\n".
"# PROP BASE Target_Dir \"\"\r\n".
"# PROP Use_MFC 0\r\n".
"# PROP Use_Debug_Libraries 1\r\n".
"# PROP Output_Dir \"Debug\"\r\n".
"# PROP Intermediate_Dir \"Debug\"\r\n".
"# PROP Ignore_Export_Lib 0\r\n".
"# PROP Target_Dir \"\"\r\n".
"# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od ".
(join " ", map {"/I \"..\\..\\$dirpfx$_\""} @srcdirs) .
" /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /GZ /c\r\n".
"# ADD CPP /nologo /W3 /Gm /GX /ZI /Od ".
(join " ", map {"/I \"..\\..\\$dirpfx$_\""} @srcdirs) .
" /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /GZ /c\r\n".
"# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\r\n".
"# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\r\n".
"# ADD BASE RSC /l 0x809 /d \"_DEBUG\"\r\n".
"# ADD RSC /l 0x809 /d \"_DEBUG\"\r\n".
"BSC32=bscmake.exe\r\n".
"# ADD BASE BSC32 /nologo\r\n".
"# ADD BSC32 /nologo\r\n".
"LINK32=link.exe\r\n".
"# 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".
"# ADD LINK32 $libs /nologo /subsystem:$subsys /debug /machine:I386 /pdbtype:sept\r\n".
"# SUBTRACT LINK32 /pdb:none\r\n".
"\r\n".
"!ENDIF \r\n".
"\r\n".
"# Begin Target\r\n".
"\r\n".
"# Name \"$windows_project - Win32 Release\"\r\n".
"# Name \"$windows_project - Win32 Debug\"\r\n".
"# Begin Group \"Source Files\"\r\n".
"\r\n".
"# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n";
foreach $source_file (@source_files) {
print
"# Begin Source File\r\n".
"\r\n".
"SOURCE=..\\..\\$source_file\r\n";
if($source_file =~ /ssh\.c/io) {
# Disable 'Edit and continue' as Visual Studio can't handle the macros
print
"\r\n".
"!IF \"\$(CFG)\" == \"$windows_project - Win32 Release\"\r\n".
"\r\n".
"!ELSEIF \"\$(CFG)\" == \"$windows_project - Win32 Debug\"\r\n".
"\r\n".
"# ADD CPP /Zi\r\n".
"\r\n".
"!ENDIF \r\n".
"\r\n";
}
print "# End Source File\r\n";
}
print
"# End Group\r\n".
"# Begin Group \"Header Files\"\r\n".
"\r\n".
"# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n";
foreach $header_file (@header_files) {
print
"# Begin Source File\r\n".
"\r\n".
"SOURCE=..\\..\\$header_file\r\n".
"# End Source File\r\n";
}
print
"# End Group\r\n".
"# Begin Group \"Resource Files\"\r\n".
"\r\n".
"# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n";
foreach $resource_file (@resources) {
print
"# Begin Source File\r\n".
"\r\n".
"SOURCE=..\\..\\$resource_file\r\n".
"# End Source File\r\n";
}
print
"# End Group\r\n".
"# End Target\r\n".
"# End Project\r\n";
select STDOUT; close OUT;
chdir "..";
}
}
if (defined $makefiles{'vstudio10'} || defined $makefiles{'vstudio12'}) {
##-- Visual Studio 2010+ Solution and Projects
if (defined $makefiles{'vstudio10'}) {
create_vs_solution('vstudio10', "2010", "11.00", "v100");
}
if (defined $makefiles{'vstudio12'}) {
create_vs_solution('vstudio12', "2012", "12.00", "v110");
}
sub create_vs_solution {
my ($makefilename, $name, $version, $toolsver) = @_;
$dirpfx = &dirpfx($makefiles{$makefilename}, "\\");
@deps = &deps("X.obj", "X.res", $dirpfx, "\\", $makefilename);
%all_object_deps = map {$_->{obj} => $_->{deps}} @deps;
my @prognames = &prognames("G:C");
# Create the solution file.
mkdir $makefiles{$makefilename}
if(! -f $makefiles{$makefilename});
chdir $makefiles{$makefilename};
open OUT, ">$project_name.sln"; select OUT;
print
"Microsoft Visual Studio Solution File, Format Version $version\n" .
"# Visual Studio $name\n";
my %projguids = ();
foreach $progname (@prognames) {
($windows_project, $type) = split ",", $progname;
$projguids{$windows_project} = $guid =
&invent_guid("project:$progname");
print
"Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"$windows_project\", \"$windows_project\\$windows_project.vcxproj\", \"{$guid}\"\n" .
"EndProject\n";
}
print
"Global\n" .
" GlobalSection(SolutionConfigurationPlatforms) = preSolution\n" .
" Debug|Win32 = Debug|Win32\n" .
" Release|Win32 = Release|Win32\n" .
" EndGlobalSection\n" .
" GlobalSection(ProjectConfigurationPlatforms) = postSolution\n" ;
foreach my $projguid (values %projguids) {
print
" {$projguid}.Debug|Win32.ActiveCfg = Debug|Win32\n" .
" {$projguid}.Debug|Win32.Build.0 = Debug|Win32\n" .
" {$projguid}.Release|Win32.ActiveCfg = Release|Win32\n" .
" {$projguid}.Release|Win32.Build.0 = Release|Win32\n";
}
print
" EndGlobalSection\n" .
" GlobalSection(SolutionProperties) = preSolution\n" .
" HideSolutionNode = FALSE\n" .
" EndGlobalSection\n" .
"EndGlobal\n";
select STDOUT; close OUT;
foreach $progname (@prognames) {
($windows_project, $type) = split ",", $progname;
create_vs_project(\%all_object_deps, $windows_project, $type, $projguids{$windows_project}, $toolsver);
}
chdir $orig_dir;
}
sub create_vs_project {
my ($all_object_deps, $windows_project, $type, $projguid, $toolsver) = @_;
# Break down the project's dependency information into the appropriate
# groups.
%seen_objects = ();
%lib_files = ();
%source_files = ();
%header_files = ();
%resource_files = ();
%icon_files = ();
@object_files = split " ", &objects($progname, "X.obj", "X.res", "X.lib");
foreach $object_file (@object_files) {
next if defined $seen_objects{$object_file};
$seen_objects{$object_file} = 1;
if($object_file =~ /\.lib$/io) {
$lib_files{$object_file} = 1;
next;
}
$object_deps = $all_object_deps{$object_file};
foreach $object_dep (@$object_deps) {
if($object_dep eq $object_deps->[0]) {
if($object_dep =~ /\.c$/io) {
$source_files{$object_dep} = 1;
} elsif($object_dep =~ /\.rc$/io) {
$resource_files{$object_dep} = 1;
}
} elsif ($object_dep =~ /\.[ch]$/io) {
$header_files{$object_dep} = 1;
} elsif ($object_dep =~ /\.ico$/io) {
$icon_files{$object_dep} = 1;
}
}
}
$libs = join ";", sort keys %lib_files;
@source_files = sort keys %source_files;
@header_files = sort keys %header_files;
@resources = sort keys %resource_files;
@icons = sort keys %icon_files;
$subsystem = ($type eq "G") ? "Windows" : "Console";
mkdir $windows_project
if(! -d $windows_project);
chdir $windows_project;
open OUT, ">$windows_project.vcxproj"; select OUT;
open FILTERS, ">$windows_project.vcxproj.filters";
# The bulk of the project file is just boilerplate stuff, so we
# can mostly just dump it out here. Note, buried in the ClCompile
# item definition, that we use a debug information format of
# ProgramDatabase, which disables the edit-and-continue support
# that breaks most of the project builds.
print
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" .
"<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n" .
" <ItemGroup Label=\"ProjectConfigurations\">\n" .
" <ProjectConfiguration Include=\"Debug|Win32\">\n" .
" <Configuration>Debug</Configuration>\n" .
" <Platform>Win32</Platform>\n" .
" </ProjectConfiguration>\n" .
" <ProjectConfiguration Include=\"Release|Win32\">\n" .
" <Configuration>Release</Configuration>\n" .
" <Platform>Win32</Platform>\n" .
" </ProjectConfiguration>\n" .
" </ItemGroup>\n" .
" <PropertyGroup Label=\"Globals\">\n" .
" <SccProjectName />\n" .
" <SccLocalPath />\n" .
" <ProjectGuid>{$projguid}</ProjectGuid>\n" .
" </PropertyGroup>\n" .
" <Import Project=\"\$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n" .
" <PropertyGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n" .
" <ConfigurationType>Application</ConfigurationType>\n" .
" <UseOfMfc>false</UseOfMfc>\n" .
" <CharacterSet>MultiByte</CharacterSet>\n" .
" <PlatformToolset>$toolsver</PlatformToolset>\n" .
" </PropertyGroup>\n" .
" <PropertyGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n" .
" <ConfigurationType>Application</ConfigurationType>\n" .
" <UseOfMfc>false</UseOfMfc>\n" .
" <CharacterSet>MultiByte</CharacterSet>\n" .
" <PlatformToolset>$toolsver</PlatformToolset>\n" .
" </PropertyGroup>\n" .
" <Import Project=\"\$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n" .
" <ImportGroup Label=\"ExtensionTargets\">\n" .
" </ImportGroup>\n" .
" <ImportGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|Win32'\" Label=\"PropertySheets\">\n" .
" <Import Project=\"\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props\" Condition=\"exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n" .
" </ImportGroup>\n" .
" <ImportGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Release|Win32'\" Label=\"PropertySheets\">\n" .
" <Import Project=\"\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props\" Condition=\"exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n" .
" </ImportGroup>\n" .
" <PropertyGroup Label=\"UserMacros\" />\n" .
" <PropertyGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Release|Win32'\">\n" .
" <OutDir>.\\Release\\</OutDir>\n" .
" <IntDir>.\\Release\\</IntDir>\n" .
" <LinkIncremental>false</LinkIncremental>\n" .
" </PropertyGroup>\n" .
" <PropertyGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|Win32'\">\n" .
" <OutDir>.\\Debug\\</OutDir>\n" .
" <IntDir>.\\Debug\\</IntDir>\n" .
" <LinkIncremental>true</LinkIncremental>\n" .
" </PropertyGroup>\n" .
" <ItemDefinitionGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Release|Win32'\">\n" .
" <ClCompile>\n" .
" <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n" .
" <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\n" .
" <StringPooling>true</StringPooling>\n" .
" <FunctionLevelLinking>true</FunctionLevelLinking>\n" .
" <Optimization>MaxSpeed</Optimization>\n" .
" <SuppressStartupBanner>true</SuppressStartupBanner>\n" .
" <WarningLevel>Level3</WarningLevel>\n" .
" <AdditionalIncludeDirectories>" . (join ";", map {"..\\..\\$dirpfx$_"} @srcdirs) . ";%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n" .
" <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;POSIX;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n" .
" <AssemblerListingLocation>.\\Release\\</AssemblerListingLocation>\n" .
" <PrecompiledHeaderOutputFile>.\\Release\\$windows_project.pch</PrecompiledHeaderOutputFile>\n" .
" <ObjectFileName>.\\Release\\</ObjectFileName>\n" .
" <ProgramDataBaseFileName>.\\Release\\</ProgramDataBaseFileName>\n" .
" </ClCompile>\n" .
" <Midl>\n" .
" <SuppressStartupBanner>true</SuppressStartupBanner>\n" .
" <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n" .
" <TypeLibraryName>.\\Release\\$windows_project.tlb</TypeLibraryName>\n" .
" <MkTypLibCompatible>true</MkTypLibCompatible>\n" .
" <TargetEnvironment>Win32</TargetEnvironment>\n" .
" </Midl>\n" .
" <ResourceCompile>\n" .
" <Culture>0x0809</Culture>\n" .
" <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n" .
" </ResourceCompile>\n" .
" <Bscmake>\n" .
" <SuppressStartupBanner>true</SuppressStartupBanner>\n" .
" <OutputFile>.\\Release\\$windows_project.bsc</OutputFile>\n" .
" </Bscmake>\n" .
" <Link>\n" .
" <SuppressStartupBanner>true</SuppressStartupBanner>\n" .
" <SubSystem>$subsystem</SubSystem>\n" .
" <OutputFile>.\\Release\\$windows_project.exe</OutputFile>\n" .
" <AdditionalDependencies>$libs;%(AdditionalDependencies)</AdditionalDependencies>\n" .
" </Link>\n" .
" </ItemDefinitionGroup>\n" .
" <ItemDefinitionGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|Win32'\">\n" .
" <ClCompile>\n" .
" <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n" .
" <InlineFunctionExpansion>Default</InlineFunctionExpansion>\n" .
" <FunctionLevelLinking>false</FunctionLevelLinking>\n" .
" <Optimization>Disabled</Optimization>\n" .
" <SuppressStartupBanner>true</SuppressStartupBanner>\n" .
" <WarningLevel>Level3</WarningLevel>\n" .
" <MinimalRebuild>true</MinimalRebuild>\n" .
" <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n" .
" <AdditionalIncludeDirectories>" . (join ";", map {"..\\..\\$dirpfx$_"} @srcdirs) . ";%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n" .
" <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POSIX;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n" .
" <AssemblerListingLocation>.\\Debug\\</AssemblerListingLocation>\n" .
" <PrecompiledHeaderOutputFile>.\\Debug\\$windows_project.pch</PrecompiledHeaderOutputFile>\n" .
" <ObjectFileName>.\\Debug\\</ObjectFileName>\n" .
" <ProgramDataBaseFileName>.\\Debug\\</ProgramDataBaseFileName>\n" .
" <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n" .
" </ClCompile>\n" .
" <Midl>\n" .
" <SuppressStartupBanner>true</SuppressStartupBanner>\n" .
" <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n" .
" <TypeLibraryName>.\\Debug\\$windows_project.tlb</TypeLibraryName>\n" .
" <MkTypLibCompatible>true</MkTypLibCompatible>\n" .
" <TargetEnvironment>Win32</TargetEnvironment>\n" .
" </Midl>\n" .
" <ResourceCompile>\n" .
" <Culture>0x0809</Culture>\n" .
" <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n" .
" </ResourceCompile>\n" .
" <Bscmake>\n" .
" <SuppressStartupBanner>true</SuppressStartupBanner>\n" .
" <OutputFile>.\\Debug\\$windows_project.bsc</OutputFile>\n" .
" </Bscmake>\n" .
" <Link>\n" .
" <SuppressStartupBanner>true</SuppressStartupBanner>\n" .
" <GenerateDebugInformation>true</GenerateDebugInformation>\n" .
" <SubSystem>$subsystem</SubSystem>\n" .
" <OutputFile>\$(TargetPath)</OutputFile>\n" .
" <AdditionalDependencies>$libs;%(AdditionalDependencies)</AdditionalDependencies>\n" .
" </Link>\n" .
" </ItemDefinitionGroup>\n";
# The VC++ projects don't have physical structure to them, instead
# the files are organized by logical "filters" that are stored in
# a separate file, so different users can organize things differently.
# The filters file contains a copy of the ItemGroup elements from
# the main project file that list the included items, but tack
# on a filter name where needed.
print FILTERS
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" .
"<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n";
print " <ItemGroup>\n";
print FILTERS " <ItemGroup>\n";
foreach $icon_file (@icons) {
$icon_file =~ s/..\\windows\\//;
print " <CustomBuild Include=\"..\\..\\$icon_file\" />\n";
print FILTERS
" <CustomBuild Include=\"..\\..\\$icon_file\">\n" .
" <Filter>Resource Files</Filter>\n" .
" </CustomBuild>\n";
}
print FILTERS " </ItemGroup>\n";
print " </ItemGroup>\n";
print " <ItemGroup>\n";
print FILTERS " <ItemGroup>\n";
foreach $resource_file (@resources) {
$resource_file =~ s/..\\windows\\//;
print
" <ResourceCompile Include=\"..\\..\\$resource_file\">\n" .
" <AdditionalIncludeDirectories Condition=\"'\$(Configuration)|\$(Platform)'=='Release|Win32'\">..\\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n" .
" <AdditionalIncludeDirectories Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|Win32'\">..\\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n" .
" </ResourceCompile>\n";
print FILTERS
" <ResourceCompile Include=\"..\\..\\$resource_file\">\n" .
" <Filter>Resource Files</Filter>\n" .
" </ResourceCompile>\n";
}
print FILTERS " </ItemGroup>\n";
print " </ItemGroup>\n";
print " <ItemGroup>\n";
print FILTERS " <ItemGroup>\n";
foreach $source_file (@source_files) {
$source_file =~ s/..\\windows\\//;
print " <ClCompile Include=\"..\\..\\$source_file\" />\n";
print FILTERS
" <ClCompile Include=\"..\\..\\$source_file\">\n" .
" <Filter>Source Files</Filter>\n" .
" </ClCompile>";
}
print FILTERS " </ItemGroup>\n";
print " </ItemGroup>\n";
print " <ItemGroup>\n";
print FILTERS " <ItemGroup>\n";
foreach $header_file (@header_files) {
$header_file =~ s/..\\windows\\//;
print " <ClInclude Include=\"..\\..\\$header_file\" />\n";
print FILTERS
" <ClInclude Include=\"..\\..\\$header_file\">\n" .
" <Filter>Header Files</Filter>\n" .
" </ClInclude>";
}
print FILTERS " </ItemGroup>\n";
print " </ItemGroup>\n";
print
" <Import Project=\"\$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n" .
"</Project>";
print FILTERS
" <ItemGroup>\n" .
" <Filter Include=\"Source Files\">\n" .
" <UniqueIdentifier>{" . &invent_guid("sources:$windows_project") . "}</UniqueIdentifier>\n" .
" </Filter>\n" .
" <Filter Include=\"Header Files\">\n" .
" <UniqueIdentifier>{" . &invent_guid("headers:$windows_project") . "}</UniqueIdentifier>\n" .
" </Filter>\n" .
" <Filter Include=\"Resource Files\">\n" .
" <UniqueIdentifier>{" . &invent_guid("resources:$windows_project") . "}</UniqueIdentifier>\n" .
" </Filter>\n" .
" </ItemGroup>\n" .
"</Project>";
select STDOUT; close OUT; close FILTERS;
chdir "..";
}
}
if (defined $makefiles{'gtk'}) {
$dirpfx = &dirpfx($makefiles{'gtk'}, "/");
##-- X/GTK/Unix makefile
open OUT, ">$makefiles{'gtk'}"; select OUT;
print
"# Makefile for $project_name under X/GTK and Unix.\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
($_ = $help) =~ s/([=" ])\/D/$1-D/gs;
print $_;
print
"\n".
"# You can define this path to point at your tools if you need to\n".
"# TOOLPATH = /opt/gcc/bin\n".
"CC = \$(TOOLPATH)cc\n".
"# If necessary set the path to krb5-config here\n".
"KRB5CONFIG=krb5-config\n".
"# You can manually set this to `gtk-config' or `pkg-config gtk+-1.2'\n".
"# (depending on what works on your system) if you want to enforce\n".
"# building with GTK 1.2, or you can set it to `pkg-config gtk+-2.0 x11'\n".
"# if you want to enforce 2.0. The default is to try 2.0 and fall back\n".
"# to 1.2 if it isn't found.\n".
"GTK_CONFIG = sh -c 'pkg-config gtk+-2.0 x11 \$\$0 2>/dev/null || gtk-config \$\$0'\n".
"\n".
"-include Makefile.local\n".
"\n".
"unexport CFLAGS # work around a weird issue with krb5-config\n".
"\n".
&splitline("CFLAGS = -O2 -Wall -Werror -g " .
(join " ", map {"-I$dirpfx$_"} @srcdirs) .
" \$(shell \$(GTK_CONFIG) --cflags)").
" -D _FILE_OFFSET_BITS=64\n".
"XLDFLAGS = \$(LDFLAGS) \$(shell \$(GTK_CONFIG) --libs)\n".
"ULDFLAGS = \$(LDFLAGS)\n".
"ifeq (,\$(findstring NO_GSSAPI,\$(COMPAT)))\n".
"ifeq (,\$(findstring STATIC_GSSAPI,\$(COMPAT)))\n".
"XLDFLAGS+= -ldl\n".
"ULDFLAGS+= -ldl\n".
"else\n".
"CFLAGS+= -DNO_LIBDL \$(shell \$(KRB5CONFIG) --cflags gssapi)\n".
"XLDFLAGS+= \$(shell \$(KRB5CONFIG) --libs gssapi)\n".
"ULDFLAGS+= \$(shell \$(KRB5CONFIG) --libs gssapi)\n".
"endif\n".
"endif\n".
"INSTALL=install\n".
"INSTALL_PROGRAM=\$(INSTALL)\n".
"INSTALL_DATA=\$(INSTALL)\n".
"prefix=/usr/local\n".
"exec_prefix=\$(prefix)\n".
"bindir=\$(exec_prefix)/bin\n".
"mandir=\$(prefix)/man\n".
"man1dir=\$(mandir)/man1\n".
"\n".
&def($makefile_extra{'gtk'}->{'vars'}) .
"\n".
".SUFFIXES:\n".
"\n".
"\n";
print &splitline("all:" . join "", map { " $_" } &progrealnames("X:U"));
print "\n\n";
foreach $p (&prognames("X:U")) {
($prog, $type) = split ",", $p;
$objstr = &objects($p, "X.o", undef, undef);
print &splitline($prog . ": " . $objstr), "\n";
$libstr = &objects($p, undef, undef, "-lX");
print &splitline("\t\$(CC) -o \$@ " .
$objstr . " \$(${type}LDFLAGS) $libstr", 69), "\n\n";
}
foreach $d (&deps("X.o", undef, $dirpfx, "/", "gtk")) {
if ($forceobj{$d->{obj_orig}}) {
printf("%s: FORCE\n", $d->{obj});
} else {
print &splitline(sprintf("%s: %s", $d->{obj},
join " ", @{$d->{deps}})), "\n";
}
print &splitline("\t\$(CC) \$(COMPAT) \$(CFLAGS) \$(XFLAGS) -c $d->{deps}->[0]\n");
}
print "\n";
print $makefile_extra{'gtk'}->{'end'};
print "\nclean:\n".
"\trm -f *.o". (join "", map { " $_" } &progrealnames("X:U")) . "\n";
print "\nFORCE:\n";
select STDOUT; close OUT;
}
if (defined $makefiles{'unix'}) {
$dirpfx = &dirpfx($makefiles{'unix'}, "/");
##-- GTK-free pure-Unix makefile for non-GUI apps only
open OUT, ">$makefiles{'unix'}"; select OUT;
print
"# Makefile for $project_name under Unix.\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
($_ = $help) =~ s/([=" ])\/D/$1-D/gs;
print $_;
print
"\n".
"# You can define this path to point at your tools if you need to\n".
"# TOOLPATH = /opt/gcc/bin\n".
"CC = \$(TOOLPATH)cc\n".
"\n".
"-include Makefile.local\n".
"\n".
"unexport CFLAGS # work around a weird issue with krb5-config\n".
"\n".
&splitline("CFLAGS = -O2 -Wall -Werror -g " .
(join " ", map {"-I$dirpfx$_"} @srcdirs)).
" -D _FILE_OFFSET_BITS=64\n".
"ULDFLAGS = \$(LDFLAGS)\n".
"INSTALL=install\n".
"INSTALL_PROGRAM=\$(INSTALL)\n".
"INSTALL_DATA=\$(INSTALL)\n".
"prefix=/usr/local\n".
"exec_prefix=\$(prefix)\n".
"bindir=\$(exec_prefix)/bin\n".
"mandir=\$(prefix)/man\n".
"man1dir=\$(mandir)/man1\n".
"\n".
&def($makefile_extra{'unix'}->{'vars'}) .
"\n".
".SUFFIXES:\n".
"\n".
"\n";
print &splitline("all:" . join "", map { " $_" } &progrealnames("U"));
print "\n\n";
foreach $p (&prognames("U")) {
($prog, $type) = split ",", $p;
$objstr = &objects($p, "X.o", undef, undef);
print &splitline($prog . ": " . $objstr), "\n";
$libstr = &objects($p, undef, undef, "-lX");
print &splitline("\t\$(CC) -o \$@ " .
$objstr . " \$(${type}LDFLAGS) $libstr", 69), "\n\n";
}
foreach $d (&deps("X.o", undef, $dirpfx, "/", "unix")) {
if ($forceobj{$d->{obj_orig}}) {
printf("%s: FORCE\n", $d->{obj});
} else {
print &splitline(sprintf("%s: %s", $d->{obj},
join " ", @{$d->{deps}})), "\n";
}
print &splitline("\t\$(CC) \$(COMPAT) \$(CFLAGS) \$(XFLAGS) -c $d->{deps}->[0]\n");
}
print "\n";
print &def($makefile_extra{'unix'}->{'end'});
print "\nclean:\n".
"\trm -f *.o". (join "", map { " $_" } &progrealnames("U")) . "\n";
print "\nFORCE:\n";
select STDOUT; close OUT;
}
if (defined $makefiles{'am'}) {
Move the Unix configure script up to the top level. Previously, 'configure' and its assorted machinery lived in the 'unix' subdir, because that seemed like a clean place to keep it given that all the other per-platform Makefiles live in their platform directories. However, this never sat all that happily with autotools, and even less so now that it likes to have object file pathnames parallel source file pathnames: if you have Makefile.am refer to source files outside its subdir as "../terminal.c" and enable subdir-objects then any out-of-tree build calls the corresponding object file "../terminal.o" and so your build products mostly end up at the directory above your build dir! And as of autotools 1.14 my previous compensatory bodge of prefixing every source file path in Makefile.am with "$(srcdir)" has stopped working too. So I'm giving in to necessity, and changing policy by moving the configure machinery up to the top level of the source tree where autotools will be less confused by it. This should not be taken as any indication of the primacy of the Unix port, only of the recalcitrance of autotools. Whereas before we had a trivial script called 'configure' at the top level that invoked unix/configure to effectively do an 'out-of-tree build' (for make purposes) at the top level of the source tree, we now have a similar script in unix/configure. So this _should_ make very little difference: people who were previously running configure from the top level should still be able to, and likewise people who were running it from the unix subdir. [originally from svn r10141]
2014-02-22 22:01:32 +04:00
die "Makefile.am in a subdirectory is not supported\n"
if &dirpfx($makefiles{'am'}, "/") ne "";
##-- Unix/autoconf Makefile.am
open OUT, ">$makefiles{'am'}"; select OUT;
print
"# Makefile.am for $project_name under Unix with Autoconf/Automake.\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\n";
# 2014-02-22: as of automake-1.14 we begin to get complained at if
# we don't use this option
print "AUTOMAKE_OPTIONS = subdir-objects\n\n";
# Complete list of source and header files. Not used by the
# auto-generated parts of this makefile, but Recipe might like to
# have it available as a variable so that mandatory-rebuild things
# (version.o) can conveniently be made to depend on it.
Move the Unix configure script up to the top level. Previously, 'configure' and its assorted machinery lived in the 'unix' subdir, because that seemed like a clean place to keep it given that all the other per-platform Makefiles live in their platform directories. However, this never sat all that happily with autotools, and even less so now that it likes to have object file pathnames parallel source file pathnames: if you have Makefile.am refer to source files outside its subdir as "../terminal.c" and enable subdir-objects then any out-of-tree build calls the corresponding object file "../terminal.o" and so your build products mostly end up at the directory above your build dir! And as of autotools 1.14 my previous compensatory bodge of prefixing every source file path in Makefile.am with "$(srcdir)" has stopped working too. So I'm giving in to necessity, and changing policy by moving the configure machinery up to the top level of the source tree where autotools will be less confused by it. This should not be taken as any indication of the primacy of the Unix port, only of the recalcitrance of autotools. Whereas before we had a trivial script called 'configure' at the top level that invoked unix/configure to effectively do an 'out-of-tree build' (for make purposes) at the top level of the source tree, we now have a similar script in unix/configure. So this _should_ make very little difference: people who were previously running configure from the top level should still be able to, and likewise people who were running it from the unix subdir. [originally from svn r10141]
2014-02-22 22:01:32 +04:00
@sources = ("allsources", "=", sort keys %allsourcefiles);
print &splitline(join " ", @sources), "\n\n";
@cliprogs = ("bin_PROGRAMS", "=");
foreach $p (&prognames("U")) {
($prog, $type) = split ",", $p;
push @cliprogs, $prog;
}
@allprogs = @cliprogs;
foreach $p (&prognames("X")) {
($prog, $type) = split ",", $p;
push @allprogs, $prog;
}
print "if HAVE_GTK\n";
print &splitline(join " ", @allprogs), "\n";
print "else\n";
print &splitline(join " ", @cliprogs), "\n";
print "endif\n\n";
%objtosrc = ();
Move the Unix configure script up to the top level. Previously, 'configure' and its assorted machinery lived in the 'unix' subdir, because that seemed like a clean place to keep it given that all the other per-platform Makefiles live in their platform directories. However, this never sat all that happily with autotools, and even less so now that it likes to have object file pathnames parallel source file pathnames: if you have Makefile.am refer to source files outside its subdir as "../terminal.c" and enable subdir-objects then any out-of-tree build calls the corresponding object file "../terminal.o" and so your build products mostly end up at the directory above your build dir! And as of autotools 1.14 my previous compensatory bodge of prefixing every source file path in Makefile.am with "$(srcdir)" has stopped working too. So I'm giving in to necessity, and changing policy by moving the configure machinery up to the top level of the source tree where autotools will be less confused by it. This should not be taken as any indication of the primacy of the Unix port, only of the recalcitrance of autotools. Whereas before we had a trivial script called 'configure' at the top level that invoked unix/configure to effectively do an 'out-of-tree build' (for make purposes) at the top level of the source tree, we now have a similar script in unix/configure. So this _should_ make very little difference: people who were previously running configure from the top level should still be able to, and likewise people who were running it from the unix subdir. [originally from svn r10141]
2014-02-22 22:01:32 +04:00
foreach $d (&deps("X", undef, "", "/", "am")) {
$objtosrc{$d->{obj}} = $d->{deps}->[0];
}
print &splitline(join " ", "AM_CPPFLAGS", "=",
Move the Unix configure script up to the top level. Previously, 'configure' and its assorted machinery lived in the 'unix' subdir, because that seemed like a clean place to keep it given that all the other per-platform Makefiles live in their platform directories. However, this never sat all that happily with autotools, and even less so now that it likes to have object file pathnames parallel source file pathnames: if you have Makefile.am refer to source files outside its subdir as "../terminal.c" and enable subdir-objects then any out-of-tree build calls the corresponding object file "../terminal.o" and so your build products mostly end up at the directory above your build dir! And as of autotools 1.14 my previous compensatory bodge of prefixing every source file path in Makefile.am with "$(srcdir)" has stopped working too. So I'm giving in to necessity, and changing policy by moving the configure machinery up to the top level of the source tree where autotools will be less confused by it. This should not be taken as any indication of the primacy of the Unix port, only of the recalcitrance of autotools. Whereas before we had a trivial script called 'configure' at the top level that invoked unix/configure to effectively do an 'out-of-tree build' (for make purposes) at the top level of the source tree, we now have a similar script in unix/configure. So this _should_ make very little difference: people who were previously running configure from the top level should still be able to, and likewise people who were running it from the unix subdir. [originally from svn r10141]
2014-02-22 22:01:32 +04:00
map {"-I\$(srcdir)/$_"} @srcdirs), "\n";
@amcflags = ("\$(COMPAT)", "\$(XFLAGS)", "\$(WARNINGOPTS)");
print "if HAVE_GTK\n";
print &splitline(join " ", "AM_CFLAGS", "=",
"\$(GTK_CFLAGS)", @amcflags), "\n";
print "else\n";
print &splitline(join " ", "AM_CFLAGS", "=", @amcflags), "\n";
print "endif\n\n";
%amspeciallibs = ();
foreach $obj (sort { $a cmp $b } keys %{$cflags{'am'}}) {
print "lib${obj}_a_SOURCES = ", $objtosrc{$obj}, "\n";
print &splitline(join " ", "lib${obj}_a_CFLAGS", "=", @amcflags,
$cflags{'am'}->{$obj}), "\n";
$amspeciallibs{$obj} = "lib${obj}.a";
}
print &splitline(join " ", "noinst_LIBRARIES", "=",
sort { $a cmp $b } values %amspeciallibs), "\n\n";
foreach $p (&prognames("X:U")) {
($prog, $type) = split ",", $p;
print "if HAVE_GTK\n" if $type eq "X";
@progsources = ("${prog}_SOURCES", "=");
%sourcefiles = ();
@ldadd = ();
$objstr = &objects($p, "X", undef, undef);
foreach $obj (split / /,$objstr) {
if ($amspeciallibs{$obj}) {
push @ldadd, $amspeciallibs{$obj};
} else {
$sourcefiles{$objtosrc{$obj}} = 1;
}
}
push @progsources, sort { $a cmp $b } keys %sourcefiles;
print &splitline(join " ", @progsources), "\n";
if ($type eq "X") {
push @ldadd, "\$(GTK_LIBS)";
}
if (@ldadd) {
print &splitline(join " ", "${prog}_LDADD", "=", @ldadd), "\n";
}
print "endif\n" if $type eq "X";
print "\n";
}
print $makefile_extra{'am'}->{'end'};
select STDOUT; close OUT;
}
if (defined $makefiles{'lcc'}) {
$dirpfx = &dirpfx($makefiles{'lcc'}, "\\");
##-- lcc makefile
open OUT, ">$makefiles{'lcc'}"; select OUT;
print
"# Makefile for $project_name under lcc.\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";
# lcc command line option is -D not /D
($_ = $help) =~ s/([=" ])\/D/$1-D/gs;
print $_;
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.lcc\n".
"\n".
"# C compilation flags\n".
"CFLAGS = -D_WINDOWS " .
(join " ", map {"-I$dirpfx$_"} @srcdirs) .
"\n".
"# Resource compilation flags\n".
"RCFLAGS = ".(join " ", map {"-I$dirpfx$_"} @srcdirs)."\n".
"\n".
"# Get include directory for resource compiler\n".
"\n".
$makefile_extra{'lcc'}->{'vars'} .
"\n";
print &splitline("all:" . join "", map { " $_.exe" } &progrealnames("G:C"));
print "\n\n";
foreach $p (&prognames("G:C")) {
($prog, $type) = split ",", $p;
$objstr = &objects($p, "X.obj", "X.res", undef);
print &splitline("$prog.exe: " . $objstr ), "\n";
$subsystemtype = '';
if ($type eq "G") { $subsystemtype = "-subsystem windows"; }
my $libss = "shell32.lib wsock32.lib ws2_32.lib winspool.lib winmm.lib imm32.lib";
print &splitline("\tlcclnk $subsystemtype -o $prog.exe $objstr $libss");
print "\n\n";
}
foreach $d (&deps("X.obj", "X.res", $dirpfx, "\\", "lcc")) {
if ($forceobj{$d->{obj_orig}}) {
printf("%s: FORCE\n", $d->{obj});
} else {
print &splitline(sprintf("%s: %s", $d->{obj},
join " ", @{$d->{deps}})), "\n";
}
if ($d->{obj} =~ /\.obj$/) {
print &splitline("\tlcc -O -p6 \$(COMPAT)".
" \$(CFLAGS) \$(XFLAGS) ".$d->{deps}->[0],69)."\n";
} else {
print &splitline("\tlrc \$(RCFL) -r \$(RCFLAGS) ".
$d->{deps}->[0],69)."\n";
}
}
print "\n";
print $makefile_extra{'lcc'}->{'end'} if defined $makefile_extra{'lcc'}->{'end'};
print "\nclean:\n".
"\t-del *.obj\n".
"\t-del *.exe\n".
"\t-del *.res\n".
"\n".
"FORCE:\n";
select STDOUT; close OUT;
}
if (defined $makefiles{'osx'}) {
$dirpfx = &dirpfx($makefiles{'osx'}, "/");
##-- Mac OS X makefile
open OUT, ">$makefiles{'osx'}"; select OUT;
print
"# Makefile for $project_name under Mac OS X.\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
($_ = $help) =~ s/([=" ])\/D/$1-D/gs;
print $_;
print
"CC = \$(TOOLPATH)gcc\n".
"\n".
&splitline("CFLAGS = -O2 -Wall -Werror -g " .
(join " ", map {"-I$dirpfx$_"} @srcdirs))."\n".
"MLDFLAGS = -framework Cocoa\n".
"ULDFLAGS =\n".
"\n" .
$makefile_extra{'osx'}->{'vars'} .
"\n" .
&splitline("all:" . join "", map { " $_" } &progrealnames("MX:U")) .
"\n";
foreach $p (&prognames("MX")) {
($prog, $type) = split ",", $p;
$objstr = &objects($p, "X.o", undef, undef);
$icon = &special($p, ".icns");
$infoplist = &special($p, "info.plist");
print "${prog}.app:\n\tmkdir -p \$\@\n";
print "${prog}.app/Contents: ${prog}.app\n\tmkdir -p \$\@\n";
print "${prog}.app/Contents/MacOS: ${prog}.app/Contents\n\tmkdir -p \$\@\n";
$targets = "${prog}.app/Contents/MacOS/$prog";
if (defined $icon) {
print "${prog}.app/Contents/Resources: ${prog}.app/Contents\n\tmkdir -p \$\@\n";
print "${prog}.app/Contents/Resources/${prog}.icns: ${prog}.app/Contents/Resources $icon\n\tcp $icon \$\@\n";
$targets .= " ${prog}.app/Contents/Resources/${prog}.icns";
}
if (defined $infoplist) {
print "${prog}.app/Contents/Info.plist: ${prog}.app/Contents/Resources $infoplist\n\tcp $infoplist \$\@\n";
$targets .= " ${prog}.app/Contents/Info.plist";
}
$targets .= " \$(${prog}_extra)";
print &splitline("${prog}: $targets", 69) . "\n\n";
print &splitline("${prog}.app/Contents/MacOS/$prog: ".
"${prog}.app/Contents/MacOS " . $objstr), "\n";
$libstr = &objects($p, undef, undef, "-lX");
print &splitline("\t\$(CC) \$(MLDFLAGS) -o \$@ " .
$objstr . " $libstr", 69), "\n\n";
}
foreach $p (&prognames("U")) {
($prog, $type) = split ",", $p;
$objstr = &objects($p, "X.o", undef, undef);
print &splitline($prog . ": " . $objstr), "\n";
$libstr = &objects($p, undef, undef, "-lX");
print &splitline("\t\$(CC) \$(ULDFLAGS) -o \$@ " .
$objstr . " $libstr", 69), "\n\n";
}
foreach $d (&deps("X.o", undef, $dirpfx, "/", "osx")) {
if ($forceobj{$d->{obj_orig}}) {
printf("%s: FORCE\n", $d->{obj});
} else {
print &splitline(sprintf("%s: %s", $d->{obj},
join " ", @{$d->{deps}})), "\n";
}
$firstdep = $d->{deps}->[0];
if ($firstdep =~ /\.c$/) {
print "\t\$(CC) \$(COMPAT) \$(FWHACK) \$(CFLAGS) \$(XFLAGS) -c \$<\n";
} elsif ($firstdep =~ /\.m$/) {
print "\t\$(CC) -x objective-c \$(COMPAT) \$(FWHACK) \$(CFLAGS) \$(XFLAGS) -c \$<\n";
}
}
print "\n".&def($makefile_extra{'osx'}->{'end'});
print "\nclean:\n".
"\trm -f *.o *.dmg". (join "", map { " $_" } &progrealnames("U")) . "\n".
"\trm -rf *.app\n".
"\n".
"FORCE:\n";
select STDOUT; close OUT;
}
if (defined $makefiles{'devcppproj'}) {
$dirpfx = &dirpfx($makefiles{'devcppproj'}, "\\");
$orig_dir = cwd;
##-- Dev-C++ 5 projects
#
# Note: All files created in this section are written in binary
# mode to prevent any posibility of misinterpreted line endings.
# I don't know if Dev-C++ is as touchy as MSVC with LF-only line
# endings. But however, CRLF line endings are the common way on
# Win32 machines where Dev-C++ is running.
# Hence, in order for mkfiles.pl to generate CRLF project files
# even when run from Unix, I make sure all files are binary and
# explicitly write the CRLFs.
#
# Create directories if necessary
mkdir $makefiles{'devcppproj'}
if(! -d $makefiles{'devcppproj'});
chdir $makefiles{'devcppproj'};
@deps = &deps("X.obj", "X.res", $dirpfx, "\\", "devcppproj");
%all_object_deps = map {$_->{obj} => $_->{deps}} @deps;
# Make dir names FAT/NTFS compatible
my @srcdirs = @srcdirs;
for ($i=0; $i<@srcdirs; $i++) {
$srcdirs[$i] =~ s/\//\\/g;
$srcdirs[$i] =~ s/\\$//;
}
# Create the project files
# Get names of all Windows projects (GUI and console)
my @prognames = &prognames("G:C");
foreach $progname (@prognames) {
create_devcpp_project(\%all_object_deps, $progname);
}
chdir $orig_dir;
sub create_devcpp_project {
my ($all_object_deps, $progname) = @_;
# Construct program's dependency info (Taken from 'vcproj', seems to work right here, too.)
%seen_objects = ();
%lib_files = ();
%source_files = ();
%header_files = ();
%resource_files = ();
@object_files = split " ", &objects($progname, "X.obj", "X.res", "X.lib");
foreach $object_file (@object_files) {
next if defined $seen_objects{$object_file};
$seen_objects{$object_file} = 1;
if($object_file =~ /\.lib$/io) {
$lib_files{$object_file} = 1;
next;
}
$object_deps = $all_object_deps{$object_file};
foreach $object_dep (@$object_deps) {
if($object_dep =~ /\.c$/io) {
$source_files{$object_dep} = 1;
next;
}
if($object_dep =~ /\.h$/io) {
$header_files{$object_dep} = 1;
next;
}
if($object_dep =~ /\.(rc|ico)$/io) {
$resource_files{$object_dep} = 1;
next;
}
}
}
$libs = join " ", sort keys %lib_files;
@source_files = sort keys %source_files;
@header_files = sort keys %header_files;
@resources = sort keys %resource_files;
($windows_project, $type) = split ",", $progname;
mkdir $windows_project
if(! -d $windows_project);
chdir $windows_project;
$subsys = ($type eq "G") ? "0" : "1"; # 0 = Win32 GUI, 1 = Win32 Console
open OUT, ">$windows_project.dev"; binmode OUT; select OUT;
print
"# DEV-C++ 5 Project File - $windows_project.dev\r\n".
"# ** DO NOT EDIT **\r\n".
"\r\n".
# No difference between DEBUG and RELEASE here as in 'vcproj', because
# Dev-C++ does not support mutiple compilation profiles in one single project.
# (At least I can say this for Dev-C++ 5 Beta)
"[Project]\r\n".
"FileName=$windows_project.dev\r\n".
"Name=$windows_project\r\n".
"Ver=1\r\n".
"IsCpp=1\r\n".
"Type=$subsys\r\n".
# Multimon is disabled here, as Dev-C++ (Version 5 Beta) does not have multimon.h
"Compiler=-W -D__GNUWIN32__ -DWIN32 -DNDEBUG -D_WINDOWS -DNO_MULTIMON -D_MBCS_\@\@_\r\n".
"CppCompiler=-W -D__GNUWIN32__ -DWIN32 -DNDEBUG -D_WINDOWS -DNO_MULTIMON -D_MBCS_\@\@_\r\n".
"Includes=" . (join ";", map {"..\\..\\$dirpfx$_"} @srcdirs) . "\r\n".
"Linker=-ladvapi32 -lcomctl32 -lcomdlg32 -lgdi32 -limm32 -lshell32 -luser32 -lwinmm -lwinspool_\@\@_\r\n".
"Libs=\r\n".
"UnitCount=" . (@source_files + @header_files + @resources) . "\r\n".
"Folders=\"Header Files\",\"Resource Files\",\"Source Files\"\r\n".
"ObjFiles=\r\n".
"PrivateResource=${windows_project}_private.rc\r\n".
"ResourceIncludes=..\\..\\..\\WINDOWS\r\n".
"MakeIncludes=\r\n".
"Icon=\r\n". # It's ok to leave this blank.
"ExeOutput=\r\n".
"ObjectOutput=\r\n".
"OverrideOutput=0\r\n".
"OverrideOutputName=$windows_project.exe\r\n".
"HostApplication=\r\n".
"CommandLine=\r\n".
"UseCustomMakefile=0\r\n".
"CustomMakefile=\r\n".
"IncludeVersionInfo=0\r\n".
"SupportXPThemes=0\r\n".
"CompilerSet=0\r\n".
"CompilerSettings=0000000000000000000000\r\n".
"\r\n";
$unit_count = 1;
foreach $source_file (@source_files) {
print
"[Unit$unit_count]\r\n".
"FileName=..\\..\\$source_file\r\n".
"Folder=Source Files\r\n".
"Compile=1\r\n".
"CompileCpp=0\r\n".
"Link=1\r\n".
"Priority=1000\r\n".
"OverrideBuildCmd=0\r\n".
"BuildCmd=\r\n".
"\r\n";
$unit_count++;
}
foreach $header_file (@header_files) {
print
"[Unit$unit_count]\r\n".
"FileName=..\\..\\$header_file\r\n".
"Folder=Header Files\r\n".
"Compile=1\r\n".
"CompileCpp=1\r\n". # Dev-C++ want's to compile all header files with both compilers C and C++. It does not hurt.
"Link=1\r\n".
"Priority=1000\r\n".
"OverrideBuildCmd=0\r\n".
"BuildCmd=\r\n".
"\r\n";
$unit_count++;
}
foreach $resource_file (@resources) {
if ($resource_file =~ /.*\.(ico|cur|bmp|dlg|rc2|rct|bin|rgs|gif|jpg|jpeg|jpe)/io) { # Default filter as in 'vcproj'
$Compile = "0"; # Don't compile images and other binary resource files
$CompileCpp = "0";
} else {
$Compile = "1";
$CompileCpp = "1"; # Dev-C++ want's to compile all .rc files with both compilers C and C++. It does not hurt.
}
print
"[Unit$unit_count]\r\n".
"FileName=..\\..\\$resource_file\r\n".
"Folder=Resource Files\r\n".
"Compile=$Compile\r\n".
"CompileCpp=$CompileCpp\r\n".
"Link=0\r\n".
"Priority=1000\r\n".
"OverrideBuildCmd=0\r\n".
"BuildCmd=\r\n".
"\r\n";
$unit_count++;
}
#Note: By default, [VersionInfo] is not used.
print
"[VersionInfo]\r\n".
"Major=0\r\n".
"Minor=0\r\n".
"Release=1\r\n".
"Build=1\r\n".
"LanguageID=1033\r\n".
"CharsetID=1252\r\n".
"CompanyName=\r\n".
"FileVersion=0.1\r\n".
"FileDescription=\r\n".
"InternalName=\r\n".
"LegalCopyright=\r\n".
"LegalTrademarks=\r\n".
"OriginalFilename=$windows_project.exe\r\n".
"ProductName=$windows_project\r\n".
"ProductVersion=0.1\r\n".
"AutoIncBuildNr=0\r\n";
select STDOUT; close OUT;
chdir "..";
}
}
# All done, so do the Unix postprocessing if asked to.
if ($do_unix) {
chdir $orig_dir;
system "./mkauto.sh";
die "mkfiles.pl: mkauto.sh returned $?\n" if $? > 0;
if ($do_unix == 1) {
Move the Unix configure script up to the top level. Previously, 'configure' and its assorted machinery lived in the 'unix' subdir, because that seemed like a clean place to keep it given that all the other per-platform Makefiles live in their platform directories. However, this never sat all that happily with autotools, and even less so now that it likes to have object file pathnames parallel source file pathnames: if you have Makefile.am refer to source files outside its subdir as "../terminal.c" and enable subdir-objects then any out-of-tree build calls the corresponding object file "../terminal.o" and so your build products mostly end up at the directory above your build dir! And as of autotools 1.14 my previous compensatory bodge of prefixing every source file path in Makefile.am with "$(srcdir)" has stopped working too. So I'm giving in to necessity, and changing policy by moving the configure machinery up to the top level of the source tree where autotools will be less confused by it. This should not be taken as any indication of the primacy of the Unix port, only of the recalcitrance of autotools. Whereas before we had a trivial script called 'configure' at the top level that invoked unix/configure to effectively do an 'out-of-tree build' (for make purposes) at the top level of the source tree, we now have a similar script in unix/configure. So this _should_ make very little difference: people who were previously running configure from the top level should still be able to, and likewise people who were running it from the unix subdir. [originally from svn r10141]
2014-02-22 22:01:32 +04:00
chdir ($targetdir = "unix")
or die "$targetdir: chdir: $!\n";
}
system "./configure", @confargs;
die "mkfiles.pl: configure returned $?\n" if $? > 0;
}
sub invent_guid($) {
my ($name) = @_;
# Invent a GUID for use in Visual Studio project files. We need
# a few of these for every executable file we build.
#
# In order to avoid having to use the non-core Perl module
# Data::GUID, and also arrange for GUIDs to be stable, we generate
# our GUIDs by hashing a pile of fixed (but originally randomly
# generated) data with the filename for which we need an id.
#
# Hashing _just_ the filenames would clearly be cheating (it's
# quite conceivable that someone might hash the same string for
# another reason and so generate a colliding GUID), but hashing a
# whole SHA-512 data block of random gibberish as well should make
# these GUIDs pseudo-random enough to not collide with anyone
# else's.
my $randdata = pack "N*",
0xD4AB035F,0x76998BA0,0x2DCCB0BD,0x6D3FA320,0x53638051,0xFE312F35,
0xDE1CECC0,0x784DF852,0x6C9F4589,0x54B7AC23,0x14E7A1C4,0xF9BF04DF,
0x19C08B6D,0x3FB69EF1,0xB2DA9043,0xDB5362F3,0x25718DB6,0x733560DA,
0xFEF871B0,0xFECF7A0C,0x67D19C95,0xB492E911,0xF5D562A3,0xFCE1D478,
0x02C50434,0xF7326B7E,0x93D39872,0xCF0D0269,0x9EF24C0F,0x827689AD,
0x88BD20BC,0x74EA6AFE,0x29223682,0xB9AB9287,0x7EA7CE4F,0xCF81B379,
0x9AE4A954,0x81C7AD97,0x2FF2F031,0xC51DA3C2,0xD311CCE7,0x0A31EB8B,
0x1AB04242,0xAF53B714,0xFC574D40,0x8CB4ED01,0x29FEB16F,0x4904D7ED,
0xF5C5F5E1,0xF138A4C2,0xA9D881CE,0xCEA65187,0x4421BA97,0x0EE8428E,
0x9556E384,0x6D0484C9,0x561BD84B,0xD9516A40,0x6B4FD33F,0xDDFFE4C8,
0x3D5DF8A5,0xFE6B7D99,0x3443371B,0xF4E30A3E,0xE62B9FDA,0x6BAA75DB,
0x9EF3C2C7,0x6815CA42,0xE6536076,0xF851E6E2,0x39D16E69,0xBCDF3BB6,
0x50EFFA41,0x378CDF2A,0xB5EC0D0C,0x1E94C433,0xE818241A,0x2689EB1F,
0xB649CEF9,0xD7344D46,0x59C1BB13,0x27511FDF,0x7DAD1768,0xB355E29E,
0xDFAE550C,0x2433005B,0x09DE10B0,0xAA00BA6B,0xC144ED2D,0x8513D007,
0xB0315232,0x7A10DAB6,0x1D97654E,0xF048214D,0xE3059E75,0x83C225D1,
0xFC7AB177,0x83F2B553,0x79F7A0AF,0x1C94582C,0xF5E4AF4B,0xFB39C865,
0x58ABEB27,0xAAB28058,0x52C15A89,0x0EBE9741,0x343F4D26,0xF941202A,
0xA32FD32F,0xDCC055B8,0x64281BF3,0x468BD7BA,0x0CEE09D3,0xBB5FD2B6,
0xA528D412,0xA6A6967E,0xEAAF5DAE,0xDE7B2FAE,0xCA36887B,0x0DE196EB,
0x74B95EF0,0x9EB8B7C2,0x020BFC83,0x1445086F,0xBF4B61B2,0x89AFACEC,
0x80A5CD69,0xC790F744,0x435A6998,0x8DE7AC48,0x32F31BC9,0x8F760D3D,
0xF02A74CB,0xD7B47E20,0x9EC91035,0x70FDE74D,0x9B531362,0x9D81739A,
0x59ADC2EB,0x511555B5,0xCA84B8D5,0x3EC325FF,0x2E442A4C,0x82AF30D9,
0xBFD3EC87,0x90C59E07,0x1C6DC991,0x2D16B822,0x7EA44EB5,0x3A655A39,
0xAB640886,0x09311821,0x777801D9,0x489DBE61,0xA1FFEC65,0x978B49B1,
0x7DB700CD,0x263CF3D6,0xF977E89F,0xBA0B3D01,0x6C6CED19,0x1BE6F23A,
0x19E0ED98,0x8E71A499,0x70BA3271,0x3FB7EE98,0xABA46848,0x2B797959,
0x72C6DE59,0xE08B795C,0x02936C39,0x02185CCB,0xD6F3CE18,0xD0157A40,
0x833DEC3F,0x319B00C4,0x97B59513,0x900B81FD,0x9A022379,0x16E44E1A,
0x0C4CC540,0xCA98E7F9,0xF9431A26,0x290BCFAC,0x406B82C0,0xBC1C4585,
0x55C54528,0x811EBB77,0xD4EDD4F3,0xA70DC02E,0x8AD5C0D1,0x28D64EF4,
0xBEFF5C69,0x99852C4A,0xB4BBFF7B,0x069230AC,0xA3E141FA,0x4E99FB0E,
0xBC154DAA,0x323C7F15,0x86E0247E,0x2EEA3054,0xC9CA1D32,0x8964A006,
0xC93978AC,0xF9B2C159,0x03F2079E,0xB051D284,0x4A7EA9A9,0xF001DA1F,
0xD47A0DAA,0xCF7B6B73,0xF18293B2,0x84303E34,0xF8BC76C4,0xAFBEE24F,
0xB589CA80,0x77B5BF86,0x21B9FD5B,0x1A5071DF,0xA3863110,0x0E50CA61,
0x939151A5,0xD2A59021,0x83A9CDCE,0xCEC69767,0xC906BB16,0x3EE1FF4D,
0x1321EAE4,0x0BF940D6,0x52471E61,0x8A087056,0x66E54293,0xF84AAB9B,
0x08835EF1,0x8F12B77A,0xD86935A5,0x200281D7,0xCD3C37C9,0x30ABEC05,
0x7067E8A0,0x608C4838,0xC9F51CDE,0xA6D318DE,0x41C05B2A,0x694CCE0E,
0xC7842451,0xA3194393,0xFBDC2C84,0xA6D2B577,0xC91E7924,0x01EDA708,
0x22FBB61E,0x662F9B7B,0xDE3150C3,0x2397058C;
my $digest = sha512_hex($name . "\0" . $randdata);
return sprintf("%s-%s-%04x-%04x-%s",
substr($digest,0,8),
substr($digest,8,4),
0x4000 | (0xFFF & hex(substr($digest,12,4))),
0x8000 | (0x3FFF & hex(substr($digest,16,4))),
substr($digest,20,12));
}