Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 用于JNI应用程序的可移植Makefile_Java_C_Makefile_Java Native Interface - Fatal编程技术网

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

Java 用于JNI应用程序的可移植Makefile,java,c,makefile,java-native-interface,Java,C,Makefile,Java Native Interface,我有一个Java应用程序,它有一个C JNI后端,我想分发。分发Java部分非常简单——这正是JAR和JVM的用途。分发预编译的C代码并不是那么容易,我想我将不得不要求用户自己构建本机库 目前,我正在使用ant构建Java代码,并使用make构建C代码。问题是我在Makefile中硬编码了jni.h和jni_md.h的位置,这是不可移植的。我在万维网上搜索了尽可能多的JNI示例,它们都有硬编码的路径。如果它是JNI以外的任何包,我可以很高兴地使用类似于pkg config的东西来获得正确的inc

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

目前,我正在使用
ant
构建Java代码,并使用
make
构建C代码。问题是我在Makefile中硬编码了
jni.h
jni_md.h
的位置,这是不可移植的。我在万维网上搜索了尽可能多的JNI示例,它们都有硬编码的路径。如果它是JNI以外的任何包,我可以很高兴地使用类似于
pkg config
的东西来获得正确的include标志,但据我所知,JNI不提供任何此类功能

问题:如何编写一个可移植的makefile,在任何*系统中查找JNI头并编译我的C本机代码

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

  • 我可以使用CMake的函数,但我不想使用,因为C代码没有那么复杂,CMake有点过火(加上对用户的额外依赖)

  • 我希望设置了
    JAVA\u HOME
    环境变量,但我并不希望总是这样,因为(至少在Ubuntu中)在安装JAVA时,它不是默认设置的

  • 我可以使用
    locate
    find
    手动查找文件并将include标志缝合在一起,但这感觉相当粗糙


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

如果它的便携性足以让您依赖GNU make(至少,这在大多数平台上都可用),您可以使用
Java\u 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
示例输出:

>制作
JAVA_HOME:/usr/lib/jvm/JAVA-6-openjdk-amd64
JNI_INCLUDEDIR:/usr/lib/jvm/java-6-openjdk-amd64/include
JNI_平台包含目录:/usr/lib/jvm/java-6-openjdk-amd64/include/linux
>使JAVA_成为HOME=/foo/bar
JAVA\u HOME:/foo/bar
JNI_INCLUDEDIR:/foo/bar/include
JNI_PLATFORMINCLUDEDIR:/foo/bar/include/linux
>使JNI_INCLUDEDIR=/foo/bar
JAVA_HOME:/usr/lib/jvm/JAVA-6-openjdk-amd64
JNI_INCLUDEDIR:/foo/bar
JNI_平台包含目录:/foo/bar/linux
>使JNI_平台=amigaos
JAVA_HOME:/usr/lib/jvm/JAVA-6-openjdk-amd64
JNI_INCLUDEDIR:/usr/lib/jvm/java-6-openjdk-amd64/include
JNI_平台包含目录:/usr/lib/jvm/java-6-openjdk-amd64/include/amigaos

在您的软件包中分发正确版本的
jni.h
怎么样?@KinCheung感谢您的评论。
jni.h
是否依赖于安装的特定Java版本?在我的系统中,
jni.h
位于
/usr/lib/jvm/java-8-openjdk-amd64
中,因此,AFAIK仅仅抓住
jni.h
不一定能在使用除openjdk 8以外的任何java的系统中工作。不是这样吗?太棒了,谢谢@FelixPalmen。jni_md.h怎么样?这通常位于
${JNI_INCLUDEDIR}
的依赖于操作系统的子文件夹中。有没有办法在
${JNI_INCLUDEDIR}
中查找和包含子文件夹?这有点棘手,最好的办法是根据
$(CC)-dumpmachine
的输出来确定它。。。我将添加一个简单的示例,看起来不错,它在我的Ubuntu 16.04中做到了这一点。我将在Windows机器上试用,如果它能工作,我会将答案标记为正确。记录在案:我试过了,它确实按预期工作。回答接受,谢谢!