目标我将幻灯片写在 Markdown 文件中,然后对其进行编译以供显示,将其上传到我的网络服务器并执行其他操作。我想组织将 markdown 写入 makefile 后的步骤:
PROJNAME = `pwd | grep -oP '(\w|-)+' | tail -n 2 | head -n 1 | tr '[:upper:]' '[:lower:]'`
presentation: slides.pandoc
pandoc --self-contained --data-dir=$(HOME)/.pandoc --template=slides/revealjs_niels_tmpl.html -V revealjs-url:$(HOME)/.pandoc/revealjs -V theme:solarized slides.pandoc -f markdown -t revealjs -o $(PROJNAME).html
onlinepresent: $(PROJNAME).html
cp $(PROJNAME).html $(HOME)/Share/index.html
解释 PROJNAME
查找项目文件夹名称并将其转换为小写。在我使用它并生成标题中显示的消息的示例文件夹中,这会导致ws-anno-ii
.该presentation
规则使用 将幻灯片编译为 html pandoc
。宏PROJNAME
用于定义输出文件的名称。如果该文件存在于已安装的外部文件系统 ( ) 中,则停止位置应复制包含项目名称 ( )onlinepresent
的make
文件。如果不存在,当然应该首先应用该规则。但是当我输入命令时没有任何反应,并且我收到消息ws-anno-ii.html
Share
presentation
make
该make
过程停止并Makefile:6: *** multiple target patterns. Stop.
引用该行onlinepresent: $(PROJNAME).html
谁能向我解释为什么会发生这种情况?
答案1
make 变量的值PROJNAME
是
`pwd | grep -oP '(\w|-)+' | tail -n 2 | head -n 1 | tr '[:upper:]' '[:lower:]'`
反引号字符在 make 中并不特殊。如果在 shell 命令中使用该变量,shell 会看到反引号并将它们解析为命令替换。但是,如果您在 make 解释变量的地方使用该变量,则反引号不会执行任何特殊操作。onlinepresent: $(PROJNAME).html
变量扩展后,该行变为:
onlinepresent: `pwd | grep -oP '(\w|-)+' | tail -n 2 | head -n 1 | tr '[:upper:]' '[:lower:]'`.html
使解析为onlinepresent
, colon, `pwd
, \
, grep
, -oP
, , , , , , , , , '(\w|-)+'
, , , , colon, , colon, , , colon, , colon, 。最右边冒号的左边有多个单词,因此是“多个目标模式”。|
tail
-n
2
|
head
-n
1
|
tr
'[
upper
]'
'[
lower
]'`.html
如果你想在 make 能够读取的地方使用 shell 命令的输出,你需要调用shell
功能。这是一个 GNU make 功能,在其他 make 实现中不起作用。
PROJNAME = $(shell pwd | grep -oP '(\w|-)+' | tail -n 2 | head -n 1 | tr '[:upper:]' '[:lower:]'`)
这会将PROJNAME
变量设置为工作目录的倒数第二个转换为小写的组件。
请注意,使用当前目录是脆弱的:这意味着如果从不同的目录作为目标调用您的 makefile 将无法工作。PROJNAME
从到目标的路径进行计算会更加稳健。如果不是小写部分,您可以使用 make 函数完全完成(如果很麻烦)(我假设您拆分代码的目的实际上是提取路径名组件):
$(notdir $(patsubst %/,%,$(dir $(patsubst %/,%,$(dir $(abspath $@))))))
但 GNU make 没有大小写转换工具。如果您无论如何都要调用 shell,则可以使其变得更简单。
PROJNAME = $(shell set -x; echo '$(abspath $@)' | awk -F/ '{$$0=tolower($$0); print $$(NF-2)}')
onlinepresent: $(PROJNAME).html
cp $< $$HOME/Share/index.html
$$
请注意makefile 中的使用,它将成为$
shell 命令中的内容。这是有效的,因为PROJNAME
变量是在每次使用时计算的,而不是在定义时计算(如果使用 ,则 make 中的变量定义在每次使用时扩展=
,如果使用 ,则在读取赋值时扩展:=
)。
答案2
当你跑步时make onlinepresent
,make
走到目标处onlinepresent
并看到它需要$(PROJNAME).html
,这有点像错误的...从make的角度来看,因为没有直接提供的目标$(PROJNAME).html
。
我还假设您的分配PROJNAME
只有一种可能结果。
尝试用
presentation: slides.pandoc
#your pandoc rule
onlinepresent: presentation
#your mv command
这说明make
为了实现目标,需要onlinepresent
目标。presentation
然后目标表示告诉 make 这是必需的,因此如果是新的或已修改的slides.pandoc
规则,它将运行该规则。slides.pandoc
或者
您还可以尝试将目标重命名presentation
为$(PROJNAME).html
,使其看起来像
$(PROJNAME).html: slides.pandoc
#your pandoc rule
onlinepresent: $(PROJNAME).html
#your mv command