Code conventions for the build system
Magnus Ihse Bursie
magnus.ihse.bursie at oracle.com
Tue Oct 8 07:40:28 UTC 2013
Whitespace and indentation in makefiles is a more problematic area than
for other languages. Even while most of the time whitespace is not
significant, sometimes is is. This might be considered a design flaw in
make, but that's not something we can do anything about. In particular,
initial tabs signify make rule recipes, and in make string manipulation,
sometimes spaces matter.
Probably partly due to this, there is little editor/IDE/tooling support
for automatically formatting makefiles. This in turns makes keeping sane
whitespace usage and indentation a "manual" task. When we started
writing the new build system, we didn't set up a set of coding
conventions to regulate whitespace and indentation (which we regret
now). So the existing code varies wildly in style and indentation. All
too often, proper indentation is completely missing, making it hard to
read and understand the code.
So, we created a set of rules for indention and whitespace usage. We
tried to stay close to the Java code conventions, but Makefiles are not
Java source code. We have then started to transform the code base
according to these conventions. A webrev will shortly follow, with the
whitespace changes resulting from this work.
But first, let us present the set of rules.
Indentation:
1) The basic level of indentation is two spaces. Use this for
"logical" indentation (if blocks, function definitions etc).
2) If a line must be broken, use four spaces for indentation.
3) Recipes in makefile rules must start with a tab (per definition).
4) If a single tab (interpreted as 8 spaces wide) is not enough to
put the recipe clearly indented (meaning at least 4 spaces difference)
from the code around it, use additional tabs.
5) Non-shell commands in a recipe (e.g. comments and make directives
like ifdef) must not start with tab, but should instead be indented to
the same level as the surrounding shell commands using spaces (with tabs
interpreted as 8 spaces wide).
6) Additional indentation in recipes should be done using space after
the tab(s), as in normal makefile lines.
7) Partial recipes (macro definitions that are supposed to be inlined
into a recipe) should be treaded like a recipe and start with tabs as well.
Whitespace, required:
8) Trailing whitespaces is never allowed.
9) Do not use tabs, only spaces (except for in recipes, as stated by
rule 3-7).
Whitespace, recommended:
10) There should be no whitespace between the list of targets and the
: at the start of a rule.
11) There should be an empty line before and after each rule.
12) Avoid empty lines inside the recipe.
13) Broken lines should end with a backslash, and a single space
before the backslash (" \").
14) A single space should separate a comma from the next argument in a
function call.
15) A single space should be used before and after assignment
operators (e.g. :=, =, +=).
These recommendations are not always possible to follow, since
whitespace might have semantic meaning. If an exception from these
recommendations is required by make, it should ideally be pointed out by
a comment. Especially spacing around commas might be sensitive, so beware.
Style recommentations:
16) Use := (direct assignment) instead of = (recursive macro
definition), unless you really need the recursive definition.
17) In long lists, do not let the first and last element have
different form. For instance, start the first element on a new line
rather than after a :=, and end the list with an empty comment (#) to be
able to have a trailing backslash on the last line.
18) Avoid padding internally in a line with spaces to try to align
some feature into columns with surrounding lines.
19) For multiple commands run by the shell, separated by "&& \" or
similar, all commands should start at the same indention level.
Rationales (to some of the rules):
1-2) This is in contrast to Java, which has twice as long indentations
(4 space logical indentation, 8 spaces for wrapped lines). But since all
indentation needs to be done basically by repeatedly pressing space, and
since wrapped lines are fairly common, we felt it important to keep the
indentation level short. Otherwise a wrapped line two levels in would
needed 16 presses on the space bar.
9-12) Tabs are required in recipes, but for the sake of sanity, this
is the only accepted use of tabs. The makefile syntax does not make it
easy to spot rules in complex makefiles, and everything that helps in
distinguishing rules from non-rules is needed.
16) Recursive macro definition (= instead of :=) slows down make and
can have surprising effects. Typically this is not what you mean.
17-18) A very typical use case of makefile changes is to add things
(files, compiler directives, etc) to a list. These rules help making
such changes easy and context free. Otherwise the developer must modify
several lines that are unrelated to the actual change. Chances are that
a nicely padded grid will not be updated and start deteriorating from
the very first change.
19) Separating multiple shell commands (e.g. after a shell "if"
command) should not be considered a broken line which needs to be
indenting, but a way to specify a list of commands on the same
indentation levels. This is after all the intent; the && is merely a
roundabout device to get this to work properly in makefiles.
/Magnus
More information about the build-dev
mailing list