Porting Guidelines for Andrew Andrew User Interface System Version 8 (October 1996) Andrew Consortium School of Computer Science Carnegie Mellon University 5000 Forbes Avenue Pittsburgh, PA 15213-3891 USA Phone: (412) 268-6710 Fax: (412) 268-5576 Web: http://www.cs.cmu.edu/~AUIS Demo: finger @atk.cs.cmu.edu Archives: ftp.andrew.cmu.edu: /pub/AUIS Bugs: info-andrew-bugs@andrew.cmu.edu Info & Subscriptions: info-andrew-request@andrew.cmu.edu In the documentation, the source directory will be referred to as $/ and the destination as $ANDREWDIR/. If you are reading an all-ASCII version of this file, the version in Andrew format is in the distribution at: $ANDREWDIR/doc/DEVELOPER/Porting.ez Copyright 1996 Carnegie Mellon University. All rights reserved. Please see further copyrights and disclaimer at the end of this file. Introduction Manufacturers continue to produce new hardware/operating system platforms on which people would want to use Andrew (AUIS or the Andrew User Interface System). This document describes some of the tasks essential to creating a port for Andrew. 1. Preliminary Definitions and Notes In general, the term refers to a name chosen to refer to the platform, a combination of a hardware architecture and an operating system. (Some hardware has more than one operating system, and vice versa.) Often it is the name used by Transarc's AFS to identify the platform and therefore available as the `sys` command or the value of @sys as a path component on AFS systems. Usually the name is a compound listing, first the hardware and then the operating system; for example, the s for the IBM RS_6000 are rs_aix32 and rs_aix41. The platform name must be #defined as the value of the variable SYS_NAME in $/config//system.h. Currently system-type names are of the form _. In the future, system types should be named: ____ The later portions may be omitted if the remainder is sufficiently descriptive. (The README should be consulted for a full list of make variables and #defines which may need to be changed for different systems and/or sites.) For machine/OS specific information, note that: * most new platforms are now POSIX and/or SVR4 based, * most of the OS dependent macros should be correct for such a system by default. 2. General Rules about Porting Andrew to a New Platform Make as few changes as is possible; the fewer additional characters, lines and files, the better. Try to restrict your changes to: $/config//system.{h,mcr} $/overhead/class/machdep//... $/atk/console/stats//... You will also modify ./config/platform.tmpl to use new system.mcr. 3. The Config Directory The config directory contains the imake configurations files, including the imake "rules" files, the .mcr files, and the .h files. These are used to generate Makefiles from Imakefiles and to produce the andrewos.h include file which is included in all source code files. When generating a Makefile from an Imakefile, the file $/config/imake.tmpl is preprocessed. It defines various Makefile variables and has #includes for: platform.tmpl (which #includes system.mcr and presite.h) andrew.rls (which #includes site.rls) the-Imakefile-itself Platform.tmpl is responsible only for determining what platform this is. It then #includes the system.mcr file for the platform. On some systems it may be necessary for platform.tmpl to key off a #define set in the presite.h file to select the appropriate system.mcr file. System.mcr defines Makefile variables with '='. It #includes system.h, allsys.mcr, and site.mcr. A flag is set so the system.h does not #include header files for the operating system. System.h #defines various preprocessor variables and also #includes allsys.h, various operating system include files, and site.h. Site.mcr and site.h should be empty in a distribution. They can be utilized at a given site to override definitions given in the other files. The andrew.rls files (and site.rls) #define preprocessor macros which are invoked in the Imakefile. We do not expect you to add new rules; if you feel you must, please contact the Consortium staff. Each .c source file includes andrewos.h, which does nothing more than #include system.h, but this time the flag is not set and the various operating system header files are #included. The latter include approprately named versions of: types.h, syslog.h, unistd.h, signal.h, param.h, fcntl.h, file.h dirXXX.h, stringX.h, timeX.h When adding support for a new platform, you must (1) create a new subdirectory of ./config whose name identifies the new system type, (2) populate that new directory with a system.h and system.mcr file, and (3) add the proper "vendor block" to the file ./config/platform.tmpl, so that the new files are used under the proper platform. Here are sketches of the order of inclusions among the various .h and .mcr files. When a source file #includes andrewos.h, that file in turn #includes system.h (which has been copied from $/config/system-type/system.h). System.h #includes presite.h and allsys.h before doing its own definitions and then #includes site.h which can override those definitions. andrewos.h system.h presite.h allsys.h all definitions site.h When an Imakefile is transformed to a Makefile, the C preprocessor is invoked to process the file called imake.tmpl. This #includes platform.tmpl, andrew.rls, and finally the Imakefile itself. Platform.tmpl #includes presite.h and then determines what host is being used; the host type is used to select a subdirectory of config from which ins #included the system.mcr file, which in turn includes system.h, allsys.mcr, and site.mcr. imake.tmpl platform.tmpl presite.h system.mcr system.h presite.h allsys.h all definitions site.h allsys.mcr site.mcr andrew.rls Imakefile Note that the platform is determined by platform.tmpl every time genmake or imake is run to create a Makefile. 3.1 Adding New Config Files Suppose you are adding support for a variant of UNIX, called SPINIX, that runs on the Intel 80386 chip. You typically create the new directory config/spinix_i386 and populate it with system files borrowed from an already-ported i386 system, like sco_i386. Then add a test in ./config/platform.tmpl to check for a cpp symbol unique to SPINIX, so that the correct files are used: #if defined(i386) && defined(spinix) #include #define MacroIncludeFile i386_spinix/system.mcr #endif /* Spinix */ With the above "bootstrap" code, it is assume that the two symbols "i386" and "spinix" are defined by the cpp. You can generally determine what symbols are exported by cpp by running the strings command on the cpp executable: % strings /lib/cpp | more .. or, if you use gcc, use the verbose flag (-v) to see what arguments gcc passes to cpp: % touch foo.c; gcc -v -o foo foo.c The symbols defined for the compilation are given after -D on the line showing the call to cpp. If your cpp does not define any special symbols you should pick a symbol (such as SOLARIS for the Solaris OS), and #define it in presite.h, on platforms where multiple compilers are used the presite.h should also contain a #define identifying which compiler to use. 3.2 What Goes in a system.h File The system.h file initializes the cpp state seen by each source module and each Imakefile. Each system.h file has this general form: #include XXXX #ifndef In_Imake BEGINCPLUSPLUSPROTOS XYXY ENDCPLUSPLUSPROTOS #ifndef __cplusplus XZXZ #endif #endif /* In_Imake */ XXXX #include The token XXXX denotes that arbitrary #defines are used here. XYXY denotes that a combination of #defines, additonal file-inclusion directives and C declarations may be used here. XZXZ denotes that C++ declarations or header files may be included here. The contents of the whole file is available to source modules via inclusion of the header andrewos.h while only the XXXX sections are included in the final Makefiles. In the config header files you should *only*: 1) define or redefine cpp symbols, 2) #include additional header files (protected by #ifndef In_Imake if they include arbitrary C constructs) 3) Insert C or C++ declarations, if absolutely necessary (again, place them between #ifndef In_Imake and #endif /* In_Imake */) Since C++ is relatively new it is often necessary to include C and/or C++ declarations in the system.h to correct problems in the system header files in /usr/include. For example HP-UX comes with a bad prototype for select in sys/time.h. To correct this problem the following fragments are present in it's system.h file: #define select __hide_select #include #undef select The __hide_select string is arbitrarily chosen to try to avoid conflicts, this construct effectively hides the prototype for select which is included in sys/time.h. Then a correct declaration is given: BEGINCPLUSPLUSPROTOS extern int select(int numfds, fd_set *readset, fd_set *writeset, fd_set *exceptionset, struct timeval *timeout); ENDCPLUSPLUSPROTOS The BEGIN/ENDCPLUSPLUSPROTOS words are macros which will ensure that the function is treated as a C function even when system.h is included by a C++ source file. All C functions which will be called from C++ code will need to be bracketed by these macros, multiple C functions can be included in one BEGIN/ENDCPLUSPLUSPROTOS pair. Two other common problems include missing prototypes for system functions and the use of C++ keywords in C headers. Missing prototypes should be provided with BEGIN/ENDCPLUSPLUSPROTOS blocks as described above. When a C++ keyword is used in a C header a construct like that below should be used: #define new new_c #include #undef new Here math.h used the keyword new in a prototype, which a C++ compiler won't allow. Another case is where the keyword is used as a structure member. In this case the same strategy as above should be used, and any references to the member should be changed to use the new_c name. 3.3 An Annotated System.h You can follow along in the file protosys.h. (Or cp protosys.h to config//system.h and edit it as you go.) /* ********************************************************************** *\ * Copyright IBM Corporation 1988,1994 - All Rights Reserved * * For full copyright information see:'andrew/config/COPYRITE' * \* ********************************************************************** */ The copyright notice may be dropped or replaced with your copyright notice. Any copyright notice should be in the MIT style giving unrestricted modification/distribution rights. /* $ Disclaimer: $ {{{omit the space in $ D}}} */ This section is our standard MIT style disclaimer stating that there is no warranty, etc... #ifndef SYSTEM_H #define SYSTEM_H These protect the system.h file against multiple inclusion in C or C++ source files. #include This line picks up the default definitions for all the macros . The following section contains definitions and includes which should be present for both C, C++ source files and for Imakefiles. All #includes should be present exactly as they are in this file, unless otherwise noted. The default definitions of ANSI_COMPILER, ANSI_CPP and ANSI_IMAKECPP may be overridden here and/or in site.h #undef ANSI_COMPILER #define ANSI_COMPILER 1 ANSI compiler. #undef ANSI_CPP #define ANSI_CPP 1 ANSI CPP used for C and C++ code. #undef ANSI_IMAKECPP The CPP used for imake is typically NOT an ANSI C Preprocessor. It may be on your system though, you should check and #define ANSI_IMAKECPP 1 if it is. #include presite.h should be used to select a compiler if the system.h file has support for multiple compilers. #undef MAX #undef MIN If the system header files included later define MIN and MAX then the versions from allsys.h should be #undef'd here. Otherwise these two lines should be omitted. #define OPSYSNAME "HPUX_700/90" The full name of the operating system. This should be human readable. #define sys_hp_hpux_90 1 Currently system-type names are generally of the form _. In the future system types should be named as follows: ____ The later portions may be omitted if the remainder is sufficiently descriptive. #define SYS_NAME "hp_hpux_90" A string version of the sys_ macro, without the sys_ prefix. /* any necessary machine specific #defines may be set here */ /* #define HAVE_SHARED_LIBRARIES 1 #ifdef In_Imake #define INSTALL_SHLIB_SUPPORT() @@\ InstallFileToFile(hp700_90/mkatkshlib, $(INSTPROGFLAGS), $(DESTDIR)/etc) #endif */ If the system provides shared libraries and you have implemented a means to build ATK libraries as shared (by implementing mkatkshlib), then HAVE_SHARED_LIBRARIES should be defined. If software is needed to support the installation of shared libraries (such as mkatkshlib), its source should be in config/system-type-name and commands should be added to the Imakefile there to install it. /* #define HAVE_DYNAMIC_LOADING 1 */ If you have implemented the AUIS dynamic loading code for this platform this should be uncommented. /* #define SY_B42 1 */ /* define for bsd 4.2 */ /* #define SY_B43 1 */ /* define for bsd 4.3 */ /* These are here for System V support. */ /* #define SY_U51 1 */ /* define for SysVR1 */ /* #define SY_U52 1 */ /* define for SysVR2 */ /* #define SY_U53 1 */ /* define for SysVR3 */ /* These are here for AIX support. */ /* #define SY_AIX11 1 */ /* define for AIX 1.1 (e.g. on PS/2) */ /* #define SY_AIX12 1 */ /* define for AIX 1.2 (e.g. on PS/2) */ /* #define SY_AIX221 1 */ /* define for AIX 2.2.1 */ /* #define SY_AIX3 1 */ /* defined for AIX 3 (e.g. on RS/6000) */ #undef SY_U52 #define SY_U52 1 You should add a corresponding #undef SY_* line before the line you uncomment. (To avoid warnings from CPP about redefined macros.) The SY_ macros should hopefully become obsolete fairly soon, in the meantime you should uncomment one of the macros below which most closely describes your system. In general these should be generic OS descriptions like SVR4, or BSD4.4, not specific OSes like AIX... #ifndef SYSV #define SYSV 1 #endif If your system is based on System V you should have this section, otherwise it should be omitted. #ifndef In_Imake The following section includes #defines, #includes and any other hackery which is needed in C and/or C++ source files. (and which should NOT be included for Imakefiles) #include The definitions of BEGINCPLUSPLUSPROTOS and ENDCPLUSPLUSPROTOS. These macros should be used to delimit any sequence of data types or function prototypes for C functions or datastructures. #ifdef NEED_ALLOCA Any special hacks for files using alloca should go here. As much as possible AUIS code should avoid reliance on alloca. #endif /* NEED_ALLOCA */ The following list of #includes may be modified as necessary to bring in the required types, macros and functions. #include the following types should be included. (usually from sys/types.h) dev_t device identifiers gid_t group ids ino_t file inode numbers mode_t file attributes nlink_t link count off_t file size pid_t process identifiers size_t (the C standard type) ssize_t a count of bytes which uses a negative value for an error condition uid_t a numeric user identifier #include The following macros, types and functions should be included. (usually from sys/stat.h) Data Structures: struct stat with members: st_atime may not be meaningful for files on a distributed file system. st_atime last access time st_ctime last file status change time st_mtime last file modification time st_dev and st_ino should generally not be used, as their meaning is unclear in the context of a distributed file system. st_dev device identifier st_ino file inode number it should be noted that st_gid and st_uid may not correctly reflect whether the current user owns a file (in the context of a distributed file system) st_gid group identifier st_uid owner of the file note that with a distributed file system (such as AFS) the st_mode flags for group and other access may be ignored. st_mode file attributes st_nlink number of links to the file st_size size of the file MACROS: (m is taken from the st_mode member of a stat structure.) S_ISDIR(m) true iff the file is a directory. S_ISCHR(m) true iff the file is a character special file S_ISBLK(m) true iff the file is a block special file S_ISREG(m) true iff the file is a regular file S_ISFIFO(m) true iff the file is a pipe or FIFO S_IRWXU Read, Write and Search/Execute permission mask for st_mode. (for the owner) S_IRWXG Read, Write, and Search/Execute permission mask for st_mode. (for the group) S_IRWXO Read, Write, and Search/Execute permission mask for st_mode. (for others) S_ISUID Set user id. S_ISGID Set group id. Functions: int chmod(const char *path, mode_t mode); int mkdir(const char *path); int stat(const char *path, struct stat *buf); int fstat(int fd, struct stat *buf); int mkfifo(const char *path, mode_t mode); int umask(mode_t cmask); #include The following macros, types and functions should be included. (usually from stdlib.h) Macros: EXIT_FAILURE EXIT_SUCCESS MB_CUR_MAX NULL RAND_MAX Types: div_t the structure returned from div() (the remainder and quotient of two ints) ldiv_t the structure returned from ldiv() (the remainder and quotient of two longs) size_t a count of bytes, unsigned. whcar_t a wide character Functions: abort abs atexit atof atol atoi bsearch calloc div exit free getenv labs ldiv malloc mblen mbstowcs mbtowc qsort rand realloc srand strtod strtol strtoul wcstombs wctomb /* #include */ strings.h commonly has the old-style string functions: bcopy bzero index rindex if strings.h is not present or does not include appropriate definitions of these functions other steps should be taken to define them. #include string.h is mandated by posix and contains: Macros: NULL Types: size_t Functions: memchr memcmp memcpy memmove memset strcat strchr strcmp strcoll strcpy strcspn strerror strlen strncat strncmp strncpy strpbrk strrchr strspn strstr strtok strxfrm #include unistd.h is mandated by posix: Macros: F_OK NULL R_OK SEEK_CUR SEEK_END SEEK_SET STDERR_FILENO W_OK X_OK #include stdarg.h is part of the ANSI standard: (note that varargs cannot be substituted, a stdarg interface is required. Macros: va_arg va_end va_list va_start #include stdio.h is specified by posix and ANSI: Macros: BUFSIZ EOF FILENAME_MAX L_ctermid L_cuserid L_tmpnam NULL SEEK_CUR SEEK_END SEEK_SET STREAM_MAX TMP_MAX stderr stdin stdout _IOFBF _IOLBF _IONBF Types: fpos_t size_t FILE Functions: clearerr fclose fdopen feof ferror fflush fgetc fgetpos fgets fileno fopen fprintf fputc fputs fread freopen fscanf fseek fsetpos ftell fwrite getc getchar gets perror printf putc putchar puts remove rename rewind scanf setbuf setvbuf sprintf sscanf tmpfile tmpnam ungetc vfprintf vprintf vsprintf #include dirent.h is specified by POSIX, on BSD systems this header is sys/dir.h and struct dirent is struct direct. (The macro DIRENT_TYPE will need to be changed if your system uses struct direct instead of struct dirent. See the last part of this file.) Types: DIR struct dirent with member char * d_name. Functions: closedir opendir readdir rewinddir #include sys/wait.h is specified by POSIX. Macros: WEXITSTATUS WIFSIGNALED WNOHANG WTERMSIG WIFEXITED WIFSTOPPED WSTOPSIG WUNTRACED Functions: wait waitpid /* #include */ This should only be needed on BSD systems, to get the open(2) constants. /* #include */ sys/time.h usually has struct timeval, but it is not specified by Posix. timeval may be defined in whatever header file has select. #include sys/times.h is specified by posix: Types: clock_t struct tms with members: tms_ctime, tms_cutime, tms_stime, tms_utime Functions: times #include time.h is specified by posix: Macros: CLK_TCK CLOCKS_PER_SEC NULL Types: clock_t size_t time_t struct tm with members tm_hour, tm_mday, tm_mon, tm_wday, tm_year, tm_isdst, tm_min, tm_sec, tmyday Functions: asctime ctime gmtime mktime time clock difftime localtime strftime tzzet Variable: char *tzname #include MAXPATHLEN maximum length of file path names. #include int syslog(int priority, const char *message, int parameters, ...); int openlog(const char *ident, int logopt, int facility); int closelog(void); int setlogmask(int maskpri); /* BEGINCPLUSPLUSPROTOS extern int select(int numfds, fd_set *readset, fd_set *writeset, fd_set *exceptionset, struct timeval *timeout); BEGINCPLUSPLUSPROTOS */ If no other header file declares select, you will need to find a header file which declares it and #include it here, or simply put a declaration of select here. If your system doesn't use fd_set's then add a typedef int fd_set before the select declaration, or substitute the appropriate type in place of int. #ifdef __GNUG__ /* Additional hackery may have to be added here on some platforms when using G++. */ /* Hack around SignalHandler typedef provided by GNU for Interviews compatibility, it conflicts with a method called SignalHandler. */ #define SignalHandler G_SignalHandler #include #undef SignalIgnore #undef SignalBad #undef SignalDefault #define SignalDefault ((G_SignalHandler)0) #define SignalIgnore ((G_SignalHandler)1) #define SignalBad ((G_SignalHandler)-1) #undef SignalHandler #else #include #endif This block should be present if g++ may be used to build on this platform. It works around some incompatibilites with AUIS code and the Interviews compatibility in g++ header files. If g++ won't be used a simple #include would be sufficient. #include Functions: isalnum isdigit islower ispunct isupper tolower isalpha isgraph isprint isspace isxdigit toupper iscntrl #define OSI_HAS_SYMLINKS 1 If OSI_HAS_SYMLINKS is not defined, osi_readlink is present in libutil. #define osi_readlink(PATH,BUF,SIZE) readlink((PATH),(BUF),(SIZE)) readlink should copy the destination path of the PATH symlink into BUF, up to SIZE bytes. #include fcntl is specified by posix: Macros: FD_CLOEXEC F_DUPFD F_GETFD F_GETFL F_GETLK F_RDLCK F_SETFD F_SETFL F_SETLK F_SETLKW F_UNLCK F_WRLCK O_ACCMODE O_APPEND O_CREAT O_EXCL O_NOCTTY O_NONBLCOK O_RDONLY O_RDWR O_TRUNC O_WRONLY Types: flock with members: l_len, l_pid, l_start, l_type, l_whence Functions: creat fcntl open /* #include #include */ These header files are NOT specified by POSIX. POSIX specifies an fcntl interface to locking. If your system doesn't have lockf you should define NEED_LOCKF as described later in this file. #define osi_ExclusiveLockNoBlock(fid) lockf((fid), F_TLOCK, 0) osi_ExclusiveLockNoBlock tries to get a lock, and returns immediately if it is unable to get the lock. #define osi_UnLock(fid) lockf((fid), F_ULOCK, 0) osi_UnLock unlocks the file. #define osi_O_READLOCK O_RDWR The mode needed in the open flags in order for locking to be done. #define osi_F_READLOCK "r+" Like O_READLOCK, except for fopen. #define osi_vfork() fork() osi_vfork should be the fastest available fork, on some systems the child created by osi_vfork will suspend it's parent until an exec call and will share the address space of the parent until the exec. #define osi_setjmp setjmp #define osi_longjmp longjmp If your system requires any special handling of setjmp and longjmp modify osi_setjmp and osi_longjmp, you will probably have to update some of the sources as well as modifying these macros. struct osi_Times {unsigned long int Secs; unsigned long int USecs;}; Set one of the above with a call to osi_GetTimes(&foo) #define osi_GetSecs() time((long int *) 0) Get the seconds since Jan 1, 1970 1200:00. #define osi_SetZone() tzset() Initialize the timezone. #define osi_ZoneNames tzname Get the timezone name. #define osi_SecondsWest timezone Get the SecondsWest of the current timezone. #define osi_IsEverDaylight daylight True if daylight savings time is in effect. BEGINCPLUSPLUSPROTOS extern int osi_GetTimes(struct osi_Times *p); ENDCPLUSPLUSPROTOS #define setlinebuf(file) setvbuf(file, NULL, _IOLBF, BUFSIZ) If your system has setlinebuf in libc you can remove this line. #define HAS_SYSEXITS 1 HAS_SYSEXITS should be one if the file /usr/include/sysexits.h exists. #define BIT_ZERO_ON_LEFT 1 BIT_ZERO_ON_LEFT should be one if Most Significant Bit is on the left, if the byte order is not simply Most to Least significant bits from left to right or right to left code may need to be updated. #undef SCANDIRSELFUNC #undef QSORTFUNC #define SCANDIRSELFUNC(x) (( int (*)(const struct dirent*))x) #define QSORTFUNC(x) ( ( int (*)(const void *, const void *))x) #define bcopy(src, dst, length) memmove(dst, src, length) #define bzero(b, length) memset(b, 0, length) #define bcmp(region1, region2, length) memcmp(region1, region2, length) #define index(str, ch) strchr(str, ch) #define rindex(str, ch) strrchr(str, ch) These old style memory and string functions should be provided here for now unless your system supplies them by default. #define killpg(pgid, signal) kill(-(pgid), signal) Sends a signal to all the processes in the indicated process group. If you have killpg in libc you can delete this. #endif /* !In_Imake */ #define GETDOMAIN_ENV 1 GETDOMAIN_ENV should be defined as 1 if the getdomain() function is defined and can be concatenated with the result of gethostname to make a fully qualified hostname. /* Now follow the site-specific customizations. */ #include #define NEED_LOCKF 1 This is needed on platforms which don't have lockf. (Most platforms will need this defined.) #endif /* SYSTEM_H */ The file AndrewCoding.ez describes a number of functions which applications can use. If these should be other than the default, you will need to define them for your environment. NEED_ANSI_TMPFILES (defaults to undefined) If your libc does not contain the functions tmpnam and tmpfile you will need to define this in your system.h. (Only for use by porters.) NEED_LOCKF (defaults to undefined) If your libc does not contain the functions lockf and unlockf you will need to define this in your system.h. (Only for use by porters.) NEED_UTIMES (defaults to undefined) NEED_INSREMQUE (defaults to undefined) NEED_RANDOM_MAPPED_TO_RAND48 (defaults to undefined) These are hacks necessary to use AFS on an HP running HP-UX9.0 and AFS 3.2. (Only for use by porters.) 3.4 What Goes in a system.mcr File The system.mcr file is included in all Makefiles, after being processed by cpp. Macros defined in system.mcr are related to such issues as, "where is the X11 bin directory" and "what are the debug flags to be passed to the compiler." XBINDIR = /usr/local/bin CDEBUGFLAGS = -g In the config macro files, you should *only* set the values of various Make variables. It is OK to set these Make macros based on the state of the cpp, for instance: #ifdef POSIX_ENV STD_DEFINES = -D_POSIX_SOURCE -D_ALL_SOURCE #endif See the README file for a list of all the make variables that you may need to set. The most important variables to set are: CPPSTDLIB The standard C++ library, either full pathnames or a combination of -L and -l flags. GCCLIBDIR If you are using gcc this should be the path to the gcc library directory. With recent versionf of gcc (2.6.x) you can run: gcc --print-file-name "" To print the path which GCCLIBDIR should be set to. The path should be enclosed in double quotes. GCCLIB This should be set to $(GCCLIBDIR)/libgcc.a. 4. Shared Libraries The Andrew User Interface System allows ATK libraries to be shared libraries. This helps save both disk space and virtual memory. Since there is no universal standard for how shared libraries are created you will have to consult your system documentation to determine the exact details needed to implement ATK shared library support for a particular platform. 4.1 Information Sources man ld man cc (an ANSI C compiler) man CC (the C++ compiler) man ld.so (possibly) (Depending on your system you may need or want to use compilers other than cc or CC.) 4.2 Compile-Time Flags On some systems additional compile time flags are required or recommended when compiling a source file to be included in a shared library. For example SunOS 4.1 requires the -pic or -PIC flags. (-fpic and -fPIC with gcc.) Under SVR4 systems a similar flag may be required. Any flags needed should be put in the COMPILERFLAGS make variable by the system.mcr file. Possibly conditional on a #define to indicate what compiler is being used. If different flags are needed by the C and C++ compiler then COMPILERFLAGS should be set as appropriate for the C compiler and CPPCCOMPILERFLAGS should be set as appropriate for the C++ compiler. 4.3 mkatkshlib Script This script is responsible for actually producing a shared library from a list of object files and libraries. mkatkshlib is run by mkatklib as follows: $basedir/etc/mkatkshlib $name $basedir "$linkprefix" $* $name is the base name of the library to be created. The final name is currently libname.a. $basedir is the $ANDREWDIR where any AUIS programs or data needed by the script should be found. $linkprefix is usually "$basedir/bin/relativize ---". This program helps allow the shared libraries to be moved on some platforms by linking them in with -lfoo instead of full pathnames. (Notably SunOS 4.1 had the restriction that a shared library or executable linked against a shared library by a full path wouldn't work if the shared library were moved.) You can set the linkprefix by setting the LINKPREFIX make variable in the system.mcr file. $* is the rest of the arguments including the object files, libraries and any flags from the ATKLIBLDARGS make variable. (You can set ATKLIBLDARGS in the system.mcr or simply hard code values into the mkatkshlib script if appropriate.) The link line might look something like: $linkprefix CC -G -o lib$name.a $* See config/hp700_90/mkatkshlib or config/rs_aix3/mkatkshlib for an example. 4.4 Shared Library Export Symbols With some shared library implementations each symbol to be exported by a library must be listed. On such systems you will need to use nm or another program to list the symbols defined in the object files and produce a list suitable for the way exported symbols are specified on your platform. You should take care that all C++ class functions and any necessary symbols used internally by the C++ implementation are included in the export list. In addition if there is a name.sym file in the directory where mkatkshlib is run it should be consulted for a list of non-class functions which should be included. (Where name is the name of the library under construction.) The symbols named in name.sym should be included regardless of name mangling. For example a foo_Bar__Fv symbol might be the definition of the function foo_Bar() and should be included if name.sym has foo_Bar as one of it's entries. You may need to give nm or whatever other program you use flags to indicate that it should NOT report demangled symbol names. For example the function foo_Bar(int) might be displayed as foo_Bar__Fi in mangled form, or foo_Bar(int) in demangled form. Depending on the tools provided for building shared libraries you may need one form or the other in the export list. Usually the mangled form will be used in the export list. If a separate 4.5 Constructors and Destructors C++ classes can have special functions to be called to initialize an object before use and to clean it up prior to it's deletion or program exit. Global and static objects must have the constructor called to initialize them before any function in the file containing them is executed. Usually this is ensured by having the constructors for all such objects called before the main function is called. (Or as the very first thing the main function does.) This is sometimes implemented during program linking by having the linker scan the object files looking for objects which need such a call and constructing a function to perfom those calls. But sometimes the linker isn't made aware of how to do this for shared libraries. In other cases the linker deals with the issue when the shared library is created or when an executable is linked against the shared library. 4.6 Shared Library Search Paths For a program linked against shared libraries to function the libraries must be available when the program is run. Usually as long as the libraries are located on the same path at run time as they were at link time there will be no problem. However one of the design goals of AUIS is that it should be possible to move the binaries and execute them from an arbitrary path. Probably every system which supports shared libraries will support some means of setting a search path for shared libraries, usually by an environment variable such as LD_LIBRARY_PATH. On some systems it may be necessary to link against shared libraries with -Ldir and -lname directives instead of dir/libname.so, in order to avoid hardcoding the path names into the executable. If this is a problem the LINKPREFIX make variable in the system.mcr file can be set to: $(BASEDIR)/bin/relativize $(LOCALNORELS) $(NORELS) --- 4.7 Standard System Libraries Shared libraries generally need symbols from at least the standard C and C++ libraries. Some system libraries may be supplied only as archive libraries. For these libraries you should arrange for the shared libraries to get the symbols via the executable rather than linking in the archive library directly. Otherwise there may be code and/or data duplicated between the executable and shared libraries, or between different shared libraries. This can lead to unpredictable results as some functions such as the C++ iostream code, and the libc malloc functions expect that each process will have only one copy of the code and data. The C library itself is usually available as a shared library, but C++ libraries are often distributed only as archive libraries. The C++ libraries also vary in naming, for example: libC.a, libg++.a, libiostream.a, etc... You should use the make variable ATKLIBLDFLAGS to ensure that a shared library is linked against the appropriate libraries. (Or make sure it gets the symbols another way, from the executable for example.) If the system provides a shared C++ library simply setting CPPSTDLIB to point to the standard C++ library should suffice. (None of the current ATK code uses anything beyond iostreams.) SYS_OVERHEADDIR If for any of the above reasons you need to introduce utility programs, or do anything else specific to a particular platform during the build you can define this as follows in the system.h: #define SYS_OVERHEADDIR $(SYS_CONFDIR) Then create the appropriate directory in overhead. For example you might use this if the compiler and linker don't handle constructors/destructors for global objects in shared libraries. (By implementing an aexelink program to create the ATK_IniList and ATK_FiniList lists for use with the NEED_ATKINIFINI support provided in ossupport/oscommon.c, libatkos.a. Note that if you are using dynamic loading aexelink should be implemented in overhead/dynlink/$(SYS_DYNDIR).) 4.8 Testing By default the support for ATK Libraries (shared or not) will be tested for a few common failings in atk/basics/testing, just before the first real ATK library is created. This testing will detect whether proper precautions have been taken to ensure that only one copy of the iostream library is used by both the libraries and the executable, and that constructors and destructors for global objects defined in libraries are called. The possible messages from the test program are shown below. ERROR: The shared library seems to have a copy of cout separate from the one used by the executable.\nThis could cause iostream input/output to be mangled or not work at all. OK: The shared library seems to have the same copy of cout as the executable. ERROR: The constructor for testVar was not run before testing::Run was called. OK: The constructor for testVar was run before testing::TestA was called. INFO: The constructor for testVar was run after main() started.\n You cannot use the -ctor flag for mkdynmain.\n (This only matters if you are implementing dynamic loading.) 5. Dynamic Loading -- $/overhead/dynlink The machine-dependent sub-directories of dynlink implement the dynamic loading feature of ATK for particular combinations of hardware and operating system. 5.1 Overview of Dynamic Loading for C++ and ATK Dynamic loading is a process whereby the code that implements a particular class is loaded into a running process when called by key sequence or menu item, or by an attempt to add an inset to a document. For instance, if I have a multimedia filesystem browser it is likely that during the course of browsing I will run across multimedia compound documents containing references to objects of arbitrary classes. If those classes have already been used within the process, then a description of them exists and instances can be created. If the class description is not in the current process, the class has not been previously used and the system needs to find the proper "dynamic object" to load, to obtain a description of the class so that a copy can be instantiated. The dynamic loading system is dependent on what services are offered by the OS. Newer OS's provide shared library and dynamic loading support. A shared library is similar to a dynamically loaded class in that the code is not actually included in the executable, and it may not even be loaded until needed. Even when it is attached, the text portion of the library code is shared among all the processes using the library while each process has it's own copy of the data segment. On systems that support shared libraries (IBM RS/6000, HPUX, SunOS) the task of actually loading the code into the running process is greatly simplified as it is provided by a system call. In more archaic OS's (BSD), the task of actually loading an external object module is complicated and calls for additonal steps. 5.2 Class with Shared Libraries On platforms that support shared libraries, system calls are often provided that make it possible to attach a module to the running process and to lookup the address of symbols within that attach module. On SYSV platforms the set of system calls are dlopen, dlsym, dlerror, and dlclose. The modules that can be manipulated by these shared library services must be compiled such that they contain no symbols that absolutely reference other elements of the object file. This type of module contains what is called position-independent code (pic). On the RS/6000, all code generated by the stock compiler is pic by default. On other platforms you may need to specify to the compiler that pic is desired by setting the PICFLAG macro in that platform's system.mcr file. It would be nice if we could just compile each and every module as position-independent but there are compiler & runtime limits under certain platforms that prevent that simple-minded solution. One notable example of this problem is under SunOS4.1.x. where we must either compile both pic and non-pic of each module or stick to non-pic code to avoid a stub table overflow. 5.3 Class without Shared Libraries On platforms that do not support shared libraries, the symbols found in a module to be dynamically loaded must all be manually relocated in the running processes address space. This is a very complicated matter as it gets into the details of the object file format for a particular operating system. Luckily there are some defacto-standards for object file formats: a.out, COFF, XCOFF, and ELF. Of these, only a.out and COFF are any trouble because the others come from OS's that support shared libraries. In the machine-dependent class directory, there are several implementations of symbol relocation for a.out format (see $/overhead/class/machdep/aos_rt/class.c). There are certain routines in the C library that rely on local data. Malloc is one of these routines. The code for these routines must be gathered up and linked into the main process (called runapp) and also these routines must be excluded from the dynamic objects. The rest of the routines in the C library must be wrapped up and put into an auxillary library known as libcx.a. It is libcx.a that is linked against the object files that implement a class in the machine-dependent file ATKOLinkI.C. ATKOLinkI's purpose is to run the link-editor (aka: ld) on the the object files that implement a class, explicitly specifying the resultant file's entrypoint, and resolving any external references to symbols in libcx.a, and the list of globals that will be found in runapp. The list of globals which will be found in runapp includes those sections of libc.a that are excluded from libcx.a and those exported from C++ ATK libraries statically linked into runapp. The choice of symbols to be included in libcx.a is made in the machine-dependent Imakefile in overhead/dynlink/system-name via various nm-related hacks that are very ugly. (See pmax_ul4 for an example.) ATKELinkI.C is responsible for linking an executable such that the symbols in libc.a which were excluded from libcx.a and the symbols exported by any C++ ATK libraries are available for the dynamic loading code to resolve symbol references in a dynamic object. The following fragment should be placed in the system.mcr if this support is needed: AEXELINK=ANDREWDIR=$(BASEDIR);export ANDREWDIR;$(BASEDIR)/etc/aexelink ATKLIBFLAGS=-d '$(BASEDIR)/etc/alibexp' Where alibexp should be installed by overhead/dynlink/system-name/Imakefile, and alibexp is used by mkatklib to create name.exp. name.exp should have any information needed by aexelink to handle giving dynamic objects to the symbols in C++ ATK libraries. Given the ATKLIBFLAGS setting above alibexp is run as follows from config/mkatklib: $(BASEDIR)/etc/alibexp name basedir "linkprefix" object files and libraries The system.h file should then define InstallATKExportsTarget as follows: #undef InstalLATKExportsTarget #define InstallATKExportsTarget(target,name,dest) @@\ target:: name.exp @@\ $(INSTALL) $(INSTINCFLAGS) name.exp dest/name.exp If dynamic objects cannot be statically linked into executables then you should also define: #undef ATKExportsLibrary #define ATKExportsLibrary(dobj,objs,libs,syslibs,extraargs) ATKLibrary(dobj,objs,libs,syslibs,extraargs) #undef InstallATKExportsLibrary #define InstallATKExportsLibrary(dobj,dest) InstallATKLibrary(dobj,dest) 5.4 Common Features of Both Kinds of Platforms ATKOLinkI.C should perform any massaging of the link line needed to produce a dynamic object. (Possibly removing libraries, adding arguments, etc...) The following fragment should be placed in the system.mcr if this support is needed: DYNLINKPROG =ANDREWDIR=$(BASEDIR);export ANDREWDIR;$(BASEDIR)/etc/adynlink $(CPPC) The machine dependent directory should also install a libATKDynload.a library. This library should implement the function: extern "C" int (*ATKDoLoad(const char *path, int debug))(int argc, char **argv) { } This function takes a path to a dynamic object, and a non-zero flag if debugging output should be generated. It returns a point to a function returning int and taking an int and a char **. (ie a pointer to a function with the prototype usually associated with main.) When a dynamic object is loaded (attached to a running process), it's entrypoint is looked up and called. This entrypoint is often called main. The main function registers the classes which were included in the object and causes any constructors for global and static C++ objects to be called. config/mkdynmain is a csh script provided to generate the main function. To set up mkdynmain: MKDYNMAIN=$(BASEDIR)/etc/mkdynmain -ctor or MKDYNMAIN=$(BASEDIR)/etc/mkdynmain [- EntryFunctionName] (Where the brackets are removed and EntryFunctionName is changed as appropriate.) The -ctor version can be used only if the constructors and destructors for global objects in dynamic objects will be called appropriately. (See the Testing section under Shared Libraries above.) Otherwise the second form must be used. 6. Console Statistics -- $/atk/console/stats//getstats.c Getstats runs as a separate process extracting information from the kernel and passing it to the 'console' application. (A separate process is needed because it must be setuid to root on some platforms.) Information reported includes disk occupancy (% full) and a host of statistics from /dev/kmem including CPU load, I/O load, and VM occupancy. Getstats extracts info at fixed intervals; for each cycle and each datum, it prints a line to stdout. The parent program (Console, or any other program which wishes to get at this information) is responsible for setting up a pipe, binding the child's (this program) stdout to one end of a pipe, and parsing the strings which are passed back. The format of each line is an ID (int), a colon, a value (int), and optionally another colon followed by a string. The ID is coded from the included file "getstats.h". The main program in $/atk/console/stats/common/gsmain.c calls on three functions which must be defined in $/atk/console/stats//getstats.c: InitGVMStats() Do any required initialization. Typically, this means reading the namelist associated with the kernel to find the locations of the information. GetGVMStats(int UsersID) Send lines to stdout for each relevant statistic in ../../lib/getstats.h. The UserId canbe used to distinguish processes belonging to this user from other users. GetDiskStats(int Init) If Init is TRUE, send lines to stdout giving the mount point of each disk. Otherwise send lines giving the percent of each idsk which is occupied. The ID in these messages will be DISK1, DISK2, ... . 7. Portability Macros We have introduced many portability macros in order to keep the sources as clean as possible and to ease the burden of porting the sources to a new platform. See the Portability Macros section in $/CodingStd.ez. 8. System Definition Variables In addition to the variables described in $/README and $/CodingStd , the following may be #defined in $/config//system.h file #define LIBDL_ENV 1 This variable should be defined iff dynamic loading is to be implemented with the SunOS or SYSV dlopen interface. #define HAVE_SHARED_LIBRARIES 1 HAVE_SHARED_LIBRARIES indicates whether the system supprts shared libraries. If this is defined then INSTALL_SHLIB_SUPPORT should also be defined. #define INSTALL_SHLIB_SUPPORT() InstallFileToFile($(SYS_CONFDIR)/mkatkshlib, $(INSTPROGFLAGS), $(DESTDIR)/etc) INSTALL_SHLIB_SUPPORT should install mkatkshlib and any other files needed to support the creation of shared libraries on your system. #define HAVE_DYNAMIC_LOADING 1 If the dynamic loading support has been implemented for this platform this should be defined. #define HAVE_DYNAMIC_INTERLINKING 1 This should be defined if support for calling functions in one dynamic object from another dynamic object has been implemented for this platform. Settable in $/config//system.mcr: PICFLAG = $(PICFLAG) should have cc switches appropriate to compiling a .c file for inclusion in a shared library or dlopenable object. POSIX Emulation Note that every effort should be made to provide emulation of POSIX and ANSI functions for non ANSI/POSIX systems, for example old-style BSD systems. The emulation should be provided in a portability library (libatkos.a see below) or include file. Source code files should generally NOT be #ifdefed for POSIX_ENV or even specific OS features. Where possible and necessary macros should be used for constructs which vary from OS to OS. (e.g. struct direct becomes: DIRENT_TYPE, which would be struct dirent on POSIX systems and struct direct on non-POSIX systems.) As a general strategy when we can implement POSIX functions in terms of BSD functions and keep all the POSIX semantics we should provide a macro mapping the POSIX function name to our name for the function. (for tmpnam I used Andrew_tmpnam) Of course in cases like malloc where getting different versions of the function in different source files might become an issue, or where we can't get POSIX semantics with BSD code we should provide a slightly higher level macro which provides the particular features needed by our code. (e.g. NEWPGRP() creates a new process group, abstracting away the ability to set the process group to an arbitrary number.) BSD versions of POSIX functions should be placed in andrew/ossupport/oscommon.c. (The source file for libatkos.a) They should be proctected by a #ifdef NEED_XXX_WHATEVER. Any #defines or function declarations needed should be placed in atkos.h and proctected by a #ifdef NEED_XXX_WHATEVER. If a system needs a particular feature provided in libatkos.a the system.h file should have: #define NEED_XXX_WHATEVER 1 . . . #ifndef IN_ATKOS_LIB #include #endif The system.mcr file should have: SUPLIB = $(BASEDIR)/lib/libatkos.a /* it may need more depending on whether there was a pre-existing setting for SUPLIB */ (as many NEED_* macros as are needed may be defined before the inclusion of atkos.h) (XXX_WHATEVER should be replaced by a descriptive name for the feature provided) Currently libatkos.a provides NEED_ANSI_TMPFILES, which will provide the tmpnam and tmpfile functions from ANSI C. All #ifdefs in libatkos.a should be based on #defines descriptive of the feature they fix or add. The appropriate #defines should then be placed in the system.h files for the systems needing those fixes or additions. libossupp.a is obsolescent. New features should not be added to it, instead, they should be added to libatkos.a. libossupp.a features should be moved into libatkos.a as resources permit. 8.1 config/system_type/system.h See config/protosys.h. If your system is non-POSIX or doesn't have an ANSI libc you should put appropriate BSD compatible definitions of the OS dependent macros and additional macros mapping ANSI mem* and str* functions to the BSD equivalents. (In general the macros should take the same arguments as the function and pass the arguments on to the function. This will hopefully avoid some problems with structure members which have the same names as the functions being #defined.) On many platforms and compilers specialized hacks will be needed in system.h to correct bad or missing prototypes and to ensure that all prototypes for C functions are enclosed in extern "C" { .... }. As of this writing HP is the only manufacturer known to have mostly C++ compatible system header files. The following #define's may need to be redefined or undefined in the system.h file. AMS_SUBSCRIPTIONMAPFILE [Default: ".SubscriptionMap" or ".SubsMap"] This is the name of one of the files AMS uses to store information about the bboards which exist. For historical reasons it defaults to .SubscriptionMap unless compiling on an HP or a SysV system (where M_UNIX is defined). The reason for the distinction is the limitation of these systems to 14 character filenames. If bboards will be stored on filesystems with this limitation all clients which access them must be compiled with #define AMS_SUBSCRIPTIONMAPFILE ".SubsMap" in the site.h file. If you're not sure and don't have any existing AMS bboard trees the ".SubsMap" setting is safe for all systems. If you have an existing AMS bboard tree you can check which setting to use with ls -a ..../.MESSAGES/.Subs* (Where .... is replaced with the path to the top of the bboard tree.) PRE_X11R4_ENV [Default: not defined] PRE_X11R4_ENV should be defined if you will be linking against X11 header files and libraries that come from versions of X11 prior to the fourth release (X11R4). This information is needed because release 4 defines some new variable types and makes use of ANSI C function prototypes. DPS_ENV [Default: not defined] DPS_ENV should be defined if your systems support the Display PostScript extension to X Windows. IBM's Xv11r3 server product and DEC's DecWindows product both have this extension, while the MIT servers typically do not. Defining this variable will cause some code to attempt to link against the DPS libraries. It will also cause some code to attempt to contact the DPS extension of an X server at runtime. ANDREW_MALLOC_ENV [Default: defined] ANDREW_MALLOC_ENV, if defined, causes the Andrew Toolkit memory management package to be used. This memory allocator package not only saves VM space but also provides more error detection, when compared to many of the memory allocators distributed with Unix systems. On some system platforms, use of this allocator has led to multiply defined symbols. If this occurs, you can undefine this symbol and rebuild atk/basics and atk/apps. DEBUG_MALLOC_ENV [Default: not defined] DEBUG_MALLOC_ENV is defined if the debugging version of the Andrew Toolkit memory management package should be used. Its definition implies the definition of ANDREW_MALLOC_ENV. NO_FONTS_ENV [Default: not defined] NO_FONTS_ENV controls whether or not the Andrew fonts will get built. Some sites, that make heavy use of Xterminals or support many different display types, may find it convenient to not convert the fonts to any specific server format. By default this symbol is not defined and, thus, the fonts are created and installed during the build process. Define this symbol in your site.h file if you do not want the Andrew fonts to be built. FONTS_TO_BDF_ENV [Default: not defined] FONTS_TO_BDF_ENV controls whether or not the Andrew fonts will be converted into their Server Normal Format (.snf) during the build process. It may be convenient to leave the fonts in Bitmap Distribution Format (.bdf) when it is necessary to convert these to various different Server Normal Formats corresponding to the various X servers that may exist at your site. If you define this symbol the result will be that all of the Andrew fonts will be installed into ${DESTDIR}/X11fonts in BDF. You can then run self-created font conversion scripts to go to the various final formats. FONTS_TO_PCF_ENV [Default: defined] FONTS_TO_PCF_ENV controls whether the Andrew fonts will be converted into the .pcf format during the build process. If this is defined, you should ensure that XFC is a valid path to your bdftopcf compiler. OPENWINDOWS_ENV [Default: not defined] If you want to run Andrew applications under Open Windows, define this symbol in your site.h file. If you define this symbol, you should set your path to include the Open Windows binaries (usually /usr/openwin/bin). Open Windows is available only on Sun platforms. As such, all Sun site files define a CONVERTFONT macro to be /usr/openwin/bin/convertfont. You can override this default value in your site.mcr file. OLD_ULTRIX_ENV [Default: not defined] Some older version of the Ultrix operating system had a bug that caused passwords to be echoed in the typescript program. Define this symbol in your site.h file if you are using a version of Ultrix that has this bug. CONTRIB_ENV [Default: not defined] CONTRIB_ENV controls the construction of the contributed software found under source directory $/contrib. At present, this includes a growing collection of interesting and valuable utilities and objects, including various classes for viewing programming language text files, a slew of utilities and classes submitted by MIT (such as header/footer, note, ps), an audio inset from Bell Labs, a subclass of textview that recognizes gestures (gtextv), and the termulator shell interface (tm). ISO80_FONTS_ENV [Default: defined] ISO80_FONTS_ENV controls which text fonts are used by Andrew applications. If ISO80_FONTS_ENV is defined, then a font.alias file is installed to supply pointers to the X11 fonts that comply with the ISO 8859 defined international character set. For sites that have these fonts, this is the preferred option, since it will make accented characters available to users and programmers in most applications, including messages. See the cpchar help file for details on how to use them. This option also provides better behavior when used with R5's scalable fonts, and with 100dpi fonts, and it also eliminates the need for additional fonts to be installed in the destination directory. The only known drawback is that these fonts are not as carefully tuned as the their Andrew counterparts. RESOLVER_ENV [Default: defined] RESOLVER_ENV is defined if the Internet Domain Name Resolver is to be used. See also the discussion for the symbol RESOLVLIB in the section describing the *.mcr files, because if RESOLVER_ENV is defined, RESOLVLIB will be used as the path to the resolver library routines. DITROFF_ENV [Default: defined] DITROFF_ENV is defined if ditroff is available for printing Andrew Toolkit documents. (See installation of printing.) LOCAL_ANDREW_SETUP_ENV [Default: not defined] The AndrewSetup mechanism, described in $/overhead/util/lib/setup.help, is used for specifying system options to Andrew software at execution time. LOCAL_ANDREW_SETUP_ENV is defined if an additional path (or paths) for the AndrewSetup file should be compiled into Andrew software. Andrew software has many options that may be re-bound dynamically with the AndrewSetup mechanism (cf. setup.help), where a configuration file is read in at execution time. (One of the options that may be re-bound, for example, is the location of the installed Andrew software.) One option that cannot be configured by the AndrewSetup mechanism is the location of the AndrewSetup configuration file itself. Instead, Andrew software searches a path to find the AndrewSetup file to use. The LOCAL_ANDREW_SETUP_ENV option is the way that the Andrew installer may specify that Andrew software look in additional locations for the AndrewSetup file. Andrew software looks in the following five (or more) locations for an AndrewSetup file: /AndrewSetup /etc/AndrewSetup $(LOCAL_ANDREW_SETUP_ENV) /usr/vice/etc/AndrewSetup $(DEFAULT_ANDREWDIR_ENV)/etc/AndrewSetup $ANDREWDIR/etc/AndrewSetup (These alternatives have arisen from feedback about how typical sites protect their system directories.) If any file is found in this path, its values are used and no further files are examined; otherwise, compilation-time default values are used. The default condition for the LOCAL_ANDREW_SETUP_ENV option, that it not be defined, specifies that only those five locations are read. If LOCAL_ANDREW_SETUP_ENV is defined, it should be a path name of an AndrewSetup file, in double-quotes. It may also be a comma-separated list of double-quoted path names if many paths should be checked. An AndrewSetup file could, for example, contain the line AndrewDir: "full path of andrew tree base not in quotations" RequiredSubsFile: /usr/lib/RequiredSubscriptions DEFAULT_LOCALDIR_ENV [Default: "/usr/local"] DEFAULT_LOCALDIR_ENV controls where to find locally-installed information. Only a few options are specified via this ``local'' directory; two examples are the name of a library of console files and the name of the file that names the folders to which all users must subscribe (via AMS). Andrew software's idea of the ``local'' directory may be overridden by either the value of the LOCALDIR environment variable or the value of the AndrewSetup option ``LocalDir''. NDBM_ENV [Default: defined for only some platforms] NDBM_ENV controls whether some parts of AMDS, the Andrew Message Delivery System, can use the ``ndbm'' package to manage small local databases. GETDOMAIN_ENV [Default: defined for only some platforms] GETDOMAIN_ENV, if defined, says that the getdomainname(2) call is available on this system and may be concatenated with the result of gethostname(2) to obtain a fully-qualified domain name for the local machine, for use by AMS. While this option is not defined in the distributed allsys.h file, it is defined in the platform-dependent system.h file for all Suns, for Vax BSD, and for Vax Ultrix version 3.0 and later. RELEASE2_ENV [Default: not defined] RELEASE2_ENV controls the use of some X.V11R2 specific files. By default, this is undefined (which then assumes an X11 release 3, 4, or 5 environment). This only affects which font compiler (fc versus bdftosnf) is used, how aliases for fonts are generated, and some workarounds for early bugs in the Xlib region code. config/system_type/system.mcr See config/protosys.mcr. The following make variables may need to be overridden in the system.mcr file. CDEBUGFLAGS [Default: -O] CDEBUGFLAGS are passed to the C compiler when compiling programs. XBASEDIR [Default: /] XBASEDIR should point to the root of your installed X tree. X include files are assumed to be in $(XBASEDIR)/usr/include/X11. Xlib and bdftosnf are also found in this tree. If your compiler cannot handle paths like ``//usr/include/X11'' (with the double slash), you may wish to redefine this as the null string. XINCDIR [Default: $(XBASEDIR)/usr/include] XLIBDIR [Default: $(XBASEDIR)/usr/lib] XBINDIR [Default: /usr/bin/X11] XBINDIR should point to the location of the X bin directory under the XBASEDIR. Do not include XBASEDIR in your definition of XBINDIR XUTILDIR [Default: /usr/bin/X11] As is the case with XBINDIR, XUTILDIR should also point to the location of the X bin directory under the XBASEDIR. Do not include XBASEDIR in your definition of XUTILDIR IMAKE [Default: $(XUTILDIR)/imake] XMAKEDEPEND [Default: $(XUTILDIR)/makedepend] XMKFONTDIR [Default: $(XBASEDIR)/$(XBINDIR)/mkfontdir] XFC [Default: RELEASE2_ENV implies $(XSRCDIR)/fonts/compiler/fc, FONTS_TO_PCF_ENV implies $(XBASEDIR)/$(XBINDIR)/bdftopcf, otherwise $(XBASEDIR)/$(XBINDIR)/bdftosnf] RESOLVLIB [Default: empty string] RESOLVLIB denotes the full path of the domain name resolver library. It is used only if RESOLVER_ENV is defined, which it is unless your system.h or site.h file undefines it. The default value (the empty string) is useful if the resolver code is in your libc.a. If the resolver code is in a separate library, such as /usr/lib/libresolv.a, that name should be the definition for RESOLVLIB; define it in your site.mcr file. The programmer's interface to the resolver library has changed over time. The file overhead/mail/lib/valhost.c (which is built into DESTDIR/lib/libmail.a) makes calls to different versions of that programmer's interface, using the fact that definitions in the resolver's exported ``include'' files changed slightly with successive releases. In particular, it checks for the definition of NO_DATA in the 4.8 version of /usr/include/netdb.h and for the definition of CQUERYM in the pre-4.7.3 version of /usr/include/arpa/nameser.h. If your versions of these include files correspond to the version of the resolver named by RESOLVLIB (or libc.a otherwise), you will have no trouble with its interface to Andrew. The overhead/mail/lib/valhost.c file contains suggestions for what to do if this is not the case. INSTALL [Default: $(BASEDIR}/etc/install] INSTALL denotes the name of the install program on your system. If you do not have an install program, or if your install program does not work, edit the site.h file and: #define BUILDANDREWINSTALL_ENV 1 and then re-make your Makefiles (if already made) and continue from there. (The setting of INSTALL is based upon the setting of BUILDANDREWINSTALL_ENV and will be picked up correctly if set in the site.h file.) Additional definitions are unlikely to change. However, you may want to check these values: SHELL [Default: /bin/sh] SHELL specifies the path to the Bourne shell. CSHELL [Default: /bin/csh] CSHELL specifies the path to the C shell. CC [Default: cc] C compiler to use. CPPC [Default: CC] C++ compiler to use. PICFLAG [Default is empty] Set this to any compiler flags which are needed for compiling code to be included in a shared library or dynamic object. SHLIBLDFLAGS [Default is empty] If you will be supporting shared libraries add the flags here which tell your ld to create a shared library and export all symbols. DEFINES [Default is empty] Any special local defines which need to be passed on the compile line. ECOMPFLAGS [Default is empty] Add any extra flags which need to be added when linking with shared libraries here. This should be set only in the system.mcr file. COMPILERFLAGS [Default: $(ECOMPFLAGS) $(PICFLAG)] Any additional flags needed for both the C++ and C compilers may be added here. This should be set only in allsys.mcr and system.mcr. GCCLIB [Default is empty] Any extra system libraries which must be linked into shared libraries or dynamic objects. (Commonly it is libgcc.a if you are compiling with gcc, it can have other libraries in addition or instead of libgcc.a. MATHLIB [Default: -lm] If there is some problem with linking dynamic objects or shared libraries make this empty and make other arrangements for getting the math functions. SYS_LIBRARIES [Default is empty] If your platform needs extra system libraries linked into all executables and dynamic objects list them here. SUPLIBS [Default is empty] If your platform needs functions supplied in andrew/ossupport, this should be defined as $(DESTDIR)/lib/libossup.a LINKPREFIX [Default is empty] If your platform requires libraries to be referenced by -l in order to get shared libraries and to be able to move the libraries once they have been installed then define this to be: $(BASEDIR)/etc/relativize $(LOCALNORELS) $(NORELS) --- NORELS [Default is empty] If LINKPREFIX is set and there are libraries which should NOT be referenced via -l, add their full paths here. MALLOCALIGNMENT [Default: 8] If using the Andrew malloc this should be set to largest alignment needed for any data type on this system. 8 should be fairly safe. 8.2 config/platform.tmpl You will need to edit this file to test for the kind of platform and #include the appropriate system.mcr file, and #define MacroIncludeFile to the path of the selected file. (relative to the config directory) Usually there is some set of #defines set by the systems C preprocessor, and you can use these to determine which system file to include. If no distinguishing symbols are defined on your platform add a #define to the selsys.h file in config. (When you submit it to us comment out the definition and be sure to document for what systems it is appropriate to uncomment it.) As yet there is no system independent support for dynamic loading so you don't need to worry about writing the system dependent parts. To support shared libraries you will need to implement mkatkshlib for your platform and follow the instructions in system.h for modifying that file. See config/hp700_90 or config/rs_aix3 for example implementations of mkatkshlib. mkatkshlib should export all symbols in the listed object files. 9. $/config/system-type The $/config/system-type directory for your system type installs programs and scripts needed solely to support your system. This directory should include at least Imakefile system.h system.mcr getnms The Imakefile installs getnms in $ANDREWDIR/etc and installs other programs and scripts accordingly. However, the Imakefile does NOT install system.h or system.mcr. System.h and system.mcr have been described above. Getnms should be a script which processes its current directory and all subordinate directories checking each .o file. For each function name it finds, it should produce a line of output having the form: $/raster/lib/xwdio.o: xwdio::WriteRow That is, the source directory name--relative to the current directory--followed by a colon, a space, and the function name. For a standard UCB system getnms can be: #!/bin/sh find . -name "*.o" -exec /usr/ucb/nm -og '{}' \; | \ awk '/ T / {print ($0);}' Unfortunately, every vendor seems to have a different set of flags for nm and a different format for the output. 10. General Issues In general if there is some feature used in the code which your system does not support or supports with a different function, you should NOT #if the code. Instead add a macro to allsys.h and replace occurrences of the function call or code fragment with an invocation of the macro. The definition of the macro in allsys.h should be appropriate for POSIX systems, where possible. If a different version of the macro is needed for BSD systems, add an appropriate definition in bsdsys.h. 10.1 Filenames Filenames must be <=14 characters. On a system with a 14 character limit on filenames it may not be possible to put the sources in a version control system. Currently used extensions, any conflicting use should be avoided. C (C++ source) c (C source) l (lex source) y (yacc source) spp (assembly source, to be pre-processed) s (assembly source) rf (Library class references) lt (Library dependencies) o (object files) a (libraries) ez (ATK format text files) fi (figure files) zip (zip drawing editor files) raster (monochrome bitmap files in ATK format) gif (GIF standard picture files) tiff (TIFF standard picture files) jpeg (JPEG standard picture files) lib (Currently used for Imakefile.lib and Makefile.lib) exp (Shared library export lists) mac (Old Mac-paint format bitmaps) more??? 10.2 Reserved Extensions These extensions are known to be used for the indicated purpose, any conflicting use should be avoided. .cc (C++ source) .c++ (ditto) .cxx (ditto) .cpp (ditto) more??? 10.3 Extending ATK When you add a non-ATK library to the system you should update $ANDREWDIR/lib/genstatl/liborder by putting the library's installed path name in the appropriate place. (before any libraries it needs.) Copyright Carnegie Mellon University 1996. All rights reserved. $Disclaimer: # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, provided # that the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of IBM not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. # # THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD # TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ANY COPYRIGHT # HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL # DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, # DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # # $