| # 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.capi := $(dir.src.jni)/capi |
| 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 ?= |
| javac.flags += -encoding utf8 |
| # -------------^^^^^^^^^^^^^^ required for Windows builds |
| 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) |
| CApi.java := $(dir.src.capi)/CApi.java |
| SQLTester.java := $(dir.src.capi)/SQLTester.java |
| CApi.class := $(CApi.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/%,\ |
| Experimental.java \ |
| NotNull.java \ |
| Nullable.java \ |
| ) $(patsubst %,$(dir.src.capi)/%,\ |
| 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 \ |
| CApi.java \ |
| TableColumnMetadata.java \ |
| TraceV2Callback.java \ |
| UpdateHookCallback.java \ |
| ValueHolder.java \ |
| WindowFunction.java \ |
| XDestroyCallback.java \ |
| sqlite3.java \ |
| sqlite3_blob.java \ |
| sqlite3_context.java \ |
| sqlite3_stmt.java \ |
| sqlite3_value.java \ |
| ) $(patsubst %,$(dir.src.jni)/wrapper1/%,\ |
| AggregateFunction.java \ |
| ScalarFunction.java \ |
| SqlFunction.java \ |
| Sqlite.java \ |
| SqliteException.java \ |
| ValueHolder.java \ |
| WindowFunction.java \ |
| ) |
| |
| JAVA_FILES.unittest := $(patsubst %,$(dir.src.jni)/%,\ |
| capi/Tester1.java \ |
| wrapper1/Tester2.java \ |
| ) |
| ifeq (1,$(enable.fts5)) |
| JAVA_FILES.unittest += $(patsubst %,$(dir.src.fts5)/%,\ |
| 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 |
| $(1).class: $(1).java |
| CLASS_FILES += $(1).class |
| endef |
| $(foreach B,$(basename \ |
| $(JAVA_FILES.main) $(JAVA_FILES.unittest) $(JAVA_FILES.tester)),\ |
| $(eval $(call CLASSFILE_DEPS,$(B)))) |
| $(CLASS_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_THREADSAFE=$(opt.threadsafe) \ |
| -DSQLITE_TEMP_STORE=2 \ |
| -DSQLITE_USE_URI=1 \ |
| -DSQLITE_OMIT_LOAD_EXTENSION \ |
| -DSQLITE_OMIT_DEPRECATED \ |
| -DSQLITE_OMIT_SHARED_CACHE \ |
| -DSQLITE_C=$(sqlite3.c) \ |
| -DSQLITE_JNI_FATAL_OOM=$(opt.fatal-oom) \ |
| -DSQLITE_JNI_ENABLE_METRICS=$(opt.metrics) |
| |
| opt.extras ?= 1 |
| ifeq (1,$(opt.extras)) |
| 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_NORMALIZE \ |
| -DSQLITE_ENABLE_SQLLOG \ |
| -DSQLITE_ENABLE_COLUMN_METADATA |
| endif |
| |
| ifeq (1,$(opt.debug)) |
| SQLITE_OPT += -DSQLITE_DEBUG -g -DDEBUG -UNDEBUG |
| else |
| SQLITE_OPT += -Os |
| 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.capi),CApi,_capi)) |
| $(eval $(call ADD_JNI_H,$(dir.src.capi),SQLTester,_capi)) |
| 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 = \ |
| -std=c99 \ |
| -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 |
| Tester1.flags ?= |
| Tester2.flags ?= |
| test.flags.jvm = -ea -Djava.library.path=$(dir.bld.c) \ |
| $(java.flags) -cp $(classpath) |
| test.deps := $(CLASS_FILES) $(package.dll) |
| test-one: $(test.deps) |
| $(bin.java) $(test.flags.jvm) org.sqlite.jni.capi.Tester1 $(Tester1.flags) |
| $(bin.java) $(test.flags.jvm) org.sqlite.jni.wrapper1.Tester2 $(Tester2.flags) |
| test-sqllog: $(test.deps) |
| @echo "Testing with -sqllog..." |
| $(bin.java) $(test.flags.jvm) org.sqlite.jni.capi.Tester1 $(Tester1.flags) -sqllog |
| test-mt: $(test.deps) |
| @echo "Testing in multi-threaded mode:"; |
| $(bin.java) $(test.flags.jvm) org.sqlite.jni.capi.Tester1 \ |
| -t 7 -r 50 -shuffle $(Tester1.flags) |
| $(bin.java) $(test.flags.jvm) org.sqlite.jni.wrapper1.Tester2 \ |
| -t 7 -r 50 -shuffle $(Tester2.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.capi.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.capi.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 \ |
| | 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.capi.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. |
| # javadoc.exclude += -exclude org.sqlite.jni.capi |
| # ^^^^ exclude the capi API only for certain builds (TBD) |
| $(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)/*/*.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) |