从Maven版本获取Makefile变量异常:编写Make规则存变量失败
解决Makefile中无法存储Maven/Git命令输出的问题
我猜你大概率是踩了Make的两个常见坑:默认Shell不是bash,或者变量赋值用了Shell语法而非Make的语法。别急,咱们一步步来解决。
首先给你一个能直接用的完整示例,再拆解背后的原因:
# 明确指定用bash执行命令(如果你的Maven/Git命令依赖bash特性的话) SHELL := /bin/bash # 获取Git短提交哈希(Make解析阶段就执行命令并存储值) GIT_COMMIT := $(shell git rev-parse --short HEAD) # 获取Maven生成的原始Jar包名称(不带.jar后缀) ORIGINAL_JAR := $(shell mvn help:evaluate -Dexpression=project.build.finalName -q -DforceStdout) # 定义新的Jar包名称(用Git哈希命名) NEW_JAR := $(GIT_COMMIT).jar # 重命名Jar包的规则 rename-jar: mv target/$(ORIGINAL_JAR).jar target/$(NEW_JAR)
为什么你之前的写法无效?
常见的错误场景有两种:
1. 用Shell的变量赋值语法写在Makefile里
比如你可能直接写了:
# 错误写法:Make不认识这种Shell赋值 ORIGINAL_JAR=$(mvn help:evaluate -Dexpression=project.build.finalName -q -DforceStdout)
Make的变量赋值需要用$(shell ...)来包裹Shell命令,这样Make才会在解析阶段执行命令并把输出存到变量里。
2. 在规则的命令里跨行用Shell变量
如果你的写法是这样的:
# 错误写法:每行命令是独立的Shell进程,变量无法共享 rename-jar: ORIGINAL_JAR=$(mvn help:evaluate -Dexpression=project.build.finalName -q -DforceStdout) mv target/$$ORIGINAL_JAR.jar target/$(GIT_COMMIT).jar
这里第一行的ORIGINAL_JAR只在当前行的Shell进程里有效,第二行的$$ORIGINAL_JAR会是空的。解决办法要么把两行用;连起来,要么加上.ONESHELL:让整个规则的命令在同一个Shell进程里执行:
.ONESHELL: rename-jar: ORIGINAL_JAR=$(mvn help:evaluate -Dexpression=project.build.finalName -q -DforceStdout) mv target/$${ORIGINAL_JAR}.jar target/$(GIT_COMMIT).jar
不过更推荐用前面的Make变量方式,因为变量值在Make启动时就已经确定,不会受规则执行时的环境影响。
额外注意点
- 确保Maven命令的
-q -DforceStdout参数不能少,否则Maven会输出多余的日志信息,导致ORIGINAL_JAR变量里包含垃圾内容。 - 如果你的项目需要先打包再重命名,可以把
rename-jar规则依赖于package目标:
rename-jar: package mv target/$(ORIGINAL_JAR).jar target/$(NEW_JAR)
内容的提问来源于stack exchange,提问作者gregmacfarlane
相关产品推荐
相关产品推荐

