我有一个带有C JNI后端的Java应用程序,我想分发。分发Java部分非常简单 - 这正是jars和JVM的用途。分发预编译的C代码并不容易,我想我必须要求用户自己构建本机库。
目前,我使用ant
构建Java代码,make
构建C代码。问题是我在我的Makefile中硬编码jni.h
和jni_md.h
的位置,这远远不可移植。我在万维网上找到了尽可能多的JNI示例,并且所有这些示例都在某处有一条硬编码路径。如果它是除JNI以外的任何包,我可以愉快地使用pkg-config
之类的东西来获得正确的包含标志,但据我所知,JNI不提供任何此类功能。
问题:如何编写可移植 makefile,它将在任何*系统中找到JNI标头并编译我的C本机代码?
供参考,以下是我考虑过的几个选项:
我可以使用CMake的FindJNI功能,但我不愿意,因为C代码不是那么复杂而且CMake会有点过分(另外还有一些额外的功能)对用户的依赖)。
我希望设置JAVA_HOME
环境变量,我不希望总是这样,因为(至少在Ubuntu中)它没有设置安装Java时的默认值。
我可以使用locate
或find
手动查找文件并将包含标志拼接在一起,但这感觉相当骇人听闻。
*我最感兴趣的是Windows,OSX和主流的Ubuntu版本以及任何合理的现代版Java。
答案 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