DragonFly On-Line Manual Pages
XMAKE(1) DragonFly General Commands Manual XMAKE(1)
NAME
xmake - portable make utility
SYNOPSIS
xmake [ -v ] [ -f xmakefile ] [ -d[#] ] [ -n ] [ -D sym[=data] ] label1
... labelN
-v print version and exit. If xmake doesn't know what version
it is, someone forgot to re-make and re-install it with itself.
-f specify different default file
-d[#] turn on debugging
-n dry run - do not execute commands lists
-Dsym[=data] specify additional symbols to call cpp with, also sets
the EXTDEFS variable
DESCRIPTION
XMake is a make utility. It is not compatible with other makes, but
provides extended functionality over most standard makes. Whereas most
other makes have confusing rulesets and do not support many-to-many
dependancy specifications, XMake has relatively few (basically no)
rulesets and allows you to easily specify many:many dependancies. This
gives XMake the flexibility to deal with complex project hierarchies
very simply. Despite the fact that there are no built-in rulesets, an
XMakefile is often no more complex then a normal Makefile. XMake
incorporates the following major features:
The ability to specify one-to-many, and many-to-one dependancies
The ability to apply a single command list to many one-to-one
dependancies (typically lots of object files depending on lots of
source files can be dealt with in a single line).
The ability to embed shell commands (e.g. find, ls, whatever...) in
variable and other definitions.
The ability to generate wildcard template conversions on the fly. For
example, you can list the source files and generate the object files
and all associated dependancies from the source file list.
Runs the C preprocessor, allowing you to use #if/#else/#endif and, if
need be, use preprocessor macros. The main purpose is to support the
#include directive and allow operating system and compiler auto-detect.
Maintains special 'dependancy' variables %(left) and %(right) which may
used in command sequences.
Allows variables to be .set inside a command sequence, where the .set
directive is executed when/if the command sequence is executed...
useful when dealing with side effect issues.
Understands delayed-expansion variable specifications. A normal
variable specification is something like $(NAME) or %(NAME), whereas a
delayed-expansion variable specification is something like ${NAME}.
This allows you to set up global variables whos contents are based on
other variables which have not yet been initialized. The variable is
fully resolved when used in a dependancy or executed as part of a
command list.
By default, XMake attempts to access the XMakefile in the current
directory. This can be overriden with the -f option.
DIRECTIVES AND VARIABLE SPECIFICATIONS
Directives must start in column 1. XMake understands the following
directives:
.set varname contents
Set the contents of the specified variable
.beg / .end
Applicable only within a command sequence, allows blank lines to be
inserted without terminating a command sequence.
Variables may be referenced in any one of several ways:
$(varname)
$(varname?wildmatch)
$(varname?wildmatch:wildreplace)
$(varname:wildmatch)
$(varname:wildmatch:wildreplace)
%(special)
%(special:wildmatch)
%(special:wildmatch:wildreplace)
The $() variable form references a .set variable, while the %()
variable form references a special dependancy variable. Dependancy
variables only work within command sequences. Currently %(left) and
%(right) are defined. %(left) represents the left hand side of the
dependancy, while %(right) represents the right hand side.
The optional wildmatch and wildreplace elements allow you to
dynamically restrict transform the elements contained within the
variable. For example, if a variable contains a mix of .c and .h
files, you can extract just the .c files with $(VARNAME:*.c) .
Transformations are accomplished with a third element. Each '*' or '?'
in the match side is represented by %1 to %N on the replace side. You
can also use '*' and '?' on the replace side, which sequentially
represent %1 ... %N. The most common transformation is something like
this:
.set SRCS include.c list.c main.c subs.c
.set OBJS $(SRCS:"*.c":"$(OD)/*.o")
DEPENDANCIES
XMake allows you to specify dependancies in a manner simliar to make.
However, XMake extends the facility to allow many one-to-one
dependancies to be specified on a single line, as well as other
combinations. The format for a dependancy is:
d1 d2 ... dn : s1 s2 ... sn [ : a1 a2 a3 ... aX ]
d1 : s1 s2 ... sn [ : a1 a2 a3 ... aX ]
d1 d2 .. dn : [ : s1 a2 a3 ... aX ]
In the first form, each dN is dependant on the associated sN and ALL of
the a1-aX elemnts.
In the second form, a single d1 depends on ALL of the s1-sN and a1-aX
elements.
In the third form, each destination dN depends on ALL of the a1-aX
elements, and there are no 's' elements listed at all.
Note that the a1..aX elements are optional. You may also specify a
dependancy with no right hand side elements at all. This will cause
the execution list for the left hand side to be run if the left hand
side is ever depended upon from a higher level.
The right hand side is not required to represent a real file if its
label is used on the left hand side of another dependancy. However, if
it does represent a real file, then the 'return code' will be based on
a time-stamp comparison even if the sub-dependancies of the right hand
side themselves are out of date and cause commands to run. The best
example of this is the PROTOS dependancy shown below:
$(OBJS):: $(PROTOS)
$(OBJS):: defs.h
$(OBJS): $(SRCS)
cc $(CFLAGS) %(right) -o %(left) -c
$(PROTOS): $(OD)/$(XMKPROTO) $(SRCS)
$(OD)/$(XMKPROTO) -o %(left) %(right:"*.c")
In this example, the object modules are dependant on the prototype file
being up-to-date (as well as defs.h). However, the prototype file is
updated by xmkproto if any of the source files change. xmkproto is
smart enough to not touch the prototype file if it determines that none
of the prototypes have changed. Even though the PROTOS:SRCS dependancy
is run, the OBJS:PROTOS dependancy will not be run if the prototypes
file was not actually modified.
INCLUDE PATHS
XMake automatically includes the following directories when it runs CPP
on your XMakefile:
The . directory
The .. directory
Your $HOME/.xmk directory
/usr/local/share/xmk
/usr/share/xmk
This allows you to configure XMake in a global system, with local
overrides. Most XMakefiles will not need any of these directories.
The most useful is the . and .. directories, which allow you to setup
hierarchical XMakefile.inc files which are recursively included.
CONCEPTS
It is extremely easy to construct XMakefile's that use a single file or
directory list to compile an entire project. Once you have learned how
to use the wildcard match-and-replace capabilities, you will wonder how
you could have lived without it before. Amoung other things, these
functions allow you to mix multiple file extensions in a single
variable, such as SRCS, yet apply a different ruleset to each
extension.
FILES
XMakefile default xmake control file
$HOME/.xmk In include path for cpp
/usr/local/share/xmk In include path for cpp
/usr/share/xmk In include path for cpp
XMAKE(1)