# mainly because I was too scared to go anywhere near it.
# - sbcsgen.pl is still run at startup.
+# Other things undone:
+# - special-define objects (foo.o[PREPROCSYMBOL]) are not
+# supported in the mac or vcproj makefiles.
+
use FileHandle;
use Cwd;
%programs = (); # maps prog name + type letter to listref of objects/resources
%groups = (); # maps group name to listref of objects/resources
+@allobjs = (); # all object file names
+
while (<IN>) {
# Skip comments (unless the comments belong, for example because
# they're part of a diversion).
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 "!begin") {
if (&mfval($_[1])) {
$divert = \$makefile_extra{$_[1]};
$type = substr($i,1,(length $i)-2);
} else {
push @$listref, $i;
+ push @allobjs, $i;
}
}
if ($prog and $type) {
close IN;
+# Find object file names with predefines (in square brackets after
+# the module name), and decide on actual object names for them.
+foreach $i (@allobjs) {
+ if ($i !~ /\[/) {
+ $objname{$i} = $i;
+ $srcname{$i} = $i;
+ $usedobjname{$i} = 1;
+ }
+}
+foreach $i (@allobjs) {
+ if ($i =~ /^(.*)\[([^\]]*)/) {
+ $defs{$i} = [ split ",",$2 ];
+ $srcname{$i} = $s = $1;
+ $index = 1;
+ while (1) {
+ $maxlen = length $s;
+ $maxlen = 8 if $maxlen < 8;
+ $chop = $maxlen - length $index;
+ $chop = length $s if $chop > length $s;
+ $chop = 0 if $chop < 0;
+ $name = substr($s, 0, $chop) . $index;
+ $index++, next if $usedobjname{$name};
+ $objname{$i} = $name;
+ $usedobjname{$name} = 1;
+ last;
+ }
+ }
+}
+
# 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.
@list = grep { $status = ($prev ne $_); $prev=$_; $status }
sort @{$programs{$i}};
$programs{$i} = [@list];
- foreach $j (@list) {
+ foreach $jj (@list) {
+ $j = $srcname{$jj};
# Dependencies for "x" start with "x.c" or "x.m" (depending on
# which one exists).
# Dependencies for "x.res" start with "x.rc".
# Libraries (.lib) don't have dependencies at all.
if ($j =~ /^(.*)\.res$/) {
$file = "$1.rc";
- $depends{$j} = [$file];
+ $depends{$jj} = [$file];
push @scanlist, $file;
} elsif ($j =~ /^(.*)\.rsrc$/) {
$file = "$1.r";
- $depends{$j} = [$file];
+ $depends{$jj} = [$file];
push @scanlist, $file;
- } elsif ($j =~ /\.lib$/) {
- # libraries don't have dependencies
- } else {
+ } elsif ($j !~ /\./) {
$file = "$j.c";
$file = "$j.m" unless &findfile($file);
- $depends{$j} = [$file];
+ $depends{$jj} = [$file];
push @scanlist, $file;
}
}
my @ret;
my ($i, $x, $y);
@ret = ();
- foreach $i (@{$programs{$prog}}) {
+ foreach $ii (@{$programs{$prog}}) {
+ $i = $objname{$ii};
$x = "";
if ($i =~ /^(.*)\.(res|rsrc)/) {
$y = $1;
} elsif ($i =~ /^(.*)\.lib/) {
$y = $1;
($x = $ltmpl) =~ s/X/$y/;
- } else {
+ } 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);
+ @ret = ();
+ foreach $ii (@{$programs{$prog}}) {
+ $i = $objname{$ii};
+ if (substr($i, (length $i) - (length $suffix)) eq $suffix) {
+ push @ret, $i;
+ }
+ }
+ return join " ", @ret;
+}
+
sub splitline {
my ($line, $width, $splitchar) = @_;
my ($result, $len);
my @deps, @ret;
@ret = ();
$depchar ||= ':';
- foreach $i (sort keys %depends) {
+ foreach $ii (sort keys %depends) {
+ $i = $objname{$ii};
+ next if $specialobj{$mftyp}->{$i};
if ($i =~ /^(.*)\.(res|rsrc)/) {
next if !defined $rtmpl;
$y = $1;
} else {
($x = $otmpl) =~ s/X/$i/;
}
- @deps = @{$depends{$i}};
+ @deps = @{$depends{$ii}};
@deps = map {
$_ = &findfile($_);
s/\//$dirsep/g;
$_ = $prefix . $_;
} @deps;
- push @ret, {obj => $x, deps => [@deps]};
+ push @ret, {obj => $x, deps => [@deps], defs => $defs{$ii}};
}
return @ret;
}
# Now we're ready to output the actual Makefiles.
if (defined $makefiles{'cygwin'}) {
+ $mftyp = 'cygwin';
$dirpfx = &dirpfx($makefiles{'cygwin'}, "/");
##-- CygWin makefile
foreach $d (&deps("X.o", "X.res.o", $dirpfx, "/")) {
print &splitline(sprintf("%s: %s", $d->{obj}, join " ", @{$d->{deps}})),
"\n";
+ if ($d->{obj} =~ /\.res\.o$/) {
+ print "\t\$(RC) \$(FWHACK) \$(RCFL) \$(RCFLAGS) \$< \$\@\n";
+ } else {
+ $deflist = join "", map { " -D$_" } @{$d->{defs}};
+ print "\t\$(CC) \$(COMPAT) \$(FWHACK) \$(XFLAGS)" .
+ " \$(CFLAGS)$deflist -c \$< -o \$\@\n";
+ }
}
print "\n";
print $makefile_extra{'cygwin'};
##-- Borland makefile
if (defined $makefiles{'borland'}) {
+ $mftyp = 'borland';
$dirpfx = &dirpfx($makefiles{'borland'}, "\\");
%stdlibs = ( # Borland provides many Win32 API libraries intrinsically
"!if !\$d(BCB)\n".
"BCB = \$(MAKEDIR)\\..\n".
"!endif\n".
- "\n".
- ".c.obj:\n".
- &splitline("\tbcc32 -w-aus -w-ccc -w-par -w-pia \$(COMPAT) \$(FWHACK)".
- " \$(XFLAGS) \$(CFLAGS) ".
- (join " ", map {"-I$dirpfx$_"} @srcdirs) .
- " /c \$*.c",69)."\n".
- ".rc.res:\n".
- &splitline("\tbrcc32 \$(FWHACK) \$(RCFL) -i \$(BCB)\\include -r".
- " -DNO_WINRESRC_H -DWIN32 -D_WIN32 -DWINVER=0x0401 \$*.rc",69)."\n".
"\n";
print &splitline("all:" . join "", map { " $_.exe" } &progrealnames("G:C"));
print "\n\n";
foreach $d (&deps("X.obj", "X.res", $dirpfx, "\\")) {
print &splitline(sprintf("%s: %s", $d->{obj}, join " ", @{$d->{deps}})),
"\n";
+ if ($d->{obj} =~ /\.res$/) {
+ print &splitline("\tbrcc32 \$(FWHACK) \$(RCFL) " .
+ "-i \$(BCB)\\include -r -DNO_WINRESRC_H -DWIN32".
+ " -D_WIN32 -DWINVER=0x0401 \$*.rc",69)."\n";
+ } else {
+ $deflist = join "", map { " -D$_" } @{$d->{defs}};
+ print &splitline("\tbcc32 -w-aus -w-ccc -w-par -w-pia \$(COMPAT)" .
+ " \$(FWHACK) \$(XFLAGS) \$(CFLAGS)$deflist ".
+ (join " ", map {"-I$dirpfx$_"} @srcdirs) .
+ " /o$d->{obj} /c ".$d->{deps}->[0],69)."\n";
+ }
}
print "\n";
print $makefile_extra{'borland'};
}
if (defined $makefiles{'vc'}) {
+ $mftyp = 'vc';
$dirpfx = &dirpfx($makefiles{'vc'}, "\\");
##-- Visual C++ makefile
"# 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" } &progrealnames("G:C"));
print "\n\n";
foreach $d (&deps("X.obj", "X.res", $dirpfx, "\\")) {
print &splitline(sprintf("%s: %s", $d->{obj}, join " ", @{$d->{deps}})),
"\n";
+ if ($d->{obj} =~ /\.res$/) {
+ print "\trc \$(FWHACK) \$(RCFL) -r -DWIN32 -D_WIN32 ".
+ "-DWINVER=0x0400 ".$d->{deps}->[0]."\n";
+ } else {
+ $deflist = join "", map { " /D$_" } @{$d->{defs}};
+ print "\tcl \$(COMPAT) \$(FWHACK) \$(XFLAGS) \$(CFLAGS)$deflist".
+ " /c ".$d->{deps}->[0]." /Fo$d->{obj}\n";
+ }
}
print "\n";
print $makefile_extra{'vc'};
}
if (defined $makefiles{'vcproj'}) {
+ $mftyp = 'vcproj';
$orig_dir = cwd;
}
if (defined $makefiles{'gtk'}) {
+ $mftyp = 'gtk';
$dirpfx = &dirpfx($makefiles{'gtk'}, "/");
##-- X/GTK/Unix makefile
"# You can define this path to point at your tools if you need to\n".
"# TOOLPATH = /opt/gcc/bin\n".
"CC = \$(TOOLPATH)cc\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'\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 \$\$0 2>/dev/null || gtk-config \$\$0'\n".
"\n".
&splitline("CFLAGS = -O2 -Wall -Werror -g " .
(join " ", map {"-I$dirpfx$_"} @srcdirs) .
- " `gtk-config --cflags`")."\n".
- "XLDFLAGS = `gtk-config --libs`\n".
+ " `\$(GTK_CONFIG) --cflags`")."\n".
+ "XLDFLAGS = `\$(GTK_CONFIG) --libs`\n".
"ULDFLAGS =#\n".
"INSTALL=install\n",
"INSTALL_PROGRAM=\$(INSTALL)\n",
"prefix=/usr/local\n",
"exec_prefix=\$(prefix)\n",
"bindir=\$(exec_prefix)/bin\n",
+ "gamesdir=\$(exec_prefix)/games\n",
"mandir=\$(prefix)/man\n",
"man1dir=\$(mandir)/man1\n",
- "\n".
- ".SUFFIXES:\n".
- "\n".
- "%.o:\n".
- "\t\$(CC) \$(COMPAT) \$(FWHACK) \$(XFLAGS) \$(CFLAGS) -c \$<\n".
"\n";
print &splitline("all:" . join "", map { " $_" } &progrealnames("X:U"));
print "\n\n";
foreach $d (&deps("X.o", undef, $dirpfx, "/")) {
print &splitline(sprintf("%s: %s", $d->{obj}, join " ", @{$d->{deps}})),
"\n";
+ $deflist = join "", map { " -D$_" } @{$d->{defs}};
+ print "\t\$(CC) \$(COMPAT) \$(FWHACK) \$(XFLAGS) \$(CFLAGS)$deflist" .
+ " -c \$< -o \$\@\n";
}
print "\n";
print $makefile_extra{'gtk'};
}
if (defined $makefiles{'mpw'}) {
+ $mftyp = 'mpw';
##-- MPW Makefile
open OUT, ">$makefiles{'mpw'}"; select OUT;
print
}
if (defined $makefiles{'lcc'}) {
+ $mftyp = 'lcc';
$dirpfx = &dirpfx($makefiles{'lcc'}, "\\");
##-- lcc makefile
"\n".
"\n".
"# Get include directory for resource compiler\n".
- "\n".
- ".c.obj:\n".
- &splitline("\tlcc -O -p6 \$(COMPAT) \$(FWHACK)".
- " \$(XFLAGS) \$(CFLAGS) \$*.c",69)."\n".
- ".rc.res:\n".
- &splitline("\tlrc \$(FWHACK) \$(RCFL) -r \$*.rc",69)."\n".
"\n";
print &splitline("all:" . join "", map { " $_.exe" } &progrealnames("G:C"));
print "\n\n";
foreach $d (&deps("X.obj", "X.res", $dirpfx, "\\")) {
print &splitline(sprintf("%s: %s", $d->{obj}, join " ", @{$d->{deps}})),
"\n";
+ if ($d->{obj} =~ /\.res$/) {
+ print &splitline("\tlrc \$(FWHACK) \$(RCFL) -r \$*.rc",69)."\n";
+ } else {
+ $deflist = join "", map { " -D$_" } @{$d->{defs}};
+ print &splitline("\tlcc -O -p6 \$(COMPAT) \$(FWHACK) \$(XFLAGS)".
+ " \$(CFLAGS)$deflist ".$d->{deps}->[0]." -o \$\@",69)."\n";
+ }
}
print "\n";
print $makefile_extra{'lcc'};
}
if (defined $makefiles{'osx'}) {
+ $mftyp = 'osx';
$dirpfx = &dirpfx($makefiles{'osx'}, "/");
##-- Mac OS X makefile
print
"CC = \$(TOOLPATH)gcc\n".
"\n".
- &splitline("CFLAGS = -O2 -Wall -Werror -g -DMAC_OS_X " .
+ &splitline("CFLAGS = -O2 -Wall -Werror -g " .
(join " ", map {"-I$dirpfx$_"} @srcdirs))."\n".
"LDFLAGS = -framework Cocoa\n".
+ &splitline("all:" . join "", map { " $_" } &progrealnames("MX:U")) .
+ "\n" .
+ $makefile_extra{'osx'} .
"\n".
".SUFFIXES: .o .c .m\n".
- "\n".
- ".c.o:\n".
- "\t\$(CC) \$(COMPAT) \$(FWHACK) \$(XFLAGS) \$(CFLAGS) -c \$<\n".
- ".m.o:\n".
- "\t\$(CC) -x objective-c \$(COMPAT) \$(FWHACK) \$(XFLAGS) \$(CFLAGS) -c \$<\n".
"\n";
- print &splitline("all:" . join "", map { " $_" } &progrealnames("MX"));
print "\n\n";
foreach $p (&prognames("MX")) {
($prog, $type) = split ",", $p;
$objstr = &objects($p, "X.o", undef, undef);
- print "${prog}: ${prog}.app/Contents/MacOS/$prog\n\n";
- print "${prog}.app:\n\tmkdir \$\@\n";
- print "${prog}.app/Contents: ${prog}.app\n\tmkdir \$\@\n";
- print "${prog}.app/Contents/MacOS: ${prog}.app/Contents\n\tmkdir \$\@\n";
+ $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)" . $mw . " \$(LDFLAGS) -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)" . $mw . " \$(ULDFLAGS) -o \$@ " .
+ $objstr . " $libstr", 69), "\n\n";
+ }
foreach $d (&deps("X.o", undef, $dirpfx, "/")) {
print &splitline(sprintf("%s: %s", $d->{obj}, join " ", @{$d->{deps}})),
"\n";
+ $deflist = join "", map { " -D$_" } @{$d->{defs}};
+ if ($d->{deps}->[0] =~ /\.m$/) {
+ print "\t\$(CC) -x objective-c \$(COMPAT) \$(FWHACK) \$(XFLAGS)".
+ " \$(CFLAGS)$deflist -c \$< -o \$\@\n";
+ } else {
+ print "\t\$(CC) \$(COMPAT) \$(FWHACK) \$(XFLAGS) \$(CFLAGS)$deflist" .
+ " -c \$< -o \$\@\n";
+ }
}
- print "\n";
- print $makefile_extra{'osx'};
print "\nclean:\n".
- "\trm -f *.o\n".
+ "\trm -f *.o *.dmg". (join "", map { " $_" } &progrealnames("U")) . "\n".
"\trm -rf *.app\n";
select STDOUT; close OUT;
}