home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-10-18 | 61.8 KB | 2,238 lines |
- .\" format with
- .\" tbl % | xroff -ms | lpr
- .\"
- .\" revision date - change whenever this file is edited
- .ds Rd 3 August 1990
- .\" document revision number - change each time document is released
- .ds Rn 1.03
- .\"
- .nr PO 1.2i \" page offset 1.2 inches
- .nr PD .7v \" inter-paragraph distance
- .\"
- .EH 'Imake in X11R4'- % -''
- .OH ''- % -'Imake in X11R4'
- .OF 'Revision date:\0\0\*(Rd'\s+1\*-DRAFT SCRIBBLINGS\*-\s-1'Printed:\0\0\n(dy \*(MO 19\n(yr'
- .EF 'Revision date:\0\0\*(Rd'\s+1\*-DRAFT SCRIBBLINGS\*-\s-1'Printed:\0\0\n(dy \*(MO 19\n(yr'
- .\"
- .\"
- .\" I - italic font (taken from -ms and changed)
- .de I
- .nr PQ \\n(.f
- .if t \&\\$3\\f2\\$1\\fP\&\\$2
- .if n .if \\n(.$=1 \&\\$1
- .if n .if \\n(.$>1 \&\\$1\c
- .if n .if \\n(.$>1 \&\\$2
- ..
- .\" start block. LP gives a bit extra space. Can say .Ds .IP C, etc.
- .de Ds
- .if \\n(.$<1 .LP
- .if \\n(.$>=1 \\$1
- .if \\n(.$<2 .DS
- .if \\n(.$>=2 .DS \\$2 \\$3 \\$4 \\$5
- ..
- .\" end block. If arg is given, it replaces the .LP (e.g., .De .IP).
- .de De
- .DE
- .if \\n(.$<1 .LP
- .if \\n(.$>=1 \\$1 \\$2 \\$3 \\$4 \\$5
- ..
- .TL
- Using Imake to Configure
- .br
- the X Window System
- .br
- Version 11, Release 4
- .AU
- Paul DuBois
- dubois@primate.wisc.edu
- .AI
- Wisconsin Regional Primate Research Center
- Document revision:\0\0\*(Rn
- Revision date:\0\0\*(Rd
- .AB
- The X Window System\(dg
- .FS \(dg
- X Window System is a trademark of the Massachusetts Institute of Technology.
- .FE
- is a large software project that, despite its size,
- is remarkable in its portability.
- Much of this is due to the method employed to configure the X
- distribution for building and installation: use of a small number of
- tools and isolation of machine dependencies into a small number of
- files that can be easily maintained and modified.
- This document discusses one of those tools,
- .I imake ,
- and the design of the configuration files used in conjunction with it.
- .AE
- .NH
- Introduction
- .LP
- This document describes how
- .I imake
- configuration files are set up in the X Window System.
- It is assumed that you know something about what
- .I imake
- is supposed to be used for (in general),
- and that you're reading this to find out something
- about how that is accomplished in X (in particular).
- The description applies to X Version 11, release 4 configuration files, which
- are organized quite differently than those from previous releases.
- .LP
- Other documentation (from the X11R4 distribution) that you may find useful
- includes:
- .IP \(bu
- Section 2 of ``X Window System, Version 11 Release 4 Release Notes,''
- by Jim Fulton.
- .IP \(bu
- .I mit/doc/config/usenixws/paper.ms :
- ``Configuration Management in the X Window System,'' also by Jim Fulton.
- .IP \(bu
- .I mit/config/README :
- ``X Window System Imake Configuration Guide, Release 4.''
- .IP \(bu
- .I mit/config/imake.man :
- manual page for
- .I imake .
- .IP \(bu
- .I mit/util/makedepend/mkdepend.man :
- manual page for
- .I makedepend .
- .IP \(bu
- .I contrib/doc/imake/imake.tex :
- ``An
- .I Imake
- Tutorial,'' by Mark Moraes.
- This was written between R3 and R4, but is worthwhile reading, nevertheless.
- .LP
- You should also have access to the X configuration files (in
- .I mit/config ).
- These are not really documentation as such,
- but it is expected that you have them at hand, for comparison
- against the descriptions below.
- .LP
- .I imake
- is generally conceded to have a pretty steep learning curve.
- The
- .I README
- referred to above notes that
- .I imake
- ``can be somewhat tricky to master,'' an observation attested to by
- many who use it.
- There seem to be three camps regarding
- .I imake ;
- those who think it's wonderful, those who think it's wretched, and those
- who suspect it might be useful (else why would it be used to configure
- a major publicly-available effort like X?) but are puzzled by it.
- The present document was written to fill in some of the gaps in the
- existing documentation, in order to try to swell the ranks of the first
- group by depleting the membership of the third.
- (Those who despise
- .I imake \*-members
- of the second group\*-have good reasons for doing so and the present
- effort is not likely to sway them.
- It is worth noting that the author of
- .I imake
- is in this group.)
- .LP
- Where appropriate, the current X configuration files are compared to those
- from previous releases to show how limitations of earlier configuration
- architectures have been eased.
- There are also occasional comments to indicate how
- .I imake
- and the X configuration files might be adapted for use in contexts
- other than building X.
- .LP
- This document is independent of the efforts of the MIT X Consortium.
- There are no doubt errors lurking within, both of understanding and of fact;
- they are my own.
- Please send corrections, criticisms and comments to the address above.
- .NH
- The tools: imake, makedepend, xmkmf
- .LP
- .I imake
- is a configuration tool\*-the main tool used to configure X.
- It is not a replacement for the
- .I make
- program, but it works
- in an environment that assumes the availability of
- .I make
- as the tool used to direct project building and installation.
- .I imake
- eliminates the need to write
- .I Makefiles
- directly.
- The name means ``include-make''\*-\fIimake\fR
- uses the C preprocessor
- .I cpp ,
- taking advantage of its include-file and macro-processing
- facilities for the purpose of generating
- .I Makefiles
- suitable for
- .I make .
- .LP
- For each directory in the X distribution,
- .I imake
- reads a bunch of
- configuration files that go to a lot of trouble to compensate for and
- adjust to the individual characteristics of your system.
- These are combined with an
- .I Imakefile
- from the current directory and the whole mess is sent through
- .I cpp
- to build a
- .I Makefile
- there.
- The same configuration files are used to build every
- .I Makefile ;
- they are kept together in
- .I mit/config ,
- isolating machine dependencies in one location to ease development
- and maintenance.
- In contrast, the
- .I Imakefile
- is directory-specific (it specifies the targets to be built in that directory)
- and is machine-independent.
- .LP
- This means that when the distribution is built on a different machine,
- only the configuration files need be changed.
- The
- .I Imakefiles
- do not need to be.
- If X configuration were specified directly using
- .I Makefiles ,
- this would not be true.
- Because
- the configuration information in
- .I Makefiles
- is not portable, each one would have to be edited individually\*-bad
- enough for a single
- .I Makefile ,
- but an overwhelming prospect for a project the size of X.
- .LP
- The value of being able to localize machine-dependent configuration
- information into one place should not be underestimated, particularly
- as X becomes more sophisticated and the number of systems on which it
- runs increases.
- The number of
- .I make
- variables used to build X has increased from approximately 60
- in R1 to 100 in R3 to 150 in R4.
- .LP
- Another tool,
- .I makedepend ,
- is used to generate header file dependencies for C source files in
- each directory after the
- .I Makefile
- has been built.
- Dependencies of targets upon object files can be statically listed in the
- .I Imakefile ,
- but not those for header files.
- Different systems organize these differently so dependencies on them
- must be generated dynamically.
- .LP
- While X is being built,
- .I imake
- itself is located with the configuration files in
- .I mit/config .
- .I makedepend
- lives in
- .I util/makedepend
- if you use the compiled version (preferred),
- or in
- .I util/scripts
- if you use the shell script version (slower).
- .LP
- When X is installed, copies of
- .I imake ,
- .I makedepend ,
- and a related tool,
- .I xmkmf ,
- are placed in a public directory, and the configuration files are
- copied to
- .I /usr/lib/X11/config .
- .I xmkmf
- is used to bootstrap a
- .I Makefile
- from an
- .I Imakefile
- using the installed configuration files,\**
- .FS
- Normally a new
- .I Makefile
- is produced with ``make Makefile'', an operation that presumes you
- already have a properly configured
- .I Makefile
- containing the rules necessary to run
- .I imake .
- Hence the bootstrap problem.
- Obviously, if you know the proper incantation to utter, you can issue
- the appropriate
- .I imake
- command manually, but
- .I xmkmf
- eliminates the need.
- Besides, the only way you'd know which wand to wave is by having a
- reasonable understanding of
- .I imake
- in the first place\*-in which case you wouldn't be reading this!
- .FE
- and can be used to build
- programs from outside of the X source tree, such as you might write
- yourself or get from comp.sources.x on Usenet.
- .LP
- The X configuration files make very
- few assumptions about the capabilities of
- .I make
- itself.
- Although several enhanced versions of
- .I make
- provide special features or extensions, any
- .I Makefile
- that relies on universal availability of those features
- will fail on systems with less-capable versions of
- .I make .
- .I Makefiles
- produced by
- .I imake
- in X do not use any of these constructs, so they should work with
- even the lowest-common-denominator
- .I make
- program.
- .LP
- Since
- .I imake
- passes its input through
- .I cpp ,
- the configuration file writer can take advantage of several features
- not present in plain-vanilla
- .I make ,
- such as parametrized macros (using #define), file inclusion (using
- #include) and conditional testing (using #if, #ifdef, #ifndef).
- This ameliorates many of the consequences of having to assume that such a
- .I make
- is the only one available.
- .LP
- Use of
- .I cpp
- can produce problems, too, of course.
- .IP (1)
- How to specify comments that should end up in the
- .I Makefile .
- .I make
- comments are introduced by a ``#'' character\*-unfortunately,
- .I cpp
- treats lines beginning with ``#'' as preprocessor directives.
- A comment of the form
- .Ds
- # if your system doesn't have ranlib, use /bin/true
- .De .IP
- is considered a symbol test by
- .I cpp
- and is gobbled up, while a comment like
- .Ds
- # The next rule is a workaround for a broken compiler
- .De .IP
- generates a
- .I cpp
- syntax error.
- To get around this, comments
- should be preceded by ``/**/#'' instead of just ``#''.
- .I cpp
- will strip off the ``/**/'' (the empty C comment)
- and won't treat the line as a directive (though it's
- still liable to symbol substitution).
- .IP
- The exception to this ``comment-commenting'' convention is in the
- .I Imakefile
- itself, where
- .I imake
- automatically adds ``/**/'' onto lines beginning with ``#'' that are not
- preprocessor directives.
- The reason for this is to insulate the end user of
- .I imake
- (who simply writes the
- .I Imakefile
- and not the underlying configuration files) from the need to be aware
- of, or abide by, the commenting convention.
- I would hazard a guess that many people are not aware of this
- exception, given the high incidence of
- .I Imakefiles
- containing ``/**/#''.
- .IP
- Comments that are to be passed through to the
- .I Makefile
- can be written as normal C comments (text surrounded by ``/*'' and ``*/'')
- and will deleted by
- .I cpp .
- .IP (2)
- The configuration files define several multiple-line macros that are
- intended to produce multiple lines of output.
- .I cpp
- joins multi-line macros into a single line, so some post-processing is
- necessary.
- .IP (3)
- Sometimes the values of
- .I cpp
- symbols are to be concatenated.
- The symbol names cannot be concatenated in the configuration files,
- because that results in a different symbol name, so they must be kept
- apart somehow.
- The empty C comment is useful here, too.
- For instance, if Prefix, LibName and Suffix are defined as
- .I lib ,
- .I mylib
- and
- .I .a ,
- respectively, to obtain the concatentation value
- .I libmylib.a
- one must write Prefix/**/LibName/**/Suffix, not PrefixLibNameSuffix.
- .NH
- Configuration file architecture
- .LP
- To produce a
- .I Makefile
- from an
- .I Imakefile ,
- the following configuration files are used:
- .Ds
- .ta 1.5i
- Imake.tmpl master template
- \fIplatform\fR.cf platform-specific definitions (the filename varies)
- site.def site-specific definitions
- Project.tmpl X-specific default definitions
- Imake.rules \fIcpp\fR macros to generate \fImake\fR rules
- .De
- In general,
- if a port exists for your system, the only file that you should need to modify
- to build and install X is
- .I site.def .
- In some cases it may be necessary to modify the platform file.
- .I Imake.tmpl ,
- .I Project.tmpl
- and
- .I Imake.rules
- should be left alone.\**
- .FS
- It should be emphasized that ``should be left alone'' applies
- .I "only to building X itself" .
- If you are adapting the configuration files for use with another
- project, you will probably modify all of them somewhat.
- You may even find yourself in the position of having modified them to such
- an extent that they end up hacked to bits, incapable of configuring
- anything, with you left possessing only the faint hope that something useful
- will rise, Phoenix-like, from out of the remains.
- Be assured\*-it won't.
- But cheer up; start again and learn from your mistakes.
- .FE
- .LP
- If you are porting X to a new platform, you will need to write your
- own platform file, and modify the top part of
- .I Imake.tmpl
- slightly.
- If you are doing a new port of X,
- .I or
- porting the X configuration files for use with a different project, you
- are well-advised to study all of the configuration files thoroughly.
- Ignorance is not bliss in such instances.
- .LP
- .I Imake.tmpl
- contains an #include line for each of the other four configuration files and
- for the
- .I Imakefile
- in the current directory.
- It also contains in-line sections for global constant definitions,
- header block selection, description of system characteristics, build
- definitions, and extra
- .I make
- rules.
- The template is
- structured as follows to make everything fit together:
- .LP
- .TS
- box tab (%) ;
- l l s l l
- l _ _ _ l
- l | l l s | l
- l | l l s | l
- l | l _ l | l
- l | l | l | l | l
- l | l _ l | l
- l | l _ l | l
- l | l | l | l | l
- l | l _ l | l
- l | l l l | l
- l | l l l | l
- l | l _ l | l
- l | l | l | l | l
- l | l _ l | l
- l | l _ l | l
- l | l | l | l | l
- l | l _ l | l
- l | l _ l | l
- l | l | l | l | l
- l | l _ l | l
- l | l l s | l
- l _ _ _ l .
- \h'.01i'%Imake.tmpl:%\h'.01i'%\h'.01i'
- %
- %\h'.01i'%global constants
- %%header blocks
- %%
- %%#include <\fIplatform\fR.cf>
- %%
- %%
- %%#include <site.def>
- %%
- %%system description and
- %%build definitions
- %%
- %%#include <Project.tmpl>
- %%
- %%
- %%#include <Imake.rules>
- %%
- %%
- %%#include "./Imakefile"
- %%
- %%extra \fImake\fR rules
- %
- .TE
- .LP
- Before these sections of the template are described, there are some general
- principles that should be kept in mind.
- .LP
- Much of the flexibility of the X configuration files is achieved
- through the use of the following construct, which defines
- .I symbol
- only if it has not already been defined:
- .Ds
- #ifndef \fIsymbol\fR
- #define \fIsymbol value\fR
- #endif
- .De
- This construct allows any system-, build- or project-related symbol to
- be given a default definition if none has been supplied earlier;
- coupled with support for inclusion of platform- and site-specific
- files prior to the section in which the default is defined,
- the default may be overridden
- by a definition occurring within those files.
- For example, the default for the C compiler symbol occurs in the build
- definitions section of
- .I Imake.tmpl
- and is defined thus:
- .Ds
- #ifndef CcCmd
- #define CcCmd cc
- #endif
- .De
- If the GNU C compiler is to be used instead, the default definition
- can be overridden
- simply by putting the following in
- .I site.def :
- .Ds
- #ifndef CcCmd
- #define CcCmd gcc
- #endif
- .De
- Use of the #ifndef/#endif construct is pervasive throughout the X11R4
- configuration files, to a much greater extent than in the X11R3 files.
- This is especially true in the platform-specific files.
- .LP
- A fairly consistent pattern followed within the system/build section of
- .I Imake.tmpl
- and within
- .I Project.tmpl
- is that definitions for
- .I cpp
- symbols are listed first, followed by definitions for
- .I make
- variables.
- I presume this is done because there is greater flexibility
- available in defining
- .I cpp
- symbols, e.g., through #ifndef conditional testing.
- Since
- .I cpp
- can't tell whether a
- .I make
- variable has previously been defined, the strategy adopted is to associate a
- .I cpp
- symbol with a given
- .I make
- variable, define the symbol conditionally to allow the possibility of
- overriding, then equate the
- variable to whatever value the symbol ends up with.
- For instance,
- .I Imake.tmpl
- contains:
- .Ds
- #ifndef CcCmd
- #define CcCmd cc
- #endif
- .sp .3v
- \&. . .
- .sp .3v
- CC = CcCmd
- .De
- If no earlier definition of CcCmd overrides the default (e.g., in
- .I site.def ),
- CC ends up as
- ``cc''.
- On the other hand, if the default is overridden, e.g., to use ``gcc''
- instead, CC ends up as ``gcc''.
- .LP
- Sometimes ``mixed'' symbol definitions occur, in which
- .I cpp
- symbols are defined in terms of
- .I make
- variables.
- There are at least two reasons to do this.
- .IP (1)
- To avoid order-of-definition problems.
- Consider the two sets of definitions below.
- .Ds
- .ta 3i
- #ifndef a #ifndef a
- #define a b #define a ${B}
- #endif #endif
- A = a A = a
- .sp .3v
- \&. . . . . .
- .sp .3v
- #ifndef b #ifndef b
- #define b z #define b z
- #endif #endif
- B = b B = b
- .De .IP
- What ends up in the
- .I Makefile
- is:
- .Ds
- .ta 3i
- A = b A = ${B}
- B = z B = z
- .De .IP
- The example on the left defines a (and hence A) in terms of
- a symbol that hasn't been defined yet; both get the value of a
- literal ``b''.
- The example on the right works; b is defined as ``z'', B gets
- the same value.
- A becomes ``${B}'', which is not evaluated further until
- .I make
- is run.
- At that time A evaluates properly to ``z'', independently of the order in
- which a and b are defined in the configuration file.
- .IP (2)
- To allow for greater flexibility at installation time.
- For example, UsrLibDir and USRLIBDIR are defined as:
- .Ds
- #ifndef UsrLibDir
- #define UsrLibDir $(DESTDIR)/usr/lib
- #endif
- .sp .3v
- \&. . .
- .sp .3v
- USRLIBDIR = UsrLibDir
- .De .IP
- Symbols such as IncRoot, BinDir, AdmDir are defined similarly, even
- though DestDir (to which DESTDIR is eventually equated) is defined
- earlier (i.e., there is no order-of-definition problem here).
- If a user wants the install to take place under a different root than
- DestDir, the command ``make DESTDIR=/alternate/root install''
- suffices, by overriding the definition of DESTDIR in the
- .I Makefile .
- If UsrLibDir, etc., were defined directly in terms of DestDir rather
- than DESTDIR, this would not be possible.\**
- .FS
- Actually, it would be possible, but cumbersome: ``make install
- BINDIR=/alt/bin/dir ADMDIR=/alt/adm/dir LIBDIR=/alt/lib/dir ...''
- .FE
- .LP
- Each of the sections of
- .I Imake.tmpl
- is described below.
- The descriptions only contain representative examples of the symbols
- used in each configuration file.
- For exhaustive lists, consult the appendix.
- .NH 2
- Global constant definitions
- .LP
- This section of
- .I Imake.tmpl
- defines two symbols (YES as 1 and NO as 0).
- References to these symbols are legion
- throughout the rest of the configuration
- specification and their values should not be changed.
- .LP
- Note: symbols #define'd in the configuration files or the
- .I Imakefile
- have nothing to do with symbols #define'd in your programs; they
- are entirely independent.\**
- .FS
- I once wondered about this, which seems pretty ridiculous now.
- .FE
- .NH 2
- Header block selection
- .LP
- The header block section of
- .I Imake.tmpl
- determines the type of machine on which
- .I imake
- is being run.
- This is done by looking for a
- .I trigger \*-a
- .I cpp
- preprocessor symbol that uniquely and unambiguously indicates a given platform.
- For instance,
- ``sun'' is defined only on Sun systems, ``apollo'' only on Apollo systems,
- and
- ``ultrix'' is only on Ultrix systems.
- Their header blocks look like this:
- .Ds
- .ta 3i
- \fBSun:\fR \fBUltrix:\fR
- #ifdef sun #ifdef ultrix
- #define MacroIncludeFile <sun.cf> #define MacroIncludeFile <ultrix.cf>
- #define MacroFile sun.cf #define MacroFile ultrix.cf
- #undef sun #ifdef vax
- #define SunArchitecture #undef vax
- #endif /* sun */ #define VaxArchitecture
- #endif
- \fBApollo:\fR #ifdef mips
- #ifdef apollo #undef mips
- #define MacroIncludeFile <apollo.cf> #define MipsArchitecture
- #define MacroFile apollo.cf #endif
- #undef apollo #undef ultrix
- #define ApolloArchitecture #define UltrixArchitecture
- #endif /* apollo */ #endif
- .De
- The trigger symbol might be predefined by
- .I cpp
- itself; if no such predefined symbol is available,\**
- .FS
- A goal ANSI C will help us reach?
- .FE
- .I imake
- is built to explicitly pass a definition for one to
- .I cpp
- to cause the correct header block to be selected.
- .LP
- If no trigger is defined, a generic configuration
- header block is selected instead.
- Since that means the platform wasn't
- properly determined, a warning is written into the
- .I Makefile :
- .Ds
- # WARNING: Imake.tmpl not configured; guessing at definitions!!!
- # This might mean that BOOTSTRAPCFLAGS wasn't set when building imake.
- .De
- The resulting generically-configured
- .I Makefile
- will probably fail in one of a number of strange and wondrous ways when
- used to try to build anything,
- With any luck, the hapless user will examine the
- .I Makefile
- to figure out
- what went wrong, see the warning, and realize that the platform wasn't
- determined properly.
- .LP
- Failure to find a defined trigger symbol might occur because no
- port exists for the machine in question, and thus no header block for
- it exists.
- (Each time X is ported to a new platform, a new header block is added
- to this section of
- .I Imake.tmpl .)
- Failure will also occur if
- .I imake
- was not built properly (i.e., it doesn't pass the
- proper trigger symbol definition to
- .I cpp ).
- .LP
- Assuming the proper header block is selected, several
- things happen inside of it.
- The name of the associated platform-specific
- .I .cf
- file is defined for later inclusion by the template; one or more architecture
- indicator symbols are defined that can be used
- by later configuration sections
- to test for particular software or hardware platforms;
- the trigger symbol is undefined so it won't trigger any other header
- block.
- .LP
- A header block may define a single architecture indicator symbol that refers
- both to the software and hardware,
- or separate indicators may be defined for an operating system that
- runs on multiple hardware types,
- For example, ``ultrix'' indicates an Ultrix system, but it is no longer
- true (as it once was) that a VAX can be assumed as the hardware
- platform\*-RISC Ultrix systems run on MIPS chips now.
- Thus UltrixArchitecture is defined as the software indicator symbol, and
- VaxArchitecture or MipsArchitecture as the hardware indicator.
- .LP
- Software indicator symbols should be unique.
- Hardware indicator symbols are not necessarily unique in themselves
- and may be shared across different software
- platforms, e.g., MipsArchitecture can be defined for Ultrix or SGI systems,
- VaxArchitecture for Ultrix or BSD systems.
- .LP
- .I Imakefiles
- should always test for indicator symbols rather than trigger symbols,
- since the former are more reliable (the latter are undefined by the
- header block, anyway).
- .LP
- The use of predefined or
- .I imake -supplied
- .I cpp
- trigger symbols is fraught with peril, and one must construct the
- header blocks carefully, for two reasons:
- .IP (1)
- Symbols may be ambiguous.
- For instance, ``vax'' can be defined both under Ultrix and under BSD.
- Thus, the Ultrix header block must come first.
- It tests for ``ultrix'' and if that succeeds, defines UltrixArchitecture
- and undefines ``vax'' so the BSD block will fail.
- .IP (2)
- Symbols may become ambiguous in unanticipated ways in the
- future.
- The ``mips'' symbol is an example.
- In R3 it was used to unambiguously detect a true MIPS machine.
- This can no longer be done given the presence of that symbol on other
- systems that also run on MIPS chips now.
- .LP
- When porting X to other platforms, it is sometimes
- difficult to know either what the trigger symbol should be, or what
- indicator symbol(s) to use.
- Consider MIPS machines running RISC/os.
- ``mips'' is insufficient as a trigger, because it is does not
- unambiguously define MIPS systems.
- The hardware indicator symbol is clear enough, MipsArchitecture, but
- the software indicator is less so.
- The name of the MIPS operating system suggests that
- RiscosArchitecture might be a good choice.
- Guess again.
- Acorn Computers Ltd. has an OS with a similar name, ``RISC OS''.\**
- .FS
- My own preference is to use ``mipsriscos'' as the trigger symbol,
- MipsArchitecture as the hardware indicator,
- and MipsRiscosArchitecture
- (which seems suitably unique, but has the disadvantage of being quite
- long, and uneuphonious to boot) as the software indicator.
- .FE
- .NH 2
- platform.cf
- .LP
- After the header block section has determined which platform-specific
- file to use, that file is then included by
- .I Imake.tmpl :
- .Ds
- /**/################################################################
- /**/# platform-specific configuration parameters - edit MacroFile to change
- #include MacroIncludeFile
- .De
- where MacroIncludeFile has been defined properly by the header block.
- .LP
- The platform file contains definitions needed to make X build and
- install correctly on a particular system.
- Some common things found here are definitions for the operating
- system name version numbers (major and minor), C compiler version
- numbers, and workarounds for missing commands.
- Overall, these files are really quite a hodgepodge of different things,
- and it is difficult to describe them in any general way.
- You really should read through the
- .I .cf
- file for your system before you try to compile anything, to get an
- idea what can be done with it.
- (It doesn't hurt to read
- .I all
- the
- .I .cf
- files, as a matter of fact, especially if you are doing a new port.)
- .LP
- It is important that version numbers in the platform file
- accurately reflect your system.
- Some symbol definitions are contingent upon the OS or C
- compiler version, to accommodate system changes, deficiencies, or
- bugs, so you want to make sure you get the right definitions.
- For example,
- .I sun.cf
- contains the following:
- .Ds
- #if OSMajorVersion <= 3
- #define HasVoidSignalReturn NO
- #else
- #define HasVoidSignalReturn YES
- #endif
- .De
- This reflects a change in the return type of the
- .I signal()
- system call (from int to void) on Sun systems beginning with SunOS 4.0.
- .LP
- A common missing command workaround occurs for those systems
- that have no BSD-compatible
- .I install
- command, such as in
- .I cray.cf :
- .Ds
- #define InstallCmd sh $(SCRIPTSRC)/install.sh
- .De
- It is important to set the value of the SystemV symbol to either YES or NO
- in the platform file because
- (1) the value of parameters defined in
- .I site.def
- may depend on it, and the default value is not set until
- the system/build definition section (i.e., after
- .I site.def );
- (2)
- the default values of many parameters in later parts of the template
- depend on the value of SystemV.
- For instance, there is usually no
- .I ranlib
- under System V, so the default is defined as a no-op:
- .Ds
- #ifndef RanlibCmd
- #if SystemV
- #define RanlibCmd /bin/true
- #else
- #define RanlibCmd ranlib
- #endif
- #endif
- .De
- It is perhaps safer to rely on predefined
- .I cpp
- symbols (should they exist)
- in the platform-specific files than in the header block section of
- .I Imake.tmpl
- since once you know the system type
- the universe of such
- symbols is more constrained and their meanings cannot clash with those
- of symbols defined on other vendors' systems.
- .LP
- The platform files were significantly reorganized between R3 and R4.
- In R3, each platform file was expected to contain a definition for
- each of the build parameters (C compiler, loader, link command,
- etc.).
- Whenever a change was made that affected one platform file, it usually
- affected them all.
- Since the definitions were usually broadly similar across platforms,
- this was more work than necessary.
- The approach adopted in R4 is to supply best-guess values as the
- default definitions for these parameters in the template, which
- individual platform files may override as necessary.
- This set of defaults defines a baseline configuration.
- There are two advantages to this method.
- The platform files need only specify where they
- .I differ
- from the baseline, by overriding the default definitions; and changes or
- additions to the baseline do not necessarily require all platform files to
- be changed.
- .NH 2
- site.def
- .LP
- This file contains site-specific definitions.
- It is used to reflect local site-wide conventions, at least in
- theory.
- Should you wish to override the defaults,
- this is the place to indicate installation directories, whether to
- build the server and example programs, any special versions of
- programs to use during the build, etc.
- .LP
- The name
- .I site.def
- seems, to me at least, something of a misnomer.
- For instance, one of the things that is likely to be set there
- is HasLargeTmp, to indicate whether you have a large temp file
- directory.
- .I site.def
- is the place for this definition (it depends on your particular
- file system layout, so it doesn't go in the platform-specific file,
- and it's not
- .I cpp -guessable,
- so it doesn't go in the system description section).
- But a ``site'' can be a location at which multiple hosts
- are administered, and which may be configured dissimilarly.
- Some may have a large temp directory, others may not.
- Similarly,
- .I site.def
- is the logical place to specify that you want to use the GNU C
- compiler,
- but you might not necessarily want to use it on all hosts at a site.
- In some ways
- .I host.def
- might be a better name for this file.
- .NH 2
- System description and build parameter definitions
- .LP
- The platform- and site-specific files are followed by a section containing
- a number of default definitions.
- Generally, these describe system characteristics
- (e.g., does it have
- .I vfork() ?
- does it have sockets?) or are related to management of the
- build and installation\**
- .FS
- Viz.,
- .I how
- things should be installed, not
- .I where ;
- defaults for the latter are in
- .I Project.tmpl .
- .FE
- processes (e.g., what is the name of the C compiler?
- does the loader need any special flags?).
- These are not X issues and so are segregated into their own section.
- .LP
- This section of
- .I Imake.tmpl
- should not be modified; definitions should be overridden
- in platform- or site-specific files.
- .NH 2
- Project.tmpl
- .LP
- This
- file contains definitions for parameters that are specific to X.
- Examples: whether to build debuggable versions of libraries, the
- screen resolution, what sorts of connections to accept (UNIX, TCP
- or DECnet sockets), where programs or libraries should be installed.
- .LP
- A number of the
- .I make
- variables in
- .I Project.tmpl
- are directory locations.
- Most of them are named in one of two ways, \fIXXX\fRDIR or \fIXXX\fRSRC.
- Variables of the first form are defined by equating them to the
- values
- .I cpp
- symbols having similar names (e.g., LIBDIR=LibDir).
- The
- .I cpp
- symbols are defined in the usual default-provided-but-override-allowed
- manner.
- This is because these variables refer to where things are to be placed
- at installation time, something which the installer might wish to
- change.
- .LP
- Variables of the second form, \fIXXX\fRSRC, indicate the layout of various
- source directories within the X distribution.
- They are not supposed to be changed, so there is no provision for
- overriding them; they are simply defined
- directly (e.g., SERVERSRC=$(TOP)/server), rather than being equated to
- .I cpp
- symbols.
- .LP
- .I Project.tmpl
- should not be modified; definitions should be overridden
- in platform- or site-specific files.
- .NH 2
- Imake.rules
- .LP
- This file contains
- .I cpp
- macros used to generate (sometimes quite complicated)
- .I make
- rules from concise descriptions of targets and dependencies.
- Since all the
- .I cpp
- symbol substitution functionality is available, these macros can be
- very powerful.
- On the other hand, the syntax used to express them is somewhat
- strange, in order to keep
- .I cpp
- from totally destroying the usefulness of the output for
- .I make
- purposes.
- In fact, one of the functions of
- .I imake
- is to undo some of the damage done by
- .I cpp ;
- an uneasy alliance indeed.
- .LP
- Rules may be defined over multiple lines by appending ``\e'' to the
- end of all lines but the last.
- Since
- .I cpp
- collapses all multi-line macros into a single line, a special trick is
- used to allow
- .I imake
- to post-process
- .I cpp
- output to figure out where to put the newlines back so that proper
- .I make
- syntax is preserved:
- ``@@'' in a rule is replaced by a newline in the resulting
- .I Makefile .\**
- .FS
- This all seems quite natural and obvious, now that I have worked
- with these things for a while.
- I remember, though, that the first few times I looked at the X
- .I imake
- rules, especially the more complicated ones,
- the formatting and syntax seemed so bizarre to me that
- a switch flipped in my brain, which then refused to comprehend
- anything at all.
- Repeated exposure gradually inured me to the infelicities of the
- syntax.
- .FE
- .LP
- .B Example:
- A simple rule to compile a program might be (this isn't an actual X
- rule):
- .Ds
- .ta .5i +4i
- # define CompileProgram(program,objects,libraries) @@\e
- program: objects @@\e
- c \-o program objects libraries
- .De
- If invoked in an
- .I Imakefile
- as:
- .Ds
- CompileProgram (xproga, main.o, \-lm)
- .De
- this would expand in the
- .I Makefile
- to:
- .Ds
- .ta .5i
- xproga: main.o
- cc \-o xproga main.o \-lm
- .De
- If invoked as:
- .Ds
- CompileProgram (xprogb, main.o parse.o scan.o, \-lm \-ll \-ly)
- .De
- this would expand to:
- .Ds
- .ta .5i
- xproga: main.o parse.o scan.o
- cc \-o xproga main.o parse.o scan.o \-lm \-ll \-ly
- .De
- .LP
- All the rules in
- .I Imake.rules
- are defined using the standard override
- construct:
- .Ds
- #ifndef \fIrulename\fR
- #define \fIrulename\fR ...
- #endif
- .De
- Thus, even rules are subject to being overridden (something that was
- not true in R3).
- If a rule needs to be overridden for a particular platform,
- the default definition will be placed in the
- platform-specific
- file (\fIsgi.cf\fR does this).
- If a rule only needs redefining in a single directory, it may be
- better to undefine it and redefine right it in that directory's
- .I Imakefile
- (see
- .I mit/config/Imakefile
- for an example).
- .LP
- .I Imake.rules
- should not be modified; definitions should be overridden
- in platform- or site-specific files.
- .NH 2
- \&./Imakefile
- .LP
- The last file included by the template is the
- .I Imakefile
- from the current directory.
- As already mentioned,
- .I make
- comments in this file are made
- .I cpp -safe
- by preceding them with ``/**/'' if necessary.
- The
- .I Imakefile
- indicates targets to be built and installed, and their
- dependencies, in terms of the
- .I cpp
- macros defined in
- .I Imake.rules .
- There may also be targets for generating dependencies, creating
- installation directories, creating lint libraries or tag files, etc.
- .LP
- .I Imakefile -writing
- is described in more detail in a later section.
- .NH 2
- Extra make rules
- .LP
- The last section of
- .I Imake.tmpl
- adds some common targets to the
- .I Makefile ,
- such as a ``Makefile'' target to regenerate the
- .I Makefile
- itself, and default ``tags'' and ``clean'' targets.
- If the directory has subdirectories, rules to
- recurse through them for the ``install'', ``install.man'', ``clean'',
- ``tags'', ``Makefiles'' and ``includes'' targets are generated.
- These rules are added if
- IHaveSubdirs is defined and SUBDIRS is equated to the list of
- subdirectories in the
- .I Imakefile .
- .NH
- Building imake
- .LP
- Before you can build any part of X,
- .I imake
- itself must be built.
- ``make World'' in the top-level X directory builds
- .I imake
- automatically (in
- .I mit/config ).
- The following discussion explains what happens during that process and
- some of the things you may need to do in preparation for the ``World''
- build..
- You want to read this section if ``make World'' dies when you try it, or you
- want to port X to another platform,
- or you want to build
- .I imake
- or adapt the X configuration files for use with other projects.
- It is best if you are willing to look at the following files:
- .I Makefile.ini ;
- .I imakemdep.h ;
- .I ccimake.c ;
- .I imake.c .
- .NH 2
- What you are trying to accomplish
- .LP
- When you build
- .I imake
- you want to
- (1) get it to compile successfully, so you can use it;
- (2) guarantee that it makes sure
- .I cpp
- knows the trigger symbol\*-whether
- .I cpp
- predefines it or not\*-so you don't end up with generically-configured
- .I Makefiles .
- Conspiring to keep you from your goal are three dilemmas.
- .LP
- Dilemma #1:
- .I imake
- generates
- .I Makefiles
- for use in compiling programs;
- .I imake
- is compiled using a
- .I Makefile .
- .LP
- Dilemma #2:
- .I imake
- needs to know your system's trigger symbol in order to pass it along to
- .I cpp
- for proper
- .I Makefile
- generation.
- But
- .I imake
- doesn't know the trigger itself if neither
- .I cc
- nor
- .I cpp
- predefine it.
- .LP
- Dilemma #3:
- Some systems require special C compiler flags to ensure proper
- compilation of all but the most trivial programs.
- One of the facilities provided by
- .I imake -generated
- .I Makefiles
- is that these flags can be automatically specified.
- Of course, that is small consolation when the program to be compiled is
- .I imake \*-which
- happens to be just such a non-trivial program itself.
- .LP
- The solution to the first dilemma is to use a handwritten minimal file
- .I Makefile.ini
- instead.\**
- .FS
- There might be a
- .I Makefile
- in
- .I mit/config
- already,
- but it might not have been generated on your system, so it's not safe to
- use.
- It has a bug in it, anyway.
- .FE
- You might need to hack
- .I Makefile.ini
- file slightly for your system\*-but only slightly.
- If you find yourself making large changes, that is a symptom you don't
- understand what you're supposed to be doing.\**
- .FS
- Or a symptom that I've not explained very clearly what is supposed to
- happen...of course, I prefer the first possibility!
- .FE
- Stop and think some more first.
- .LP
- The second and third dilemmas are solved by manually passing the trigger symbol
- to the
- .I imake
- compilation and using a small bootstrap program that knows what
- special flags are necessary to get
- .I imake
- to compile without error.
- The commands in
- .I Makefile.ini
- that build
- .I imake
- look something like this:\**
- .FS
- The commands actually use CFLAGS, which is defined
- as ``CFLAGS = $(BOOTSTRAPCFLAGS) $(CDEBUGFLAGS)''; you get the idea.
- .FE
- .Ds
- $(CC) \-o ccimake $(BOOTSTRAPCFLAGS) $(CDEBUGFLAGS) ccimake.c
- $(CC) \-o imake $(BOOTSTRAPCFLAGS) $(CDEBUGFLAGS) imake.c `./ccimake`
- .De
- BOOTSTRAPCFLAGS is the
- .I make
- variable used to pass the trigger value for your system to
- .I ccimake
- and
- .I imake
- so they know the platform type.
- It is typically ``BOOTSTRAPCFLAGS=\-D\fItrigger\fR''
- if your
- .I cpp
- doesn't predefine the trigger, empty otherwise.\**
- .FS
- The BOOTSTRAPCFLAGS mechanism was not present in some earlier versions
- of X11 (e.g., R1).
- The number of systems to which X had been ported then was smaller and
- apparently all of them had
- .I cpp 's
- that predefined a unique symbol.
- .FE
- .I ccimake
- is the bootstrap program used to figure out any extra flags needed on
- your platform to get
- .I imake
- to compile.
- It is itself\*-by design\*-so simple that it should compile
- without any special treatment.
- .LP
- BOOTSTRAPCFLAGS is supplied to the
- .I ccimake
- build so it can select the necessary extra flags by platform type.
- Compiled with those flags, and the trigger value in BOOTSTRAPCFLAGS,
- .I imake
- builds correctly, and learns and memorizes the trigger for
- itself, to pass along to
- .I cpp .
- That in turn allows
- .I cpp
- to properly determine the correct header block in
- .I Imake.tmpl
- when
- .I Makefiles
- are generated.
- .NH 2
- Lay the groundwork
- .LP
- First, you need to determine what the trigger symbol is for your system,
- as well as the value of BOOTSTRAPCFLAGS.
- For existing ports, you can find out the trigger symbol by
- examining the header block section of
- .I Imake.tmpl .
- The value of BOOTSTRAPCFLAGS can be found in the platform
- .I .cf
- file for your system.
- Look for a line that defines BootstrapCFlags; if
- .I cpp
- predefines the trigger, there will likely be no such line.
- This means BOOTSTRAPCFLAGS is empty.\**
- .FS
- A complication likely to arise in the future with regard to
- predefined preprocessor symbols is that ANSI C takes a dim view of
- all (or almost all) such.
- BOOTSTRAPCFLAGS is likely
- to be non-empty on more systems as implementations of ANSI C become
- distributed more widely.
- .FE
- Otherwise the value will be something like ``\-D\fItrigger\fR'', e.g.,
- ``\-DmacII'', ``\-Datt'', ``\-Daix''.
- .LP
- (\fBNote:\fR
- .I Imake.tmpl
- contains some comments near its beginning pertaining to new ports.
- These indicate that
- .I imake.c ,
- and
- .I main.c
- in the
- .I makedepend
- source, should be modified.
- These comments are correct for R3 but evidently were not updated for R4;
- in both cases the modifications should be made to
- .I imakemdep.h .
- Similarly, the
- .I README
- file refers to
- .I ccflags.c ,
- the R3 equivalent of
- .I ccimake.c .)
- .LP
- For new ports, you need to invent a trigger symbol
- that uniquely identifies your system and define
- BOOTSTRAPCFLAGS accordingly.
- Suppose you have a Brand X system.
- You can use ``brandx'' as the trigger and ``BOOTSTRAPCFLAGS=\-Dbrandx''.
- You also must modify
- .I imakemdep.h .
- This is a header file #include'd by three programs,
- .I ccimake ,
- .I imake
- and
- .I makedepend ,
- and has one section for each.
- .LP
- The first section of
- .I imakemdep.h
- pertains to
- .I ccimake ;
- it consists of a bunch of #ifdef/#endif blocks that define
- .I imake_ccflags
- according to the trigger symbol.
- .I imake_ccflags
- is defined as the flags needed to compile
- .I imake
- on your platform.
- For instance, if your Brand X system is System V-based, you need to
- specify that:
- .Ds
- #ifdef brandx
- #define imake_ccflags "\-DSYSV"
- #endif
- .De
- .I ccimake
- simply writes the value of
- .I imake_ccflags
- to its standard output.
- Common flags in this definition are \-DSYSV or \-DUSG to indicate System
- V or USG systems.
- Other flags might also be necessary\*-see the ``hpux'' and ``umips''
- blocks for some particularly unpleasant examples.
- If no special flags are necessary to compile
- .I imake
- (e.g., under Ultrix or BSD),
- there does not need to be any block for your trigger symbol, and
- .I ccimake
- simply writes out a default definition of
- .I imake_ccflags
- (currently \-O).
- .LP
- You might have to fool around trying to compile
- .I imake
- by hand to determine the correct flags before you know how to define
- .I imake_ccflags .
- .LP
- The second section of
- .I imakemdep.h
- is for
- .I imake .
- It too has a set of #ifdef/#endif blocks, this time to select a
- trigger symbol definition based on the trigger symbol.
- That sounds circular and it is.
- These blocks add entries to
- .I cpp_argv [\|],
- which is an array of strings to be passed to
- .I cpp
- by
- .I imake .
- If your
- .I cpp
- predefines the correct trigger symbol automatically, you don't need to
- do anything to this.
- Otherwise, this is where you want your trigger symbol to be listed,
- and there should be a block something like this:
- .Ds
- #ifdef brandx
- "\-Dbrandx", /* for Brand X systems */
- #endif
- .De
- This causes
- .I imake
- to pass ``\-Dbrandx'' to
- .I cpp
- to make it simulate predefinition of the trigger.
- When
- .I cpp
- reads the configuration files the trigger will have been defined and
- the correct header block in
- .I Imake.tmpl
- will be selected.
- .LP
- Following the sections for
- .I ccimake
- and
- .I imake ,
- .I imakemdep.h
- contains a third section for
- .I makedepend
- (the compiled version; if you use the shell script version of
- .I makedepend
- in
- .I mit/util/scripts ,
- this section of
- .I imakemdep.h
- is irrelevant).
- It looks for various system- and compiler-related definitions that may
- be predefined by
- .I cc
- and/or
- .I cpp .
- .I makedepend
- uses this information to be smart.
- Consider the following C program fragment:
- .Ds
- #ifdef ultrix
- #include "inca.h"
- #else
- #include "incb.h"
- #endif /* ultrix */
- .De
- If ``ultrix'' is defined,
- .I makedepend
- knows to generate a dependency for ``inca.h'' and not
- ``incb.h'';
- a dumb
- .I makedepend
- has to to assume dependencies on both.
- .LP
- It's easiest simply to leave this section of
- .I imakemdep.h
- alone.
- .NH 2
- Build the program
- .LP
- You're ready to begin (this should actually be simple if you've done
- the above correctly).
- The first thing to do is ensure the absence of any detritus that might
- be laying around from previous builds:
- .Ds
- make \-f Makefile.ini clean
- .De
- Then build
- .I ccimake
- and
- .I imake .
- If your
- .I cpp
- predefines the trigger, you can build with:
- .Ds
- make \-f Makefile.ini
- or
- make \-f Makefile.ini BOOTSTRAPCFLAGS=
- .De
- Otherwise, specify the trigger explicitly.
- E.g., for Brand X, use:
- .Ds
- make \-f Makefile.ini BOOTSTRAPCFLAGS=\-Dbrandx
- .De .NH 2
- Test your handiwork
- .LP
- If
- .I imake
- is supposed to pass a trigger symbol definition to
- .I cpp ,
- you should test whether it actually does or not by executing the
- following command (\fB\-T\fI/dev/null\fR provides an empty input template, and
- \fB\-s\fI/dev/null\fR throws away the output so it doesn't clobber the
- .I Makefile
- in your current directory):
- .Ds
- imake \-v \-T/dev/null \-s/dev/null
- .De
- .B \-v
- causes
- .I imake
- to print out the
- .I cpp
- command that it executes.
- If you don't see a \-D\fItrigger\fR
- in that command,
- .I imake
- wasn't built properly.
- .NH 2
- Modifying other configuration files for a new platform
- .LP
- If you are developing a new port to another system,
- you have to do more than be able to compile
- .I imake ,
- you also need to be able to use it
- in conjunction with the configuration files.
- First, you must modify the header block section of
- .I Imake.tmpl
- to add a block for your system.
- It will look something like this:
- .Ds
- #ifdef brandx
- #define MacroIncludeFile <brandx.cf>
- #define MacroFile brandx.cf
- #undef brandx
- #define BrandxArchitecture
- #endif /* brandx */
- .De
- Second, you must create a platform-specific file
- .I brandx.cf .
- If your bootstrap flags are non-empty, this should contain, at
- minimum, ``#define BootstrapCFlags \-Dbrandx''.
- Most certainly it will have other things in it, too.
- You will discover just what as you go through the process
- of porting the server and/or clients.
- .NH
- Building X, or, When is BOOTSTRAPCFLAGS necessary?
- .LP
- If you have gotten this far, you know you can get
- .I imake
- to build and can proceed to build X itself.
- .I "Before you do anything else,"
- copy the top-level
- .I Makefile
- somewhere safe (outside of the source tree).
- If something goes wrong and this file gets trashed,
- you want to be able to recover it.
- .LP
- Since this document is really about configuring X, not building it, the
- question addressed in this section is:
- how can you get all the
- .I Makefiles
- built?
- .LP
- The ``do everything'' operation in building X is ``make World''.
- It builds
- .I imake ,
- generates all the
- .I Makefiles ,
- removes extraneous object files, builds the header file tree,
- generates dependencies, and compiles everything.
- The only interesting part of from a configuration perspective is the first two
- steps.
- .LP
- The important questions are: (1) what is the value of BOOTSTRAPCFLAGS;
- and (2) when
- must BOOTSTRAPCFLAGS be specified?
- You have already answered the first question in determining how to
- build
- .I imake ,
- so only the second is considered below.
- .LP
- When you build
- .I imake
- ``manually'' in
- .I mit/config
- using
- .I Makefile.ini ,
- you must specify BOOTSTRAPCFLAGS explicitly if it is non-empty.
- What about when building from the top-level directory, e.g., ``make
- World''?
- It is a useful exercise to build
- .I imake
- by hand to test your understanding of the issues involved, but that
- won't help you to do the ``World'' build\*-the first thing
- ``make World'' does, unfortunately, is throw
- .I imake
- away and rebuild it from scratch.
- .LP
- The X Release Notes (section 2) indicate that for
- ``make World'' you should
- specify BOOTSTRAPCFLAGS if you find a definition for BootstrapCFlags in the platform
- .I .cf
- file (which means there is no unique predefined
- .I cpp
- symbol).
- By implication, you do not need to specify BOOTSTRAPCFLAGS
- if there is no value of BootstrapCFlags in your platform
- .I .cf
- file.
- This means essentially that the empty value ``BOOTSTRAPCFLAGS='' is sufficient to
- compile
- .I imake
- properly, which brings up a subtle point.
- Each
- .I Makefile
- created in the X distribution contains a line that says
- .Ds
- BOOTSTRAPCFLAGS=\fIsomething\fR
- .De
- where
- .I something
- may or may not be empty.
- Thus, when you execute a command such as
- .Ds
- make World BOOTSTRAPCFLAGS=\-Dbrandx
- .De
- you are not just
- .I providing
- a value of BOOTSTRAPCFLAGS, you are also
- .I overriding
- the default value in the
- .I Makefile .
- .LP
- The implication that BOOTSTRAPCFLAGS need not be specified when BootstrapCFlags is
- not defined involves a hidden assumption, i.e., that BOOTSTRAPCFLAGS
- .I already
- has the empty value in the top-level
- .I Makefile .
- If you obtain your X distribution from a system on which X has been built
- and on which BOOTSTRAPCFLAGS is non-empty, that assumption is incorrect, so
- if you don't explicitly provide an empty value by saying
- .Ds
- make World BOOTSTRAPCFLAGS=
- .De
- to override the default in the
- .I Makefile ,
- a value which is incorrect for your system is used instead.
- You can get some very strange results this way.
- .LP
- I submit that, in general, the deciding factor determining whether to
- specify BOOTSTRAPCFLAGS is not so much whether BootstrapCFlags is defined or not,
- but whether you've built your
- .I Makefiles
- yet.
- If not, you need to specify BOOTSTRAPCFLAGS,
- .I "even if it's empty."
- Otherwise, you don't have to.
- In practice, this means that when you are building X on a new system,
- you should assume BOOTSTRAPCFLAGS in the
- .I Makefile
- is incorrect and explicitly override it on the command line.
- Normally this will be on the first ``World'' or ``mastermakefiles'' build.
- .LP
- The Release Notes do not cover the general case.
- Rather, they assume you are working from a virgin distribution (where
- the default BOOTSTRAPCFLAGS is in fact empty).
- .LP
- Once the
- .I Makefiles
- have BOOTSTRAPCFLAGS set properly, they will take care of propagating the correct value
- for you automatically\*-forever, even into another operation that
- rebuilds
- .I imake
- and the
- .I Makefiles .
- You can test this for yourself on a machine that has a non-empty BOOTSTRAPCFLAGS.
- Do ``make mastermakefiles BOOTSTRAPCFLAGS=\-D\fItrigger\fR'', then ``make
- mastermakefiles''.
- You'll see that in the second case, BOOTSTRAPCFLAGS is supplied for you.
- .LP
- .B "Note 1:"
- The above discussion assumes that if BOOTSTRAPCFLAGS is not empty, BootstrapCFlags is
- defined
- correctly in the platform
- .I .cf
- file, because BOOTSTRAPCFLAGS normally gets its value from that symbol when
- .I Makefiles
- are generated.
- .LP
- .B "Note 2:"
- It is not necessary to do a ``World'' build to build
- .I imake
- and the
- .I Makefiles ;
- there is a ``mastermakefiles'' target that will do so.
- This is a far more modest undertaking than doing the ``World'' build
- and you can check a few of the
- .I Makefiles
- afterward to see if the ``World'' build is likely to succeed or not:
- If BOOTSTRAPCFLAGS is correct and the correct header block was selected,
- you can
- then go ahead and do ``make World'' without having to specify BOOTSTRAPCFLAGS.
- .NH 2
- Alternatives to BOOTSTRAPCFLAGS
- .LP
- There are two alternatives to specifying BOOTSTRAPCFLAGS explicitly
- on the
- command line when you build
- the
- .I Makefiles ,
- both sneaky and both deprecated.
- They are mentioned here in order to point out why you shouldn't use
- them.
- .LP
- First, you can edit
- .I Makefile.ini
- manually to set the value of BOOTSTRAPCFLAGS directly.
- The reason this is not a good idea is that if you give your X
- distribution to somebody else that doesn't have the same kind of
- machine, you've given away an explicitly misconfigured
- .I Makefile.ini .
- The recipient might fail to appreciate the subtle irony of this
- gesture.
- .LP
- Second, you can forget about BOOTSTRAPCFLAGS entirely.
- That's correct\*-you can build
- .I imake
- with wild abandon and total lack of regard for whether it knows about
- the correct trigger symbol or not.
- ``But on some systems,
- .I imake
- must pass the trigger definition to
- .I cpp
- explicitly,'' you say, ``and
- .I imake
- compiled in such a reckless and irresponsible manner may not do the job.''
- Quite right.
- However...
- .I imake
- also examines your environment, and the value of IMAKEINCLUDE, if
- defined there, is passed to
- .I cpp .
- The value of IMAKEINCLUDE must begin with ``\-I'' (or
- .I imake
- will reject it), but you can set it to ``\-I. \-Dbrandx'' and the
- trigger symbol will be passed through to
- .I cpp
- and your
- .I Makefiles
- will build happily.
- .LP
- This is sneaky because it uses the environment to affect the
- build process in a way that is not evident.
- Worse yet, if you actually install an
- .I imake
- built this way, it won't work for anyone else who isn't privy to the
- IMAKEINCLUDE convention.
- .LP
- (A third alternative is to edit
- BOOTSTRAPCFLAGS to the proper value in the top-level
- .I Makefile
- before ``make World''.
- This is functionally equivalent to specifying it on the command line and
- doesn't really gain you anything.)
- .LP
- (Might want to discuss here how BOOTSTRAPCFLAGS propagates during
- those
- .I make
- operations through use of the ImakeDependency() rule.
- Discuss what that rule checks.)
- .LP
- Discuss
- .I xmkmf ,
- IMAKE_CMD and operation of UseInstalled here.
- .NH
- Imakeconoclasm\*-X configuration bugs
- .LP
- Ugh.
- Highly redundant.
- .LP
- ``make World'' does a ``make clean'' after making all the
- .I Makefiles .
- This means that if you need to remake a
- .I Makefile ,
- .I imake
- will have been removed.
- The rules for ``make Makefile'' include a check to see whether
- .I imake
- needs rebuilding, which is clever enough.
- Unfortunately, when they cause
- .I imake
- to be rebuilt they may not pass BOOTSTRAPCFLAGS.
- This means that every time you build a ``Makefile'' target, BOOTSTRAPCFLAGS
- needs to be specified if it's not empty.
- .B "Give the fix."
- .LP
- .B "[Bug section]"
- If what you are doing won't build
- .I imake ,
- you don't need BOOTSTRAPCFLAGS.
- But it is not always apparent whether a given target will build it or
- not.
- If you don't have UseInstalled defined, the rules for the``Makefile''
- target (present in virtually every
- .I Makefile )
- contain a check to see whether
- .I mit/config/imake
- is actually built; if not, they build it.
- Thus even an apparently innocuous ``make Makefile''
- in some obscure directory somewhere might trigger an
- .I imake
- build.
- .LP
- One bit of confusion that may strike you:
- Do ``make World''.
- This builds
- .I imake ,
- generates all the
- .I Makefiles ,
- cleans all the directories and finally builds the X stuff.
- .LP
- If you later rebuild the
- .I Makefile
- in any directory with ``make Makefile'', you might be surprised to
- find that
- .I imake
- is rebuilt first.
- This reason is that the rules for the ``Makefile'' target check
- whether
- .I imake
- exists, and if not they build it first.
- Since the ``World'' build does a clean after generating the
- .I Makefiles ,
- .I imake
- was thrown away.
- .LP
- In fact,
- .I imake
- will be built the first time ``make Makefile'' is done even if the
- cleaning had not been done.
- The rules that check
- .I imake 's
- existence look for
- .I Makefile
- in
- .I mit/config
- and build
- .I imake
- with that if it's there.
- (It will be because the ``World'' build generates it.)
- But the dependency for
- .I imake
- in
- .I Makefile
- is
- .I imake.o
- while the dependency in
- .I Makefile.ini
- (which
- .I imake
- is initially built with) is
- .I imake.c .
- This means that even if
- .I imake
- is present in
- .I mit/config ,
- it will be built again because
- .I imake.o
- isn't.
- .LP
- That isn't a bug, but it can be confusing.
- What
- .I is
- a bug is that...
- .LP
- The IncRoot symbol is defined twice, once in
- .I Imake.tmpl
- and once in
- .I Project.tmpl .
- This is a minor nit, since neither file is supposed to be modified.
- However, if you use a copy of the configuration files as a base for your own
- projects, you probably
- .I will
- modify them; be aware that changing the definition in
- .I Project.tmpl
- has no effect if you leave both definitions in.
- .LP
- .I makedepend
- has some hardwired pathnames.
- This may bite you if you use
- .I gcc
- or compile on a MIPS system under BSD environment.
- .NH
- Courting disaster: How to do the wrong thing
- .LP
- .I imake
- is wonderful for portability when everything is configured
- properly.
- However, subtle syntax errors in the configuration files are often difficult
- to track down when you begin to make any significant changes to them.
- This section describes some of the misfortunes that may beset you
- should you make so bold as to engage in such an endeavor.
- .LP
- For X, the source of problems might be in any of
- .I Imakefile ,
- .I Imake.rules ,
- .I Imake.tmpl ,
- the platform
- .I .cf
- file, or
- .I site.def .
- The most likely candidates are
- .I site.def
- and the platform file, though, since those are the only ones you're supposed
- to edit.
- (If you're writing an
- .I Imakefile ,
- add that to the list, too.)
- Just remember that effects of mistakes in the early files may
- not be manifest until much later on.
- Problems may appear to originate at locations far from the actual
- cause.
- .IP (1)
- .I Makefile
- trashing
- .IP
- A number of problems during ``make Makefile'' can result in a trashed
- .I Makefile .
- If you have
- .I xmkmf
- working, you can use that to regenerate the
- .I Makefile
- after fixing whatever the problem was.
- Otherwise you must recover it somehow.
- If you have a copy of
- .I Makefile
- stashed somewhere, you can use that.
- If not:
- the first thing that ``make Makefile'' does is to move the original
- .I Makefile
- to
- .I Makefile.bak ;
- if the new
- .I Makefile
- isn't created properly, you can
- usually recover it with ``cp Makefile.bak Makefile''.
- Then you can fix
- the problem and try again.
- If
- .I Makefile.bak
- is trashed as well, you can
- grab the
- .I Makefile
- from another directory at the same level and use that (this works because
- they both contain the same ``make Makefile''
- rule).
- You can also use a
- .I Makefile
- from a directory at another level,
- but you need to edit the line that sets TOP to reflect where the top
- project directory is in relation to the current directory.
- .IP (2)
- Boolean vs. existent/nonexistent symbols
- .IP
- Some symbols are used in boolean fashion and are defined as
- YES or NO.
- They are tested by ``#if \fIsymbol\fR'' or ``#if !\fIsymbol\fR''.
- Others are turned on simply by being defined.
- They are tested by ``#ifdef \fIsymbol\fR'' or ``#ifndef \fIsymbol\fR''.
- Failure to distinquish the sense in which a symbol is used can lead to
- problems.
- It is necessary to define symbols properly
- .I and
- to test them properly.
- .IP
- .B Example:
- YES/NO symbols must be defined properly.
- SystemV is such a symbol, and the test is ``#if SystemV''.
- If you use ``#define SystemV'' thinking that will turn it on, you'll
- have problems; ``#if SystemV'' turns into just ``#if'' and generates:
- .Ds
- cpp: /usr/tmp/tmp-imake.nnnn:line mmmm: syntax error
- .De .IP
- .B Example:
- YES/NO symbols must be tested properly.
- If you test such a symbol with #ifdef, the test will always succeed,
- whether the value is YES or NO; the symbol is defined in
- .I both
- cases.
- .IP
- .B Example:
- Existent/nonexistent symbols must be defined properly.
- A symbol such as UseInstalled is simply defined (as nothing) or left undefined.
- If you say ``#define UseInstalled NO'', thinking that will turn it
- off, you will be surprised.
- (The test ``#ifdef UseInstalled'' will succeed.)
- .IP
- .B Example:
- Existent/nonexistent symbols must be properly.
- Such a symbol may be defined as nothing.
- If you test it, incorrectly, with ``#if symbol'', the test will fail.
- Use #ifdef.
- .IP (3)
- Rule definition problems.
- .IP
- These can occur after ``make Makefile'', if a rule in
- .I Imake.rules
- is
- #define'd with a space between the rule name and the argument list:
- .Ds
- #define rule(arglist) right
- #define rule (arglist) wrong!
- .De .IP
- Some (all?)
- .I cpp 's
- will define rulename as ``(arglist)''.
- When this happens, you'll see
- .Ds
- make: line nnn: syntax error
- .De .IP
- and you'll find `` (arglist)'' on line nnn of the
- .I Makefile
- because ``rule'' wasn't expanded properly (or at least not the way you
- expect).
- Fix it and try again.
- .IP
- Other similar errors can occur if rules are defined or used with spaces
- anywhere between the end of the macro name to the closing parenthesis of
- the argument list.
- This is particularly true if a macro argument is used
- to generate a rule target name.
- .B "Give example."
- .IP (4)
- Failure to supply
- .I cpp
- symbol default values
- .IP
- When a
- .I make
- variable is equated to a
- .I cpp
- symbol, that symbol must be defined somewhere, even if it's just
- defined as nothing.
- Otherwise the make variable will be set to the literal
- .I cpp
- symbol name.
- That is, if you have ``MAKEVAR=CppSymbol'', it must be preceded
- somewhere by:
- .Ds
- #ifndef CppSymbol
- #define CppSymbol \fIwhatever\fR
- #endif
- .De .IP
- or MAKEVAR will end up with the value ``CppSymbol''\*-literally.
- .IP (5)
- Macros expansion failure
- .IP
- Suppose you include the following line in your
- .I Imakefile
- so that a special version of your library will be compiled:
- .Ds
- DebuggedAndProfiledLibraryObjectrule()
- .De .IP
- After you regenerate
- .I Makefile ,
- you try to use it and get the message:
- .Ds
- Make: Must be a separator on rules line nnn. Stop.
- .De .IP
- This is symptomatic of a spelling error.
- The rule is actually
- ``DebuggedAndProfiledLibraryObjectRule()'';
- compare closely with the above.
- If you spell a rule name incorrectly, it won't be expanded.
- Fortunately, these errors are easy to find, because at least the message
- tells you where to look.
- Unfortunately, you can't say ``make Makefile'' after you fix
- .I Imakefile ,
- because the effect of the error is to make your
- .I Makefile
- unusable.
- .NH
- Writing Imakefiles.
- .LP
- This section assumes that
- .I imake ,
- .I makedepend
- and
- .I xmkmf
- are installed in a public directory somewhere.
- (implies configuration files are installed where
- .I xmkmf
- can get at them.)
- This means, in particular, that you should be able to do ``xmkmf''
- to build a
- .I Makefile
- from an
- .I Imakefile
- in the current directory.
- Detailed
- knowledge of the guts of the configuration process is
- .I not
- assumed.
- .LP
- Give example null
- .I Imakefile
- here.
- .LP
- To test the syntactic correctness of your
- .I Imakefile :
- .Ds
- xmkmf ; make Makefile
- .De
- .I xmkmf
- builds the
- .I Makefile
- from scratch and fails if the configuration is bad.
- .I make
- builds a new
- .I Makefile
- using the one built by
- .I xmkmf ,
- and fails if that one is not legal.
- (say how that can happen, e.g., spelling errors cause it.)
- .LP
- Note that the following command lines are not always equivalent:
- .Ds
- make Makefile Makefiles
- make Makefile ; make Makefiles
- .De
- You normally want to build the ``Makefiles'' target when there are
- subdirectories.
- Suppose you add a new directory.
- This is done by changing
- SUBDIRS in the current directory's
- .I Imakefile .
- You then need to rebuild the
- .I Makefile
- so that the definition of SUBDIRS is reset, and then rebuild
- .I Makefile
- in each of those subdirectories.
- The first command line above builds the ``Makefiles'' target using the
- (old) value of SUBDIRS from the (current)
- .I Makefile ,
- which is incorrect.
- The second command line rebuilds the
- .I Makefile ,
- then runs a second
- .I make
- process to build ``Makefiles''.
- The second process sees the (new) value of SUBDIRS in the (new)
- .I Makefile ,
- which includes the new subdirectory, and has the intended result.
- .LP
- This is an instance of the ``doesn't work first time, works second time
- phenomenon''...
- .LP
- Some rules may not work as you expect after changing
- .I IMakefile .
- This means problems can occur the first time you try ``make \fIop\fR'' that
- mysteriously disappear the second time.
- .B "[Illustrate this.]"
- .LP
- Don't forget ``make depend'' after ``make Makefile''.
- .NH
- Other topics to be dealt with
- .LP
- Listed below are some other topics that should eventually find their
- way into this document.
- What do
- .I you
- want to see?
- .LP
- Shortcomings.
- No provision for building non-shell scripts, especially if
- ExecableScripts is NO.
- List disadvantages of
- .I cpp
- scripts.
- .LP
- Some
- .I cpp
- symbols have no
- .I make
- variable equivalent are exist only to control construction of the
- .I Makefile .
- .LP
- IHaveSubdirs,
- IHaveSpecialMakefileTarget
- .LP
- PassCDebugFlags\*-but related to CDEBUGFLAGS
- .LP
- UseInstalled
-