1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435 |
- #/do/not/tclsh
- # ^^^ help out editors which guess this file's content type.
- #
- # This is the main autosetup-compatible configure script for the
- # SQLite project.
- #
- # This script should be kept compatible with JimTCL, a copy of which
- # is included in this source tree as ./autosetup/jimsh0.c. The number
- # of incompatibilities between canonical TCL and JimTCL is very low
- # and alternative formulations of incompatible constructs have, so
- # far, been easy to find.
- #
- # JimTCL: https://jim.tcl.tk
- #
- use cc cc-db cc-shared cc-lib proj pkg-config
- # $DUMP_DEFINES_TXT is the file emitted by --dump-defines, intended
- # only for build debugging and not part of the public build interface.
- set DUMP_DEFINES_TXT ./config.defines.txt
- # $DUMP_DEFINES_JSON is the autosetup counterpart of the historical
- # "DEFS" var which was generated by the autotools in the pre-processed
- # autotools builds (but not in the canonical tree). Generation of this
- # file is disabled (via an empty file name) until/unless someone
- # voices a specific interest in it. The original motivating use case
- # is handled fine by sqlite_cfg.h.
- set DUMP_DEFINES_JSON ""; #./config.defines.json
- ########################################################################
- # Regarding flag compatibility with the historical autotool configure
- # script:
- #
- # A very long story made short, autosetup's --flag handling has
- # some behaviors which make it impossible to implement 100% identical
- # flags compared to the historical autotools build. The differences
- # are documented here:
- #
- # 1) --debug is used by autosetup itself, so we have to rename it to
- # --with-debug. We cannot use --enable-debug because that is, for
- # autosetup, an alias for --debug=1. Alternately, we can patch
- # autosetup to use --autosetup-debug for its own purposes instead.
- #
- # 2) In autosetup, all flags starting with (--enable, --disable) are
- # forced to be booleans and receive special handling in how they're
- # resolved. Because of that we have to rename:
- #
- # 2.1) --enable-tempstore[=no] to --with-tempstore[=no], noting that
- # it has four legal values, not two.
- #
- ########################################################################
- # A gentle introduction to flags handling in autosetup
- #
- # Reference: https://msteveb.github.io/autosetup/developer/
- #
- # All configure flags must be described in an 'options' call, which
- # must appear very early on in this script. The general syntax is:
- #
- # FLAG => {Help text}
- #
- # Where FLAG can have any of the following formats:
- #
- # boolopt => "a boolean option which defaults to disabled"
- # boolopt2=1 => "a boolean option which defaults to enabled"
- # stringopt: => "an option which takes an argument, e.g. --stringopt=value"
- # stringopt2:=value => "an option where the argument is optional and defaults to 'value'"
- # optalias booltopt3 => "a boolean with a hidden alias. --optalias is not shown in --help"
- #
- # Autosetup does no small amount of specialized handling for flags,
- # especially booleans. Each bool-type --FLAG implicitly gets
- # --enable-FLAG and --disable-FLAG forms. e.g. we define a flag
- # "readline", which will be interpreted in one of two ways, depending
- # on how it's invoked and how its default is defined:
- #
- # --enable-readline ==> boolean true
- # --disable-readline ==> boolean false
- #
- # Passing --readline or --readline=1 is equivalent to passing
- # --enable-readline, and --readline=0 is equivalent to
- # --disable-readline.
- #
- # The behavior described above can lead lead to some confusion when
- # writing help text. For example:
- #
- # options { json=1 {Disable JSON functions} }
- #
- # The reason the help text says "disable" is because a boolean option
- # which defaults to true is, in the --help text, rendered as:
- #
- # --disable-json Disable JSON functions
- #
- # Whereas a bool flag which defaults to false will instead render as:
- #
- # --enable-FLAG
- #
- # Non-boolean flags, in contrast, use the names specifically given to
- # them in the [options] invocation. e.g. "with-tcl" is the --with-tcl
- # flag.
- #
- # Fetching values for flags:
- #
- # booleans: use one of:
- # - [opt-bool FLAG] is autosetup's built-in command for this, but we
- # have some convenience variants:
- # - [proj-opt-truthy FLAG]
- # - [proj-opt-if-truthy FLAG {THEN} {ELSE}]
- #
- # Non-boolean (i.e. string) flags:
- # - [opt-val FLAG ?default?]
- # - [opt-str ...] - see the docs in ./autosetup/autosetup
- #
- ########################################################################
- set flags {
- # When writing {help text blocks}, be aware that autosetup formats
- # them differently (left-aligned, directly under the --flag) if the
- # block starts with a newline. It does NOT expand vars and commands,
- # but we use a [subst] call below which will replace (only) var
- # refs.
- # <build-modes>
- shared=1 => {Disable build of shared libary}
- static=1 => {Disable build of static library (mostly)}
- amalgamation=1 => {Disable the amalgamation and instead build all files separately.}
- # </build-modes>
- # <lib-feature>
- threadsafe=1 => {Disable mutexing}
- with-tempstore:=no => {Use an in-RAM database for temporary tables: never,no,yes,always}
- largefile=1 => {Disable large file support}
- load-extension=1 => {Disable loading of external extensions}
- math=1 => {Disable math functions}
- json=1 => {Disable JSON functions}
- memsys5 => {Enable MEMSYS5}
- memsys3 => {Enable MEMSYS3}
- fts3 => {Enable the FTS3 extension}
- fts4 => {Enable the FTS4 extension}
- fts5 => {Enable the FTS5 extension}
- update-limit => {Enable the UPDATE/DELETE LIMIT clause}
- geopoly => {Enable the GEOPOLY extension}
- rtree => {Enable the RTREE extension}
- session => {Enable the SESSION extension}
- all => {Enable FTS4, FTS5, Geopoly, RTree, Sessions}
- # </lib-feature>
- # <tcl>
- with-tcl:DIR =>
- {Directory containing tclConfig.sh or a directory one level up from
- that, from which we can derive a directory containing tclConfig.sh.
- A dir name of "prefix" is equivalent to the directory specified by
- the --prefix flag.}
- with-tclsh:PATH =>
- {Full pathname of tclsh to use. It is used for (A) trying to find
- tclConfig.sh and (B) all TCL-based code generation. Warning: if
- its containing dir has multiple tclsh versions, it may select the
- wrong tclConfig.sh!}
- tcl=1 =>
- {Disable components which require TCL, including all tests.
- This tree requires TCL for code generation but can use the in-tree
- copy of autosetup/jimsh0.c for that. The SQLite TCL extension and the
- test code require a canonical tclsh.}
- # <tcl>
- # <line-editing>
- readline=1 => {Disable readline support}
- # --with-readline-lib is a backwards-compatible alias for
- # --with-readline-ldflags
- with-readline-lib:
- with-readline-ldflags:=auto
- => {Readline LDFLAGS, e.g. -lreadline -lncurses}
- # --with-readline-inc is a backwards-compatible alias for
- # --with-readline-cflags.
- with-readline-inc:
- with-readline-cflags:=auto
- => {Readline CFLAGS, e.g. -I/path/to/includes}
- with-readline-header:PATH
- => {Full path to readline.h, from which --with-readline-cflags will be derived}
- with-linenoise:DIR => {Source directory for linenoise.c and linenoise.h}
- editline=0 => {Enable BSD editline support}
- # </line-editing>
- # <icu>
- with-icu-ldflags:LDFLAGS
- => {Enable SQLITE_ENABLE_ICU and add the given linker flags for the ICU libraries}
- with-icu-cflags:CFLAGS
- => {Apply extra CFLAGS/CPPFLAGS necessary for building with ICU. e.g. -I/usr/local/include}
- with-icu-config:=auto => {Enable SQLITE_ENABLE_ICU. Value must be one of: auto, pkg-config, /path/to/icu-config}
- icu-collations=0 => {Enable SQLITE_ENABLE_ICU_COLLATIONS. Requires --with-icu-ldflags=... or --with-icu-config}
- # </icu>
- # <alternative-builds>
- with-wasi-sdk:=/opt/wasi-sdk
- => {Top-most dir of the wasi-sdk for a WASI build}
- with-emsdk:=auto => {Top-most dir of the Emscripten SDK installation. Default = EMSDK env var.}
- # </alternative-builds>
- # <developer>
- # Note that using the --debug/--enable-debug flag here requires patching
- # autosetup/autosetup to rename the --debug to --autosetup-debug.
- with-debug=0
- debug=0 =>
- {Enable debug build flags. This option will impact performance by
- as much as 4x, as it includes large numbers of assert()s in
- performance-critical loops. Never use --debug for production
- builds.}
- scanstatus => {Enable the SQLITE_ENABLE_STMT_SCANSTATUS feature flag}
- dev => {Enable dev-mode build: automatically enables certain other flags}
- test-status => {Enable status of tests}
- gcov=0 => {Enable coverage testing using gcov}
- linemacros => {Enable #line macros in the amalgamation}
- dump-defines=0 => {Dump autosetup defines to $DUMP_DEFINES_TXT (for build debugging)}
- dynlink-tools => {Dynamically link libsqlite3 to certain tools which normally statically embed it.}
- soname:=legacy =>
- {SONAME for libsqlite3.so. "none", or not using this flag, sets no
- soname. "legacy" sets it to its historical value of
- libsqlite3.so.0. A value matching the glob "libsqlite3.*" sets
- it to that literal value. Any other value is assumed to be a
- suffix which gets applied to "libsqlite3.so.",
- e.g. --soname=9.10 equates to "libsqlite3.so.9.10".
- }
- # --soname has a long story behind it: https://sqlite.org/src/forumpost/5a3b44f510df8ded
- # </developer>
- }
- if {"" ne $DUMP_DEFINES_JSON} {
- lappend flags \
- defines-json-include-lowercase=0 \
- => {Include lower-case defines (primarily system paths) in $DUMP_DEFINES_JSON}
- }
- options [subst -nobackslashes -nocommands $flags]
- unset flags
- #
- # Carry values from hidden --flag aliases over to their canonical flag
- # forms.
- #
- proj-xfer-options-aliases {
- with-readline-inc => with-readline-cflags
- with-readline-lib => with-readline-ldflags
- with-debug => debug
- }
- set srcdir $::autosetup(srcdir)
- set PACKAGE_VERSION [proj-file-content -trim $srcdir/VERSION]
- define PACKAGE_NAME "sqlite"
- define PACKAGE_URL {https://sqlite.org}
- define PACKAGE_VERSION $PACKAGE_VERSION
- define PACKAGE_STRING "[get-define PACKAGE_NAME] $PACKAGE_VERSION"
- define PACKAGE_BUGREPORT [get-define PACKAGE_URL]/forum
- msg-result "Source dir = $srcdir"
- msg-result "Build dir = $::autosetup(builddir)"
- msg-result "Configuring SQLite version $PACKAGE_VERSION"
- apply {{} {
- #
- # SQLITE_AUTORECONFIG contains make target rules for re-running the
- # configure script with the same arguments it was initially invoked
- # with. This can be used to automatically reconfigure
- #
- proc squote {arg} {
- # Wrap $arg in single-quotes if it looks like it might need that
- # to avoid mis-handling as a shell argument. We assume that $arg
- # will never contain any single-quote characters.
- if {[string match {*[ &;$*"]*} $arg]} { return '$arg' }
- return $arg
- }
- define-append SQLITE_AUTORECONFIG cd [squote $::autosetup(builddir)] && [squote $::srcdir/configure]
- #{*}$::autosetup(argv) breaks with --flag='val with spaces', so...
- foreach arg $::autosetup(argv) {
- define-append SQLITE_AUTORECONFIG [squote $arg]
- }
- rename squote ""
- }}
- # Are we cross-compiling?
- set isCrossCompiling [proj-is-cross-compiling]
- define OPT_FEATURE_FLAGS {} ; # -DSQLITE_OMIT/ENABLE flags.
- define OPT_SHELL {} ; # Feature-related CFLAGS for the sqlite3 CLI app
- ########################################################################
- # Adds $args, if not empty, to OPT_FEATURE_FLAGS. If the first arg is
- # -shell then it strips that arg and passes the remaining args the
- # sqlite-add-shell-opt in addition to adding them to
- # OPT_FEATURE_FLAGS.
- proc sqlite-add-feature-flag {args} {
- set shell ""
- if {"-shell" eq [lindex $args 0]} {
- set args [lassign $args shell]
- }
- if {"" ne $args} {
- if {"" ne $shell} {
- sqlite-add-shell-opt {*}$args
- }
- define-append OPT_FEATURE_FLAGS {*}$args
- }
- }
- # Appends $args, if not empty, to OPT_SHELL.
- proc sqlite-add-shell-opt {args} {
- if {"" ne $args} {
- define-append OPT_SHELL {*}$args
- }
- }
- # Pass msg-debug=1 to configure to enable obnoxiously loud output from
- # msg-debug.
- set msgDebugEnabled [proj-val-truthy [get-env msg-debug 0]]
- proc msg-debug {msg} {
- if {$::msgDebugEnabled} {
- puts stderr [proj-bold "** DEBUG: $msg"]
- }
- }
- proj-file-extensions
- if {".exe" eq [get-define TARGET_EXEEXT]} {
- define SQLITE_OS_UNIX 0
- define SQLITE_OS_WIN 1
- } else {
- define SQLITE_OS_UNIX 1
- define SQLITE_OS_WIN 0
- }
- #########
- # Programs needed
- cc-check-tools ld ar ; # must come before [sqlite-check-wasi-sdk]
- if {"" eq [proj-bin-define install]} {
- proj-warn "Cannot find install binary, so 'make install' will not work."
- define BIN_INSTALL false
- }
- ########################################################################
- # We differentiate between two C compilers: the one used for binaries
- # which are to run on the build system (in autosetup it's called
- # CC_FOR_BUILD and in Makefile.in it's $(B.cc)) and the one used for
- # compiling binaries for the target system (CC a.k.a. $(T.cc)).
- # Normally they're the same, but they will differ when
- # cross-compiling.
- define CFLAGS [proj-get-env CFLAGS {-g -O2}]
- define BUILD_CFLAGS [proj-get-env BUILD_CFLAGS {-g}]
- proj-if-opt-truthy dev {
- # --enable-dev needs to come early so that the downstream tests
- # which check for the following flags use their updated state.
- proj-opt-set all 1
- proj-opt-set debug 1
- proj-opt-set amalgamation 0
- define CFLAGS [get-env CFLAGS {-O0 -g}]
- }
- ########################################################################
- # Handle --with-wasi-sdk=DIR
- #
- # This must be run relatively early on because it may change the
- # toolchain and disable a number of config options.
- proc sqlite-check-wasi-sdk {} {
- set wasiSdkDir [opt-val with-wasi-sdk] ; # ??? [lindex [opt-val with-wasi-sdk] end]
- define HAVE_WASI_SDK 0
- if {$wasiSdkDir eq ""} {
- return 0
- } elseif {$::isCrossCompiling} {
- proj-fatal "Cannot combine --with-wasi-sdk with cross-compilation"
- }
- msg-result "Checking WASI SDK directory \[$wasiSdkDir]... "
- #puts "prefix = [prefix $wasiSdkDir/bin {clang ld}]"
- proj-affirm-files-exist -v {*}[prefix "$wasiSdkDir/bin/" {clang wasm-ld ar}]
- define HAVE_WASI_SDK 1
- define WASI_SDK_DIR $wasiSdkDir
- # Disable numerous options which we know either can't work or are
- # not useful in this build...
- msg-result "Using wasi-sdk clang. Disabling CLI shell modifying config flags:"
- # Boolean (--enable-/--disable-) flags which must be switched off:
- foreach opt {
- dynlink-tools
- editline
- gcov
- icu-collations
- load-extension
- readline
- shared
- tcl
- threadsafe
- } {
- if {[opt-bool $opt]} {
- msg-result " --disable-$opt"
- proj-opt-set $opt 0
- }
- }
- # Non-boolean flags which need to be cleared:
- foreach opt {
- with-emsdk
- with-icu-config
- with-icu-ldflags
- with-icu-cflags
- with-linenoise
- with-tcl
- } {
- if {[proj-opt-was-provided $opt]} {
- msg-result " removing --$opt"
- proj-opt-set $opt ""
- }
- }
- # Remember that we now have a discrepancy beteween
- # $::isCrossCompiling and [proj-is-cross-compiling].
- set ::isCrossCompiling 1
- #
- # Changing --host and --target have no effect here except to
- # possibly cause confusion. Autosetup has finished processing them
- # by this point.
- #
- # host_alias=wasm32-wasi
- # target=wasm32-wasi
- #
- # Merely changing CC, LD, and AR to the wasi-sdk's is enough to get
- # sqlite3.o building in WASM format.
- #
- define CC "${wasiSdkDir}/bin/clang"
- define LD "${wasiSdkDir}/bin/wasm-ld"
- define AR "${wasiSdkDir}/bin/ar"
- #define STRIP "${wasiSdkDir}/bin/strip"
- return 1
- }; # sqlite-check-wasi-sdk
- sqlite-check-wasi-sdk
- ########################################################################
- # --dynlink-tools tells the build to dynamically link certain binaries
- # to libsqlite3.so instead of embedding a copy of the amalgamation.
- define LINK_TOOLS_DYNAMICALLY [proj-opt-was-provided dynlink-tools]
- #
- # Enable large file support (if special flags are necessary)
- define HAVE_LFS 0
- if {[opt-bool largefile]} {
- cc-check-lfs
- }
- #
- # Check for needed/wanted data types
- cc-with {-includes stdint.h} \
- {cc-check-types int8_t int16_t int32_t int64_t intptr_t \
- uint8_t uint16_t uint32_t uint64_t uintptr_t}
- #
- # Check for needed/wanted functions
- cc-check-functions gmtime_r isnan localtime_r localtime_s \
- malloc_usable_size strchrnul usleep utime pread pread64 pwrite pwrite64
- proj-check-function-in-lib fdatasync rt
- define LDFLAGS_FDATASYNC [get-define lib_fdatasync]
- undefine lib_fdatasync
- #
- # Check for needed/wanted headers
- cc-check-includes \
- sys/types.h sys/stat.h dlfcn.h unistd.h \
- stdlib.h malloc.h memory.h \
- string.h strings.h \
- inttypes.h
- if {[cc-check-includes zlib.h] && [proj-check-function-in-lib deflate z]} {
- # TODO? port over the more sophisticated zlib search from the fossil auto.def
- define HAVE_ZLIB 1
- define LDFLAGS_ZLIB -lz
- sqlite-add-shell-opt -DSQLITE_HAVE_ZLIB=1
- } else {
- define HAVE_ZLIB 0
- define LDFLAGS_ZLIB ""
- }
- proj-check-rpath ; # Determine proper rpath-handling flag
- ########################################################################
- # "soname" for libsqlite3.so. See discussion at:
- # https://sqlite.org/src/forumpost/5a3b44f510df8ded
- apply {{} {
- define LDFLAGS_LIBSQLITE3_SONAME ""
- if {[proj-opt-was-provided soname]} {
- set soname [join [opt-val soname] ""]
- } else {
- # Enabling soname breaks linking for the --dynlink-tools feature,
- # and this project has no direct use for soname, so default to
- # none. Package maintainers, on the other hand, like to have an
- # soname.
- set soname none
- }
- switch -exact -- $soname {
- none - "" { return 0 }
- auto { set soname libsqlite3.so.3 }
- legacy { set soname libsqlite3.so.0 }
- default {
- if {[string match libsqlite3.* $soname]} {
- # use it as-is
- } else {
- # Assume it's a suffix
- set soname "libsqlite3.so.${soname}"
- }
- }
- }
- msg-debug "soname=$soname"
- if {[proj-check-soname $soname]} {
- define LDFLAGS_LIBSQLITE3_SONAME [get-define LDFLAGS_SONAME_PREFIX]$soname
- msg-result "Setting SONAME using: [get-define LDFLAGS_LIBSQLITE3_SONAME]"
- } elseif {[proj-opt-was-provided soname]} {
- # --soname was explicitly requested but not available, so fail fatally
- proj-fatal "This environment does not support SONAME."
- } else {
- # --soname was not explicitly requested but not available, so just warn
- msg-result "This environment does not support SONAME."
- }
- }}
- proj-define-for-opt shared ENABLE_SHARED "Build shared library?"
- if {![proj-define-for-opt static ENABLE_STATIC \
- "Build static library?"]} {
- proj-warn "Static lib build may be implicitly re-activated by other components, e.g. some test apps."
- }
- proj-define-for-opt amalgamation USE_AMALGAMATION "Use amalgamation for builds?"
- proj-define-for-opt gcov USE_GCOV "Use gcov?"
- proj-define-for-opt test-status TSTRNNR_OPTS \
- "test-runner flags:" {--status} {}
- proj-define-for-opt linemacros AMALGAMATION_LINE_MACROS \
- "Use #line macros in the amalgamation:"
- msg-checking "SQLITE_DEBUG build? "
- proj-if-opt-truthy debug {
- define SQLITE_DEBUG 1
- define TARGET_DEBUG {-g -DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0 -Wall}
- proj-opt-set memsys5
- msg-result yes
- } {
- define TARGET_DEBUG {-DNDEBUG}
- msg-result no
- }
- ########################################################################
- # TCL...
- #
- # sqlite-check-tcl performs most of the --with-tcl and --with-tclsh
- # handling. Some related bits and pieces are performed before and
- # after that function is called.
- #
- # Important [define]'d vars:
- #
- # - HAVE_TCL indicates whether we have a tclsh suitable for building
- # the TCL SQLite extension and, by extension, the testing
- # infrastructure. This must only be 1 for environments where
- # tclConfig.sh can be found.
- #
- # - TCLSH_CMD is the path to the canonical tclsh or "". It never
- # refers to jimtcl.
- #
- # - TCL_CONFIG_SH is the path to tclConfig.sh or "".
- #
- # - TCLLIBDIR is the dir to which libtclsqlite3 gets installed.
- #
- # - BTCLSH = the path to the tcl interpreter used for in-tree code
- # generation. It may be jimtcl or the canonical tclsh but may not
- # be empty - this tree requires TCL to generated numerous
- # components.
- #
- # If --tcl or --with-tcl are provided but no TCL is found, this
- # function fails fatally. If they are not explicitly provided then
- # failure to find TCL is not fatal but a loud warning will be emitted.
- #
- proc sqlite-check-tcl {} {
- rename sqlite-check-tcl ""
- define TCLSH_CMD false ; # Significant is that it exits with non-0
- define HAVE_TCL 0 ; # Will be enabled via --tcl or a successful search
- define TCLLIBDIR "" ; # Installation dir for TCL extension lib
- define TCL_CONFIG_SH ""; # full path to tclConfig.sh
- # Clear out all vars which would be set by tclConfigToAutoDef.sh, so
- # that the late-config validation of @VARS@ works even if
- # --disable-tcl is used.
- foreach k {TCL_INCLUDE_SPEC TCL_LIB_SPEC TCL_STUB_LIB_SPEC TCL_EXEC_PREFIX TCL_VERSION} {
- define $k ""
- }
- file delete -force ".tclenv.sh"; # ensure no stale state from previous configures.
- if {![opt-bool tcl]} {
- proj-indented-notice {
- NOTE: TCL is disabled via --disable-tcl. This means that none
- of the TCL-based components will be built, including tests
- and sqlite3_analyzer.
- }
- return
- }
- # TODO: document the steps this is taking.
- global srcdir
- msg-result "Checking for a suitable tcl... "
- proj-assert [proj-opt-truthy tcl]
- set use_tcl 1
- set with_tclsh [opt-val with-tclsh]
- set with_tcl [opt-val with-tcl]
- if {"prefix" eq $with_tcl} {
- set with_tcl [get-define prefix]
- }
- msg-debug "sqlite-check-tcl: use_tcl ${use_tcl}"
- msg-debug "sqlite-check-tcl: with_tclsh=${with_tclsh}"
- msg-debug "sqlite-check-tcl: with_tcl=$with_tcl"
- if {"" eq $with_tclsh && "" eq $with_tcl} {
- # If neither --with-tclsh nor --with-tcl are provided, try to find
- # a workable tclsh.
- set with_tclsh [proj-first-bin-of tclsh9.0 tclsh8.6 tclsh]
- msg-debug "sqlite-check-tcl: with_tclsh=${with_tclsh}"
- }
- set doConfigLookup 1 ; # set to 0 to test the tclConfig.sh-not-found cases
- if {"" ne $with_tclsh} {
- # --with-tclsh was provided or found above. Validate it and use it
- # to trump any value passed via --with-tcl=DIR.
- if {![file isfile $with_tclsh]} {
- proj-fatal "TCL shell $with_tclsh is not a file"
- } elseif {![file-isexec $with_tclsh]} {
- proj-fatal "TCL shell $with_tclsh is not executable"
- } else {
- define TCLSH_CMD $with_tclsh
- #msg-result "Using tclsh: $with_tclsh"
- }
- if {$doConfigLookup &&
- [catch {exec $with_tclsh $srcdir/tool/find_tclconfig.tcl} result] == 0} {
- set with_tcl $result
- }
- if {"" ne $with_tcl && [file isdir $with_tcl]} {
- msg-result "$with_tclsh recommends the tclConfig.sh from $with_tcl"
- } else {
- proj-warn "$with_tclsh is unable to recommend a tclConfig.sh"
- set use_tcl 0
- }
- }
- set cfg ""
- set tclSubdirs {tcl9.0 tcl8.6 lib}
- while {$use_tcl} {
- if {"" ne $with_tcl} {
- # Ensure that we can find tclConfig.sh under ${with_tcl}/...
- if {$doConfigLookup} {
- if {[file readable "${with_tcl}/tclConfig.sh"]} {
- set cfg "${with_tcl}/tclConfig.sh"
- } else {
- foreach i $tclSubdirs {
- if {[file readable "${with_tcl}/$i/tclConfig.sh"]} {
- set cfg "${with_tcl}/$i/tclConfig.sh"
- break
- }
- }
- }
- }
- if {"" eq $cfg} {
- proj-fatal "No tclConfig.sh found under ${with_tcl}"
- }
- } else {
- # If we have not yet found a tclConfig.sh file, look in
- # $libdir which is set automatically by autosetup or by the
- # --prefix command-line option. See
- # https://sqlite.org/forum/forumpost/e04e693439a22457
- set libdir [get-define libdir]
- if {[file readable "${libdir}/tclConfig.sh"]} {
- set cfg "${libdir}/tclConfig.sh"
- } else {
- foreach i $tclSubdirs {
- if {[file readable "${libdir}/$i/tclConfig.sh"]} {
- set cfg "${libdir}/$i/tclConfig.sh"
- break
- }
- }
- }
- if {![file readable $cfg]} {
- break
- }
- }
- msg-result "Using tclConfig.sh: $cfg"
- break
- }
- define TCL_CONFIG_SH $cfg
- # Export a subset of tclConfig.sh to the current TCL-space. If $cfg
- # is an empty string, this emits empty-string entries for the
- # various options we're interested in.
- eval [exec "${srcdir}/tool/tclConfigShToAutoDef.sh" "$cfg"]
- if {"" eq $with_tclsh && $cfg ne ""} {
- # We have tclConfig.sh but no tclsh. Attempt to locate a tclsh
- # based on info from tclConfig.sh.
- proj-assert {"" ne [get-define TCL_EXEC_PREFIX]}
- set with_tclsh [get-define TCL_EXEC_PREFIX]/bin/tclsh[get-define TCL_VERSION]
- if {![file-isexec $with_tclsh]} {
- set with_tclsh2 [get-define TCL_EXEC_PREFIX]/bin/tclsh
- if {![file-isexec $with_tclsh2]} {
- proj-warn "Cannot find a usable tclsh (tried: $with_tclsh $with_tclsh2)"
- } else {
- set with_tclsh $with_tclsh2
- }
- }
- }
- define TCLSH_CMD $with_tclsh
- if {$use_tcl} {
- # Set up the TCLLIBDIR
- #
- # 2024-10-28: calculation of TCLLIBDIR is now done via the shell
- # in main.mk (search it for T.tcl.env.sh) so that
- # static/hand-written makefiles which import main.mk do not have
- # to define that before importing main.mk. Even so, we export
- # TCLLIBDIR from here, which will cause the canonical makefile to
- # use this one rather than to re-calculate it at make-time.
- set tcllibdir [get-env TCLLIBDIR ""]
- if {"" eq $tcllibdir} {
- # Attempt to extract TCLLIBDIR from TCL's $auto_path
- if {"" ne $with_tclsh &&
- [catch {exec echo "puts stdout \$auto_path" | "$with_tclsh"} result] == 0} {
- foreach i $result {
- if {[file isdir $i]} {
- set tcllibdir $i/sqlite3
- break
- }
- }
- } else {
- proj-warn "Cannot determine TCLLIBDIR."
- # The makefile will fail fatally in this case if a target is
- # invoked which requires TCLLIBDIR.
- }
- }
- #if {"" ne $tcllibdir} { msg-result "TCLLIBDIR = ${tcllibdir}"; }
- define TCLLIBDIR $tcllibdir
- }; # find TCLLIBDIR
- if {[file-isexec $with_tclsh]} {
- msg-result "Using tclsh: $with_tclsh"
- if {$cfg ne ""} {
- define HAVE_TCL 1
- } else {
- proj-warn "Found tclsh but no tclConfig.sh."
- }
- }
- show-notices
- # If TCL is not found: if it was explicitly requested then fail
- # fatally, else just emit a warning. If we can find the APIs needed
- # to generate a working JimTCL then that will suffice for build-time
- # TCL purposes (see: proc sqlite-determine-codegen-tcl).
- if {![get-define HAVE_TCL] &&
- ([proj-opt-was-provided tcl] || [proj-opt-was-provided with-tcl])} {
- proj-fatal "TCL support was requested but no tclConfig.sh could be found."
- }
- if {"" eq $cfg} {
- proj-assert {0 == [get-define HAVE_TCL]}
- proj-indented-notice {
- WARNING: Cannot find a usable tclConfig.sh file. Use
- --with-tcl=DIR to specify a directory where tclConfig.sh can be
- found. SQLite does not use TCL internally, but some optional
- components require TCL, including tests and sqlite3_analyzer.
- }
- }
- }; # sqlite-check-tcl
- sqlite-check-tcl
- ########################################################################
- # sqlite-determine-codegen-tcl checks which TCL to use as a code
- # generator. By default, prefer jimsh simply because we have it
- # in-tree (it's part of autosetup) unless --with-tclsh=X is used, in
- # which case prefer X.
- #
- # Returns the human-readable name of the TCL it selects. Fails fatally
- # if it cannot detect a TCL appropriate for code generation.
- #
- # Defines:
- #
- # - BTCLSH = the TCL shell used for code generation. It may set this
- # to an unexpanded makefile var name.
- #
- # - CFLAGS_JIMSH = any flags needed for buildng a BTCLSH-compatible
- # jimsh. The defaults may be passed on to configure as
- # CFLAGS_JIMSH=...
- set useJimForCodeGen 0 ; # Set to 1 when using jimsh for code generation.
- # May affect later decisions.
- proc sqlite-determine-codegen-tcl {} {
- rename sqlite-determine-codegen-tcl ""
- msg-result "Checking for TCL to use for code generation... "
- define CFLAGS_JIMSH [proj-get-env CFLAGS_JIMSH {-O1}]
- set cgtcl [opt-val with-tclsh jimsh]
- if {"jimsh" ne $cgtcl} {
- # When --with-tclsh=X is used, use that for all TCL purposes,
- # including in-tree code generation, per developer request.
- define BTCLSH "\$(TCLSH_CMD)"
- return $cgtcl
- }
- set flagsToRestore {CC CFLAGS AS_CFLAGS CPPFLAGS AS_CPPFLAGS LDFLAGS LINKFLAGS LIBS CROSS}
- define-push $flagsToRestore {
- # We have to swap CC to CC_FOR_BUILD for purposes of the various
- # [cc-...] tests below. Recall that --with-wasi-sdk may have
- # swapped out CC with one which is not appropriate for this block.
- # Per consulation with autosetup's creator, doing this properly
- # requires us to [define-push] the whole $flagsToRestore list
- # (plus a few others which are not relevant in this tree).
- #
- # These will get set to their previous values at the end of this
- # block.
- foreach flag $flagsToRestore {define $flag ""}
- define CC [get-define CC_FOR_BUILD]
- # These headers are technically optional for JimTCL but necessary if
- # we want to use it for code generation:
- set sysh [cc-check-includes dirent.h sys/time.h]
- # jimsh0.c hard-codes #define's for HAVE_DIRENT_H and
- # HAVE_SYS_TIME_H on the platforms it supports, so we do not
- # need to add -D... flags for those. We check for them here only
- # so that we can avoid the situation that we later, at
- # make-time, try to compile jimsh but it then fails due to
- # missing headers (i.e. fail earlier rather than later).
- if {$sysh && [cc-check-functions realpath]} {
- define-append CFLAGS_JIMSH -DHAVE_REALPATH
- define BTCLSH "\$(JIMSH)"
- set ::useJimForCodeGen 1
- } elseif {$sysh && [cc-check-functions _fullpath]} {
- # _fullpath() is a Windows API. It's not entirely clear
- # whether we need to add {-DHAVE_SYS_TIME_H -DHAVE_DIRENT_H}
- # to CFLAGS_JIMSH in this case. On MinGW32 we definitely do
- # not want to because it already hard-codes them. On _MSC_VER
- # builds it does not.
- define-append CFLAGS_JIMSH -DHAVE__FULLPATH
- define BTCLSH "\$(JIMSH)"
- set ::useJimForCodeGen 1
- } elseif {[file-isexec [get-define TCLSH_CMD]]} {
- set cgtcl [get-define TCLSH_CMD]
- define BTCLSH "\$(TCLSH_CMD)"
- } else {
- # One last-ditch effort to find TCLSH_CMD: use info from
- # tclConfig.sh to try to find a tclsh
- if {"" eq [get-define TCLSH_CMD]} {
- set tpre [get-define TCL_EXEC_PREFIX]
- if {"" ne $tpre} {
- set tv [get-define TCL_VERSION]
- if {[file-isexec "${tpre}/bin/tclsh${tv}"]} {
- define TCLSH_CMD "${tpre}/bin/tclsh${tv}"
- } elseif {[file-isexec "${tpre}/bin/tclsh"]} {
- define TCLSH_CMD "${tpre}/bin/tclsh"
- }
- }
- }
- set cgtcl [get-define TCLSH_CMD]
- if {![file-isexec $cgtcl]} {
- proj-fatal "Cannot find a tclsh to use for code generation."
- }
- define BTCLSH "\$(TCLSH_CMD)"
- }
- }; # CC swap-out
- return $cgtcl
- }; # sqlite-determine-codegen-tcl
- msg-result "TCL for code generation: [sqlite-determine-codegen-tcl]"
- # /TCL
- ########################################################################
- ########################################################################
- # Thread safety?
- msg-checking "Support threadsafe operation? "
- proj-if-opt-truthy threadsafe {
- msg-result yes
- sqlite-add-feature-flag -DSQLITE_THREADSAFE=1
- if {![proj-check-function-in-lib pthread_create pthread]
- || ![proj-check-function-in-lib pthread_mutexattr_init pthread]} {
- user-error "Missing required pthread bits"
- }
- define LDFLAGS_PTHREAD [get-define lib_pthread_create]
- undefine lib_pthread_create
- # Recall that LDFLAGS_PTHREAD might be empty even if pthreads if
- # found because it's in -lc on some platforms.
- } {
- msg-result no
- sqlite-add-feature-flag -DSQLITE_THREADSAFE=0
- define LDFLAGS_PTHREAD ""
- }
- ########################################################################
- # Do we want temporary databases in memory?
- #
- apply {{} {
- set ts [opt-val with-tempstore no]
- set tsn 1
- msg-checking "Use an in-RAM database for temporary tables? "
- switch -exact -- $ts {
- never { set tsn 0 }
- no { set tsn 1 }
- yes { set tsn 2 }
- always { set tsn 3 }
- default {
- user-error "Invalid --with-tempstore value '$ts'. Use one of: never, no, yes, always"
- }
- }
- msg-result $ts
- sqlite-add-feature-flag -DSQLITE_TEMP_STORE=$tsn
- }}
- ########################################################################
- # sqlite-check-line-editing jumps through proverbial hoops to try to
- # find a working line-editing library, setting:
- #
- # - HAVE_READLINE to 0 or 1
- # - HAVE_LINENOISE to 0, 1, or 2
- # - HAVE_EDITLINE to 0 or 1
- #
- # Only one of ^^^ those will be set to non-0.
- #
- # - LDFLAGS_READLINE = linker flags or empty string
- #
- # - CFLAGS_READLINE = compilation flags for clients or empty string.
- #
- # Note that LDFLAGS_READLINE and CFLAGS_READLINE may refer to
- # linenoise or editline, not necessarily libreadline. In some cases
- # it will set HAVE_READLINE=1 when it's really using editline, for
- # reasons described in this function's comments.
- #
- # Returns a string describing which line-editing approach to use, or
- # "none" if no option is available.
- #
- # Order of checks:
- #
- # 1) --with-linenoise trumps all others and skips all of the
- # complexities involved with the remaining options.
- #
- # 2) --editline trumps --readline
- #
- # 3) --disable-readline trumps --readline
- #
- # 4) Default to automatic search for optional readline
- #
- # 5) Try to find readline or editline. If it's not found AND the
- # corresponding --FEATURE flag was explicitly given, fail fatally,
- # else fail silently.
- proc sqlite-check-line-editing {} {
- rename sqlite-check-line-editing ""
- msg-result "Checking for line-editing capability..."
- define HAVE_READLINE 0
- define HAVE_LINENOISE 0
- define HAVE_EDITLINE 0
- define LDFLAGS_READLINE ""
- define CFLAGS_READLINE ""
- set failIfNotFound 0 ; # Gets set to 1 for explicit --FEATURE requests
- # so that we know whether to fail fatally or not
- # if the library is not found.
- set libsForReadline {readline edit} ; # -l<LIB> names to check for readline().
- # The libedit check changes this.
- set editLibName "readline" ; # "readline" or "editline"
- set editLibDef "HAVE_READLINE" ; # "HAVE_READLINE" or "HAVE_EDITLINE"
- set dirLn [opt-val with-linenoise]
- if {"" ne $dirLn} {
- # Use linenoise from a copy of its sources (not a library)...
- if {![file isdir $dirLn]} {
- proj-fatal "--with-linenoise value is not a directory"
- }
- set lnH $dirLn/linenoise.h
- if {![file exists $lnH] } {
- proj-fatal "Cannot find linenoise.h in $dirLn"
- }
- set lnC ""
- set lnCOpts {linenoise-ship.c linenoise.c}
- foreach f $lnCOpts {
- if {[file exists $dirLn/$f]} {
- set lnC $dirLn/$f
- break;
- }
- }
- if {"" eq $lnC} {
- proj-fatal "Cannot find any of $lnCOpts in $dirLn"
- }
- set flavor ""
- set lnVal [proj-which-linenoise $lnH]
- switch -- $lnVal {
- 1 { set flavor "antirez" }
- 2 { set flavor "msteveb" }
- default {
- proj-fatal "Cannot determine the flavor of linenoise from $lnH"
- }
- }
- define CFLAGS_READLINE "-I$dirLn $lnC"
- define HAVE_LINENOISE $lnVal
- sqlite-add-shell-opt -DHAVE_LINENOISE=$lnVal
- if {$::useJimForCodeGen && 2 == $lnVal} {
- define-append CFLAGS_JIMSH -DUSE_LINENOISE [get-define CFLAGS_READLINE]
- user-notice "Adding linenoise support to jimsh."
- }
- return "linenoise ($flavor)"
- } elseif {[opt-bool editline]} {
- # libedit mimics libreadline and on some systems does not have its
- # own header installed (instead, that of libreadline is used).
- #
- # shell.c historically expects HAVE_EDITLINE to be set for
- # libedit, but it then expects to see <editline/readline.h>, which
- # some system's don't actually have despite having libedit. If we
- # end up finding <editline/readline.h> below, we will use
- # -DHAVE_EDITLINE=1, else we will use -DHAVE_READLINE=1. In either
- # case, we will link against libedit.
- set failIfNotFound 1
- set libsForReadline {edit}
- set editLibName editline
- } elseif {![opt-bool readline]} {
- msg-result "Readline support explicitly disabled with --disable-readline"
- return "none"
- } elseif {[proj-opt-was-provided readline]} {
- # If an explicit --[enable-]readline was used, fail if it's not
- # found, else treat the feature as optional.
- set failIfNotFound 1
- }
- # Transform with-readline-header=X to with-readline-cflags=-I...
- set v [opt-val with-readline-header]
- proj-opt-set with-readline-header ""
- if {"" ne $v} {
- if {"auto" eq $v} {
- proj-opt-set with-readline-cflags auto
- } else {
- set v [file dirname $v]
- if {[string match */readline $v]} {
- # Special case: if the path includes .../readline/readline.h,
- # set the -I to one dir up from that because our sources
- # #include <readline/readline.h> or <editline/readline.h>.
- set v [file dirname $v]
- }
- proj-opt-set with-readline-cflags "-I$v"
- }
- }
- # Look for readline.h
- set rlInc [opt-val with-readline-cflags auto]
- if {"auto" eq $rlInc} {
- set rlInc ""
- if {$::isCrossCompiling} {
- # ^^^ this check is derived from the legacy configure script.
- proj-warn "Skipping check for readline.h because we're cross-compiling."
- } else {
- set dirs "[get-define prefix] /usr /usr/local /usr/local/readline /usr/contrib /mingw"
- set subdirs "include/$editLibName"
- if {"editline" eq $editLibName} {
- lappend subdirs include/readline
- # ^^^ editline, on some systems, does not have its own header,
- # and uses libreadline's header.
- }
- lappend subdirs include
- # ^^^ The dirs and subdirs lists are, except for the inclusion
- # of $prefix and editline, from the legacy configure script
- set rlInc [proj-search-for-header-dir readline.h \
- -dirs $dirs -subdirs $subdirs]
- if {"" ne $rlInc} {
- if {[string match */readline $rlInc]} {
- set rlInc [file dirname $rlInc]; # shell #include's <readline/readline.h>
- } elseif {[string match */editline $rlInc]} {
- set editLibDef HAVE_EDITLINE
- set rlInc [file dirname $rlInc]; # shell #include's <editline/readline.h>
- }
- set rlInc "-I${rlInc}"
- }
- }
- } elseif {"" ne $rlInc && ![string match *-I* $rlInc]} {
- proj-fatal "Argument to --with-readline-cflags is intended to be CFLAGS and contain -I..."
- }
- # If readline.h was found/specified, look for lib(readline|edit)...
- #
- # This is not quite straightforward because both libreadline and
- # libedit typically require some other library which (according to
- # legacy autotools-generated tests) provides tgetent(3). On some
- # systems that's built into libreadline/edit, on some (most?) its in
- # lib[n]curses, and on some it's in libtermcap.
- set rlLib ""
- if {"" ne $rlInc} {
- set rlLib [opt-val with-readline-ldflags]
- if {"" eq $rlLib || "auto" eq $rlLib} {
- set rlLib ""
- set libTerm ""
- if {[proj-check-function-in-lib tgetent "$editLibName ncurses curses termcap"]} {
- # ^^^ that libs list comes from the legacy configure script ^^^
- set libTerm [get-define lib_tgetent]
- undefine lib_tgetent
- }
- if {$editLibName eq $libTerm} {
- set rlLib $libTerm
- } elseif {[proj-check-function-in-lib readline $libsForReadline $libTerm]} {
- set rlLib [get-define lib_readline]
- lappend rlLib $libTerm
- undefine lib_readline
- }
- }
- }
- # If we found a library, configure the build to use it...
- if {"" ne $rlLib} {
- if {"editline" eq $editLibName && "HAVE_READLINE" eq $editLibDef} {
- # Alert the user that, despite outward appearances, we won't be
- # linking to the GPL'd libreadline. Presumably that distinction is
- # significant for those using --editline.
- proj-indented-notice {
- NOTE: the local libedit but uses <readline/readline.h> so we
- will compile with -DHAVE_READLINE=1 but will link with
- libedit.
- }
- }
- set rlLib [join $rlLib]
- set rlInc [join $rlInc]
- define LDFLAGS_READLINE $rlLib
- define CFLAGS_READLINE $rlInc
- proj-assert {$editLibDef in {HAVE_READLINE HAVE_EDITLINE}}
- proj-assert {$editLibName in {readline editline}}
- sqlite-add-shell-opt -D${editLibDef}=1
- msg-result "Using $editLibName flags: $rlInc $rlLib"
- # Check whether rl_completion_matches() has a signature we can use
- # and disable that sub-feature if it doesn't.
- if {![cctest \
- -cflags "$rlInc -D${editLibDef}" -libs $rlLib -nooutput 1 -source {
- #include <stdio.h>
- #ifdef HAVE_EDITLINE
- #include <editline/readline.h>
- #else
- #include <readline/readline.h>
- #endif
- static char * rcg(const char *z, int i){(void)z; (void)i; return 0;}
- int main(void) {
- char ** x = rl_completion_matches("one", rcg);
- (void)x;
- return 0;
- }
- }]} {
- proj-warn "readline-style completion disabled due to rl_completion_matches() signature mismatch"
- sqlite-add-shell-opt -DSQLITE_OMIT_READLINE_COMPLETION
- }
- return $editLibName
- }
- if {$failIfNotFound} {
- proj-fatal "Explicit --$editLibName failed to find a matching library."
- }
- return "none"
- }; # sqlite-check-line-editing
- msg-result "Line-editing support for the sqlite3 shell: [sqlite-check-line-editing]"
- proj-if-opt-truthy load-extension {
- if {[proj-check-function-in-lib dlopen dl]} {
- define LDFLAGS_DLOPEN [get-define lib_dlopen]
- undefine lib_dlopen
- } else {
- user-error "dlopen() not found. Use --disable-load-extension to bypass this check."
- }
- } {
- define LDFLAGS_DLOPEN ""
- sqlite-add-feature-flag {-DSQLITE_OMIT_LOAD_EXTENSION=1}
- msg-result "Disabling loadable extensions."
- }
- proj-if-opt-truthy math {
- if {![proj-check-function-in-lib ceil m]} {
- user-error "Cannot find libm functions. Use --disable-math to bypass this."
- }
- define LDFLAGS_MATH [get-define lib_ceil]
- undefine lib_ceil
- sqlite-add-feature-flag {-DSQLITE_ENABLE_MATH_FUNCTIONS}
- msg-result "Enabling math SQL functions [get-define LDFLAGS_MATH]"
- } {
- define LDFLAGS_MATH ""
- msg-result "Disabling math SQL functions"
- }
- ########################################################################
- # ICU - International Components for Unicode
- #
- # Handles these flags:
- #
- # --with-icu-ldflags=LDFLAGS
- # --with-icu-cflags=CFLAGS
- # --with-icu-config[=auto | pkg-config | /path/to/icu-config]
- # --enable-icu-collations
- #
- # --with-icu-config values:
- #
- # - auto: use the first one of (pkg-config, icu-config) found on the
- # system.
- # - pkg-config: use only pkg-config to determine flags
- # - /path/to/icu-config: use that to determine flags
- #
- # If --with-icu-config is used as neither pkg-config nor icu-config
- # are found, fail fatally.
- #
- # If both --with-icu-ldflags and --with-icu-config are provided, they
- # are cumulative. If neither are provided, icu-collations is not
- # honored and a warning is emitted if it is provided.
- #
- # Design note: though we could automatically enable ICU if the
- # icu-config binary or (pkg-config icu-io) are found, we specifically
- # do not. ICU is always an opt-in feature.
- proc sqlite-check-icu {} {
- rename sqlite-check-icu ""
- define LDFLAGS_ICU [join [opt-val with-icu-ldflags ""]]
- define CFLAGS_ICU [join [opt-val with-icu-cflags ""]]
- if {[proj-opt-was-provided with-icu-config]} {
- set icuConfigBin [opt-val with-icu-config]
- set tryIcuConfigBin 1; # set to 0 if we end up using pkg-config
- if {"auto" eq $icuConfigBin || "pkg-config" eq $icuConfigBin} {
- if {[pkg-config-init 0] && [pkg-config icu-io]} {
- # Maintenance reminder: historical docs say to use both of
- # (icu-io, icu-uc). icu-uc lacks a required lib and icu-io has
- # all of them on tested OSes.
- set tryIcuConfigBin 0
- define LDFLAGS_ICU [get-define PKG_ICU_IO_LDFLAGS]
- define-append LDFLAGS_ICU [get-define PKG_ICU_IO_LIBS]
- define CFLAGS_ICU [get-define PKG_ICU_IO_CFLAGS]
- } elseif {"pkg-config" eq $icuConfigBin} {
- proj-fatal "pkg-config cannot find package icu-io"
- } else {
- proj-assert {"auto" eq $icuConfigBin}
- }
- }
- if {$tryIcuConfigBin} {
- if {"auto" eq $icuConfigBin} {
- set icuConfigBin [proj-first-bin-of \
- /usr/local/bin/icu-config \
- /usr/bin/icu-config]
- if {"" eq $icuConfigBin} {
- proj-fatal "--with-icu-config=auto cannot find (pkg-config icu-io) or icu-config binary"
- }
- }
- if {[file-isexec $icuConfigBin]} {
- set x [exec $icuConfigBin --ldflags]
- if {"" eq $x} {
- proj-fatal "$icuConfigBin --ldflags returned no data"
- }
- define-append LDFLAGS_ICU $x
- set x [exec $icuConfigBin --cppflags]
- define-append CFLAGS_ICU $x
- } else {
- proj-fatal "--with-icu-config=$bin does not refer to an executable"
- }
- }
- }
- set ldflags [define LDFLAGS_ICU [string trim [get-define LDFLAGS_ICU]]]
- set cflags [define CFLAGS_ICU [string trim [get-define CFLAGS_ICU]]]
- if {"" ne $ldflags} {
- sqlite-add-feature-flag -shell -DSQLITE_ENABLE_ICU
- msg-result "Enabling ICU support with flags: $ldflags $cflags"
- if {[opt-bool icu-collations]} {
- msg-result "Enabling ICU collations."
- sqlite-add-feature-flag -shell -DSQLITE_ENABLE_ICU_COLLATIONS
- # Recall that shell.c builds with sqlite3.c
- }
- } elseif {[opt-bool icu-collations]} {
- proj-warn "ignoring --enable-icu-collations because neither --with-icu-ldflags nor --with-icu-config provided any linker flags"
- } else {
- msg-result "ICU support is disabled."
- }
- }; # sqlite-check-icu
- sqlite-check-icu
- ########################################################################
- # Check for the Emscripten SDK for building the web-based wasm
- # components. The core lib and tools do not require this but ext/wasm
- # does.
- apply {{} {
- if {$::autosetup(srcdir) ne $::autosetup(builddir)} {
- # The EMSDK pieces require writing to the original source tree
- # even when doing an out-of-tree build. The ext/wasm pieces do not
- # support an out-of-tree build so we catch that case and treat it
- # as if EMSDK were not found.
- msg-result "Out-of tree build: not checking for EMSDK."
- define EMCC_WRAPPER ""
- return
- }
- set emccsh $::srcdir/tool/emcc.sh
- if {![get-define HAVE_WASI_SDK] && [proj-check-emsdk]} {
- define EMCC_WRAPPER $emccsh
- proj-make-from-dot-in $emccsh
- catch {exec chmod u+x $emccsh}
- } else {
- define EMCC_WRAPPER ""
- file delete -force $emccsh
- }
- }}
- ########################################################################
- # Check for log(3) in libm and die with an error if it is not
- # found. $featureName should be the feature name which requires that
- # function (it's used only in error messages). defines LDFLAGS_MATH to
- # the required linker flags (which may be empty even if the math APIs
- # are found, depending on the OS).
- proc affirm-have-math {featureName} {
- if {"" eq [get-define LDFLAGS_MATH ""]} {
- if {![msg-quiet proj-check-function-in-lib log m]} {
- user-error "Missing math APIs for $featureName"
- }
- define LDFLAGS_MATH [get-define lib_log ""]
- undefine lib_log
- }
- }
- ########################################################################
- # Handle various SQLITE_ENABLE_... feature flags.
- msg-result "Feature flags..."
- foreach {boolFlag featureFlag ifSetEvalThis} {
- all {} {
- # The 'all' option must be first in this list.
- proj-opt-set fts4
- proj-opt-set fts5
- proj-opt-set geopoly
- proj-opt-set rtree
- proj-opt-set session
- }
- fts4 -DSQLITE_ENABLE_FTS4 {affirm-have-math fts4}
- fts5 -DSQLITE_ENABLE_FTS5 {affirm-have-math fts5}
- geopoly -DSQLITE_ENABLE_GEOPOLY {proj-opt-set rtree}
- rtree -DSQLITE_ENABLE_RTREE {}
- session {-DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK} {}
- update-limit -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT {}
- memsys5 -DSQLITE_ENABLE_MEMSYS5 {}
- memsys3 {} {
- if {[opt-bool memsys5]} {
- proj-warn "not enabling memsys3 because memsys5 is enabled."
- expr 0
- } else {
- sqlite-add-feature-flag -DSQLITE_ENABLE_MEMSYS3
- }
- }
- scanstatus -DSQLITE_ENABLE_STMT_SCANSTATUS {}
- } {
- proj-if-opt-truthy $boolFlag {
- sqlite-add-feature-flag $featureFlag
- if {0 != [eval $ifSetEvalThis] && "all" ne $boolFlag} {
- msg-result " + $boolFlag"
- }
- } {
- if {"all" ne $boolFlag} {
- msg-result " - $boolFlag"
- }
- }
- }
- ########################################################################
- # Invert the above loop's logic for some SQLITE_OMIT_... cases. If
- # config option $boolFlag is false, [sqlite-add-feature-flag
- # $featureFlag], where $featureFlag is intended to be
- # -DSQLITE_OMIT_...
- foreach {boolFlag featureFlag} {
- json -DSQLITE_OMIT_JSON
- } {
- if {[proj-opt-truthy $boolFlag]} {
- msg-result " + $boolFlag"
- } else {
- sqlite-add-feature-flag $featureFlag
- msg-result " - $boolFlag"
- }
- }
- #########################################################################
- # Show the final feature flag sets:
- apply {{} {
- set oFF [get-define OPT_FEATURE_FLAGS]
- if {"" ne $oFF} {
- define OPT_FEATURE_FLAGS [lsort -unique $oFF]
- msg-result "Library feature flags: [get-define OPT_FEATURE_FLAGS]"
- }
- set oFF [get-define OPT_SHELL]
- if {"" ne $oFF} {
- define OPT_SHELL [lsort -unique $oFF]
- msg-result "Shell options: [get-define OPT_SHELL]"
- }
- unset oFF
- }}
- ########################################################################
- # "Re-export" the autoconf-conventional --XYZdir flags into something
- # which is more easily overridable from a make invocation. See the docs
- # for [proj-remap-autoconf-dir-vars] for the explanation of why.
- #
- # We do this late in the config process, immediately before we export
- # the Makefile and other generated files, so that configure tests
- # which make make use of the autotools-conventional flags
- # (e.g. [proj-check-rpath]) may do so before we "mangle" them here.
- proj-remap-autoconf-dir-vars
- ########################################################################
- # Generate the output files.
- #
- # Potential TODO (unclear): in sqlite3.pc.in, do we need to include
- # any CFLAGS_READLINE, CFLAGS_ZLIB, etc in its "Cflags:" section?
- proj-make-from-dot-in -touch Makefile sqlite3.pc
- make-config-header sqlite_cfg.h \
- -bare {SIZEOF_* HAVE_DECL_*} \
- -none {HAVE_CFLAG_* LDFLAGS_* SH_* SQLITE_AUTORECONFIG
- TARGET_* USE_GCOV TCL_*} \
- -auto {HAVE_* PACKAGE_*} \
- -none *
- proj-touch sqlite_cfg.h ; # help avoid frequent unnecessary @SQLITE_AUTORECONFIG@
- ########################################################################
- # Some build-dev/debug-only output
- proj-if-opt-truthy dump-defines {
- make-config-header $::DUMP_DEFINES_TXT \
- -bare {SQLITE_OS* SQLITE_DEBUG USE_*} \
- -str {BIN_* CC LD AR LDFLAG* OPT_*} \
- -auto {*}
- # achtung: ^^^^ whichever SQLITE_OS_foo flag which is set to 0 will
- # get _undefined_ here unless it's part of the -bare set.
- if {"" ne $DUMP_DEFINES_JSON} {
- msg-result "--dump-defines is creating $::DUMP_DEFINES_JSON"
- ########################################################################
- # Dump config-defines.json...
- # Demonstrate (mis?)handling of spaces in JSON-export array values:
- # define-append OPT_FOO.list {"-DFOO=bar baz" -DBAR="baz barre"}
- define OPT_FEATURE_FLAGS.list [get-define OPT_FEATURE_FLAGS]
- define OPT_SHELL.list [get-define OPT_SHELL]
- set dumpDefsOpt {
- -bare {SIZEOF_* HAVE_DECL_*}
- -none {HAVE_CFLAG_* LDFLAGS_* SH_* SQLITE_AUTORECONFIG TARGET_* USE_GCOV TCL_*}
- -array {*.list}
- -auto {OPT_* PACKAGE_* HAVE_*}
- }
- if {[opt-bool defines-json-include-lowercase]} {
- lappend dumpDefsOpt -none {lib_*} ; # remnants from proj-check-function-in-lib and friends
- lappend dumpDefsOpt -auto {[a-z]*}
- }
- lappend dumpDefsOpt -none *
- proj-dump-defs-json $DUMP_DEFINES_JSON {*}$dumpDefsOpt
- undefine OPT_FEATURE_FLAGS.list
- undefine OPT_SHELL.list
- }
- }
- ########################################################################
- # Perform some high-level validation on the generated files...
- #
- # 1) Ensure that no unresolved @VAR@ placeholders are in files which
- # use those.
- #
- # 2) TBD
- apply {{} {
- # Check #1: ensure that files which get filtered for @VAR@ do not
- # contain any unresolved @VAR@ refs. That may indicate an
- # unexported/unused var or a typo.
- foreach f "Makefile sqlite3.pc $::srcdir/tool/emcc.sh" {
- if {![file exists $f]} continue
- set lnno 1
- foreach line [proj-file-content-list $f] {
- if {[regexp {(@[A-Za-z_]+@)} $line match]} {
- error "Unresolved reference to $match at line $lnno of $f"
- }
- incr lnno
- }
- }
- }}
|