来自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
答案 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