Execute complex shell command from makefile

19,621

Using $(shell ...) inside of a make recipe is virtually never correct. You're already in a shell... just type the commands you want directly. Trying to use the make $(shell ...) function just adds confusion. You will have to escape $ by writing $$.

You have another problem: make always invokes its scripts using /bin/sh and you're using a bash-specific construct (<(...)).

Of course, the bigger question is why you're using vi, which is a visual editor, to do automated changes like this instead of, for example, sed which is designed for it. I'd rewrite it as something like:

edit:
        sed -i "1 s,^// VERSION: .*,// VERSION: $$(date)," $(src).cpp

If you really want to use vi, you'll have to do something like:

SHELL := /bin/bash

edit:
        vi '$(src).cpp' -s <( echo ":1 s/^\/\/ VERSION: .*$$/\/\/VERSION: $$(date)/g" )
Share:
19,621
jippie
Author by

jippie

I'm into: Linux; Networking; IT Security; Perl; System integration; Arduino; ATtiny &amp; ATmega Microcontrollers (AVR); Analog electronics;

Updated on June 04, 2022

Comments

  • jippie
    jippie almost 2 years

    I have the following command line that works from the Linux command prompt:

    vi /tmp/test.txt -s <( echo ":1 s/^\/\/ VERSION: .*$/\/\/VERSION: $(date)/g" )
    

    It creates a temporary file (using Process Substitution) that contains the following vim command:

    :1 s/^\/\/ VERSION: .*$/\/\/ VERSION: $(date)/g
    

    It opens file /tmp/test.txt for editing and executes the command from the previously created temporary file. It finds line 1 and replaces the line with a current time stamp. It looks a bit like this:

    // VERSION: Fri Apr 12 21:20:03 CEST 2013
    ...
    ...
    

    Next I can do any required editing and only when I decide to save the file, all changes are commited to disk. It is not an option to first change the file on disk, then start the editor, as the file will have a different timestamp while the contents itself didn't change.

    So far it works as designed / intended.

    Now I'm trying to move this vi command line into a make file and that is where I fail. I tried a $(shell .....) construction, but make is throwing errors at me.

    edit:
            $(shell vi $(src).cpp -s <( echo ":1 s/^\/\/ VERSION: .*$/\/\/VERSION: $(date)/g" )
    

    I'm trying to figure out how the line in the Makefile should read fiddling with extra quotes and parentheses, but I haven't solved it yet.

    I am running Ubuntu Linux 12.10 and GNU Make 3.81

    vi project.cpp -s <( echo ":1 s/^\/\/ VERSION: .*$/\/\/VERSION: $(date)/g" )

    Make doesn't seem to like the "Process Substitution" construction <( command ). I do not want to use an extra (real) file.

    € make edit
    vi project.cpp -s <( echo ":1 s/^\/\/ VERSION: .*$/\/\/VERSION: $(date)/g" )
    /bin/sh: 1: Syntax error: "(" unexpected
    make: *** [edit] Error 2