[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Behaviour of $(shell command args) is dangerously different from `co

From: Paul Smith
Subject: Re: Behaviour of $(shell command args) is dangerously different from `command args`
Date: Wed, 10 Apr 2013 13:28:38 -0400

On Wed, 2013-04-10 at 18:18 +0200, Vincent de Phily wrote:

> > SHELL := /bin/bash
> > date := $(shell date -R)
> > prevtag := $(shell git describe --tags|cut -d- -f1)

This is not good: what if your tag contains a "-" in it?

I think you want: $(shell git describe --tags --abbrev=0)

> > release:
> > #       sed -i "1s#^#$(VERSION) ($(date))\n$(shell git log HEAD...$(prevtag)
> > #           '--pretty=format:\\t* %s\\n'|tr -d '\n')\n#1" Changelog
> >         sed -i "1s#^#$(VERSION) ($(date))\n`git log HEAD...$(prevtag)
> >             '--pretty=format:\\t* %s\\n'|tr -d '\n'`\n#1" Changelog
> The problem is that with the first (commented) version of the command, if I 
> have a commit message containing something between backquotes, that something 
> gets executed by make. In my case I was lucky and just ran into an infinite 
> loop executing `make release`, but I would have been in bigger trouble if I 
> had a commit to, say, "Protect against unintentional `rm -rf /`."
> If the behaviour is expected (why ?), it would be usefull to explain the 
> difference between `command` and $(shell command) in the info pages.

There is no difference between `command` and $(shell command), except
the order in which they're executed.

Remember that make will expand all make functions and variables in the
recipe FIRST, then pass the resulting text string to the shell for the
shell to execute.  Make doesn't interpret the results of the functions
or variables itself.

If you want to understand how make works, then you can emulate it from a
shell command line by doing this:

First, run the command you provided to $(shell ...) from the prompt:

  $ git log HEAD...`git describe --tags --abbrev=0` --pretty=format:\\t* 
%s\\n'|tr -d '\n'

You'll get a bunch of output.

Now enter your sed command, but CUT AND PASTE the output of the git log
command into the right spot:

  $ sed  -i "1s#^#<VERSION> (`date -R`)\n<CUT-N-PASTE HERE>\n#1" Changelog

You'll see the same behavior here as you get with make, because that's
what make is doing: it's not interpreting the output of the $(shell ...)
command at all: it's just taking that output and pasting it directly
into the command string, then passing the whole thing to the shell.

When you use `` in the shell, the shell is invoking the `` command and
the shell will treate the output of that command differently (for
example, the shell does not recursively expand the output of the ``
command so if that output contains more `` commands, they are not

In general you should never, and never need to, use $(shell ...) inside
a recipe command.  You're already running a shell, so why?

reply via email to

[Prev in Thread] Current Thread [Next in Thread]