mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 09:27:59 +00:00
6593009b0e
This is for sanitising output that's going to be sent to a terminal, if you don't want it to be able to send arbitrary escape sequences and thereby (for example) move the cursor back up to existing text on the screen and overprint it confusingly. It works using the standard C library: we convert to a wide-character string and back, and then use wctype.h to spot control characters in the intermediate form. This means its idea of the conversion character set is locale-based rather than any of our own charset library's fixed settings - which is what you want if the aim is to protect your local terminal (which we assume the system locale represents accurately). This also means that the sanitiser strips things that will _act_ as control characters when sent to the local terminal, whether or not they were intended as control characters by a server that might have had a different character set in mind. Since the main aim is to protect the local terminal rather than to faithfully replicate the server's intention, I think that's the right criterion. It only strips control characters at the charset-independent layer, like backspace, carriage return and the escape character: wctype.h classifies those as control characters, but classifies as printing all of the more Unicode-specific controls like bidirectional overrides. But that's enough to prevent cursor repositioning, for example. stripctrl.c comes with a test main() of its own, which I wasn't able to fold into testcrypt and put in the test suite because of its dependence on the system locale - it wouldn't be guaranteed to work the same way on different test systems anyway. A knock-on build tweak: because you can feed data into this sanitiser in chunks of arbitrary size, including partial multibyte chars, I had to use mbrtowc() for the decoding, and that means that in the 'old' Win32 builds I have to link against the Visual Studio C++ library as well as the C library, because for some reason that's where mbrtowc lived in VS2003.
2093 lines
82 KiB
Perl
Executable File
2093 lines
82 KiB
Perl
Executable File
#!/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, and licence.h is likewise generated by licence.pl. We
|
|
# need to generate those _now_, before attempting dependency analysis.
|
|
eval 'chdir "charset"; require "./sbcsgen.pl"; chdir ".."; select STDOUT;';
|
|
eval 'require "./licence.pl"; 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
|
|
if ($rest eq "") {
|
|
# Make sure this file doesn't get lumped together with any
|
|
# other file's cflags.
|
|
$rest = "F" . $_[2];
|
|
} else {
|
|
# Give this file a specific set of cflags, but permit it to
|
|
# go together with other files using the same set.
|
|
$rest = "C" . $rest;
|
|
}
|
|
$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 && $_[1] eq "=") {
|
|
$groups{$_[0]} = [] if !defined $groups{$_[0]};
|
|
$listref = $groups{$_[0]};
|
|
$prog = undef;
|
|
shift @objs; # eat the group name
|
|
} elsif ($#_ >= 1 && $_[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 =~ /^\[([A-Z]*)\]$/) and defined $prog) {
|
|
$type = substr($i,1,(length $i)-2);
|
|
die "unrecognised program type for $prog [$type]\n"
|
|
if ! grep { $type eq $_ } qw(G C X U MX XT UT);
|
|
} 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","lcc","devcppproj","gtk","unix",
|
|
"am","osx","vstudio10","vstudio12","clangcl")) {
|
|
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{'clangcl'}) {
|
|
$dirpfx = &dirpfx($makefiles{'clangcl'}, "/");
|
|
|
|
##-- Makefile for cross-compiling using clang-cl, lld-link, and
|
|
## MinGW's windres for resource compilation.
|
|
#
|
|
# This makefile allows a complete Linux-based cross-compile, but
|
|
# using the real Visual Studio header files and libraries. In
|
|
# order to run it, you will need:
|
|
#
|
|
# - clang-cl, llvm-rc and lld-link on your PATH.
|
|
# * I built these from the up-to-date LLVM project trunk git
|
|
# repositories, as of 2018-05-29.
|
|
# - case-mashed copies of the Visual Studio include directories.
|
|
# * On a real VS installation, run vcvars32.bat and look at
|
|
# the resulting value of %INCLUDE%. Take a full copy of each
|
|
# of those directories, and inside the copy, for each
|
|
# include file that has an uppercase letter in its name,
|
|
# make a lowercased symlink to it. Additionally, one of the
|
|
# directories will contain files called driverspecs.h and
|
|
# specstrings.h, and those will need symlinks called
|
|
# DriverSpecs.h and SpecStrings.h.
|
|
# * Now, on Linux, define the environment variable INCLUDE to
|
|
# be a list, separated by *semicolons* (in the Windows
|
|
# style), of those directories, but before all of them you
|
|
# must also include lib/clang/5.0.0/include from the clang
|
|
# installation area (which contains in particular a
|
|
# clang-compatible stdarg.h overriding the Visual Studio
|
|
# one).
|
|
# - similarly case-mashed copies of the library directories.
|
|
# * Again, on a real VS installation, run vcvars32 or
|
|
# vcvarsx86_amd64 (as appropriate), look at %LIB%, make a
|
|
# copy of each directory, and provide symlinks within that
|
|
# directory so that all the files can be opened as
|
|
# lowercase.
|
|
# * Then set LIB to be a semicolon-separated list of those
|
|
# directories (but you'll need to change which set of
|
|
# directories depending on whether you want to do a 32-bit
|
|
# or 64-bit build).
|
|
# - for a 64-bit build, set 'Platform=x64' in the environment as
|
|
# well, or else on the make command line.
|
|
# * This is a variable understood only by this makefile - none
|
|
# of the tools we invoke will know it - but it's consistent
|
|
# with the way the VS scripts like vcvarsx86_amd64.bat set
|
|
# things up, and since the environment has to change
|
|
# _anyway_ between 32- and 64-bit builds (different set of
|
|
# paths in $LIB) it's reasonable to have the choice of
|
|
# compilation target driven by another environment variable
|
|
# set in parallel with that one.
|
|
# - for older versions of the VS libraries you may also have to
|
|
# set EXTRA_console and/or EXTRA_windows to the name of an
|
|
# object file manually extracted from one of those libraries.
|
|
# * This is because old VS seems to manage its startup code by
|
|
# having libcmt.lib contain lots of *crt0.obj objects, one
|
|
# for each possible user entry point (main, WinMain and the
|
|
# wide-char versions of both), of which the linker arranges
|
|
# to include the right one by special-case code. But lld
|
|
# only seems to mimic half of that code - it does include
|
|
# the right crt0 object, but it doesn't also deliberately
|
|
# _avoid_ including the _wrong_ ones, and since all those
|
|
# objects define a common set of global symbols for other
|
|
# parts of the library to use, lld may well select an
|
|
# arbitrary one of them the first time it sees a reference
|
|
# to one of those global symbols, and then later also select
|
|
# the _right_ one for the application's entry point, causing
|
|
# a multiple-definitions crash.
|
|
# * So the workaround is to explicitly include the right
|
|
# *crt0.obj file on the linker command line before lld even
|
|
# begins searching libraries. Hence, for a console
|
|
# application, you might extract crt0.obj from the library
|
|
# in question and set EXTRA_console=crt0.obj, and for a GUI
|
|
# application, do the same with wincrt0.obj. Then this
|
|
# makefile will include the right one of those objects
|
|
# alongside the matching /subsystem linker option.
|
|
# - also for older versions of the VS libraries, you may also
|
|
# have to set EXTRA_libs to include extra library files.
|
|
|
|
open OUT, ">$makefiles{'clangcl'}"; select OUT;
|
|
print
|
|
"# Makefile for cross-compiling $project_name using clang-cl, lld-link,\n".
|
|
"# and llvm-rc, using GNU make on Linux.\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".
|
|
"CCCMD = clang-cl\n".
|
|
"RCCMD = llvm-rc\n".
|
|
"ifeq (\$(Platform),x64)\n".
|
|
"CCTARGET = x86_64-pc-windows-msvc18.0.0\n".
|
|
"PLATFORMCFLAGS =\n".
|
|
"else ifeq (\$(Platform),arm)\n".
|
|
"CCTARGET = arm-pc-windows-msvc18.0.0\n".
|
|
"PLATFORMCFLAGS = /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE /GS-\n".
|
|
"else ifeq (\$(Platform),arm64)\n".
|
|
"CCTARGET = arm64-pc-windows-msvc18.0.0\n".
|
|
"PLATFORMCFLAGS = /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE /GS-\n".
|
|
"else\n".
|
|
"CCTARGET = i386-pc-windows-msvc18.0.0\n".
|
|
"PLATFORMCFLAGS =\n".
|
|
"endif\n".
|
|
"CC = \$(CCCMD)\n".
|
|
"RC = \$(RCCMD) /c 1252 \n".
|
|
"RCPREPROC = \$(CCCMD) /P /TC\n".
|
|
"LD = lld-link\n".
|
|
"\n".
|
|
"# C compilation flags\n".
|
|
&splitline("CFLAGS = --target=\$(CCTARGET) /nologo /W3 /O1 -Wvla " .
|
|
(join " ", map {"-I$dirpfx$_"} @srcdirs) .
|
|
" /D_WINDOWS /D_WIN32_WINDOWS=0x500 /DWINVER=0x500 ".
|
|
"/D_CRT_SECURE_NO_WARNINGS /D_WINSOCK_DEPRECATED_NO_WARNINGS").
|
|
" \$(PLATFORMCFLAGS)\n".
|
|
"LFLAGS = /incremental:no /dynamicbase /nxcompat\n".
|
|
&splitline("RCPPFLAGS = ".(join " ", map {"-I$dirpfx$_"} @srcdirs).
|
|
" -DWIN32 -D_WIN32 -DWINVER=0x0400")." \$(RCFL)\n".
|
|
"\n".
|
|
&def($makefile_extra{'clangcl'}->{'vars'}) .
|
|
"\n".
|
|
"\n";
|
|
print &splitline("all:" . join "", map { " \$(BUILDDIR)$_.exe" } &progrealnames("G:C"));
|
|
print "\n\n";
|
|
foreach $p (&prognames("G:C")) {
|
|
($prog, $type) = split ",", $p;
|
|
$objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", undef);
|
|
print &splitline("\$(BUILDDIR)$prog.exe: " . $objstr), "\n";
|
|
|
|
$objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", "X.lib");
|
|
$subsys = ($type eq "G") ? "windows" : "console";
|
|
print &splitline("\t\$(LD) \$(LFLAGS) \$(XLFLAGS) ".
|
|
"/out:\$(BUILDDIR)$prog.exe ".
|
|
"/lldmap:\$(BUILDDIR)$prog.map ".
|
|
"/subsystem:$subsys\$(SUBSYSVER) ".
|
|
"\$(EXTRA_$subsys) $objstr \$(EXTRA_libs)")."\n\n";
|
|
}
|
|
my $rc_pp_rules = "";
|
|
foreach $d (&deps("\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", $dirpfx, "/", "vc")) {
|
|
$extradeps = $forceobj{$d->{obj_orig}} ? ["*.c","*.h","*.rc"] : [];
|
|
my $rule;
|
|
my @deps = @{$d->{deps}};
|
|
my @incdeps = grep { m!\.rc2?$! } @deps;
|
|
my @rcdeps = grep { ! m!\.rc2$! } @deps;
|
|
if ($d->{obj} =~ /\.res$/) {
|
|
my $rc = $deps[0];
|
|
my $rcpp = $rc;
|
|
$rcpp =~ s!.*/!!;
|
|
$rcpp =~ s/\.rc$/.rcpp/;
|
|
$rcpp = "\$(BUILDDIR)" . $rcpp;
|
|
$rule = "\$(RC) ".$rcpp." /FO ".$d->{obj};
|
|
$rc_pp_rules .= &splitline(
|
|
sprintf("%s: %s", $rcpp, join " ", @incdeps)) ."\n" .
|
|
"\t\$(RCPREPROC) \$(RCPPFLAGS) /Fi\$\@ \$<\n\n";
|
|
$rcdeps[0] = $rcpp;
|
|
} else {
|
|
$rule = "\$(CC) /Fo\$(BUILDDIR) \$(COMPAT) \$(CFLAGS) \$(XFLAGS) /c \$<";
|
|
}
|
|
print &splitline(sprintf("%s: %s", $d->{obj},
|
|
join " ", @$extradeps, @rcdeps)), "\n";
|
|
print "\t" . $rule . "\n\n";
|
|
}
|
|
print "\n" . $rc_pp_rules;
|
|
print &def($makefile_extra{'clangcl'}->{'end'});
|
|
print "\nclean:\n".
|
|
&splitline("\trm -f \$(BUILDDIR)*.obj \$(BUILDDIR)*.exe ".
|
|
"\$(BUILDDIR)*.res \$(BUILDDIR)*.map ".
|
|
"\$(BUILDDIR)*.exe.manifest")."\n";
|
|
select STDOUT; close OUT;
|
|
}
|
|
|
|
if (defined $makefiles{'cygwin'}) {
|
|
$dirpfx = &dirpfx($makefiles{'cygwin'}, "/");
|
|
|
|
##-- MinGW/CygWin makefile (called 'cygwin' for historical reasons)
|
|
open OUT, ">$makefiles{'cygwin'}"; select OUT;
|
|
print
|
|
"# Makefile for $project_name under MinGW, Cygwin, 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".
|
|
"# TOOLPATH = i686-w64-mingw32-\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 = -Wall -O2 -std=gnu99 -Wvla -D_WINDOWS".
|
|
" -DWIN32S_COMPAT -D_NO_OLDNAMES -D__USE_MINGW_ANSI_STDIO=1 " .
|
|
(join " ", map {"-I$dirpfx$_"} @srcdirs)) .
|
|
"\n".
|
|
"LDFLAGS = -s\n".
|
|
&splitline("RCFLAGS = \$(RCINC) --define WIN32=1 --define _WIN32=1 ".
|
|
"--define WINVER=0x0400 ".(join " ", map {"-I$dirpfx$_"} @srcdirs))."\n".
|
|
"\n".
|
|
&def($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 &def($makefile_extra{'cygwin'}->{'end'});
|
|
print "\nclean:\n".
|
|
"\trm -f *.o *.exe *.res.o *.so *.map\n".
|
|
"\n".
|
|
"FORCE:\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 /D_CRT_SECURE_NO_WARNINGS /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE\n".
|
|
"LFLAGS = /incremental:no /dynamicbase /nxcompat\n".
|
|
"RCFLAGS = ".(join " ", map {"-I$dirpfx$_"} @srcdirs).
|
|
" -DWIN32 -D_WIN32 -DWINVER=0x0400\n".
|
|
"\n".
|
|
&def($makefile_extra{'vc'}->{'vars'}) .
|
|
"\n".
|
|
"\n";
|
|
print &splitline("all:" . join "", map { " \$(BUILDDIR)$_.exe" } &progrealnames("G:C"));
|
|
print "\n\n";
|
|
foreach $p (&prognames("G:C")) {
|
|
($prog, $type) = split ",", $p;
|
|
$objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", undef);
|
|
print &splitline("\$(BUILDDIR)$prog.exe: " . $objstr), "\n";
|
|
|
|
$objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", "X.lib");
|
|
$subsys = ($type eq "G") ? "windows" : "console";
|
|
$inlinefilename = "link_$prog";
|
|
print "\ttype <<$inlinefilename\n";
|
|
@objlist = split " ", $objstr;
|
|
@objlines = ("");
|
|
foreach $i (@objlist) {
|
|
if (length($objlines[$#objlines] . " $i") > 72) {
|
|
push @objlines, "";
|
|
}
|
|
$objlines[$#objlines] .= " $i";
|
|
}
|
|
for ($i=0; $i<=$#objlines; $i++) {
|
|
print "$objlines[$i]\n";
|
|
}
|
|
print "<<\n";
|
|
print "\tlink \$(LFLAGS) \$(XLFLAGS) -out:\$(BUILDDIR)$prog.exe -map:\$(BUILDDIR)$prog.map -nologo -subsystem:$subsys\$(SUBSYSVER) \@$inlinefilename\n\n";
|
|
}
|
|
foreach $d (&deps("\$(BUILDDIR)X.obj", "\$(BUILDDIR)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} =~ /.res$/) {
|
|
print "\trc /Fo@{[$d->{obj}]} \$(RCFL) -r \$(RCFLAGS) ".$d->{deps}->[0],"\n\n";
|
|
}
|
|
}
|
|
print "\n";
|
|
foreach $real_srcdir ("", @srcdirs) {
|
|
$srcdir = $real_srcdir;
|
|
if ($srcdir ne "") {
|
|
$srcdir =~ s!/!\\!g;
|
|
$srcdir = $dirpfx . $srcdir;
|
|
$srcdir =~ s!\\\.\\!\\!;
|
|
$srcdir = "{$srcdir}";
|
|
}
|
|
# The double colon at the end of the line makes this a
|
|
# 'batch-mode inference rule', which means that nmake will
|
|
# aggregate multiple invocations of the rule and issue just
|
|
# one cl command with multiple source-file arguments. That
|
|
# noticeably speeds up builds, since starting up the cl
|
|
# process is a noticeable overhead and now has to be done far
|
|
# fewer times.
|
|
print "${srcdir}.c.obj::\n\tcl /Fo\$(BUILDDIR) \$(COMPAT) \$(CFLAGS) \$(XFLAGS) /c \$<\n\n";
|
|
}
|
|
print &def($makefile_extra{'vc'}->{'end'});
|
|
print "\nclean: tidy\n".
|
|
"\t-del \$(BUILDDIR)*.exe\n\n".
|
|
"tidy:\n".
|
|
"\t-del \$(BUILDDIR)*.obj\n".
|
|
"\t-del \$(BUILDDIR)*.res\n".
|
|
"\t-del \$(BUILDDIR)*.pch\n".
|
|
"\t-del \$(BUILDDIR)*.aps\n".
|
|
"\t-del \$(BUILDDIR)*.ilk\n".
|
|
"\t-del \$(BUILDDIR)*.pdb\n".
|
|
"\t-del \$(BUILDDIR)*.rsp\n".
|
|
"\t-del \$(BUILDDIR)*.dsp\n".
|
|
"\t-del \$(BUILDDIR)*.dsw\n".
|
|
"\t-del \$(BUILDDIR)*.ncb\n".
|
|
"\t-del \$(BUILDDIR)*.opt\n".
|
|
"\t-del \$(BUILDDIR)*.plg\n".
|
|
"\t-del \$(BUILDDIR)*.map\n".
|
|
"\t-del \$(BUILDDIR)*.idb\n".
|
|
"\t-del \$(BUILDDIR)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+-3.0 x11 \$\$0 2>/dev/null || 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 -std=gnu99 -Wvla -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:XT:U:UT"));
|
|
print "\n\n";
|
|
foreach $p (&prognames("X:XT:U:UT")) {
|
|
($prog, $type) = split ",", $p;
|
|
($ldflags = $type) =~ s/T$//;
|
|
$objstr = &objects($p, "X.o", undef, undef);
|
|
print &splitline($prog . ": " . $objstr), "\n";
|
|
$libstr = &objects($p, undef, undef, "-lX");
|
|
print &splitline("\t\$(CC) -o \$@ " .
|
|
$objstr . " \$(${ldflags}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 &def($makefile_extra{'gtk'}->{'end'});
|
|
print "\nclean:\n".
|
|
"\trm -f *.o". (join "", map { " $_" } &progrealnames("X:XT:U:UT")) . "\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 -std=gnu99 -Wvla -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:UT"));
|
|
print "\n\n";
|
|
foreach $p (&prognames("U:UT")) {
|
|
($prog, $type) = split ",", $p;
|
|
($ldflags = $type) =~ s/T$//;
|
|
$objstr = &objects($p, "X.o", undef, undef);
|
|
print &splitline($prog . ": " . $objstr), "\n";
|
|
$libstr = &objects($p, undef, undef, "-lX");
|
|
print &splitline("\t\$(CC) -o \$@ " .
|
|
$objstr . " \$(${ldflags}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:UT")) . "\n";
|
|
print "\nFORCE:\n";
|
|
select STDOUT; close OUT;
|
|
}
|
|
|
|
if (defined $makefiles{'am'}) {
|
|
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.
|
|
@sources = ("allsources", "=",
|
|
sort grep {$_ ne "empty.h"} 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";
|
|
|
|
@noinstcliprogs = ("noinst_PROGRAMS", "=");
|
|
foreach $p (&prognames("UT")) {
|
|
($prog, $type) = split ",", $p;
|
|
push @noinstcliprogs, $prog;
|
|
}
|
|
@noinstallprogs = @noinstcliprogs;
|
|
foreach $p (&prognames("XT")) {
|
|
($prog, $type) = split ",", $p;
|
|
push @noinstallprogs, $prog;
|
|
}
|
|
print "if HAVE_GTK\n";
|
|
print &splitline(join " ", @noinstallprogs), "\n";
|
|
print "else\n";
|
|
print &splitline(join " ", @noinstcliprogs), "\n";
|
|
print "endif\n\n";
|
|
|
|
%objtosrc = ();
|
|
foreach $d (&deps("X", undef, "", "/", "am")) {
|
|
$objtosrc{$d->{obj}} = $d->{deps}->[0];
|
|
}
|
|
|
|
print &splitline(join " ", "AM_CPPFLAGS", "=",
|
|
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'}}) {
|
|
my $flags = $cflags{'am'}->{$obj};
|
|
$flags = "" if $flags !~ s/^C//;
|
|
print "lib${obj}_a_SOURCES = ", $objtosrc{$obj}, "\n";
|
|
print &splitline(join " ", "lib${obj}_a_CFLAGS", "=", @amcflags,
|
|
$flags), "\n";
|
|
$amspeciallibs{$obj} = "lib${obj}.a";
|
|
}
|
|
print &splitline(join " ", "noinst_LIBRARIES", "=",
|
|
sort { $a cmp $b } values %amspeciallibs), "\n\n";
|
|
|
|
foreach $p (&prognames("X:XT:U:UT")) {
|
|
($prog, $type) = split ",", $p;
|
|
print "if HAVE_GTK\n" if $type eq "X" || $type eq "XT";
|
|
@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" || $type eq "XT") {
|
|
push @ldadd, "\$(GTK_LIBS)";
|
|
}
|
|
if (@ldadd) {
|
|
print &splitline(join " ", "${prog}_LDADD", "=", @ldadd), "\n";
|
|
}
|
|
print "endif\n" if $type eq "X" || $type eq "XT";
|
|
print "\n";
|
|
}
|
|
print &def($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".
|
|
&def($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 &def($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 -std=gnu99 -Wvla -g " .
|
|
(join " ", map {"-I$dirpfx$_"} @srcdirs))."\n".
|
|
"MLDFLAGS = -framework Cocoa\n".
|
|
"ULDFLAGS =\n".
|
|
"\n" .
|
|
&def($makefile_extra{'osx'}->{'vars'}) .
|
|
"\n" .
|
|
&splitline("all:" . join "", map { " $_" } &progrealnames("MX:U:UT")) .
|
|
"\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:UT")) {
|
|
($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:UT")) . "\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 multiple 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) {
|
|
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));
|
|
}
|