It appears that I’ve given up one ancient codebase for another.
No more am I writing a framework that supports System 7 and is built using Classic-only legacy tools.
Instead, as part of TADS Workbench for Macintosh, I am now employing someone else’s codebase, a port of the text-based TADS utilities, that supports 15 often elderly variants of Unix, and is built by the even more ancient makefile system.
Did I think I would no longer be involved with a 68K platform? Wrong!
This project supports such discontinued 68K platforms as Sun3 and the NeXT Cube.
Good grief, it even supports the otherwise forgotten IBM RT workstation.
How does it support all these platforms? Well, since they’re all Unix, they share most of their APIs.
But the differences, and how the project deals with them, are the interesting part. Interesting enough to fill more than one weblog post.
I’ll start by talking about the makefile.
There’s only one for the whole project, but this one file has different sections in it for all the platforms. Script-specific variables are defined, but commented out, in each of those sections.
The particular values you uncomment are then used to build your desired platform’s version of the tools.
Not unusual for this sort of thing, but in one of the explanatory files, the maintainer mentions that it could be done better, more automatically.
Investigating this a little further quickly led me to the book GNU Autoconf, Automake, and Libtool, which I will be looking into.
Before I go to do that, though, I’d like to mention one detail. It turns out that, for TADS Workbench, I’m both building the whole TADS tools via the makefile and also building just a few TADS source files into my GUI IDE application via Xcode.
Xcode doesn’t use makefiles, so I can’t reuse the settings from that makefile, and instead have to specify them a second time in my Xcode project.
Wouldn’t it be nice if all the build flags could be assembled in just one place where they could be used by both the makefile and by the Xcode project?
It appears that it is possible, by using the gcc
flag -include
in your makefile. You specify e.g. the defines.h
file there, and then also use that same defines.h
file in, for example, your Xcode target’s Language panel as the prefix file. I just tested it with a sample project and makefile, and it works.
This doesn’t seem to be the usual strategy. (Nor does it handle linker flags.) I’m curious whether autoconf
and friends even accommodate it.
We’ll see.
Be warned. I’ve looked into autoconf et al (although admittedly without a book) and it is one of the most convoluted, arcane things ever. And apparently doesn’t work well on some platforms. Good luck.
Yeah, I’m sadly responsible for some of that. And horrors! I perpetuated it for the Glk port, mainly because autoconf scared me silly.
At work, we used autoconf but not automake. This meant having to roll more of our own stuff by hand, but our Makefile nazi swore that autoconf was halfway sane but automake was not. Libtool, of course, is not only useless but actively harmful.
I don’t know why the Unix build system is still in common use. It’s insane. Inertia, I guess.
autoconf rocks. It has a steep initial learning curve, but once you get past that — and you can do that mostly by cribbing off of existing autoconf scripts and looking up new terms in the online documentation — adding new platforms or switching code based on support for various things is trivial.
I’ve never used automake, mainly because every time I thought about using it I ran into tons of comments from people saying that nobody should use it. And if you already have a makefile that works, you can clean it up a bit with autoconf but it’ll continue to work fine.
As for libtool, I haven’t use it either, but I’ve heard good things about it from some people. It isn’t strictly necessary, though.
I bought the aforementioned book once when I was interested in portability. I found the book to be just about completely useless. The word on the street is that everyone makes their autoconf/automake input files by stealing other people’s input files, taking what looks reasonable. Apparently, wherever M4 goes, that horrible sendmail mentality goes with it.
I read a great paper called Recursive Make Considered Harmful at http://www.pcug.org.au/~millerp/rmch/recu-make-cons-harm.html which explains why recursive invocations of make are bad. Make is actually a very powerful tool, it keeps track of what work has been done and what needs to be done, but using it recursively prevents it from getting all the requisite data, sort of limiting its usefulness. Automake is pretty much a recursive makefile template/generator. The paper describes an alternative system which depends on GNU make.
So the question is really, what’s worse of autoconf/automake and depending on GNU make? I have a sensation you can convince XCode to use your makefile instead, but I’ve never really tried either.
The other option that comes to mind as something “cool” to do, would be to load up all the options in XCode, then have a script which pulls that data out into a config file which is included by make, or which drives autoconf/automake. After all, XCode is probably storing the build info in an XML Plist somewhere, it shouldn’t be hard to get it out and put it in a more UNIX-friendly format. Then you just need to remember to run your tool before you post a tarball for the old school users, who probably don’t have XML parsers on their ancient platforms.
Of course, you do have another option after all this: drop support for the ancient platforms. 🙂 In the modern world, it seems to me that supporting Mac/Linux/FreeBSD usually suffices, and they have most high-level libraries in common anyway. How many people are going to complain that you don’t support NEXTSTEP anyway? It’s kind of a lame attitude to have, but without having all those platforms around to test on, you can’t really say for certain that you do support them (in my opinion).