008b62f1ae
FossilOrigin-Name: 7927c42410ba0d5fc8e6e08caaa5cbaaeb359869f17d1afaa082f1aa47fdb2fc
477 lines
15 KiB
Makefile
477 lines
15 KiB
Makefile
# Quick-and-dirty makefile to bootstrap the sqlite3-jni project. This
|
|
# build assumes a Linux-like system.
|
|
default: all
|
|
|
|
JAVA_HOME ?= $(HOME)/jdk/current
|
|
# e.g. /usr/lib/jvm/default-javajava-19-openjdk-amd64
|
|
JDK_HOME ?= $(JAVA_HOME)
|
|
# ^^^ JDK_HOME is not as widely used as JAVA_HOME
|
|
bin.jar := $(JDK_HOME)/bin/jar
|
|
bin.java := $(JDK_HOME)/bin/java
|
|
bin.javac := $(JDK_HOME)/bin/javac
|
|
bin.javadoc := $(JDK_HOME)/bin/javadoc
|
|
ifeq (,$(wildcard $(JDK_HOME)))
|
|
$(error set JDK_HOME to the top-most dir of your JDK installation.)
|
|
endif
|
|
MAKEFILE := $(lastword $(MAKEFILE_LIST))
|
|
$(MAKEFILE):
|
|
|
|
package.jar := sqlite3-jni.jar
|
|
|
|
dir.top := ../..
|
|
dir.tool := ../../tool
|
|
dir.jni := $(patsubst %/,%,$(dir $(MAKEFILE)))
|
|
dir.src := $(dir.jni)/src
|
|
dir.src.c := $(dir.src)/c
|
|
dir.bld := $(dir.jni)/bld
|
|
dir.bld.c := $(dir.bld)
|
|
dir.src.jni := $(dir.src)/org/sqlite/jni
|
|
dir.src.fts5 := $(dir.src.jni)/fts5
|
|
dir.tests := $(dir.src)/tests
|
|
mkdir ?= mkdir -p
|
|
$(dir.bld.c):
|
|
$(mkdir) $@
|
|
|
|
javac.flags ?= -Xlint:unchecked -Xlint:deprecation
|
|
java.flags ?=
|
|
jnicheck ?= 1
|
|
ifeq (1,$(jnicheck))
|
|
java.flags += -Xcheck:jni
|
|
endif
|
|
|
|
classpath := $(dir.src)
|
|
CLEAN_FILES := $(package.jar)
|
|
DISTCLEAN_FILES := $(dir.jni)/*~ $(dir.src.c)/*~ $(dir.src.jni)/*~
|
|
|
|
sqlite3-jni.h := $(dir.src.c)/sqlite3-jni.h
|
|
.NOTPARALLEL: $(sqlite3-jni.h)
|
|
SQLite3Jni.java := src/org/sqlite/jni/SQLite3Jni.java
|
|
SQLTester.java := src/org/sqlite/jni/SQLTester.java
|
|
SQLite3Jni.class := $(SQLite3Jni.java:.java=.class)
|
|
SQLTester.class := $(SQLTester.java:.java=.class)
|
|
|
|
########################################################################
|
|
# The future of FTS5 customization in this API is as yet unclear.
|
|
# The pieces are all in place, and are all thin proxies so not much
|
|
# complexity, but some semantic changes were required in porting
|
|
# which are largely untested.
|
|
#
|
|
# Reminder: this flag influences the contents of $(sqlite3-jni.h),
|
|
# which is checked in. Please do not check in changes to that file in
|
|
# which the fts5 APIs have been stripped unless that feature is
|
|
# intended to be stripped for good.
|
|
enable.fts5 ?= 1
|
|
|
|
ifeq (,$(wildcard $(dir.tests)/*))
|
|
enable.tester := 0
|
|
else
|
|
enable.tester := 1
|
|
endif
|
|
|
|
# bin.version-info = binary to output various sqlite3 version info
|
|
# building the distribution zip file.
|
|
bin.version-info := $(dir.top)/version-info
|
|
.NOTPARALLEL: $(bin.version-info)
|
|
$(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
|
|
$(MAKE) -C $(dir.top) version-info
|
|
|
|
# Be explicit about which Java files to compile so that we can work on
|
|
# in-progress files without requiring them to be in a compilable statae.
|
|
JAVA_FILES.main := $(patsubst %,$(dir.src.jni)/%,\
|
|
annotation/Canonical.java \
|
|
annotation/NotNull.java \
|
|
annotation/Nullable.java \
|
|
AbstractCollationCallback.java \
|
|
AggregateFunction.java \
|
|
AuthorizerCallback.java \
|
|
AutoExtensionCallback.java \
|
|
BusyHandlerCallback.java \
|
|
CollationCallback.java \
|
|
CollationNeededCallback.java \
|
|
CommitHookCallback.java \
|
|
ConfigLogCallback.java \
|
|
ConfigSqllogCallback.java \
|
|
NativePointerHolder.java \
|
|
OutputPointer.java \
|
|
PrepareMultiCallback.java \
|
|
PreupdateHookCallback.java \
|
|
ProgressHandlerCallback.java \
|
|
ResultCode.java \
|
|
RollbackHookCallback.java \
|
|
ScalarFunction.java \
|
|
SQLFunction.java \
|
|
CallbackProxy.java \
|
|
SQLite3Jni.java \
|
|
TableColumnMetadata.java \
|
|
TraceV2Callback.java \
|
|
UpdateHookCallback.java \
|
|
WindowFunction.java \
|
|
XDestroyCallback.java \
|
|
sqlite3.java \
|
|
sqlite3_context.java \
|
|
sqlite3_stmt.java \
|
|
sqlite3_value.java \
|
|
)
|
|
JAVA_FILES.unittest := $(patsubst %,$(dir.src.jni)/%,\
|
|
Tester1.java \
|
|
)
|
|
ifeq (1,$(enable.fts5))
|
|
JAVA_FILES.unittest += $(patsubst %,$(dir.src.jni)/%,\
|
|
TesterFts5.java \
|
|
)
|
|
JAVA_FILES.main += $(patsubst %,$(dir.src.fts5)/%,\
|
|
fts5_api.java \
|
|
fts5_extension_function.java \
|
|
fts5_tokenizer.java \
|
|
Fts5.java \
|
|
Fts5Context.java \
|
|
Fts5ExtensionApi.java \
|
|
Fts5PhraseIter.java \
|
|
Fts5Tokenizer.java \
|
|
XTokenizeCallback.java \
|
|
)
|
|
endif
|
|
JAVA_FILES.tester := $(SQLTester.java)
|
|
JAVA_FILES.package.info := \
|
|
$(dir.src.jni)/package-info.java \
|
|
$(dir.src.jni)/annotation/package-info.java
|
|
|
|
CLASS_FILES.main := $(JAVA_FILES.main:.java=.class)
|
|
CLASS_FILES.unittest := $(JAVA_FILES.unittest:.java=.class)
|
|
CLASS_FILES.tester := $(JAVA_FILES.tester:.java=.class)
|
|
|
|
JAVA_FILES += $(JAVA_FILES.main) $(JAVA_FILES.unittest)
|
|
ifeq (1,$(enable.tester))
|
|
JAVA_FILES += $(JAVA_FILES.tester)
|
|
endif
|
|
|
|
CLASS_FILES :=
|
|
define CLASSFILE_DEPS
|
|
all: $(1).class
|
|
CLASS_FILES += $(1).class
|
|
endef
|
|
$(foreach B,$(basename \
|
|
$(JAVA_FILES.main) $(JAVA_FILES.unittest) $(JAVA_FILES.tester)),\
|
|
$(eval $(call CLASSFILE_DEPS,$(B))))
|
|
$(CLASS_FILES): $(JAVA_FILES) $(MAKEFILE)
|
|
$(bin.javac) $(javac.flags) -h $(dir.bld.c) -cp $(classpath) $(JAVA_FILES)
|
|
|
|
#.PHONY: classfiles
|
|
|
|
########################################################################
|
|
# Set up sqlite3.c and sqlite3.h...
|
|
#
|
|
# To build with SEE (https://sqlite.org/see), either put sqlite3-see.c
|
|
# in the top of this build tree or pass
|
|
# sqlite3.c=PATH_TO_sqlite3-see.c to the build. Note that only
|
|
# encryption modules with no 3rd-party dependencies will currently
|
|
# work here: AES256-OFB, AES128-OFB, and AES128-CCM. Not
|
|
# coincidentally, those 3 modules are included in the sqlite3-see.c
|
|
# bundle.
|
|
#
|
|
# A custom sqlite3.c must not have any spaces in its name.
|
|
# $(sqlite3.canonical.c) must point to the sqlite3.c in
|
|
# the sqlite3 canonical source tree, as that source file
|
|
# is required for certain utility and test code.
|
|
sqlite3.canonical.c := $(firstword $(wildcard $(dir.src.c)/sqlite3.c) $(dir.top)/sqlite3.c)
|
|
sqlite3.canonical.h := $(firstword $(wildcard $(dir.src.c)/sqlite3.h) $(dir.top)/sqlite3.h)
|
|
sqlite3.c := $(sqlite3.canonical.c)
|
|
sqlite3.h := $(sqlite3.canonical.h)
|
|
#ifeq (,$(shell grep sqlite3_activate_see $(sqlite3.c) 2>/dev/null))
|
|
# SQLITE_C_IS_SEE := 0
|
|
#else
|
|
# SQLITE_C_IS_SEE := 1
|
|
# $(info This is an SEE build.)
|
|
#endif
|
|
|
|
.NOTPARALLEL: $(sqlite3.h)
|
|
$(sqlite3.h):
|
|
$(MAKE) -C $(dir.top) sqlite3.c
|
|
$(sqlite3.c): $(sqlite3.h)
|
|
|
|
opt.threadsafe ?= 1
|
|
opt.fatal-oom ?= 1
|
|
opt.debug ?= 1
|
|
opt.metrics ?= 1
|
|
SQLITE_OPT = \
|
|
-DSQLITE_ENABLE_RTREE \
|
|
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
|
|
-DSQLITE_ENABLE_STMTVTAB \
|
|
-DSQLITE_ENABLE_DBPAGE_VTAB \
|
|
-DSQLITE_ENABLE_DBSTAT_VTAB \
|
|
-DSQLITE_ENABLE_BYTECODE_VTAB \
|
|
-DSQLITE_ENABLE_OFFSET_SQL_FUNC \
|
|
-DSQLITE_ENABLE_PREUPDATE_HOOK \
|
|
-DSQLITE_ENABLE_SQLLOG \
|
|
-DSQLITE_OMIT_LOAD_EXTENSION \
|
|
-DSQLITE_OMIT_DEPRECATED \
|
|
-DSQLITE_OMIT_SHARED_CACHE \
|
|
-DSQLITE_THREADSAFE=$(opt.threadsafe) \
|
|
-DSQLITE_TEMP_STORE=2 \
|
|
-DSQLITE_USE_URI=1 \
|
|
-DSQLITE_C=$(sqlite3.c) \
|
|
-DSQLITE_JNI_FATAL_OOM=$(opt.fatal-oom) \
|
|
-DSQLITE_JNI_ENABLE_METRICS=$(opt.metrics)
|
|
|
|
ifeq (1,$(opt.debug))
|
|
SQLITE_OPT += -DSQLITE_DEBUG -g -DDEBUG -UNDEBUG
|
|
else
|
|
SQLITE_OPT += -O2
|
|
endif
|
|
|
|
ifeq (1,$(enable.fts5))
|
|
SQLITE_OPT += -DSQLITE_ENABLE_FTS5
|
|
endif
|
|
|
|
sqlite3-jni.c := $(dir.src.c)/sqlite3-jni.c
|
|
sqlite3-jni.o := $(dir.bld.c)/sqlite3-jni.o
|
|
sqlite3-jni.h := $(dir.src.c)/sqlite3-jni.h
|
|
package.dll := $(dir.bld.c)/libsqlite3-jni.so
|
|
# All javac-generated .h files must be listed in $(sqlite3-jni.h.in):
|
|
sqlite3-jni.h.in :=
|
|
# $(java.with.jni) lists all Java files which contain JNI decls:
|
|
java.with.jni :=
|
|
define ADD_JNI_H
|
|
sqlite3-jni.h.in += $$(dir.bld.c)/org_sqlite_jni$(3)_$(2).h
|
|
java.with.jni += $(1)/$(2).java
|
|
$$(dir.bld.c)/org_sqlite_jni$(3)_$(2).h: $(1)/$(2).java
|
|
endef
|
|
# Invoke ADD_JNI_H once for each Java file which includes JNI
|
|
# declarations:
|
|
$(eval $(call ADD_JNI_H,$(dir.src.jni),SQLite3Jni,))
|
|
$(eval $(call ADD_JNI_H,$(dir.src.jni),SQLTester,))
|
|
ifeq (1,$(enable.fts5))
|
|
$(eval $(call ADD_JNI_H,$(dir.src.fts5),Fts5ExtensionApi,_fts5))
|
|
$(eval $(call ADD_JNI_H,$(dir.src.fts5),fts5_api,_fts5))
|
|
$(eval $(call ADD_JNI_H,$(dir.src.fts5),fts5_tokenizer,_fts5))
|
|
endif
|
|
$(sqlite3-jni.h.in): $(dir.bld.c)
|
|
|
|
#package.dll.cfiles :=
|
|
package.dll.cflags = \
|
|
-fPIC \
|
|
-I. \
|
|
-I$(dir $(sqlite3.h)) \
|
|
-I$(dir.src.c) \
|
|
-I$(JDK_HOME)/include \
|
|
$(patsubst %,-I%,$(patsubst %.h,,$(wildcard $(JDK_HOME)/include/*))) \
|
|
-Wall
|
|
# The gross $(patsubst...) above is to include the platform-specific
|
|
# subdir which lives under $(JDK_HOME)/include and is a required
|
|
# include path for client-level code.
|
|
#
|
|
# Using (-Wall -Wextra) triggers an untennable number of
|
|
# gcc warnings from sqlite3.c for mundane things like
|
|
# unused parameters.
|
|
########################################################################
|
|
ifeq (1,$(enable.tester))
|
|
package.dll.cflags += -DSQLITE_JNI_ENABLE_SQLTester
|
|
endif
|
|
|
|
$(sqlite3-jni.h): $(sqlite3-jni.h.in) $(MAKEFILE)
|
|
@cat $(sqlite3-jni.h.in) > $@.tmp
|
|
@if cmp $@ $@.tmp >/dev/null; then \
|
|
rm -f $@.tmp; \
|
|
echo "$@ not modified"; \
|
|
else \
|
|
mv $@.tmp $@; \
|
|
echo "Updated $@"; \
|
|
fi
|
|
@if [ x1 != x$(enable.fts5) ]; then \
|
|
echo "*** REMINDER:"; \
|
|
echo "*** enable.fts5=0, so please do not check in changes to $@."; \
|
|
fi
|
|
|
|
$(package.dll): $(sqlite3-jni.h) $(sqlite3.c) $(sqlite3.h)
|
|
$(package.dll): $(sqlite3-jni.c) $(MAKEFILE)
|
|
$(CC) $(package.dll.cflags) $(SQLITE_OPT) \
|
|
$(sqlite3-jni.c) -shared -o $@
|
|
all: $(package.dll)
|
|
|
|
.PHONY: test test-one
|
|
test.flags ?=
|
|
test.main.flags = -ea -Djava.library.path=$(dir.bld.c) \
|
|
$(java.flags) -cp $(classpath) \
|
|
org.sqlite.jni.Tester1
|
|
test.deps := $(CLASS_FILES) $(package.dll)
|
|
test-one: $(test.deps)
|
|
$(bin.java) $(test.main.flags) $(test.flags)
|
|
test-sqllog: $(test.deps)
|
|
@echo "Testing with -sqllog..."
|
|
$(bin.java) $(test.main.flags) -sqllog
|
|
test-mt: $(test.deps)
|
|
@echo "Testing in multi-threaded mode:";
|
|
$(bin.java) $(test.main.flags) -t 7 -r 50 -shuffle $(test.flags)
|
|
|
|
test: test-one test-mt
|
|
tests: test test-sqllog
|
|
|
|
tester.scripts := $(sort $(wildcard $(dir.src)/tests/*.test))
|
|
tester.flags ?= # --verbose
|
|
.PHONY: tester tester-local tester-ext
|
|
ifeq (1,$(enable.tester))
|
|
tester-local: $(CLASS_FILES.tester) $(package.dll)
|
|
$(bin.java) -ea -Djava.library.path=$(dir.bld.c) \
|
|
$(java.flags) -cp $(classpath) \
|
|
org.sqlite.jni.SQLTester $(tester.flags) $(tester.scripts)
|
|
tester: tester-local
|
|
else
|
|
tester:
|
|
@echo "SQLTester support is disabled."
|
|
endif
|
|
|
|
tester.extdir.default := $(dir.tests)/ext
|
|
tester.extdir ?= $(tester.extdir.default)
|
|
tester.extern-scripts := $(wildcard $(tester.extdir)/*.test)
|
|
ifneq (,$(tester.extern-scripts))
|
|
tester-ext:
|
|
$(bin.java) -ea -Djava.library.path=$(dir.bld.c) \
|
|
$(java.flags) -cp $(classpath) \
|
|
org.sqlite.jni.SQLTester $(tester.flags) $(tester.extern-scripts)
|
|
else
|
|
tester-ext:
|
|
@echo "******************************************************"; \
|
|
echo "*** Include the out-of-tree test suite in the 'tester'"; \
|
|
echo "*** target by either symlinking its directory to"; \
|
|
echo "*** $(tester.extdir.default) or passing it to make"; \
|
|
echo "*** as tester.extdir=/path/to/that/dir."; \
|
|
echo "******************************************************";
|
|
endif
|
|
|
|
tester-ext: tester-local
|
|
tester: tester-ext
|
|
tests: tester
|
|
########################################################################
|
|
# Build each SQLITE_THREADMODE variant and run all tests against them.
|
|
multitest: clean
|
|
define MULTIOPT
|
|
multitest: multitest-$(1)
|
|
multitest-$(1):
|
|
$$(MAKE) opt.debug=$$(opt.debug) $(patsubst %,opt.%,$(2)) \
|
|
tests clean enable.fts5=1
|
|
endef
|
|
|
|
$(eval $(call MULTIOPT,01,threadsafe=0 oom=1))
|
|
$(eval $(call MULTIOPT,00,threadsafe=0 oom=0))
|
|
$(eval $(call MULTIOPT,11,threadsafe=1 oom=1))
|
|
$(eval $(call MULTIOPT,10,threadsafe=1 oom=0))
|
|
$(eval $(call MULTIOPT,21,threadsafe=2 oom=1))
|
|
$(eval $(call MULTIOPT,20,threadsafe=2 oom=0))
|
|
|
|
|
|
########################################################################
|
|
# jar bundle...
|
|
package.jar.in := $(abspath $(dir.src)/jar.in)
|
|
CLEAN_FILES += $(package.jar.in)
|
|
JAVA_FILES.jar := $(JAVA_FILES.main) $(JAVA_FILES.unittest) $(JAVA_FILES.package.info)
|
|
CLASS_FILES.jar := $(filter-out %/package-info.class,$(JAVA_FILES.jar:.java=.class))
|
|
$(package.jar.in): $(package.dll) $(MAKEFILE)
|
|
ls -1 \
|
|
$(dir.src.jni)/*.java $(dir.src.jni)/*.class \
|
|
$(dir.src.jni)/annotation/*.java $(dir.src.jni)/annotation/*.class \
|
|
| sed -e 's,^$(dir.src)/,,' | sort > $@
|
|
|
|
$(package.jar): $(CLASS_FILES.jar) $(MAKEFILE) $(package.jar.in)
|
|
@rm -f $(dir.src)/c/*~ $(dir.src.jni)/*~
|
|
cd $(dir.src); $(bin.jar) -cfe ../$@ org.sqlite.jni.Tester1 @$(package.jar.in)
|
|
@ls -la $@
|
|
@echo "To use this jar you will need the -Djava.library.path=DIR/CONTAINING/libsqlite3-jni.so flag."
|
|
@echo "e.g. java -Djava.library.path=bld -jar $@"
|
|
|
|
jar: $(package.jar)
|
|
run-jar: $(package.jar) $(package.dll)
|
|
$(bin.java) -Djava.library.path=$(dir.bld) -jar $(package.jar) $(run-jar.flags)
|
|
|
|
########################################################################
|
|
# javadoc...
|
|
dir.doc := $(dir.jni)/javadoc
|
|
doc.index := $(dir.doc)/index.html
|
|
javadoc.exclude := -exclude org.sqlite.jni.fts5
|
|
# ^^^^ 2023-09-13: elide the fts5 parts from the public docs for
|
|
# the time being, as it's not clear where the Java bindings for
|
|
# those bits are going.
|
|
$(doc.index): $(JAVA_FILES.main) $(MAKEFILE)
|
|
@if [ -d $(dir.doc) ]; then rm -fr $(dir.doc)/*; fi
|
|
$(bin.javadoc) -cp $(classpath) -d $(dir.doc) -quiet \
|
|
-subpackages org.sqlite.jni $(javadoc.exclude)
|
|
@echo "javadoc output is in $@"
|
|
|
|
.PHONY: doc javadoc docserve
|
|
.FORCE: doc
|
|
doc: $(doc.index)
|
|
javadoc: $(doc.index)
|
|
# Force rebild of docs
|
|
redoc:
|
|
@rm -f $(doc.index)
|
|
@$(MAKE) doc
|
|
docserve: $(doc.index)
|
|
cd $(dir.doc) && althttpd -max-age 1 -page index.html
|
|
########################################################################
|
|
# Clean up...
|
|
CLEAN_FILES += $(dir.bld.c)/* \
|
|
$(dir.src.jni)/*.class \
|
|
$(dir.src.jni.tester)/*.class \
|
|
$(package.dll) \
|
|
hs_err_pid*.log
|
|
|
|
.PHONY: clean distclean
|
|
clean:
|
|
-rm -f $(CLEAN_FILES)
|
|
distclean: clean
|
|
-rm -f $(DISTCLEAN_FILES)
|
|
-rm -fr $(dir.bld.c) $(dir.doc)
|
|
|
|
########################################################################
|
|
# disttribution bundle rules...
|
|
|
|
ifeq (,$(filter snapshot,$(MAKECMDGOALS)))
|
|
dist-name-prefix := sqlite-jni
|
|
else
|
|
dist-name-prefix := sqlite-jni-snapshot-$(shell /usr/bin/date +%Y%m%d)
|
|
endif
|
|
dist-name := $(dist-name-prefix)-TEMP
|
|
|
|
|
|
dist-dir.top := $(dist-name)
|
|
dist-dir.src := $(dist-dir.top)/src
|
|
dist.top.extras := \
|
|
README.md
|
|
|
|
.PHONY: dist snapshot
|
|
|
|
dist: \
|
|
$(bin.version-info) $(sqlite3.canonical.c) \
|
|
$(package.jar) $(MAKEFILE)
|
|
@echo "Making end-user deliverables..."
|
|
@echo "****************************************************************************"; \
|
|
echo "*** WARNING: be sure to build this with JDK8 (javac 1.8) for compatibility."; \
|
|
echo "*** reasons!"; $$($(bin.javac) -version); \
|
|
echo "****************************************************************************"
|
|
@rm -fr $(dist-dir.top)
|
|
@mkdir -p $(dist-dir.src)
|
|
@cp -p $(dist.top.extras) $(dist-dir.top)/.
|
|
@cp -p jar-dist.make $(dist-dir.top)/Makefile
|
|
@cp -p $(dir.src.c)/*.[ch] $(dist-dir.src)/.
|
|
@cp -p $(sqlite3.canonical.c) $(sqlite3.canonical.h) $(dist-dir.src)/.
|
|
@set -e; \
|
|
vnum=$$($(bin.version-info) --download-version); \
|
|
vjar=$$($(bin.version-info) --version); \
|
|
vdir=$(dist-name-prefix)-$$vnum; \
|
|
arczip=$$vdir.zip; \
|
|
cp -p $(package.jar) $(dist-dir.top)/sqlite3-jni-$${vjar}.jar; \
|
|
echo "Making $$arczip ..."; \
|
|
rm -fr $$arczip $$vdir; \
|
|
mv $(dist-dir.top) $$vdir; \
|
|
zip -qr $$arczip $$vdir; \
|
|
rm -fr $$vdir; \
|
|
ls -la $$arczip; \
|
|
set +e; \
|
|
unzip -lv $$arczip || echo "Missing unzip app? Not fatal."
|
|
|
|
snapshot: dist
|
|
|
|
.PHONY: dist-clean
|
|
clean: dist-clean
|
|
dist-clean:
|
|
rm -fr $(dist-name) $(wildcard sqlite-jni-*.zip)
|