适用于JNI应用程序的可移植Makefile

时间:2017-05-29 09:38:05

标签: java c makefile java-native-interface

我有一个带有C JNI后端的Java应用程序,我想分发。分发Java部分非常简单 - 这正是jars和JVM的用途。分发预编译的C代码并不容易,我想我必须要求用户自己构建本机库。

目前,我使用ant构建Java代码,make构建C代码。问题是我在我的Makefile中硬编码jni.hjni_md.h的位置,这远远不可移植。我在万维网上找到了尽可能多的JNI示例,并且所有这些示例都在某处有一条硬编码路径。如果它是除JNI以外的任何包,我可以愉快地使用pkg-config之类的东西来获得正确的包含标志,但据我所知,JNI不提供任何此类功能。

问题:如何编写可移植 makefile,它将在任何*系统中找到JNI标头并编译我的C本机代码?

供参考,以下是我考虑过的几个选项:

  • 我可以使用CMake的FindJNI功能,但我不愿意,因为C代码不是那么复杂而且CMake会有点过分(另外还有一些额外的功能)对用户的依赖)。

  • 我希望设置JAVA_HOME环境变量,我不希望总是这样,因为(至少在Ubuntu中)它没有设置安装Java时的默认值。

  • 我可以使用locatefind手动查找文件并将包含标志拼接在一起,但这感觉相当骇人听闻。

*我最感兴趣的是Windows,OSX和主流的Ubuntu版本以及任何合理的现代版Java。

1 个答案:

答案 0 :(得分:0)

如果它足够便携,您可以依赖 GNU make (至少在大多数平台上都可以使用),您可以使用JAVA_HOME并尝试确定它如果不是这样设置的话,请自己:

ifeq ($(JAVA_HOME),)
ifeq ($(OS),Windows_NT)
which = $(shell where $1)
else
which = $(shell which $1)
endif
JAVAC ?= $(realpath $(call which,javac))
JAVA_HOME = $(abspath $(dir $(JAVAC))..)
endif

ifneq ($(JAVA_HOME),)
JNI_INCLUDEDIR ?= $(JAVA_HOME)/include
endif

ifeq ($(JNI_INCLUDEDIR),)
$(error could not determine JNI include dir, try specifying either \
    JAVA_HOME or JNI_INCLUDEDIR)
endif

TARGETTRIPLET := $(shell $(CC) -dumpmachine)
ifeq ($(JNI_PLATFORM),)
ifeq ($(findstring mingw,$(TARGETTRIPLET)),mingw)
JNI_PLATFORM:= win32
else
ifeq ($(findstring linux,$(TARGETTRIPLET)),linux)
JNI_PLATFORM:= linux
# add more checks here
endif
endif
endif

JNI_PLATFORMINCLUDEDIR ?= $(JNI_INCLUDEDIR)/$(JNI_PLATFORM)

$(info JAVA_HOME: $(JAVA_HOME))
$(info JNI_INCLUDEDIR: $(JNI_INCLUDEDIR))
$(info JNI_PLATFORMINCLUDEDIR: $(JNI_PLATFORMINCLUDEDIR))

all:
    @:

.PHONY: all

示例输出:

> make
JAVA_HOME: /usr/lib/jvm/java-6-openjdk-amd64
JNI_INCLUDEDIR: /usr/lib/jvm/java-6-openjdk-amd64/include
JNI_PLATFORMINCLUDEDIR: /usr/lib/jvm/java-6-openjdk-amd64/include/linux

> make JAVA_HOME=/foo/bar
JAVA_HOME: /foo/bar
JNI_INCLUDEDIR: /foo/bar/include
JNI_PLATFORMINCLUDEDIR: /foo/bar/include/linux

> make JNI_INCLUDEDIR=/foo/bar
JAVA_HOME: /usr/lib/jvm/java-6-openjdk-amd64
JNI_INCLUDEDIR: /foo/bar
JNI_PLATFORMINCLUDEDIR: /foo/bar/linux

> make JNI_PLATFORM=amigaos
JAVA_HOME: /usr/lib/jvm/java-6-openjdk-amd64
JNI_INCLUDEDIR: /usr/lib/jvm/java-6-openjdk-amd64/include
JNI_PLATFORMINCLUDEDIR: /usr/lib/jvm/java-6-openjdk-amd64/include/amigaos