Add tests for the new code on this branch.
[sqlite.git] / ext / jni / GNUmakefile
blob26a38dad9a13c4665a8d8dd86240c3c41fb380b8
1 # Quick-and-dirty makefile to bootstrap the sqlite3-jni project. This
2 # build assumes a Linux-like system.
3 default: all
5 JAVA_HOME ?= $(HOME)/jdk/current
6 # e.g. /usr/lib/jvm/default-javajava-19-openjdk-amd64
7 JDK_HOME ?= $(JAVA_HOME)
8 # ^^^ JDK_HOME is not as widely used as JAVA_HOME
9 bin.jar := $(JDK_HOME)/bin/jar
10 bin.java := $(JDK_HOME)/bin/java
11 bin.javac := $(JDK_HOME)/bin/javac
12 bin.javadoc := $(JDK_HOME)/bin/javadoc
13 ifeq (,$(wildcard $(JDK_HOME)))
14 $(error set JDK_HOME to the top-most dir of your JDK installation.)
15 endif
16 MAKEFILE := $(lastword $(MAKEFILE_LIST))
17 $(MAKEFILE):
19 package.jar := sqlite3-jni.jar
21 dir.top := ../..
22 dir.tool := ../../tool
23 dir.jni := $(patsubst %/,%,$(dir $(MAKEFILE)))
24 dir.src := $(dir.jni)/src
25 dir.src.c := $(dir.src)/c
26 dir.bld := $(dir.jni)/bld
27 dir.bld.c := $(dir.bld)
28 dir.src.jni := $(dir.src)/org/sqlite/jni
29 dir.src.capi := $(dir.src.jni)/capi
30 dir.src.fts5 := $(dir.src.jni)/fts5
31 dir.tests := $(dir.src)/tests
32 mkdir ?= mkdir -p
33 $(dir.bld.c):
34 $(mkdir) $@
36 javac.flags ?= -Xlint:unchecked -Xlint:deprecation
37 java.flags ?=
38 javac.flags += -encoding utf8
39 # -------------^^^^^^^^^^^^^^ required for Windows builds
40 jnicheck ?= 1
41 ifeq (1,$(jnicheck))
42 java.flags += -Xcheck:jni
43 endif
45 classpath := $(dir.src)
46 CLEAN_FILES := $(package.jar)
47 DISTCLEAN_FILES := $(dir.jni)/*~ $(dir.src.c)/*~ $(dir.src.jni)/*~
49 sqlite3-jni.h := $(dir.src.c)/sqlite3-jni.h
50 .NOTPARALLEL: $(sqlite3-jni.h)
51 CApi.java := $(dir.src.capi)/CApi.java
52 SQLTester.java := $(dir.src.capi)/SQLTester.java
53 CApi.class := $(CApi.java:.java=.class)
54 SQLTester.class := $(SQLTester.java:.java=.class)
56 ########################################################################
57 # The future of FTS5 customization in this API is as yet unclear.
58 # The pieces are all in place, and are all thin proxies so not much
59 # complexity, but some semantic changes were required in porting
60 # which are largely untested.
62 # Reminder: this flag influences the contents of $(sqlite3-jni.h),
63 # which is checked in. Please do not check in changes to that file in
64 # which the fts5 APIs have been stripped unless that feature is
65 # intended to be stripped for good.
66 enable.fts5 ?= 1
68 ifeq (,$(wildcard $(dir.tests)/*))
69 enable.tester := 0
70 else
71 enable.tester := 1
72 endif
74 # bin.version-info = binary to output various sqlite3 version info
75 # building the distribution zip file.
76 bin.version-info := $(dir.top)/version-info
77 .NOTPARALLEL: $(bin.version-info)
78 $(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
79 $(MAKE) -C $(dir.top) version-info
81 # Be explicit about which Java files to compile so that we can work on
82 # in-progress files without requiring them to be in a compilable statae.
83 JAVA_FILES.main := $(patsubst %,$(dir.src.jni)/annotation/%,\
84 Experimental.java \
85 NotNull.java \
86 Nullable.java \
87 ) $(patsubst %,$(dir.src.capi)/%,\
88 AbstractCollationCallback.java \
89 AggregateFunction.java \
90 AuthorizerCallback.java \
91 AutoExtensionCallback.java \
92 BusyHandlerCallback.java \
93 CollationCallback.java \
94 CollationNeededCallback.java \
95 CommitHookCallback.java \
96 ConfigLogCallback.java \
97 ConfigSqlLogCallback.java \
98 NativePointerHolder.java \
99 OutputPointer.java \
100 PrepareMultiCallback.java \
101 PreupdateHookCallback.java \
102 ProgressHandlerCallback.java \
103 ResultCode.java \
104 RollbackHookCallback.java \
105 ScalarFunction.java \
106 SQLFunction.java \
107 CallbackProxy.java \
108 CApi.java \
109 TableColumnMetadata.java \
110 TraceV2Callback.java \
111 UpdateHookCallback.java \
112 ValueHolder.java \
113 WindowFunction.java \
114 XDestroyCallback.java \
115 sqlite3.java \
116 sqlite3_blob.java \
117 sqlite3_context.java \
118 sqlite3_stmt.java \
119 sqlite3_value.java \
120 ) $(patsubst %,$(dir.src.jni)/wrapper1/%,\
121 AggregateFunction.java \
122 ScalarFunction.java \
123 SqlFunction.java \
124 Sqlite.java \
125 SqliteException.java \
126 ValueHolder.java \
127 WindowFunction.java \
130 JAVA_FILES.unittest := $(patsubst %,$(dir.src.jni)/%,\
131 capi/Tester1.java \
132 wrapper1/Tester2.java \
134 ifeq (1,$(enable.fts5))
135 JAVA_FILES.unittest += $(patsubst %,$(dir.src.fts5)/%,\
136 TesterFts5.java \
138 JAVA_FILES.main += $(patsubst %,$(dir.src.fts5)/%,\
139 fts5_api.java \
140 fts5_extension_function.java \
141 fts5_tokenizer.java \
142 Fts5.java \
143 Fts5Context.java \
144 Fts5ExtensionApi.java \
145 Fts5PhraseIter.java \
146 Fts5Tokenizer.java \
147 XTokenizeCallback.java \
149 endif
150 JAVA_FILES.tester := $(SQLTester.java)
151 JAVA_FILES.package.info := \
152 $(dir.src.jni)/package-info.java \
153 $(dir.src.jni)/annotation/package-info.java
155 CLASS_FILES.main := $(JAVA_FILES.main:.java=.class)
156 CLASS_FILES.unittest := $(JAVA_FILES.unittest:.java=.class)
157 CLASS_FILES.tester := $(JAVA_FILES.tester:.java=.class)
159 JAVA_FILES += $(JAVA_FILES.main) $(JAVA_FILES.unittest)
160 ifeq (1,$(enable.tester))
161 JAVA_FILES += $(JAVA_FILES.tester)
162 endif
164 CLASS_FILES :=
165 define CLASSFILE_DEPS
166 all: $(1).class
167 $(1).class: $(1).java
168 CLASS_FILES += $(1).class
169 endef
170 $(foreach B,$(basename \
171 $(JAVA_FILES.main) $(JAVA_FILES.unittest) $(JAVA_FILES.tester)),\
172 $(eval $(call CLASSFILE_DEPS,$(B))))
173 $(CLASS_FILES): $(MAKEFILE)
174 $(bin.javac) $(javac.flags) -h $(dir.bld.c) -cp $(classpath) $(JAVA_FILES)
176 #.PHONY: classfiles
178 ########################################################################
179 # Set up sqlite3.c and sqlite3.h...
181 # To build with SEE (https://sqlite.org/see), either put sqlite3-see.c
182 # in the top of this build tree or pass
183 # sqlite3.c=PATH_TO_sqlite3-see.c to the build. Note that only
184 # encryption modules with no 3rd-party dependencies will currently
185 # work here: AES256-OFB, AES128-OFB, and AES128-CCM. Not
186 # coincidentally, those 3 modules are included in the sqlite3-see.c
187 # bundle.
189 # A custom sqlite3.c must not have any spaces in its name.
190 # $(sqlite3.canonical.c) must point to the sqlite3.c in
191 # the sqlite3 canonical source tree, as that source file
192 # is required for certain utility and test code.
193 sqlite3.canonical.c := $(firstword $(wildcard $(dir.src.c)/sqlite3.c) $(dir.top)/sqlite3.c)
194 sqlite3.canonical.h := $(firstword $(wildcard $(dir.src.c)/sqlite3.h) $(dir.top)/sqlite3.h)
195 sqlite3.c := $(sqlite3.canonical.c)
196 sqlite3.h := $(sqlite3.canonical.h)
197 #ifeq (,$(shell grep sqlite3_activate_see $(sqlite3.c) 2>/dev/null))
198 # SQLITE_C_IS_SEE := 0
199 #else
200 # SQLITE_C_IS_SEE := 1
201 # $(info This is an SEE build.)
202 #endif
204 .NOTPARALLEL: $(sqlite3.h)
205 $(sqlite3.h):
206 $(MAKE) -C $(dir.top) sqlite3.c
207 $(sqlite3.c): $(sqlite3.h)
209 opt.threadsafe ?= 1
210 opt.fatal-oom ?= 1
211 opt.debug ?= 1
212 opt.metrics ?= 1
213 SQLITE_OPT = \
214 -DSQLITE_THREADSAFE=$(opt.threadsafe) \
215 -DSQLITE_TEMP_STORE=2 \
216 -DSQLITE_USE_URI=1 \
217 -DSQLITE_OMIT_LOAD_EXTENSION \
218 -DSQLITE_OMIT_DEPRECATED \
219 -DSQLITE_OMIT_SHARED_CACHE \
220 -DSQLITE_C=$(sqlite3.c) \
221 -DSQLITE_JNI_FATAL_OOM=$(opt.fatal-oom) \
222 -DSQLITE_JNI_ENABLE_METRICS=$(opt.metrics)
224 opt.extras ?= 1
225 ifeq (1,$(opt.extras))
226 SQLITE_OPT += -DSQLITE_ENABLE_RTREE \
227 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
228 -DSQLITE_ENABLE_STMTVTAB \
229 -DSQLITE_ENABLE_DBPAGE_VTAB \
230 -DSQLITE_ENABLE_DBSTAT_VTAB \
231 -DSQLITE_ENABLE_BYTECODE_VTAB \
232 -DSQLITE_ENABLE_OFFSET_SQL_FUNC \
233 -DSQLITE_ENABLE_PREUPDATE_HOOK \
234 -DSQLITE_ENABLE_NORMALIZE \
235 -DSQLITE_ENABLE_SQLLOG \
236 -DSQLITE_ENABLE_COLUMN_METADATA
237 endif
239 ifeq (1,$(opt.debug))
240 SQLITE_OPT += -DSQLITE_DEBUG -g -DDEBUG -UNDEBUG
241 else
242 SQLITE_OPT += -Os
243 endif
245 ifeq (1,$(enable.fts5))
246 SQLITE_OPT += -DSQLITE_ENABLE_FTS5
247 endif
249 sqlite3-jni.c := $(dir.src.c)/sqlite3-jni.c
250 sqlite3-jni.o := $(dir.bld.c)/sqlite3-jni.o
251 sqlite3-jni.h := $(dir.src.c)/sqlite3-jni.h
252 package.dll := $(dir.bld.c)/libsqlite3-jni.so
253 # All javac-generated .h files must be listed in $(sqlite3-jni.h.in):
254 sqlite3-jni.h.in :=
255 # $(java.with.jni) lists all Java files which contain JNI decls:
256 java.with.jni :=
257 define ADD_JNI_H
258 sqlite3-jni.h.in += $$(dir.bld.c)/org_sqlite_jni$(3)_$(2).h
259 java.with.jni += $(1)/$(2).java
260 $$(dir.bld.c)/org_sqlite_jni$(3)_$(2).h: $(1)/$(2).java
261 endef
262 # Invoke ADD_JNI_H once for each Java file which includes JNI
263 # declarations:
264 $(eval $(call ADD_JNI_H,$(dir.src.capi),CApi,_capi))
265 $(eval $(call ADD_JNI_H,$(dir.src.capi),SQLTester,_capi))
266 ifeq (1,$(enable.fts5))
267 $(eval $(call ADD_JNI_H,$(dir.src.fts5),Fts5ExtensionApi,_fts5))
268 $(eval $(call ADD_JNI_H,$(dir.src.fts5),fts5_api,_fts5))
269 $(eval $(call ADD_JNI_H,$(dir.src.fts5),fts5_tokenizer,_fts5))
270 endif
271 $(sqlite3-jni.h.in): $(dir.bld.c)
273 #package.dll.cfiles :=
274 package.dll.cflags = \
275 -std=c99 \
276 -fPIC \
277 -I. \
278 -I$(dir $(sqlite3.h)) \
279 -I$(dir.src.c) \
280 -I$(JDK_HOME)/include \
281 $(patsubst %,-I%,$(patsubst %.h,,$(wildcard $(JDK_HOME)/include/*))) \
282 -Wall
283 # The gross $(patsubst...) above is to include the platform-specific
284 # subdir which lives under $(JDK_HOME)/include and is a required
285 # include path for client-level code.
287 # Using (-Wall -Wextra) triggers an untennable number of
288 # gcc warnings from sqlite3.c for mundane things like
289 # unused parameters.
290 ########################################################################
291 ifeq (1,$(enable.tester))
292 package.dll.cflags += -DSQLITE_JNI_ENABLE_SQLTester
293 endif
295 $(sqlite3-jni.h): $(sqlite3-jni.h.in) $(MAKEFILE)
296 @cat $(sqlite3-jni.h.in) > $@.tmp
297 @if cmp $@ $@.tmp >/dev/null; then \
298 rm -f $@.tmp; \
299 echo "$@ not modified"; \
300 else \
301 mv $@.tmp $@; \
302 echo "Updated $@"; \
304 @if [ x1 != x$(enable.fts5) ]; then \
305 echo "*** REMINDER:"; \
306 echo "*** enable.fts5=0, so please do not check in changes to $@."; \
309 $(package.dll): $(sqlite3-jni.h) $(sqlite3.c) $(sqlite3.h)
310 $(package.dll): $(sqlite3-jni.c) $(MAKEFILE)
311 $(CC) $(package.dll.cflags) $(SQLITE_OPT) \
312 $(sqlite3-jni.c) -shared -o $@
313 all: $(package.dll)
315 .PHONY: test test-one
316 Tester1.flags ?=
317 Tester2.flags ?=
318 test.flags.jvm = -ea -Djava.library.path=$(dir.bld.c) \
319 $(java.flags) -cp $(classpath)
320 test.deps := $(CLASS_FILES) $(package.dll)
321 test-one: $(test.deps)
322 $(bin.java) $(test.flags.jvm) org.sqlite.jni.capi.Tester1 $(Tester1.flags)
323 $(bin.java) $(test.flags.jvm) org.sqlite.jni.wrapper1.Tester2 $(Tester2.flags)
324 test-sqllog: $(test.deps)
325 @echo "Testing with -sqllog..."
326 $(bin.java) $(test.flags.jvm) org.sqlite.jni.capi.Tester1 $(Tester1.flags) -sqllog
327 test-mt: $(test.deps)
328 @echo "Testing in multi-threaded mode:";
329 $(bin.java) $(test.flags.jvm) org.sqlite.jni.capi.Tester1 \
330 -t 7 -r 50 -shuffle $(Tester1.flags)
331 $(bin.java) $(test.flags.jvm) org.sqlite.jni.wrapper1.Tester2 \
332 -t 7 -r 50 -shuffle $(Tester2.flags)
334 test: test-one test-mt
335 tests: test test-sqllog
337 tester.scripts := $(sort $(wildcard $(dir.src)/tests/*.test))
338 tester.flags ?= # --verbose
339 .PHONY: tester tester-local tester-ext
340 ifeq (1,$(enable.tester))
341 tester-local: $(CLASS_FILES.tester) $(package.dll)
342 $(bin.java) -ea -Djava.library.path=$(dir.bld.c) \
343 $(java.flags) -cp $(classpath) \
344 org.sqlite.jni.capi.SQLTester $(tester.flags) $(tester.scripts)
345 tester: tester-local
346 else
347 tester:
348 @echo "SQLTester support is disabled."
349 endif
351 tester.extdir.default := $(dir.tests)/ext
352 tester.extdir ?= $(tester.extdir.default)
353 tester.extern-scripts := $(wildcard $(tester.extdir)/*.test)
354 ifneq (,$(tester.extern-scripts))
355 tester-ext:
356 $(bin.java) -ea -Djava.library.path=$(dir.bld.c) \
357 $(java.flags) -cp $(classpath) \
358 org.sqlite.jni.capi.SQLTester $(tester.flags) $(tester.extern-scripts)
359 else
360 tester-ext:
361 @echo "******************************************************"; \
362 echo "*** Include the out-of-tree test suite in the 'tester'"; \
363 echo "*** target by either symlinking its directory to"; \
364 echo "*** $(tester.extdir.default) or passing it to make"; \
365 echo "*** as tester.extdir=/path/to/that/dir."; \
366 echo "******************************************************";
367 endif
369 tester-ext: tester-local
370 tester: tester-ext
371 tests: tester
372 ########################################################################
373 # Build each SQLITE_THREADMODE variant and run all tests against them.
374 multitest: clean
375 define MULTIOPT
376 multitest: multitest-$(1)
377 multitest-$(1):
378 $$(MAKE) opt.debug=$$(opt.debug) $(patsubst %,opt.%,$(2)) \
379 tests clean enable.fts5=1
380 endef
382 $(eval $(call MULTIOPT,01,threadsafe=0 oom=1))
383 $(eval $(call MULTIOPT,00,threadsafe=0 oom=0))
384 $(eval $(call MULTIOPT,11,threadsafe=1 oom=1))
385 $(eval $(call MULTIOPT,10,threadsafe=1 oom=0))
386 $(eval $(call MULTIOPT,21,threadsafe=2 oom=1))
387 $(eval $(call MULTIOPT,20,threadsafe=2 oom=0))
390 ########################################################################
391 # jar bundle...
392 package.jar.in := $(abspath $(dir.src)/jar.in)
393 CLEAN_FILES += $(package.jar.in)
394 JAVA_FILES.jar := $(JAVA_FILES.main) $(JAVA_FILES.unittest) $(JAVA_FILES.package.info)
395 CLASS_FILES.jar := $(filter-out %/package-info.class,$(JAVA_FILES.jar:.java=.class))
396 $(package.jar.in): $(package.dll) $(MAKEFILE)
397 ls -1 \
398 $(dir.src.jni)/*/*.java $(dir.src.jni)/*/*.class \
399 | sed -e 's,^$(dir.src)/,,' | sort > $@
401 $(package.jar): $(CLASS_FILES.jar) $(MAKEFILE) $(package.jar.in)
402 @rm -f $(dir.src)/c/*~ $(dir.src.jni)/*~
403 cd $(dir.src); $(bin.jar) -cfe ../$@ org.sqlite.jni.capi.Tester1 @$(package.jar.in)
404 @ls -la $@
405 @echo "To use this jar you will need the -Djava.library.path=DIR/CONTAINING/libsqlite3-jni.so flag."
406 @echo "e.g. java -Djava.library.path=bld -jar $@"
408 jar: $(package.jar)
409 run-jar: $(package.jar) $(package.dll)
410 $(bin.java) -Djava.library.path=$(dir.bld) -jar $(package.jar) $(run-jar.flags)
412 ########################################################################
413 # javadoc...
414 dir.doc := $(dir.jni)/javadoc
415 doc.index := $(dir.doc)/index.html
416 javadoc.exclude := -exclude org.sqlite.jni.fts5
417 # ^^^^ 2023-09-13: elide the fts5 parts from the public docs for
418 # the time being, as it's not clear where the Java bindings for
419 # those bits are going.
420 # javadoc.exclude += -exclude org.sqlite.jni.capi
421 # ^^^^ exclude the capi API only for certain builds (TBD)
422 $(doc.index): $(JAVA_FILES.main) $(MAKEFILE)
423 @if [ -d $(dir.doc) ]; then rm -fr $(dir.doc)/*; fi
424 $(bin.javadoc) -cp $(classpath) -d $(dir.doc) -quiet \
425 -subpackages org.sqlite.jni $(javadoc.exclude)
426 @echo "javadoc output is in $@"
428 .PHONY: doc javadoc docserve
429 .FORCE: doc
430 doc: $(doc.index)
431 javadoc: $(doc.index)
432 # Force rebild of docs
433 redoc:
434 @rm -f $(doc.index)
435 @$(MAKE) doc
436 docserve: $(doc.index)
437 cd $(dir.doc) && althttpd -max-age 1 -page index.html
438 ########################################################################
439 # Clean up...
440 CLEAN_FILES += $(dir.bld.c)/* \
441 $(dir.src.jni)/*.class \
442 $(dir.src.jni)/*/*.class \
443 $(package.dll) \
444 hs_err_pid*.log
446 .PHONY: clean distclean
447 clean:
448 -rm -f $(CLEAN_FILES)
449 distclean: clean
450 -rm -f $(DISTCLEAN_FILES)
451 -rm -fr $(dir.bld.c) $(dir.doc)
453 ########################################################################
454 # disttribution bundle rules...
456 ifeq (,$(filter snapshot,$(MAKECMDGOALS)))
457 dist-name-prefix := sqlite-jni
458 else
459 dist-name-prefix := sqlite-jni-snapshot-$(shell /usr/bin/date +%Y%m%d)
460 endif
461 dist-name := $(dist-name-prefix)-TEMP
464 dist-dir.top := $(dist-name)
465 dist-dir.src := $(dist-dir.top)/src
466 dist.top.extras := \
467 README.md
469 .PHONY: dist snapshot
471 dist: \
472 $(bin.version-info) $(sqlite3.canonical.c) \
473 $(package.jar) $(MAKEFILE)
474 @echo "Making end-user deliverables..."
475 @echo "****************************************************************************"; \
476 echo "*** WARNING: be sure to build this with JDK8 (javac 1.8) for compatibility."; \
477 echo "*** reasons!"; $$($(bin.javac) -version); \
478 echo "****************************************************************************"
479 @rm -fr $(dist-dir.top)
480 @mkdir -p $(dist-dir.src)
481 @cp -p $(dist.top.extras) $(dist-dir.top)/.
482 @cp -p jar-dist.make $(dist-dir.top)/Makefile
483 @cp -p $(dir.src.c)/*.[ch] $(dist-dir.src)/.
484 @cp -p $(sqlite3.canonical.c) $(sqlite3.canonical.h) $(dist-dir.src)/.
485 @set -e; \
486 vnum=$$($(bin.version-info) --download-version); \
487 vjar=$$($(bin.version-info) --version); \
488 vdir=$(dist-name-prefix)-$$vnum; \
489 arczip=$$vdir.zip; \
490 cp -p $(package.jar) $(dist-dir.top)/sqlite3-jni-$${vjar}.jar; \
491 echo "Making $$arczip ..."; \
492 rm -fr $$arczip $$vdir; \
493 mv $(dist-dir.top) $$vdir; \
494 zip -qr $$arczip $$vdir; \
495 rm -fr $$vdir; \
496 ls -la $$arczip; \
497 set +e; \
498 unzip -lv $$arczip || echo "Missing unzip app? Not fatal."
500 snapshot: dist
502 .PHONY: dist-clean
503 clean: dist-clean
504 dist-clean:
505 rm -fr $(dist-name) $(wildcard sqlite-jni-*.zip)