Configuration Options for the GABI Library

General

The GABI Library has been designed to be relatively portable to a variety of machines, systems and complers. Basic configuration is by specifying these three elements, either as environment variables, command line settings, or in the Defaults.mk file, e.g.:

      make ARCH=sparc SYST=solaris COMP=gcc3
    
(Note that the makefiles provided only work with GNU make; on some installations, you may have to use gmake instead of make.

With very few exceptions (mostly historical), the code contains no #ifdef or other such filth; these options are used to select subdirectories — including subdirectories for parts of the makefile. Similarly, generated files (objects, libraries, executables) will be found in subdirectories, so it is quite possible to maintain several different configurations on a single file system. These three options provide a very fine grained choice of the configuration (although they do leave one or two points open).

For many things, such fine grained configuration is too much of a good thing. There are only two major versions of iostreams, for example; why have to maintain separate code for each of the $ARCH/$SYST/$COMP variants, when two versions suffice. (Originally, I only developped under Unix, and the many variants were simply links. This doesn't work for Windows or other OS's, however.) For this reason, we have introduced the concept of variants. For each configuration, the system dependant part of the makefile (Makefiles/conf/$ARCH/$SYST/$COMP/system.mk) defines which version is relevant for that particular architecture, for each variant. The different versions are then maintained in different directories, as with the different configurations, but there will typically be only two or three different versions, and not one per configuration triplet.

Since many of the system dependancies are particular to a given system (Solaris, Linux, etc.), a given architecure (Intel, Sparc, etc.), or a given compiler (g++, Sun CC), each of these elements of the configuration is also treated as a variant.

Note that directories for the variants are only present in the source tree, and in the copies of the include files in the generated sections (directories include and sources). Since the variants are defined uniquely by the configuration triplet, one directory per triplet is sufficient for objects, libraries and executables. (There are, in fact, several additional directories for these files as well, according to the compiler options, e.g.: debug, optimized, with or without thread support, and as a statically or dynamically linked library.)

What this means with regards to directories

The parameters concerning the configuration are:

name meaning currently supported values
arch
The hardware architecture.
i80x86: Intel IA-32 architecture
sparc: Generic 32 bit Sparc architecture
sparcv9: Sparc v9 and above, 64 bits
syst
The type of OS. This will generally be more precise than the system variant.
solaris: Solaris (2.7 up)
linux: Linux (versions ???)
win32: MS-Windows 32 bit (Windows NT, 2000 or XP)
comp
The compiler. In this case, we generally need versioning information as well. For historical reasons, this is somewhat mixed with the name.
gcc: g++ 2.95.2
gcc3: g++ 3.2 up
suncc: Sun CC 5.1 (and up?)
vc60: Microsoft VC++ 6.0

In general, we define $(configPath) to correspond to arch/syst/comp in the makefiles. Each variant also corresponds to a single pathname component, defined as variant.type, e.g. system.posix, iostreams.standard, etc. accessible via the macro $(variantPath).

Est-que c'est vraiment ce qu'on veut, ou est-ce qu'il ne vaut pas mieux d'utiliser les sous-répertoires, comme avant ? Quelque chose du genre iostreams/classic.

In terms of maintained directories, it is necessary to distinguish between directories which contain binary information, and those with sources or other text. In the case of directories with binary data (work, objects, lib and bin, all of the data will be in the configuration specific sub-directory, e.g. lib/$(configPath), etc. No global or variant specific directories are used. In the case of directories with (copies of) sources or text (sources or include), all of the files will be found in a final sub-directory gb, which appears explicitly in the include directive, as a sort of namespace management of our include files. Under each of these directories, there is not only a gb direct, but also a $(configPath)/gb, and for each variant, a $(variantPath)/gb.

The variants

To start with, the three components of the configuration triplet are all considered variants, i.e.: arch, syst and comp The different variants are specified in the platform specific makefile, for each system.

System family (sysFamily)

While the basic organization uses the precise system (e.g. Solaris, AIX, MS-Windows) as part of the basic configuration, for the most part, it can be said that we support two basic systems: Posix and (MS-)Windows. We thus have the system variants posix and windows (which result in directories sysFamily.posix and sysFamily.windows).

Note that this is different from syst above, which gives the precise system, and can also be used as a variant. (Typically, this will be the case when there is a problem with one particular system -- for example, for some reason, Solaris doesn't support the Posix function pthread_rwlock_timedwrlock, which is used in the implementation of timed mutexes. So we implement them differently for Solaris, in the solaris variant. The configuration based variants are included before the others, so the compiler will pick up the specific Solaris implementation, rather than the "standard" Posix implementation.)

IO streams (iostreams)

Many environments still in use don't support the standard IO streams correctly; we've even had problems with VC++ 6.0 here, because of bugs in the compiler. The result is that we have two versions, classic and standard, giving directories iostreams.classic and iostreams.standard.

(In fact, it's slightly worse, and we have a variant wclassic for Windows as well.)

Threading model (,code>threads)

There are actually two threading models built per system. The first is an unthreaded model which is common to all configurations, and goes under the name nothreads. The currently supported threading models for threaded operation are winthreads and pthreads.

This really could be incorporated into the system parameter, except that I suspect that there will be cases where it can't be: in the past, for example, Solaris has had their own interpretation of threads.

Order of includes

The information here is no longer correct. The idea is nice in theory, but means that users of the library must specify far too many -I options, most of which contain configuration specific information. So we've changed the policy, giving ourself a little less flexibility, but making it easier on the user.

A certain order of the above directories has been rigorously followed: within any hierarchy, the configuration directory is included first, then the configuration based variants, then the directories with the variants, then the base directory. In this way, it is possible to furnish a default version of the include file, or a default version for a specific variant, and override it with a configuration specific include file.

Similarly, we use a vpath directive in the makefile, with the same basic ordering of the files, so that a particular configuration or system can easily replace an entire source file. Note: we do not use the VPATH pseudo target, so that exported headers will not be copied over to the root include.

Source file considerations

All source files start with an include of gb/Global.hh; this file includes a configuration specific file which is automatically generated by the makefiles from the configuration information in them. The results is that a macro named GB_dependentInclude defined. This macro takes two parameters, the first the name of the variant, and the second a filename. The name of the variant must be literally one of the following: conf, arch, syst, comp, sysFamily, threads or iostreams. (conf is used for the complete configuration triplet.)

Thus, for a dependent include, the source file will contain something like:

        #include GB_dependentInclude( threads, gb/Mutex.hh )
    

Such include statements are normally reserved for our own library includes and implementation. The library itself will provide an include file gb/Mutex.hh which will forward to the appropriate dependent include, so this is largely transparent to the user.

When the user compiles, he must specify four include directories, e.g.:

        -I$GABIROOT/include/$ARCH/$SYST/$COMP
        -I$GABIROOT/include
        -I$GABIROOT/sources/$ARCH/$SYST/$COMP
        -I$GABIROOT/sources
    

The library path is:

        -L$GABIROOT/lib/$ARCH/$SYST/$COMP