1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-05-10 01:41:06 +03:00
sqlite/autosetup/sqlite-config.tcl

2132 lines
80 KiB
Tcl

# This file holds functions for autosetup which are specific to the
# sqlite build tree. They are in this file, instead of auto.def, so
# that they can be reused in the autoconf sub-tree. This file requires
# functions from proj.tcl.
if {[string first " " $autosetup(srcdir)] != -1} {
user-error "The pathname of the source tree\
may not contain space characters"
}
if {[string first " " $autosetup(builddir)] != -1} {
user-error "The pathname of the build directory\
may not contain space characters"
}
#parray ::autosetup; exit 0
use proj
#
# We want the package version info to be emitted early on, but doing
# so requires a bit of juggling. We have to [use system] for
# --prefix=... to work and to emit the Host/Build system info, but we
# don't want those to interfere with --help output.
define PACKAGE_VERSION [proj-file-content -trim $::autosetup(srcdir)/VERSION]
if {"--help" ni $::argv} {
msg-result "Configuring SQLite version [get-define PACKAGE_VERSION]"
}
use system ; # Will output "Host System" and "Build System" lines
if {"--help" ni $::argv} {
msg-result "Source dir = $::autosetup(srcdir)"
msg-result "Build dir = $::autosetup(builddir)"
use cc cc-db cc-shared cc-lib pkg-config
}
#
# Object for communicating certain config-time state across various
# auto.def-related pieces.
array set sqliteConfig [subst [proj-strip-hash-comments {
#
# Gets set by [sqlite-configure] (the main configure script driver).
build-mode unknown
#
# Gets set to 1 when using jimsh for code generation. May affect
# later decisions.
use-jim-for-codegen 0
#
# Set to 1 when cross-compiling This value may be changed by certain
# build options, so it's important that config code which checks for
# cross-compilation uses this var instead of
# [proj-is-cross-compiling].
is-cross-compiling [proj-is-cross-compiling]
#
# Pass msg-debug=1 to configure to enable obnoxiously loud output
# from [msg-debug].
msg-debug-enabled 0
#
# Output file for --dump-defines. Intended only for build debugging
# and not part of the public build interface.
dump-defines-txt ./config.defines.txt
#
# If not empty then --dump-defines will dump not only
# (dump-defines-txt) but also a JSON file named after this option's
# value.
dump-defines-json ""
}]]
########################################################################
# Processes all configure --flags for this build, run build-specific
# config checks, then finalize the configure process. $buildMode must
# be one of (canonical, autoconf), and others may be added in the
# future. After bootstrapping, $configScript is eval'd in the caller's
# scope, then post-configuration finalization is run. $configScript is
# intended to hold configure code which is specific to the given
# $buildMode, with the caveat that _some_ build-specific code is
# encapsulated in the configuration finalization step.
#
# The intent is that all (or almost all) build-mode-specific
# configuration goes inside the $configScript argument to this
# function, and that an auto.def file contains only two commands:
#
# use sqlite-config
# sqlite-configure BUILD_NAME { build-specific configure script }
#
# There are snippets of build-mode-specific decision-making in
# [sqlite-configure-finalize]
proc sqlite-configure {buildMode configScript} {
proj-assert {$::sqliteConfig(build-mode) eq "unknown"} \
"sqlite-configure must not be called more than once"
set allBuildModes {canonical autoconf tcl-extension}
if {$buildMode ni $allBuildModes} {
user-error "Invalid build mode: $buildMode. Expecting one of: $allBuildModes"
}
set ::sqliteConfig(build-mode) $buildMode
########################################################################
# 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. 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"
# stringopt:DESCR => As for stringopt: with a description for the 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. That 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
#
# [proj-opt-was-provided] can be used to determine whether a flag was
# explicitly provided, which is often useful for distinguishing from
# the case of a default value.
########################################################################
set allFlags {
# Structure: a list of M {Z} pairs, where M is a descriptive
# option group name and Z is a list of X Y pairs. X is a list of
# $buildMode name(s) to which the Y flags apply, or {*} to apply
# to all builds. Y is a {block} in the form expected by
# autosetup's [options] command. Each block which is applicable
# to $buildMode is appended to a new list before that list is
# passed on to [options]. The order of each Y and sub-Y is
# retained, which is significant for rendering of --help.
# When writing {help text blocks}, be aware that:
#
# A) autosetup formats them differently if the {block} starts with
# a newline: it starts left-aligned, directly under the --flag, and
# the rest of the block is pasted verbatim rather than
# pretty-printed.
#
# B) Vars and commands are NOT expanded, but we use a [subst] call
# below which will replace (only) var refs.
# Options for how to build the library
build-modes {
{canonical autoconf} {
shared=1 => {Disable build of shared library}
static=1 => {Disable build of static library}
}
{canonical} {
amalgamation=1 => {Disable the amalgamation and instead build all files separately}
}
}
# Library-level features and defaults
lib-features {
{*} {
threadsafe=1 => {Disable mutexing}
with-tempstore:=no => {Use an in-RAM database for temporary tables: never,no,yes,always}
load-extension=1 => {Disable loading of external extensions}
# ^^^ one of the downstream custom builds overrides the load-extension default to 0, which
# confuses the --help text generator. https://github.com/msteveb/autosetup/issues/77
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}
largefile=1
=> {This legacy flag has no effect on the library but may influence
the generated sqlite_cfg.h by adding #define HAVE_LFS}
}
}
# Options for TCL support
tcl {
{canonical} {
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.}
}
{canonical tcl-extension} {
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!}
}
}
# Options for line-editing modes for the CLI shell
line-editing {
{canonical autoconf} {
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}
}
}
# Options for ICU: International Components for Unicode
icu {
{*} {
with-icu-ldflags:LDFLAGS
=> {Enable SQLITE_ENABLE_ICU and add the given linker flags for the
ICU libraries. e.g. on Ubuntu systems, try '-licui18n -licuuc -licudata'.}
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}
}
}
# Options for exotic/alternative build modes
alternative-builds {
{canonical autoconf} {
with-wasi-sdk:=/opt/wasi-sdk
=> {Top-most dir of the wasi-sdk for a WASI build}
}
{canonical} {
with-emsdk:=auto
=> {Top-most dir of the Emscripten SDK installation.
Needed only by ext/wasm. Default=EMSDK env var.}
amalgamation-extra-src:FILES
=> {Space-separated list of soure files to append as-is to the resulting
sqlite3.c amalgamation file. May be provided multiple times.}
}
}
# Options primarily for downstream packagers/package maintainers
packaging {
{autoconf} {
# --disable-static-shell: https://sqlite.org/forum/forumpost/cc219ee704
static-shell=1
=> {Link the sqlite3 shell app against the DLL instead of embedding sqlite3.c}
}
{canonical autoconf} {
# A potential TODO without a current use case:
#rpath=1 => {Disable use of the rpath linker flag}
# soname: https://sqlite.org/src/forumpost/5a3b44f510df8ded
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".}
# dll-basename: https://sqlite.org/forum/forumpost/828fdfe904
dll-basename:=auto
=> {Specifies the base name of the resulting DLL file.
If not provided, "libsqlite3" is usually assumed but on some platforms
a platform-dependent default is used. On some platforms this flag
gets automatically enabled if it is not provided. Use "default" to
explicitly disable platform-dependent activation on such systems.}
# out-implib: https://sqlite.org/forum/forumpost/0c7fc097b2
out-implib:=auto
=> {Enable use of --out-implib linker flag to generate an
"import library" for the DLL. The output's base name is
specified by this flag's value, with "auto" meaning to figure
out a name automatically. On some platforms this flag gets
automatically enabled if it is not provided. Use "none" to
explicitly disable this feature on such platforms.}
}
}
# Options mostly for sqlite's own development
developer {
{*} {
# Note that using the --debug/--enable-debug flag here
# requires patching autosetup/autosetup to rename its builtin
# --debug to --autosetup-debug. See details in
# autosetup/README.md#patching.
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}
}
{canonical} {
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}
dynlink-tools
=> {Dynamically link libsqlite3 to certain tools which normally statically embed it}
asan-fsanitize:=auto
=> {Comma- or space-separated list of -fsanitize flags for use with the
fuzzcheck-asan tool. Only those which the compiler claims to support
will actually be used. May be provided multiple times.}
}
{*} {
dump-defines=0
=> {Dump autosetup defines to $::sqliteConfig(dump-defines-txt)
(for build debugging)}
}
}
}; # $allFlags
set allFlags [proj-strip-hash-comments $allFlags]
# ^^^ lappend of [sqlite-custom-flags] introduces weirdness if
# we delay [proj-strip-hash-comments] until after that.
########################################################################
# sqlite-custom.tcl is intended only for vendor-branch-specific
# customization. See autosetup/README.md#branch-customization for
# details.
if {[file exists $::autosetup(libdir)/sqlite-custom.tcl]} {
uplevel 1 {source $::autosetup(libdir)/sqlite-custom.tcl}
}
if {[llength [info proc sqlite-custom-flags]] > 0} {
# sqlite-custom-flags is assumed to be imported via
# autosetup/sqlite-custom.tcl.
set scf [sqlite-custom-flags]
if {"" ne $scf} {
lappend allFlags sqlite-custom-flags $scf
}
}
# Filter allFlags to create the set of [options] legal for this build
set opts {}
foreach {group XY} [subst -nobackslashes -nocommands \
[proj-strip-hash-comments $allFlags]] {
foreach {X Y} $XY {
if { $buildMode in $X || "*" in $X } {
foreach y $Y {
lappend opts $y
}
}
}
}
#lappend opts "soname:=duplicateEntry => {x}"; #just testing
if {[catch {options $opts} msg xopts]} {
# Workaround for <https://github.com/msteveb/autosetup/issues/73>
# where [options] behaves oddly on _some_ TCL builds when it's
# called from deeper than the global scope.
dict incr xopts -level
return {*}$xopts $msg
}
sqlite-configure-phase1 $buildMode
uplevel 1 $configScript
sqlite-configure-finalize
}; # sqlite-configure
########################################################################
# Runs "phase 1" of the configure process: after initial --flags
# handling but before the build-specific parts are run. $buildMode
# must be the mode which was passed to [sqlite-configure].
proc sqlite-configure-phase1 {buildMode} {
define PACKAGE_NAME sqlite
define PACKAGE_URL {https://sqlite.org}
define PACKAGE_BUGREPORT [get-define PACKAGE_URL]/forum
define PACKAGE_STRING "[get-define PACKAGE_NAME] [get-define PACKAGE_VERSION]"
proj-xfer-options-aliases {
# Carry values from hidden --flag aliases over to their canonical
# flag forms. This list must include only options which are common
# to all build modes supported by [sqlite-configure].
with-readline-inc => with-readline-cflags
with-readline-lib => with-readline-ldflags
with-debug => debug
}
set ::sqliteConfig(msg-debug-enabled) [proj-val-truthy [get-env msg-debug 0]]
proc-debug "msg-debug is enabled"
sqlite-autoreconfig
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
}
sqlite-setup-default-cflags
define HAVE_LFS 0
if {[opt-bool largefile]} {
#
# Insofar as we can determine HAVE_LFS has no effect on the
# library. Perhaps it did back in the early 2000's. The
# --enable/disable-largefile flag is retained because it's
# harmless, but it doesn't do anything useful. It does have
# visible side-effects, though: the generated sqlite_cfg.h may (or
# may not) define HAVE_LFS.
cc-check-lfs
}
}; # sqlite-configure-phase1
########################################################################
# Performs late-stage config steps common to all supported
# $::sqliteConfig(build-mode) values.
proc sqlite-configure-finalize {} {
sqlite-handle-rpath
sqlite-handle-soname
sqlite-handle-threadsafe
sqlite-handle-tempstore
sqlite-handle-load-extension
sqlite-handle-math
sqlite-handle-icu
if {[proj-opt-exists readline]} {
sqlite-handle-line-editing
}
if {[proj-opt-exists shared]} {
proj-define-for-opt shared ENABLE_LIB_SHARED "Build shared library?"
}
if {[proj-opt-exists static]} {
if {![proj-define-for-opt static ENABLE_LIB_STATIC "Build static library?"]} {
# This notice really only applies to the canonical build...
proj-indented-notice {
NOTICE: static lib build may be implicitly re-activated by
other components, e.g. some test apps.
}
}
}
sqlite-handle-env-quirks
sqlite-handle-common-feature-flags
sqlite-finalize-feature-flags
sqlite-process-dot-in-files; # do not [define] anything after this
sqlite-post-config-validation
sqlite-dump-defines
}
########################################################################
# Internal config-time debugging output routine. It generates no
# output unless msg-debug=1 is passed to the configure script.
proc msg-debug {msg} {
if {$::sqliteConfig(msg-debug-enabled)} {
puts stderr [proj-bold "** DEBUG: $msg"]
}
}
########################################################################
# A [msg-debug] proxy which prepends the name of the current proc to
# the debug message. It is not legal to call this from the global
# scope.
proc proc-debug {msg} {
msg-debug "\[[proj-current-proc-name 1]\]: $msg"
}
########################################################################
# Sets up the SQLITE_AUTORECONFIG define.
proc sqlite-autoreconfig {} {
# 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.
set 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 [apply $squote $::autosetup(builddir)] \
&& [apply $squote $::autosetup(srcdir)/configure]
#{*}$::autosetup(argv) breaks with --flag='val with spaces', so...
foreach arg $::autosetup(argv) {
define-append SQLITE_AUTORECONFIG [apply $squote $arg]
}
}
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. This is intended only for holding
# -DSQLITE_ENABLE/OMIT/... flags, but that is not enforced here.
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
}
}
########################################################################
# 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 sqlite-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
}
}
########################################################################
# Run checks for required binaries, like ld and ar. In the canonical
# build this must come before [sqlite-handle-wasi-sdk].
proc sqlite-check-common-bins {} {
cc-check-tools ld ar ; # must come before [sqlite-handle-wasi-sdk]
if {"" eq [proj-bin-define install]} {
proj-warn "Cannot find install binary, so 'make install' will not work."
define BIN_INSTALL false
}
}
########################################################################
# Run checks for system-level includes and libs which are common to
# both the canonical build and the "autoconf" bundle.
#
# For the canonical build this must come after
# [sqlite-handle-wasi-sdk], as that function may change the
# environment in ways which affect this.
proc sqlite-check-common-system-deps {} {
# 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
set ldrt ""
# Collapse funcs from librt into LDFLAGS_RT.
# Some systems (ex: SunOS) require -lrt in order to use nanosleep
foreach func {fdatasync nanosleep} {
if {[proj-check-function-in-lib $func rt]} {
lappend ldrt [get-define lib_${func}]
}
}
define LDFLAGS_RT [join [lsort -unique $ldrt] ""]
# 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 ""
}
}
########################################################################
# Move -DSQLITE_OMIT... and -DSQLITE_ENABLE... flags from CFLAGS and
# CPPFLAGS to OPT_FEATURE_FLAGS and remove them from BUILD_CFLAGS.
proc sqlite-munge-cflags {} {
# Move CFLAGS and CPPFLAGS entries matching -DSQLITE_OMIT* and
# -DSQLITE_ENABLE* to OPT_FEATURE_FLAGS. This behavior is derived
# from the legacy build and was missing the 3.48.0 release (the
# initial Autosetup port).
# https://sqlite.org/forum/forumpost/9801e54665afd728
#
# Handling of CPPFLAGS, as well as removing ENABLE/OMIT from
# CFLAGS/CPPFLAGS, was missing in the 3.49.0 release as well.
#
# If any configure flags for features are in conflict with
# CFLAGS/CPPFLAGS-specified feature flags, all bets are off. There
# are no guarantees about which one will take precedence.
foreach flagDef {CFLAGS CPPFLAGS} {
set tmp ""
foreach cf [get-define $flagDef ""] {
switch -glob -- $cf {
-DSQLITE_OMIT* -
-DSQLITE_ENABLE* {
sqlite-add-feature-flag $cf
}
default {
lappend tmp $cf
}
}
}
define $flagDef $tmp
}
# Strip all SQLITE_ENABLE/OMIT flags from BUILD_CFLAGS,
# for compatibility with the legacy build.
set tmp ""
foreach cf [get-define BUILD_CFLAGS ""] {
switch -glob -- $cf {
-DSQLITE_OMIT* -
-DSQLITE_ENABLE* {}
default {
lappend tmp $cf
}
}
}
define BUILD_CFLAGS $tmp
}
#########################################################################
# Set up the default CFLAGS and BUILD_CFLAGS values.
proc sqlite-setup-default-cflags {} {
########################################################################
# 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.
#
# When cross-compiling we default to not using the -g flag, based on a
# /chat discussion prompted by
# https://sqlite.org/forum/forumpost/9a67df63eda9925c
set defaultCFlags {-O2}
if {!$::sqliteConfig(is-cross-compiling)} {
lappend defaultCFlags -g
}
define CFLAGS [proj-get-env CFLAGS $defaultCFlags]
# BUILD_CFLAGS is the CFLAGS for CC_FOR_BUILD.
define BUILD_CFLAGS [proj-get-env BUILD_CFLAGS {-g}]
sqlite-munge-cflags
}
########################################################################
# Handle various SQLITE_ENABLE/OMIT_... feature flags.
proc sqlite-handle-common-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 {sqlite-affirm-have-math fts4}
fts5 -DSQLITE_ENABLE_FTS5 {sqlite-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 {}
} {
if {$boolFlag ni $::autosetup(options)} {
# Skip flags which are in the canonical build but not
# the autoconf bundle.
continue
}
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"
}
}
}
#########################################################################
# Remove duplicates from the final feature flag sets and show them to
# the user.
proc sqlite-finalize-feature-flags {} {
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]"
}
if {"" ne [set extraSrc [get-define AMALGAMATION_EXTRA_SRC ""]]} {
proj-assert {"canonical" eq $::sqliteConfig(build-mode)}
msg-result "Appending source files to amalgamation: $extraSrc"
}
if {[lsearch [get-define TARGET_DEBUG ""] -DSQLITE_DEBUG=1] > -1} {
msg-result "Note: this is a debug build, so performance will suffer."
}
}
########################################################################
# Checks for the --debug flag and [define]s TARGET_DEBUG based on
# that. TARGET_DEBUG is unused in the autoconf build but that is
# arguably a bug.
proc sqlite-handle-debug {} {
msg-checking "SQLITE_DEBUG build? "
proj-if-opt-truthy debug {
define TARGET_DEBUG {-g -DSQLITE_DEBUG=1 -O0 -Wall}
sqlite-add-feature-flag -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE
proj-opt-set memsys5
msg-result yes
} {
define TARGET_DEBUG {-DNDEBUG}
msg-result no
}
}
########################################################################
# "soname" for libsqlite3.so. See discussion at:
# https://sqlite.org/src/forumpost/5a3b44f510df8ded
proc sqlite-handle-soname {} {
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 }
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}"
}
}
}
proc-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."
}
}
########################################################################
# If --enable-threadsafe is set, this adds -DSQLITE_THREADSAFE=1 to
# OPT_FEATURE_FLAGS and sets LDFLAGS_PTHREAD to the linker flags
# needed for linking pthread (possibly an empty string). If
# --enable-threadsafe is not set, adds -DSQLITE_THREADSAFE=0 to
# OPT_FEATURE_FLAGS and sets LDFLAGS_PTHREAD to an empty string.
proc sqlite-handle-threadsafe {} {
msg-checking "Support threadsafe operation? "
define LDFLAGS_PTHREAD ""
set enable 0
proj-if-opt-truthy threadsafe {
msg-result "Checking for libs..."
if {[proj-check-function-in-lib pthread_create pthread]
&& [proj-check-function-in-lib pthread_mutexattr_init pthread]} {
set enable 1
define LDFLAGS_PTHREAD [get-define lib_pthread_create]
undefine lib_pthread_create
undefine lib_pthread_mutexattr_init
} elseif {[proj-opt-was-provided threadsafe]} {
user-error "Missing required pthread libraries. Use --disable-threadsafe to disable this check."
} else {
msg-result "pthread support not detected"
}
# Recall that LDFLAGS_PTHREAD might be empty even if pthreads if
# found because it's in -lc on some platforms.
} {
msg-result "Disabled using --disable-threadsafe"
}
sqlite-add-feature-flag -DSQLITE_THREADSAFE=${enable}
return $enable
}
########################################################################
# Handles the --with-tempstore flag.
#
# The test fixture likes to set SQLITE_TEMP_STORE on its own, so do
# not set that feature flag unless it was explicitly provided to the
# configure script.
proc sqlite-handle-tempstore {} {
if {[proj-opt-was-provided with-tempstore]} {
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
}
}
########################################################################
# 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. Most of the work is done via [proj-check-emsdk], then this
# function adds the following defines:
#
# - EMCC_WRAPPER = "" or top-srcdir/tool/emcc.sh
# - BIN_WASM_OPT = "" or path to wasm-opt
# - BIN_WASM_STRIP = "" or path to wasm-strip
#
# Noting that:
#
# 1) Not finding the SDK is not fatal at this level, nor is failure to
# find one of the related binaries.
#
# 2) wasm-strip is part of the wabt package:
#
# https://github.com/WebAssembly/wabt
#
# and this project requires it for production-mode builds but not dev
# builds.
#
proc sqlite-handle-emsdk {} {
define EMCC_WRAPPER ""
define BIN_WASM_STRIP ""
define BIN_WASM_OPT ""
set srcdir $::autosetup(srcdir)
if {$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 treat that case as if EMSDK
# were not found.
msg-result "Out-of tree build: not checking for EMSDK."
return
}
set emccSh $srcdir/tool/emcc.sh
set extWasmConfig $srcdir/ext/wasm/config.make
if {![get-define HAVE_WASI_SDK] && [proj-check-emsdk]} {
define EMCC_WRAPPER $emccSh
set emsdkHome [get-define EMSDK_HOME ""]
proj-assert {"" ne $emsdkHome}
#define EMCC_WRAPPER ""; # just for testing
proj-bin-define wasm-strip
proj-bin-define bash; # ext/wasm/GNUmakefile requires bash
if {[file-isexec $emsdkHome/upstream/bin/wasm-opt]} {
define BIN_WASM_OPT $emsdkHome/upstream/bin/wasm-opt
} else {
# Maybe there's a copy in the path?
proj-bin-define wasm-opt BIN_WASM_OPT
}
proj-make-from-dot-in $emccSh $extWasmConfig
catch {exec chmod u+x $emccSh}
} else {
define EMCC_WRAPPER ""
file delete -force -- $emccSh $extWasmConfig
}
}
########################################################################
# Internal helper for [sqlite-check-line-editing]. Returns a list of
# potential locations under which readline.h might be found.
#
# On some environments this function may perform extra work to help
# sqlite-check-line-editing figure out how to find libreadline and
# friends. It will communicate those results via means other than the
# result value, e.g. by modifying configure --flags.
proc sqlite-get-readline-dir-list {} {
# Historical note: the dirs list, except for the inclusion of
# $prefix and some platform-specific dirs, originates from the
# legacy configure script
set dirs [list [get-define prefix]]
switch -glob -- [get-define host] {
*-linux-android {
# Possibly termux
lappend dirs /data/data/com.termux/files/usr
}
*-mingw32 {
lappend dirs /mingw32 /mingw
}
*-mingw64 {
lappend dirs /mingw64 /mingw
}
*-haiku {
lappend dirs /boot/system/develop/headers
if {[opt-val with-readline-ldflags] in {auto ""}} {
# If the user did not supply their own --with-readline-ldflags
# value, hijack that flag to inject options which are known to
# work on a default Haiku installation.
if {"" ne [glob -nocomplain /boot/system/lib/libreadline*]} {
proj-opt-set with-readline-ldflags {-L/boot/system/lib -lreadline}
}
}
}
}
lappend dirs /usr /usr/local /usr/local/readline /usr/contrib
set rv {}
foreach d $dirs {
if {[file isdir $d]} {lappend rv $d}
}
#proc-debug "dirs=$rv"
return $rv
}
########################################################################
# 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 {$::sqliteConfig(use-jim-for-codegen) && 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 {$::sqliteConfig(is-cross-compiling)} {
# ^^^ this check is derived from the legacy configure script.
proj-warn "Skipping check for readline.h because we're cross-compiling."
} else {
set dirs [sqlite-get-readline-dir-list]
set subdirs [list \
include/$editLibName \
readline]
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
set rlInc [proj-search-for-header-dir readline.h \
-dirs $dirs -subdirs $subdirs]
#proc-debug "rlInc=$rlInc"
if {"" ne $rlInc} {
if {[string match */readline $rlInc]} {
set rlInc [file dirname $rlInc]; # CLI shell: #include <readline/readline.h>
} elseif {[string match */editline $rlInc]} {
set editLibDef HAVE_EDITLINE
set rlInc [file dirname $rlInc]; # CLI shell: #include <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]
#proc-debug "rlLib=$rlLib"
if {$rlLib in {auto ""}} {
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 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
########################################################################
# Runs sqlite-check-line-editing and adds a message around it. In the
# canonical build this must not be called before
# sqlite-determine-codegen-tcl for reasons now lost to history (and
# might not still be applicable).
proc sqlite-handle-line-editing {} {
msg-result "Line-editing support for the sqlite3 shell: [sqlite-check-line-editing]"
}
########################################################################
# 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-handle-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]} {
msg-result "Checking for ICU support..."
set icuConfigBin [opt-val with-icu-config]
set tryIcuConfigBin 1; # set to 0 if we end up using pkg-config
if {$icuConfigBin in {auto pkg-config}} {
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-indented-notice -error {
--with-icu-config=auto cannot find (pkg-config icu-io) or icu-config binary.
On Ubuntu-like systems try:
--with-icu-ldflags='-licui18n -licuuc -licudata'
}
}
}
if {[file-isexec $icuConfigBin]} {
set x [exec $icuConfigBin --ldflags]
if {"" eq $x} {
proj-indented-notice -error \
[subst {
$icuConfigBin --ldflags returned no data.
On Ubuntu-like systems try:
--with-icu-ldflags='-licui18n -licuuc -licudata'
}]
}
define-append LDFLAGS_ICU $x
set x [exec $icuConfigBin --cppflags]
define-append CFLAGS_ICU $x
} else {
proj-fatal "--with-icu-config=$icuConfigBin 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 except in the case
# of --disable-static-shell, a combination we do not
# specifically attempt to account for.
}
} 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-handle-icu
########################################################################
# Handles the --enable-load-extension flag. Returns 1 if the support
# is enabled, else 0. If support for that feature is not found, a
# fatal error is triggered if --enable-load-extension is explicitly
# provided, else a loud warning is instead emitted. If
# --disable-load-extension is used, no check is performed.
#
# Makes the following environment changes:
#
# - defines LDFLAGS_DLOPEN to any linker flags needed for this
# feature. It may legally be empty on some systems where dlopen()
# is in libc.
#
# - If the feature is not available, adds
# -DSQLITE_OMIT_LOAD_EXTENSION=1 to the feature flags list.
proc sqlite-handle-load-extension {} {
define LDFLAGS_DLOPEN ""
set found 0
proj-if-opt-truthy load-extension {
set found [proj-check-function-in-lib dlopen dl]
if {$found} {
define LDFLAGS_DLOPEN [get-define lib_dlopen]
undefine lib_dlopen
} else {
if {[proj-opt-was-provided load-extension]} {
# Explicit --enable-load-extension: fail if not found
proj-indented-notice -error {
--enable-load-extension was provided but dlopen()
not found. Use --disable-load-extension to bypass this
check.
}
} else {
# It was implicitly enabled: warn if not found
proj-indented-notice {
WARNING: dlopen() not found, so loadable module support will
be disabled. Use --disable-load-extension to bypass this
check.
}
}
}
}
if {$found} {
msg-result "Loadable extension support enabled."
} else {
msg-result "Disabling loadable extension support. Use --enable-load-extension to enable them."
sqlite-add-feature-flag -DSQLITE_OMIT_LOAD_EXTENSION=1
}
return $found
}
########################################################################
# Handles the --enable-math flag.
proc sqlite-handle-math {} {
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"
} {
define LDFLAGS_MATH ""
msg-result "Disabling math SQL functions"
}
}
########################################################################
# If this OS looks like a Mac, checks for the Mac-specific
# -current_version and -compatibility_version linker flags. Defines
# LDFLAGS_MAC_CVERSION to an empty string and returns 0 if they're not
# supported, else defines that to the linker flags and returns 1.
#
# We don't check this on non-Macs because this whole thing is a
# libtool compatibility kludge to account for a version stamp which
# libtool applied only on Mac platforms.
#
# Based on https://sqlite.org/forum/forumpost/9dfd5b8fd525a5d7.
proc sqlite-handle-mac-cversion {} {
define LDFLAGS_MAC_CVERSION ""
set rc 0
if {[proj-looks-like-mac]} {
cc-with {-link 1} {
# These version numbers are historical libtool-defined values, not
# library-defined ones
if {[cc-check-flags "-Wl,-current_version,9.6.0"]
&& [cc-check-flags "-Wl,-compatibility_version,9.0.0"]} {
define LDFLAGS_MAC_CVERSION "-Wl,-compatibility_version,9.0.0 -Wl,-current_version,9.6.0"
set rc 1
} elseif {[cc-check-flags "-compatibility_version 9.0.0"]
&& [cc-check-flags "-current_version 9.6.0"]} {
define LDFLAGS_MAC_CVERSION "-compatibility_version 9.0.0 -current_version 9.6.0"
set rc 1
}
}
}
return $rc
}
########################################################################
# Handles the --dll-basename configure flag. [define]'s
# SQLITE_DLL_BASENAME to the DLL's preferred base name (minus
# extension). If --dll-basename is not provided (or programmatically
# set - see [sqlite-handle-env-quirks]) then this is always
# "libsqlite3", otherwise it may use a different value based on the
# value of [get-define host].
proc sqlite-handle-dll-basename {} {
if {[proj-opt-was-provided dll-basename]} {
set dn [join [opt-val dll-basename] ""]
if {$dn in {none default}} { set dn libsqlite3 }
} else {
set dn libsqlite3
}
if {$dn in {auto ""}} {
switch -glob -- [get-define host] {
*-*-cygwin { set dn cygsqlite3-0 }
*-*-ming* { set dn libsqlite3-0 }
*-*-msys { set dn msys-sqlite3-0 }
default { set dn libsqlite3 }
}
}
define SQLITE_DLL_BASENAME $dn
}
########################################################################
# [define]s LDFLAGS_OUT_IMPLIB to either an empty string or to a
# -Wl,... flag for the platform-specific --out-implib flag, which is
# used for building an "import library .dll.a" file on some platforms
# (e.g. msys2, mingw). SQLITE_OUT_IMPLIB is defined to the name of the
# import lib or an empty string. Returns 1 if supported, else 0.
#
# The name of the import library is [define]d in SQLITE_OUT_IMPLIB.
#
# If the configure flag --out-implib is not used (or programmatically
# set) then this simply sets the above-listed defines to empty strings
# (but see [sqlite-handle-env-quirks]). If that flag is used but the
# capability is not available, a fatal error is triggered.
#
# This feature is specifically opt-in because it's supported on far
# more platforms than actually need it and enabling it causes creation
# of libsqlite3.so.a files which are unnecessary in most environments.
#
# Added in response to: https://sqlite.org/forum/forumpost/0c7fc097b2
#
# Platform notes:
#
# - cygwin sqlite packages historically install no .dll.a file.
#
# - msys2 and mingw sqlite packages historically install
# /usr/lib/libsqlite3.dll.a despite the DLL being in
# /usr/bin.
proc sqlite-handle-out-implib {} {
define LDFLAGS_OUT_IMPLIB ""
define SQLITE_OUT_IMPLIB ""
set rc 0
if {[proj-opt-was-provided out-implib]} {
set olBaseName [join [opt-val out-implib] ""]
if {$olBaseName in {auto ""}} {
set olBaseName "libsqlite3" ;# [get-define SQLITE_DLL_BASENAME]
# Based on discussions with mingw/msys users, the import lib
# should always be called libsqlite3.dll.a even on platforms
# which rename libsqlite3.dll to something else.
}
if {$olBaseName ne "none"} {
cc-with {-link 1} {
set dll "${olBaseName}[get-define TARGET_DLLEXT]"
set flags [proj-cc-check-Wl-flag --out-implib ${dll}.a]
if {"" ne $flags} {
define LDFLAGS_OUT_IMPLIB $flags
define SQLITE_OUT_IMPLIB ${dll}.a
set rc 1
}
}
if {!$rc} {
user-error "--out-implib is not supported on this platform"
}
}
}
return $rc
}
########################################################################
# If the given platform identifier (defaulting to [get-define host])
# appears to be one of the Unix-on-Windows environments, returns a
# brief symbolic name for that environment, else returns an empty
# string.
#
# It does not distinguish between msys and msys2, returning msys for
# both. The build does not, as of this writing, specifically support
# msys v1. Similarly, this function returns "mingw" for both "mingw32"
# and "mingw64".
proc sqlite-env-is-unix-on-windows {{envTuple ""}} {
if {"" eq $envTuple} {
set envTuple [get-define host]
}
set name ""
switch -glob -- $envTuple {
*-*-cygwin { set name cygwin }
*-*-ming* { set name mingw }
*-*-msys { set name msys }
}
return $name
}
########################################################################
# Performs various tweaks to the build which are only relevant on
# certain platforms, e.g. Mac and "Unix on Windows" platforms (msys2,
# cygwin, ...).
#
# 1) DLL installation:
#
# [define]s SQLITE_DLL_INSTALL_RULES to a symbolic name suffix for a
# set of "make install" rules to use for installation of the DLL
# deliverable. The makefile is tasked with providing rules named
# install-dll-NAME which runs the installation for that set, as well
# as providing a rule named install-dll which resolves to
# install-dll-NAME (perhaps indirectly, depending on whether the DLL
# is (de)activated).
#
# The default value is "unix-generic".
#
# 2) --out-implib:
#
# On platforms where an "import library" is conventionally used but
# --out-implib was not explicitly used, automatically add that flag.
# This conventionally applies only to the "Unix on Windows"
# environments like msys and cygwin.
#
# 3) --dll-basename:
#
# On the same platforms addressed by --out-implib, if --dll-basename
# is not explicitly specified, --dll-basename=auto is implied.
proc sqlite-handle-env-quirks {} {
set instName unix-generic; # name of installation rules set
set autoDll 0; # true if --out-implib/--dll-basename should be implied
set host [get-define host]
switch -glob -- $host {
*apple* -
*darwin* { set instName darwin }
default {
set x [sqlite-env-is-unix-on-windows $host]
if {"" ne $x} {
set instName $x
set autoDll 1
}
}
}
define SQLITE_DLL_INSTALL_RULES $instName
if {$autoDll} {
if {![proj-opt-was-provided out-implib]} {
# Imply --out-implib=auto
proj-indented-notice [subst -nocommands -nobackslashes {
NOTICE: auto-enabling --out-implib for environment [$host].
Use --out-implib=none to disable this special case
or --out-implib=auto to squelch this notice.
}]
proj-opt-set out-implib auto
}
if {![proj-opt-was-provided dll-basename]} {
# Imply --dll-basename=auto
proj-indented-notice [subst -nocommands -nobackslashes {
NOTICE: auto-enabling --dll-basename for environment [$host].
Use --dll-basename=default to disable this special case
or --dll-basename=auto to squelch this notice.
}]
proj-opt-set dll-basename auto
}
}
sqlite-handle-dll-basename
sqlite-handle-out-implib
sqlite-handle-mac-cversion
if {[llength [info proc sqlite-custom-handle-flags]] > 0} {
# sqlite-custom-handle-flags is assumed to be imported via a
# client-specific import: autosetup/sqlite-custom.tcl.
sqlite-custom-handle-flags
}
}
########################################################################
# Perform some late-stage work and generate the configure-process
# output file(s).
proc sqlite-process-dot-in-files {} {
########################################################################
# "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
set srcdir $::autosetup(srcdir)/
foreach f {Makefile sqlite3.pc} {
if {[file exists $srcdir/$f.in]} {
# ^^^ we do this only so that this block can be made to work for
# multiple builds. e.g. the tea build (under construction) does
# not hae sqlite3.pc.in.
proj-make-from-dot-in -touch $f
}
}
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@
}
########################################################################
# Perform some high-level validation on the generated files...
#
# 1) Ensure that no unresolved @VAR@ placeholders are in files which
# use those.
#
# 2) TBD
proc sqlite-post-config-validation {} {
# 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.
set srcdir $::autosetup(srcdir)
foreach f [list Makefile sqlite3.pc \
$srcdir/tool/emcc.sh \
$srcdir/ext/wasm/config.make] {
if {![file exists $f]} continue
set lnno 1
foreach line [proj-file-content-list $f] {
if {[regexp {(@[A-Za-z0-9_]+@)} $line match]} {
error "Unresolved reference to $match at line $lnno of $f"
}
incr lnno
}
}
}
########################################################################
# 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. However, in the
# canonical build this must come after [sqlite-check-common-bins].
proc sqlite-handle-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 {$::sqliteConfig(is-cross-compiling)} {
proj-fatal "Cannot combine --with-wasi-sdk with cross-compilation"
}
msg-result "Checking WASI SDK directory \[$wasiSdkDir]... "
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 and 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 {[proj-opt-exists $opt] && [opt-bool $opt]} {
# -^^^^ not all builds define all of these flags
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 between
# $::sqliteConfig(is-cross-compiling) and [proj-is-cross-compiling].
set ::sqliteConfig(is-cross-compiling) 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-handle-wasi-sdk
########################################################################
# 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
# Clear out all vars which would harvest from tclConfig.sh so that
# the late-config validation of @VARS@ works even if --disable-tcl
# is used.
proj-tclConfig-sh-to-autosetup ""
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.
set srcdir $::autosetup(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]
}
proc-debug "use_tcl ${use_tcl}"
proc-debug "with_tclsh=${with_tclsh}"
proc-debug "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.1 tclsh9.0 tclsh8.6 tclsh]
proc-debug "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-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 $::autosetup(libdir)/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.1 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 via 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.
proj-tclConfig-sh-to-autosetup $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.
set tclExecPrefix [get-define TCL_EXEC_PREFIX]
proj-assert {"" ne $tclExecPrefix}
set tryThese [list \
$tclExecPrefix/bin/tclsh[get-define TCL_VERSION] \
$tclExecPrefix/bin/tclsh ]
foreach trySh $tryThese {
if {[file-isexec $trySh]} {
set with_tclsh $trySh
break
}
}
if {![file-isexec $with_tclsh]} {
proj-warn "Cannot find a usable tclsh (tried: $tryThese)
}
}
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-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=...
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]
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 ::sqliteConfig(use-jim-for-codegen) 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 ::sqliteConfig(use-jim-for-codegen) 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)"
}
}; # /define-push $flagsToRestore
return $cgtcl
}; # sqlite-determine-codegen-tcl
########################################################################
# Runs sqlite-check-tcl and, if $alsoCheckCodeGen is true,
# sqlite-determine-codegen-tcl (intended only for the canonical
# build).
proc sqlite-handle-tcl {{alsoCheckCodeGen 1}} {
sqlite-check-tcl
if {$alsoCheckCodeGen} {
msg-result "TCL for code generation: [sqlite-determine-codegen-tcl]"
}
}
########################################################################
# Handle the --enable/disable-rpath flag.
proc sqlite-handle-rpath {} {
proj-check-rpath
# autosetup/cc-shared.tcl sets the rpath flag definition in
# [get-define SH_LINKRPATH], but it does so on a per-platform basis
# rather than as a compiler check. Though we should do a proper
# compiler check (as proj-check-rpath does), we may want to consider
# adopting its approach of clearing the rpath flags for environments
# for which sqlite-env-is-unix-on-windows returns a non-empty
# string.
# if {[proj-opt-truthy rpath]} {
# proj-check-rpath
# } else {
# msg-result "Disabling use of rpath."
# define LDFLAGS_RPATH ""
# }
}
########################################################################
# If the --dump-defines configure flag is provided then emit a list of
# all [define] values to config.defines.txt, else do nothing.
proc sqlite-dump-defines {} {
proj-if-opt-truthy dump-defines {
make-config-header $::sqliteConfig(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 $::sqliteConfig(dump-defines-json)} {
msg-result "--dump-defines is creating $::sqliteConfig(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 {$::sqliteConfig(dump-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 $::sqliteConfig(dump-defines-json) {*}$dumpDefsOpt
undefine OPT_FEATURE_FLAGS.list
undefine OPT_SHELL.list
}
}
}