首页 > 解决方案 > 添加规则以在缺少时生成特定标头

问题描述

我有一个将 Java 和 C++ 与 JNI 混合的 Makefile,我想在需要时自动生成 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 标头不对应的文件。

标签: makefilejava-native-interface

解决方案


所以,你的$(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/,,$@)))

推荐阅读