The code that goes into a Rules.mk or
plugin.mk file is regular GNU
Make code. There are certain practices that you
should follow when writing GNU Make
code for use within abuild. A good way to learn about writing
rules for abuild is to study existing rules. Here we will
briefly list some things that rules authors must keep in mind:
If you are about to write some rules, consider carefully
whether they should be local rules for a specific build item
(accessed with the LOCAL_RULES variable),
exported rules provided by a build item (accessed with the
BUILD_ITEM_RULES variable), or whether they
should be made globally accessible by being included in a
plugin. The latter case will be rare and should only be used
for functionality that really should work “out of the
box” in a particular build tree. Note also that rules
that are part of abuild or are declared in a plugin are
specific to a target type. This restriction is not present
for local rules and rules provided by build-items. (The reason that rules accessible through the
RULES variable are segregated by target
type is to support loading of base rules
that abuild loads before loading the actual rules. This is
the mechanism used to make the variable
CCXX_TOOLCHAIN available to all object-code
rules.) Plugin rules must appear in the
rules/
directory within a plugin, where
target-typetarget-type is the target type to
which the rules belong. Build item rules appear in
Rules.mk. Local rules can appear
anywhere, and the location must be named in the
LOCAL_RULES variable in
Abuild.mk. It is also possible to create
global make code that is loaded from a plugin directory:
abuild will load any plugin.mk files
defined in plugins in the order in which the plugins are
declared.
Abuild invokes make with the --warn-undefined-variables flag. This means that your users will see warnings if you assume that an undefined variable has the empty string as a value. If it is your intention to have an undefined variable default to the empty string, then you should include
VARIABLE ?=
in your rules, where VARIABLE is the name
of the variable you are setting. You can always provide
default values for variables in this fashion if the intention
is to allow users to override those values in their own
Abuild.mk files.
Note that Abuild.mk files are included
before rules files. This is necessary because the
Abuild.mk file contains information about
which rules are to be included. If your rules are providing
values that users will use in their
Abuild.mk files, you should recognize
that your users will need to avoid referencing those variables
in assignment statements that use :=
instead of = since the
Rules.mk variables will not yet be
defined when Abuild.mk is read.
You should always provide a rules-help target
in your rules files. For an example and discussion of this, see
Section 18.2, “Code Generator Example”. If your rules use
values that should be provided in
Abuild.interface files, then you should
also provide a interface-help target.
If your rules require certain variables to be set, check for
those variables and given an error if they are not defined.
For an example of this, see Section 18.2, “Code Generator Example”. The
ccxx.mk rules in the abuild sources
(Appendix D, The ccxx.mk File) provide a somewhat more
elaborate example of doing this since they actually generate
dynamically in terms of other values the list of variables
that should be defined.
All rules should provide an all:: target. Note that abuild only invokes clean targets when run manually from inside an output directory, so providing a clean target is optional. Still, providing clean targets is good practice and can also aid in debugging. Although you can add additional targets in your rules files, think carefully before doing so. Having too many custom targets will make a source tree hard to build and maintain. If you are adding functionality that should be done as part of every build, consider making it part of the all:: target.
Sometimes it may be useful to provide debugging targets for your
users that provide some information about the state as your
rules see it. The ccxx.mk rules provide a
ccxx_debug target for this purpose.
Always remember that any targets you define in your rules files
are run from the output subdirectory. The variable
$(SRCDIR) points to the directory that
contains the actual Abuild.mk file and
therefore presumably the source files. Abuild sets the
VPATH variable to this as well, but you may
have to explicitly run your actions with arguments that point
back to the source directory (e.g., -I
$(SRCDIR)).
In order to have your rules behave properly with the
--verbose and --silent
flags, you should avoid putting
@ in front of commands that the user should
see in verbose mode, and you should have all your rules print
short, simple descriptive messages about what they are doing.
These rules should be printed using
@$(PRINT). The PRINT
variable is usually set to echo, but it is
set to @: when abuild is running in
silent mode. Note that we put an @ sign at
the beginning of the @$(PRINT) command so
that the user will not see the echo command itself being
echoed when they are running in verbose mode.
There are some convenience functions provided by abuild's
GNU Make code. The best way to learn is to read existing
rules. If you are going to be writing a lot of
make code for abuild, it will be
in your interest to familiarize yourself with the code in
make/global.mk in the abuild
distribution.