summaryrefslogtreecommitdiff
path: root/public/build-bash-1.md
diff options
context:
space:
mode:
Diffstat (limited to 'public/build-bash-1.md')
-rw-r--r--public/build-bash-1.md87
1 files changed, 87 insertions, 0 deletions
diff --git a/public/build-bash-1.md b/public/build-bash-1.md
new file mode 100644
index 0000000..e70a36b
--- /dev/null
+++ b/public/build-bash-1.md
@@ -0,0 +1,87 @@
+Building Bash 1.14.7 on a modern system
+=======================================
+---
+date: "2015-03-18"
+---
+
+In a previous revision of my [Bash arrays post](./bash-arrays.html), 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:
+
+1. Replace `#include <varargs.h>` with `#include <stdarg.h>`
+2. Replace `function_name (va_alist) va_dcl` with
+ `function_name (char *format, ...)`.
+3. Removing the declaration and assignment for `format` from the
+ function body.
+4. Replace `va_start (args);` with `va_start (args, format);` in the
+ function bodies.
+5. Replace `function_name ();` with `function_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](./bash-1.14.7-gcc4-stdarg.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:
+
+1. Replace `#if defined (i386)` with
+ `#if defined (i386) || defined (__x86_64__)`. The purpose of this
+ is obvious.
+2. 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 use 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](./bash-1.14.7-machines-config.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 in `cpp-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`. The `getwd` function in `unistd.h`
+ is considered deprecated (use `getcwd` instead). However, if
+ `getcwd` is available, Bash uses it's own `getwd` wrapper around
+ `getcwd` (implemented in `general.c`), and only uses the signature
+ from `unistd.h`, not the actually 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's `exp2`
+ helper function and `math.h`'s base-2 exponential function.
+
+Have fun, software archaeologists!