Code conventions for the build system

Salter, Thomas A Thomas.Salter at unisys.com
Tue Oct 8 12:08:02 UTC 2013


Was there any thought given to using this GNU Make feature to get rid of significant tab characters, or is it not even possible in all the supported build environments?  Some of the legacy systems I deal with don't handle tab characters well.

From: http://www.gnu.org/software/make/manual/make.html#Special-Variables

.RECIPEPREFIX
The first character of the value of this variable is used as the character make assumes is introducing a recipe line. If the variable is empty (as it is by default) that character is the standard tab character. For example, this is a valid makefile: 
          .RECIPEPREFIX = >
          all:
          > @echo Hello, world

The value of .RECIPEPREFIX can be changed multiple times; once set it stays in effect for all rules parsed until it is modified. 


Tom Salter
Unisys

------------------------------
Date: Tue, 08 Oct 2013 09:40:28 +0200
From: Magnus Ihse Bursie <magnus.ihse.bursie at oracle.com>
Subject: Code conventions for the build system
To: build-dev <build-dev at openjdk.java.net>
Message-ID: <5253B6EC.9020804 at oracle.com>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed

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