Chapter 8. Extending a Module's Makefiles

Table of Contents

Makefile Conventions
File Names
Variable Assignments
Variable References
The Glue Makefile
Basic Structure
Auxiliary Files
Extension
Individual Component Makefiles
Basic Structure
Extension
Specific Modules
Multiple Libraries in VR Juggler
Java in Tweek
IDL in Tweek

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.

Makefile Conventions

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.

File Names

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.

Variable Assignments

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.

Variable References

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:

  1. 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.

  2. 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.

  3. 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”).