【问题标题】:Error: no source files when using command substitution [duplicate]错误:使用命令替换时没有源文件[重复]
【发布时间】:2021-09-23 02:12:35
【问题描述】:

我有以下代码:

all: ./source/Listener.java ./source/ServerThread.java ./source/TestClient.java 
    javac -d target $(find ./source/* | grep .java)

当我运行 Make 时,我得到了这个输出

javac -d target
error: no source files
Makefile:2: recipe for target 'all' failed
make: *** [all] Error 2

当我在 bash 中运行 javac 命令时,它编译得很好。此外,当我运行“查找”部分时,我会得到一个我想要的文件列表。另外,第 1 行的文件路径都是准确的。

有什么建议吗?

(我必须使用查找功能,因为使用的文件很多,并且随着时间的推移而增加。我将其修剪为3,但仍然存在错误)

【问题讨论】:

  • 你想在你的“all”目标中执行哪个命令?
  • 将配方中的$(find ...) 替换为$$(find ...) 以逃避make 扩展。正如您所写,make 扩展了一个名为 find ... .java 的 make 变量,该变量显然不存在。
  • @RenaudPacalet 成功了,非常感谢!

标签: bash makefile javac


【解决方案1】:

正如 RenaudPacalet 所说,我必须在第二行前面多加一个 $。

【讨论】:

  • 首先在规则中使用find 是相当可疑的。如果这就是您的意思,可能使用javac -d target $$(find ./source/ -name '*.java'),或者您可能只是指javac -d target ./source/*.java,而无需递归到子目录。但更好的办法是在 Makefile 中声明显式依赖项并让 make 找出要编译的内容;这就是它的用途。
【解决方案2】:

如果您想在 Makefile 中执行 shell 命令,请使用以下语法:$(shell ...)

警告:

  • 默认的shell是sh(使用SHELL宏定义来改变它)
    • 示例:SHELL=/bin/bash
  • 美元 ($) 符号在 Makefile 和 bash 脚本中是特殊的(如果你想在 shell 脚本中使用它,请用双美元分隔:$$)。
    • 示例:$(shell X=a_value; echo $$a_value)
    • 如果要分shell的当前进程:$(shell echo $$$$)...丑,不行吗?
  • 你真的想调用shell吗?它不是便携式的。假设它。

如果您搜索源文件或其他任何内容,请使用 wildcard 内部 make 函数。

例子:

all: x.class y.class z.class

x.class: a.java dir_b/b.java dir_c/c.java
    @echo "$$^=$^="
    @echo "not portable command ..." $(shell find . -name "*.java")

# Better with deps in target definition
SRCS=$(shell find . -name "*.java")
y.class: $(SRCS)
    @echo x_my_command $^

# Really better (portable)
SRCS=$(wildcard */*.java *.java)
z.class: $(SRCS)
    @echo y_my_command $^

输出:

$^=a.java dir_b/b.java dir_c/c.java=
not portable command ... ./dir_b/b.java ./dir_c/c.java ./a.java
x_my_command dir_b/b.java dir_c/c.java a.java
y_my_command dir_b/b.java dir_c/c.java a.java

【讨论】:

  • 不需要在配方中使用 make shell 函数。食谱已经是 shell 脚本。 OP想要的是在配方中使用shell命令,这没什么奇怪的,这绝对是正常的。并且无需将默认 shell 更改为bash 即可使用find。在 OP 的 Makefile 中有几件事可以改进(find -name 而不是 find | grepsource/%.class: target/%.java 模式规则......)但它们与关于配方扩展的问题无关。
  • 我想变得更强壮:你应该永远在食谱中使用$(shell ...)。我们绝对不建议人们在回答问题时这样做。
  • @Renaud Pacalet、@MadScientist:我总是使用$ (shell ...) 拨打外部电话。明确地看到与内置函数的差异一直是必不可少的。我遇到过用户调用名称为join、`findstring` 或error 的标准或非标准命令的情况。显然,我完全可以理解错误,但我从来没有遇到过使用$ (shell ...)的问题
猜你喜欢
  • 1970-01-01
  • 2016-07-20
  • 2012-02-19
  • 2017-04-01
  • 2014-01-03
  • 2014-12-28
  • 1970-01-01
  • 1970-01-01
  • 2021-05-22
相关资源
最近更新 更多