Makefile执行命令替换时出现no source files错误如何解决
问题原因
Makefile 中 $ 是特殊字符,默认会被解析为 Make 自身的变量引用。你编写的 $(find ./source/* | grep .java) 会被 Make 识别为读取名为 find ./source/* | grep .java 的自定义变量,该变量不存在所以返回空值,最终传给 shell 的命令就变成了 javac -d target,自然会报找不到源文件的错误。
你直接在 bash 中运行命令正常,是因为没有 Make 的变量解析环节,$() 会被 bash 正确识别为命令替换语法。
解决方法
方法1:转义 $ 符号(推荐)
在 $ 前额外加一个 $ 转义,Make 会把 $$ 替换为单个 $ 传给 shell,就能正确执行命令替换。同时建议提前创建 target 目录,避免目录不存在时 javac 报错:
all: ./source/Listener.java ./source/ServerThread.java ./source/TestClient.java mkdir -p target javac -d target $$(find ./source -type f -name "*.java")
注意:Makefile 中所有命令行必须以 Tab 字符开头,不能用空格代替,否则会识别失败。
方法2:使用 Make 内置的 shell 函数
也可以直接用 Make 的 shell 函数在 Make 解析阶段执行 find 命令,提前收集所有 Java 文件:
# 提前收集所有Java源文件 JAVA_FILES = $(shell find ./source -type f -name "*.java") all: $(JAVA_FILES) mkdir -p target javac -d target $(JAVA_FILES)
该方案的特点是 Make 读取 Makefile 时就执行一次 find 命令,后续新增 Java 文件需要重新运行 make 才能识别,适合绝大多数常规开发场景。
优化说明
原命令中 find ./source/* | grep .java 可以直接替换为 find ./source -type f -name "*.java",无需额外 grep 过滤,写法更简洁、执行效率也更高。
内容的提问来源于stack exchange,提问作者user6697988
相关产品推荐
相关产品推荐

