GNU 制作 |如何在源代码层次结构和编译器输出 h-hy 之间创建依赖关系?

GNU Make | How to create dependency between source code hierarchy and compiler output h-hy?

来自Makefile的一些代码:

tempDir := ...
javaSources := $(wildcard src/java/**/%.java)
javaClasses := $(subst src/java, $(tempDir)/java/classes, $(subst .java,.class, $(javaSources)))

$(javaClasses): $(javaSources)
  mkdir -p $(tempDir)/java/classes || true
  javac \
    -d  $(tempDir)/java/classes \
    -cp $(tempDir)/java/classes \
  $?

如何创建模式规则(如 )以保留进/出顺序?

@MadScientist

首先,您的 wildcard 无法正常工作。 GNU make 只使用基本的 shell 通配符,这意味着它无法理解像 ** 意思是 "search all subdirectories" 这样的高级通配符。其次,% 根本不是 shell 通配符,因此您只是在查找字面上命名为 %.java.

的文件

相反,您可能想要这样的东西:

javaSources := $(shell find src/java -name '*.java')

下一步,创建 javaClasses 你真的不想使用 subst 的内容,因为它会替换所有可能给出错误匹配的地方(例如,$(subst .x,.y,foo.xbar) 会产生 foo.ybar 这可能不是你想要的)。

像这样比较容易理解:

javaClasses := $(patsubst src/java/%.java,$(tempdir)/java/classes/%.class,$(javaSources))

最后,您重复了与上一个问题完全相同的错误,您在上一个问题中尝试列出同一规则中的所有目标和所有先决条件。正如我对那个问题所说的那样,那是不对的。

答案与上一个问题完全相同:您应该编写一个模式规则来描述如何从一个单一来源构建一个单一目标文件.

同样,您需要一个 all 目标或类似目标,这取决于所有输出。

作为 MadScientist 答案的补充,您可能应该使用如下模式规则:

$(tempDir)/java/classes/%.class: src/java/%.java
    mkdir -p $(dir $@)
    javac -d $(dir $@) -cp $(dir $@) $<

(不确定在这种情况下 -cp 应该是什么,这取决于您的具体项目)。正如 MadScientist 也建议的那样,您将需要:

.PHONY: all
all: $(javaClasses)

这样你就可以调用make all编译所有需要的源文件。如果您希望 all 成为默认目标,请将它放在任何其他显式目标之前(如果您只是调用 make,目标 make 就会选择),或者使用 .DEFAULT_GOAL 特殊变量:

.DEFAULT_GOAL := all