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

时间:2019-04-17 06:32:46

标签: makefile gnu

来自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 \
  $?

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

@MadScientist

2 个答案:

答案 0 :(得分:1)

首先,您的wildcard无法正常工作。 GNU make仅使用基本的外壳glob,这意味着它无法理解**这样的高级glob,意思是“搜索所有子目录”。其次,%根本不是shell的globbing字符,因此您只在寻找字面名为%.java的文件。

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

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

接下来,要创建javaClasses内容,您真的不想使用subst,因为它会替换所有可能产生错误匹配的地方(例如,$(subst .x,.y,foo.xbar)会产生{{1} },这可能不是您想要的。

这样的事情更容易理解:

foo.ybar

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

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

同样,您需要一个javaClasses := $(patsubst src/java/%.java,$(tempdir)/java/classes/%.class,$(javaSources)) 目标或类似目标,具体取决于所有输出。

答案 1 :(得分:0)

作为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