- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
- <HTML>
- <HEAD>
- <META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
- <META NAME="VPSiteProject" CONTENT="file:///D|/rld/Docs/Project.vpp">
- <META NAME="GENERATOR" Content="Visual Page 2.0 for Windows">
- <TITLE>Using Jamfile, Jamrules and Jambase</TITLE>
- </HEAD>
- <BODY>
- <P ALIGN="CENTER"><A HREF="http://ddunbar/Analytics/Jam/Jam.html"> Jam </A></A><A NAME="TOP"></A>
- <H2 ALIGN="CENTER">Using Jamfile, Jamrules and Jambase</H2>
- <P>This document describes how to write Jamfiles using the Jam Jambase rules to build software products. Related
- documents of interest are:</P>
- <UL>
- <LI><A HREF="Jam.html">The Jam Executable Program</A>, which describes using the <B>jam</B> command and the language
- used in Jambase
- <LI><A HREF="Jambase.html">Jambase Reference</A>, which summarizes the Jambase rules and variables
- </UL>
- <P>Jam documentation and source are available from the <A HREF="http://public.perforce.com/public/index.html">Perforce
- Public Depot</A>.</P>
- <P>
- <HR ALIGN="CENTER">
- <H2>Overview</H2>
- <P><B>jam,</B> the Jam executable program, recursively builds target files from source files using dependency and
- build specifications defined in Jamfiles. <B>jam</B> parses rules in Jamfiles to identify targets and sources,
- examines the filesystem to determine which targets need updating, and issues OS commands to update targets.</P>
- <P>A base rules file called "Jambase" is provided with the Jam distribution. The Jambase file defines
- rules and variables which support standard software build operations, like compiling, linking, etc.</P>
- <P>When the Jambase rules are used, <B>jam</B> reads Jambase, then reads a file called "Jamfile" in the
- current directory. The Jamfile describes what to do with the source files in its directory. It may also cause Jamfiles
- in other directories to be read.</P>
- <P>Under certain circumstances, the first Jamfile read also causes a site-specific "Jamrules" file to
- be read. The Jamrules file is an optional set of rule and variable definitions used to define site- or directory-specific
- processing.</P>
- <P>
- <H4>The Basic Jamfile</H4>
- <P>Jamfiles contain rule descriptions, which usually look like:</P>
- <PRE> <I>RuleName</I> <I>targets</I> : <I>targets</I> ;
- </PRE>
- <P>The target(s) to the left of the colon usually indicate what gets built, and the target(s) to the right of the
- colon usually indicate what it is built from.</P>
- <P>A Jamfile can be as simple as this:</P>
- <PRE> Main myprog : main.c util.c ;
- </PRE>
- <P>This specifies that there is a main.c and util.c file in the same directory as the Jamfile, and that those source
- files should be compiled and linked into an executable called myprog. If you cd to the directory where this Jamfile
- lives, you can see exactly how <B>jam</B> would build myprog with:</P>
- <PRE> jam -n
- </PRE>
- <P>Or, you can actually build myprog with the command:</P>
- <PRE> jam</PRE>
- <P>
- <H4>Whitespace</H4>
- <P>Jamfile elements are delimited by whitespace (blanks, tabs, or newlines). The elements include rule names, targets,
- colons, and semicolons. A common mistake users make is to forget the whitespace, e.g.,</P>
- <PRE> Main myprog: main.c util.c ; #<I>WRONG!</I>
- </PRE>
- <P>Jam doesn't distinguish between a typo and a target called "myprog:", so if you get strange results,
- the first thing you should check for in your Jamfile is missing whitespace.</P>
- <P>
- <H4>Filenames, Target Identifiers, and Buildable Targets</H4>
- <P>Consider this Jamfile:</P>
- <PRE> Main myprog : main.c util.c ;
- Libs myprog : libtree ;
- Archive libtree : treemake.c treetrav.c ;
- </PRE>
- <P>The Main rule specifies that an executable called myprog will be built. The compiled main.c and util.c objects
- will be linked to produce myprog. The Libs rule specifies that libtree will be linked into myprog as well. The
- Archive rule specifies which source files will be compiled and archived into the libtree archive library.</P>
- <P>The Jamfile above refers to targets like "myprog" and "libtree". However, depending on the
- build platform, the actual filenames of those targets could be "myprog.exe" and "libtree.lib".
- Most Jambase rules supply the actual filenames of targets, so that Jamfiles themselves need not make any platform-specific
- filename references. If platform specific names are used, they are coerced to the names specific to the build platform
- (eg., xxx.dll -> libxxx.so).</P>
- <P>The <B>jam</B> program builds up a list of unique target identifiers. Unless you are using the SubDir rules
- (described later), the default identifier for a file target is its filename. In the above example, the target identifiers
- on Windows are the filenames: myprog.exe, libtree.lib, main.obj, etc.</P>
- <P>While all Jambase rules refer to "targets", not all targets are buildable. There are two kinds of
- buildable targets: file targets and pseudotargets. File targets are objects that can be found in the filesystem.
- Pseudotargets are symbolic, and represent other targets.</P>
- <P>You can use any buildable target on the <B>jam</B> command line to build a subset of defined targets. On unix,
- for example:</P>
- <PRE> jam libtree.a
- </PRE>
- <P>builds the libtree archive and all the compiled objects that go in it.</P>
- <P>
- <H4>Pseudotargets</H4>
- <P>Most Jambase rules that define file targets also define pseudotargets which are dependent on types of file targets.
- For example, Jambase defines a pseudotarget called "lib", which is dependent on file targets created
- by the Library and Archive rules. So the command:</P>
- <PRE> jam lib
- </PRE>
- <P>used with the Jamfile above would cause the libtree library to be built. <BR>
- There is one pseudotarget built into <B>jam</B> itself, called "all". Jambase sets "all" dependent
- on (almost) all other targets.</P>
- <P>In the unfortunate case where you have a buildable target whose name is the same as one of the Jambase pseudotargets,
- you'll have problems with the conflicting target name. Your workaround choices are:</P>
- <OL>
- <LI>Change the name of your buildable file or directory that conflicts.
- <P>
- <LI>Modify your Jambase and change the name of the conflicting pseudotarget. (Pseudotargets are defined in Jambase
- using the <FONT SIZE="2" FACE="Courier New, Courier">NotFile</FONT> rule.)
- <P>
- <LI>Use grist on the conflicting target name in your Jamfile. E.g., instead of
- <PRE> File lib : libfoo.a ; </PRE>
- try
- <PRE> File <dir>lib : libfoo.a ;
- </PRE>
- </OL>
- <H4>Dependencies</H4>
- <P>Jambase rules set dependencies on targets, so that if you update a source file, all the file targets that depend
- on that source file, and only the ones that depend on that source file, will be updated (rebuilt) the next time
- you run <B>jam</B>.</P>
- <P>Here are some of the dependencies that get set when <B>jam</B> runs on Windows using our example Jamfile:</P>
- <BLOCKQUOTE>
- <BLOCKQUOTE>
- <PRE> Main myprog : main.c util.c ;
- Libs myprog : libtree ;
- Archive libtree : treemake.c treetrav.c ; </PRE>
- </BLOCKQUOTE>
- </BLOCKQUOTE>
- <BLOCKQUOTE>
- <BLOCKQUOTE>
- <P>
- <TABLE BORDER="0">
- <tbody> <TR>
- <TD><B>Target</B></TD>
- <TD> </TD>
- <TD><B>Depends on</B></TD>
- </TR>
- <TR>
- <TD><FONT SIZE="2" FACE="Courier New, Courier">myprog.exe</FONT></TD>
- <TD><FONT SIZE="2" FACE="Courier New, Courier"> </FONT></TD>
- <TD><FONT SIZE="2" FACE="Courier New, Courier">main.obj, util.obj, libtree.lib</FONT></TD>
- </TR>
- <TR>
- <TD><FONT SIZE="2" FACE="Courier New, Courier">libtree.lib</FONT></TD>
- <TD><FONT SIZE="2" FACE="Courier New, Courier"> </FONT></TD>
- <TD><FONT SIZE="2" FACE="Courier New, Courier">treemake.obj, treetrav.obj</FONT></TD>
- </TR>
- <TR>
- <TD><FONT SIZE="2" FACE="Courier New, Courier">treetrav.obj</FONT></TD>
- <TD><FONT SIZE="2" FACE="Courier New, Courier"> </FONT></TD>
- <TD><FONT SIZE="2" FACE="Courier New, Courier">treetrav.c</FONT></TD>
- </TR>
- </tbody> </TABLE>
- </P>
- </BLOCKQUOTE>
- </BLOCKQUOTE>
- <P>Furthermore, the Main and Library rules set up recursive header scanning on their source targets. So after <B>jam</B>
- parses the Jamfile and sets the rule-driven dependencies, it scans the source files for "#include" lines.
- All #include files found during this scan become dependencies of the compiled object. E.g., all header files used
- to compile treetrav.c would be made dependencies of treetrav.obj.</P>
- <P>As a result, when you run <B>jam</B>, it will rebuild targets if either the source files change or the header
- files change. You can't tell by looking at a Jamfile which header files are dependencies, but you can easily display
- those dependencies with:</P>
- <PRE> jam -ndm
- </PRE>
- <H4>Rule Ordering</H4>
- <P>Rules which specify dependencies ( like <FONT FACE="Courier New, Courier">Main</FONT>, <FONT FACE="Courier New, Courier">Library</FONT>
- and <FONT FACE="Courier New, Courier">Archive</FONT>) can be written in any order. <BR>
- <B>jam</B> figures out the order in which targets are built from their dependencies.</P>
- <P>Some rules, however, set variables which are used by subsequent rule invocations, and their ordering is important.
- For example, the SubDir* rules (discussed later) must be invoked in a particular order.</P>
- <P>
- <H4>Detailed Jambase Specifications</H4>
- <P>This document describes how to use various Jambase rules from a functional point of view. You can see the summary
- of available Jambase rules in the <A HREF="http://public.perforce.com/public/jam/src/Jambase.html">Jambase Reference</A>.
- The detailed specifications for any Jambase rule can be found by reading the rule definition itself in the Jambase
- file.</P>
- <P>
- <HR ALIGN="CENTER">
- <H2>Handling Directory Trees</H2>
- <P>The SubDir* rules are used to define source code directory hierarchies. With SubDir and SubInclude, you can
- use <B>jam</B> to build software from source files and Jamfiles spread across many directories, which is typical
- for large projects.</P>
- <P>The SubDir* rules unify an entire source code tree so that <B>jam</B> can read in all the Jamfiles in one pass
- and compute dependencies across the entire project.</P>
- <P>To use the SubDir* rules, you must:</P>
- <OL>
- <LI>Insert a <FONT FACE="Courier New, Courier">SubDir</FONT> rule into the <FONT FACE="Courier New, Courier">Jamfile</FONT>
- for each directory, which describes it's place in the hierarchy.
- <P>
- <LI>Place at the root of the tree a file named <FONT FACE="Courier New, Courier">Jamrules</FONT>. This file could
- be empty, but in practice it contains user-provided rules and variable definitions that are shared throughout the
- tree. Examples of such definitions are library names, header directories, install directories, compiler flags,
- etc.
- <P>
- <LI>Optionally, set an environment variable pointing to the root directory of the source tree. The variable's name
- is left up to you, but in these examples, we use TOP. If TOP is set, absolute path names are constructed; if unset,
- relative path names are used.
- </OL>
- <P>
- <H4>SubDir Rule</H4>
- <P>The SubDir rule must be invoked before any rules that refer to the contents of the directory - it is best to
- put it at the top of each Jamfile. For example:</P>
- <PRE> # Jamfile in $(TOP)/src/util directory.
- SubDir TOP src util ;
- Main myprog : main.c util.c ;
- Libs myprog : libtree ;
- Archive libtree : treemake.c treetrav.c ;
- </PRE>
- <P>This compiles four files in $(TOP)/src/util, archives two of the objects into libtree, and links the whole thing
- into myprog. Outputs are placed in the $(TOP)/src/util directory.</P>
- <P>This doesn't appear to be any different from the previous example that didn't have a SubDir rule, but two things
- are happening behind the scenes:</P>
- <OL>
- <LI>The SubDir rule causes <B>jam</B> to read in the $(TOP)/Jamrules file. (The Jamrules file can alternately be
- named by the variable $(xxxRULES), where xxx is the name of the root variable, e.g., $(TOPRULES)).
- <P>The Jamrules file can contain variable and rule definitions specific to your codeline. It allows you to completely
- customize your build environment without having to rewrite Jambase. Jamrules is only read in once, at the first
- SubDir invocation.</P>
- <LI>The SubDir rule initializes a set of variables that are used to uniquely identify the source files in this
- directory and assign locations to the targets built from files in this directory.
- <P>When you have set a root variable, e.g., $(TOP), SubDir constructs path names rooted with $(TOP), e.g., $(TOP)/src/util.</P>
- <P>Otherwise, SubDir constructs relative pathnames to the root directory, computed from the number of arguments
- to the first SubDir rule, e.g., ../../src/util. In either case, the SubDir rule constructs the path names that
- locate source files. You'll see how this is useful later.</P>
- <P>The SubDir rule takes as its first argument the root variable's name and takes as subsequent arguments the directory
- names leading from the root to the directory of the current Jamfile. Note that the name of the subdirectory is
- given as individual elements: the SubDir rule does not use system-specific directory name syntax. (Note: but it
- could contain system-specific names, and be coerced).
- </OL>
- <H4>SubInclude Rule</H4>
- <P>The SubInclude rule is used in a Jamfile to cause another Jamfile to be read in. Its arguments are in the same
- format as SubDir's.</P>
- <P>The recommended practice is only to include one level of subdirectories at a time, and let the Jamfile in each
- subdirectory include its own subdirectories. This allows a user to sit in any arbitrary directory of the source
- tree and build that subtree. For example:</P>
- <PRE> # This is $(TOP)/Jamfile, top level Jamfile for mondo project.
- SubInclude TOP src ;
- SubInclude TOP man ;
- SubInclude TOP misc ;
- SubInclude TOP util ;
- </PRE>
- <P>If a directory has both subdirectories of its own as well as files that need building, the SubIncludes should
- be either before the SubDir rule or be at the end of the Jamfile - not between the SubDir and other rule invocations.
- For example:</P>
- <PRE> # This is $(TOP)/src/Jamfile:
- SubDir TOP src ;
- Main mondo : mondo.c ;
- Libs mondo : libmisc libutil ;
- SubInclude TOP src misc ;
- SubInclude TOP src util ;
- </PRE>
- <P><B>jam</B> processes all the Jamfiles it reads as if it were reading one single, large Jamfile. Build rules
- like Main and Libs rely on the preceding SubDir rule to set up source file and output file locations, and SubIncludes
- rules read in Jamfiles that contain SubDir rules. So if you put a SubIncludes rule between a SubDir and a Main
- rule, <B>jam</B> will try to find the source files for the Main rule in the wrong directory.
- <H4>Variables Used to Handle Directory Trees</H4>
- <P>The following variables are set by the SubDir rule and used by the Jambase rules that define file targets:</P>
- <P>
- <TABLE BORDER="0">
- <tbody> <TR>
- <TD WIDTH="171" VALIGN="TOP">SEARCH_SOURCE</TD>
- <TD>Rules like Main and Library use $(SEARCH_SOURCE) to set search paths on source files. The SubDir targets (e.g.,
- "TOP src util") are used to construct a pathname (e.g., $(TOP)/src/util), and that pathname is assigned
- to $(SEARCH_SOURCE).</TD>
- </TR>
- <TR>
- <TD WIDTH="171" VALIGN="TOP">LOCATE_SOURCE</TD>
- <TD>$(LOCATE_SOURCE) is used by rules that build generated source files (e.g., Yacc and Lex) to set location of output
- files. The SubDir rule sets LOCATE_SOURCE to the same value as $(SEARCH_SOURCE), unless ALL_LOCATE_TARGET is set.
- Thus the default location of built source files is the directory of the Jamfile that defines them.</TD>
- </TR>
- <TR>
- <TD WIDTH="171" VALIGN="TOP">LOCATE_TARGET</TD>
- <TD>$(LOCATE_TARGET) is used by rules that build binary objects (e.g., Main and Library) to set location of output
- files. Initalized by the SubDir rule to the same value as $(SEARCH_SOURCE), unless ALL_LOCATE_TARGET is set. Thus
- the default location of built binaray files is the directory of the Jamfile that defines them.</TD>
- </TR>
- <TR>
- <TD WIDTH="171" VALIGN="TOP">ALL_LOCATE_TARGET</TD>
- <TD>If $(ALL_LOCATE_TARGET) is set, LOCATE_SOURCE and and LOCATE_TARGET are set to $(ALL_LOCATE_TARGET) instead of
- to $(SEARCH_SOURCE). This can be used to direct built files to be written to a location outside of the source tree,
- and enables building from read-only source trees.</TD>
- </TR>
- <TR>
- <TD WIDTH="171" VALIGN="TOP">SOURCE_GRIST</TD>
- <TD>$(LOCATE_TARGET) is used by rules that build binary objects (e.g., Main and Library) to set location of output
- files. The SubDir targets are formed into a string like "src!util" and that string is assigned to SOURCE_GRIST.
- X This is used to assure uniqueness of target identifiers where filenames themselves are not unique. For example,
- the target identifiers of $(TOP)/src/client/main.c and $(TOP)/src/server/main.c would be <src!client>main.c
- and <src!server>main.c.</TD>
- </TR>
- </tbody> </TABLE>
- </P>
- <P>The $(LOCATE_TARGET) and $(SEARCH_SOURCE) variables are used extensively by rules in Jambase: most rules that
- generate targets (like Main, Object, etc.) set $(LOCATE) to $(LOCATE_TARGET) for the targets they generate, and
- rules that use sources (most all of them) set $(SEARCH) to be $(SEARCH_SOURCE) for the sources they use.</P>
- <P>$(LOCATE) tells jam where to create new targets and $(SEARCH) tells where to find existing ones. See an expanded
- explanation in <A HREF="Jam.html">The Jam Executable Program</A>.</P>
- <P>Note that you can reset these variables after SubDir sets them. For example, this Jamfile builds a program called
- gensrc, then runs it to create a source file called new.c:</P>
- <PRE> SubDir TOP src util ;
- Main gensrc : gensrc.c ;
- LOCATE_SOURCE = $(NEWSRC) ;
- GenFile new.c : gensrc ; </PRE>
- <P>By default, new.c would be written into the $(TOP)/src/util directory, but resetting LOCATE_SOURCE causes it
- to be written to the $(NEWSRC) directory. ($(NEWSRC) is assumed to have been set elsewhere, e.g., in Jamrules.)<BR>
- See the yacc definition in Jambase as another example.
- <H2>Building Executables and Libraries</H2>
- <P>The rules that build executables and libraries are: <FONT FACE="Courier New, Courier">Main, Library</FONT>,
- and <FONT FACE="Courier New, Courier">Archive</FONT>.</P>
- <H4>Main Rule</H4>
- <P>The Main rule compiles source files and links the resulting objects into an executable. For example:</P>
- <PRE> Main myprog : main.c util.c ;
- </PRE>
- <P>This compiles main.c and util.c and links main.o and util.o into myprog. The object files and resulting executable
- are named appropriately for the platform.</P>
- <P>Main uses $(SUFEXE) to determine the suffix on the filename of the built target. <BR>
- <BR>
- Main uses the Objects rule to compile source targets.</P>
- <H4>Archive Rule<BR>
- Library Rule</H4>
- <P>The Archive rule compiles source files, archives the resulting object files into a library, and then deletes
- the object files. For example:</P>
- <PRE> Library libstring : strcmp.c strcpy.c strlen.c ;
- Library libtree : treemake.c treetrav.c ;
- </PRE>
- <P>This compiles five source files, archives three of the object files into libstring and the other two into libtree.
- Actual archive filenames are formed with the $(SUFLIB) suffix. Once the objects are safely in the libraries, the
- objects are deleted.</P>
- <P>Library uses the Objects rule to compile source files.</P>
- <P>
- <H4>Libs Rule</H4>
- <P>To link executables with built libraries, use the Libs rule. For example:</P>
- <PRE> Main myprog : main.c util.c ;
- Libs myprog : libstring libtree ;
- </PRE>
- <P>The Libs rule does two things: it makes the libraries a dependency on the executable, so that they get built
- first; and it makes the libraries show up on the command line that links the executable. The ordering of the lines
- above is not important, because <B>jam</B> builds targets in the order that they are needed.</P>
- <P>You can put multiple libraries on a single invocation of the Libs rule, or you can provide them in multiple
- invocations. In both cases, the libraries appear on the link command line in the order in which they were encountered.
- You can also provide multiple executables to the Libs rule, if they need the same libraries, e.g.:</P>
- <PRE> Libs prog1 prog2 prog3 : libstring libtree ;
- </PRE>
- <H4>Variables Used in Building Executables and Libraries</H4>
- <P>
- <TABLE BORDER="0">
- <tbody> <TR>
- <TD>
- <P ALIGN="CENTER">AR
- </TD>
- <TD> </TD>
- <TD>Archive command, used for Library targets.</TD>
- </TR>
- <TR>
- <TD>
- <P ALIGN="CENTER">SUFEXE
- </TD>
- <TD>*</TD>
- <TD>Suffix on filenames of executables referenced by Main and Libs.</TD>
- </TR>
- <TR>
- <TD>
- <P ALIGN="CENTER">LINK
- </TD>
- <TD> </TD>
- <TD>Link command, used for Main targets.</TD>
- </TR>
- <TR>
- <TD>
- <P ALIGN="CENTER">LINKFLAGS
- </TD>
- <TD> </TD>
- <TD>Linker flags.</TD>
- </TR>
- <TR>
- <TD>
- <P ALIGN="CENTER">LINKLIBS
- </TD>
- <TD> </TD>
- <TD>Link libraries that aren't dependencies. (See note below.) <B>STDLIBS?</B></TD>
- </TR>
- <TR>
- <TD>
- <P ALIGN="CENTER">EXEMODE
- </TD>
- <TD>*</TD>
- <TD>File permissions on Main targets.</TD>
- </TR>
- <TR>
- <TD>
- <P ALIGN="CENTER">MODE
- </TD>
- <TD> </TD>
- <TD>Target-specific file permissions on Main targets (set from $(EXEMODE))</TD>
- </TR>
- <TR>
- <TD>
- <P ALIGN="CENTER">RANLIB
- </TD>
- <TD> </TD>
- <TD>Name of ranlib program, if any.</TD>
- </TR>
- </tbody> </TABLE>
- </P>
- <P>Variables above marked with "*" are used by the Main, Library, and Libs rules. Their values at the
- time the rules are invoked are used to set target-specific variables.</P>
- <P>All other variables listed above are globally defined, and are used in actions that update Main and Library
- targets. This means that the global values of those variables are used, uness target-specific values have been
- set. (For instance, a target-specific MODE value is set by the Main rule.) The target-specific values always override
- global values.</P>
- <P>Note that there are two ways to specify link libraries for executables:</P>
- <UL>
- <LI>Use the Libs rule to specify built libraries; i.e., libraries that are built by Library rules. This assures
- that these libraries are built first, and that Main targets are rebuilt when the libraries are updated.
- <LI>Use the LINKLIBS (<B>STDLIBS?) </B>variable to specify external libraries; e.g., system libraries or third-party
- libraries. The LINKLIBS variable must be set to the the actual link command flag that specifies the libraries.
- </UL>
- <P>For example:</P>
- <PRE> <I>#In Jamrules:</I>
- if $(UNIX) { X11LINKLIBS = -lXext -lX11 ; }
- if $(NT) { X11LINKLIBS = libext.lib libX11.lib ; }
- <I>#In Jamfile:</I>
- Main xprog : xprog.c ;
- LINKLIBS on xprog$(SUFEXE) = $(X11LINKLIBS) ;
- Libs xprog : libxutil ;
- Library libxutil : xtop.c xbottom.c xutil.c ;
- </PRE>
- <P>This example uses the Jam syntax "variable on target" to set a target-specific variable. In this way,
- only xprog will be linked with this special $(X11LINKLIBS), even if other executables were going to be built by
- the same Jamfile. Note that when you set a variable on a target, you have to specify the target identifer exactly,
- which in this case is the suffixed filename of the executable. The actual link command line on Unix, for example,
- would look something like this:</P>
- <PRE> cc -o xprog xprog.o libxutil.a -lXext -lX11
- </PRE>
- <H2>Compiling</H2>
- <P>Compiling of source files occurs normally as a byproduct of the Main or Library rules, which call the rules
- described here. These rules may also be called explicitly if the Main and Library behavior doesn't satisfy your
- requirements.</P>
- <P>
- <H4>Objects Rule</H4>
- <P>The Main and Library rules call the Objects rule on source files. Compiled object files built by the Objects
- rule are a dependency of the <I>obj</I> pseudotarget, so "jam obj" will build object files used in Main
- and Library rules.</P>
- <P>Target identifiers created by the Objects rule have grist set to $(SOURCE_GRIST). So given this Jamfile:</P>
- <PRE> SubDir TOP src lock ;
- Main locker : lock.c ;
- </PRE>
- <P>the object file created is lock.o (or lock.obj) and its target identifier is <src!lock>lock.o (or <src!lock>lock.obj).</P>
- <P>You can also call Objects directly. For example:</P>
- <PRE> Objects a.c b.c c.c ;
- </PRE>
- <P>This compiles a.c into a.o, b.c into b.o, etc. The object file suffix is supplied by the Objects rule.</P>
- <P>
- <H4>Object Rule</H4>
- <P>Objects gets its work done by calling the Object rule on each of the source files. You could use the Object
- rule directly. For example, on Unix, you could use:</P>
- <PRE> Object foo.o : foo.c ;
- </PRE>
- <P>However, the Object rule does not provide suffixes, and it does not provide the grist needed to construct target
- identifiers if you are using the SubDir* rules. A portable and robust Jamfile would need to invoke Object thus:</P>
- <PRE> Object <src!util>foo$(SUFOBJ) : <src!util>foo.c ;
- </PRE>
- <P>which is inelegant and clearly shows why using Objects is better than using Object.</P>
- <P>If there's any advantage to the Object rule, it's that it doesn't require that the object name bear any relationship
- to the source. It is thus possible to compile the same file into different objects. For example:</P>
- <PRE> Object a.o : foo.c ;
- Object b.o : foo.c ;
- Object c.o : foo.c ;
- </PRE>
- <P>This compiles foo.c (three times) into a.o, b.o, and c.o. Later examples show how this is useful.</P>
- <P>The Object rule looks at the suffix of the source file and calls the appropriate rules to do the actual preprocessing
- (if any) and compiling needed to produce the output object file. The Object rule is capable of the generating of
- an object file from any type of source. For example:</P>
- <PRE> Object grammar$(SUFOBJ) : grammar.y ;
- Object scanner$(SUFOBJ) : scanner.l ;
- Object fastf$(SUFOBJ) : fastf.f ;
- Object util$(SUFOBJ) : util.c ;
- </PRE>
- <P>An even more elegant way to get the same result is to let the Objects rule call Object:</P>
- <PRE> Objects grammar.y scanner.l fastf.f util.c ;
- </PRE>
- <P>In addition to calling the compile rules, Object sets up a bunch of variables specific to the source and target
- files. (See Variables Used in Compiling, below.)</P>
- <H4>Cc, C++, Yacc, Lex, As, etc. Rules</H4>
- <P>The Object rule calls compile rules specific to the suffix of the source file. (You can see which suffixes are
- supported by looking at the Object rule definition in Jambase.) Because the extra work done by the Object rule,
- it is not always useful to call the compile rules directly. But the adventurous user might attempt it. For example:</P>
- <PRE> Yacc grammar.c : grammar.y ;
- Lex scan.c : scan.l ;
- Cc prog.o : prog.c ;
- </PRE>
- <P>These examples individually run yacc(1), lex(1), and the C compiler on their sources.</P>
- <P>
- <H4>UserObject Rule</H4>
- <P>Any files with suffixes not understood by the Object rule are passed to the UserObject rule. The default definition
- of UserObject simply emits a warning that the suffix is not understood. This Jambase rule definition is intended
- to be overridden in Jamrules with one that recognizes the project-specific source file suffixes.</P>
- <P><B>ToDo: </B>This is a nice example of why you need UserObject rule, but we need a <B>Resource</B> rule for
- this built-in.</P>
- <P>For example:</P>
- <PRE> #In Jamrules:
- rule UserObject {
- switch $(>){
- case *.rc : ResourceCompiler $(<) : $(>) ;
- case * : ECHO "unknown suffix on" $(>) ;
- }
- }
- rule ResourceCompiler {
- Depends $(<) : $(>) ;
- Clean clean : $(<) ;
- }
- actions ResourceCompiler {
- rc /fo $(<) $(RCFLAGS) $(>)
- }
- #In Jamfile:
- Library liblock : lockmgr.c ;
- if $(NT) { Library liblock : lock.rc ; }
- </PRE>
- <P>In this example, the UserObject definition in Jamrules allows *.rc files to be handle as regular Main and Library
- sources. The lock.rc file is compiled into lock.obj by the "rc" command, and lock.obj is archived into
- a library with other compiled objects.</P>
- <H4>LibraryFromObjects Rule</H4>
- <P>Sometimes the Library rule's straightforward compiling of source into object modules to be archived isn't flexible
- enough. The LibraryFromObjects rule does the archiving (and deleting) job of the Library rule, but not the compiling.
- The user can make use of the Objects or Object rule for that. For example:</P>
- <PRE> LibraryFromObjects libfoo.a : max.o min.o ;
- Object max.o : maxmin.c ;
- Object min.o : maxmin.c ;
- ObjectCcFlags max.o : -DUSEMAX ; <B>ToDo: </B>Use rule to get flag name
- ObjectCcFlags min.o : -DUSEMIN ;
- </PRE>
- <P>This Unix-specific example compiles the same source file into two different objects, with different compile
- flags, and archives them. (The ObjectCcFlags rule is described shortly.) <BR>
- Unfortunately, the portable and robust implementation of the above example is not as pleasant to read:</P>
- <PRE> SubDir TOP foo bar ;
- LibraryFromObjects libfoo$(SUFLIB) : <foo!bar>max$(SUFOBJ)
- <foo!bar>min$(SUFOBJ) ;
- Object <foo!bar>min$(SUFOBJ) : <foo!bar>maxmin.c ;
- Object <foo!bar>max$(SUFOBJ) : <foo!bar>maxmin.c ;
- ObjectCcFlags <foo!bar>min$(SUFOBJ) : -DUSEMIN ;
- ObjectCcFlags <foo!bar>max$(SUFOBJ) : -DUSEMAX ;
- </PRE>
- <P>Note that, among other things, you must supply the library file suffix when using the LibraryFromObjects rule.
- jam will adjust the suffix for the platform specific value.
- <H4>MainFromObjects Rule</H4>
- <P>Similar to LibraryFromObjects, MainFromObjects does the linking part of the Main rule, but not the compiling.
- MainFromObjects can be used when there are no objects at all, and everything is to be loaded from libraries. For
- example:</P>
- <PRE> MainFromObjects testprog ;
- Libs testprog : libprog ;
- Library libprog : main.c util.c ;
- </PRE>
- <P>On Unix, this generates a link command that looks like:</P>
- <PRE> cc -o testprog libprog.a
- </PRE>
- <P>Linking purely from libraries is something that doesn't work everywhere: it depends on the symbol "main"
- being undefined when the linker encounters the library that contains the definition of "main".
- <H4>Variables Used in Compiling</H4>
- <P>The following variables control the compiling of source files:</P>
- <P>
- <TABLE BORDER="0">
- <tbody> <TR>
- <TD VALIGN="TOP">C++</TD>
- <TD>The C++ compiler command</TD>
- </TR>
- <TR>
- <TD VALIGN="TOP">CC</TD>
- <TD>The C compiler command</TD>
- </TR>
- <TR>
- <TD VALIGN="TOP">C++FLAGS <BR>
- CCFLAGS</TD>
- <TD VALIGN="TOP">Compile flags, used to create or update compiled objects</TD>
- </TR>
- <TR>
- <TD>SUBDIRC++FLAGS <BR>
- SUBDIRCCFLAGS</TD>
- <TD VALIGN="TOP">Additonal compile flags for source files in this directory.</TD>
- </TR>
- <TR>
- <TD VALIGN="TOP">OPTIM</TD>
- <TD>Compiler optimization flag. The Cc and C++ actions use this as well as C++FLAGS or CCFLAGS.</TD>
- </TR>
- <TR>
- <TD VALIGN="TOP">HDRS</TD>
- <TD>Non-standard header directories; i.e., the directories the compiler will not look in by default and which therefore
- must be supplied to the compile command. These directories are also used by <B>jam</B> to scan for include files.</TD>
- </TR>
- <TR>
- <TD VALIGN="TOP">STDHDRS</TD>
- <TD>Standard header directories, i.e., the directories the compiler searches automatically. These are not passed to
- the compiler, but they are used by <B>jam</B> to scan for include files.</TD>
- </TR>
- <TR>
- <TD>SUBDIRHDRS</TD>
- <TD>Additional paths to add to HDRS for source files in this directory.</TD>
- </TR>
- <TR>
- <TD>LEX</TD>
- <TD>The lex(1) command</TD>
- </TR>
- <TR>
- <TD>YACC</TD>
- <TD>The yacc(1) command</TD>
- </TR>
- </tbody> </TABLE>
- </P>
- <P>The Cc rule sets a target-specific $(CCFLAGS) to the current value of $(CCFLAGS) and $(SUBDIRCCFLAGS). Similarly
- for the C++ rule. The Object rule sets a target-specific $(HDRS) to the current value of $(HDRS) and $(SUBDDIRHDRS).</P>
- <P>$(CC), $(C++), $(CCFLAGS), $(C++FLAGS), $(OPTIM), and $(HDRS) all affect the compiling of C and C++ files. <BR>
- $(OPTIM) is separate from $(CCFLAGS) and $(C++FLAGS) so they can be set independently.</P>
- <P>$(HDRS) lists the directories to search for header files, and it is used in two ways: <BR>
- first, it is passed to the C compiler (with the flag -I prepended); <BR>
- second, it is used by HdrRule to locate the header files whose names were found when scanning source files. <BR>
- $(STDHDRS) lists the header directories that the C compiler already knows about. <BR>
- It does not need passing to the C compiler, but is used by HdrRule.</P>
- <P>Note that these variables, if set as target-specific variables, must be set on the target, not the source file.
- The target file in this case is the object file to be generated. For example:</P>
- <PRE> Library libximage : xtiff.c xjpeg.c xgif.c ;
- HDRS on xjpeg$(SUFOBJ) = /usr/local/src/jpeg ; <B>ToDo: Use rules to simplify</B>
- CCFLAGS on xtiff$(SUFOBJ) = -DHAVE_TIFF ; </PRE>
- <P><B>ToDo: </B>Bad example. Don't set flags with CCFLAGS. Use DEFINES.</P>
- <PRE></PRE>
- <P>This can be done more easily with the rules that follow.</P>
- <P>
- <H4>ObjectCcFlags, ObjectC++Flags, ObjectHdrs Rules</H4>
- <P>$(CCFLAGS), $(C++FLAGS) and $(HDRS) can be set on object file targets directly, but there are rules that allow
- these variables to be set by referring to the original source file name, rather than to the derived object file
- name. ObjectCcFlags adds object-specific flags to the $(CCFLAGS) variable, ObjectC++Flags adds object-specific
- flags to the $(C++FLAGS) variable, and ObjectHdrs add object-specific directories to the $(HDRS) variable. For
- example: <B><BR>
- ToDo: </B>Another bad example. Use rule Fdefines or <B>ObjectDefines.</B></P>
- <PRE> #In Jamrules:
- if $(NT) {
- CCFLAGS_X = /DXVERSION ; <B>ToDo: Simplify this example.</B>
- HDRS_X = \\\\SPARKY\\X11\\INCLUDE\\X11 ;
- }
- #In Jamfile:
- Main xviewer : viewer.c ;
- ObjectCcFlags viewer.c : $(CCFLAGS_X) ;
- ObjectHdrs viewer.c : $(HDRS_X) ;
- </PRE>
- <P>The ObjectCcFlags and ObjectHdrs rules take .c files as targets, but actually set $(CCFLAGS) and $(HDRS) values
- on the .obj (or .o) files. As a result, the action that updates the target .obj file uses the target-specific values
- of $(CCFLAGS) and $(HDRS).</P>
- <P>
- <H4>SubDirCcFlags, SubDirC++Flags, SubDirHdrs Rules</H4>
- <P>These rules set the values of $(SUBDIRCCFLAGS), $(SUBDIRC++FLAGS) and $(SUBDIRHDRS), which are used by the Cc,
- C++, and Object rules when setting the target-specific values for $(CCFLAGS), $(C++FLAGS) and $(HDRS).</P>
- <P>The SubDir rule clears these variables out, and thus they provide directory-specific values of $(CCFLAGS), $(C++FLAGS)
- and $(HDRS). For example:</P>
- <PRE> #In Jamrules:
- GZHDRS = $(TOP)/src/gz/include ;
- GZFLAG = -DGZ ; <B>ToDo: Bad example!</B>
- #In Jamfile:
- SubDir TOP src gz utils ;
- SubDirHdrs $(GZHDRS) ;
- SubDirCcFlags $(GZFLAG) ;
- Library libgz : gizmo.c ;
- Main gizmo : main.c ;
- Libs gizmo : libgz ;
- </PRE>
- <P>All .c files in this directory files will be compiled with $(GZFLAG) as well as the default $(CCFLAG), and the
- include paths used on the compile command will be $(GZHDRS) as well as the default $(HDRS).
- <H2>Header File Processing</H2>
- <P>One of the functions of the Object rule is set up scanning of source files for (C style) header file inclusions.
- <BR>
- To do so, it sets the special variables $(HDRSCAN) and $(HDRRULE) as target-specific variables on the source file.</P>
- <P>The presence of these variables triggers a special mechanism in <B>jam</B> for scanning a file for header file
- inclusions and invoking a rule with the results of the scan. <BR>
- The $(HDRSCAN) variable is set to an egrep(1) pattern that matches "#include" statements in C source
- files.<BR>
- The $(HDRRULE) variable is set to the name of the rule that gets invoked as such:</P>
- <PRE> $(HDRRULE) source-file : included-files ;
- </PRE>
- <P>This rule is supposed to set up the dependencies between the source file and the included files. <BR>
- The Object rule uses HdrRule to do the job. <BR>
- HdrRule itself expects another variable, $(HDRSEARCH), to be set to the list of directories where the included
- files can be found. <BR>
- Object does this as well, setting $(HDRSEARCH) to $(HDRS) and $(STDHDRS).</P>
- <P>The header file scanning occurs during the "file binding" phase of <B>jam</B>, which means that the
- target-specific variables (for the source file) are in effect. To accomodate nested includes, one of the HdrRule's
- jobs is to pass the target-specific values of $(HDRRULE), $(HDRSCAN), and $(HDRSEARCH) onto the included files,
- so that they will be scanned as well.</P>
- <P>
- <H4>HdrRule Rule</H4>
- <P>Normally, HdrRule is not invoked directly; the Object rule (called by Main and Library) invokes it.</P>
- <P>If there are special dependencies that need to be set, and which are not set by HdrRule itself, you can define
- another rule and let it invoke HdrRule. For example:</P>
- <PRE> #In Jamrules:
- rule BuiltHeaders {
- Depends $(>) : mkhdr$(SUFEXE) ;
- HdrRule $(<) : $(>) ;
- }
- #In Jamfile:
- Main mkhdr : mkhdr.c ;
- Main ugly : ugly.c ;
- HDRRULE on ugly.c = BuiltHeaders ;
- </PRE>
- <P>This example just says that the files included by "ugly.c" are generated by the program "mkhdr",
- which can be built from "mkhdr.c". During the binding phase, <B>jam</B> will scan ugly.c, and if it finds
- an include file, ughdr.h, for example, it will automatically invoke the rule:</P>
- <PRE> BuiltHeaders ugly.c : ughdr.h ;
- </PRE>
- <P>By calling HdrRule at the end of BuiltHeaders, all the gadgetry of HdrRule takes effect and it doesn't need
- to be duplicated.
- <H4>Variables Used for Header Scanning</H4>
- <P>
- <TABLE BORDER="0">
- <tbody> <TR>
- <TD VALIGN="TOP">HDRPATTERN</TD>
- <TD> </TD>
- <TD>Default scan pattern for "include" lines.</TD>
- </TR>
- <TR>
- <TD VALIGN="TOP">HDRSCAN</TD>
- <TD> </TD>
- <TD>Scan pattern to use. This is a special variable: during binding, if both HDRSCAN and HDRRULE are set, scanning
- is activated on the target being bound. The HdrRule and Object rules sets this to $(HDRPATTERN) on their source
- targets.</TD>
- </TR>
- <TR>
- <TD VALIGN="TOP">HDRRULE</TD>
- <TD> </TD>
- <TD>Name of rule to invoked on files found in header scan. The HdrRule and Object rules set this to "HdrRule"
- on their source targets. This is also a special variable; it's the only <B>jam</B> variable that can hold the name
- of a rule to be invoked.</TD>
- </TR>
- <TR>
- <TD VALIGN="TOP">HDRSEARCH</TD>
- <TD> </TD>
- <TD>Search paths for files found during header scanning. This is set from $(HDRS) and $(STDHDRS), which are described
- in the Compiling section. <B>jam</B> will search $(HDRSEARCH) directories for the files found by header scans.</TD>
- </TR>
- </tbody> </TABLE>
- </P>
- <P>The Object rule sets HDRRULE and HDRSCAN specifically for the source files to be scanned, rather than globally.
- If they were set globally, jam would attempt to scan all files, even library archives and executables, for header
- file inclusions. That would be slow and probably not yield desirable results.</P>
- <P>
- <H2>Copying Files</H2>
- <H4>File Rule</H4>
- <P>The File rule copies one file to another. The target name needn't be the same as the source name. For example:</P>
- <PRE> switch $(OS){
- case NT* : File config.h : confignt.h ;
- case * : File config.h : configunix.h ;
- }
- LOCATE on config.h = $(LOCATE_SOURCE) ; <B>ToDo: Why was this bit neccessary?</B>
- </PRE>
- <P>This creates a config.h file from either confignt.h or configunix.h, depending on the current build platform.</P>
- <P>The File rule does not use the LOCATE_SOURCE variable set by the SubDir rule (although it does use SEARCH_SOURCE),
- which means you have to set the copied file's output directory yourself. That's done by setting the special LOCATE
- variable on the target, as shown above, or with the MakeLocate rule described below.</P>
- <H4>Bulk Rule</H4>
- <P>The Bulk rule is a shorthand for many invocations of the File rule when all files are going to the same directory.
- For example:</P>
- <PRE> #In Jamrules:
- DISTRIB_GROB = d:\\distrib\\grob ;
- #In Jamfile:
- Bulk $(DISTRIB_GROB) : grobvals.txt grobvars.txt ;
- </PRE>
- <P>This causes gobvals.txt and grobvars.txt to be copied into the $(DISTRIB_GROB) directory.
- <H4>HardLink Rule</H4>
- <P>The Unix-only HardLink rule makes a hard link (using ln(1)) from the source to the target, if there isn't one
- already. For example:</P>
- <PRE> HardLink config.h : configunix.h ;
- </PRE>
- <H4>Shell Rule</H4>
- <P>The Shell rule is like the File rule, except that on Unix it makes sure the first line of the target is "#!/bin/sh"
- and sets the permission to make the file executable. For example:</P>
- <PRE> Shell /usr/local/bin/add : add.sh ;
- </PRE>
- <P>You can also use $(SHELLHEADER) to dictate what the first line of the copied file will be. For example:</P>
- <PRE> Shell /usr/local/bin/add : add.awk ;
- SHELLHEADER on /usr/local/bin/add = "#!/bin/awk -f" ;
- </PRE>
- <P>This installs an awk(1) script.</P>
- <P>
- <H4>Variables Used When Copying Files</H4>
- <P>
- <TABLE BORDER="0">
- <tbody> <TR>
- <TD VALIGN="TOP">FILEMODE</TD>
- <TD> </TD>
- <TD>Default file permissions for copied files</TD>
- </TR>
- <TR>
- <TD VALIGN="TOP">SHELLMODE</TD>
- <TD> </TD>
- <TD>Default file permissions for Shell rule targets</TD>
- </TR>
- <TR>
- <TD VALIGN="TOP">MODE</TD>
- <TD> </TD>
- <TD>File permissions set on files copied by File, Bulk, and Shell rules. File and Shell sets a target-specific MODE
- to the current value of $(FILEMODE) or $(SHELLMODE), respectively.</TD>
- </TR>
- <TR>
- <TD VALIGN="TOP">SHELLHEADER</TD>
- <TD> </TD>
- <TD>String to write in first line of Shell targets (default is #!/bin/sh).</TD>
- </TR>
- </tbody> </TABLE>
- <H2>Installing Files</H2>
- <P>Jambase provides a set of Install* rules to copy files into an destination directory and set permissions on
- them. On Unix, the install(1) program is used. If the destination directory does not exist, <B>jam</B> creates
- it first.</P>
- <P>All files copied with the Install* rules are dependencies of the <I>install</I> pseudotarget, which means that
- the command "jam install" will cause the installed copies to be updated. Also, "jam uninstall"
- will cause the installed copies to be removed.</P>
- <P>The Install* rules are:</P>
- <P>
- <TABLE BORDER="0">
- <tbody> <TR>
- <TD VALIGN="TOP"><B>InstallBin</B></TD>
- <TD VALIGN="TOP">
- <P>Copies file and sets its permission to $(EXEMODE). You must specify the suffixed executable name. E.g.:</P>
- <PRE>InstallBin $(BINDIR) : thing$(SUFEXE) ;
- </PRE>
- </TD>
- </TR>
- <TR>
- <TD VALIGN="TOP"><B>InstallFile</B></TD>
- <TD VALIGN="TOP">
- <P>Copies file and sets its permission to $(FILEMODE). E.g.:</P>
- <PRE>InstallFile $(DESTDIR) : readme.txt ;
- </PRE>
- </TD>
- </TR>
- <TR>
- <TD VALIGN="TOP"><B>InstallLib</B></TD>
- <TD VALIGN="TOP">
- <P>Copies file and sets its permission to $(FILEMODE). You must specify the suffixed library name. E.g.:</P>
- <PRE>InstallLib $(LIBDIR) : libzoo$(SUFLIB) ;
- </PRE>
- </TD>
- </TR>
- <TR>
- <TD VALIGN="TOP"><B>InstallMan</B></TD>
- <TD VALIGN="TOP">
- <P>Copies file into the man<I>n</I> subdirectory of the target directory and sets its permission to $(FILEMODE).
- E.g., this copies foo.5 into the $(DESTDIR)/man5 directory:</P>
- <PRE>InstallMan $(DESTDIR) : foo.5 ;
- </PRE>
- </TD>
- </TR>
- <TR>
- <TD VALIGN="TOP"><B>InstallShell</B></TD>
- <TD VALIGN="TOP">
- <P>Copies file and sets its permission to $(SHELLMODE). E.g.:</P>
- <PRE>InstallShell $(DESTDIR) : startup ;
- </PRE>
- </TD>
- </TR>
- </tbody> </TABLE>
- <B>Variables</B></P>
- <P>The following variables control the installation rules:</P>
- <P>
- <TABLE BORDER="0">
- <tbody> <TR>
- <TD>
- <P ALIGN="CENTER">INSTALL
- </TD>
- <TD>The install program (Unix only)</TD>
- </TR>
- <TR>
- <TD>
- <P ALIGN="CENTER">FILEMODE
- </TD>
- <TD>Default file permissions on readable files.</TD>
- </TR>
- <TR>
- <TD>
- <P ALIGN="CENTER">EXEMODE
- </TD>
- <TD>Default file permission executable files.</TD>
- </TR>
- <TR>
- <TD>
- <P ALIGN="CENTER">SHELLMODE
- </TD>
- <TD>Default file permission on shell script files.</TD>
- </TR>
- <TR>
- <TD>
- <P ALIGN="CENTER">SHRMODE
- </TD>
- <TD>Default file permission on shared libraries</TD>
- </TR>
- <TR>
- <TD>
- <P ALIGN="CENTER">MODE
- </TD>
- <TD>Target-specific file permissions</TD>
- </TR>
- </tbody> </TABLE>
- </P>
- <P>The Install rules set a target-specific MODE to the current value of $(FILEMODE), $(EXEMODE), or $(SHELLMODE),
- depending on which Install rule was invoked.</P>
- <P>The directory variables are defined for convenience: they must be passed as the target to the appropriate Install
- rule. The $(INSTALL) and mode variables must be set (globally) before calling the Install rules in order to take
- effect.</P>
- <H2>Miscellaneous Rules</H2>
- <H4>Clean Rule</H4>
- <P>The Clean rule defines files to be removed when you run "jam clean". Any site-specific build rules
- defined in your Jamrules should invoke Clean so that outputs can be removed. E.g.,</P>
- <PRE> rule ResourceCompiler {
- Depends $(<) : $(>) ;
- Clean clean : $(<) ;
- }
- </PRE>
- <P>Most Jambase rules invoke the Clean rule on their built targets, so "jam clean" will remove all compiled
- objects, libraries, executables, etc.</P>
- <P>
- <H4>MakeLocate Rule</H4>
- <P>MakeLocate is a single convenient rule that creates a directory, sets LOCATE on a target to that directory,
- and makes the directory a dependency of the target. It is used by many Jambase rules, and can be invoked directly,
- e.g.:</P>
- <PRE> GenFile data.tbl : hxtract data.h ;
- MakeLocate data.tbl : $(TABLEDIR) ;
- </PRE>
- <P>In this example, the File rule creates data.tbl from data.h. The MakeLocate causes data.tbl to be written into
- the $(TABLEDIR) directory; and if the directory doesn't exist, it is created first.</P>
- <P>The MakeLocate rule invokes another Jambase rule, MkDir, to (recursively) create directories. MkDir uses the
- $(MKDIR) variable to determine the platform-specific command that creates directories.</P>
- <H4>RmTemps Rule</H4>
- <P>Some intermediate files are meant to be temporary. The RmTemps rule can be used to cause <B>jam</B> to delete
- them after they are used.</P>
- <P>RmTemps must be:</P>
- <UL>
- <LI>the last rule invoked on the permanent file that uses the temporary file(s)
- <LI>invoked with the permanent file as the output target and the temporary file(s) as the input target
- <LI>invoked with the exact target identifiers of the permanent file and the temporary file(s)
- </UL>
- <P>For example:</P>
- <PRE> SubDir TOP src big ;
- GenFile big.y : joinfiles part1.y part2.y part3.y ; # <B>joinfiles ???</B>
- Main bigworld : main.c big.y ;
- RmTemps bigworld$(SUFEXE) : <src!big>big.y ; <B>ToDo: Gristed name rule?</B>
- </PRE>
- <P>This causes big.y to be deleted after it has been used to create the bigworld executable. The exact target identifier
- of big.y is <src!big>big.y (the GenFile and Main rules tack on the grist automatically); the exact target
- identifier of the bigworld executable is bigworld$(SUFEXE).
- <H2>Debugging Jam</H2>
- <OL>
- <LI>Display what jam will build, without executing: <FONT FACE="Courier New, Courier"> jam -n</FONT>
- <LI>Display header dependencies: <FONT FACE="Courier New, Courier">jam -ndm</FONT>
- <LI>Display variable assignments: <FONT FACE="Courier New, Courier">jam -d+5</FONT>
- </OL>
- <H2>Best Practices</H2>
- <OL>
- <LI>To Be Determined
- </OL>
- <P>
- <HR ALIGN="CENTER">
- </P>
- <P>Copyright 1997, 2000 Perforce Software, Inc.
- </BODY>
- </HTML>
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#2 | 4362 | Dick Dunbar | Documentation updates. | 21 years ago | |
#1 | 4356 | Dick Dunbar | Jam 2.5 base established | 21 years ago | |
//guest/perforce_software/jam/src/Jamfile.html | |||||
#6 | 2488 | rmg | Remove the /MR suffix from Jam. === computer:1666: Change 37146 by seiwald@play-seiwald... on 2002/10/21 15:23:18 « |
22 years ago | |
#5 | 486 | Perforce staff | Jam 2.3. See RELNOTES for a list of changes from 2.2.x. Just about every source... file was touched when jam got ANSI-fied. « |
24 years ago | |
#4 | 76 | Laura Wingerd | Integrate command-block-too-long fix, plus minor doc updates. Jam/MR release level is now... 2.2.5. (change 72, change 73, change 74, change 75) « |
26 years ago | |
#3 | 51 | Laura Wingerd | Update copyright year. | 26 years ago | |
#2 | 3 | Perforce maintenance | Jam/MR 2.2.1 (fix for NT handle leak) | 27 years ago | |
#1 | 2 | laura | Add Jam/MR 2.2 source | 27 years ago |