XMake USAGE
XMake version: 0.93a
Release Date: 08/17/05
Copyright (c) 2003 Gregory Keranen. All rights reserved.
Contents
Introduction
Basic:
Project Configuration
The xmake Command
Special Targets
Advanced:
Technical Overview
Makefiles
XMExtensions
Bundled XMExtensions
Custom Makefiles
Macros for Rule Creation
Other Macros
Special Variables
Naming Conventions
Examples
Debugging
Introduction
One of the goals of XMake is to work as a 'black box', requiring little or
no knowledge of makefile scripting: install, configure, create source
files (with a supported filename suffix), run 'xmake' and output files
will be created automatically without the need to edit a single line in
any makefile. Read the sections below on 'Project Configuration', 'The
xmake Command' and 'Special Targets', to get you started.
Beyond basic usage, XMake offers a re-usable library of makefiles and
macros to simplify project customization and create new XMExtensions to
handle additional source file types. The easiest way to learn how to
customize XMake is to study the included makefile sources and examples.
Advanced users should have a deeper understanding of Gnu Make, such as:
+ makefile syntax; 'include', 'ifeq' and other directives
+ makefile variables : simply expanded versus recursively expanded
+ how Gnu Make reads a makefile and decides what rules to use in
building targets
+ immediate versus delayed variable expansion
+ automatic variables such as '$@', '$<', '$*', etc
+ the various types of rules: explicit rules, pattern or 'implicit'
rules, static-pattern rules, dependency rules
+ built-in functions
+ user-defined functions (actually variables, we prefer to call
'macros')
+ the new $(eval ...) function; use of escaping variables with '$$'
+ command line options such as -p, -d
We have tried to use terminology consistent with Gnu Make, as much as
possible although our usage may differ: 'target' refers to what Gnu Make
calls a 'goal'; a 'dependency' of a target is what Gnu Make calls a
'prerequisite'; 'pattern rules' are sometimes referred to as by Gnu Make
as 'implicit rules'.
The best source for Gnu Make documentation is the included info file;
command: 'info make'.
Project Configuration
In order to provide a stable build environment that does not depend on user
environment settings, XMake is configured creating a PROJECT which includes
all subdirectories not explicitly excluded, or which contain nested XMake
projects. (Project directories are listed in the variable, 'XM_dirTree',
defined in $XMAKE_PROJECT_MAKEFILE.)
Global application-level configuration files are found in the directory:
$XMAKE_HOME/config/
The command for creating a new project is:
$XMAKE_HOME/bin/xmakep
Usage: xmakep [OPTIONS] [PROJECT_DIR]
xmakep OPTIONS:
-b backup local files prior to overwrite
-D enable Debugging info
-e make local copy of XMExtensions directory
-f force overwriting files; non-interactive
-h display help; exit
-p print the current project directory; exit
-t copy template files to local project directory
-v display version; exit
When you create a new project, the files in the directory,
$XMAKE_HOME/config/Project are always copied to the current directory. If
any of these files already exists it will not be overwritten unless you
choose the 'force' option:
$XMAKE_HOME/bin/xmakep -f
The directory, $XMAKE_HOME/config/XMExtensions, contains makefiles which
support processing specific types of source files. To isolate your project
from changes to these global XMExtensions makefiles, you can choose to make
local copies of any or all of them with the command:
$XMAKE_HOME/bin/xmakep -e
If a local XMExtensions makefile is found, XMake will always use it instead
of the global copy.
You may want to add custom makefiles to the local XMExtensions directory if
they will only be used in the current project, otherwise put them in the
global XMExtensions directory to make them available to all projects.
Create a new project at the /path/to/projectDir:
cd /path/to/projectDir
$XMAKE_HOME/bin/xmakep
Edit the project configuration file: '/path/to/projectDir/XMake.conf'
Example of default values:
export XMAKE_SHELL_CMD=/usr/local/bin/bash
export XMAKE_BUILD_CMD=/usr/local/bin/make
export XMAKE_FINAL_TARGETS_PATTERN='/usr/lib/% /usr/include/%'
# export XMAKE_EXTENSIONS=all # enables all extensions
# export XMAKE_EXTENSIONS=none # disables all extensions
By default, xmake tries to build targets in within the current directory
and below, excluding the following directory name patterns: XMExtensions,
tmp, XMakeIgnore*, CVS, RCS, SCCS. You can customize this by editing the
variable, XMAKE_IGNORE_DIRS_RE
(OPTIONAL) Edit the custom project makefile:
'/path/to/projectDir/XMakefile.mks'
This is where you should write custom logic for your project
XMakefile.mks is created with xmakep, but any file with .mks extension
can be used.
(DISCOURAGED) Edit the project makefile: '/path/to/projectDir/XMakefile'
Editing this file gives you more control. Edit at your own risk.
Better to confine customizations to XMakefile.mks
To delete an XMake project, you only need to remove one file:
rm XMake.conf
If another XMake project exists at a higher level in the current path - an
'ancestor' of the deleted project - then the files in the deleted project
come within the scope of the ancestor, although the directories and source
files recognized as actually belonging to the ancestor project will depend
on the ancestor's configuration.
The xmake Command
The command, $XMAKE_HOME/bin/xmake is a wrapper script which passes
arguments to Gnu Make.
For help, type 'xmake -h'
[greg@p3 src]$ xmake -h
Usage: xmake [OPTIONS] [TARGETS]
xmake OPTIONS (not used by Gnu make):
-D Debugging & Verbose output
-E [ext_list] set XMAKE_EXTENSIONS=[ext_list]; override
XMake.conf
-h display help; exit
-V Verbose makefile output
-v display version info; exit
-X set XMAKE_RECURSION=1; override XMake.conf
-x set XMAKE_RECURSION=0; override XMake.conf
All options for Gnu make are supported
Common usage:
xmake
- build the default goal
- by default, this is equivalent to 'make all': all output files
related to source files governed by active XMExtensions will be made
- xmake includes all makefiles in the current project directories
and automatically detects all source files
- any XMake targets or prerequisites outside this directory tree
will be built recursively, if possible, prior to building the default goal
xmake [targets]
- same as above, specifying targets other than the default
xmake clean
- delete all target files created by 'make all'
xmake debug
- display the values of makefile variables
xmake -C newDirectory [targets]
- all actions are performed after changing to 'newDirectory',
including searching for the XMake.conf file, which determines the current
project context
- changing directory within the current project has no effect, due
to the single-makefile design of XMake; the -C option is only useful when
changing to a directory within another project
xmake -X [targets]
- enable recursive sub-make of any external XMake targets
SEE: RECURSION.html
xmake -x [targets]
- inhibit recursive XMake of any external targets
SEE: RECURSION.html
Special Targets
For more detail, see files:
$XMAKE_HOME/config/XMakefile.mkr
$XMAKE_HOME/config/XMakefile
recurse:
# recursively build all targets listed in $(XM_externalTargets) which
# reside in other XMake projects
# this target is automatically built, in a separate process, prior to
# building any other targets, when XMAKE_RECURSION=1, or when 'xmake -X' is
# used from the command line
init : first
# the 'default' rule: used if no command-line targets are specified
# by default, this translates to building target 'all'
first: all
# to override do the following:
- set XM_overrideTargets+=first
- implement the rule for 'first', in a custom makefile
all: $(XM_outfiles)
# builds all targets listed in $(XM_outfiles)
# $(XM_outfiles) is deduced from $(XM_sources), if auto-detect sources
# is enabled
# if auto-detect sources is disabled, you can assign files to
# $(XM_sources) in a special file: $(XMAKE_PROJECT_DIR)/XM_sources.mkho
# Any output files, not implied by XM_sources, should be added manually
# to XM_outfiles
# to add to XM_outfiles, use:
$(eval $(call XM_append,XM_outfiles,$(itemList)))
clean.makefiles:
@-rm -f $(XM_autoMakefiles)
clean.outfiles:
@-rm -f $(XM_outfiles)
clean: clean.outfiles clean.makefiles
# removes all generated files, listed in $(XM_autoMakefiles) and
# $(XM_outfiles)
debug:
# prints the values of some XMake variables
deprules:
# creates the file $(XMAKE_PROJECT_DIR)/XMake.deprules
# this file is used for performing introspection on makefile
# dependencies
Technical Overview
To simplify discussion, we give the following general overview for the
default case, where no modifications have been made to makefiles or
configuration files. By default, 'xmake' performs the following actions,
in the following sequence:
+ read default options from $XMAKE_HOME/config/XMake.defaults
+ try to locate a XMake project file, XMake.conf, within the current
path
+ read options from the XMake.conf file (command line options override)
- I.e.: XMAKE_SHELL_CMD, XMAKE_BUILD_CMD_OPTIONS, XMAKE_EXTENSIONS
- if XMake.conf doesn't exist, prompt user to create a project;
exit
+ set environmental variables, such as $XMAKE_PROJECT_DIR, etc.
+ parse command line options, such as:
-E [extensions_list] overrides settings in XMake.conf
-X enables XMAKE_RECURSION, overriding XMake.conf
-x disables XMAKE_RECURSION, overriding XMake.conf
+ if XMAKE_RECURSION is set:
- try to make all EXTERNAL targets, prior to any others
+ invoke Gnu Make:
- if XMAKE_RECURSION is set:
/usr/local/bin/make -f $XMAKE_HOME/config/XMakefile.xmh -r
recurse
- with no targets specified, 'xmake' next executes:
/usr/local/bin/make -f $XMAKE_HOME/config/XMakefile.xmh -r
+ Gnu Make is now in control; it reads $XMAKE_HOME/config/XMakefile.xmh
+ $XMAKE_HOME/config/XMakefile.xmh
- assigns default values to variables such as:
$(XMAKE), $(XMAKE_PROJECT_MAKEFILE), $(XM_extensions), etc.
- define macros of pattern rules and static pattern rules for
creating output files, such as: XME_patternRule, etc.
- if $XMAKE_PROJECT_DIR/XMakefile.mk exists:
XMAKE_PROJECT_MAKEFILE:=$XMAKE_PROJECT_DIR/XMakefile.mk
include XMAKE_PROJECT_MAKEFILE
else
XMAKE_PROJECT_MAKEFILE:=$XMAKE_HOME/config/XMakefile.mk
include XMAKE_PROJECT_MAKEFILE
+ $XMAKE_PROJECT_MAKEFILE performs the following actions, in order:
- set values of variables such as:
$(XM_dirTree) - computes a list of directories in the current
project, excluding nested projects and other special directories matching
a given pattern
$(XM_extensions) - a list of source files suffixes, supported
by XMExtensions makefiles
$(XM_sources) - if XMAKE_AUTODETECT_SOURCE_FILES enabled source
files with suffixes listed in $(XM_extensions) are automatically detected
$(first) - the name of the default target
- if XMAKE_AUTODETECT_SOURCE_FILES=0 include file XM_sources.mkho
- define the default rule: 'first'
- include the appropriate XMExtensions header makefiles:
XMExtensions/%.mkh
+ for each item listed in $(XM_extensions), appropriate
implementing makefiles are found, in either the local or global
XMExtensions directory
+ XMExtensions/%.mkh define macros which do the following:
- define an output file name, assume 'outputFile' for this
example
- define a corresponding source file, assume 'sourceFile'
for this example
- initialize variables used by the XMExtension
- include $XMAKE_HOME/XMakefile.mkr
+ creates pattern rules for external NESTED targets
+ creates pattern rules for ignored subdirectories
+ defines rules such as recurse, etc.
+ contains empty rules for XMake makefiles, etc.
- include any custom makefiles with suffix %.mkr, excluding
XMExtensions/%.mkr
- include any custom makefiles with suffix %.mko for every file
with suffix %.mks
+ any makefiles with suffix '.mks' are compiled as '.mko' at
this point
- include the appropriate XMExtensions rules makefiles:
XMExtensions/%.mkr
+ XMExtensions/%.mkr do the following:
- define any explicit rules needed
- evaluate macros defined in XMakefile.mkh to create rules
for creating output files
- define rules such as: 'first: $(XM_outfiles)'
+ building $(XM_outfiles) invokes XMExtensions rules, or any
custom rules that apply
- include $(XM_dependencyAutoMakefiles)
+ these are the auto-generated files "%.mkdo"
+ %.mkdo prerequisites force creating them if they don't exist
After all makefiles have been read, then Gnu make builds targets, using the
first applicable rule found in the order in which makefiles were read.
For more detail, please refer to the source files listed in FILES.html
which contain many comments.
Makefiles
The exact order in which makefiles are read is crucial to insure that
variables are set properly and that no rules are defined prior to the
default rule.
The most important distinction is between makefiles which include rules and
those that do not:
+ XMake will always include makefiles without rules before including
any with rules.
A secondary distinction is between auto-generated and manually-generated
makefiles:
+ XMake includes manually generated makefiles BEFORE auto-generated
makefiles of the same type in order to allow custom rules to take
precedence when multiple rules can apply for the same target.
Since there is no standard naming convention in common use for this
purpose, other than the generic "myMakefile.mk", XMake has defined the
following makefile suffix name conventions:
Suffix Type Generated Examples
%.mkh no rules Manually XMExtensions/%.mkh
%.mkho no rules Automatic XM_sources.mkho; may specify sources
%.mkr rules Manually XMExtensions/%.mkr
%.mks rules Manually XMakefile.mks; the preferred method of
customization
%.mko rules Automatic auto-generated from %.mks; $(CURDIR) is
expanded
%.mkdo rules Automatic generated for source files listed in
$(XM_sources)
All Xmake makefiles conform to the SINGLE MAKEFILE CONCEPT, which implies:
+ all makefiles in a project are recursively included, starting with
the top level $XMAKE_MASTER_HEADER:
$XMAKE_HOME/config/XMakefile.mkh
+ only ABSOLUTE PATHS may be used in filenames and pattern rules:
- $(CURDIR) is translated automatically in makefiles with suffix
%.mks
- NOTE: The Gnu Make variable, $(CURDIR), is always set to the
absolute path of the current directory, resolving any symbolic links. This
is NOT the same as using $(PWD) or `pwd`. Since XMake requires consistent
naming of paths, we recommend you ALWAYS use $(CURDIR) in makefiles and
not $(PWD), which may not even be defined in some environments.
All makefiles with suffixes .mkdo .mkho .mko are auto-generated by XMake
and are deleted with 'xmake clean'.
XMExtensions
In the most general terms, XMExtensions can be thought of as a 'package' of
makefiles which are auto-loaded and can provide a set of variables, macros
and rules to the XMake makefile context.
XMExtensions usually define a one-to-one correspondence between source
files and output files.
Extensions are named according to the suffix (excluding any leading dot) of
a single source file type. Each XMExtension defines its variables and rules
in files related to its name:
$XMAKE_EXTENSIONS_DIR/extName.mkh - 'header' makefile; no rules
$XMAKE_EXTENSIONS_DIR/extName.mkr - may include rules
$XMAKE_EXTENSIONS_DIR/extName.conf - config settings appended to
XMake.conf
In general terms, the job of XMExtensions is to encapsulate all specific
knowledge about a source file type:
+ how to process the source file
+ what to name the created output file
+ how to determine any dependencies of the output file
XMExtensions provide:
+ a modular method of including makefiles with rules for source file
types which can be shared among projects; each XMExtension defines a
[source file] -> [output file] name mapping and associated build rules
+ a standard set of macros for writing XMExtension makefiles
+ a consistent interface for writing custom rules which pass options to
Extension rules
+ a set of global variables to control configuration options
XMExtensions are enabled by either:
+ setting XMAKE_EXTENSIONS in XMake.conf file
+ using 'xmake -E' command line option
-E option causes XMAKE_EXTENSIONS to be exported across projects
if you don't want this, use:
export XMAKE_EXTENSIONS='<ext names ...>'; xmake ...
XMExtensions are implemented by:
+ defining a source file suffix, not used by other XMExtensions
+ defining a relationship between source file suffixes and output file
suffixes
+ implementing the necessary makefiles:
Example: if an extension supports source files of suffix '.myExt'
- the name of the XMExtension is 'myExt'
- the makefiles will be named:
'myExt.mkh' - must not contain any rules
'myExt.mkr' - creates all the rules; typically with a call
to eval()
+ installing in the implementing makefiles in directory:
$XMAKE_HOME/config/XMExtensions
+ enabling the use of an XMExtension in your project
There are a some macros that must be defined and a few that must be
evaluated in all XMExtensions makefiles.
The easiest way to create new XMExtensions is to copy an existing makefiles
(such as c.mkh, c.mkr) and modify them to suit your purposes. Begin by
replacing the existing XMExtension name with the name of your new
extension throughout the makefiles; next you must modify the macros (such
as XME_c_cmd, XME_c_dependCmd) to suit the applications which will process
your source files.
One important point to keep in mind is first determine how your XMExtension
will map source -> output file names:
+ If the source filename suffix is simply stripped off in generating
the output file name, use a similar XMExtension (such as phpc which maps
myFile.phpc -> myFile) as a guide
Please refer to the XMExtensions makefiles for a more detailed view of how
they work.
Bundled XMExtensions
XMake is bundled with the following XMExtensions.
The following table lists:
Name - name of the XMExtension
Lang - source file language
Source - wildcard pattern used for auto-detecting source files
Output - pattern of generated output files; '%' matches source
file stem pattern
XME Files - implemented by these files (see
xmake/config/XMExtensions/)
Default - XMExtension is enabled or disabled by default (see
XMakefile)
Name Lang Source Output XME Files Default
c C %.c %.o c.mkh enabled
c.mkr
phpc PHP %.phpc % phpc.mkh disabled
phpc.mkr
phpc.inc
t2h PHP %.t2h % t2h.mkh disabled
t2h.mkr
xdir n/a %.xdir % xdir.mkh enabled
xdir.mkr
ENABLED XMExtensions require only commonly available software:
c
- compile C files; requires gcc or other C compiler
phpc
SEE: PHP.html for full discussion
- processes PHP source files, using PHP command-line binary
- sources are ordinary PHP sources included with php -r '...'
- does NOT require executable source files or #!/usr/bin/php
t2h
- 'text to html' converter, written in PHP
- used to create the XMake documentation
( See http://www.proliberty.com/tools/txt2html-php/doc/ )
xdir
- generic directory container for related files used to
generate output
- contents of file %.xdir/output is copied to %
Custom Makefiles
Custom applications can include any makefile of any name or make use of any
of the suffixes defined above, for organizational purposes.
The preferred method is:
+ put all of your custom makefile code in
$(XMAKE_PROJECT_DIR)/XMakefile.mks
+ *.mks files allow the convenient use of $(CURDIR) to create the
required absolute paths: they are automatically processed to %.mko and
auto-included by XMake.
+ ALL makefiles with suffix %.mks will be translated to %.mko and
automatically included by $(XMAKE_PROJECT_DIR)/XMakefile.
+ If more than one %.mks file exists within the project, the ORDER in
which they are included is NOT specified: this may introduce confusing
behavior. Using only a single custom makefile ensures a more manageable
build environment.
When you create a new project, one empty custom makefile is automatically
created:
$XMAKE_PROJECT_DIR/XMakefile.mks
+ copy this template to any subdirectories that need custom
makefiles
By default, for each source file, a related output file will be generated
by a pattern-rule in the XMExtension makefile. For example, the C language
XMExtension creates a default pattern rule for all *.c source files with
the following line in $XMAKE_HOME/config/XMExtensions/c.mkr:
$(eval $(call XME_patternRule,c))
All macros prefixed by 'XME_' only will apply to source files handled by an
enabled XMExtension. The name of the XMExtension is always the first
parameter to these macros.
Since custom makefiles are read BEFORE the XMExtensions makefiles, any
applicable custom pattern rules will always be used to build targets for
which no explicit or static rules are defined. In other words, custom
pattern rules take precedence over generic pattern rules since they are
encountered first in the makefile order.
Generally, pattern rules are preferable to explicit or static rules since
they support 'chaining': i.e., they can build intermediate target files
generated on the fly, by inference.
Macros for Rule Creation
In order to facilitate handling of external targets, it is recommended to
use XMake macros for custom rule creation, rather than writing your own
rules by hand, since the macros perform additional checks to detect
external targets. Pattern rules in custom makefiles will be read PRIOR to
the default pattern rules and, hence, take precedence.
The easiest way to understand how XMake macros are used to create custom
rules is to study a working example:
$(XMAKE_HOME)/test/XMakeTests.mks
These XMExtensions files can give further insights:
$(XMAKE_HOME)/config/XMExtensions/%.mkh
$(XMAKE_HOME)/config/XMExtensions/%.mkr
Each of the following macros automatically detects any external targets in
the input parameters and adds them to $(XM_externalTargets) so that they
will be built PRIOR to attempting to build dependent targets. ( For full
discussion, see RECURSION.html )
In the examples below, assume:
+ 'ext' is the name of the XMExtension you want to use
+ 'ext-cmd' is the name of the command that creates output files from
source files
+ source files %.ext map to output files %.ext_out
I.e., 'myFile.ext' is compiled by the XMExtension 'ext' to produce
output file 'myFile.ext_out'
+ ellipsis (...) is used to indicate that additional code is not shown
XME_patternRule
USAGE: $(eval $(call XME_patternRule,ext,$(prerequisites),$(cmdOptions)))
Evaluates to a rule of the form:
$(XMAKE_PROJECT_DIR)/%.ext_out : $(XMAKE_PROJECT_DIR)/%.ext
$(prerequisites)
...
ext-cmd $(cmdOptions) ...
Most XMExtensions use XME_patternRule to create the default pattern rule
for output files.
Any custom pattern rules will take precedence over the default pattern
rule, if several rules could apply to the same target (I.e., if all
prerequisite targets either exist or can be made). This does not mean that
custom pattern rules override default pattern rules: the default rules will
still be used for targets for which the prerequisites of custom pattern
rules do not exist and cannot be made.
XME_dependencyRule
USAGE: $(eval $(call XME_dependencyRule,ext,$(srcfiles),$(prerequisites)))
Evaluates to a rule, without commands, of the form:
myFile1.ext_out myFile2.ext_out ... : $(prerequisites)
Use this rather than XME_patternRule if you only need to add some
prerequisites to a target that will be handled by the default pattern
rule.
XME_explicitRule
USAGE: $(eval $(call
XME_explicitRule,ext,$(srcfile),$(prerequisites),$(cmdOptions)))
Evaluates to a rule of the form:
myFile1.ext_out : $(prerequisites)
...
ext-cmd $(cmdOptions) ...
If a single source file requires special treatment, an explicit rule can be
used to pass custom prerequisites or command options to the
XME_explicitRule macro.
To create an explicit rule with special options for a file 'myFile.ext', do
something like the following:
prerequisites:=# any extra prerequisites, not listed in myFile.ext.mkdo
cmdOptions:=# any special options you need
$(eval $(call
XME_explicitRule,ext,myFile.ext,$(prerequisites),$(cmdOptions)))
XME_staticRule
USAGE: $(eval $(call
XME_staticRule,ext,$(srcfiles),$(prerequisites),$(cmdOptions)))
Evaluates to a rule of the form:
myFile1.ext_out myFile2.ext_out ... : %.ext_out : %.ext $(prerequisites)
...
ext-cmd $(cmdOptions) ...
Static pattern rules are similar to explicit rules in that, unlike pattern
rules, they ONLY apply to the explicitly listed targets of the rule; a
pattern is used to determine prerequisites, not the targets themselves.
Notice that this macro uses the pattern '%.ext_out'; if you need rules with
different patterns, then you can write a custom rule or use XME_staticRule
define statement as a model.
Examples of Rule Creation
Suppose you have a custom pattern rule in a makefile in a subdirectory
which contains a prerequisite file: 'ext.conf'
$(XMAKE_PROJECT_DIR)/%.ext_out : $(XMAKE_PROJECT_DIR)/%.ext
$(CURDIR)/ext.conf
ext-cmd $< ... > $@
Suppose you have a default pattern rule with only the source file as
prerequisite:
$(XMAKE_PROJECT_DIR)/%.ext_out : $(XMAKE_PROJECT_DIR)/%.ext
ext-cmd $< ... > $@
Now, if you build any %.ext file in the directory, $(XMAKE_PROJECT_DIR),
where the file 'ext.conf' does NOT exist, the default pattern rule will be
used, whereas any %.ext file in $(XMAKE_PROJECT_DIR)/dir1 will use the
custom rule.
Final XMake Rules
$(XMAKE_PROJECT_DIR)/XMakefile contains the following final rules, which
are read after all other rules in all included makefiles.
/%:
# prints error message for external targets, not in XM_externalTargets
# or XM_finalTargets
% :
# prints error message for pathless targets without explicit rules
Other Macros
XM_externalTargetsHandler
Pass all prerequisites in your custom rules to this macro which will detect
any external targets and add them to XM_externalTargets:
$(eval $(call XM_externalTargetsHandler,$(prerequisites)))
XM_append
XM_append appends targets to any simply expanded variable, such as
'XM_outfiles', avoiding duplicate items.
Example:
To add targets to XM_outfiles, use:
$(eval $(call XM_append,XM_outfiles,$(targets)))
XM_remove
XM_remove removes items from a list variable
Example:
$(eval $(call XM_remove,XM_outfiles,$(targets)))
XME_outfileMap
Returns the names of the output files for all valid source file names
handled by a given XMExtension, 'ext'; otherwise returns empty
Example:
outfiles:= $(call XME_outfileMap,ext,$(sources))
Special Variables
XM_outfiles
XM_outfiles contains a list of output files corresponding to source files.
These files are built by the default rule, 'xmake', and removed with
'xmake clean'.
Normally all existing source files with corresponding XMExtension enabled
will be auto-detected and added to XM_outfiles. If you need to process
source files that are generated from other sources, and thus, will not be
auto-detected when makefiles are initially read, or if you create custom
rules for targets not handled by XMExtensions, you should add those
targets to XM_outfiles.
XM_externalTargets
XM_externalTargets contains a list of all prerequisite targets, outside the
current project. It is used by the commands of the rule 'recurse' to build
all external targets prior to building any, possibly dependent, local
targets.
If you write custom rules with any external prerequisites, then you must
append the external targets to XM_externalTargets, or call the macro,
XM_externalTargetsHandler, to handle this for you. If you only use the
default rules or use XMake macros for all of your custom rules, or if none
of your prerequisite is external to the current project, then you will not
need to add any targets to this list.
XM_phonyTargets
Phony targets are usually used when targets should always be made; they are
always considered out of date.
Some phony targets are automatically deduced; others will be the targets of
custom rules.
XMakefile defines the rule:
.PHONY: $(XM_phonyTargets)
XM_finalTargets
XM_finalTargets is used to improve performance by creating an empty rule
for targets which are ALWAYS manually created and NEVER dependent on other
files.
Setting XMAKE_FINAL_TARGETS_PATTERN in XMake.conf is the primary interface
to XM_finalTargets.
XMakefile defines:
XM_finalTargets+=$(filter
$(XMAKE_FINAL_TARGETS_PATTERN),$(XM_externalTargets))
$(XM_finalTargets) : ;
Naming Conventions
One of the consequences of a single makefile environment, where many
makefiles share the same name space, is that more care must be taken with
variable naming to avoid collisions and side-effects. In order to
distinguish variables used and defined by XMake, and third party
XMExtensions, from any custom variables that the user may define, we
require some conventions.
Variable Names
XMake Environmental variables
prefix: 'XMAKE_'
+ this is used EXCEPT where an analogous Gnu Make variable exists
+ example: XMAKE_DEBUG, XMAKE_MAKEFILES_SEARCH,
XMAKE_PROJECT_MAKEFILE
Gnu Make analogies:
+ $(XMAKE) analogous to $(MAKE)
- always use $(XMAKE) instead of 'xmake' when invoking sub-make
- do not use $(MAKE) or 'make'
XMake makefile variables
prefix: 'XM_'
+ general usage throughout XMake makefiles
+ example: XM_extensions, XM_dirTree, XM_sources, XM_outfiles
prefix: '_XM_'
+ private use, usually within define statements; avoids collision
with other XMake variables
XMExtensions makefile variables
prefix: 'XME_'
+ require XMExtensions makefiles
+ example: XME_patternRule, XME_staticRule
prefix: 'XME_<XMExtensionName>_'
<XMExtensionName> is the name of an XMExtension
+ implemented/defined by specific XMExtensions makefiles
+ example: XME_c_cmd, XME_c_outfileMap, XME_c_outfileMacro
prefix: '_XME_'
+ private use, usually within define statements; avoids collision
with other XMake variables
Gnu Make variables
All Gnu Make variables work fine with XMake, except for $(MAKE) (see
above).
+ example: $(MAKELEVEL), $(MAKEFLAGS)
Special Cases
$(XMAKE_SHELL_CMD)
+ this is used by XMake to set the value of $(SHELL) in order to
isolate the makefile environment from the user's shell environment. Gnu
Make recommends setting $(SHELL) explicitly in the makefile, XMake
enforces it: XMAKE_SHELL_CMD is assigned a default value of 'bin/sh' in
'XMake.conf', then XMakefile sets:
SHELL:=$(XMAKE_SHELL_CMD)
$(XMAKEFLAGS) is almost analogous to $(MAKEFLAGS), except:
$(XMAKEFLAGS) is a list of XMake-specific options with '-'
prefixes; example: ' -D'
$(MAKEFLAGS) is a list of flags; single-letter options catenated as
a string, without preceding '-'; long options are included, for example:
'rd --no-print-directory'
NOTE:
$(XMAKEFLAGS) ONLY INCLUDES XMake-specific options; all others are
in $(MAKEFLAGS);
$(MAKEFLAGS) behaves exactly the same under XMake as in Gnu Make.
CAVEATS
You should be able to define any variables in your own custom makefiles
without risk of side-effects from current or future versions of XMake,
PROVIDED that you avoid collision with naming conventions discussed above.
Since a custom makefile may be read before and after reading other included
makefiles, a custom makefile must be certain that a variable which may be
set and used in other custom makefiles will not be affected by any other
XMake makefiles.
WRONG:
# XMake includes your makefile: 'myMakefile.mks' which contains the
# assignment:
XM_myVar:=myValue
# XMake includes another XMake makefile which could affect your
# variable:
XM_myVar:=
# XMake includes another one of your makefiles: 'myOtherMakefile.mks'
# which contains:
ifeq( XM_myVar,myValue )
# this won't do what you expected now!
endif
CORRECT: never use XMake names in custom makefiles unless you know what
you're doing!
# XMake includes your makefile: 'myMakefile.mks' which contains the
# assignment:
myVar:=myValue
# XMake includes another XMake makefile which will NEVER affect your
# variable
# XMake includes another one of your makefiles: 'myOtherMakefile.mks'
# which contains:
ifeq( myVar,myValue )
# this will ALWAYS do what you expect
endif
File Names
Generally, all XMake project files should begin with the prefix: 'XMake'
Examples: XMake.conf, XMakefile, XMakefile.mks
This convention makes it easy to distinguish in a directory listing
Exceptions:
A makefile which only sets the value of a single XMake variable should
use the name of that variable as the basename: E.g., 'XM_sources.mkho'
would set XM_sources:= ...
Output file names are determined by XMExtensions, or on a custom basis
Auto-generated makefiles, such as %.xmdo, use the source file basename
XMExtensions: must be unique, no 'dot' in the name
For pattern rules to work correctly in handling source files of the
correct type, the extension name must not include a dot.
For example, if an extension where named 'a.c' then it would be
detected as type 'c' and handled by the C language XMExtension.
Recommended use is '-' or '_', such as: 'phpc', 'xdir'
Targets of Explicit Rules
There are no naming conventions regarding rule targets, other than those
concerning file names. All of the built-in explicit XMake rules are
defined in the files:
$(XMAKE_HOME)/XMakefile.mkr
$(XMAKE_HOME)/config/XMakefile
Duplication of rules causes make to generate an error messages alerting the
user to the problem.
Examples
Some example projects can be found in:
xmake/test/
xmake/examples/
xmake/doc/src/
In order to build any of the above projects, you must first make sure that
the project configuration files are correct for your system then you must
delete all auto-generated makefiles so that they can be rebuilt with paths
on your system. Testing the installation should work without much force:
cd $(XMAKE_HOME)/test
xmakep
xmake
If the above fails, try these commands:
cd $(XMAKE_HOME)/test
xmakep -f
xmake clean.makefiles
xmake -E 'c xdir'
By default, XMake creates output files in the same directory as the
corresponding source files. One of the common needs of C/C++ projects is
to build separate binaries/libraries for specific platforms: output files
need to be compiled with special options or header files for each platform
and should be written to separate platform-specific directories. To
accomplish this, we suggest customizing $XMAKE_PROJECT_DIR/XMakefile.mks.
Some ideas:
+ set makefile variables on the command line to determine what build
rules will be used:
xmake platform=linux
xmake platform=solaris
etc.
+ define rules according the each platform:
ifeq($(platform),linux)
#define rules for building for linux
endif
ifeq($(platform),solaris)
#define rules for building for solaris
endif
+ define a target directory for output files:
ifeq($(platform),linux)
destDir:=$(XMAKE_PROJECT_DIR)/arch/linux
endif
ifeq($(platform),solaris)
destDir:=$(XMAKE_PROJECT_DIR)/arch/solaris
endif
+ create a rule to build for the platform and move the output files to
the target directory:
XM_phonyTargets+=move
build: all
@mv $(XM_outfiles) $(destDir)
+ build the platform-specific output with the following command:
xmake build platform=linux
Debugging
If something goes wrong, try these commands, in order:
xmake clean # removes all output files and makefiles
xmake clean.makefiles # removes only generated makefiles
xmakep # interactively copies new config files, or
xmakep -f # if you don't mind blowing all project config/makefiles away
If you write something like $(error ...) in XMakefile.mks (which is
compiled to XMakefile.mko), 'xmake clean' may be unable to delete the
generated XMakefile.mko before reading it and exiting. To get around this
problem, we can force makefile deletion without reading them, with 'xmake
clean.makefiles'.
Debugging options allow you to see exactly how xmake/make is interpreting
your makefile.
Try these:
xmake -V
xmake -d -D
xmake -n
xmake -p
XMake includes a few built-in rules to give debug output:
xmake debug # generates a list of XMake variables and values
xmake XM.var.varName # echoes the value of variable 'varName'; such as:
xmake XM.var.XM_outfiles # echoes the value of variable 'XM_outfiles'
xmake XM.vars # lists the names of all the XMake variables
xmake XM.deprule./path/to/target # echoes the dependency rule for
/path/to/target in the form:
/path/to/target: prerequisite1 prerequisite2 ...
xmake XM.reqs./path/to/target # echoes the prerequisites for
/path/to/target in the form:
prerequisite1 prerequisite2 ...
Experimental:
xmake XM.deps./path/to/target # lists the targets which are dependent on
/path/to/target