This library defines a set of compiler, architecture, operating system, and
library version numbers from the information it can gather of C++ predefined
macros or those defined in generally available headers. The idea for this library
grew out of a proposal to extend the Boost Config library to provide more,
and consistent, information than the feature definitions it supports. What
follows is an edited version of that brief proposal.
The idea is to define a set of macros to identify compilers and consistently
represent their version. This includes:
-
A unique BOOST_VERSION_NUMBER(major,minor,patch) macro to specify version
numbers (unfortunately, the name BOOST_VERSION is already taken to designate
the version number of boost itself).
-
A compiler identification macro, suitable for use in #if/#elif directives,
for each of the supported compilers. All macros would be defined, regardless
of the compiler. The one macro corresponding to the compiler being used
would be defined, in terms of BOOST_VERSION_NUMBER, to carry the exact
compiler version. All other macros would expand to an expression evaluating
to false (for instance, the token 0) to indicate that the corresponding
compiler is not present.
-
"Null values" could be set, for all macros, in boost/config/select_compiler.hpp;
then, for each compiler the corresponding identification macro would be
#undef and re-#defined in the corresponding boost/compiler/(cc).hpp; however
in the context of the Boost.Config infrastructure using a "prefix"
header (to be introduced) or boost/config/suffix.hpp is a better solution.
This point is further clarified later.
The current Predef library is now, both an independent library, and expanded
in scope. It includes detection and definition of architectures, compilers,
languages, libraries, and operating systems. The key benefits are:
-
Version numbers that are always defined so that one doesn't have to guard
with
#ifdef.
-
All possible definitions are included with the single
#include
<boost/predef.h>
so that it's friendly to precompiled header usage.
-
Predefs can be directly used in both preprocessor and compiler expressions
for comparison to other similarly defined values.
-
The headers are usable from multiple languages, that support the C preprocessor.
In particular C++, C, Objective C, and Objective C++.
An important design choice concerns how to represent compiler versions by means
of a single integer number suitable for use in preprocessing directives. Let's
do some calculation. The "basic" signed type for preprocessing constant-expressions
is long in C90 (and C++, as of 2006) and intmax_t in C99. The type long shall
at least be able to represent the number +2 147 483 647.
This means the most significant digit can only be 0, 1 or 2; and if we want
all decimal digits to be able to vary between 0 and 9, the largest range we
can consider is [0, 999 999 999]. Distributing evenly, this
means 3 decimal digits for each version number part.
So we can:
-
use an uneven distribution or
-
use more bits (a larger type) or
-
use 3/3/3 and have the particular compiler/platform/stdlib deal with setting
the numbers within the 3-digit range.
It appears relatively safe to go for the first option and set it at 2/2/5.
That covers CodeWarrior and others, which are up to and past 10 for the major
number. Some compilers use the build number in lieu of the patch one; five
digits (which is already reached by VC++ 8) seems a reasonable limit even in
this case.
![[Note]](../images/note.png) |
Note |
A 2/2/6 scheme would allow for bigger patch/build numbers at the cost, for
instance, of limiting the major version number to 20 (or, with further constraints,
to 21).
|
It might reassure the reader that this decision is actually encoded in one
place in the code; the definition of BOOST_VERSION_NUMBER.
Even though the basics of this library are done, there is much work that can
be done:
-
Right now we limit the detection of libraries to known built-in predefined
macros, and to guaranteed to exist system and library headers. It might
be interesting to add something like auto-configuration predefs. This way
we can add definitions for user specific libraries and features.
-
Along with the above, it might be good to add some user control as to which
headers are included with the top-level header.
-
Additionally, even if there is no auto-configure style option.. It would
be good to add optionally included headers so that user can get consistent
version number definitions for libraries they use.
-
Having a consistent set of version number definitions opens the door to
improving the user level syntax of libraries that do checks against version
numbers. Specifically Boost Config's
BOOST_WORKAROUND
macro would benefit from a more readable syntax. As would the BOOST_TESTED_AT detail macro.
-
And obviously there's lots of work to do in reformulating the existing
Boost libraries to use the Predef library once it's accepted.
-
And there's the continuing work of adding definitions for present and future
compilers, platforms, architectures, languages, and libraries.