从makefile执行复杂的shell命令

jip*_*pie 2 linux makefile gnu-make

我有以下命令行在Linux命令提示符下工作:

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

它创建一个包含以下vim命令的临时文件(使用Process Substitution):

:1 s/^\/\/ VERSION: .*$/\/\/ VERSION: $(date)/g
Run Code Online (Sandbox Code Playgroud)

它打开文件/tmp/test.txt进行编辑,并从先前创建的临时文件中执行命令.它找到第1行并用当前时间戳替换该行.看起来有点像这样:

// VERSION: Fri Apr 12 21:20:03 CEST 2013
...
...
Run Code Online (Sandbox Code Playgroud)

接下来我可以进行任何所需的编辑,只有当我决定保存文件时,所有更改都将提交到磁盘.首先更改磁盘上的文件,然后启动编辑器不是一个选项,因为文件将具有不同的时间戳,而内容本身不会更改.

到目前为止,它按设计/预期工作.

现在我正在尝试将此vi命令行移动到make文件中,这就是我失败的地方.我尝试了一个$(shell .....)结构,但是make会给我带来错误.

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

我正在试图弄清楚Makefile中的行应如何阅读摆弄额外的引号和括号,但我还没有解决它.

我正在运行Ubuntu Linux 12.10和GNU Make 3.81

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

Make似乎不喜欢"过程替代"结构<( command ).我不想使用额外的(真实)文件.

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

Mad*_*ist 9

$(shell ...)一个化妆配方里面几乎是从来不正确的.你已经在shell中...只需直接输入你想要的命令.尝试使用make $(shell ...)函数只会增加混乱.你必须$通过写作逃脱$$.

您还有另一个问题:make始终使用其脚本调用它,/bin/sh并且您正在使用特定于bash的构造(<(...)).

当然,更大的问题是为什么你使用vi(一个可视化编辑器)来做这样的自动更改,而不是例如sed为它设计的.我会把它重写为:

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

如果你真的想使用vi,你必须做类似的事情:

SHELL := /bin/bash

edit:
        vi '$(src).cpp' -s <( echo ":1 s/^\/\/ VERSION: .*$$/\/\/VERSION: $$(date)/g" )
Run Code Online (Sandbox Code Playgroud)