Date: Wed, 24 May 2000 13:39:17 -0400 From: "Eric S. Raymond" <esr@snark.thyrsus.com> To: linux-kernel@vger.rutgers.edu, linux-kbuild@torque.net Subject: Announcing CML2, a replacement for the kbuild system For some weeks now, I have been developing a replacement for the kbuild system used to configure Linux kernels. This effort has had the support of Michael Elizabeth Chastain, the principal kbuild maintainer, and has benefited from input by others on the kbuild list. The project is not yet complete, but it has reached a beta stage at which it is usable and in significant ways functionally superior to the present system. I am confident that it will complete. I am announcing now rather than holding off until I'm completely done because there are some preparations which, if begun now, will significantly reduce total transition costs. These preparations will *not* break the present kbuild system. Why this project at all? It all started when I realized that building kernels is way too hard. I wanted to simplify the configuration task enough to make configuration accessible to non-gurus. It needs to have more policy options. Rather than hundreds of questions like "Include FOOBAR2317 driver?", the novice should see stuff like "Compile in all modular drivers as modules without prompting?" This just can't be done with the existing kbuild system. The existing config-language programs are hard to read and modify, and the code that interprets them has become a huge, unmaintainable hairball of Tcl/Tk, C, makefiles, and shell. It has all become terminally brittle, and the maintainers agree that it needs to be nuked and rebuilt from scratch. It happens that I love writing domain-specific minilanguages, so I have tackled this problem head-on. I have designed a new configuration language I call CML2 (the existing language I have retrospectively named CML1). The implementation has two parts: 1. I have implemented a CML2 compiler that validates CML2 rulesets and generates a rulebase that can be used to drive a configuration process. I have translated almost all of the 7049 lines of CML1 in the 2.3.99-pre9 source tree to validated CML2 (and *that*, believe me, was hard work -- it took longer than the CML2 design and coding!). 2. I have written a configurator that is ready for testing. This program reads in the rulebase and uses it to do the actual config-file generation from a dialog with the user. Though not yet equipped with a Tk interface, this program fully demonstrates the capabilities of CML2. It runs in either line-oriented or curses mode depending on the display environment (line-oriented mode can be forced with a command-line switch). The line-oriented mode of the new configurator is much more powerful than the original Configure. It's possible to move backward or jump around in the configuration sequence; the constraints that were expressed by if-then-else logic in CML1 are now checked every time the value of a relevant symbol is changed. It also has full access to the help system. The curses mode, unlike the old menuconfig code, also has full access to the help text. It reports attempts to set symbol combinations that would result in an invalid configuration. The configurator should be able to present a Tk-based menu interface when it detects that it's running on an X display. This is the part I haven't written yet. The code needs more testing, which is one reason I am announcing now. It would be useful for configure maintainers to begin running through odd configurations to see if they can get it to misbehave. The first alpha of CML2 is available at http://www.tuxedo.org/~esr/kbuild/ It includes the alpha implementation, documentation, and a transition guide for maintainers of CML1 code. OK, here's the bad news: the new system will not be an instant, painless replacement for the old. I tried hard, but there was just too much cruft to clean up for that to be possible. The major source of problems is, as you might expect, that 6747-line mass of old code -- the new language is nontrivially different than the old, and the CML1 corpus is so tangled and nasty that I am certain I have made at least a few mistakes in the translation. There are a couple of places where I didn't understand the author's intentions well enough to translate some particularly grotty CML1 code. I'll need some help untangling these knots. I apologize for this, but the translation overhead would only have been avoidable if CML1 had been good enough not to replace. It's a cost we have to pay to clean up a mess that would otherwise only have gotten worse, and eventually have become a serious drag on kernel development and porting. There are some other minor problems, which we can fix up front. Mostly they have to do with cleaning up the configuration-symbol namespace (which would be a good idea even if we planned to keep CML1). Now the good news: we will win big by changing over. Here are some of the advantages of the new language: 1. Single parser and front end CML1 had three different interpreters, none perfectly compatible with any of the others. CML2 has one rule compiler and one rulebase-interpreter front end. This will be good for consistency and economy. 2. A more expressive, easier-to-program configuration language The rather spiky and cluttered shell-like syntax of CML1 is replaced with a much simpler and more regular format resembling that of .netrc or .fetchmailrc. More importantly, the semantics of the language are declarative rather than imperative -- a better match for the problem domain, and thus more expressive and easier to code in. 3. Drastic reduction in code size and complexity The 7049 lines of CML1 in the 2.3.99-pre9 kernel translate to a hair less than 2400 lines of CML2, a reduction by a factor of about three. The CML2 compiler and prototype interpreter are the same factor of three smaller than the nearly 10,000 lines of code in the CML1 interpreters and tools. Where CML1 is a complex mixture of C, shell, Tcl/Tk, and Makefiles, CML2 is all be written in a single language (Python). 4. Eliminates (or at least drastically reduces) lag between port configurations The fact that the top-level CML1 files of the nine ports in the kernel tree are separate means there have been plenty of opportunities for the common code in them to suffer from version skew -- I point out about a dozen bugs of this kind in the list of errors at the end of this post. CML2's design and compilation rules should effectively prevent future bugs of this kind. 5. Clean separation between configuration language and configuration UI CML decouples the configuration language from the configuration user interface (they communicate with each other only through the compiled rulebase). This means that it will be relatively easy to improve the UI and the language separately. 6. Internationalization CML2 query prompts and menu banners are separated from the symbol dependency declarations. Thus CML2 system definitions can be internationalized and localized. 7. Language is fully documented CML2 has a complete, explicit description. Syntax, language semantics, and front-end policy options are all discussed in detail. 8. Policy-based options The declarative semantics of CML2 makes it much easier to set up and check interdependencies among symbols. I have done only enough of this in the CML1 translation for demonstration purposes (there are new symbols TUNING, EXPERT and WIZARD that change some visibilities). Once CML2 is in place, it should be a relatively small effort to give the user a rich set of policy and don't-bother-me options. So, how do we get there from here? Obviously, I have to finish the CML2 front end. This is not a large job; I already have a demonstrable prototype that runs in tty and curses modes, and even on my heavy travel schedule I expect to have the Tk version ready in about two weeks. I have designed the CML2 implementation to coexist with CML1, so both methods can be used while CML2 is being field-tested and debugged. I anticipate a phase-in over three or four point releases during 2.5.x, followed by a back-port to 2.4.x. Once CML2 is reported OK by the various porting groups, Linus can quietly nuke the CML1 machinery. There are a couple of preparation steps that can fruitfully begin now and should happen before 2.4 in order to minimize backporting hassles later. 1. Notably, I would appreciate it if config-file maintainers made the following changes in those files and relevant C code: CONFIG_6xx -> CONFIG_PPC_6xx CONFIG_4xx -> CONFIG_PPC_4xx CONFIG_PPC64 -> CONFIG_PPC_64 CONFIG_8260 -> CONFIG_PPC_8260 CONFIG_8xx -> CONFIG_PPC_88x CONFIG_060_WRITETHROUGH -> CONFIG_M68060_WRITETHROUGH CONFIG_21285_WATCHDOG -> CONFIG_DC21285_WATCHDOG CONFIG_3C515 -> CONFIG_ISA3C515 CONFIG_8139TOO -> CONFIG_RTL8139 CONFIG_82C710_MOUSE -> CONFIG_CT82C710_MOUSE CONFIG_977_WATCHDOG -> CONFIG_WB83C977_WATCHDOG CONFIG_3215 -> CONFIG_IBM3215 CONFIG_3215_CONSOLE -> CONFIG_IBM3215_CONSOLE The reason for these is that CML2 symbol names drop the CONFIG_ prefix. It's unneeded clutter, and made CML1 programs harder to read (the eye-brain systems that handle spelling look for prefix matches to recognize things). Also, I had to change the KEYBOARD and MOUSE symbols used in the MIPS branch to MIPS_KEYBOARD and MIPS_MOUSE. This is because the MOUSE symbol seems to be used in different ways on different architectures (notably in the Intel branch). 2. I also found some apparent errors. I need these explained so I'll know how to handle them in the translation. A summary of these apparent errors is included at the end of this post. 3. Those are the easy parts. The hard part is that I'd like to ask config maintainers to eyeball-check the CML2 translation of their work *now*. Where I am most likely to have erred is in setting visibility constraints by architecture. Ideally, I'd like everyone to have confidence that the translation is correct by the time the Tk-based front end comes out. Presently the entire CML2 translation lives in a single file, rather than being distributed into per-subdirectory files like the CML1 corpus. This is a temporary expedient to make the transition easier. CML2's "source" facility is quite powerful enough to support distributing the information later on. The current CML2 menu tree is ugly and poorly organized -- that is to say, it has changed relatively little from the CML1 version. I am deliberately refraining from large changes yet. Once we have tested and switched over to CML2, it will be possible to do a complete redesign of the kbuild user experience. The most important feature of CML2 is that it will give us the capability to explore that design space without risking breaking the ability to build kernels at all. Here are the apparent errors I found in the CML1 corpus: ----------------------------------------------------------------------------- There is what appears to be an error in the M68K configuration sequence. Inside a PARPORT guard, the question 'Q40 Parallel port' sets PARPORT again. I created a PARPORT_Q40 symbol and set it from this question. The symbols SGI occurs in conditionals in config files but are never set or associated with a query, nor are they used in C code anywere. The symbol SUN3 is used in conditionals and set to n at one point, but there is no place where it is set to y. The symbol FB_CONSOLE is set at one point but never used in either C or config language code. The symbol ABSTRACT_CONSOLE is not used in C code, nor set anywhere in config code. The symbol AIC7XXX_TAGGED_QUEUEING is set in the sparc64 configuration code, but not used in C code. I suspect it should be AIC7XXX_TCQ_ON_BY_DEFAULT. The symbol ADB_PMU68K defined in the M68K driver is not referenced anywhere in the config code and not used in the C code. It seems to be a misspelling of ADB_PMU. I have eliminated it. In the ARM port configuration, symbols ARCH_TBOX and ARCH_SHARK and ARCH_NEXUSPCI and ARCH_NEXUSPCI are referenced but never associated with a query or defined. There are two symbols in the configuration code that seem to relate to endianness on processors that can operate in either big-endian or little-endian mode. One is CPU_LITTLE_ENDIAN (in the MIPS ports) and the other is LITTLE_ENDIAN (in the SuperH port). Neither is used in the C code; CPU_LITTLE_ENDIAN is used in a guard, once, in the MIPS32 config. I have changed LITTLE_ENDIAN to CPU_LITTLE_ENDIAN. The symbol PRINTER_READBACK is queried for once, but never used in the config or C code. I suspect it should have been asking for PARPORT_1284. ----------------------------------------------------------------------------- Note: this announcement was crossposted to the linux-kernel and linux-kbuild lists. You may want to use group reply in respnding to it to reach both populations. Port maintainers and others with a continuing interest in the development of CML2 should probably join the kbuild list -- subscribe in the usual way via linux-kbuild-request@torque.net -- <a href="http://www.tuxedo.org/~esr">Eric S. Raymond</a> The Bible is not my book, and Christianity is not my religion. I could never give assent to the long, complicated statements of Christian dogma. -- Abraham Lincoln - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/