Table of Contents
In this chapter, we explain how to extend a given module's makefiles. In most cases, all the modules in the Juggler Project use the same basic structure for their makefiles. Those that do not follow the existing conventions should be updated to ease maintenance issues. This chapter begins with a discussion of the basic ideas used in writing makefiles for a Juggler module. We then move on to the top-level glue makefile. Next, we discuss the individual component makefiles that typically perform the actual compiling steps. This chapter concludes with an examination of some specific modules to understand how different special cases are handled.
Due to the size of the Juggler Project code base, following conventions in all makefiles is very important. The uniformity makes it easier for anyone to maintain the various module build systems. If a given module does not follow the conventions, someone who does not have direct knowledge of that makefile may find it hard to fix problems that may occur. Furthermore, extensions to a given module's build system are more difficult if the same basic ideas cannot be shared across all modules. The following subsections cover most of the conventions currently in use.
Due to Autoconf rules, all files that are to be generated by a
configure script must have the suffix .in.
Because of that, this is not so much a convention as it is a
requirement. However, there are other files used in the build
system, and their names are important.
Makefile stubs that make variable assignments have the string
“defs” somewhere in their name. In general, such
makefile stubs do not define any targets, though this may not always
be the case. Examples are make.defs.mk,
common.defs.mk (a Doozer++ file), and test.defs.mk.
In some cases, one makefile may include targets from another.
The idea here is that the high-level tasks are defined in
Makefile.in, and all the grunt work is done in
the included file(s). Providing this separation can help casual
viewers to understand the high-level tasks without worrying about
all the behind-the-scenes details. The included files have the
string “inc” in their name. The most common example
seen in modules is Makefile.inc.in, though
there could be files such as Makefile.inc0.in,
Makefile.inc1.in, and so on. The use of
numbering allows multiple files to be used for separating the
tasks.
It is important to note that all of the makefiles named in the
above examples begin with a capital letter. While it is often useful
to include multiple makefiles in a single directory (of the Autoconf
.in template variety and otherwise), there must
never be a situation where a directory could contain the files
Makefile and makefile.
Win32 file systems cannot distinguish between the two, and only bad
things can occur as a result.
Recently, there has been a shift in the style used to perform variable assignments. The new style is based on the formatting used in all FreeBSD system and ports makefiles. This style was adopted to make formatting makefiles easier and cleaner. It is shown below:
VAR= value OPT_VAR?= default-setting LIST_VAR= item1 \ item2 \ item3 LIST_VAR+= item4
The key is the whitespace around the assignment operators. On the left-hand side, there is no whitespace; on the right-hand side, there are one or more tabs. When using multiple lines, tabs are used for indentation. Spaces are never used. Because tabs must be used in makefile targets, it is convenient (with most editors) to use tabs for all formatting characters.
This convention is relatively new, and its adoption is not yet complete. Files that have not been updated should be reformatted when they are encountered.
Most implementations of make(1) allow the use of two variable reference styles. These are shown below:
VAR= value
target:
echo ${VAR}
echo $(VAR)In the first line of the target called
'target', curly braces are used. This is the same
syntax used to clarify variable interpolations in most shell
scripting languages. The second line uses parentheses.
In the Juggler Project, we prefer the use of parentheses over curly braces for the following reasons:
It distinguishes make variable references from shell variable references. Since shell scripting can be used to a limited degree in makefiles, this can be important.
Some implementations of make(1) only support this style. While the majority of the build system is based on GNU make, some makefiles are designed to work with any implementation. Having some makefiles that use one style and others that make use of a different style can be confusing. By choosing the style that is supported by all implementations, we can never go wrong.
The look of the parentheses is cleaner than the curly braces. This, of course, is purely aesthetic, so it does not make the best case during style discussions (read, “arguments”).