This is a quick introduction to metaconfig. Metaconfig is a combination of a methodology and a program that will help you write portable programs. It is well known that all UN*X systems are not the same. Instead of writing lots of #ifdef/#endif for each machine the program is ported on, it seems better to directly rely on the actual possibilities of the system, without having to consider whether it comes from HP or SUN. The idea is to write the program using some symbols, known by a "unit", for all the hardware- or kernel- specific parts of code. A metaconfig unit will automatically define the symbol or not, depending on the system. Source files are scanned by metaconfig and the necessary units are loaded and put into a shell script called Configure. Running the Configure script will automatically determine a suitable value for each symbol. How does a Configure script work ? It studies the environment it runs on by extracting names in the C library, by compiling some small sample C programs, and by asking questions when in doubt, always providing a computed default answer. Here is a small example. It is said in the glossary of the symbols that RENAME is defined if the rename routine is available to rename files. Without metaconfig, we could write (for each occurrence of a "rename" in the code): #if defined(HP-UX-7.0) || defined(SUN) || defined(BSD) rename(old, new); #else unlink(new); link(old, new); unlink(old); #endif With the help of metaconfig, we shall write (once !): #ifndef HAS_RENAME int rename(old, new) char *old, *new; { (void) unlink(new); if (-1 != link(old, new)) return unlink(old); else return -1; } #endif .... rename(old, new); And that's all. The Configure script will check whether `rename' is available on the target machine and accordingly define the RENAME symbol. It is even more powerful that it may appear on a first glance, because "rename" was not there on old SUNOS3 systems or HP-UX older than 6.5 (for series 800) and 7.0 (for series 300). You cannot rely on the fact that the target machine has the latest OS release ! Another problem is to determine whether a C program should include , or with KERNEL defined. With metaconfig, you simply write: #ifdef I_TIME # include #endif #ifdef I_SYS_TIME # include #endif #ifdef I_SYS_TIME_KERNEL # define KERNEL # include # undef KERNEL #endif and the Configure script will generate a small C program, compile it, and correctly define one of the three symbols I_TIME, I_SYS_TIME and I_SYS_TIME_KERNEL. Another kind of precious information can be collected by a Configure script. For instance, the symbol USE_STRUCT_COPY will be defined if the C compiler can copy structures. It is up to the programmer to use this information, of course. The symbol VOIDSIG will be defined if the system declares "void (*signal())()" instead of "int (*signal())()". Thus you can say: #ifdef VOIDSIG extern void (*signal())(); #else extern int (*signal())(); #endif and no suspicious warning will be emitted by the C compiler. Finally, Configure can help you in shell scripts or in makefile. By using a file called Makefile.SH, which will be run through a shell to produce a Makefile, you can use the variable substitution feature. The variable $ranlib will be set to 'ranlib' or to ': ' (null statement) in a makefile, which is useful for random libraries generation. Likewise, the variable $bin will hold the full path for installing binaries (a question will be issued by Configure). Needless to say, an initial amount of time must be spent before being able to use metaconfig. The proper symbols must be known, and the program must be prepared to deal with all the possible configurations. But likewise, it will adapt itself to a greater number of systems without any further source code modification.