Michael Henry's home pagehttps://drmikehenry.com/2018-06-08T00:00:00-04:00GNU Make line continuations2018-06-08T00:00:00-04:002018-06-08T00:00:00-04:00Michael Henrytag:drmikehenry.com,2018-06-08:/gnu-make-line-continuations/<p>It can be difficult to split lines in GNU Makefiles for better readability
without changing their meaning; but there are several ways to work around the
line-continuation rules.</p>
<div class="section" id="line-continuation-rules-for-makefiles">
<h2>Line continuation rules for Makefiles</h2>
<p>Most programming languages have a facility for breaking up long lines. For
example, in the C language …</p></div><p>It can be difficult to split lines in GNU Makefiles for better readability
without changing their meaning; but there are several ways to work around the
line-continuation rules.</p>
<div class="section" id="line-continuation-rules-for-makefiles">
<h2>Line continuation rules for Makefiles</h2>
<p>Most programming languages have a facility for breaking up long lines. For
example, in the C language a long line may be split by placing a
backslash-newline combination in the middle. Consider this line:</p>
<div class="highlight"><pre><span></span><span class="n">printf</span><span class="p">(</span><span class="s">"This is a long line that can be split up</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
</pre></div>
<p>It can be split into two lines anywhere the programmer desires, e.g.:</p>
<div class="highlight"><pre><span></span><span class="n">printf</span><span class="p">(</span><span class="s">"This is a long line that \</span>
<span class="s">can be split up</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
</pre></div>
<p>It can even be split within a word:</p>
<div class="highlight"><pre><span></span><span class="n">printf</span><span class="p">(</span><span class="s">"This is a long line that can be sp\</span>
<span class="s">lit up</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
</pre></div>
<p>This works nicely because the C pre-processor simply deletes any
backslash-newline pairs.</p>
<p>Makefiles have a similar facility, but unlike with C, a backslash-newline
combination is not simply deleted; instead, the backslash-newline pair and any
surrounding whitespace <a class="footnote-reference" href="#continuation-rules" id="id1">[1]</a> are together replaced with a
single space character. So in a Makefile, the following three assignments to
<tt class="docutils literal">x</tt> are the same:</p>
<div class="highlight"><pre><span></span><span class="nv">x</span> <span class="o">:=</span> This is a long line that can be split up
<span class="nv">x</span> <span class="o">:=</span> This is a long line<span class="se">\</span>
<span class="err">that</span> <span class="err">can</span> <span class="err">be</span> <span class="err">split</span> <span class="err">up</span>
<span class="nv">x</span> <span class="o">:=</span> This is a long line <span class="se">\</span>
that can be split up
</pre></div>
<p>Splitting in this way works without changing the meaning as long as the line is
split where there is already a single space; but inserting a backslash-newline
elsewhere has the deeply unfortunate consequence of injecting a space that often
changes the meaning of the line, e.g.:</p>
<div class="highlight"><pre><span></span><span class="c"># The meaning has been changed:</span>
<span class="nv">x</span> <span class="o">:=</span> This is a long line that can be sp<span class="se">\</span>
<span class="err">lit</span> <span class="err">up</span>
</pre></div>
<p>The above is <em>not</em> the same as previous lines; it is the same as the below line
(note the extra space inserted into <tt class="docutils literal">sp lit</tt>):</p>
<div class="highlight"><pre><span></span><span class="c"># Extra space was injected here -------v</span>
<span class="nv">x</span> <span class="o">:=</span> This is a long line that can be sp lit up
</pre></div>
<p>Consider this example simplified from a StackOverflow question. The questioner
wanted to construct the recursively defined variable <tt class="docutils literal">CP</tt> to hold a Java
classpath built as a colon-separated string of paths:</p>
<div class="highlight"><pre><span></span><span class="nv">CP</span> <span class="o">=</span> <span class="si">${</span><span class="nv">ROOT</span><span class="si">}</span>/lib1.jar:<span class="si">${</span><span class="nv">ROOT</span><span class="si">}</span>/lib2.jar:<span class="si">${</span><span class="nv">ROOT</span><span class="si">}</span>/lib3.jar
</pre></div>
<p>But because the paths were so long, he wanted to split up each path component
onto its own line as follows:</p>
<div class="highlight"><pre><span></span><span class="c"># This doesn't work:</span>
<span class="nv">CP</span> <span class="o">=</span> <span class="se">\</span>
<span class="si">${</span><span class="nv">ROOT</span><span class="si">}</span>/lib1.jar:<span class="se">\</span>
<span class="si">${</span><span class="nv">ROOT</span><span class="si">}</span>/lib2.jar:<span class="se">\</span>
<span class="err">${ROOT}/lib3.jar</span>
</pre></div>
<p>Unfortunately, his attempt fails because of the injected spaces; it is
equivalent to:</p>
<div class="highlight"><pre><span></span><span class="c"># Injected spaces ----v-----------------v</span>
<span class="nv">CP</span> <span class="o">=</span> <span class="si">${</span><span class="nv">ROOT</span><span class="si">}</span>/lib1.jar: <span class="si">${</span><span class="nv">ROOT</span><span class="si">}</span>/lib2.jar: <span class="si">${</span><span class="nv">ROOT</span><span class="si">}</span>/lib3.jar
</pre></div>
<p>This problem occurs frequently in user-defined functions as well, where in
addition to keeping down the line length, it's often desirable to split lines at
logical boundaries to aid in readability. Consider the <tt class="docutils literal">resubst</tt> function
below, which performs repeated calls to <tt class="docutils literal">$(subst)</tt> until nothing more changes:</p>
<div class="highlight"><pre><span></span><span class="c"># Replace $1 with $2 in $3 until no more changes are made.</span>
<span class="nv">resubst</span> <span class="o">=</span> <span class="k">$(if</span> <span class="k">$(</span>findstring <span class="nv">$1</span>,<span class="nv">$3</span><span class="k">)</span>,<span class="k">$(</span>call <span class="nv">$0</span>,<span class="nv">$1</span>,<span class="nv">$2</span>,<span class="k">$(</span>subst <span class="nv">$1</span>,<span class="nv">$2</span>,<span class="nv">$3</span><span class="k">))</span>,<span class="nv">$3</span><span class="k">)</span>
</pre></div>
<p>Even though it fits on a single line, it would be clearer if it could be
formatted to show that the <tt class="docutils literal">$(if)</tt> is choosing between the result of the
recursive <tt class="docutils literal">$(call <span class="pre">$0,...)</span></tt> and the input, <tt class="docutils literal">$3</tt>:</p>
<div class="highlight"><pre><span></span><span class="c"># This doesn't work; spaces get injected.</span>
<span class="nv">resubst</span> <span class="o">=</span> <span class="se">\</span>
<span class="k">$(if</span> <span class="k">$(</span>findstring <span class="nv">$1</span>,<span class="nv">$3</span><span class="k">)</span>,<span class="se">\</span>
<span class="k">$(</span>call <span class="nv">$0</span>,<span class="se">\</span>
<span class="nv">$1</span>,<span class="se">\</span>
<span class="nv">$2</span>,<span class="se">\</span>
<span class="k">$(</span>subst <span class="nv">$1</span>,<span class="nv">$2</span>,<span class="nv">$3</span><span class="k">))</span>,<span class="se">\</span>
<span class="nv">$3</span><span class="o">)</span>
</pre></div>
</div>
<div class="section" id="breaking-lines-without-breaking-anything-else">
<h2>Breaking lines without breaking anything else</h2>
<p>Sometimes Make's line-continuation rules cause programmers to despair of
eliminating those pernicious injected spaces, so they simply avoid breaking
lines entirely. They choose instead to create impenetrable one-liners with no
logical formatting to aid in understanding, allowing their logic to either
disappear far off-screen beyond their editor's right-hand margin or to be
wrapped randomly by their text editor into an unreadable mess spanning across
many screen lines. This is understandable, as Make doesn't initially appear to
offer any support for breaking lines at sensible places; however, there are
several techniques shown below for dealing with line continuations without
resorting to inscrutable one-liners.</p>
<div class="section" id="break-lines-where-spaces-don-t-matter">
<h3>Break lines where spaces don't matter</h3>
<p>Sometimes the easiest solution is to break the line where spaces don't matter.
The most natural case occurs for whitespace-separated lists, e.g.:</p>
<div class="highlight"><pre><span></span><span class="nv">SRCS</span> <span class="o">:=</span> <span class="se">\</span>
file1.c <span class="se">\</span>
file2.c <span class="se">\</span>
file3.c
</pre></div>
<p>This is the original use case motivating the rules for line splitting, and with
GNU Make's line-continuation rules it is equivalent to:</p>
<div class="highlight"><pre><span></span><span class="nv">SRCS</span> <span class="o">:=</span> file1.c file2.c file3.c
</pre></div>
<p>It's also usable where a list is being passed to a function, because adding
spaces to the start or end of a list doesn't change the semantics. Consider
this example:</p>
<div class="highlight"><pre><span></span><span class="nv">OBJS</span> <span class="o">:=</span> <span class="k">$(</span>addprefix obj/, <span class="se">\</span>
<span class="k">$(</span>SRCS:.c<span class="o">=</span>.o<span class="k">)</span><span class="o">)</span>
</pre></div>
<p>This is equivalent to:</p>
<div class="highlight"><pre><span></span><span class="nv">OBJS</span> <span class="o">:=</span> <span class="k">$(</span>addprefix obj/, <span class="k">$(</span>SRCS:.c<span class="o">=</span>.o<span class="k">))</span>
</pre></div>
<p>The extra space injected by the backslash-newline-indentation at the start of
the second argument to <tt class="docutils literal">$(addprefix)</tt> doesn't hurt anything, because the
<tt class="docutils literal">$(addprefix)</tt> function treats that argument as a whitespace-delimited list
where extraneous whitespace is ignored.</p>
<p>Because Make removes spaces after a function name, splitting a line there
doesn't change the meaning. This is usually better than making an overly long
one-liner, though readability can suffer compared to splitting the line at more
ideal locations. Consider for example the function <tt class="docutils literal">toMacro</tt> that converts
filenames into C macros by replacing punctuation characters <tt class="docutils literal">.</tt>, <tt class="docutils literal">-</tt>, and
<tt class="docutils literal">/</tt> with underscores:</p>
<div class="highlight"><pre><span></span><span class="nv">toMacro</span> <span class="o">=</span> <span class="se">\</span>
<span class="k">$(</span>subst <span class="se">\</span>
-,_,<span class="k">$(</span>subst <span class="se">\</span>
.,_,<span class="k">$(</span>subst <span class="se">\</span>
/,_,<span class="nv">$1</span><span class="o">)))</span>
</pre></div>
<p>This is equivalent to the below one-liner, where the line continuations do no
harm because each is replaced with a single space where one is required anyway:</p>
<div class="highlight"><pre><span></span><span class="nv">toMacro</span> <span class="o">=</span> <span class="k">$(</span>subst -,_,<span class="k">$(</span>subst .,_,<span class="k">$(</span>subst /,_,<span class="nv">$1</span><span class="k">)))</span>
</pre></div>
</div>
<div class="section" id="strip-the-return-value">
<h3>Strip the return value</h3>
<p>Sometimes wrapping a call to <tt class="docutils literal">$(strip)</tt> around a function's return value can
remove all of the injected spaces caused by line continuations. Consider, for
example, the below loop to display filenames using <tt class="docutils literal">$(info)</tt>:</p>
<div class="highlight"><pre><span></span><span class="c"># This results in a bunch of spaces (from $(foreach) and line continuation):</span>
<span class="k">$(</span><span class="nv">foreach</span> <span class="nv">f</span>,\
<span class="k">$(</span><span class="nv">SRCS</span><span class="k">)</span>,\
<span class="k">$(</span><span class="nv">info</span> <span class="k">$(</span><span class="nv">f</span><span class="k">)))</span><span class="err">)</span>
</pre></div>
<p>Because the <tt class="docutils literal">$(info)</tt> function has an empty return value, the overall result
of the <tt class="docutils literal">$(foreach)</tt> loop consists solely of undesired spaces. The
<tt class="docutils literal">$(strip)</tt> function removes leading and trailing whitespace, as well as
normalizing runs of word-separating whitespace into individual space characters.
When presented with nothing but whitespace, it strips the result into the empty
string:</p>
<div class="highlight"><pre><span></span><span class="k">$(</span><span class="nv">strip</span> \
<span class="k">$(</span><span class="nv">foreach</span> <span class="nv">f</span>,\
<span class="k">$(</span><span class="nv">SRCS</span><span class="k">)</span>,\
<span class="k">$(</span><span class="nv">info</span> <span class="k">$(</span><span class="nv">f</span><span class="k">))))</span>
</pre></div>
</div>
<div class="section" id="strip-individual-line-continuations">
<h3>Strip individual line continuations</h3>
<p>Since <tt class="docutils literal">$(strip)</tt> removes whitespace, it can be used in a targeted way to
individually remove each space injected by line continuations. Consider again
the <tt class="docutils literal">toMacro</tt> function above:</p>
<div class="highlight"><pre><span></span><span class="nv">toMacro</span> <span class="o">=</span> <span class="se">\</span>
<span class="k">$(</span>subst <span class="se">\</span>
-,_,<span class="k">$(</span>subst <span class="se">\</span>
.,_,<span class="k">$(</span>subst <span class="se">\</span>
/,_,<span class="nv">$1</span><span class="o">)))</span>
</pre></div>
<p>This is more readable when formatted as below, but the line continuations inject
damaging spaces:</p>
<div class="highlight"><pre><span></span><span class="c"># Injected spaces damage the meaning:</span>
<span class="nv">toMacro</span> <span class="o">=</span> <span class="se">\</span>
<span class="k">$(</span>subst -,_,<span class="se">\</span>
<span class="k">$(</span>subst .,_,<span class="se">\</span>
<span class="k">$(</span>subst /,_,<span class="nv">$1</span><span class="k">)</span><span class="o">))</span>
</pre></div>
<p>If we individually surround each sequence of backslash-newline-indentation with
a call to the <tt class="docutils literal">strip</tt> function, we can remove the injected spaces
individually. To make the purpose of these calls stand out, I prefer using the
equivalent syntax <tt class="docutils literal">${strip}</tt> instead of <tt class="docutils literal">$(strip)</tt>:</p>
<div class="highlight"><pre><span></span><span class="nv">toMacro</span> <span class="o">=</span> <span class="si">${</span><span class="nv">strip</span><span class="p"> </span><span class="se">\</span>
<span class="p"> </span><span class="si">}</span><span class="k">$(</span>subst -,_,<span class="si">${</span><span class="nv">strip</span><span class="p"> </span><span class="se">\</span>
<span class="p"> </span><span class="si">}</span><span class="k">$(</span>subst .,_,<span class="si">${</span><span class="nv">strip</span><span class="p"> </span><span class="se">\</span>
<span class="o">}</span><span class="k">$(</span>subst /,_,<span class="nv">$1</span><span class="k">)</span><span class="o">))</span>
</pre></div>
<p>After processing the line continuations, this becomes:</p>
<div class="highlight"><pre><span></span><span class="nv">toMacro</span> <span class="o">=</span> <span class="si">${</span><span class="nv">strip</span><span class="p"> </span><span class="si">}</span><span class="k">$(</span>subst -,_,<span class="si">${</span><span class="nv">strip</span><span class="p"> </span><span class="si">}</span><span class="k">$(</span>subst .,_,<span class="si">${</span><span class="nv">strip</span><span class="p"> </span><span class="si">}</span><span class="k">$(</span>subst /,_,<span class="nv">$1</span><span class="k">)))</span>
</pre></div>
<p>Each <tt class="docutils literal">${strip }</tt> invocation evaporates into the empty string at runtime,
giving the equivalent of:</p>
<div class="highlight"><pre><span></span><span class="nv">toMacro</span> <span class="o">=</span> <span class="k">$(</span>subst -,_,<span class="k">$(</span>subst .,_,<span class="k">$(</span>subst /,_,<span class="nv">$1</span><span class="k">)))</span>
</pre></div>
</div>
<div class="section" id="wrap-line-continuations-with-the-and-function">
<h3>Wrap line continuations with the "and" function</h3>
<p>Another shorter choice is the function "and". Typically it is called with two
arguments, but when given a single empty argument, it is defined to return the
empty string. The word "and" also hints at the concept of line continuation; it
reads as "the first line <em>and</em> the second line <em>and</em> so on".</p>
<div class="highlight"><pre><span></span><span class="nv">toMacro</span> <span class="o">=</span> <span class="si">${</span><span class="nv">and</span><span class="p"> </span><span class="se">\</span>
<span class="p"> </span><span class="si">}</span><span class="k">$(</span>subst -,_,<span class="si">${</span><span class="nv">and</span><span class="p"> </span><span class="se">\</span>
<span class="p"> </span><span class="si">}</span><span class="k">$(</span>subst .,_,<span class="si">${</span><span class="nv">and</span><span class="p"> </span><span class="se">\</span>
<span class="o">}</span><span class="k">$(</span>subst /,_,<span class="nv">$1</span><span class="k">)</span><span class="o">))</span>
</pre></div>
</div>
<div class="section" id="wrap-line-continuations-with-empty-variables">
<h3>Wrap line continuations with empty variables</h3>
<p>Another option is to surround the line continuation with the expansion of an
empty variable. Consider a variable named <tt class="docutils literal">e</tt> (for "empty"). If no
definition for <tt class="docutils literal">e</tt> is given, it will expand to the empty string, resulting in
an even shorter way of suppressing the injected spaces:</p>
<div class="highlight"><pre><span></span><span class="nv">toMacro</span> <span class="o">=</span> <span class="si">${</span><span class="nv">e</span><span class="p"> </span><span class="se">\</span>
<span class="p"> </span><span class="si">}</span><span class="k">$(</span>subst -,_,<span class="si">${</span><span class="nv">e</span><span class="p"> </span><span class="se">\</span>
<span class="p"> </span><span class="si">}</span><span class="k">$(</span>subst .,_,<span class="si">${</span><span class="nv">e</span><span class="p"> </span><span class="se">\</span>
<span class="o">}</span><span class="k">$(</span>subst /,_,<span class="nv">$1</span><span class="k">)</span><span class="o">))</span>
</pre></div>
<p>After processing line continuations, this becomes:</p>
<div class="highlight"><pre><span></span><span class="nv">toMacro</span> <span class="o">=</span> <span class="si">${</span><span class="nv">e</span><span class="p"> </span><span class="si">}</span><span class="k">$(</span>subst -,_,<span class="si">${</span><span class="nv">e</span><span class="p"> </span><span class="si">}</span><span class="k">$(</span>subst .,_,<span class="si">${</span><span class="nv">e</span><span class="p"> </span><span class="si">}</span><span class="k">$(</span>subst /,_,<span class="nv">$1</span><span class="k">)))</span>
</pre></div>
<p>Unfortunately, our variable <tt class="docutils literal">e</tt> isn't actually being used here; rather, the
referenced variable is named <tt class="docutils literal">e<space></tt> (an <tt class="docutils literal">e</tt> followed by a space
character). The injected space character has corrupted the variable name. But
all is not lost; Make permits spaces in variable names, so if we leave the
variable <tt class="docutils literal">e<space></tt> undefined, Make will still evaluate it to the empty
string. In fact, it's possible to have a variable whose name is a single space,
evaluated using the syntax <tt class="docutils literal">${ }</tt>. We can remove the <tt class="docutils literal">e</tt> and compress
things down to:</p>
<div class="highlight"><pre><span></span><span class="nv">toMacro</span> <span class="o">=</span> <span class="si">${</span><span class="se">\</span>
<span class="p"> </span><span class="si">}</span><span class="k">$(</span>subst -,_,<span class="si">${</span><span class="se">\</span>
<span class="p"> </span><span class="si">}</span><span class="k">$(</span>subst .,_,<span class="si">${</span><span class="se">\</span>
<span class="o">}</span><span class="k">$(</span>subst /,_,<span class="nv">$1</span><span class="k">)</span><span class="o">))</span>
</pre></div>
<p>After processing line continuations, this becomes:</p>
<div class="highlight"><pre><span></span><span class="nv">toMacro</span> <span class="o">=</span> <span class="si">${</span><span class="p"> </span><span class="si">}</span><span class="k">$(</span>subst -,_,<span class="si">${</span><span class="p"> </span><span class="si">}</span><span class="k">$(</span>subst .,_,<span class="si">${</span><span class="p"> </span><span class="si">}</span><span class="k">$(</span>subst /,_,<span class="nv">$1</span><span class="k">)))</span>
</pre></div>
<p>This is fairly low syntactical overhead to remove the injected spaces; it costs
us only four punctuation characters per line continuation (namely, <tt class="docutils literal">$</tt>, <tt class="docutils literal">{</tt>,
<tt class="docutils literal">\</tt>, and <tt class="docutils literal">}</tt>). But we can still do better.</p>
</div>
<div class="section" id="two-character-line-continuations">
<h3>Two-character line continuations</h3>
<p>The general way to expand a variable is by wrapping with <tt class="docutils literal">$()</tt> or <tt class="docutils literal">${}</tt>; but
for the special case of a single-character variable name, the use of brackets
is optional. Since backslash-newline turns into a single space character, we
can expand the single-character variable named <tt class="docutils literal"><space></tt> simply by prefixing
the backslash with <tt class="docutils literal">$</tt>:</p>
<div class="highlight"><pre><span></span><span class="nv">toMacro</span> <span class="o">=</span> $<span class="se">\</span>
<span class="k">$(</span>subst -,_,$<span class="se">\</span>
<span class="k">$(</span>subst .,_,$<span class="se">\</span>
<span class="k">$(</span>subst /,_,<span class="nv">$1</span><span class="k">)</span><span class="o">))</span>
</pre></div>
<p>After processing line continuations, this becomes:</p>
<div class="highlight"><pre><span></span><span class="nv">toMacro</span> <span class="o">=</span> $ <span class="k">$(</span>subst -,_,$ <span class="k">$(</span>subst .,_,$ <span class="k">$(</span>subst /,_,<span class="nv">$1</span><span class="k">)))</span>
</pre></div>
<p>Each occurrence of <tt class="docutils literal">$<space></tt> expands to the empty string, making a
low-overhead and readable method of breaking lines without injecting damaging
spaces. It is compatible with GNU Make at least as old as version 3.75 (from
August of 1996) and probably even older; it's hard to acquire source for those
very early versions in order to verify this behavior.</p>
<p>It's hard to beat two-character line continuations for readability, but we can
still do better.</p>
</div>
<div class="section" id="zero-character-line-continuations">
<h3>Zero-character line continuations</h3>
<p>In the body of user-defined functions, it's important for readability to break
lines at sensible boundaries and to indent lines to emphasize their logical
structure. It would be ideal if Make would simply remove newlines and spaces
used for indentation within the bodies of user-defined functions; but though
Make won't do it for us, nothing stops us from doing it ourselves (except the
lack of GNU Make 3.81 or newer).</p>
<p>Consider again the <tt class="docutils literal">toMacro</tt> function, this time written with no line
continuations at all:</p>
<div class="highlight"><pre><span></span><span class="c"># Ideal syntax, but it doesn't work yet:</span>
<span class="nv">toMacro</span> <span class="o">=</span>
<span class="k">$(</span>subst -,_,
<span class="k">$(</span>subst .,_,
<span class="k">$(</span>subst /,_,<span class="nv">$1</span><span class="k">)))</span>
</pre></div>
<p>Without the backslashes, Make doesn't have any way to know that all four lines
above are part of the function's definition. But there is an alternate syntax
for defining recursively expanded variables using <tt class="docutils literal">define</tt>/<tt class="docutils literal">endef</tt> which
provide convenient starting and ending delimiters. In this form, Make at least
knows which lines belong to our <tt class="docutils literal">toMacro</tt> function:</p>
<div class="highlight"><pre><span></span><span class="c"># Ideal syntax, but contains damaging newlines and indendation:</span>
<span class="cp">define toMacro</span>
<span class="k">$(</span>subst -,_,
<span class="k">$(</span>subst .,_,
<span class="k">$(</span>subst /,_,<span class="nv">$1</span><span class="k">)))</span>
<span class="cp">endef</span>
</pre></div>
<p>When using <tt class="docutils literal">define</tt>, Make does not remove unescaped newline characters or
indentation. We can verify this by printing out the value of <tt class="docutils literal">toMacro</tt>:</p>
<div class="highlight"><pre><span></span><span class="k">$(</span><span class="nv">info</span> <span class="nv">toMacro</span>=«<span class="k">$(</span><span class="nv">value</span> <span class="nv">toMacro</span><span class="k">)</span>»<span class="k">)</span>
</pre></div>
<p>Yielding:</p>
<pre class="literal-block">
toMacro=« $(subst -,_,
$(subst .,_,
$(subst /,_,$1)))»
</pre>
<p>The newlines terminating the first two lines are retained, though Make always
removes the final newline. In addition, the two-space indentation is preserved
for each line in <tt class="docutils literal">toMacro</tt> as well. All we require is the ability to remove
newlines and any spaces used for indentation and then to redefine <tt class="docutils literal">toMacro</tt>
with this updated value. For this, we need a couple of helpers.</p>
<p>First, we define the variable <tt class="docutils literal">empty</tt> to be the empty string and the variables
<tt class="docutils literal">space</tt> and <tt class="docutils literal">newline</tt> to contain a literal space and newline, respectively:</p>
<div class="highlight"><pre><span></span><span class="nv">empty</span> <span class="o">:=</span>
<span class="nv">space</span> <span class="o">:=</span> <span class="k">$(</span>empty<span class="k">)</span> <span class="k">$(</span>empty<span class="k">)</span>
<span class="cp">define newline</span>
<span class="cp">endef</span>
</pre></div>
<p>Next, we need a way to programmatically create a recursively expanded variable:</p>
<div class="highlight"><pre><span></span><span class="c"># Define recursively expanded variable $1 with value $2.</span>
<span class="nv">defineVar</span> <span class="o">=</span> <span class="k">$(</span><span class="nb">eval</span> define <span class="nv">$1</span><span class="k">$(</span>newline<span class="k">)</span><span class="nv">$2</span><span class="k">$(</span>newline<span class="k">)</span>endef<span class="k">)</span>
</pre></div>
<p>These, along with the <tt class="docutils literal">resubst</tt> function introduced earlier, are sufficient to
let us define functions two-dimensionally with arbitrary newlines and
indentation, then launder away the newlines and indentation to make a
single-line function without undesired whitespace.</p>
<p>The general method for laundering a function body comprises three steps:</p>
<ol class="arabic simple">
<li>Prepend a newline to the function body;</li>
<li>Repeatedly replace newline-space pairs with newlines;</li>
<li>Remove all newlines.</li>
</ol>
<p>The first step ensures that all leading spaces used for indentation are
immediately preceded by a newline. Next, replacing a newline-space with a
newline deletes the first space of each indented line; this is repeated until
all indentation has been removed. Finally, all newline characters are removed,
yielding the laundered function body. We define the function <tt class="docutils literal">def</tt> that
accepts the name of a multi-line function containing indentation and redefines
its body as a single-line function without indentation or newlines:</p>
<div class="highlight"><pre><span></span><span class="c"># $1 - name of function to redefine as a normalized single-line function.</span>
<span class="nv">def</span> <span class="o">=</span> $<span class="se">\</span>
<span class="k">$(</span>call defineVar,$<span class="se">\</span>
<span class="nv">$1</span>,$<span class="se">\</span>
<span class="k">$(</span>subst <span class="k">$(</span>newline<span class="k">)</span>,$<span class="se">\</span>
<span class="k">$(</span>empty<span class="k">)</span>,$<span class="se">\</span>
<span class="k">$(</span>call resubst,$<span class="se">\</span>
<span class="k">$(</span>newline<span class="k">)$(</span>space<span class="k">)</span>,$<span class="se">\</span>
<span class="k">$(</span>newline<span class="k">)</span>,$<span class="se">\</span>
<span class="k">$(</span>newline<span class="k">)$(</span>value <span class="nv">$1</span><span class="k">)</span><span class="o">)))</span>
</pre></div>
<p>Now we can define a function and immediately launder it via <tt class="docutils literal">def</tt>, e.g.:</p>
<div class="highlight"><pre><span></span><span class="cp">define toMacro</span>
<span class="k">$(</span>subst -,_,
<span class="k">$(</span>subst .,_,
<span class="k">$(</span>subst /,_,<span class="nv">$1</span><span class="k">)))</span>
<span class="cp">endef</span>
<span class="k">$(</span><span class="nv">call</span> <span class="nv">def</span>,<span class="nv">toMacro</span><span class="k">)</span>
</pre></div>
<p>We can see the resulting function body using <tt class="docutils literal">$(info)</tt>:</p>
<div class="highlight"><pre><span></span><span class="k">$(</span><span class="nv">info</span> <span class="nv">Normalized</span> <span class="nv">toMacro</span>=«<span class="k">$(</span><span class="nv">value</span> <span class="nv">toMacro</span><span class="k">)</span>»<span class="k">)</span>
</pre></div>
<p>With output:</p>
<pre class="literal-block">
Normalized toMacro=«$(subst -,_,$(subst .,_,$(subst /,_,$1)))»
</pre>
</div>
</div>
<div class="section" id="caveats">
<h2>Caveats</h2>
<p>There are a few caveats to consider when inserting extra function calls or
variable expansions to swallow the spaces injected by line continuations:</p>
<ul>
<li><p class="first">The inserted function call or variable expansion can be inserted almost
anywhere, but not immediately following an unescaped <tt class="docutils literal">$</tt>. Consider this
example:</p>
<pre class="literal-block">
output := $(input)
</pre>
<p>If a line break were attempted using <tt class="docutils literal">${strip \}</tt> immediately after the
<tt class="docutils literal">$</tt>, it would become:</p>
<pre class="literal-block">
output := $${strip \
}(input)
</pre>
<p>Make will view the pair <tt class="docutils literal">$$</tt> as a request for a literal <tt class="docutils literal">$</tt> which changes
the logic, resulting in the buggy literal value <tt class="docutils literal">${strip }(input)</tt>.</p>
<p>However, this is not a significant restriction; breaking a line after an
unescaped <tt class="docutils literal">$</tt> hurts readability, so there is little temptation to choose
such a location for a line break.</p>
</li>
<li><p class="first">The inserted line-breaking logic hangs around in recursively expanded variable
bodies. This causes no problems as long as the <tt class="docutils literal">$(value)</tt> of the variable
is never inspected by unsuspecting code. This is not a significant
restriction for user-defined functions because their <tt class="docutils literal">$(value)</tt> is typically
never inspected; but if a recursively expanded variable holds data that might
be later examined, the line-breaking logic could get in the way. Consider
the <tt class="docutils literal">CPPDEFINES</tt> variable below:</p>
<pre class="literal-block">
CPPDEFINES=$(localCPPDEFINES) -DVARIABLE=VALUE
</pre>
<p>If this were a long line and a line break were inserted just before the
<tt class="docutils literal">=VALUE</tt>, the result would be:</p>
<pre class="literal-block">
CPPDEFINES=$(localCPPDEFINES) -DVARIABLE$\
=VALUE
</pre>
<p>After Make processes the line continuation, the result is equivalent to:</p>
<pre class="literal-block">
CPPDEFINES=$(localCPPDEFINES) -DVARIABLE$ =VALUE
</pre>
<p>Filtering code scanning for <tt class="docutils literal"><span class="pre">-DVARIABLE=NAME</span></tt> would fail because the
inserted logic was inserted at a poorly chosen location, e.g.:</p>
<pre class="literal-block">
$(filter-out -DVARIABLE=VALUE,$(value CPPDEFINES))
</pre>
<p>But it's rare to see such filtering on the <tt class="docutils literal">$(value)</tt> of a variable, and no
issue arises if the variable is expanded in the usual way (in this case, via
<tt class="docutils literal">$(CPPDEFINES)</tt>) before filtering. Also, data variables are often lists
that are easily broken between words anyway using simple backslash-newline
continuations. But if there is still an issue for a particular variable,
post-processing the <tt class="docutils literal">$(value)</tt> (as done in the <tt class="docutils literal">def</tt> function above) can
ensure the variable contains no extraneous line-breaking logic.</p>
</li>
</ul>
</div>
<div class="section" id="conclusion">
<h2>Conclusion</h2>
<p>By using the above techniques, we can avoid creating unreadable GNU makefiles
with unreadable one-liners or lines broken at forced locations. Outside of
functions, break lines using <tt class="docutils literal">\</tt> where whitespace is desired or at least
permissible, and use <tt class="docutils literal">$\</tt> where whitespace is not desired. For user-defined
functions, use <tt class="docutils literal">define</tt>/<tt class="docutils literal">endef</tt> and the <tt class="docutils literal">def</tt> function provided above for
maximum readability.</p>
</div>
<div class="section" id="footnotes">
<h2>Footnotes</h2>
<table class="docutils footnote" frame="void" id="continuation-rules" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1">[1]</a></td><td>Actually, the line continuation rules are more
complicated. The POSIX specification says to replace the backslash-newline
pair and optional leading white space on the next line with a single space.
GNU Make is not POSIX compliant by default; it additionally strips any
whitespace preceding the backslash and any consecutive
backslash-newline-whitespace sequences. But if the special <tt class="docutils literal">.POSIX</tt> target
is defined, then recent versions of GNU Make adhere to the POSIX rules.</td></tr>
</tbody>
</table>
</div>
Dr. su's quiz answers2013-09-04T00:00:00-04:002013-09-04T00:00:00-04:00Michael Henrytag:drmikehenry.com,2013-09-04:/dr-sus-quiz-answers/<p class="first last">Below are the answers to <a class="reference external" href="/dr-sus-quiz">Dr. su's quiz</a>.</p>
<div class="highlight"><pre><span></span>who > horton
<span class="s2">"Horton Hears a Who!"</span>
tar -cf hat /bin/cat
<span class="s2">"The Cat in the Hat"</span>
tar -xf hat
<span class="s2">"The Cat in the Hat Comes Back"</span>
killall -HUP pop
<span class="s2">"Hop on Pop"</span>
sudo -u grinch mv xmas /mnt/crumpet
<span class="s2">"How the Grinch Stole Christmas!"</span>
<span class="nb">echo</span> -e <span class="s1">'\e[32meg\x67s h\x61m\e[0m'</span>
<span class="s2">"Green Eggs and Ham"</span>
su brown -c moo<span class="p">;</span> <span class="nb">test</span> -x moo
<span class="s2">"Mr. Brown Can Moo! Can You?"</span>
<span class="nb">echo</span> <span class="s1">'rm -f marvin'</span> <span class="p">|</span> at now
<span class="s2">"Marvin K. Mooney Will You Please Go Now!"</span>
<span class="nb">echo</span> <span class="o">{</span>One,Two,Red,Blue<span class="o">}</span><span class="s1">' Fish'</span>
<span class="s2">"One Fish Two Fish Red Fish Blue Fish"</span>
cp fox socks/
<span class="s2">"Fox in Socks"</span>
chown bart:cubbins hat<span class="o">{</span><span class="m">1</span>..500<span class="o">}</span>
<span class="s2">"The 500 Hats of Bartholomew Cubbins"</span>
find mulberry -name <span class="s2">"it"</span> -exec think <span class="o">{}</span> +
<span class="s2">"And to Think That I Saw It on Mulberry Street"</span>
<span class="o">[</span> -n <span class="s2">"</span><span class="k">$(</span>pgrep -u <span class="k">$(</span>whoami<span class="k">)</span> zoo<span class="k">)</span><span class="s2">"</span> <span class="o">]</span>
<span class="s2">"If I Ran the Zoo"</span>
man sleep
<span class="s2">"Dr. Seuss's Sleep Book"</span>
<span class="k">case</span> <span class="k">$(</span>date +%u<span class="k">)</span> <span class="k">in</span> <span class="o">[</span><span class="m">1234567</span><span class="o">])</span> uptime<span class="p">;;</span> <span class="k">esac</span>
<span class="s2">"Great Day for Up!"</span>
</pre></div>
<p>Note: the <a class="reference external" href="http://tinyurl.com/knw3bye">hint URL</a> resolves to:
<a class="reference external" href="http://en.wikipedia.org/wiki/Dr._Seuss_bibliography#Dr._Seuss_books">http://en.wikipedia.org/wiki/Dr._Seuss_bibliography#Dr._Seuss_books</a></p>
Dr. su's quiz2013-09-01T00:00:00-04:002013-09-01T00:00:00-04:00Michael Henrytag:drmikehenry.com,2013-09-01:/dr-sus-quiz/<p>If you are a Unix geek, give Dr. su's quiz a try.</p>
<p>See if you can determine the meaning of each line of Unix commands below. As
much as possible, these commands are valid to run on a typical Linux machine
(though some of them would require setting up particular …</p><p>If you are a Unix geek, give Dr. su's quiz a try.</p>
<p>See if you can determine the meaning of each line of Unix commands below. As
much as possible, these commands are valid to run on a typical Linux machine
(though some of them would require setting up particular files or users).</p>
<p>I hope you enjoy solving Dr. su's quiz as much as I did composing it. Answers
will follow in a later post.</p>
<p>Try <a class="reference external" href="http://tinyurl.com/knw3bye">this site</a> for a hint.</p>
<div class="highlight"><pre><span></span>who > horton
tar -cf hat /bin/cat
tar -xf hat
killall -HUP pop
sudo -u grinch mv xmas /mnt/crumpet
<span class="nb">echo</span> -e <span class="s1">'\e[32meg\x67s h\x61m\e[0m'</span>
su brown -c moo<span class="p">;</span> <span class="nb">test</span> -x moo
<span class="nb">echo</span> <span class="s1">'rm -f marvin'</span> <span class="p">|</span> at now
<span class="nb">echo</span> <span class="o">{</span>One,Two,Red,Blue<span class="o">}</span><span class="s1">' Fish'</span>
cp fox socks/
chown bart:cubbins hat<span class="o">{</span><span class="m">1</span>..500<span class="o">}</span>
find mulberry -name <span class="s2">"it"</span> -exec think <span class="o">{}</span> +
<span class="o">[</span> -n <span class="s2">"</span><span class="k">$(</span>pgrep -u <span class="k">$(</span>whoami<span class="k">)</span> zoo<span class="k">)</span><span class="s2">"</span> <span class="o">]</span>
man sleep
<span class="k">case</span> <span class="k">$(</span>date +%u<span class="k">)</span> <span class="k">in</span> <span class="o">[</span><span class="m">1234567</span><span class="o">])</span> uptime<span class="p">;;</span> <span class="k">esac</span>
</pre></div>
<!-- other titles
"Bartholomew and the Oobleck"
"Daisy-Head Mayzie"
"Did I Ever Tell You How Lucky You Are?"
"Dr. Seuss's ABC"
"Happy Birthday to You!"
"Hooray for Diffendoofer Day!"
"Horton Hatches the Egg"
"Hunches in Bunches"
"I Am NOT Going to Get Up Today!"
"I Can Draw It Myself"
"I Can Lick 30 Tigers Today! and Other Stories"
"I Can Read with My Eyes Shut!"
"I Had Trouble in Getting to Solla Sollew"
"If I Ran the Circus"
"McElligot's Pool"
"My Book about ME"
"My Many Colored Days"
"Oh Say Can You Say?"
"Oh, the Places You'll Go!"
"Oh, the Thinks You Can Think!"
"On Beyond Zebra!"
"Scrambled Eggs Super!"
"The Butter Battle Book"
"The Cat in the Hat Song Book"
"The Cat's Quizzer"
"The Foot Book"
"The King's Stilts"
"The Lorax"
"The Seven Lady Godivas"
"The Shape of Me and Other Stuff"
"The Sneetches and Other Stories"
"The Tough Coughs as He Ploughs the Dough"
"There's a Wocket in My Pocket!"
"Thidwick the Big-Hearted Moose"
"Yertle the Turtle and Other Stories"
"You're Only Old Once!" -->
Welcome to drmikehenry.com2013-08-29T00:00:00-04:002013-08-29T00:00:00-04:00Michael Henrytag:drmikehenry.com,2013-08-29:/intro/<p>Welcome to the modest online home of Michael Henry.</p>