Brian Robert Callahan
academic, developer, with an eye towards a brighter techno-social life
When it rains it pours. After making a splash with D,1 I remembered that some time ago I began an attempt to bring the GNU Modula-2 compiler to OpenBSD. Because why not? Modula-2 is a language that exists and has compiler implementations. I guess my goal is to bring all the languages and compilers to OpenBSD. And as always, there are lessons to be learned. So let's learn some.
Unlike gdc, which has been officially integrated into gcc, gm2 exists externally to the official gcc repository. With that said, setup is relatively straightforward. On the gm2 download page there are pre-setup repositories you can clone with git. Or if git isn't your thing, there are tarballs with the same contents as the git repositories. Or if you truly hate compiling and happen to be running Debian, there are some pre-built binaries available. But of course, we are on OpenBSD so let's compile. I chose the current development branch that uses gcc-11 as its base.
Let's just go for it. Let's build and see what happens. Maybe we will get lucky.
Surprise surprise, we hit a build error. This one I got a little help from Josh Rickmar, who I have known for quite a while all the way back to the Devio.us days. Thanks Josh!
The problem was that the C++ compiler was failing on a reinterpret_cast<*> (NULL)
. Turns out that on OpenBSD, if you are compiling C++11 or later, NULL
expands out to nullptr
. The standard leaves the expansion of NULL
to be implementation-defined. So I tried out a couple of Linux distros and FreeBSD to compare. On seemingly every Linux, NULL
expands unconditionally to __null
. On FreeBSD, what NULL
expands to depends on the compiler used: if using the in-base clang NULL
expands to nullptr
whereas if you use the package of gcc-10 then NULL
expands to __null
. As GNU Modula-2 uses C++11, this was a problem for OpenBSD. However, OpenBSD's expansion of NULL
is legal according to the standard, so I do not believe that changing it is what needs to be done. Instead, we should probably add to gm2 an extra preprocessor check for __OpenBSD__ and if that's true then we should undefine NULL
and redefine it as __null
. For now, I simply commented out the check in sys/_null.h
to force NULL
to expand to __null
.
After the NULL
expansion was dealt with, building continued smoothly. But then I got a host of linker errors telling me that __builtin_unreachable
was not resolved. That symbol first appears in gcc-4.5 which made me think that perhaps somehow the libgcc from gcc-4.2.1, which is still in the OpenBSD/amd64 base system, was being picked up before the libgcc from gcc-11. Heavy-handed approach here: I replaced the old gcc-4.2.1 libgcc with the new gcc-11 libgcc. I don't actually use the in-base gcc for anything, and I presume it will be removed someday. Ideally, this would be fixed but I was more interested in getting gm2 working first and then we can go back and fix these things.
Building continued until it attempted to build the gm2 plugin. Unfortunately, the build system tries to pick up gmp.h
but the build system does not include the GMP include directory in the compiler invocation. This seems like an oversight from the gm2 developers that should be fixed.
The gm2.texi file did not build with either the in-base makeinfo or the from-ports makeinfo. So I got rid of it. Can always read the online documentation if I need to.
And then the build completed successfully! That was surprisingly easy. Now it was time to test it out. Fortunately that is quite easy since gm2 has a page on testing. I ran the tests and posted the results. It is not that bad. There are plenty of failures but it is far and away mostly passes. I wrote to the gm2 mailing list with the results as well. I hope to hear back from the developers soon.
For completeness, I tried to compile a hello world program. This is the program:
MODULE hello ; FROM StrIO IMPORT WriteString, WriteLn ; BEGIN WriteString('hello world') ; WriteLn END hello.
But the build kept failing! First it seemed like gm2 could not find its own headers. Once I manually added those in, I got lots and lots of linker errors. I ended up tracking down some very old gm2 documentation squirreled away on an old ftp site that happened to always have -I.
in all their compiler invocations. That indeed was the magic addition. Once I added -I.
compilation worked correctly without having to add in anything else: gm2 -I. hello.mod
. It does leave behind a lot of intermediate files and appears to transpile Modula-2 to C++ and then compiles the C++ into a binary. The compiled binary worked as well, which was a good re-confirmaton that I indeed built a working compiler.
I am hoping that the gm2 developers get back to me soon about my mailing list post. I do want to get the testsuite failures down to zero. And I also want to submit patches to ensure that the OpenBSD build just works. There were no instructions on how patch submission worked, so I asked in my mailing list post. As gm2 is, after over 20 years of development, finally preparing to be merged into gcc, now is the perfect time to get those very small tweaks for OpenBSD support in. A pre-emptive congratulations to the gm2 team on their persistence and dedication. But I also want to make sure that OpenBSD can build gm2 out of the box the day the merge happens.
As the person who created, imported, and maintains the port of GNU Pascal, which I still use and which is sadly the only remaining Pascal compiler in ports after Free Pascal was removed after no one stepped up to maintain it after it broke, I guess I must have some affinity for Wirth languages.
But I also enjoy porting compilers and other toolchain bits. Something about the meta of it all I think. Anyhow, I hope you enjoyed this adventure into getting GNU Modula-2 working on OpenBSD!
1 Amusingly, as a result of my contributions to the D standard library, my name now appears in the gcc source tree.