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

Switch to using automake for the Unix autoconfigured build.

mkfiles.pl no longer generates a Makefile.in, but instead generates a
Makefile.am on which mkauto.sh runs automake. This means that the
autoconfigured makefile now does build-time dependency tracking (a
standard feature of automake-generated makefiles), and is generally
more like what Unix people will expect.

Some of the old-style make command-line settings (VER=-DRELEASE=foo,
XFLAGS=-DDEBUG) will still work; the COMPAT settings are better done
by autoconfiguration, and my habitual 'XFLAGS="-g -O0"' for an easily
debuggable build will actually not work any more because CFLAGS is
specified _after_ XFLAGS, so I should instead write 'make CFLAGS=-O0'
(-g is the default in automake, removed at 'make install' time).

The new makefile will automatically degrade into one that builds the
command-line tools only, in the case where GTK could not be found. In
principle, therefore, it should be an adequate replacement for _both_
the static Unix makefiles, Makefile.gtk and Makefile.ux. I haven't
actually retired those in this commit, but I'm pretty tempted.

[originally from svn r9239]
This commit is contained in:
Simon Tatham 2011-07-23 11:33:29 +00:00
parent 860cd79efd
commit 64150a5ef2
7 changed files with 211 additions and 125 deletions

32
README
View File

@ -80,22 +80,38 @@ For building on Unix:
utilities and has no Gtk dependence.
- For the graphical utilities, Gtk+-1.2 and Gtk+-2.0 should both be
supported.
supported. In the absence of either, the configure script will
automatically construct a Makefile which builds only the
command-line utilities.
- Both Unix Makefiles have an `install' target. Note that by default
it tries to install `man' pages, which you may need to have built
using Halibut first -- see below.
- pterm would like to be setuid or setgid, as appropriate, to permit
it to write records of user logins to /var/run/utmp and
/var/log/wtmp. (Of course it will not use this privilege for
anything else, and in particular it will drop all privileges before
starting up complex subsystems like GTK.) By default the makefile
will not attempt to add privileges to the pterm executable at 'make
install' time, but you can ask it to do so by running configure
with the option '--enable-setuid=USER' or '--enable-setgid=GROUP'.
- The Unix Makefiles have an `install' target. Note that by default
it tries to install `man' pages; if you have fetched the source via
Subversion then you will need to have built these using Halibut
first - see below.
All of the Makefiles are generated automatically from the file
`Recipe' by the Perl script `mkfiles.pl'. Additions and corrections
to Recipe and the mkfiles.pl are much more useful than additions and
corrections to the alternative Makefiles themselves.
`Recipe' by the Perl script `mkfiles.pl' (except for the Unix one,
which is generated by the `configure' script; mkfiles.pl only
generates the input to automake). Additions and corrections to Recipe,
mkfiles.pl and/or configure.ac are much more useful than additions and
corrections to the actual Makefiles, Makefile.am or Makefile.in.
The Unix `configure' script and its various requirements are generated
by the shell script `mkauto.sh', which requires GNU Autoconf, GNU
Automake, and Gtk; if you've got the source from Subversion rather
than using one of our source snapshots, you'll need to run this
yourself.
yourself. The input file to Automake is generated by mkfiles.pl along
with all the rest of the makefiles, so you will need to run mkfiles.pl
and then mkauto.sh.
Documentation (in various formats including Windows Help and Unix
`man' pages) is built from the Halibut (`.but') files in the `doc'

30
Recipe
View File

@ -19,7 +19,7 @@
!makefile lcc windows/Makefile.lcc
!makefile gtk unix/Makefile.gtk
!makefile unix unix/Makefile.ux
!makefile ac unix/Makefile.in
!makefile am unix/Makefile.am
!makefile osx macosx/Makefile
!makefile devcppproj windows/DEVCPP
# Source directories.
@ -169,6 +169,19 @@ version.o: FORCE
fi
!end
!specialobj gtk version
# In the automake build, we have to do the whole job by supplying
# extra CFLAGS, so we have to put the if statement inside one big
# backtick expression. We also force rebuilding via a -D option that
# makes version.o include empty.h, which we construct ourselves and
# touch whenever any source file is updated.
!cflags am version $(VER) -DINCLUDE_EMPTY_H `if test -z "$(VER)" && (cd $(srcdir)/..; md5sum -c manifest >/dev/null 2>&1); then cat $(srcdir)/../version.def; else echo "$(VER)"; fi`
!begin am
BUILT_SOURCES = empty.h
CLEANFILES = empty.h
empty.h: $(allsources)
echo '/* nothing to see here */' >$@
!end
# Add VER to Windows resource targets, and force them to be rebuilt every
# time, on the assumption that they will contain version information.
@ -228,6 +241,21 @@ install-strip:
CFLAGS += -DMACOSX
!end
# List the man pages for the automake makefile.
!begin am
man1_MANS = ../doc/plink.1 ../doc/pscp.1 ../doc/psftp.1 ../doc/pterm.1 \
../doc/putty.1 ../doc/puttygen.1 ../doc/puttytel.1
!end
# In automake, chgrp/chmod pterm after installation, if configured to.
!begin am
if HAVE_SETID_CMD
install-exec-local:
@SETID_CMD@ $(bindir)/pterm
chmod @SETID_MODE@ $(bindir)/pterm
endif
!end
# Random symbols.
!begin cygwin vars
# _WIN32_IE is required to expose identifiers that only make sense on

View File

@ -7,41 +7,5 @@
# well as from outside.
test -f unix.h && cd ..
# Persuade automake to give us a copy of its install-sh. This is a
# pain because I don't actually want to have to _use_ automake.
# Instead, I construct a trivial unrelated automake project in a
# temporary subdirectory, run automake so that it'll copy
# install-sh into that directory, then copy it back out again.
# Hideous, but it should work.
mkdir automake-grievous-hack
cat > automake-grievous-hack/hello.c << EOF
#include <stdio.h>
int main(int argc, char **argv)
{
printf("hello, world\n");
return 0;
}
EOF
cat > automake-grievous-hack/Makefile.am << EOF
bin_PROGRAMS = hello
hello_SOURCES = hello.c
EOF
cat > automake-grievous-hack/configure.ac << EOF
AC_INIT
AM_INIT_AUTOMAKE(hello, 1.0)
AC_CONFIG_FILES([Makefile])
AC_PROG_CC
AC_OUTPUT
EOF
echo Some news > automake-grievous-hack/NEWS
echo Some text > automake-grievous-hack/README
echo Some people > automake-grievous-hack/AUTHORS
echo Some changes > automake-grievous-hack/ChangeLog
rm -f install-sh # this won't work if we accidentally have one _here_
(cd automake-grievous-hack && autoreconf -i && \
cp install-sh ../unix/install-sh)
rm -rf automake-grievous-hack
# That was the hard bit. Now run autoconf on our real configure.in.
(cd unix && autoreconf && rm -rf aclocal.m4 autom4te.cache)
# Run autoconf on our real configure.in.
(cd unix && autoreconf -i && rm -rf autom4te.cache)

View File

@ -64,6 +64,12 @@ while (<IN>) {
if ($_[0] eq "!srcdir") { push @srcdirs, $_[1]; next; }
if ($_[0] eq "!makefile" and &mfval($_[1])) { $makefiles{$_[1]}=$_[2]; next;}
if ($_[0] eq "!specialobj" and &mfval($_[1])) { $specialobj{$_[1]}->{$_[2]} = 1; next;}
if ($_[0] eq "!cflags" and &mfval($_[1])) {
($rest = $_) =~ s/^\s*\S+\s+\S+\s+\S+\s*//; # find rest of input line
$rest = 1 if $rest eq "";
$cflags{$_[1]}->{$_[2]} = $rest;
next;
}
if ($_[0] eq "!forceobj") { $forceobj{$_[1]} = 1; next; }
if ($_[0] eq "!begin") {
if (&mfval($_[1])) {
@ -177,11 +183,13 @@ foreach $i (@prognames) {
# 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;
@ -226,7 +234,7 @@ sub mfval($) {
# prints a warning and returns false;
if (grep { $type eq $_ }
("vc","vcproj","cygwin","borland","lcc","devcppproj","gtk","unix",
"ac","osx",)) {
"am","osx",)) {
return 1;
}
warn "$.:unknown makefile type '$type'\n";
@ -1084,71 +1092,89 @@ if (defined $makefiles{'unix'}) {
select STDOUT; close OUT;
}
if (defined $makefiles{'ac'}) {
$dirpfx = &dirpfx($makefiles{'ac'}, "/");
if (defined $makefiles{'am'}) {
$dirpfx = "\$(srcdir)/" . &dirpfx($makefiles{'am'}, "/");
##-- Unix/autoconf makefile
open OUT, ">$makefiles{'ac'}"; select OUT;
##-- Unix/autoconf Makefile.am
open OUT, ">$makefiles{'am'}"; select OUT;
print
"# Makefile.in for $project_name under Unix with Autoconf.\n".
"# 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";
# gcc command line option is -D not /D
($_ = $help) =~ s/([=" ])\/D/$1-D/gs;
print $_;
print
"\n".
"CC = \@CC\@\n".
"\n".
&splitline("CFLAGS = \@CFLAGS\@ \@PUTTYCFLAGS\@ \@CPPFLAGS\@ " .
"\@DEFS\@ \@GTK_CFLAGS\@ " .
(join " ", map {"-I$dirpfx$_"} @srcdirs))."\n".
"XLDFLAGS = \@LDFLAGS\@ \@LIBS\@ \@GTK_LIBS\@\n".
"ULDFLAGS = \@LDFLAGS\@ \@LIBS\@\n".
"INSTALL=\@INSTALL\@\n".
"INSTALL_PROGRAM=\$(INSTALL)\n".
"INSTALL_DATA=\$(INSTALL)\n".
"prefix=\@prefix\@\n".
"exec_prefix=\@exec_prefix\@\n".
"bindir=\@bindir\@\n".
"datarootdir=\@datarootdir\@\n".
"mandir=\@mandir\@\n".
"man1dir=\$(mandir)/man1\n".
"\n".
&def($makefile_extra{'gtk'}->{'vars'}) .
"\n".
".SUFFIXES:\n".
"\n".
"\n".
"all: \@all_targets\@\n".
&splitline("all-cli:" . join "", map { " $_" } &progrealnames("U"))."\n".
&splitline("all-gtk:" . join "", map { " $_" } &progrealnames("X"))."\n";
print "\n";
"# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\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", "=",
map {"${dirpfx}$_"} sort keys %allsourcefiles);
print &splitline(join " ", @sources), "\n\n";
@cliprogs = ("bin_PROGRAMS", "=");
foreach $p (&prognames("U")) {
($prog, $type) = split ",", $p;
push @cliprogs, $prog;
}
@allprogs = @cliprogs;
foreach $p (&prognames("X")) {
($prog, $type) = split ",", $p;
push @allprogs, $prog;
}
print "if HAVE_GTK\n";
print &splitline(join " ", @allprogs), "\n";
print "else\n";
print &splitline(join " ", @cliprogs), "\n";
print "endif\n\n";
%objtosrc = ();
foreach $d (&deps("X", undef, $dirpfx, "/", "am")) {
$objtosrc{$d->{obj}} = $d->{deps}->[0];
}
@amcflags = ("\$(COMPAT)", "\$(XFLAGS)", map {"-I$dirpfx$_"} @srcdirs);
print "if HAVE_GTK\n";
print &splitline(join " ", "AM_CFLAGS", "=",
"\$(GTK_CFLAGS)", @amcflags), "\n";
print "else\n";
print &splitline(join " ", "AM_CFLAGS", "=", @amcflags), "\n";
print "endif\n\n";
%amspeciallibs = ();
foreach $obj (sort { $a cmp $b } keys %{$cflags{'am'}}) {
print "lib${obj}_a_SOURCES = ", $objtosrc{$obj}, "\n";
print &splitline(join " ", "lib${obj}_a_CFLAGS", "=", @amcflags,
$cflags{'am'}->{$obj}), "\n";
$amspeciallibs{$obj} = "lib${obj}.a";
}
print &splitline(join " ", "noinst_LIBRARIES", "=",
sort { $a cmp $b } values %amspeciallibs), "\n\n";
foreach $p (&prognames("X:U")) {
($prog, $type) = split ",", $p;
$objstr = &objects($p, "X.o", undef, undef);
print &splitline($prog . ": " . $objstr), "\n";
$libstr = &objects($p, undef, undef, "-lX");
print &splitline("\t\$(CC) -o \$@ " .
$objstr . " \$(${type}LDFLAGS) $libstr", 69), "\n\n";
}
foreach $d (&deps("X.o", undef, $dirpfx, "/", "gtk")) {
if ($forceobj{$d->{obj_orig}}) {
printf("%s: FORCE\n", $d->{obj});
} else {
print &splitline(sprintf("%s: %s", $d->{obj},
join " ", @{$d->{deps}})), "\n";
print "if HAVE_GTK\n" if $type eq "X";
@progsources = ("${prog}_SOURCES", "=");
%sourcefiles = ();
@ldadd = ();
$objstr = &objects($p, "X", undef, undef);
foreach $obj (split / /,$objstr) {
if ($amspeciallibs{$obj}) {
push @ldadd, $amspeciallibs{$obj};
} else {
$sourcefiles{$objtosrc{$obj}} = 1;
}
}
print &splitline("\t\$(CC) \$(COMPAT) \$(CFLAGS) \$(XFLAGS) -c $d->{deps}->[0]\n");
push @progsources, sort { $a cmp $b } keys %sourcefiles;
print &splitline(join " ", @progsources), "\n";
if ($type eq "X") {
push @ldadd, "\$(GTK_LIBS)";
}
if (@ldadd) {
print &splitline(join " ", "${prog}_LDADD", "=", @ldadd), "\n";
}
print "endif\n" if $type eq "X";
print "\n";
}
print "\n";
print $makefile_extra{'gtk'}->{'end'};
print "\nclean:\n".
"\trm -f *.o". (join "", map { " $_" } &progrealnames("X:U")) . "\n";
print "\ndistclean: clean\n".
"\t". &splitline("rm -f config.status config.cache config.log ".
"configure.lineno config.status.lineno Makefile") . "\n";
print "\nFORCE:\n";
print $makefile_extra{'am'}->{'end'};
select STDOUT; close OUT;
}

View File

@ -10,23 +10,27 @@
case "$1" in
????-??-??)
case "$1" in *[!-0-9]*) echo "Malformed snapshot ID '$1'" >&2;exit 1;;esac
arcsuffix="-`cat LATEST.VER`-$1"
autoconfver="`cat LATEST.VER`-$1"
arcsuffix="-$autoconfver"
ver="-DSNAPSHOT=$1"
docver=
;;
r*)
arcsuffix="-$1"
autoconfver="$1"
arcsuffix="-$autoconfver"
ver="-DSVN_REV=${1#r}"
docver=
;;
'')
autoconfver="X.XX" # got to put something in here!
arcsuffix=
ver=
docver=
;;
*)
case "$1" in *[!.0-9a-z]*) echo "Malformed release ID '$1'">&2;exit 1;;esac
arcsuffix="-$1"
autoconfver="$1"
arcsuffix="-$autoconfver"
ver="-DRELEASE=$1"
docver="VERSION=\"PuTTY release $1\""
;;
@ -34,7 +38,6 @@ esac
perl mkfiles.pl
(cd doc && make -s ${docver:+"$docver"})
sh mkauto.sh 2>/dev/null
relver=`cat LATEST.VER`
arcname="putty$arcsuffix"
@ -49,6 +52,7 @@ find . -name uxarc -prune -o \
-name CVS -prune -o \
-name .cvsignore -prune -o \
-name .svn -prune -o \
-name configure.ac -prune -o \
-name '*.zip' -prune -o \
-name '*.tar.gz' -prune -o \
-type f -exec ln -s $PWD/{} uxarc/$arcname/{} \;
@ -57,5 +61,8 @@ if test "x$ver" != "x"; then
md5sum `find . -name '*.[ch]' -print` > manifest;
echo "$ver" > version.def)
fi
sed "s/^AC_INIT(putty,.*/AC_INIT(putty, $autoconfver)/" unix/configure.ac > uxarc/$arcname/unix/configure.ac
(cd uxarc/$arcname && sh mkauto.sh) 2>errors || { cat errors >&2; exit 1; }
tar -C uxarc -chzof $arcname.tar.gz $arcname
rm -rf uxarc

View File

@ -4,18 +4,41 @@
# * Automake (for aclocal)
# If you've got them, running "autoreconf" should work.
AC_INIT
# Version number is substituted by Buildscr for releases, snapshots
# and custom builds out of svn; X.XX shows up in ad-hoc developer
# builds, which shouldn't matter
AC_INIT(putty, X.XX)
AC_CONFIG_FILES([Makefile])
AC_CONFIG_HEADERS([uxconfig.h:uxconfig.in])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_PROG_INSTALL
AC_PROG_CC
if test "X$GCC" = Xyes; then
PUTTYCFLAGS="-Wall -Werror"
else
PUTTYCFLAGS=""
fi
AC_SUBST(PUTTYCFLAGS)
AC_PROG_RANLIB
# Mild abuse of the '--enable' option format to allow manual
# specification of setuid or setgid setup in pterm.
setidtype=none
AC_ARG_ENABLE([setuid],
[AS_HELP_STRING([--enable-setuid=USER],
[make pterm setuid to a given user])],
[case "$enableval" in
no) setidtype=none;;
*) setidtype=setuid; setidval="$enableval";;
esac])
AC_ARG_ENABLE([setgid],
[AS_HELP_STRING([--enable-setgid=GROUP],
[make pterm setgid to a given group])],
[case "$enableval" in
no) setidtype=none;;
*) setidtype=setgid; setidval="$enableval";;
esac])
AM_CONDITIONAL(HAVE_SETID_CMD, [test "$setidtype" != "none"])
AS_IF([test "x$setidtype" = "xsetuid"],
[SETID_CMD="chown $setidval"; SETID_MODE="4755"])
AS_IF([test "x$setidtype" = "xsetgid"],
[SETID_CMD="chgrp $setidval"; SETID_MODE="2755"])
AC_SUBST(SETID_CMD)
AC_SUBST(SETID_MODE)
AC_ARG_WITH([gssapi],
[AS_HELP_STRING([--without-gssapi],
@ -42,7 +65,8 @@ AC_CHECK_HEADERS([utmpx.h sys/select.h],,,[
#include <sys/types.h>
#include <utmp.h>])
# Look for both GTK 1 and GTK 2.
# Look for both GTK 1 and GTK 2. If we can't find either, have the
# makefile only build the CLI programs.
gtk=none
@ -62,11 +86,7 @@ case "$gtk_version_desired" in
;;
esac
if test "$gtk" = "none"; then
all_targets="all-cli"
else
all_targets="all-cli all-gtk"
fi
AM_CONDITIONAL(HAVE_GTK, [test "$gtk" != "none"])
if test "$gtk" = "2"; then
ac_save_CFLAGS="$CFLAGS"
@ -77,7 +97,6 @@ if test "$gtk" = "2"; then
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
AC_SUBST([all_targets])
AC_SEARCH_LIBS([socket], [xnet])
@ -100,6 +119,16 @@ AC_CHECK_FUNCS([getaddrinfo ptsname setresuid strsignal updwtmpx])
AC_OUTPUT
if test "$gtk" = "none"; then cat <<EOF
'configure' was unable to find either the GTK 1 or GTK 2 libraries on
your system. Therefore, PuTTY itself and the other GUI utilities will
not be built by the generated Makefile: only the command-line tools
such as puttygen, plink and psftp will be built.
EOF
fi
AH_BOTTOM([
/* Convert autoconf definitions to ones that PuTTY wants. */

View File

@ -5,6 +5,22 @@
#define STR1(x) #x
#define STR(x) STR1(x)
#ifdef INCLUDE_EMPTY_H
/*
* Horrible hack to force version.o to be rebuilt unconditionally in
* the automake world: empty.h is an empty header file, created by the
* makefile and forcibly updated every time make is run. Including it
* here causes automake to track it as a dependency, which will cause
* version.o to be rebuilt too.
*
* The space between # and include causes mkfiles.pl's dependency
* scanner (for all other makefile types) to ignore this include,
* which is correct because only the automake makefile passes
* -DINCLUDE_EMPTY_H to enable it.
*/
# include "empty.h"
#endif
#if defined SNAPSHOT
#if defined SVN_REV