To quote or not to quote
I've been bitten by this twice, so I write it down to avoid another bite.
Short summary: The popular way to pass compiler command-line options by command/parameter substitution does not work with arguments including whitespaces.
Here I'm talking about the typical Makefile idioms such as the following:
gcc `gauche-config -I` ...
Or like this:
CFLAGS=`gauche-config -L` gcc $(CFLAGS) ...
gauche-config -I and
-L flag(s) to give to the compiler,
Typically there's one
-I flag, but there may be more
So it should be interspersed into the command line. That is,
we can't quote outside of substitution like this:
gcc "`gauche-config -L`"
On Windows, Gauche may be installed under a path that contains
whitespaces. In fact, Gauche Windows installer uses
C:\Program Files\Gauche as the default.
To pass such pathnames to
each option must already be quoted right after substitution.
So, initially I naively changed the output of gauche-config to quote the pathname:
Here came a twist.
The modern way to compile extension modules is
gauche-package compile command,
which takes care of gory details and makes Makefile simpler;
you just list the source files and the script takes care of
compiling and linking, with proper options.
Internally it uses
gauche.config module to obtain the same
information as output of
I used Windows installer to install Gauche under
and compiled Gauche-gl using it with MinGW/MSYS. Everything worked
smoothly. I was satisfied.
Then, a few days later I was testing 0.9.1 prerelease on my Linux box,
and found some extension modules didn't compile. Their makefile didn't
gauche-package, but directly invoked gcc with
`guache-config -I` for the arguments.
I remembered I had been tripped with the same problem
a few years ago and had given up. This time I wanted to solve it
once for all. I thought my quoting
scheme was wrong, and fiddled with
for some time. I couldn't managed it to work. I carefully read
the man page of bash. And leaned this:
- Quote processing is done before command/parameter substitution.
- The result of command/parameter substitution is subject of word splitting, unless the argument (before substitution) is quoted.
- Word splitting honor neither quotes, nor escaping (such as backslash). -
it is simple string splitting with the characters
This means that, as far as we use shell-level command-line substitution,
the output of
gauche-config cannot contain whitespaces inside
each argument. Tools using the same scheme, such as
have the same limitation, and in fact it is documented in
If we can have intermediate step to preprocess the command line,
and passes the quoted pathnames to the shell, it works.
It is what
gauche-package does. An alternative way
could be to invoke shell within Makefile, and let
consturct the command line:
INCLUDES = $(shell gauche-config -I) gcc $(INCLUDES) ...
With this, shell sees already expanded options, so it can process quotes correctly.
However, there may be a case that an extention can't use
gauche-package compile because it requires special build process,
and also it can't use GNU make. For the backward compatibility,
gauche-config -I and
not to quote pathnames. Hence, they are inherently unsafe way
to construct a command line.
So, what should be the proper way for the extension makefile
gauche-config to handle pathnames with spaces?
I don't know yet. For the time being, I added
--archdirs options to
They return pathnames separated by colon (or semincolon on Windows),
gauche-package constructs command line arguments from them.
I'm not satisfied with it, though.
Tags: extensions, makefile, gauche-config, gauche-package
Post a comment