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' # This CUSTOM pattern rule is defined in # $(XMAKE_PROJECT_DIR)/dir1/XMakefile.mks # This file is read PRIOR to reading # $XMAKE_HOME/config/XMExtensions/ext.mkr # This rule is actually created by the evaluating the statement: # $(eval $(call XME_patternRule,ext,$(CURDIR)/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: # This DEFAULT pattern rule is defined in # $XMAKE_HOME/config/XMExtensions/ext.mkr: $(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