The following sections describe the make-based rule sets provided by abuild.
Rules for compiling C and C++ code are provided by the
ccxx
rules. These rules also include
support for flex, bison, and Sun RPC. It is possible for a
single build item to build multiple targets including any
mixture of static library, shared library, and executable
targets.
A note about flex and bison before we get to the main event: the
flex and bison rules can take advantage of abuild's
codegen-wrapper utility. If you set the
variable FLEX_CACHE
, abuild will cache
generated flex output files and input file checksums making it
possible for your flex code to be used on systems that don't
have flex. The variable BISON_CACHE
serves
the same function for code generated with bison. Abuild's own
build uses this functionality. To use this facility, set
FLEX_CACHE
and/or
BISON_CACHE
to directories relative to our
source directory. Abuild will copy files to or from this
directory during its build. These directories are relative to
your source directory, not your output directory. As such, the
resulting files are likely to be controlled in your version
control system. This is an exception to the ordinary rule of
abuild not creating files outside of the output directory, but
it's an appropriate exception as the intention is to control
these automatically generated files so that they could be
available for users who didn't have flex or bison. For
information about using the codegen-wrapper
utility with your own builds, see Section 22.6, “Caching Generated Files”.
When building C and C++ code, you must define at least one of
TARGETS_lib
or
TARGETS_bin
. These variables contain a list
of library and executable targets respectively. Targets should
be specified without any operating system-specific prefixes or
suffixes. For example, the library target
moo
might generate
libmoo.a
on a UNIX system or
moo.lib
on a Windows system. Likewise, the
executable target quack
might generate
quack
on a UNIX system and
quack.exe
on a Windows system.
For each target target
listed in
TARGETS_lib
, you must define the variable
SRCS_lib_
to contain a list of source files used to build the library.
Likewise, for each binary target in
target
TARGETS_bin
, you must define
SRCS_bin_
.
These variables can contain any mixture of C and C++ files. The
source files listed in these variables are typically located in
the same directory as the target
Abuild.mk
, but
they may also refer to automatically source files that will
actually appear in the output directory.
[32]
There are variables that can be used to control the creation of
shared libraries. For details, see Section 21.1, “Building Shared Libraries”. Files whose names
end with .c
are treated as C code. Files
whose names end with either .cc
or
.cpp
are considered to be C++ code.
Although you can have any mixture of binary and library targets
in a build item, no single source file should be listed in more
than one target. Additionally, abuild will automatically
include any library targets at the beginning of the library list
when linking any binary targets in the build item. All targets
are created directly in the abuild output directory.
In addition to the standard targets, the
ccxx
rules provide a special target
ccxx_debug. This target prints the current
include and library path as well as the list of libraries that
we are linking against. This can be a useful debugging tool for
solving dependency declaration problems.
It is also possible to add additional preprocessor, compiler, or
linker flags globally or on a per-file basis and to specifically
override debug, optimization, or warning flags globally or on a
per-file basis. This is done by setting the values of certain
make variables, some of which may also be set in
Abuild.interface
. Details about these
variables may be obtained by running abuild
rules-help from any C/C++ build item. The following
variables are available:
additional flags passed to the preprocessor, C compiler, and C++ compiler (but not the linker)
additional flags passed to the C compiler, C++ compiler, and linker
additional flags passed to the C++ compiler and linker
additional flags passed to the linker—usually not used for libraries
debug flags passed to the processor, compilers, and linker
optimization flags passed to the processor, compilers, and linker
warning flags passed to the processor, compilers, and linker
Note that the XCPPFLAGS
,
XCFLAGS
, XCXXFLAGS
, and
XLINKFLAGS
variables may be set in
Abuild.interface
as well. Therefore,
although you assign to them normally with =
in Abuild.interface
, when assigning to them
in Abuild.mk
, it is generally better to
append to these variables (using +=
) rather
than to set them outright. Also, keep in mind that flags are
often compiler-specific. It may often make sense to set certain
flags conditionally upon the value of the
$(ABUILD_PLATFORM_COMPILER)
variable or other
platform field variables. This can be done using regular
GNU Make conditional syntax.
Each of the above variables also has a file-specific version.
For the X*FLAGS
variables, the file-specific
values are added to the general values. For example, setting
XCPPFLAGS_File.cc
will cause the value of
that variable to be added to the preprocessor, C compiler and
C++ compiler invocations for File.cc
.
File-specific versions of XCPPFLAGS
,
XCFLAGS
, and XCXXFLAGS
are
used only for compilation and, if appropriate, preprocessing of
those specific files. They are not used at link time.
The file-specific versions of DFLAGS
,
OFLAGS
, and WFLAGS
override the default values rather than
supplementing them. This makes it possible to completely change
debugging flags, optimization flags, or warning flags for
specific source files. For example, if
Hardware.cc
absolutely cannot be compiled
with any optimization, you could set
OFLAGS_Hardware.cc
to the empty string to
suppress optimization on that file regardless of the value of
OFLAGS. Similarly, if autogen.c
were an
automatically generated file with lots of warnings, you could
explicitly set WFLAGS_autogen.c
to the empty
string or to a flag that suppresses warnings. This would
suppress warnings for that file without affecting other files.
If you wish to append to the default flags instead of replacing
them, include the regular variable name in the value, as in
WFLAGS_File.cc := $(WFLAGS) -Wextra
or even
WFLAGS_File.cc := $(filter-out
-Wall,$(WFLAGS))
.
The ccxx
rules provide a mechanism for you
to generate preprocessed output for any C or C++ file. For
,
file
.c
, or
file
.cc
, run
abuild file
.cppfile
.i.
This will generate
in the
output directory. Its contents will be the output of running
the preprocessor over the specified source file with all the
same flags that would be used during actual compilation.
[33]
file
.i
When invoking abuild to build C or C++ executables or shared
libraries, it is possible to set the make variable
LINKWRAPPER
to the name of a program that
should wrap the link command. This makes it possible to use
programs such as Purify or
Quantify that wrap the link step in
this fashion.
Ordinarily, abuild uses a C++ compiler or linker to link all
executables and shared libraries. If you are writing straight C
code that doesn't make any calls to C++ functions including
those in external libraries and you want to link your program as
a C program to avoid runtime dependencies on the C++ standard
libraries, set the variable LINK_AS_C
to some
non-empty value in your Abuild.mk
. This
applies to all shared libraries and executables in the build
item.
Most of the time, abuild manages all the dependencies of the
source and object files (as opposed to inter-build-item
dependencies) automatically, but there are some rare instances
in which you may have to create such dependencies on your own,
such as when an object file depends on an automatically generate
header file that is generated in the same build item. For an
example of this, see Section 22.5, “Dependency on a Make Variable”. To make it possible
to express such dependencies in a portable fashion, the
ccxx
rules provide the variables
LOBJ
and OBJ
which are set
to the object file suffixes for library object files and
non-library object files respectively. For example, if you have
a source file called File.cc
that is part
of a library, the name of the object file will be
File.
, and the
file will be created inside the abuild output directory. If
$(LOBJ)
File.cc
were part of an executable instead,
the object file would be
File.
instead.
[34]
$(OBJ)
As is the case for any rule set, you can run abuild --help rules rule:ccxx for additional information. This help text is also included in Section E.10, “abuild --help rules rule:ccxx”.
There is a lot more to abuild's C and C++ generation than is
discussed here. For a complete understanding of how it works,
you are encouraged to read
rules/object-code/ccxx.mk
in the abuild
distribution (Appendix I, The ccxx.mk
File). There you will
find copious comments and a lot of pretty hairy GNU
Make code.
Abuild includes built-in support for Microsoft's Visual C++ compiler on Windows. There are three MSVC-specific variables that can be set:
MSVC_RUNTIME_FLAGS
: set to
/MD
by default, which causes the
executable to dependent on Microsoft runtime DLLs. By
setting this to /MT
, it is possible to
create executables that statically link with the runtime
environment. A trailing
“d
” is automatically
appended when building debugging executables or
libraries.
MSVC_MANAGEMENT_FLAGS
: set to
/EHsc
by default, which enables
synchronous exception handling and assumes
“C” functions do not throw exceptions. By
setting this to /clr
, it is possible to
build programs that work with the .NET framework.
MSVC_GLOBAL_FLAGS
: contains flags
that are passed globally to all compilation commands.
Users will seldom have to modify this. For details, see
comments in
make/toolchains/msvc.mk
.
The autoconf
rules provide rules for
including autoconf fragments for a build item.
[35]
Rather than having a monolithic autoconf-based component in a
source tree, it is recommended that individual build items use
autoconf for only those things they need. This reduces the
likelihood that something may fail to build due to lack of
support for something it doesn't need (but that is checked for
by a monolithic autoconf component). The only caveat to doing
this is that, if you use autoconf-generated header files, you
may find that the same symbols are defined in more than one
place. You will have to experiment and come up with appropriate
standards for your project.
The autoconf
rules don't supply any special
targets. A reasonably complete example of using autoconf
follows in Section 18.3, “Autoconf Example”. You may also
run abuild --help rules rule:autoconf for
full information on using these rules. This help text is also
included in Section E.9, “abuild --help rules rule:autoconf”.
Some of the tools run by autoconf
create
temporary files that may cause problems when running parallel
builds. It is therefore recommended that you place
attributes: serial in the
Abuild.conf
file of build items that use
autoconf rules.
Autoconf properly honors your C/C++ toolchain and runs
configure
with the proper C/C++ compilation
environment defined. The usual approach for autoconf-based
build items is that, if make variables need to be defined based
on the results of running configure
,
configure.ac
generates a file called
autoconf.interface
which is specified as an
after-build
file in
Abuild.interface
. This means that the
autoconf-based build item itself may not include code that is
conditional upon the results of running autoconf. It is okay,
however, for build items that depend on an autoconf-based build
item to include conditional code in their
Abuild.interface
and
Abuild.mk
files based on variables defined
in its autoconf.interface
should this be
required.
In some rare cases, it may be desirable to create an
Abuild.mk
file that does nothing. One
reason for doing this would be if you had a library that
contained some code that should only exist on certain platforms.
You might want to create an Abuild.mk
file
that was conditional upon some value of the
ABUILD_PLATFORM_OS
variable, for example.
Since abuild requires that you set at least one of
RULES
or LOCAL_RULES
, you
can set the RULES
variable to the value
empty
. Abuild will still attempt to
build the item in this case, but the build will not do anything.
The empty
rule set is available for build
items of any target type.
[32]
For example, if you have a local rule that generates
autogen.cc
in the output directory, you
can simply list autogen.cc
in one of your
SRCS
variables, and abuild will find it
anyway. This is because abuild's make code uses
GNU Make's
vpath
feature. We provide an example of
this construct in Section 22.2, “Code Generator Example for Make”.
[33]
The .i
suffix is a traditional UNIX
suffix for preprocessed C code and was created as an
intermediate file by some compilers. GCC recognizes this as
preprocessed C code and also recognizes
.ii
as a suffix for preprocessed C++
code. When abuild is given a .i
file
as a suffix, its make rules use a pattern-based rule to run
the preprocessor over the file, it never uses the resulting
files as input to the compiler. Abuild uses the original
suffix of the file (.c
,
.cc
, or .cpp
) to
determine whether the file is a C or C++ source file and does
not therefore need to distinguish between
.i
and .ii
.
[34]
LOBJ
and OBJ
usually
have the same value as each other, and the value is usually
“o
” on UNIX systems and
“obj
” on Windows systems.
However, there are some circumstances under which either of
these conditions may not be true, so it is best to use
LOBJ
or OBJ
explicitly
as required.