我有一个Makefile,它将Java和C ++与JNI混合在一起,我想在需要时自动生成JNI标头。
当前,我有以下内容:
$(OBJDIR)/org_some_package_%.cpp: $(INCDIR)/jni/org_some_package_%.h
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
@mkdir -p $(OBJDIR)
$(CC) -c -o $@ $(CFLAGS) \
-I$(INCDIR) -I../build/include -I"$(JAVA_HOME)/include" -I"$(JAVA_HOME)/include/linux" \
-MD -MF $(patsubst %.o, %.d, $@) $<
.SECONDEXPANSION:
$(INCDIR)/jni/%.h: $(JAVA_TEST_BIN)/$$(subst _,/,%).class
@mkdir -p $(INCDIR)/jni
$(JAVAH) -d inc/jni -classpath TestJNI/bin/tests:$(JUNIT_JAR):$(HAMCREST_JAR) $(basename $(subst _,.,$(subst $(INCDIR)/jni/,,$@)))
问题在于,当需要.o
文件时,永远不会应用第一个规则:
$(OBJDIR)/org_some_package_%.cpp: $(INCDIR)/jni/org_some_package_%.h
如果我用一个特定的规则替换该规则(通过用类名替换%
),它将起作用。
如何使该通用规则起作用?
我不想这样做:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(INCDIR)/jni/%.h
...因为我可能有.cpp
个与JNI标头不对应的文件。
答案 0 :(得分:1)
您不能使用模式创建简单的先决条件。没有任何配方的特征码规则不会定义先决条件,它会取消先前存在的特征码规则。 GNU make manual说:
您可以通过定义具有相同目标和先决条件但没有配方的模式规则来取消内置的隐式规则。
创建先决条件的唯一方法是使其明确。
答案 1 :(得分:1)
因此,您的$(INCDIR)/jni/a_b_c.h
依赖于$(JAVA_TEST_BIN)/a/b/c.class
?您将必须使用高级制作功能。我假设*.class
下的所有$(JAVA_TEST_BIN)
文件都对应一个内置的头文件。这(未经测试)应该可以解决您在问题中显示的内容:
CLASSES := $(patsubst $(JAVA_TEST_BIN)/%.class,%,$(shell find $(JAVA_TEST_BIN) -type f -name '*.class'))
BUILT_HEADERS :=
# $(1): class
define BUILD_HEADER_rule
header := $$(INCDIR)/jni/$$(subst /,_,$(1)).h
$$(header): $$(JAVA_TEST_BIN)/$(1).class
BUILT_HEADERS += $$(header)
endef
$(foreach c,$(CLASSES),$(eval $(call BUILD_HEADER_rule,$(c))))
$(BUILT_HEADERS):
@mkdir -p $(dir $@)
$(JAVAH) -d inc/jni -classpath TestJNI/bin/tests:$(JUNIT_JAR):$(HAMCREST_JAR) $(basename $(subst _,.,$(subst $(INCDIR)/jni/,,$@)))