Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hash inside Makefile shell call causes unexpected behaviour

The following command prints the absolute path of a particular C++ header, according to where g++ believes it to be.

echo \#include\<ham/hamsterdb.h\> | g++ -M -x c++-header - | grep hamsterdb.hpp | sed -e 's/-:  //' -e 's/ \\//'

On my system, this outputs: /usr/local/include/ham/hamsterdb.hpp

I run into a problem when trying to run this inside a Makefile in order to set a variable:

FILE=$(shell echo \#include\<ham/hamsterdb.h\> | g++ -M -x c++-header - | grep hamsterdb.hpp | sed -e 's/-:  //' -e 's/ \\//')

.PHONY spec

spec:
    @echo $(FILE)

This outputs a new line. I think it's the hash ('#') character which is messing with make; if I rewrite the FILE=... line like this:

FILE=$(shell echo \#include\<ham/hamsterdb.h\>)

the output is still nothing.

like image 547
Anthony Avatar asked Jan 29 '12 09:01

Anthony


2 Answers

You have to escape the hash twice in order to use it inside functions: once for Make and once again for the shell.

That is,

FILE = $(shell echo \\\#include\ \<ham/hamsterdb.h\>)

Notice three backslashes instead of two as one could expect. The third backslash is needed because otherwise the first one would escape the second and the hash would be still unescaped.

UPD.

Another possible solution is to only escape the hash for Make and use Bash single quotes to prevent interpreting the hash as a shell comment. This also eliminates the need of escaping spaces, < and >:

FILE = $(shell echo '\#include <ham/hamsterdb.h>')
like image 163
Eldar Abusalimov Avatar answered Oct 10 '22 07:10

Eldar Abusalimov


You need just a bit more quoting:

FILE=$(shell echo \\\#include\<ham/hamsterdb.h\> ...
                  ^^^

Quote once for make itself, a second time for the shell (the shell needs to 'see' \#).

like image 28
Mat Avatar answered Oct 10 '22 07:10

Mat