summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorrillig <rillig@pkgsrc.org>2005-05-14 03:23:20 +0000
committerrillig <rillig@pkgsrc.org>2005-05-14 03:23:20 +0000
commitb9bf8b26f88ad18e3c95904bef2e47c4dbbbc77c (patch)
treee27f1736ccbd26d5206380832d4e2a7b5fa8aa60 /doc
parent541489e8a2cf99e233788f199247633e1da225be (diff)
downloadpkgsrc-b9bf8b26f88ad18e3c95904bef2e47c4dbbbc77c.tar.gz
Added a subsection called "Quoting guideline", which describes some of the
common quoting errors.
Diffstat (limited to 'doc')
-rw-r--r--doc/guide/files/makefile.xml96
1 files changed, 93 insertions, 3 deletions
diff --git a/doc/guide/files/makefile.xml b/doc/guide/files/makefile.xml
index 4e1aac75ade..8bf16920ffd 100644
--- a/doc/guide/files/makefile.xml
+++ b/doc/guide/files/makefile.xml
@@ -1,4 +1,4 @@
-<!-- $NetBSD: makefile.xml,v 1.8 2005/05/13 23:28:08 rillig Exp $ -->
+<!-- $NetBSD: makefile.xml,v 1.9 2005/05/14 03:23:20 rillig Exp $ -->
<!-- based on:
pkgsrc/bootstrap/bmake/for.c 1.1.1.1
@@ -104,12 +104,12 @@ pkgsrc/bootstrap/bmake/var.c 1.2
<itemizedlist>
- <listitem><para>All variable names starting with an underscore
+ <listitem><para>All variable names starting with an underscore
are reserved for use by the pkgsrc infrastructure. They shall
not be used by package
<filename>Makefile</filename>s.</para></listitem>
- <listitem><para>In <!-- FIXME --><varname>.for</varname> loops
+ <listitem><para>In <!-- FIXME --><varname>.for</varname> loops
you should use lowercase variable names for the iteration
variables.</para></listitem>
@@ -211,5 +211,95 @@ all:
no example for it.</para>
</sect2>
+
+ <sect2>
+ <title>Quoting guideline</title>
+
+ <para>There are many possible sources of wrongly quoted variables.
+ This section lists some of the commonly known ones.</para>
+
+ <itemizedlist>
+
+ <listitem><para>Whenever you use the value of a list, think
+ about what happens to leading or trailing whitespace. If the
+ list is a well-formed shell expression you can apply the
+ <varname>:M*</varname> modifier to strip leading and trailing
+ whitespace from each word. The <varname>:M</varname> operator
+ first splits its argument according to the rules of the shell,
+ and then creates a new list consisting of all words that match
+ the shell glob expression <varname>*</varname>, that is: all.
+ One class of situations where this is needed is when adding a
+ variable like <varname>CPPFLAGS</varname> to
+ <varname>CONFIGURE_ARGS</varname>. If the configure script
+ invokes other configure scripts it strips the leading and
+ trailing whitespace from the variable and then passes it to the
+ other configure scripts. But these configure scripts expect the
+ (child) <varname>CPPFLAGS</varname> variable to be the same as
+ the parent <varname>CPPFLAGS</varname>. That's why we better
+ pass the <varname>CPPFLAGS</varname> value properly trimmed. And
+ here is how we do it:</para>
+
+ <programlisting>
+CPPFLAGS= # empty
+CPPFLAGS+= -Wundef -DPREFIX=\"${PREFIX:Q}\"
+CPPFLAGS+= ${MY_CPPFLAGS}
+
+CONFIGURE_ARGS+= CPPFLAGS=${CPPFLAGS:M*:Q}
+
+all:
+ echo x${CPPFLAGS:Q}x # leading and trailing whitespace
+ echo x${CONFIGURE_ARGS}x # properly trimmed
+ </programlisting></listitem>
+
+ <listitem><para>The example above contains one bug: The
+ <varname>${PREFIX}</varname> is a properly quoted shell
+ expression, but there is the C compiler after it, which also
+ expects a properly quoted string (this time in C syntax). The
+ version above is therefore only correct if
+ <varname>${PREFIX}</varname> does not have embedded backslashes
+ or double quotes. If you want to allow these, you have to add
+ another layer of quoting to each variable that is used as a C
+ string literal. You cannot use the <varname>:Q</varname>
+ operator for it, as this operator only works for the
+ shell.</para></listitem>
+
+ <listitem><para>Whenever a variable can be empty the
+ <varname>:Q</varname> operator can have surprising results. Here
+ are two completely different cases which can be solved with the
+ same trick.</para>
+
+ <programlisting>
+EMPTY= # empty
+empty_test:
+ for i in a ${EMPTY:Q} c; do \
+ echo "$$i"; \
+ done
+
+for_test:
+.for i in a:\ a:\test.txt
+ echo ${i:Q}
+ echo "."
+.endfor
+ </programlisting>
+
+ <para>The first example will only print two of the three lines
+ we might have expected. This is because
+ <varname>${EMPTY:Q}</varname> expands to the empty string, which
+ the shell cannot see. The workaround is to write
+ <varname>${EMPTY:Q}""</varname>. This pattern can be often found
+ as <varname>${TEST} -z ${VAR:Q}</varname> or as <varname>${TEST}
+ -f ${FNAME:Q}</varname> (both of these are wrong).</para>
+
+ <para>The second example will only print three lines instead of
+ four. The first line looks like <varname>a:\ echo .</varname>.
+ This is because the backslash of the value
+ <varname>a:\</varname> is interpreted as a line-continuation by
+ &man.make.1;, which makes the second line the arguments of the
+ &man.echo.1; command from the first line. To avoid this, write
+ <varname>${i:Q}""</varname>.</para></listitem>
+
+ </itemizedlist>
+ </sect2>
+
</sect1>
</chapter>