Building Bash 1.14.7 on a modern system
In a previous revision of my Bash arrays post, I wrote:
Bash 1.x won’t compile with modern GCC, so I couldn’t verify how it behaves.
I recall spending a little time fighting with it, but apparently I
didn’t try very hard: getting Bash 1.14.7 to build on a modern box is
mostly just adjusting it to use stdarg
instead of the
no-longer-implemented varargs
. There’s also a little
fiddling with the pre-autoconf automatic configuration.
stdarg
Converting to stdarg
is pretty simple: For each variadic
function (functions that take a variable number of arguments), follow
these steps:
- Replace
#include <varargs.h>
with#include <stdarg.h>
- Replace
function_name (va_alist) va_dcl
withfunction_name (char *format, ...)
. - Removing the declaration and assignment for
format
from the function body. - Replace
va_start (args);
withva_start (args, format);
in the function bodies. - Replace
function_name ();
withfunction_name (char *, ...)
in header files and/or at the top of C files.
There’s one function that uses the variable name control
instead of format
.
I’ve prepared a patch that does this.
Configuration
Instead of using autoconf-style tests to test for compiler and
platform features, Bash 1 used the file machines.h
that had
#ifdefs
and a huge database of of different operating
systems for different platforms. It’s gross. And quite likely won’t
handle your modern operating system.
I made these two small changes to machines.h
to get it
to work correctly on my box:
- Replace
#if defined (i386)
with#if defined (i386) || defined (__x86_64__)
. The purpose of this is obvious. - Add
#define USE_TERMCAP_EMULATION
to the section for Linux [sic] on i386 (# if !defined (done386) && (defined (__linux__) || defined (linux))
). What this does is tell it to link against libcurses to use curses termcap emulation, instead of linking against libtermcap (which doesn’t exist on modern GNU/Linux systems).
Again, I’ve prepared a patch that does this.
Building
With those adjustments, it should build, but with quite a few
warnings. Making a couple of changes to CFLAGS
should fix
that:
make CFLAGS='-O -g -Werror -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -Wno-deprecated-declarations -include stdio.h -include stdlib.h -include string.h -Dexp2=bash_exp2'
That’s a doozy! Let’s break it down:
-O -g
The default value for CFLAGS (defined incpp-Makefile
)-Werror
Treat warnings as errors; force us to deal with any issues.-Wno-int-to-pointer-cast -Wno-pointer-to-int-cast
Allow casting between integers and pointers. Unfortunately, the way this version of Bash was designed requires this.-Wno-deprecated-declarations
Thegetwd
function inunistd.h
is considered deprecated (usegetcwd
instead). However, ifgetcwd
is available, Bash uses it’s owngetwd
wrapper aroundgetcwd
(implemented ingeneral.c
), and only uses the signature fromunistd.h
, not the actuall implementation from libc.-include stdio.h -include stdlib.h -include string.h
Several files are missing these header file includes. If not for-Werror
, the default function signature fallbacks would work.-Dexp2=bash_exp2
Avoid a conflict between the parser’sexp2
helper function andmath.h
’s base-2 exponential function.
Have fun, software archaeologists!