Hello everyone, it's time to share something I've tinkering with for a few days.
First, motivation: There's a couple of identifiers in libc (both types and constants), that are special in ways that make organization difficult. On one side, we have things like size_t and NULL that are supposed to be defined in a multitude of different headers, not having a single "home". On the other side, we have lots of different integer types and property macros that are split across several headers, but are much more naturally defined all together in one place. In current HelenOS, some of the types and constants are defined by an autogenerated header (itself broken in several ways), which is then symlinked to several different locations; some are defined by copypasta in libarch (there's just two versions, 32b vs 64b, but there's a copy of those definitions for each architecture, and further duplication between uspace and kernel); the rest are sprinkled wherever was the most convenient at the time (I'm looking at you, ptrdiff_t). Some libraries, e.g. musl, sort this out by having a single big header that's included after defining macros like "__need_size_t", "__need_NULL", etc, and itself does more magic with "XXX_is_defined" macros. This is an antipattern, it makes the headers non-modular, and breaks clang's -fmodules feature. Clang modules are not the focus of this writeup, but as an appetizer, I will point out that properly modular headers could give us bonuses like diagnostics for unnecessary includes. Instead, I propose the following: In the abi/include directory, shared between kernel and uspace, there shall be a directory of "building block" headers (in my current implementation, this directory is named "_bits", but this is subject to bikeshedding). These headers are private and are only supposed to be included by other headers that expose the API. Each of these building blocks defines a particular subset of the basic types, at arbitrary granularity. E.g. there may be <_bits/size_t.h> that defines just size_t, and <_bits/stdint.h> that defines some or all of <stdint.h> types. However, the building block headers don't contain the actual definition of those types and constants, they simply refer to preestablished macros with reserved names, such as __SIZE_TYPE__. These macros are established all in one place, in <_bits/macros.h>, which is where all the real magic happens. macros.h expects a small subset of predefined macros (which are deliberately picked to be a subset of predefined macros provided by both GCC and clang, but can also independently be provided by autotool.py), and derives all the rest of the information necessary to provide a complete, self-consistent library. You can check out the current version here: https://github.com/le-jzr/helenos/tree/types2/abi/include/_bits Thoughts? Ideas? Fearsome criticism? -- jzr _______________________________________________ HelenOS-devel mailing list [email protected] http://lists.modry.cz/listinfo/helenos-devel
