f154cef8f2
FossilOrigin-Name: 6bfd09408b9a51c0cbdb28f901a79c9774da755294d7eb67d88e4c42c5652830
1336 lines
49 KiB
Modula-2
1336 lines
49 KiB
Modula-2
#/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
|
|
|
|
# $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, and alias for --debug=1.
|
|
#
|
|
# 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].
|
|
#
|
|
########################################################################
|
|
# 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, and explicitly adding flags
|
|
# with those prefixes will force them to be boolean flags. 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
|
|
#
|
|
# Trying to pass --readline or --readline=1 or --readline=0 will
|
|
# result in an "unrecognized option" error, despite the the [options]
|
|
# call listing the flag as "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
|
|
# defaulting 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. Autosetup may, however, choose to automatically alter the help
|
|
# text, as demonstrated here:
|
|
#
|
|
# options {
|
|
# readline=1 => {Disable readline support}
|
|
# with-readline-lib: => {Readline library}
|
|
# with-readline-inc: => {Readline include paths}
|
|
# }
|
|
#
|
|
# $ ./configure --help | grep readline
|
|
# --disable-readline disable readline support
|
|
# --with-readline-lib specify readline library
|
|
# --with-readline-inc specify readline include paths
|
|
#
|
|
# Note that it prefixed and lower-case the help message. Whether
|
|
# that's a feature or a bug can be debated.
|
|
#
|
|
# 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?]
|
|
#
|
|
########################################################################
|
|
set flags {
|
|
# <build-modes>
|
|
with-debug:=1 => {Enable debug build flags}
|
|
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 may be either a dir containing tclConfig.sh or a
|
|
# dir one level up from that from which we can derive a dir
|
|
# containing tclConfig.sh.
|
|
with-tcl: => {Root of path containing tclConfig.sh}
|
|
# If --with-tclsh=X given, 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!
|
|
with-tclsh:PATH => {Full pathname of tclsh to use}
|
|
# --disable-tcl disables building of components which require TCL,
|
|
# including 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=1 => {Disable components which require TCL}
|
|
# <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-config:=auto => {Enable SQLITE_ENABLE_ICU and fetch linker flags from the given icu-config binary}
|
|
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>
|
|
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)}
|
|
#soname:=none => {SONAME for libsqlite3.so}
|
|
#^^^ we "could", but arguably shouldn't, support clients passing a
|
|
# value of libsqlite3.so.0 for compatibility with clients which
|
|
# linked against a pre-3.48 build.
|
|
# Maybe we should support values of --soname=(none,auto,legacy), where auto means
|
|
# to use the 3.48+ value of libsqlite3.so.3..
|
|
# </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
|
|
}
|
|
|
|
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"
|
|
|
|
if {1} {
|
|
#
|
|
# 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
|
|
# todo? add -DSQLITE_OS_WIN=1 to CFLAGS or CFLAGS_sqlite3_os?
|
|
} else {
|
|
define SQLITE_OS_UNIX 1
|
|
define SQLITE_OS_WIN 0
|
|
# todo? add -DSQLITE_OS_UNIX=1 to CFLAGS or CFLAGS_sqlite3_os
|
|
}
|
|
|
|
#########
|
|
# 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."
|
|
}
|
|
|
|
########################################################################
|
|
# 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}]
|
|
|
|
########################################################################
|
|
# Handle --with-wasi-sdk=DIR
|
|
#
|
|
# This MUST be run 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 flags which must be switched off:
|
|
foreach opt {
|
|
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-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
|
|
|
|
#
|
|
# 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
|
|
|
|
########################################################################
|
|
# It's not yet clear whether we gain anything from setting -soname,
|
|
# but not having it has been a source of anxiety for some users.
|
|
# Setting it to any value other than its historical value of
|
|
# libsqlite3.so.0 may (this is not certain) break dynamic linking of
|
|
# clients which initially linked against a legacy build.
|
|
#
|
|
# See discussion in/around:
|
|
# https://sqlite.org/forum/forumpost/0c6fc6f46b2cb3
|
|
proc sqlite-check-soname {} {
|
|
define LDFLAGS_SONAME_LIBSQLITE3 ""
|
|
if {[proj-opt-was-provided soname]} {
|
|
set soname [opt-val soname]
|
|
} else {
|
|
return 0
|
|
}
|
|
switch -exact -- $soname {
|
|
none { return 0 }
|
|
auto - 3 { set soname libsqlite3.so.3 }
|
|
legacy - 0 { set soname libsqlite3.so.0 }
|
|
default {
|
|
proj-fatal "Invalid value for --soname. Use one of (none, auto, legacy)."
|
|
}
|
|
}
|
|
msg-debug "soname=$soname"
|
|
if {[proj-check-soname $soname]} {
|
|
define LDFLAGS_SONAME_LIBSQLITE3 [get-define LDFLAGS_SONAME_PREFIX]$soname
|
|
msg-result "Setting SONAME: [get-define LDFLAGS_SONAME_LIBSQLITE3]"
|
|
} else {
|
|
proj-fatal "This environment does not support SONAME."
|
|
}
|
|
return sqlite-check-soname ""
|
|
}
|
|
sqlite-check-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 with-debug {
|
|
define SQLITE_DEBUG 1
|
|
define TARGET_DEBUG {-g -DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0 -Wall}
|
|
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 {} {
|
|
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
|
|
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, including tests and sqlite3_analyzer,
|
|
will be built.
|
|
}
|
|
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/tclConfigShToTcl.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 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 prefix 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 {} {
|
|
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]
|
|
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]
|
|
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)"
|
|
} else {
|
|
# 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
|
|
} {
|
|
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 -- $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
|
|
define 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 {} {
|
|
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-config[=/path/to/icu-config]
|
|
# --enable-icu-collations
|
|
#
|
|
# If both icu-ldflags and 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 can automatically enable ICU if the
|
|
# icu-config binary is found, we specifically do not. ICU is always an
|
|
# opt-in feature.
|
|
proc sqlite-check-icu {} {
|
|
define LDFLAGS_ICU [join [opt-val with-icu-ldflags ""]]
|
|
# Flags sets seen in the wild for ICU:
|
|
# - -licui18n -licuuc -licudata
|
|
# - -licui18n -licuuc
|
|
# - /usr/local/bin/icu-config --ldflags
|
|
if {[proj-opt-was-provided with-icu-config]} {
|
|
set bin [opt-val with-icu-config]
|
|
if {"auto" eq $bin} {
|
|
set bin [proj-first-bin-of \
|
|
[get-define prefix]/bin/icu-config \
|
|
/usr/local/bin/icu-config \
|
|
/usr/bin/icu-config]
|
|
if {"" eq $bin} {
|
|
proj-fatal "--with-icu-config=auto cannot find icu-config binary"
|
|
}
|
|
}
|
|
if {[file-isexec $bin]} {
|
|
set x [exec $bin --ldflags]
|
|
if {"" eq $x} {
|
|
proj-fatal "$bin --ldflags returned no data"
|
|
}
|
|
define-append LDFLAGS_ICU $x
|
|
} else {
|
|
proj-fatal "--with-icu-config=$bin does not refer to an executable"
|
|
}
|
|
}
|
|
set flags [define LDFLAGS_ICU [string trim [get-define LDFLAGS_ICU]]]
|
|
if {"" ne $flags} {
|
|
sqlite-add-feature-flag -shell -DSQLITE_ENABLE_ICU
|
|
msg-result "Enabling ICU support with libs: $flags"
|
|
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
|
|
|
|
########################################################################
|
|
# Emscripten SDK for building the web-based wasm components.
|
|
#
|
|
proc sqlite-check-emsdk {} {
|
|
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
|
|
}
|
|
}
|
|
sqlite-check-emsdk
|
|
|
|
########################################################################
|
|
# 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 {} {
|
|
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
|
|
}
|
|
}
|
|
} {
|
|
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:
|
|
if {1} {
|
|
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 may 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
|
|
if {0} {
|
|
# Requires a hand-written sqlite_cfg.h.in...
|
|
proj-make-from-dot-in sqlite_cfg.h
|
|
# vs...
|
|
} else {
|
|
# Requires no input template...
|
|
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
|
|
}
|
|
}
|