On Mon, Feb 28, 2022 at 9:10 AM Larry McVoy <lm(a)mcvoy.com> wrote:
So I'm curious, did Plan 9 run on a similar
number of architectures and
support a similar number of graphics cards?
Yes, it did.
If it did that, nicely, then you have a great point, the X11 people
(and most of us) clearly missed a better way to do
things. If this is
the case, I'd like to understand how you did it because just including
different definitions doesn't begin to scratch the surface of what the
#ifdefs did in X11, there were tons in the actual code.
#ifdef has more or less always struck me as the solution to the wrong
problem. "We have all this code and we want to shoehorn it into a new
environment," instead of, "we have many environments, so we carefully
structure the code to accommodate the differences." Of course, the latter
is harder than the former, but it also pays larger dividends over time as
compared to the former.
Maybe the constant system interface made all the difference, that
could be.
If it supported a much smaller number of targets, well, sure, it's
easier to be clean if you have a clean set of targets.
In fairness, a meaningful comparison is hard: plan9 ran on ~a dozen
different architectures over its lifetime, but never supported near the
variety of software or workloads of Unix, and didn't exactly "compete" in
the market the way Unix did. The PC port in particular supported oodles of
graphics cards at one point, but not as many as X did, mostly because there
weren't all that many folks working with the unsupported cards, so there
wasn't a lot of motivation to write tons of drivers.
Could it have retained its elegantly clean structure over time had things
evolved differently? That's impossible to answer, but I'm sad that we never
got the chance to find out.
I remain grateful for the #ifdefs, I could make enough sense of it
all to bring up X11 on every platform I worked on. It
wasn't pretty,
there was a ton of "I don't recognize this $WHATEVER, what happens if
I just #if 0 around the whole thing? Wow, it compiles, lets see if
I get a window system. Yep, I do. Shrug." That limited what I had
to understand to the much smaller subset of code I was actually
going to run, yeah, that set of #ifdefs was a mess but not such
a mess that I didn't get a working X11.
I'm not arguing that #ifdef is good, I'm
just acknowledging it had
a lot of benefit to me, and _for me_, the cost was worth it in that
instance. I could have X11 working in less than a day.
I do think that #ifdef, used extremely judiciously, can have some utility:
for example, compiling out debug code by setting a constant. Consider:
#ifdef NDEBUG
const bool DEBUGGING = false;
#else
const bool DEBUGGING = true;
#endif
static inline
void
DBG(const char *fmt, ...)
{
if (DEBUGGING) {
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt ap);
va_end(ap);
}
}
DBG(foo);
if `NDEBUG` is defined, then the body of the static inline becomes, `if (0)
{ ... }` and one hopes our compilers are sufficiently smart to elide the
entire thing.
The biggest problem with #ifdef wasn't so much that it existed, but rather
that it was used for too many things that it wasn't well-suited for. The
second biggest problem was that it was semantically unaware of the
language; it was purely textual. Bummer.
I do get your point about abstracting the interface differences away,
I actually hate #ifdefs in the code with a passion so
in BitKeeper we
had all that stuff buried under the abstractions. We made everything
look like Unix, even on Windows, except for fork(). I haven't called
fork() directly in close to 20 years, we picked up spawn() and made that
work everywhere. The abstraction layer cuts down on the #ifdefs in the
code a LOT.
Agreed. But getting those abstractions right requires experience and taste.
#ifdef is a blunt took for a nuanced problem.
- Dan C.
On Mon, Feb 28, 2022 at 06:22:28PM +1100, Rob Pike wrote:
Plan 9 had the
distinct advantage of a constant system interface at the
source level. X11 did not, but it also made essentially no attempt to
abstract it away, so the lines starting #ifdef often outnumbered the
actual
code. I couldn't make hide nor hair of it,
and had no way to reliably
test
any change.
C with #ifdefs is not portable, it is a collection of 2^n overlaid
programs, where n is the number of distinct #if[n]def tags. It's too bad
the problems of that approach were not appreciated by the C standard
committee, who mandated the #ifndef guard approach that I'm sure could
count as a provable billion dollar mistake, probably much more. The cost
of
building #ifdef'ed code, especially with
C++, which decided to be more
fine-grained about it, is unfathomable.
Google alone might well count for many millions of dollars in wasted
compilation equipment. I remember giving a Plan 9 demo to someone soon
after I got to Google. None of the features of the system were of
interest.
The thing that astounded my audience was the
ability to build the kernel
on
a P90 in 20 seconds or so, and the window system
in under 3. At that
time,
a build of a Google server would require hours on
a large distcc cluster.
I still shudder to think of it. It's worse now, of course, far worse, but
Google has far larger clusters to handle it and some improvement in
tooling. However, the #ifdefs persist.
Tom Cargill warned Bjarne about this around 1984, but the plea fell on
deaf
ears.
-rob
On Mon, Feb 28, 2022 at 12:07 PM Douglas McIlroy <
douglas.mcilroy(a)dartmouth.edu> wrote:
> > The X11 tree was a heavily ifdef-ed. And it needed to be, I don't
have
> > an answer as to how you would reuse all
that code on different
hardware
> > in a better way.
>
> Plan 9 did it with #include. The name of the included file was the
same for
> every architecture. Only the search path for
include files changed.
Done
> with
> care, this eliminates the typical upfront #ifdefs.that define constants
> and set
> flags.
>
> Other preprocessor conditionals can usually be replaced by a regular
if,
> letting
> the compiler optimize away the unwanted alternative. This makes
> conditionals
> obey the scope rules of C.
>
> Doug
>
--
---
Larry McVoy lm at
mcvoy.com
http://www.mcvoy.com/lm