在Makefile中提取无扩展名文件名失败,生成文件仅显示版本号
Makefile提取Asciidoc文件名失败问题解决
问题场景
编写了用于将.adoc文件生成PDF/HTML的Makefile,但生成的输出文件名仅显示_1_0_0(版本号),基础文件名未被正确提取。原Makefile代码如下:
SHELL := /bin/bash .DEFAULT_GOAL := all # version and build for the target VERSION := 1.0.0 BUILD := `git rev-parse HEAD` # source directory SRCDIR := ${CURDIR}/src # create output directory OUTDIR := ${CURDIR}/build MAKE_OUTDIR = $(shell mkdir -p $(OUTDIR)) .PHONY: all build-html build-pdf clean build: $(MAKE_OUTDIR) build-html build-pdf build-html: @$(foreach file, $(wildcard $(SRCDIR)/*.adoc), asciidoctor \ -r asciidoctor-diagram \ -o $(OUTDIR)/html/$(file%.*)_$(VERSION) $(file);) build-pdf: @$(foreach file, $(wildcard $(SRCDIR)/*.adoc), asciidoctor-pdf \ -r asciidoctor-diagram \ -o $(OUTDIR)/html/$(file%.*)_$(VERSION) $(file);) clean: @rm -rf $(OUTDIR)
问题原因
$(file%.*)的匹配逻辑是从右往左匹配第一个.并截断后面的内容,但file变量包含完整的文件路径(比如/home/user/src/doc.adoc),截断后得到的是/home/user/src/doc,直接拼接到输出路径后会导致路径层级冲突,最终只剩下版本号部分。同时你还遗漏了文件扩展名,生成的文件没有对应格式后缀。
修复方案
需要先提取纯文件名,再去掉后缀,最后拼接版本号和对应扩展名:
- 用
$(notdir $(file))提取不带路径的纯文件名(比如doc.adoc) - 用
$(basename $(notdir $(file)))去掉后缀得到基础文件名(比如doc) - 拼接版本号和格式扩展名(
.html或.pdf)
修改后的build-html和build-pdf目标如下:
build-html: @$(foreach file, $(wildcard $(SRCDIR)/*.adoc), \ asciidoctor \ -r asciidoctor-diagram \ -o $(OUTDIR)/html/$(basename $(notdir $(file)))_$(VERSION).html \ $(file);) build-pdf: @$(foreach file, $(wildcard $(SRCDIR)/*.adoc), \ asciidoctor-pdf \ -r asciidoctor-diagram \ -o $(OUTDIR)/pdf/$(basename $(notdir $(file)))_$(VERSION).pdf \ $(file);)
同时建议分开HTML和PDF的输出目录,并确保所有子目录都被创建:
MAKE_OUTDIR = $(shell mkdir -p $(OUTDIR)/html $(OUTDIR)/pdf)
额外注意点
- Makefile的命令行缩进必须用Tab键,原代码中用空格可能导致执行错误,建议修正
DEFAULT_GOAL设为all,但当前未定义all目标,可添加all: build或者将build目标改名为all
内容的提问来源于stack exchange,提问作者j3d
相关产品推荐
相关产品推荐

