head 3.1; access; symbols; locks; strict; comment @.\" @; 3.1 date 95.09.03.15.35.34; author grog; state Exp; branches; next 3.0; 3.0 date 95.06.25.14.32.16; author grog; state Exp; branches; next 2.7; 2.7 date 95.06.25.10.14.16; author grog; state Exp; branches; next 2.6; 2.6 date 95.06.22.07.34.09; author grog; state Exp; branches; next 2.5; 2.5 date 95.06.09.06.16.55; author grog; state Exp; branches; next 2.4; 2.4 date 95.05.16.04.46.50; author grog; state Exp; branches; next 2.3; 2.3 date 95.02.11.13.09.39; author grog; state Exp; branches; next 2.2; 2.2 date 95.02.04.16.01.39; author grog; state Exp; branches; next 2.1; 2.1 date 95.01.23.09.27.51; author grog; state Exp; branches; next 2.0; 2.0 date 94.11.18.14.20.30; author grog; state Exp; branches; next ; desc @@ 3.1 log @Reference to config problem (cross-compiling make) @ text @.\" For emacs, this file is in -*- nroff-fill -*- mode .\" $Id: config.ms,v 3.0 1995年06月25日 14:32:16 grog Exp grog $ .\" $Log: config.ms,v $ .\" Revision 3.0 1995年06月25日 14:32:16 grog .\" Final draft .\" .\" Revision 2.6 1995年06月22日 07:34:09 grog .\" Final draft, first cut. .\" .\" Revision 2.5 1995年06月09日 06:16:55 grog .\" Remove date from page headers .\" Minor mods .\" .\" Revision 2.4 1995年05月16日 04:46:50 grog .\" Major mods after Andy's final draft review .\" .\" Revision 2.3 1995年02月11日 13:09:39 grog .\" Minor mods .\" .\" Revision 2.2 1995年02月04日 16:01:39 grog .\" Minor mods .\" .\" Revision 2.1 1995年01月23日 09:27:51 grog .\" Move stuff about BSD make config to make.ms .\" Minor mods .\" .\" .so global.ms .Se \*[nchconfig] "Package configuration" .St "Package configuration" Programs don't run in a vacuum: they interface with the outside world. The view of this outside world differs from location to location: things like host names, system resources, and local conventions will be different. Theoretically, you could change the program sources every time you install a package on a new system, but besides being a pain, it's very error-prone. All modern packages supply a method of \fIconfiguration\fR, a simplified way of adapting the sources to the environment in which the program will run. In this chapter, we'll look at common configuration conventions. We can divide system differences into one of three categories: .Pn configtypes .Ls B .Li The kind of hardware the package will run on. A compiler needs to generate the correct machine instructions, and an X server needs to know how to transfer data to the display hardware. Less well-written programs have hardware dependencies that could have been avoided with some forethought. We'll look at this in more detail in \*[chhard]. .Li The system software with which it will interact. Differences between UNIX systems are significant enough that it will be necessary to make certain decisions depending on the system flavour. For example, a communications program will need to know what kind of network interface your system has. Programs that come from other systems may need significant rewriting to conform with UNIX library calls. We'll look at these dependencies in part 2 of this book, from \*[chkdepend] to \*[chobj]. .Li The local configuration. These may include obvious things like the system name, aspects of program behaviour, information about tools used locally, or local system conventions. .Le In this chapter, we'll look at what local configuration entails, and \fIhow\fR we tell the package about our chosen configuration. .Ah "Installation paths" .XX "paths, installation" .XX "installation paths" Your system configuration may place constraints on where you can install the software. This is not normally a problem for individual systems, but on a large, heterogeneous network it could require more consideration. .LP .XX "/usr/local" Traditionally, non-system software has been installed in the hierarchy \fI/usr/local\fR. This is not an \(aesthetically pleasing location: the hierarchy can become quite large, and in a network many systems might share the directory. .LP One of the best thought-out descriptions of a modern file system structure is in the \fIUNIX System V Application Binary Interface\fR, which is also similar to structures used by SunOS and the newer BSD variants. In brief, it specifies the following top-level directories: .Pn file-system-structure .XX "file system organization" .IP "\fI/\fR" 14 .XX "/" The root directory. .IP "\fI/dev\fR" 14 .XX "/dev" The directory tree containing device files. .IP "\fI/etc\fR" 14 .XX "/etc" Directory for machine-specific configuration files. .IP "\fI/opt\fR" 14 .XX "/opt" Directory for add-on software. .IP "\fI/usr\fR" 14 .XX "/usr" This directory used to be \fIthe\fR other file system on a UNIX machine. In the System V ABI it has lost most of its importance. The ABI states uses only for \fI/usr/bin\fR and \fI/usr/share\fR, and the name \fI/usr\fR has lost its original meaning: the ABI specifies \fI/usr\fR only as a location for system files that users may wish to access. .IP "\fI/usr/bin\fR" 14 is intended for "Utility programs and commands for the use of all applications and users". In practice, it's better to use this directory for system programs only. .IP "\fI/usr/share\fR" 14 .XX "/usr/share" The System V ABI states that \fI/usr/share\fR is intended for "architecture-independent shareable files". In practice, those versions of System V that still have \fIman\fR pages put them in \fI/usr/share/man\fR, .XX "/usr/share/man" and \fIterminfo\fR data are stored in \fI/usr/share/lib/terminfo\fR. .XX "/usr/share/lib/terminfo" The rest of the directory may contain a few other odds and ends, but these two directories make up over 99% of the content. The choice of the location \fI/usr/share\fR is not a happy choice: firstly, it is frequently a separate file system, but it must be mounted on a non-root file system, and secondly the man pages aren't really architecture-independent. The choice makes more sense from the point of view of the Unix Systems Group, who are concerned only with pure System V: the man pages are mainly independent of hardware architecture. However, in a real-world net you probably have two or three different operating systems, each with their own man pages. .IP "\fI/var\fR" 14 .XX "/var" This directory contains files that are frequently modified. Typical subdirectories are \fI/var/tmp\fR for temporary files and \fI/var/spool\fR for printer output, \fIuucp\fR and \fInews\fR. .LP The System V ABI does not say anything about where to store user files. The Seventh Edition typically stored them as a subdirectory of \fI/usr\fR, but newer systems have tended to store them in a directory called \fI/home\fR. .LP The \fI/opt\fR hierarchy resembles that of \fI/usr\fR. A typical structure is: .IP "\fI/opt/bin\fR" 14 .XX "/opt/bin" for executables. .IP "\fI/opt/man\fR" 14 .XX "/opt/man" for \fIman\fR pages--not \fI/opt/share/man\fR, unlike the structure in \fI/usr\fR. .IP "\fI/opt/lib\fR" 14 .XX "/opt/lib" for additional files used by executables. In particular, this directory could contain library archives for compilers, as well as the individual passes of the compilers. .IP "\fI/opt/\fR" 14 .XX "/opt/" This is where the System V ABI places individual package data. Not many other systems follow it. .IP "\fI/opt/lib/\fR" 14 .XX "/opt/lib/" This is where most packages place private data. .LP Using the \fI/opt\fR hierarchy has one disadvantage: you may not want to have a separate file system. In modern systems, the solution is simple enough: place the directory where you want it, and create a symbolic link \fI/opt\fR that points to it. This works only if your system has symbolic links, of course, so I have come to a compromise: I use \fI/opt\fR on systems with symbolic links, and \fI/usr/local\fR on systems without symbolic links. .LP Many packages compile pathnames into the code, either because it's faster that way, or because it's easier. As a result, you should set the path names before compilation--don't put off this task until you're ready to install, or you may run into problems where the packages are all nicely installed in the correct place and look for data in the wrong directories. .Bh "Preferred tools" .XX "tools, preferences" .XX "preferences, tools" Many of the most popular software packages are alternative tools. Free software such as \fIgcc\fR, \fIemacs\fR and \fIperl\fR have become so popular that they are frequently supplied with proprietary system releases, and many other systems have ported them and use them as standard tools. If you want to use such programs, you need to tell the configuration routines about them. .LP Depending on the tools you use, you may also need to change the flags that you pass to them. For example, if you compile with \fIgcc\fR, you may choose to include additional compiler flags such as \f(CW-fstrength-reduce\fR, which is specific to \fIgcc\fR. .Ah "Conveying configuration information" .XX "configuration information, conveying" .Pn doconfig The goal of configuration is to supply the configuration information to the program sources. A good configuration mechanism will hide this from you, but it's helpful to understand what it's doing. In this section, we'll look under the covers--you can skip it if it looks too technical. .LP There are a number of possible ways to use configuration information: for example, the package may have separate communication modules for STREAMS and sockets, and the configuration routines may decide which of the two modules to compile. More typically, however, the configuration routines convey configuration information to the package by defining preprocessor variables indicating the presence or absence of a specific feature. Many packages provide this information in the \fImake\fR variable \s10\f(CWCFLAGS\fR\s0--for example, when you make \fIbash\fR, the GNU Bourne Again Shell, you see things like .Ps $ \f(CBmake\f(CW gcc -DOS_NAME='"FreeBSD"' -DProgram=bash -DSYSTEM_NAME='"i386"' \e -DMAINTAINER='"bug-bash@@prep.ai.mit.edu"' -O -g -DHAVE_SETLINEBUF -DHAVE_VFPRINTF \e -DHAVE_UNISTD_H -DHAVE_STDLIB_H -DHAVE_LIMITS_H -DHAVE_GETGROUPS \e -DHAVE_RESOURCE -DHAVE_SYS_PARAM -DVOID_SIGHANDLER -DOPENDIR_NOT_ROBUST \e -DINT_GROUPS_ARRAY -DHAVE_WAIT_H -DHAVE_GETWD -DHAVE_DUP2 -DHAVE_STRERROR \e -DHAVE_DIRENT -DHAVE_DIRENT_H -DHAVE_STRING_H -DHAVE_VARARGS_H -DHAVE_STRCHR \e -DHAVE_STRCASECMP -DHAVE_DEV_FD -D"i386" -D"FreeBSD" -DSHELL -DHAVE_ALLOCA \e -I. -I. -I././lib/ -c shell.c .Pe The \s10\f(CW-D\fR\s0 arguments pass preprocessor variables that define the configuration information. .LP An alternative method is to put this information in a file with a name like \fIconfig.h\fR. Taylor \fIuucp\fR does it this way: in \fIconfig.h\fR you will find things like: .Ps /* If your compiler supports prototypes, set HAVE_PROTOTYPES to 1. */ #define HAVE_PROTOTYPES 1 /* Set ECHO_PROGRAM to a program which echoes its arguments; if echo is a shell builtin you can just use "echo". */ #define ECHO_PROGRAM "echo" /* The following macros indicate what header files you have. Set the macro to 1 if you have the corresponding header file, or 0 if you do not. */ #define HAVE_STDDEF_H 1 /* */ #define HAVE_STDARG_H 1 /* */ #define HAVE_STRING_H 1 /* */ .Pe I prefer this approach: you have all the configuration information in one place, it is documented, and it's more reliable. Assuming that the \fIMakefile\fR dependencies are correct, any change to \fIconfig.h\fR will cause the programs to be recompiled on the next \fImake\fR. As we will see in \*[chbuild], page \*[No-dependency-on-Makefile], this usually doesn't happen if you modify the \fIMakefile\fR. .LP Typically, configuration information is based on the kind of operating system you run and the kind of hardware you use. For example, if you compile for a Sparc II running SunOS 4.1.3, you might define \f(CW\s10sparc\s0\fR to indicate the processor architecture used and \f(CW\s10sunos4\s0\fR to indicate the operating system. Since SunOS 4 is basically UNIX, you might also need to define \f(CW\s10unix\s0\fR. On an Intel 486 running UnixWare you might need to define \f(CW\s10i386\s0\fR for the processor architecture,\** .FS Why not \f(CWi486\fR? The processor is an Intel 486, but the architecture is called the i386 architecture. You also use \f(CWi386\fR when compiling for a Pentium. .FE and \f(CW\s10SVR4\s0\fR to indicate the operating system. This information is then used in the source files as arguments to preprocessor \f(CW\s10#ifdef\s0\fR commands. For example, the beginning of each source file, or a general configuration file, might contain: .Ps #ifdef i386 #include "m/i386.h" #endif #ifdef sparc #include "m/sparc.h" #endif #ifdef sunos4 #include "s/sunos4.h" #endif #ifdef SVR4 #include "s/usg-4.0.h" #endif .Pe You can get yourself into real trouble if you define more than one machine architecture or more than one operating system. Since configuration is usually automated to some extent, the likelihood of this is not very great, but if you end up with lots of double definitions when compiling, this is a possible reason. .LP Configuration through the preprocessor works nicely if the hardware and software both exactly match the expectations of the person who wrote the code. In many cases, this is not the case: looking at the example above, note that the file included for SVR4 is \fIs/usg-4.0.h\fR, which suggests that it is intended for UNIX System V release 4.0. UnixWare is System V release 4.2. Will this work? Maybe. It could be that the configuration mechanism was last revised before System V.4.2 came out. If you find a file \fIs/usg-4.2.h\fR, it's a good idea to use it instead, but otherwise it's a matter of trial and error. .LP Most software uses this approach, although it has a number of significant drawbacks: .Ls B .Li The choices are not very detailed: for example, most packages don't distinguish between Intel 386 and Intel 486, although the latter has a floating point coprocessor and the former doesn't. .Li There is no general consensus on what abbreviations to use. For UnixWare, you may find that the correct operating system information is determined by \f(CW\s10USG\s0\fR (USG is the Unix Systems Group, which, with some interruption,\** .FS The first USG was part of AT&T, and was superseded by UNIX Systems Laboratories (USL). After the sale of USL to Novell, USL became Novell's UNIX Systems Group. .FE is responsible for System V), \f(CW\s10SYSV\s0\fR, \s10\f(CWSVR4\s0\fR, \s10\f(CWSYSV_4\s0\fR, \f(CW\s10SYSV_4_2\s0\fR or even \s10\f(CWSVR3\s0\fR. This last can happen when the configuration needed to be updated from System V.2 to System V.3, but not again for System V.4. .Li .Pn HAS_RENAME The choice of operating system is usually determined by just a couple of differences. For example, base System V.3 does not have the system call \f(CW\s10rename\s0\fR, but most versions of System V.3 that you will find today have it. System V.4 does have \f(CW\s10rename\s0\fR. A software writer may use \f(CW\s10#ifdef SVR4\s0\fR only to determine whether the system has the \s10\f(CWrename\fR\s0 system call or not. If you are porting this package to a version of System V.3.2 with \f(CW\s10rename\s0\fR, it might be a better idea to define \f(CW\s10SVR4\s0\fR, and not \s10\f(CWSVR3\s0\fR. .Li Many aspects attributed to the kernel are in fact properties of the system library. As we will see in the introduction to Part 2 of this book, there is a big difference between kernel functionality and library functionality. The assumption is that a specific kernel uses the library with which it is supplied. The situation is changing, though: many companies sell systems without software development tools, and alternative libraries such as the GNU C library are becoming available. Making assumptions about the library based on the kernel was never a good idea--now it's completely untenable. For example, the GNU C library supplies a function \s10\f(CWrename\fR\s0 where needed, so our previous example would fail even on a System V.3 kernel without a \s10\f(CWrename\fR\s0 system call if it uses the GNU C library. As you can imagine, many packages break when compiled with the GNU C library, through their own fault, not that of the library. .Le In the example above, it would make a whole lot more sense to define a macro \f(CW\s10HAS_RENAME\s0\fR which can be set if the \f(CW\s10rename\s0\fR function is present. Some packages use this method, and the GNU project is gradually working towards it, but the majority of packages base their decisions primarily on the combination of machine architecture and operating system. .LP The results of incorrect configuration can be far-reaching and subtle. In many cases, it looks as if there is a bug in the package, and instead of reconfiguring, you can find yourself making significant changes to the source. This can cause it to work for the environment in which it is compiled, but to break it for anything else. .Ah "What do I need to change?" A good configuration mechanism should be able to decide the hardware and software dependencies that interest the package, but only you can tell it about the local preferences. For example, which compiler do you use? Where do you want to install the executables? If you don't know the answers to these questions, there's a good chance that you'll be happy with the defaults chosen by the configuration routines. On the other hand, you may want to use \fIgcc\fR to compile the package, and to install the package in the \fI/opt\fR hierarchy. In all probability, you'll have to tell the configuration routines about this. Some configuration routines will look for \fIgcc\fR explicitly, and will take it if they find it. In this case, you may have a reason to tell the configuration routines \fInot\fR to use \fIgcc\fR. .LP Some packages have a number of local preferences: for example, do you want the package to run with X11 (and possibly fail if X isn't running)? This sort of information \fIshould\fR be in the \fIREADME\fR file. .Ah "Creating configuration information" A number of configuration methods exist, none of them perfect. In most cases you don't get a choice: you use the method that the author of the package decided upon. The first significant problem can arise at this point: \fIwhat\fR method does he use? This is not always easy to figure out--it \fIshould\fR be described in a file called \fIREADME\fR or \fIINSTALL\fR or some such, but occasionally you just find cryptic comments in the \fIMakefile\fR. .LP In the rest of this chapter we'll look at configuration via multiple \fIMakefile\fR targets, manual configuration, shell scripts, and \fIimake\fR, the X11 configuration mechanism. In addition, the new BSD \fImake\fR system includes a system of automatic configuration: once it is set up, you don't have to do anything, assuming you already have a suitable \fIMakefile\fR. We'll look at this method in more detail in \*[chmake], page \*[BSDmake]. .Ah "Multiple Makefile targets" .XX "targets, multiple" .XX "makefile targets, multiple" .Pn multiple-targets Some packages anticipate every possibility for you and supply a customized Makefile. For example, when building \fIunzip\fR, a free uncompression utility compatible with the DOS package \fIPK-ZIP\fR, you would find: .Ps $ \f(CBmake\f(CW If you're not sure about the characteristics of your system, try typing "make generic". If the compiler barfs and says something unpleasant about "timezone redefined," try typing "make clean" followed by "make generic2". One of these actions should produce a working copy of unzip on most Unix systems. If you know a bit more about the machine on which you work, you might try "make list" for a list of the specific systems supported herein. And as a last resort, feel free to read the numerous comments within the Makefile itself. Note that to compile the decryption version of UnZip, you must obtain the full versions of crypt.c and crypt.h (see the "Where" file for ftp and mail-server sites). Have an excruciatingly pleasant day. .Pe .XX "make generic" As the comments suggest, typing \fImake generic\fR should work most of the time. If it doesn't, looking at the \fIMakefile\fR reveals a whole host of targets for a number of combined hardware/software platforms. If one of them works for you, and you can find which one, then this might be an easy way to go. If none does, you might find yourself faced with some serious Makefile rewriting. This method has an additional disadvantage that it might compile with no problems and run into subtle problems when you try to execute it--for example, if the program expects System V \f(CW\s10sigpause\fR\s0 and your system supplies BSD \f(CW\s10sigpause\fR\s0,\** .FS See \*[chsignal], pages \*[bsd-sigpause] and \*[SysV_sigpause] for further information. .FE the build process may complete without detecting any problems, but the program will not run correctly, and you might have a lot of trouble finding out why. .Ah "Manual configuration" .XX "manual configuration" .XX "configuration, manual" .XX "config.h" Modifying the \fIMakefile\fR or \fIconfig.h\fR manually is a better approach than multiple \fIMakefile\fR targets. This seemingly arduous method has a number of advantages: .Ls B .Li You get to see what is being changed. If you have problems with the resultant build, it's usually relatively easy to pin-point them. .Li Assuming that the meanings of the parameters are well documented, it can be easier to modify them manually than run an automated procedure that hides much of what it is doing. .Li If you find you \fIdo\fR need to change something, you can usually do it fairly quickly. With an automated script, you may need to go through the whole script to change a single minor parameter. .Le On the down side, manual configuration requires that you understand the issues involved: you can't do it if you don't understand the build process. In addition, you may need to repeat it every time you get an update of the package, and it is susceptible to error. .Ah "Configuration scripts" .XX "configuration scripts" .XX "scripts, configuration" Neither multiple Makefile targets nor manual modification of the Makefile leave you with the warm, fuzzy feeling that everything is going to work correctly. It would be nice to have a more mechanized method to ensure that the package gets the correct information about the environment in which it is to be built. One way to do this is to condense the decisions you need to make in manual configuration into a shell script. Some of these scripts work very well. A whole family of configuration scripts has grown up in the area of electronic mail and news. Here's part of the configuration script for C news, which for some reason is called \fIbuild\fR: .Ps $ \f(CBcd conf\f(CW $ \f(CBbuild\f(CW This interactive command will build shell files named doit.root, doit.bin, doit.news, and again.root to do all the work. It will not actually do anything itself, so feel free to abort and start again. C News wants to keep most of its files under a uid which preferably should be all its own. Its programs, however, can and probably should be owned by another user, typically the same one who owns most of the rest of the system. (Note that on a system running NFS, any program not owned by "root" is a gaping security hole.) What user id should be used for news files [news]? \fIRETURN pressed\f(CW What group id should be used for news files [news]? \fIRETURN pressed\f(CW What user id should be used for news programs [bin]? \fIRETURN pressed\f(CW What group id should be used for news programs [bin]? \fIRETURN pressed\f(CW Do the C News sources belong to bin [yes]? \f(CBno\f(CW You may need to do some of the installation procedures by hand after the software is built; doit.bin assumes that it has the power to create files in the source directories and to update the news programs. It would appear that your system is among the victims of the 4.4BSD / SVR4 directory reorganization, with (e.g.) shared data in /usr/share. Is this correct [yes]? \fIRETURN pressed\f(CW This will affect where C News directories go. We recommend making the directories wherever they have to go and then making symbolic links to them under the standard names that are used as defaults in the following questions. Should such links be made [yes]? \f(CBno\f(CW .Pe We chose not to use the symbolic links: the script doesn't say why this method is recommended, they don't buy us anything, and symbolic links mean increased access time. .LP The configuration script continues with many more questions like this. We'll pick it up at various places in the book. .LP The flexibility of a shell script is an advantage when checking for system features which are immediately apparent, but most of them require that you go through the whole process from start to finish if you need to modify anything. This can take up to 10 minutes on each occasion, and they are often interactive, so you can't just go away and let it do its thing. .Ah "GNU package configuration" .Pn GNU-configure Most GNU project packages supply another variety of configuration script. For more details, see \fIProgramming with GNU Software\fR, by Mike Loukides. GNU configuration scripts sometimes expect you to know the machine architecture and the operating system, but they often attempt to guess if you don't tell them. The main intention of the configuration utility is to figure out which features are present in your particular operating system port, thus avoiding the problems with functions like \f(CW\s10rename\s0\fR discussed on page \*[HAS_RENAME]. Taylor \fIuucp\fR uses this method: .Ps $ \f(CBsh configure\f(CW checking how to run the C preprocessor checking whether -traditional is needed \fIsee page \*[traditional]\f(CW checking for install \fIthe install program, page \*[install]\f(CW checking for ranlib \fIsee page \*[ranlib] \f(CW checking for POSIXized ISC \fIInteractive POSIX extensions?\f(CW checking for minix/config.h \fIMINIX specific \f(CW checking for AIX \fIIBM UNIX\f(CW checking for -lseq \fIlibseq.a needed?\f(CW checking for -lsun \fIlibsun.a?\f(CW checking whether cross-compiling checking for lack of working const \fIsee page \*[const]\f(CW checking for prototypes \fIdoes the compiler understand function prototypes?\f(CW checking if `#!' works in shell scripts checking for echo program \fIis echo a program or a builtin?\f(CW checking for ln -s \fIdo we have symbolic links? (page \*[symlink])\f(CW .Pe This method makes life a whole lot easier if the package has already been ported to your particular platform, and if you are prepared to accept the default assumptions that it makes, but can be a real pain if not: .Ls B .Li You may end up having to modify the configuration scripts, which are not trivial. .Li It's not always easy to configure things you want. In the example above, we accepted the default compiler flags. If you want maximum optimization, and the executables should be installed in \fI/opt/bin\fR instead of the default \fI/usr/local/bin\fR, running \fIconfigure\fR becomes significantly more complicated:\** .FS This example uses the feature of modern shells of specifying environment variables at the beginning of the command. The program being run is \fIsh\fR, and the definition of \s10\f(CWCFLAGS\fR\s0 is exported only to the program being started. .FE .Ps $ \f(CBCFLAGS="-O3 -g" sh configure --prefix=/opt .Pe .Li The scripts aren't perfect. You should really check the resultant \fIMakefile\fRs, and you will often find that you need to modify them. For example, the configuration scripts of many packages, including the GNU debugger, \fIgdb\fR, do not allow you to override the preset value of \s10\f(CWCFLAGS\fR\s0. In other cases, you can run into a lot of trouble if you do things that the script didn't expect. I once spent a couple of hours trying to figure out the behaviour of the GNU \fImake\fR configuration script when porting to Solaris 2.4: .Ps $ \f(CBCFLAGS="O3 -g" configure --prefix=/opt\f(CW creating cache ./config.cache checking for gcc... gcc checking whether we are using GNU C... yes checking how to run the C preprocessor... gcc -E checking whether cross-compiling... \fIyes\fP .Pe .IP Although this was a normal port, it claimed I was trying to cross-compile. After a lot of experimentation, I discovered that the configuration script checks for cross-compilation by compiling a simple program. If this compilation fails for any reason, the script assumes that it should set up a cross-compilation environment. In this case, I had mistakenly set my \s10\f(CWCFLAGS\fR\s0 to \s10\f(CWO3 -g\fR\s0--of course, I had meant to write \s10\f(CW-O3 -g\fR\s0. The compiler looked for a file \fIO3\fR and couldn't find it, so it failed. The configuration script saw this failure and assumed I was cross-compiling. .Li In most cases, you need to re-run the configuration script every time a package is updated. If the script runs correctly, this is not a problem, but if you need to modify the Makefile manually, it can be a pain. For example, \fIgdb\fR creates 12 \fIMakefile\fRs. If you want to change the \s10\f(CWCFLAGS\fR\s0, you will need to modify each of them every time you run \fIconfigure\fR. .Li .XX "Makefile.in" .Pn Makefile.in Like all configuration scripts, the GNU scripts have the disadvantage of only configuring things they know about. If your \fIman\fR program requires pre-formatted man pages, you may find that there is no way to configure the package to do what you want, and you end up modifying the Makefile after you have built it. .Le Modifying automatically build \fIMakefile\fRs is a pain. An alternative is to modify \fIMakefile.in\fR, the raw \fIMakefile\fR used by \fIconfigure\fR. That way, you will not have to redo the modifications after each run of \fIconfigure\fR. .Ah "imake" \fIimake\fR is the X11 solution to package configuration. It uses the C preprocessor to convert a number of configuration files into a \fIMakefile\fR. Here are the standard files for X11R6: .Ls B .Li \fIImake.tmpl\fR is the main configuration file that is passed to the C preprocessor. It is responsible for including all the other configuration files via the preprocessor \s10\f(CW#include\fR\s0 directive. .Li \fIImake.cf\fR determines the kind of system upon that \fIimake\fR is running. This may be based on preprocessor variables supplied by default to the preprocessor, or on variables compiled in to \fIimake\fR. .Li \fIsite.def\fR describes local preferences. This is one of the few files that you should normally consider modifying. .Li As its name implies, \fI.cf\fR has a different name for each platform. \fIImake.tmpl\fR decides which file to include based on the information returned by \fIImake.cf\fR. For example, on BSD/OS the file \fIbsdi.cf\fR will be included, whereas under SunOS 4 or Solaris 2 the file \fIsun.cf\fR will be included. .Li \fIImake.rules\fR contains preprocessor macros used to define the individual \fIMakefile\fR targets. .Li \fIImakefile\fR is part of the package, not the \fIimake\fR configuration, and describes the package to \fIimake\fR. .Le You don't normally run \fIimake\fR directly, since it needs a couple of pathname parameters: instead you have two possibilities: .Ls B .Li .Pn xmkmf .XX xmkmf Run \fIxmkmf\fR, which is a one-line script that supplies the parameters to \fIimake\fR. .Li Run \fImake Makefile\fR. This assumes that some kind of functinoal \fIMakefile\fR is already present in the package. .Le Strangely, \fImake Makefile\fR is the recommended way to create a new \fIMakefile\fR. I don't agree: one of the most frequent reasons to make a new \fIMakefile\fR is because the old one doesn't work, or because it just plain isn't there. If your \fIimake\fR configuration is messed up, you can easily remove all traces of a functional \fIMakefile\fR and have to restore the original version from tape. \fIxmkmf\fR always works, and anyway, it's less effort to type. .LP Once you have a \fIMakefile\fR, you may not be finished with configuration. If your package contains subdirectories, you may need to create \fIMakefile\fRs in the subdirectories as well. In general, the following sequence will build most packages: .Ps $ \f(CBxmkmf\fI run imake against the Imakefile\f(CW $ \f(CBmake Makefiles\fI create subordinate Makefiles\f(CW $ \f(CBmake depend\fI run makedepend against all Makefiles\f(CW $ \f(CBmake\fI make the packages\f(CW $ \f(CBmake install\fI install the packages .Pe These commands include no package-dependent parameters--the whole sequence can be run as a shell script. Well, yes, there are minor variations: \fImake Makefiles\fR fails if there are no subordinate \fIMakefiles\fR to be made, and sometimes you have targets like a \fImake World\fR instead of \fImake\fR or \fImake all\fR, but in general it's very straightforward. .LP If your \fIimake\fR configuration files are set up correctly, and the package that you are porting contains no obscenities, this is all you need to know about \fIimake\fR, which saves a lot of time and is good for your state of mind. Otherwise, check \fISoftware Portability with imake\fR, by Paul DuBois, for the gory details. .XX "DuBois, Paul" @ 3.0 log @Final draft @ text @d2 1 a2 1 .\" $Id: config.ms,v 2.6 1995年06月22日 07:34:09 grog Exp grog $ d4 3 d536 22 a557 1 \s10\f(CWCFLAGS\fR\s0. d563 1 a563 1 you will need to modify them every time you run \fIconfigure\fR. @ 2.7 log @Final draft, second cut @ text @a624 18 .\" .Ah "Summary" .\" Configuration, or adapting packages to the local environment, is still a messy .\" business. The following methods are in current use: .\" .Ls B .\" .Li .\" Supply different \fIMakefile\fR targets for each possible configuration. .\" .Li .\" Manually modify the \fIMakefile\fR to the desired environment. .\" .Li .\" Provide a configuration script. This may check for individual features, or it .\" may base its decisions on the operating system and hardware. .\" .Li .\" Base decisions on a user-modifiable configuration database. This is the method .\" chosen by BSD \fImake\fR and \fIimake\fR. .\" .Le .\" All of these methods have significant disadvantages, and a large proportion of .\" porting problems relate to inadequate configuration. .\" @ 2.6 log @Final draft, first cut. @ text @d2 1 a2 1 .\" $Id: config.ms,v 2.5 1995年06月09日 06:16:55 grog Exp grog $ d4 3 d116 1 a116 1 from the point of view of the Unix Systems Group, who are only concerned with d154 1 a154 1 points to it. This only works if your system has symbolic links, of course, so d522 2 a523 1 and the definition of \s10\f(CWCFLAGS\fR\s0 is only exported to the shell. d622 2 a623 1 Otherwise, check [DuBois 93] for the gory details. d625 18 a642 17 .Ah "Summary" Configuration, or adapting packages to the local environment, is still a messy business. The following methods are in current use: .Ls B .Li Supply different \fIMakefile\fR targets for each possible configuration. .Li Manually modify the \fIMakefile\fR to the desired environment. .Li Provide a configuration script. This may check for individual features, or it may base its decisions on the operating system and hardware. .Li Base decisions on a user-modifiable configuration database. This is the method chosen by BSD \fImake\fR and \fIimake\fR. .Le All of these methods have significant disadvantages, and a large proportion of porting problems relate to inadequate configuration. @ 2.5 log @Remove date from page headers Minor mods @ text @d2 1 a2 1 .\" $Id: config.ms,v 2.4 1995年05月16日 04:46:50 grog Exp grog $ d4 4 d138 1 a138 1 contain library archives for compilers, as well as the individual phases of the @ 2.4 log @Major mods after Andy's final draft review @ text @d2 1 a2 1 .\" $Id: config.ms,v 2.3 1995年02月11日 13:09:39 grog Exp grog $ d4 3 d20 1 a20 1 .St "Package configuration ($Date: 1995年02月11日 13:09:39 $)" d474 7 a480 8 more details, see XXX What's Mike's book called? .\" XXX Yes, I know this would drive Mike mad. How about some conventions? GNU configuration scripts sometimes expect you to know the machine architecture and the operating system, but they often attempt to guess if you don't tell them. The main intention of the configuration utility is to figure out which features are present in your particular operating system port, thus avoiding the problems with functions like \f(CW\s10rename\s0\fR discussed on page \*[HAS_RENAME]. Taylor \fIuucp\fR uses this method: @ 2.3 log @Minor mods @ text @d2 1 a2 1 .\" $Id: config.ms,v 2.2 1995年02月04日 16:01:39 grog Exp grog $ d4 3 d17 1 a17 1 .St "Package configuration ($Date: 1995年02月04日 16:01:39 $)" d22 5 a26 6 system, but that's not just a pain, it's also very error-prone. All modern packages supply a method of \fIconfiguration\fR, a simplified way of adapting the sources to the environment in which the program will run. In this chapter, we'll look at the conventions have arisen over the years regarding the manner in which a package source is adapted to its environment. We can divide system differences into one of three categories: d48 3 a50 9 In the following section, we'll look at what local configuration entails. Starting on page \*[doconfig] we'll look at \fIhow\fR we tell the package about our chosen configuration. .Ah "Local configuration" .XX "local configuration" Local configuration may include obvious things like the system name, aspects of program behaviour, information about tools used locally, and personal preferences. Here are some of the things that you need to think about: .Bh "Installation paths" d55 1 a55 1 large, heterogeneous network it could require rather more consideration. d57 1 d59 3 a61 16 \fI/usr/local\fR. .XX "/usr/local" This is not an \(aesthetically pleasing location: the hierarchy can become quite large, and in a network many systems might share the directory. Both of these facts make it a prime candidate for having its own file system. On one hand, it's good practice to mount file systems from the root file system, not from another mounted file system. While it's unlikely that you're going to worry much about \fI/usr/local\fR if \fI/usr\fR has gone away,\** .FS On the other hand, you might: if \fI/usr\fR has gone away because of some data integrity problem, you could have tools on \fI/usr/local\fR which you would like to use to repair it. .FE it's still better to mount the directory off the root directory. On the other hand, it's also a good idea to stick to standards, even if they are just de-facto standards. d64 1 a64 1 the System V Application binary interface [ABI 92], which is also similar to d84 1 a84 1 System V ABI it has lost most of its importance. The ABI only states uses for d87 1 a87 1 files which users may wish to access. a91 8 .IP "\fI/usr/ccs\fR" .XX "/usr/ccs" .XX "CCS" This directory is not explicitly mentioned in the System V ABI, but it is the normal directory where System V.4 stores program development tools. The abbreviation \fICCS\fR stands for C Compiling System. The binaries are placed in the directories \fI/usr/ccs/bin\fR (user-accessible binaries) and \fI/usr/ccs/lib\fR (other binaries). d96 1 a96 1 System V which still have \fIman\fR pages put them in \fI/usr/share/man\fR, d104 1 a104 1 file system, and it must be mounted on a non-root file system, and secondly the d112 1 a112 1 This directory contains files which are frequently modified. Typical d143 1 a143 1 the directory where you want it, and create a symbolic link \fI/opt\fR which d174 1 a174 1 There are a number of possible ways to convey configuration information: for d193 1 a193 1 The \s10\f(CW-D\fR\s0 arguments pass preprocessor variables which define the d214 6 a219 6 I prefer this approach: on the one hand, you have all the configuration information in one place, and it is documented. On the other hand, it's more reliable. Assuming that the \fIMakefile\fR dependencies are correct, any change to \fIconfig.h\fR will cause the programs to be recompiled on the next \fImake\fR. As we will see in \*[chbuild], page \*[No-dependency-on-Makefile], this usually doesn't happen if you modify the \fIMakefile\fR. d230 2 a231 2 called the i386 architecture. You would also use \f(CWi386\fR when compiling for a Pentium. d258 8 a265 8 This method works nicely if the hardware and software both exactly match the expectations of the person who wrote the code. In many cases, this is not the case: looking at the example above, note that the file included for SVR4 is \fIs/usg-4.0.h\fR, which suggests that it is intended for UNIX System V release 4.0. UnixWare is System V release 4.2. Will this work? Maybe. It could be that the configuration mechanism was last revised before System V.4.2 came out. If you find a file \fIs/usg-4.2.h\fR, it's a good idea to use it instead, but otherwise it's a matter of trial and error. d277 10 a286 5 \f(CW\s10USG\s0\fR (USG is the Unix Systems Group which was responsible for System V), \f(CW\s10SYSV\s0\fR, \s10\f(CWSVR4\s0\fR, \s10\f(CWSYSV_4\s0\fR, \f(CW\s10SYSV_4_2\s0\fR or even \s10\f(CWSVR3\s0\fR. This last can happen when the configuration needed to be updated from System V.2 to System V.3, but not again for System V.4. d291 6 a296 7 \f(CW\s10rename\s0\fR, but it is included in most versions of System V.3 that you will find today. System V.4 does have \f(CW\s10rename\s0\fR. In order to distinguish between the two, the software writer may use \f(CW\s10#ifdef SVR4\s0\fR to decide whether to use \f(CW\s10rename\s0\fR or not. Under these circumstances, if you are porting to a version of System V.3.2 with \f(CW\s10rename\s0\fR, it might be a better idea to define \f(CW\s10SVR4\s0\fR, and not \s10\f(CWSVR3\s0\fR. d299 12 a310 12 library. As we will see in the introduction to Part 2 of this book, on page \*[kernellib], there is a big difference between kernel functionality and library functionality. The assumption is that a specific kernel uses the library with which it is supplied. The situation is changing, though: many companies sell systems without software development tools, and alternative libraries such as the GNU C library are becoming available. Making assumptions about the library based on the kernel was never a good idea--now it's just plain untenable. For example, the GNU C library supplies a function \s10\f(CWrename\fR\s0 where needed, so our previous example would fail even on a System V.3 kernel without a \s10\f(CWrename\fR\s0 system call if it uses the GNU C library. As you can imagine, many packages break when compiled with the GNU C library, through their own fault, not that of the library. d312 5 a316 8 In almost every case, configuration variables are used to specify the presence or absence of a particular feature. Bundling them together into an operating system definition complicates matters significantly. In the example above, it would make a whole lot more sense to define a macro \f(CW\s10HAS_RENAME\s0\fR which can be set if the \f(CW\s10rename\s0\fR function is present. Some packages use this method, and the GNU project is gradually working towards it, but the majority of packages base their decisions primarily on the combination of machine architecture and operating system. d319 4 a322 3 cases, it looks as if there is a bug in the package, and the problem is solved by significant changes to the source, which causes it to work for the environment in which it is compiled, but breaks it for anything else. d325 2 a326 2 software dependencies which interest the package, but only you can tell it about the local preferences. For example, which compiler do you use? Where to you d356 1 a372 1 As the comments suggest, typing \fImake generic\fR d374 8 a381 8 should work most of the time. If it doesn't, looking at the \fIMakefile\fR reveals a whole host of targets for a number of combined hardware/software platforms. If one of the works for you, and you can find which one, then this might be an easy way to go. If none does, you might find yourself faced with some possibly serious Makefile rewriting. This method has an additional disadvantage that it might compile with no problems and run into subtle problems when you try to execute it--for example, if the program expects System V \f(CW\s10sigpause\fR\s0 and your (BSD) system supplies BSD d393 3 a395 3 Modifying the Makefile or \fIconfig.h\fR manually is a better approach than multiple \fIMakefile\fR targets. This seemingly arduous method has a number of advantages: d402 1 a402 1 easier to modify them manually than run an automated procedure which hides much d457 2 a458 1 is recommended, and symbolic links mean increased access time. d466 2 a467 2 This can take up to 10 minutes on each occasion, and since they are usually interactive, you can't just go away and let it do its thing. d470 9 a478 7 Most GNU project packages supply another variety of configuration script. GNU configuration scripts sometimes expect you to know the machine architecture and the operating system, but they often attempt to guess if you don't tell them. The main intention of the configuration utility is to figure out which features are present in your particular operating system port, thus avoiding the problems with functions like \f(CW\s10rename\s0\fR discussed on page \*[HAS_RENAME]. Taylor \fIuucp\fR uses this method: d480 1 a480 1 $ \f(CBCFLAGS="-O2 -g" CC=gcc2 sh configure\f(CW d498 2 a499 1 to your particular platform, but can be a real pain if not: d505 10 a514 6 It's not always easy to configure things you want. In the example above, we set the compiler flags to \f(CW\s10-g -O\s0\fR to specify debugging output and standard optimization. If you find you don't have enough disk space for the debugging symbols, but you want maximum optimization, and the executables should be installed in \fI/opt/bin\fR instead of the default \fI/usr/local/bin\fR, running \fIconfigure\fR becomes significantly more complicated: d516 1 a516 1 $ \f(CWCFLAGS=-O3 configure --prefix=/opt d520 4 a523 1 \fIMakefile\fRs, and you will frequently find that you need to modify them. d527 4 a530 10 need to modify the Makefile manually, it can be a pain. For example, the configure script for current versions of the GNU debugger, \fIgdb\fR, do not allow you to override the preset value of \s10\f(CWCFLAGS\fR\s0, so you may have to edit up to 12 \fIMakefile\fRs every time you run \fIconfigure\fR. .Li All configuration scripts have the disadvantage of only configuring things they know about. For example, if your \fIman\fR program requires pre-formatted man pages, you may find that there is no way to configure the package to do what you want, and you end up modifying the Makefile after you have built it. If you're using a GNU config script, you may find you have to modify \fIMakefile.in\fR, d533 5 a537 2 which is the raw \fIMakefile\fR used by \fIconfigure\fR. That way, you will not have to redo the modifications after each run of \fIconfigure\fR. d539 4 d546 1 a546 1 The standard files for X11R6 are: d549 1 a549 1 \fIImake.tmpl\fR is the main configuration file which is passed to the C d553 1 a553 1 \fIImake.cf\fR determines the kind of system upon which \fIimake\fR is running. d557 1 a557 1 \fIsite.def\fR describes local preferences. This is one of the few files which d570 1 a570 1 describes the package. d578 1 a578 1 Run \fIxmkmf\fR, which is a one-line script which supplies the parameters to d581 2 a582 2 Run \fImake Makefile\fR. This assumes the presence of some kind of \fIMakefile\fR in the package, and that it is functional. d587 4 a590 1 isn't there. \fIxmkmf\fR always works, and anyway, it's less effort to type. d621 1 a621 1 Require the user to modify the \fIMakefile\fR to his environment. @ 2.2 log @Minor mods @ text @d2 1 a2 1 .\" $Id: config.ms,v 2.1 1995年01月23日 09:27:51 grog Exp grog $ d4 3 d14 11 a24 4 .St "Package configuration ($Date: 1995年01月23日 09:27:51 $)" In this chapter, we'll look at the conventions have arisen over the years regarding the manner in which a package source is adapted to its environment. We can divide system differences into one of three categories: d190 2 a191 2 .Ah "Standard configuration information" .XX "standard configuration information" d193 59 a251 11 Typically, you convey configuration information to the package by defining preprocessor variables (\f(CW\s10#define\fR\s0s) which indicate the presence or absence of a specific feature. Typical features are the kind of operating system you run and the kind of hardware you use. .LP For example, if you compile for a Sparc II running SunOS 4.1.3, you might define \f(CW\s10sparc\s0\fR to indicate the processor architecture used and \f(CW\s10sunos4\s0\fR to indicate the operating system. Since SunOS 4 is basically UNIX, you might also need to define \f(CW\s10unix\s0\fR. On an Intel 486 running UnixWare you might need to define \f(CW\s10i386\s0\fR for the processor architecture,\** a340 19 The goal of configuration is normally to create a Makefile with correct macro definitions for the programs run by \fImake\fR, or to put the definitions in a header file, which then often has a name like \fIconfig.h\fR. .XX "config.h" For example, if you are configuring a package for System V.4, the configuration process may put a line in the Makefile: .Ps CFLAGS=-DSYSV $(DEBUGFLAGS) $(INCLUDES) .Pe or it may put it in \fIconfig.h\fR instead: .Ps #define SYSV .Pe This choice may not seem to be important. In practice, however, there is a big difference: \fIMakefile\fR dependencies usually don't include the \fIMakefile\fR itself, but they do include \fIconfig.h\fR. If you change \fIconfig.h\fR, all the necessary files will be recompiled next time you run \fImake\fR, but if you modify the \fIMakefile\fR they will not be. .LP d345 16 d375 1 a375 1 .Bh "Multiple Makefile targets" a413 1 A better approach is to modify the Makefile or \fIconfig.h\fR d415 3 a417 1 manually. This seemingly arduous method has a number of advantages: d490 1 a490 1 .Pn GNU-configure d586 1 @ 2.1 log @Move stuff about BSD make config to make.ms Minor mods @ text @d2 1 a2 1 .\" $Id: config.ms,v 2.0 1994年11月18日 14:20:30 grog Exp grog $ d4 3 d8 1 d11 1 a11 1 .St "Package configuration ($Date: 1994年11月18日 14:20:30 $)" d14 25 a38 5 As we saw on page \*[configtypes], configuration can be required for local preferences, software dependencies and hardware dependencies. In the next section, we'll look at what local configuration entails, and starting on page \*[doconfig] we'll look at \fIhow\fR we tell the package about our chosen configuration. d260 2 a261 2 Many aspects attributed to the operating system are in fact properties of the system library. As we saw in the introduction to Part 2 of this book, on page d263 10 a272 11 library functionality. These assumptions work because most systems supply a library with the kernel, and nearly everybody uses it. The situation is changing, though: many companies sell systems without software development tools, and alternative libraries such as the GNU C library are becoming available. Making assumptions about the library based on the kernel was never a good idea--now it's just plain untenable. For example, the GNU C library supplies a function \s10\f(CWrename\fR\s0 where needed, so our previous example would fail even on a System V.3 kernel without a \s10\f(CWrename\fR\s0 system call if it uses the GNU C library. As you can imagine, many packages break when compiled with the GNU C library, through their own fault, not that of the library. d315 5 a319 3 \fIMakefile\fR targets, manual configuration, shell scripts, the configuration files used with BSD \fImake\fR, and \fIimake\fR, the X11 configuration mechanism. a373 1 .\" See C-news case study XXX d433 1 a433 1 .LP d497 67 d577 1 a577 2 chosen by BSD \fImake\fR and (as we shall see in the next chapter) by \fIimake\fR. @ 2.0 log @checked in with -k by grog at 1995年01月09日 13:22:41 @ text @d2 1 a2 1 .\" $Id: config.ms,v 1.22 1994年11月18日 14:20:30 grog Exp grog $ a3 2 .\" Revision 1.22 1994年11月18日 14:20:30 grog .\" Completely revised a4 30 .\" Revision 1.21 1994年09月01日 13:30:58 grog .\" Snapshot 1 September 1994 .\" .\" Revision 1.20 1994年08月25日 17:07:57 grog .\" Change all names from .roff to .ps, set uniform version number 1.20, minor mods .\" .\" Revision 1.6 1994年08月07日 12:00:30 grog .\" Change global.defs to global.roff .\" .\" Revision 1.5 1994年08月04日 13:52:20 grog .\" Minor changes .\" .\" Revision 1.4 1994年07月29日 13:59:54 grog .\" Minor mods .\" .\" Revision 1.3 1994年07月12日 19:47:32 grog .\" Minor mods, page number references .\" .\" Revision 1.2 1994年07月11日 11:23:47 grog .\" Minor mods .\" .\" Revision 1.1 1994年07月08日 16:44:25 grog .\" Initial revision .\" .\\" Revision 1.2 1994年06月09日 12:44:34 grog .\\" Minor modifications .\\" .\" Revision 1.1 1994年05月11日 17:20:31 grog .\" Initial revision .\" d8 7 a14 8 In the preceding chapters we have seen the gory details of why packages may need to be modified before they can be built. In this chapter, we'll look at the more immediate problem of \fIhow\fR we tell the package about its environment. As we saw in the introduction to Part II of this book, on page \*[configtypes], configuration can be required for local preferences, software dependencies and hardware dependencies. In the next section, we'll look at what local configuration entails, and starting on page \*[doconfig] we'll look at \fIhow\fR we tell the package about our chosen configuration. d30 6 a35 7 This is not an \(aesthetically pleasing location: the hierarchy can become quite large, and in a network many systems might share the directory. Both of these facts make it a prime candidate for having its own file system. On one hand, it's good practices to mount file systems from the root file system, not from another mounted file system. While it's unlikely that you're going to worry much about \fI/usr/local\fR if \fI/usr\fR has gone away,\** d37 1 a37 1 On the other hand, you might: If \fI/usr\fR has gone away because of some data d62 1 a62 1 Directory for add-on software d72 2 a73 1 and users". In practice, it's a good idea to leave only system programs here. d76 1 d79 1 a79 1 abbreviation \fICCS\fR stands for C Compiling System. The binaries are placed in d93 7 a99 7 \fI/usr/share\fR is not a happy choice: firstly, it is another file system mounted on a non-root file system, and secondly the man pages aren't really architecture-independent. The choice makes more sense from the point of view of the Unix Systems Group, who are only concerned with pure System V: the man pages are mainly independent of hardware architecture. However, in a real-world net you probably have two or three different operating systems, each with their own man pages. d103 1 a103 1 subdirectories are \fI/var/tmp\fR for temporary files and \fR/var/spool\fR for d131 1 a131 1 Using the \fIopt\fR hierarchy has one disadvantage: you may not want to have a d134 3 a136 3 points to it. You can't do this if your system doesn't have symbolic links, of course, so I have come to the compromise: I use \fI/opt\fR on systems with symbolic links, and \fI/usr/local\fR on systems without symbolic links. d146 3 a148 3 Many of the most popular software packages are alternative tools. Programs such as \fIgcc\fR, \fIemacs\fR and \fIperl\fR have become so popular that they are frequently supplied with proprietary system releases, and many other systems d150 1 a150 1 programs, you have to tell the configuration routines about them. d197 2 a198 2 end up with lots of double definitions when compiling, this could be one of the reasons. d206 1 a206 1 If you find a file \fIs/usg-4.2.h\fR, it's a good idea to take that instead, but d227 8 a234 7 differences. For example, base System V.3 does not have the \f(CW\s10rename\s0\fR system call, though many ports have included it. System V.4 does have \f(CW\s10rename\s0\fR. In order to distinguish between the two, the software writer may use \f(CW\s10#ifdef SVR4\s0\fR to decide whether to use \f(CW\s10rename\s0\fR or not. Under these circumstances, if you are porting to a version of System V.3.2 with \f(CW\s10rename\s0\fR, it might be a better idea to define \f(CW\s10SVR4\s0\fR, not \s10\f(CWSVR3\s0\fR. d257 2 a258 2 but the majority of packages use the machine architecture/operating system method described above. d292 3 a294 3 \fIMakefile\fR targets, manual configuration, shell scripts and the configuration files used with BSD \fImake\fR. In \*[chimake] we'll look at the X11 configuration mechanism. d331 1 a331 1 .Bh "Manual configuration" d355 1 a355 1 .Bh "Configuration scripts" d365 38 a402 1 mail and news--we'll look at one of them in \*[chcase], page \*[c-news-config]. d417 1 a417 1 Configuring GNU emacs can look like: d419 16 a434 32 - You did not tell me what kind of host system you want to configure. - I will attempt to guess the kind of system this is. - Looks like this is a i386-univel-sysv4.2 Checking the configuration name. checking for ln -s \fI\&... many further checks\f(CW Checking window system. checking for X include and library files with xmkmf No window system specified. Looking for X11. Using X11. Examining the machine- and system-dependent files to find out - which libraries the lib-src programs will want, and - whether the GNU malloc routines are usable. checking for -lXbsd checking for XrmSetDatabase checking for random Configured for `i386-univel-sysv4.2'. Where should the build process find the source code? /aux/emacs-19.17 What operating system and machine description files should Emacs use? `s/usg5-4-2.h' and `m/intel386.h' What compiler should emacs be built with? gcc -g -O Should Emacs use the GNU version of malloc? yes Should Emacs use the relocating allocator for buffers? yes What window system should Emacs use? x11 creating config.status creating Makefile creating src/config.h a472 620 .Bh "BSD Makefile configuration system" .XX "BSD makefile configuration" .XX "configuration, BSD makefile" .Pn BSD-make-config We'll see in \*[chmake], that BSD \fImake\fR has a number of features not found in other \fImake\fRs. One of the apparent intentions of BSD \fImake\fR is to make configuration easier, so we'll look at those aspects here. A good example of how much difference it makes is in the \fIMakefile\fRs for \fIgcc\fR. The standard release Makefile for \fIgcc\fR is about 2500 lines long. The Net/2 release divides \fIgcc\fR into directories corresponding to the individual phases. The top-level \fIMakefile\fR reads, in its entirety, .Ps SUBDIR= cc cpp lib cc1 libgcc cc1plus cc1obj #libobjc \&.include .Pe The complete \fIMakefile\fR in the subdirectory \fIcc1\fR (the main phase of the compiler) reads .Ps # @@(#)Makefile 6.2 (Berkeley) 2/2/91 PROG= gcc1 BINDIR= /usr/libexec SRCS= c-parse.c c-lang.c c-lex.c c-pragma.c \e c-decl.c c-typeck.c c-convert.c c-aux-info.c \e c-iterate.c CFLAGS+= -I. -I$(.CURDIR) -I$(.CURDIR)/../lib YFLAGS= NOMAN= noman \&.if exists(${.CURDIR}/../lib/obj) LDADD= -L${.CURDIR}/../lib/obj -lgcc2 DPADD= ${.CURDIR}/../lib/obj/libgcc2.a \&.else LDADD= -L${.CURDIR}/../lib/ -lgcc2 DPADD= ${.CURDIR}/../lib/libgcc2.a \&.endif LDADD+= -lgnumalloc DPADD+= ${LIBGNUMALLOC} \&.include .Pe Clearly, a lot of work has gone into getting the \fIMakefile\fRs so small. The clue is the last line of each \fIMakefile\fR: .Ps \&.include \fI\&or\f(CW \&.include .Pe The \fI.include\fR .XX ".include" directive\** .FS \fI\&.include\fR is similar in function to the C preprocessor command \fI#include\fR. We discuss BSD \fImake\fR in more detail on page \*[bsd-make-include]. .FE reads these files, which are supplied with the system and define the hardware and software used on the system. They are normally located in \fI/usr/share/mk\fR, .XX "/usr/share/mk" and you can modify them to suit your local preferences. This directory may also contain the file \fIbsd.README\fR, which is about the only written documentation usually available. If your system doesn't supply it, you can find it on the companion CD-ROM as \fI4.4BSD/usr/src/share/mk/bsd.README\fR. .LP There is little connection between the new BSD \fImake\fR described on page \*[BSDmake] and this configuration mechanism. It could equally well have been done, for example, with GNU \fImake\fR or System V \fImake\fR. Unfortunately, the significant incompatibilities between BSD \fImake\fR and the others mean that you can't just take the configuration files and use them with other flavours of \fImake\fR. .LP The BSD system places some constraints on the \fIMakefile\fR structure. To get the best out of it, you may need to completely restructure your source tree. To quote \fIbsd.README\fR: .LP .RS \fIIt's fairly difficult to make the BSD .mk files work when you're building multiple programs in a single directory. It's a lot easier [to] split up the programs than to deal with the problem. Most of the agony comes from making the "obj" directory stuff work right, not because we switch to a new version of make. So, don't get mad at us, figure out a better way to handle multiple architectures so we can quit using the symbolic link stuff.\fR .RE .LP On the other hand, it's remarkably easy to use BSD \fImake\fR configuration once you get used to it. It's a pity that the \fImake\fR itself is so incompatible with other \fImake\fRs: although the system is good and works well, it's usually not worth restructuring your trees and rewriting your \fIMakefile\fRs to take advantage of it. .LP There are a couple of other points to note about the configuration method: .Ls B .Li \fImake depend\fR .XX "make depend" (see \*[chmake], page \*[makedepend]) is supported via an auxiliary file \&\fI.depend\fR, .XX ".depend" which \fImake\fR reads after reading the \fIMakefile\fR. .Li The configuration files are included at the \fIend\fR of the \fIMakefile\fR. This is due to the way that BSD \fImake\fR works: unlike other \fImake\fRs, if multiple targets with a single colon exist, only the first will be executed,\** .FS This behaviour is not compatible with other versions of \fImake\fR--see \*[chmake], page \*[multitarget], for further details. .FE but if multiple declarations of the same variable exist, only the last one will take effect. .Le The configuration files consist of one file, \fIsys.mk\fR, .XX "sys.mk" which \fImake\fR automatically reads before doing anything else, and a number of others, one of which is usually included as the last line in a \fIMakefile\fR. These are usually: .Ls B .Li \fIbsd.prog.mk\fR .XX "bsd.prog.mk" for a \fIMakefile\fR to make an executable binary. .Li \fIbsd.lib.mk\fR .XX "bsd.lib.mk" for a \fIMakefile\fR to make a library. .Li \fIbsd.subdir.mk\fR .XX "bsd.subdir.mk" to make binaries or libraries in subdirectories of the current directory. .Li In addition, another file \fIbsd.doc.mk\fR .XX "bsd.doc.mk" is supplied to make hardcopy documentation. In keeping with the alibi nature of such parts of a package, it is not referred to by any other file. If you want to use it, you \fI.include\fR it \fIin addition\fR to one of the other three. This is only required for hardcopy documentation, not for \fIman\fR pages, which \fIare\fR installed by the other targets. .Le .Ch "sys.mk" \fIsys.mk\fR .XX "sys.mk" contains global definitions for all makes. \fImake\fR reads it in before looking for any \fIMakefile\fRs. The documentation states that it is not intended to be modified, but since it contains default names for all tools, as well as default rules for makes, there is every reason to believe that you \fIwill\fR want to change this file: there's no provision to override these definitions anywhere else. How you handle this dilemma is your choice: I personally prefer to change \fIsys.mk\fR (and put up with having to update it when a new release comes), but you could create another file \fIbsd.own.mk\fR, .XX "bsd.own.mk" like FreeBSD does, and put your personal choices in there. The last line of the FreeBSD \fIsys.mk\fR is .Ps \&.include .Pe With this method you can override the definitions in \fIsys.mk\fR with the definitions in \fIbsd.own.mk\fR. It's up to you to decide whether this is a better solution. .Ch "bsd.prog.mk" \fIbsd.prog.mk\fR .XX "bsd.prog.mk" contains definitions for building programs. It defines the following targets: .ne 10 .Ts "bsd.prog.mk targets" .TS H linesize(2), tab(#) ; lfCWp9 | lw55 . \fRTarget#Purpose _ .TH N all#T{ Build the single program \f(CW\s10${PROG}\fR\s0, which is normally defined in the \fIMakefile\fR. T} .sp .4v clean#T{ remove \f(CW\s10${PROG}\fR\s0, any object files and the files \fIa.out\fR, \fIErrs\fR, \fIerrs\fR, \fImklog\fR, and \fIcore\fR. T} .sp .4v cleandir#T{ remove all of the files removed by the target \f(CW\s10clean\fR\s0 and also the files \fI.depend\fR, \fItags\fR, \fIobj\fR, and any manual pages. T} .sp .4v depend#T{ make the dependencies for the source files, and store them in the file \fI.depend\fR. T} .sp .4v install#T{ install the program and its manual pages. If the \fIMakefile\fR does not itself define the target \f(CW\s10install\fR\s0, the targets \f(CW\s10beforeinstall\fR\s0 and \f(CW\s10afterinstall\fR\s0 may also be used to cause actions immediately before and after the install target is executed. T} .sp .4v lint#run lint on the source files. .sp .4v tags#create a tags file for the source files. .TE .Te In addition, it supplies default definitions for the following variables. The operator \f(CW\s10?=\fR\s0 is used to ensure that they are not redefined if they are already defined in the \fIMakefile\fR (see page \*[maybeequal] for more details of the \f(CW\s10?=\fR\s0 operator). .ne 10 .Ts "variables defined in \fIbsd.prog.mk\fR" .XX "bsd.prog.mk" .TS H linesize(2), tab(#) ; lfCWp9 | lw55 . \s10\fRVariable#Purpose _ .TH N BINGRP#T{ Group ownership for binaries. Defaults to \fIbin\fR. T} .sp .4v BINOWN#T{ Owner for binaries. Defaults to \fIbin\fR. T} .sp .4v BINMODE#T{ Permissions for binaries. Defaults to 555 (read and execute permission for everybody). T} .sp .4v CLEANFILES#T{ Additional files which the \f(CW\s10clean\fR\s0 and \f(CW\s10cleandir\fR\s0 targets should remove. \fIbsd.prog.mk\fR does not define this variable, but it adds the file \fIstrings\fR to the list if the variable \f(CW\s10SHAREDSTRINGS\fR\s0 is defined. T} .sp .4v DPADD#T{ Additional library dependencies for the target \f(CW\s10${PROG}\fR\s0. For example, if you write \f(CW\s10DPADD=${LIBCOMPAT} ${LIBUTIL}\fR\s0 in your \fIMakefile\fR, the target depends on the compatibility and utility libraries. T} .sp .4v DPSRCS#T{ Dependent sources--a list of source files that must exist before compiling the program source files. Usually for a building a configuration file that is required by all sources. Not all systems define this variable. T} .sp .4v LIBC#The C library. Defaults to \fI/lib/libc.a .sp .4v LIBCOMPAT#T{ The 4.3BSD compatibility library. Defaults to \fI/usr/lib/libcompat.a T} .sp .4v LIBCURSES#The \fIcurses\fR library. Defaults to \fI/usr/lib/libcurses.a .sp .4v LIBCRYPT#The \fIcrypt\fR library. Defaults to \fI/usr/lib/libcrypt.a .sp .4v LIBDBM#The \fIdbm\fR library. Defaults to \fI/usr/lib/libdbm.a .sp .4v LIBDES#The \fIdes\fR library. Defaults to \fI/usr/lib/libdes.a .sp .4v LIBL#The \fIlex\fR library. Defaults to \fI/usr/lib/libl.a .sp .4v LIBKDB#Defaults to \fI/usr/lib/libkdb.a .sp .4v LIBKRB#Defaults to \fI/usr/lib/libkrb.a .sp .4v LIBM#The math library. Defaults to \fI/usr/lib/libm.a .sp .4v LIBMP#Defaults to \fI/usr/lib/libmp.a .sp .4v LIBPC#Defaults to \fI/usr/lib/libpc.a .sp .4v LIBPLOT#Defaults to \fI/usr/lib/libplot.a .sp .4v LIBTELNET#Defaults to \fI/usr/lib/libtelnet.a .sp .4v LIBTERM#Defaults to \fI/usr/lib/libterm.a .sp .4v LIBUTIL#Defaults to \fI/usr/lib/libutil.a .sp .4v SRCS#T{ List of source files to build the program. It defaults to \f(CW\s10${PROG}.c\fR\s0. T} .sp .4v STRIP#T{ If defined, this should be the flag passed to the install program to cause the binary to be stripped. If it is not defined, the binary will not be stripped. It defaults to \f(CW\s10-s\fR\s0. T} .TE .Te The following variables are not defined in \fIbsd.prog.mk\fR, but will be used if they have been defined elsewhere: .ne 10 .Ts "variables used by \fIbsd.prog.mk\fR" .XX "bsd.prog.mk" .TS H linesize(2), tab(#) ; lfCWp9 | lw55 . \fRVariable#Purpose _ .TH N COPTS#T{ Additional flags to supply to the compiler when compiling C object files. T} .sp .4v HIDEGAME#T{ If \f(CW\s10HIDEGAME\fR\s0 is defined, the binary is installed in \fI/usr/games/hide\fR, and a symbolic link is created to \fI/usr/games/dm\fR. T} .sp .4v LDADD#T{ Additional loader objects. Usually used for libraries. T} .sp .4v LDFLAGS#T{ Additional loader flags. T} .sp .4v LINKS#T{ A list of pairs of file names to be linked together. For example \f(CW\s10LINKS= ${DESTDIR}/bin/test ${DESTDIR}/bin/[\fR\s0 links \fI/bin/test\fR to \fI/bin/[\fR. T} .sp .4v NOMAN#T{ If set, \fImake\fR does not try to install man pages. This variable is only defined in \fIbsd.prog.mk\fR, .XX "bsd.prog.mk" and not in \fIbsd.lib.mk\fR .XX "bsd.lib.mk" or \fIbsd.man.mk\fR. .XX "bsd.man.mk" T} .sp .4v PROG#T{ The name of the program to build. If not supplied, nothing is built. T} .sp .4v SRCS#T{ List of source files to build the program. If \f(CW\s10SRC\fR\s0 is not defined, it's assumed to be \f(CW\s10${PROG}.c\fR\s0. T} .sp .4v SHAREDSTRINGS#T{ If defined, the \fIMakefile\fR defines a new \f(CW\s10.c.o\fR\s0 rule which uses \fIxstr\fR to create shared strings. T} .sp .4v SUBDIR#T{ A list of subdirectories that should be built as well. Each of the targets executes the same target in the subdirectories. Note that the name in this file is \f(CW\s10SUBDIR\fR\s0, though it has the same function as the variable \f(CW\s10SUBDIRS\fR\s0 in \fIbsd.subdir.mk\fR. .XX "bsd.subdir.mk" T} .TE .Te There are a couple more points to note: .Ls B .Li If the file \fI../Makefile.inc\fR .XX "../Makefile.inc" .XX "Makefile.inc" exists, it is included before the other definitions. This is one possibility for specifying site preferences, but of course it makes assumptions about the source tree structure, so it's not completely general. .Li The file \fIbsd.man.mk\fR .XX "bsd.man.mk" is included unless the variable \f(CW\s10NOMAN\fR\s0 is defined. We'll take another look at \fIbsd.man.mk\fR on page \*[bsd-man-mk]. .Le .Ch "bsd.lib.mk" \fIbsd.lib.mk\fR .XX "bsd.lib.mk" contains definitions for making library files. It supplies the same targets as \fIbsd.prog.mk\fR, .XX "bsd.prog.mk" but defines or uses a much more limited number of variables: .ne 10 .Ts "Variables defined or used in \fIbsd.lib.mk\fR" .TS H linesize(2), tab(#) ; lfCWp9 | lw55 . \s10\fRVariable#Purpose _ .TH N LDADD#T{ Additional loader objects. T} .sp .4v LIB#T{ The name of the library to build. The name is in the form used to pass to the C compiler with the \f(CW\s10-l\fR\s0 flag--if you want to build \fIlibfoo.a\fR, you set \f(CW\s10LIB\fR\s0 to \f(CW\s10foo\fR\s0. T} .sp .4v LIBDIR#T{ Target installation directory for libraries. Defaults to \fI/usr/lib\fR. T} .sp .4v LIBGRP#T{ Library group owner. Defaults to \fIbin\fR. T} .sp .4v LIBOWN#T{ Library owner. Defaults to \fIbin\fR. T} .sp .4v LIBMODE#T{ Library mode. Defaults to 444 (read access for everybody). T} .sp .4v LINTLIBDIR#T{ Target directory for lint libraries. Defaults to \fI/usr/libdata/lint\fR. T} .sp .4v NOPROFILE#T{ If set, only standard libraries are built. Otherwise (the default), both standard libraries (\fIlibfoo.a\fR) and profiling libraries (\fIlibfoo_p.a\fR) are built.\** T} .sp .4v SRCS#T{ List of source files to build the library. Unlike in \fIbsd.prog.mk\fR, .XX "bsd.prog.mk" there is no default value. T} .TE .Te .FS A \fIprofiling library\fR .XX "profiling library" is a library which contains additional code to aid profilers, programs which analyze the CPU usage of the program. We don't cover profiling in this book. .FE Given the choice of compiling \fIfoo.s\fR or \fIfoo.c\fR, \fIbsd.lib.mk\fR chooses \fIfoo.s\fR. Like \fIbsd.prog.mk\fR, it \fI\&.include\fRs \fIbsd.man.mk\fR. Unlike \fIbsd.prog.mk\fR, it does this even if \f(CW\s10NOMAN\fR\s0 is defined. .Ch "bsd.subdir.mk" \fIbsd.subdir.mk\fR .XX "bsd.subdir.mk" contains definitions for making files in subdirectories. Since only a single program target can be made per directory, BSD-style directory trees tend to have more branches than others, and each program is placed in its own subdirectory. For example, if I have three programs \fIfoo\fR, \fIbar\fR and \fIbaz\fR, I might normally write a \fIMakefile\fR with the rule .Ps all: foo bar baz foo: ${FOODEPS} bar: ${BARDEPS} baz: ${BAZDEPS} .Pe As we have seen, this is not easy to do with the BSD configuration scheme. Instead, you might place all the files necessary to build \fIfoo\fR in the subdirectory \fIfoo\fR, and so on. You could then write .Ps SUBDIRS = foo bar baz \&.include .Pe \fIfoo/Makefile\fR could then contain .Ps PROG = foo DPADD = ${FOODEPS} \&.include .Pe Of course, in real life it would make more sense to define \f(CW\s10DPADD\fR\s0 to be whatever \f(CW\s10FOODEPS\fR\s0 was. It's quite possible to get by with just a two line \fIMakefile\fR. .LP \fIbsd.subdir.mk\fR is structured in the same way as \fIbsd.prog.mk\fR. Use \fIbsd.prog.mk\fR for making files in the same directory, and \fIbsd.subdir.mk\fR for making files in subdirectories. If you want to do both, use \fIbsd.prog.mk\fR and define \f(CW\s10SUBDIR\fR\s0 instead of \f(CW\s10SUBDIRS\fR\s0. .Ch "bsd.man.mk" .Pn bsd-man-mk \fIbsd.man.mk\fR .XX "bsd.man.mk" contains definitions for installing man pages. It is \fI\&.include\fRd from \fIbsd.prog.mk\fR and \fIbsd.lib.mk\fR, so the target and variables are available from both of these files as well. It defines the target \f(CW\s10maninstall\fR\s0, which installs the \fIman\fR pages and their links, and uses or defines the following variables: .ne 10 .Ts "Variables used or defined by \fIbsd.man.mk\fR" .TS H linesize(2), tab(#) ; lfCWp9 | lw55 . \s10\fRVariable#Meaning _ .TH N MANDIR#T{ The base path of the installed \fIman\fR pages. Defaults to \fI/usr/share/man/cat\fR. The section number is appended directly to \f(CW\s10MANDIR\fR\s0, so that a man page \fIfoo.3\fR would be installed in \fI/usr/share/man/cat3/foo.3\fR. T} .sp .4v MANGRP#T{ The group which owns the \fIman\fR pages. Defaults to \fIbin\fR. T} .sp .4v MANOWN#T{ The owner of the \fIman\fR pages. Defaults to \fIbin\fR. T} .sp .4v MANMODE#T{ The permissions of the installed \fIman\fR pages. Defaults to 444 (read permission for anybody). T} .sp .4v MANSUBDIR#T{ The subdirectory into which to install machine specific \fIman\fR pages. For example, i386 specific pages might be installed under \fI/usr/share/man/cat4/i386\fR. In this case, \f(CW\s10MANSUBDIR\fR\s0 would be set to \f(CW\s10/i386\fR\s0. T} .sp .4v MANn#T{ (\f(CW\s10n\fR\s0 has the values 1 to 8). Manual page names, which should end in \f(CW\s10.[1-8]\fR\s0. If no \f(CW\s10MAN\fR\s0 variable is defined, \f(CW\s10MAN1=${PROG}.1\fR\s0 is assumed. T} .sp .4v MLINKS#T{ A list of pairs of names for manual page links. The first filename in a pair must exist, and it is linked to the second name in the pair. T} .TE .Te .Ch "bsd.own.mk" Not all variants of the BSD configuration system use\fIbsd.own.mk\fR. .XX "bsd.own.mk" Where it is supplied, it contains default permissions, and may be used to override definitions in \fIsys.mk\fR, which \fIinclude\fRs it. .Ch "bsd.doc.mk" \fIbsd.doc.mk\fR .XX "bsd.doc.mk" contains definitions for formatting hardcopy documentation files. It varies significantly between versions and omits even obvious things like formatting the document. It does, however, define the following variables, which can be of use in your own \fIMakefile\fR: .ne 10 .Ts "Variables defined in \fIbsd.doc.mk\fR" .TS H linesize(2), tab(#) ; lfCWp9 | lw55 . \s10\fRVariable#Meaning _ .TH N PRINTER#T{ Not a printer name at all, but an indicator of the kind of output format to be used. This is the argument to the \fI[gt]roff\fR flag \f(CW\s10-T\fR\s0. Defaults to \f(CW\s10ps\fR\s0 (PostScript output). T} .sp .4v BIB#T{ The name of the \fIbib\fR processor. Defaults to \f(CW\s10bib\fR\s0. T} .sp .4v COMPAT#T{ Compatibility mode flag for groff when formatting documents with Berkeley me macros. Defaults to \f(CW\s10-C\fR\s0. T} .sp .4v EQN#T{ How to invoke the \fIeqn\fR processor. Defaults to \f(CW\s10eqn -T${PRINTER}\fR\s0. T} .sp .4v GREMLIN#T{ The name of the gremlin processor. Defaults to \f(CW\s10grn\fR\s0. T} .sp .4v GRIND#T{ The name of the \fIvgrind\fR processor. Defaults to \f(CW\s10vgrind -f\fR\s0. T} .sp .4v INDXBIB#T{ Name of the \fIindxbib\fR processor. Defaults to \f(CW\s10indxbib\fR\s0. T} .sp .4v PAGES#T{ Specification of the page range to output. Defaults to \f(CW\s101-\fR\s0. T} .sp .4v PIC#T{ Name of the \fIpic\fR processor. Defaults to \f(CW\s10pic\fR\s0. T} .sp .4v REFER#T{ Name of the \fIrefer\fR processor. Defaults to \f(CW\s10refer\fR\s0. T} .TE .Te @

AltStyle によって変換されたページ (->オリジナル) /