Home | History | Annotate | Line # | Download | only in autosetup
      1 # This file holds functions for autosetup which are specific to the
      2 # sqlite build tree.  They are in this file, instead of auto.def, so
      3 # that they can be reused in the autoconf sub-tree. This file requires
      4 # functions from the project-agnostic proj.tcl.
      5 
      6 if {[string first " " $autosetup(srcdir)] != -1} {
      7   user-error "The pathname of the source tree\
      8               may not contain space characters"
      9 }
     10 if {[string first " " $autosetup(builddir)] != -1} {
     11   user-error "The pathname of the build directory\
     12               may not contain space characters"
     13 }
     14 
     15 use proj
     16 #
     17 # We want the package version info to be emitted early on, but doing
     18 # so requires a bit of juggling. We have to [use system] for
     19 # --prefix=... to work and to emit the Host/Build system info, but we
     20 # don't want those to interfere with --help output.
     21 define PACKAGE_VERSION [proj-file-content -trim $::autosetup(srcdir)/VERSION]
     22 if {"--help" ni $::argv} {
     23   msg-result "Configuring SQLite version [get-define PACKAGE_VERSION]"
     24 }
     25 use system ; # Will output "Host System" and "Build System" lines
     26 if {"--help" ni $::argv} {
     27   proj-tweak-default-env-dirs
     28   msg-result "Source dir = $::autosetup(srcdir)"
     29   msg-result "Build dir  = $::autosetup(builddir)"
     30   use cc cc-db cc-shared cc-lib pkg-config
     31 }
     32 
     33 #
     34 # Object for communicating certain config-time state across various
     35 # auto.def-related pieces.
     36 array set sqliteConfig [subst [proj-strip-hash-comments {
     37   #
     38   # Gets set by [sqlite-configure] (the main configure script driver).
     39   build-mode unknown
     40   #
     41   # Gets set to 1 when using jimsh for code generation. May affect
     42   # later decisions.
     43   use-jim-for-codegen  0
     44   #
     45   # Set to 1 when cross-compiling This value may be changed by certain
     46   # build options, so it's important that config code which checks for
     47   # cross-compilation uses this var instead of
     48   # [proj-is-cross-compiling].
     49   is-cross-compiling [proj-is-cross-compiling]
     50   #
     51   # Pass msg-debug=1 to configure to enable obnoxiously loud output
     52   # from [msg-debug].
     53   msg-debug-enabled    0
     54   #
     55   # Output file for --dump-defines. Intended only for build debugging
     56   # and not part of the public build interface.
     57   dump-defines-txt   ./config.defines.txt
     58   #
     59   # If not empty then --dump-defines will dump not only
     60   # (dump-defines-txt) but also a JSON file named after this option's
     61   # value.
     62   dump-defines-json  ""
     63 
     64   #
     65   # The list of feature --flags which the --all flag implies. This
     66   # requires special handling in a few places.
     67   #
     68   all-flag-enables {fts4 fts5 rtree geopoly session dbpage dbstat carray}
     69 
     70   #
     71   # Default value for the --all flag. Can hypothetically be modified
     72   # by non-canonical builds (it was added for a Tcl extension build
     73   # mode which was eventually removed).
     74   #
     75   all-flag-default 0
     76 }]]
     77 
     78 ########################################################################
     79 # Processes all configure --flags for this build, run build-specific
     80 # config checks, then finalize the configure process. $buildMode must
     81 # be one of (canonical, autoconf), and others may be added in the
     82 # future. After bootstrapping, $configScript is eval'd in the caller's
     83 # scope, then post-configuration finalization is run. $configScript is
     84 # intended to hold configure code which is specific to the given
     85 # $buildMode, with the caveat that _some_ build-specific code is
     86 # encapsulated in the configuration finalization step.
     87 #
     88 # The intent is that all (or almost all) build-mode-specific
     89 # configuration goes inside the $configScript argument to this
     90 # function, and that an auto.def file contains only two commands:
     91 #
     92 #  use sqlite-config
     93 #  sqlite-configure BUILD_NAME { build-specific configure script }
     94 #
     95 # There are snippets of build-mode-specific decision-making in
     96 # [sqlite-configure-finalize], which gets run after $configScript.
     97 proc sqlite-configure {buildMode configScript} {
     98   proj-assert {$::sqliteConfig(build-mode) eq "unknown"} \
     99     "sqlite-configure must not be called more than once"
    100   set allBuildModes {canonical autoconf}
    101   if {$buildMode ni $allBuildModes} {
    102     user-error "Invalid build mode: $buildMode. Expecting one of: $allBuildModes"
    103   }
    104   if {$::sqliteConfig(all-flag-default)} {
    105     set allFlagHelp "Disable these extensions: $::sqliteConfig(all-flag-enables)"
    106   } else {
    107     set allFlagHelp "Enable these extensions: $::sqliteConfig(all-flag-enables)"
    108   }
    109 
    110   set ::sqliteConfig(build-mode) $buildMode
    111   ########################################################################
    112   # A gentle introduction to flags handling in autosetup
    113   #
    114   # Reference: https://msteveb.github.io/autosetup/developer/
    115   #
    116   # All configure flags must be described in one or more calls to
    117   # autosetup's [options] and [options-add] functions. The general
    118   # syntax of the single argument to those functions is a list contain
    119   # a mapping of flags to help text:
    120   #
    121   #  FLAG => {Help text}
    122   #
    123   # Where FLAG can have any of the following formats:
    124   #
    125   #   boolopt            => "a boolean option which defaults to disabled"
    126   #   boolopt2=1         => "a boolean option which defaults to enabled"
    127   #   stringopt:         => "an option which takes an argument, e.g. --stringopt=value"
    128   #   stringopt:DESCR    => As for stringopt: with a description for the value
    129   #   stringopt2:=value  => "an option where the argument is optional and defaults to 'value'"
    130   #   optalias booltopt3 => "a boolean with a hidden alias. --optalias is not shown in --help"
    131   #
    132   # Autosetup does no small amount of specialized handling for flags,
    133   # especially booleans. Each bool-type --FLAG implicitly gets
    134   # --enable-FLAG and --disable-FLAG forms. That can lead lead to some
    135   # confusion when writing help text. For example:
    136   #
    137   #   options { json=1 {Disable JSON functions} }
    138   #
    139   # The reason the help text says "disable" is because a boolean option
    140   # which defaults to true is, in the --help text, rendered as:
    141   #
    142   #   --disable-json          Disable JSON functions
    143   #
    144   # Whereas a bool flag which defaults to false will instead render as:
    145   #
    146   #   --enable-FLAG
    147   #
    148   # Non-boolean flags, in contrast, use the names specifically given to
    149   # them in the [options] invocation. e.g. "with-tcl" is the --with-tcl
    150   # flag.
    151   #
    152   # Fetching values for flags:
    153   #
    154   #   booleans: use one of:
    155   #     - [opt-bool FLAG] is autosetup's built-in command for this, but we
    156   #       have some convenience variants:
    157   #     - [proj-opt-truthy FLAG]
    158   #     - [proj-opt-if-truthy FLAG {THEN} {ELSE}]
    159   #
    160   #   Non-boolean (i.e. string) flags:
    161   #     - [opt-val FLAG ?default?]
    162   #     - [opt-str ...] - see the docs in ./autosetup/autosetup
    163   #
    164   # [proj-opt-was-provided] can be used to determine whether a flag was
    165   # explicitly provided, which is often useful for distinguishing from
    166   # the case of a default value.
    167   ########################################################################
    168   set allFlags {
    169     # Structure: a list of M {Z} pairs, where M is a descriptive
    170     # option group name and Z is a list of X Y pairs. X is a list of
    171     # $buildMode name(s) to which the Y flags apply, or {*} to apply
    172     # to all builds. Y is a {block} in the form expected by
    173     # autosetup's [options] and [options-add] command.  Each block
    174     # which is applicable to $buildMode is passed on to
    175     # [options-add]. The order of each Y and sub-Y is retained, which
    176     # is significant for rendering of --help.
    177     #
    178     # Maintenance note: [options] does not support comments in
    179     # options, but we filter this object through
    180     # [proj-strip-hash-comments] to remove them before passing them on
    181     # to [options].
    182 
    183     # When writing {help text blocks}, be aware that:
    184     #
    185     # A) autosetup formats them differently if the {block} starts with
    186     # a newline: it starts left-aligned, directly under the --flag, and
    187     # the rest of the block is pasted verbatim rather than
    188     # pretty-printed.
    189     #
    190     # B) Vars and commands are NOT expanded, but we use a [subst] call
    191     # below which will replace (only) $var refs.
    192 
    193     # Options for how to build the library
    194     build-modes {
    195       {canonical autoconf} {
    196         shared=1             => {Disable build of shared library}
    197         static=1             => {Disable build of static library}
    198       }
    199       {canonical} {
    200         amalgamation=1       => {Disable the amalgamation and instead build all files separately}
    201       }
    202     }
    203 
    204     # Library-level features and defaults
    205     lib-features {
    206       {*} {
    207         threadsafe=1         => {Disable mutexing}
    208         with-tempstore:=no   => {Use an in-RAM database for temporary tables: never,no,yes,always}
    209         load-extension=1     => {Disable loading of external extensions}
    210         # ^^^ one of the downstream custom builds overrides the load-extension default to 0, which
    211         # confuses the --help text generator. https://github.com/msteveb/autosetup/issues/77
    212         math=1               => {Disable math functions}
    213         json=1               => {Disable JSON functions}
    214         memsys5              => {Enable MEMSYS5}
    215         memsys3              => {Enable MEMSYS3}
    216         fts3                 => {Enable the FTS3 extension}
    217         fts4                 => {Enable the FTS4 extension}
    218         fts5                 => {Enable the FTS5 extension}
    219         update-limit         => {Enable the UPDATE/DELETE LIMIT clause}
    220         geopoly              => {Enable the GEOPOLY extension}
    221         rtree                => {Enable the RTREE extension}
    222         session              => {Enable the SESSION extension}
    223         dbpage               => {Enable the sqlite3_dbpage extension}
    224         dbstat               => {Enable the sqlite3_dbstat extension}
    225         carray=1             => {Disable the CARRAY extension}
    226         all=$::sqliteConfig(all-flag-default) => {$allFlagHelp}
    227         largefile=1
    228           => {This legacy flag has no effect on the library but may influence
    229               the generated sqlite_cfg.h by adding #define HAVE_LFS}
    230       }
    231       {canonical} {
    232         column-metadata      => {Enable the column metadata APIs}
    233         # ^^^ Affects how sqlite3.c is generated, so is not available in
    234         # the autoconf build.
    235       }
    236     }
    237 
    238     # Options for TCL support
    239     tcl {
    240       {canonical} {
    241         tcl=1
    242           => {Disable components which require TCL, including all tests.
    243               This tree requires TCL for code generation but can use the in-tree
    244               copy of autosetup/jimsh0.c for that. The SQLite TCL extension and the
    245               test code require a canonical tclsh.}
    246         with-tcl:DIR
    247           => {Directory containing tclConfig.sh or a directory one level up from
    248               that, from which we can derive a directory containing tclConfig.sh.
    249               A dir name of "prefix" is equivalent to the directory specified by
    250               the --prefix flag.}
    251         with-tclsh:PATH
    252           => {Full pathname of tclsh to use.  It is used for (A) trying to find
    253               tclConfig.sh and (B) all TCL-based code generation. Use --with-tcl
    254               unless you have a specific need for this flag. Warning: if its
    255               containing dir has multiple tclsh versions, it may select the
    256               wrong tclConfig.sh!}
    257         static-tclsqlite3=0
    258           => {Statically-link tclsqlite3. This only works if TCL support is
    259               enabled and all requisite libraries are available in
    260               static form. Note that glibc is unable to fully statically
    261               link certain libraries required by tclsqlite3, so this won't
    262               work on most Linux environments.}
    263       }
    264     }
    265 
    266     # Options for line-editing modes for the CLI shell
    267     line-editing {
    268       {canonical autoconf} {
    269         readline=1
    270           => {Disable readline support}
    271         # --with-readline-lib is a backwards-compatible alias for
    272         # --with-readline-ldflags
    273         with-readline-lib:
    274         with-readline-ldflags:=auto
    275           => {Readline LDFLAGS, e.g. -lreadline -lncurses}
    276         # --with-readline-inc is a backwards-compatible alias for
    277         # --with-readline-cflags.
    278         with-readline-inc:
    279         with-readline-cflags:=auto
    280           => {Readline CFLAGS, e.g. -I/path/to/includes}
    281         with-readline-header:PATH
    282           => {Full path to readline.h, from which --with-readline-cflags will be derived}
    283         with-linenoise:DIR
    284           => {Source directory for linenoise.c and linenoise.h}
    285         editline=0
    286           => {Enable BSD editline support}
    287       }
    288     }
    289 
    290     # Options for ICU: International Components for Unicode
    291     icu {
    292       {*} {
    293         with-icu-ldflags:LDFLAGS
    294           => {Enable SQLITE_ENABLE_ICU and add the given linker flags for the
    295               ICU libraries. e.g. on Ubuntu systems, try '-licui18n -licuuc -licudata'.}
    296         with-icu-cflags:CFLAGS
    297           => {Apply extra CFLAGS/CPPFLAGS necessary for building with ICU.
    298               e.g. -I/usr/local/include}
    299         with-icu-config:=auto
    300           => {Enable SQLITE_ENABLE_ICU. Value must be one of: auto, pkg-config,
    301               /path/to/icu-config}
    302         icu-collations=0
    303           => {Enable SQLITE_ENABLE_ICU_COLLATIONS. Requires --with-icu-ldflags=...
    304               or --with-icu-config}
    305       }
    306     }
    307 
    308     # Options for exotic/alternative build modes
    309     alternative-builds {
    310       {canonical autoconf} {
    311         with-wasi-sdk:=/opt/wasi-sdk
    312           => {Top-most dir of the wasi-sdk for a WASI build}
    313       }
    314 
    315       {*} {
    316         # Note that --static-cli-shell has a completely different
    317         # meaning from --static-shell in the autoconf build!
    318         # --[disable-]static-shell is a legacy flag which we can't
    319         # remove without breaking downstream builds.
    320         static-cli-shell=0
    321           => {Statically-link the sqlite3 CLI shell.
    322               This only works if the requisite libraries are all available in
    323               static form.}
    324       }
    325 
    326       {canonical} {
    327         static-shells=0
    328           => {Shorthand for --static-cli-shell --static-tclsqlite3}
    329 
    330         with-emsdk:=auto
    331           => {Top-most dir of the Emscripten SDK installation.
    332               Needed only by ext/wasm. Default=EMSDK env var.}
    333 
    334         amalgamation-extra-src:FILES
    335           => {Space-separated list of source files to append as-is to the resulting
    336               sqlite3.c amalgamation file. May be provided multiple times.}
    337       }
    338     }
    339 
    340     # Options primarily for downstream packagers/package maintainers
    341     packaging {
    342       {autoconf} {
    343         # --disable-static-shell: https://sqlite.org/forum/forumpost/cc219ee704
    344         # Note that this has a different meaning from --static-cli-shell in the
    345         # canonical build!
    346         static-shell=1
    347           => {Link the sqlite3 shell app against the DLL instead of embedding sqlite3.c}
    348       }
    349       {canonical autoconf} {
    350         rpath=1 => {Disable use of the rpath linker flag}
    351         # soname: https://sqlite.org/src/forumpost/5a3b44f510df8ded
    352         soname:=legacy
    353           => {SONAME for libsqlite3.so. "none", or not using this flag, sets no
    354               soname. "legacy" sets it to its historical value of
    355               libsqlite3.so.0.  A value matching the glob "libsqlite3.*" sets
    356               it to that literal value. Any other value is assumed to be a
    357               suffix which gets applied to "libsqlite3.so.",
    358               e.g. --soname=9.10 equates to "libsqlite3.so.9.10".}
    359         # dll-basename: https://sqlite.org/forum/forumpost/828fdfe904
    360         dll-basename:=auto
    361           => {Specifies the base name of the resulting DLL file.
    362               If not provided, "libsqlite3" is usually assumed but on some platforms
    363               a platform-dependent default is used. On some platforms this flag
    364               gets automatically enabled if it is not provided. Use "default" to
    365               explicitly disable platform-dependent activation on such systems.}
    366         # out-implib: https://sqlite.org/forum/forumpost/0c7fc097b2
    367         out-implib:=auto
    368           => {Enable use of --out-implib linker flag to generate an
    369               "import library" for the DLL. The output's base name is
    370               specified by this flag's value, with "auto" meaning to figure
    371               out a name automatically. On some platforms this flag gets
    372               automatically enabled if it is not provided. Use "none" to
    373               explicitly disable this feature on such platforms.}
    374       }
    375     }
    376 
    377     # Options mostly for sqlite's own development
    378     developer {
    379       {*} {
    380         # Note that using the --debug/--enable-debug flag here
    381         # requires patching autosetup/autosetup to rename its builtin
    382         # --debug to --autosetup-debug. See details in
    383         # autosetup/README.md#patching.
    384         with-debug=0
    385         debug=0
    386           => {Enable debug build flags. This option will impact performance by
    387               as much as 4x, as it includes large numbers of assert()s in
    388               performance-critical loops.  Never use --debug for production
    389               builds.}
    390         scanstatus
    391           => {Enable the SQLITE_ENABLE_STMT_SCANSTATUS feature flag}
    392       }
    393       {canonical} {
    394         dev
    395           => {Enable dev-mode build: automatically enables certain other flags}
    396         test-status
    397           => {Enable status of tests}
    398         gcov=0
    399           => {Enable coverage testing using gcov}
    400         linemacros
    401           => {Enable #line macros in the amalgamation}
    402         dynlink-tools
    403           => {Dynamically link libsqlite3 to certain tools which normally statically embed it}
    404         asan-fsanitize:=auto
    405           => {Comma- or space-separated list of -fsanitize flags for use with the
    406               fuzzcheck-asan tool. Only those which the compiler claims to support
    407               will actually be used. May be provided multiple times.}
    408       }
    409       {*} {
    410         dump-defines=0
    411           => {Dump autosetup defines to $::sqliteConfig(dump-defines-txt)
    412               (for build debugging)}
    413       }
    414     }
    415   }; # $allFlags
    416 
    417   set allFlags [proj-strip-hash-comments $allFlags]
    418   # ^^^ lappend of [sqlite-custom-flags] introduces weirdness if
    419   # we delay [proj-strip-hash-comments] until after that.
    420 
    421   ########################################################################
    422   # sqlite-custom.tcl is intended only for vendor-branch-specific
    423   # customization.  See autosetup/README.md#branch-customization for
    424   # details.
    425   if {[file exists $::autosetup(libdir)/sqlite-custom.tcl]} {
    426     uplevel 1 {source $::autosetup(libdir)/sqlite-custom.tcl}
    427   }
    428 
    429   if {[llength [info proc sqlite-custom-flags]] > 0} {
    430     # sqlite-custom-flags is assumed to be imported via
    431     # autosetup/sqlite-custom.tcl.
    432     set scf [sqlite-custom-flags]
    433     if {"" ne $scf} {
    434       lappend allFlags sqlite-custom-flags $scf
    435     }
    436   }
    437 
    438   #lappend allFlags just-testing {{*} {soname:=duplicateEntry => {x}}}
    439 
    440   # Filter allFlags to create the set of [options] legal for this build
    441   foreach {group XY} [subst -nobackslashes -nocommands $allFlags] {
    442     foreach {X Y} $XY {
    443       if { $buildMode in $X || "*" in $X } {
    444         options-add $Y
    445       }
    446     }
    447   }
    448 
    449   if {[catch {options {}} msg xopts]} {
    450     # Workaround for <https://github.com/msteveb/autosetup/issues/73>
    451     # where [options] behaves oddly on _some_ TCL builds when it's
    452     # called from deeper than the global scope.
    453     dict incr xopts -level
    454     return {*}$xopts $msg
    455   }
    456   sqlite-configure-phase1 $buildMode
    457   uplevel 1 $configScript
    458   sqlite-configure-finalize
    459 }; # sqlite-configure
    460 
    461 ########################################################################
    462 # Runs "phase 1" of the configure process: after initial --flags
    463 # handling but before sqlite-configure's $configScript argument is
    464 # run. $buildMode must be the mode which was passed to
    465 # [sqlite-configure].
    466 proc sqlite-configure-phase1 {buildMode} {
    467   define PACKAGE_NAME sqlite
    468   define PACKAGE_URL {https://sqlite.org}
    469   define PACKAGE_BUGREPORT [get-define PACKAGE_URL]/forum
    470   define PACKAGE_STRING "[get-define PACKAGE_NAME] [get-define PACKAGE_VERSION]"
    471   proj-xfer-options-aliases {
    472     # Carry values from hidden --flag aliases over to their canonical
    473     # flag forms. This list must include only options which are common
    474     # to all build modes supported by [sqlite-configure].
    475     with-readline-inc => with-readline-cflags
    476     with-readline-lib => with-readline-ldflags
    477     with-debug => debug
    478   }
    479   set ::sqliteConfig(msg-debug-enabled) [proj-val-truthy [get-env msg-debug 0]]
    480   proc-debug "msg-debug is enabled"
    481   proj-setup-autoreconfig SQLITE_AUTORECONFIG
    482   proj-file-extensions
    483   if {".exe" eq [get-define TARGET_EXEEXT]} {
    484     define SQLITE_OS_UNIX 0
    485     define SQLITE_OS_WIN 1
    486   } else {
    487     define SQLITE_OS_UNIX 1
    488     define SQLITE_OS_WIN 0
    489   }
    490   sqlite-setup-default-cflags
    491   define HAVE_LFS 0
    492   if {[opt-bool largefile]} {
    493     #
    494     # Insofar as we can determine HAVE_LFS has no effect on the
    495     # library.  Perhaps it did back in the early 2000's. The
    496     # --enable/disable-largefile flag is retained because it's
    497     # harmless, but it doesn't do anything useful. It does have
    498     # visible side-effects, though: the generated sqlite_cfg.h may (or
    499     # may not) define HAVE_LFS.
    500     cc-check-lfs
    501   }
    502   set srcdir $::autosetup(srcdir)
    503   proj-dot-ins-append $srcdir/Makefile.in
    504   if {[file exists $srcdir/sqlite3.pc.in]} {
    505     proj-dot-ins-append $srcdir/sqlite3.pc.in
    506   }
    507   sqlite-handle-hpux; # must be relatively early so that other config tests can work
    508 }; # sqlite-configure-phase1
    509 
    510 ########################################################################
    511 # Performs late-stage config steps common to all supported
    512 # $::sqliteConfig(build-mode) values.
    513 proc sqlite-configure-finalize {} {
    514   sqlite-handle-rpath
    515   sqlite-handle-soname
    516   sqlite-handle-threadsafe
    517   sqlite-handle-tempstore
    518   sqlite-handle-load-extension
    519   sqlite-handle-math
    520   sqlite-handle-icu
    521   if {[proj-opt-exists readline]} {
    522     sqlite-handle-line-editing
    523   }
    524   if {[proj-opt-exists shared]} {
    525     proj-define-for-opt shared ENABLE_LIB_SHARED "Build shared library?"
    526   }
    527   if {[proj-opt-exists static]} {
    528     if {![proj-define-for-opt static ENABLE_LIB_STATIC "Build static library?"]} {
    529       # This notice really only applies to the canonical build...
    530       proj-indented-notice {
    531         NOTICE: static lib build may be implicitly re-activated by
    532         other components, e.g. some test apps.
    533       }
    534     }
    535   }
    536   sqlite-handle-env-quirks
    537   sqlite-handle-common-feature-flags
    538   sqlite-finalize-feature-flags
    539   sqlite-process-dot-in-files; # do not [define] anything after this
    540   sqlite-dump-defines
    541 }
    542 
    543 ########################################################################
    544 # Internal config-time debugging output routine. It generates no
    545 # output unless msg-debug=1 is passed to the configure script.
    546 proc msg-debug {msg} {
    547   if {$::sqliteConfig(msg-debug-enabled)} {
    548     puts stderr [proj-bold "** DEBUG: $msg"]
    549   }
    550 }
    551 ########################################################################
    552 # A [msg-debug] proxy which prepends the name of the current proc to
    553 # the debug message. It is not legal to call this from the global
    554 # scope.
    555 proc proc-debug {msg} {
    556   msg-debug "\[[proj-scope 1]\]: $msg"
    557 }
    558 
    559 define OPT_FEATURE_FLAGS {} ; # -DSQLITE_OMIT/ENABLE flags.
    560 #
    561 # OPT_SHELL = feature-related CFLAGS for the sqlite3 CLI app. The
    562 # list's initial values are defaults which are always applied and not
    563 # affected by --feature-flags. The list is appended to by various
    564 # --feature-flags.
    565 define OPT_SHELL {
    566   -DSQLITE_DQS=0
    567   -DSQLITE_ENABLE_FTS4
    568   -DSQLITE_ENABLE_RTREE
    569   -DSQLITE_ENABLE_EXPLAIN_COMMENTS
    570   -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
    571   -DSQLITE_ENABLE_STMTVTAB
    572   -DSQLITE_ENABLE_DBPAGE_VTAB
    573   -DSQLITE_ENABLE_DBSTAT_VTAB
    574   -DSQLITE_ENABLE_BYTECODE_VTAB
    575   -DSQLITE_ENABLE_OFFSET_SQL_FUNC
    576   -DSQLITE_ENABLE_PERCENTILE
    577   -DSQLITE_STRICT_SUBTYPE=1
    578 }
    579 ########################################################################
    580 # Adds $args, if not empty, to OPT_FEATURE_FLAGS.  If the first arg is
    581 # -shell then it strips that arg and passes the remaining args the
    582 # sqlite-add-shell-opt in addition to adding them to
    583 # OPT_FEATURE_FLAGS. This is intended only for holding
    584 # -DSQLITE_ENABLE/OMIT/... flags, but that is not enforced here.
    585 proc sqlite-add-feature-flag {args} {
    586   set shell ""
    587   if {"-shell" eq [lindex $args 0]} {
    588     set args [lassign $args shell]
    589   }
    590   if {"" ne $args} {
    591     if {"" ne $shell} {
    592       sqlite-add-shell-opt {*}$args
    593     }
    594     define-append OPT_FEATURE_FLAGS {*}$args
    595   }
    596 }
    597 
    598 ########################################################################
    599 # Appends $args, if not empty, to OPT_SHELL.
    600 proc sqlite-add-shell-opt {args} {
    601   if {"" ne $args} {
    602     define-append OPT_SHELL {*}$args
    603   }
    604 }
    605 
    606 ########################################################################
    607 # Check for log(3) in libm and die with an error if it is not
    608 # found. $featureName should be the feature name which requires that
    609 # function (it's used only in error messages). defines LDFLAGS_MATH to
    610 # the required linker flags (which may be empty even if the math APIs
    611 # are found, depending on the OS).
    612 proc sqlite-affirm-have-math {featureName} {
    613   if {"" eq [get-define LDFLAGS_MATH ""]} {
    614     if {![msg-quiet proj-check-function-in-lib log m]} {
    615       user-error "Missing math APIs for $featureName"
    616     }
    617     set lfl [get-define lib_log ""]
    618     undefine lib_log
    619     if {"" ne $lfl} {
    620       user-notice "Forcing requirement of $lfl for $featureName"
    621     }
    622     define LDFLAGS_MATH $lfl
    623   }
    624 }
    625 
    626 ########################################################################
    627 # Run checks for required binaries, like ld and ar. In the canonical
    628 # build this must come before [sqlite-handle-wasi-sdk].
    629 proc sqlite-check-common-bins {} {
    630   cc-check-tools ld ar ; # must come before [sqlite-handle-wasi-sdk]
    631   if {"" eq [proj-bin-define install]} {
    632     proj-warn "Cannot find install binary, so 'make install' will not work."
    633     define BIN_INSTALL false
    634   }
    635 }
    636 
    637 ########################################################################
    638 # Run checks for system-level includes and libs which are common to
    639 # both the canonical build and the "autoconf" bundle.
    640 #
    641 # For the canonical build this must come after
    642 # [sqlite-handle-wasi-sdk], as that function may change the
    643 # environment in ways which affect this.
    644 proc sqlite-check-common-system-deps {} {
    645   # Check for needed/wanted data types
    646   cc-with {-includes stdint.h} \
    647     {cc-check-types int8_t int16_t int32_t int64_t intptr_t \
    648        uint8_t uint16_t uint32_t uint64_t uintptr_t}
    649 
    650   # Check for needed/wanted functions
    651   cc-check-functions gmtime_r isnan localtime_r localtime_s \
    652     usleep utime pread pread64 pwrite pwrite64
    653 
    654   apply {{} {
    655     set ldrt ""
    656     # Collapse funcs from librt into LDFLAGS_RT.
    657     # Some systems (ex: SunOS) require -lrt in order to use nanosleep
    658     foreach func {fdatasync nanosleep} {
    659       if {[proj-check-function-in-lib $func rt]} {
    660         set ldrt [get-define lib_${func} ""]
    661         undefine lib_${func}
    662         if {"" ne $ldrt} {
    663           break
    664         }
    665       }
    666     }
    667     define LDFLAGS_RT $ldrt
    668   }}
    669 
    670   # Check for needed/wanted headers
    671   cc-check-includes \
    672     sys/types.h sys/stat.h dlfcn.h unistd.h \
    673     stdlib.h malloc.h memory.h \
    674     string.h strings.h \
    675     inttypes.h
    676 
    677   if {[cc-check-includes zlib.h] && [proj-check-function-in-lib deflate z]} {
    678     # TODO? port over the more sophisticated zlib search from the fossil auto.def
    679     define HAVE_ZLIB 1
    680     define LDFLAGS_ZLIB -lz
    681     sqlite-add-shell-opt -DSQLITE_HAVE_ZLIB=1
    682     sqlite-add-feature-flag -DSQLITE_HAVE_ZLIB=1
    683   } else {
    684     define HAVE_ZLIB 0
    685     define LDFLAGS_ZLIB ""
    686   }
    687 }
    688 
    689 ########################################################################
    690 # Move -DSQLITE_OMIT... and -DSQLITE_ENABLE... flags from CFLAGS and
    691 # CPPFLAGS to OPT_FEATURE_FLAGS and remove them from BUILD_CFLAGS.
    692 proc sqlite-munge-cflags {} {
    693   # Move CFLAGS and CPPFLAGS entries matching -DSQLITE_OMIT* and
    694   # -DSQLITE_ENABLE* to OPT_FEATURE_FLAGS. This behavior is derived
    695   # from the legacy build and was missing the 3.48.0 release (the
    696   # initial Autosetup port).
    697   # https://sqlite.org/forum/forumpost/9801e54665afd728
    698   #
    699   # Handling of CPPFLAGS, as well as removing ENABLE/OMIT from
    700   # CFLAGS/CPPFLAGS, was missing in the 3.49.0 release as well.
    701   #
    702   # If any configure flags for features are in conflict with
    703   # CFLAGS/CPPFLAGS-specified feature flags, all bets are off.  There
    704   # are no guarantees about which one will take precedence.
    705   foreach flagDef {CFLAGS CPPFLAGS} {
    706     set tmp ""
    707     foreach cf [get-define $flagDef ""] {
    708       switch -glob -- $cf {
    709         -DSQLITE_OMIT* -
    710         -DSQLITE_ENABLE* {
    711           sqlite-add-feature-flag $cf
    712         }
    713         default {
    714           lappend tmp $cf
    715         }
    716       }
    717     }
    718     define $flagDef $tmp
    719   }
    720 
    721   # Strip all SQLITE_ENABLE/OMIT flags from BUILD_CFLAGS,
    722   # for compatibility with the legacy build.
    723   set tmp ""
    724   foreach cf [get-define BUILD_CFLAGS ""] {
    725     switch -glob -- $cf {
    726       -DSQLITE_OMIT* -
    727       -DSQLITE_ENABLE* {}
    728       default {
    729         lappend tmp $cf
    730       }
    731     }
    732   }
    733   define BUILD_CFLAGS $tmp
    734 }
    735 
    736 #########################################################################
    737 # Set up the default CFLAGS and BUILD_CFLAGS values.
    738 proc sqlite-setup-default-cflags {} {
    739   ########################################################################
    740   # We differentiate between two C compilers: the one used for binaries
    741   # which are to run on the build system (in autosetup it's called
    742   # CC_FOR_BUILD and in Makefile.in it's $(B.cc)) and the one used for
    743   # compiling binaries for the target system (CC a.k.a. $(T.cc)).
    744   # Normally they're the same, but they will differ when
    745   # cross-compiling.
    746   set defaultCFlags {-O2}
    747   if {!$::sqliteConfig(is-cross-compiling)} {
    748     # When cross-compiling we default to not using the -g flag, based
    749     # on a /chat discussion prompted by
    750     # https://sqlite.org/forum/forumpost/9a67df63eda9925c
    751     lappend defaultCFlags -g
    752   }
    753   define CFLAGS [proj-get-env CFLAGS $defaultCFlags]
    754   # BUILD_CFLAGS is the CFLAGS for CC_FOR_BUILD.
    755   define BUILD_CFLAGS [proj-get-env BUILD_CFLAGS {-g}]
    756   sqlite-munge-cflags
    757 }
    758 
    759 ########################################################################
    760 # Handle various SQLITE_ENABLE/OMIT_... feature flags.
    761 proc sqlite-handle-common-feature-flags {} {
    762   msg-result "Feature flags..."
    763   if {![opt-bool all]} {
    764     # Special handling for --disable-all
    765     foreach flag $::sqliteConfig(all-flag-enables) {
    766       if {![proj-opt-was-provided $flag]} {
    767         proj-opt-set $flag 0
    768       }
    769     }
    770   }
    771   foreach {boolFlag featureFlag ifSetEvalThis} [proj-strip-hash-comments {
    772     all         {} {
    773       # The 'all' option must be first in this list.  This impl makes
    774       # an effort to only apply flags which the user did not already
    775       # apply, so that combinations like (--all --disable-geopoly)
    776       # will indeed disable geopoly. There are corner cases where
    777       # flags which depend on each other will behave in non-intuitive
    778       # ways:
    779       #
    780       # --all --disable-rtree
    781       #
    782       # Will NOT disable geopoly, though geopoly depends on rtree.
    783       # The --geopoly flag, though, will automatically re-enable
    784       # --rtree, so --disable-rtree won't actually disable anything in
    785       # that case.
    786       foreach k $::sqliteConfig(all-flag-enables) {
    787         if {![proj-opt-was-provided $k]} {
    788           proj-opt-set $k 1
    789         }
    790       }
    791     }
    792     fts3         -DSQLITE_ENABLE_FTS3    {sqlite-affirm-have-math fts3}
    793     fts4         -DSQLITE_ENABLE_FTS4    {sqlite-affirm-have-math fts4}
    794     fts5         -DSQLITE_ENABLE_FTS5    {sqlite-affirm-have-math fts5}
    795     geopoly      -DSQLITE_ENABLE_GEOPOLY {proj-opt-set rtree}
    796     rtree        -DSQLITE_ENABLE_RTREE   {}
    797     session      {-DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK} {}
    798     update-limit -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT {}
    799     memsys5      -DSQLITE_ENABLE_MEMSYS5 {}
    800     memsys3      {} {
    801       if {[opt-bool memsys5]} {
    802         proj-warn "not enabling memsys3 because memsys5 is enabled."
    803         expr 0
    804       } else {
    805         sqlite-add-feature-flag -DSQLITE_ENABLE_MEMSYS3
    806       }
    807     }
    808     bytecode-vtab   -DSQLITE_ENABLE_BYTECODE_VTAB {}
    809     scanstatus      {-DSQLITE_ENABLE_STMT_SCANSTATUS -DSQLITE_ENABLE_BYTECODE_VTAB} {}
    810     column-metadata -DSQLITE_ENABLE_COLUMN_METADATA {}
    811     dbpage          -DSQLITE_ENABLE_DBPAGE_VTAB {}
    812     dbstat          -DSQLITE_ENABLE_DBSTAT_VTAB {}
    813     carray          -DSQLITE_ENABLE_CARRAY {}
    814   }] {
    815     if {$boolFlag ni $::autosetup(options)} {
    816       # Skip flags which are in the canonical build but not
    817       # the autoconf bundle.
    818       continue
    819     }
    820     proj-if-opt-truthy $boolFlag {
    821       sqlite-add-feature-flag $featureFlag
    822       if {0 != [eval $ifSetEvalThis] && "all" ne $boolFlag} {
    823         msg-result "  + $boolFlag"
    824       }
    825     } {
    826       if {"all" ne $boolFlag} {
    827         msg-result "  - $boolFlag"
    828       }
    829     }
    830   }
    831   ########################################################################
    832   # Invert the above loop's logic for some SQLITE_OMIT_...  cases. If
    833   # config option $boolFlag is false, [sqlite-add-feature-flag
    834   # $featureFlag], where $featureFlag is intended to be
    835   # -DSQLITE_OMIT_...
    836   foreach {boolFlag featureFlag} {
    837     json        -DSQLITE_OMIT_JSON
    838   } {
    839     if {[proj-opt-truthy $boolFlag]} {
    840       msg-result "  + $boolFlag"
    841     } else {
    842       sqlite-add-feature-flag $featureFlag
    843       msg-result "  - $boolFlag"
    844     }
    845   }
    846 }
    847 
    848 #########################################################################
    849 # Remove duplicates from the final feature flag sets and show them to
    850 # the user.
    851 proc sqlite-finalize-feature-flags {} {
    852   set oFF [get-define OPT_FEATURE_FLAGS]
    853   if {"" ne $oFF} {
    854     define OPT_FEATURE_FLAGS [lsort -unique $oFF]
    855     msg-result "Library feature flags: [get-define OPT_FEATURE_FLAGS]"
    856   }
    857   set oFF [get-define OPT_SHELL]
    858   if {"" ne $oFF} {
    859     define OPT_SHELL [lsort -unique $oFF]
    860     msg-result "Shell options: [get-define OPT_SHELL]"
    861   }
    862   if {"" ne [set extraSrc [get-define AMALGAMATION_EXTRA_SRC ""]]} {
    863     proj-assert {"canonical" eq $::sqliteConfig(build-mode)}
    864     msg-result "Appending source files to amalgamation: $extraSrc"
    865   }
    866   if {[lsearch [get-define TARGET_DEBUG ""] -DSQLITE_DEBUG=1] > -1} {
    867     msg-result "Note: this is a debug build, so performance will suffer."
    868   }
    869 }
    870 
    871 ########################################################################
    872 # Checks for the --debug flag and [define]s TARGET_DEBUG based on
    873 # that.  TARGET_DEBUG is unused in the autoconf build but that is
    874 # arguably a bug.
    875 proc sqlite-handle-debug {} {
    876   msg-checking "SQLITE_DEBUG build? "
    877   proj-if-opt-truthy debug {
    878     define TARGET_DEBUG {-g -DSQLITE_DEBUG=1 -O0 -Wall}
    879     sqlite-add-feature-flag -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE
    880     proj-opt-set memsys5
    881     msg-result yes
    882   } {
    883     define TARGET_DEBUG {-DNDEBUG}
    884     msg-result no
    885   }
    886 }
    887 
    888 ########################################################################
    889 # "soname" for libsqlite3.so. See discussion at:
    890 # https://sqlite.org/src/forumpost/5a3b44f510df8ded
    891 proc sqlite-handle-soname {} {
    892   define LDFLAGS_LIBSQLITE3_SONAME ""
    893   if {[proj-opt-was-provided soname]} {
    894     set soname [join [opt-val soname] ""]
    895   } else {
    896     # Enabling soname breaks linking for the --dynlink-tools feature,
    897     # and this project has no direct use for soname, so default to
    898     # none. Package maintainers, on the other hand, like to have an
    899     # soname.
    900     set soname none
    901   }
    902   switch -exact -- $soname {
    903     none - "" { return 0 }
    904     legacy    { set soname libsqlite3.so.0 }
    905     default {
    906       if {[string match libsqlite3.* $soname]} {
    907         # use it as-is
    908       } else {
    909         # Assume it's a suffix
    910         set soname "libsqlite3.so.${soname}"
    911       }
    912     }
    913   }
    914   proc-debug "soname=$soname"
    915   if {[proj-check-soname $soname]} {
    916     define LDFLAGS_LIBSQLITE3_SONAME [get-define LDFLAGS_SONAME_PREFIX]$soname
    917     msg-result "Setting SONAME using: [get-define LDFLAGS_LIBSQLITE3_SONAME]"
    918   } elseif {[proj-opt-was-provided soname]} {
    919     # --soname was explicitly requested but not available, so fail fatally
    920     proj-fatal "This environment does not support SONAME."
    921   } else {
    922     # --soname was not explicitly requested but not available, so just warn
    923     msg-result "This environment does not support SONAME."
    924   }
    925 }
    926 
    927 ########################################################################
    928 # If --enable-threadsafe is set, this adds -DSQLITE_THREADSAFE=1 to
    929 # OPT_FEATURE_FLAGS and sets LDFLAGS_PTHREAD to the linker flags
    930 # needed for linking pthread (possibly an empty string). If
    931 # --enable-threadsafe is not set, adds -DSQLITE_THREADSAFE=0 to
    932 # OPT_FEATURE_FLAGS and sets LDFLAGS_PTHREAD to an empty string.
    933 proc sqlite-handle-threadsafe {} {
    934   msg-checking "Support threadsafe operation? "
    935   define LDFLAGS_PTHREAD ""
    936   set enable 0
    937   proj-if-opt-truthy threadsafe {
    938     msg-result "Checking for libs..."
    939     if {[proj-check-function-in-lib pthread_create pthread]
    940         && [proj-check-function-in-lib pthread_mutexattr_init pthread]} {
    941       set enable 1
    942       define LDFLAGS_PTHREAD [get-define lib_pthread_create]
    943       undefine lib_pthread_create
    944       undefine lib_pthread_mutexattr_init
    945     } elseif {[proj-opt-was-provided threadsafe]} {
    946       user-error "Missing required pthread libraries. Use --disable-threadsafe to disable this check."
    947     } else {
    948       msg-result "pthread support not detected"
    949     }
    950     # Recall that LDFLAGS_PTHREAD might be empty even if pthreads if
    951     # found because it's in -lc on some platforms.
    952   } {
    953     msg-result "Disabled using --disable-threadsafe"
    954   }
    955   sqlite-add-feature-flag -DSQLITE_THREADSAFE=${enable}
    956   return $enable
    957 }
    958 
    959 ########################################################################
    960 # Handles the --with-tempstore flag.
    961 #
    962 # The test fixture likes to set SQLITE_TEMP_STORE on its own, so do
    963 # not set that feature flag unless it was explicitly provided to the
    964 # configure script.
    965 proc sqlite-handle-tempstore {} {
    966   if {[proj-opt-was-provided with-tempstore]} {
    967     set ts [opt-val with-tempstore no]
    968     set tsn 1
    969     msg-checking "Use an in-RAM database for temporary tables? "
    970     switch -exact -- $ts {
    971       never  { set tsn 0 }
    972       no     { set tsn 1 }
    973       yes    { set tsn 2 }
    974       always { set tsn 3 }
    975       default {
    976         user-error "Invalid --with-tempstore value '$ts'. Use one of: never, no, yes, always"
    977       }
    978     }
    979     msg-result $ts
    980     sqlite-add-feature-flag -DSQLITE_TEMP_STORE=$tsn
    981   }
    982 }
    983 
    984 ########################################################################
    985 # Check for the Emscripten SDK for building the web-based wasm
    986 # components.  The core lib and tools do not require this but ext/wasm
    987 # does. Most of the work is done via [proj-check-emsdk], then this
    988 # function adds the following defines:
    989 #
    990 # - EMCC_WRAPPER = "" or top-srcdir/tool/emcc.sh
    991 # - BIN_WASM_OPT = "" or path to wasm-opt
    992 # - BIN_WASM_STRIP = "" or path to wasm-strip
    993 #
    994 # Noting that:
    995 #
    996 # 1) Not finding the SDK is not fatal at this level, nor is failure to
    997 #    find one of the related binaries.
    998 #
    999 # 2) wasm-strip is part of the wabt package:
   1000 #
   1001 #   https://github.com/WebAssembly/wabt
   1002 #
   1003 # and this project requires it for production-mode builds but not dev
   1004 # builds.
   1005 #
   1006 proc sqlite-handle-emsdk {} {
   1007   define EMCC_WRAPPER ""
   1008   define BIN_WASM_STRIP ""
   1009   define BIN_WASM_OPT ""
   1010   set srcdir $::autosetup(srcdir)
   1011   if {$srcdir ne $::autosetup(builddir)} {
   1012     # The EMSDK pieces require writing to the original source tree
   1013     # even when doing an out-of-tree build. The ext/wasm pieces do not
   1014     # support an out-of-tree build so we treat that case as if EMSDK
   1015     # were not found.
   1016     msg-result "Out-of tree build: not checking for EMSDK."
   1017     return
   1018   }
   1019   set emccSh $srcdir/tool/emcc.sh
   1020   set extWasmConfig $srcdir/ext/wasm/config.make
   1021   if {![get-define HAVE_WASI_SDK] && [proj-check-emsdk]} {
   1022     define EMCC_WRAPPER $emccSh
   1023     set emsdkHome [get-define EMSDK_HOME ""]
   1024     proj-assert {"" ne $emsdkHome}
   1025     #define EMCC_WRAPPER ""; # just for testing
   1026     proj-bin-define wasm-strip
   1027     proj-bin-define bash; # ext/wasm/GNUmakefile requires bash
   1028     if {[file-isexec $emsdkHome/upstream/bin/wasm-opt]} {
   1029       define BIN_WASM_OPT $emsdkHome/upstream/bin/wasm-opt
   1030     } else {
   1031       # Maybe there's a copy in the path?
   1032       proj-bin-define wasm-opt BIN_WASM_OPT
   1033     }
   1034     proj-dot-ins-append $emccSh.in $emccSh {
   1035       catch {exec chmod u+x $dotInsOut}
   1036     }
   1037     proj-dot-ins-append $extWasmConfig.in $extWasmConfig
   1038   } else {
   1039     define EMCC_WRAPPER ""
   1040     file delete -force -- $emccSh $extWasmConfig
   1041   }
   1042 }
   1043 
   1044 ########################################################################
   1045 # Internal helper for [sqlite-check-line-editing]. Returns a list of
   1046 # potential locations under which readline.h might be found.
   1047 #
   1048 # On some environments this function may perform extra work to help
   1049 # sqlite-check-line-editing figure out how to find libreadline and
   1050 # friends. It will communicate those results via means other than the
   1051 # result value, e.g. by modifying configure --flags.
   1052 proc sqlite-get-readline-dir-list {} {
   1053   # Historical note: the dirs list, except for the inclusion of
   1054   # $prefix and some platform-specific dirs, originates from the
   1055   # legacy configure script.
   1056   set dirs [list [get-define prefix]]
   1057   switch -glob -- [get-define host] {
   1058     *-linux-android {
   1059       # Possibly termux
   1060       lappend dirs /data/data/com.termux/files/usr
   1061     }
   1062     *-mingw32 {
   1063       lappend dirs /mingw32 /mingw
   1064     }
   1065     *-mingw64 {
   1066       lappend dirs /mingw64 /mingw
   1067     }
   1068     *-haiku {
   1069       lappend dirs /boot/system/develop/headers
   1070       if {[opt-val with-readline-ldflags] in {auto ""}} {
   1071         # If the user did not supply their own --with-readline-ldflags
   1072         # value, hijack that flag to inject options which are known to
   1073         # work on Haiku OS installations.
   1074         if {"" ne [glob -nocomplain /boot/system/lib/libreadline*]} {
   1075           proj-opt-set with-readline-ldflags {-L/boot/system/lib -lreadline}
   1076         }
   1077       }
   1078     }
   1079   }
   1080   lappend dirs /usr /usr/local /usr/local/readline /usr/contrib
   1081   set rv {}
   1082   foreach d $dirs {
   1083     if {[file isdir $d]} {lappend rv $d}
   1084   }
   1085   #proc-debug "dirs=$rv"
   1086   return $rv
   1087 }
   1088 
   1089 ########################################################################
   1090 # sqlite-check-line-editing jumps through proverbial hoops to try to
   1091 # find a working line-editing library, setting:
   1092 #
   1093 #   - HAVE_READLINE to 0 or 1
   1094 #   - HAVE_LINENOISE to 0, 1, or 2
   1095 #   - HAVE_EDITLINE to 0 or 1
   1096 #
   1097 # Only one of ^^^ those will be set to non-0.
   1098 #
   1099 #   - LDFLAGS_READLINE = linker flags or empty string
   1100 #
   1101 #   - CFLAGS_READLINE = compilation flags for clients or empty string.
   1102 #
   1103 # Note that LDFLAGS_READLINE and CFLAGS_READLINE may refer to
   1104 # linenoise or editline, not necessarily libreadline.  In some cases
   1105 # it will set HAVE_READLINE=1 when it's really using editline, for
   1106 # reasons described in this function's comments.
   1107 #
   1108 # Returns a string describing which line-editing approach to use, or
   1109 # "none" if no option is available.
   1110 #
   1111 # Order of checks:
   1112 #
   1113 #  1) --with-linenoise trumps all others and skips all of the
   1114 #     complexities involved with the remaining options.
   1115 #
   1116 #  2) --editline trumps --readline
   1117 #
   1118 #  3) --disable-readline trumps --readline
   1119 #
   1120 #  4) Default to automatic search for optional readline
   1121 #
   1122 #  5) Try to find readline or editline. If it's not found AND the
   1123 #     corresponding --FEATURE flag was explicitly given then fail
   1124 #     fatally, else fail non-fatally.
   1125 proc sqlite-check-line-editing {} {
   1126   msg-result "Checking for line-editing capability..."
   1127   define HAVE_READLINE 0
   1128   define HAVE_LINENOISE 0
   1129   define HAVE_EDITLINE 0
   1130   define LDFLAGS_READLINE ""
   1131   define CFLAGS_READLINE ""
   1132   set failIfNotFound 0 ; # Gets set to 1 for explicit --FEATURE requests
   1133                          # so that we know whether to fail fatally or not
   1134                          # if the library is not found.
   1135   set libsForReadline {readline edit} ; # -l<LIB> names to check for readline().
   1136                                         # The libedit check changes this.
   1137   set editLibName "readline"     ; # "readline" or "editline"
   1138   set editLibDef "HAVE_READLINE" ; # "HAVE_READLINE" or "HAVE_EDITLINE"
   1139   set dirLn [opt-val with-linenoise]
   1140 
   1141   # If none of --with-linenoise, --enable-readline, or --enable-editline
   1142   # are provided, but there exists a directory "linenoise" at $HOME or
   1143   # a sibling of the build or source directory, then try to use that linenoise
   1144   # direcctory.
   1145   #
   1146   if {"" eq $dirLn
   1147    && ![proj-opt-was-provided readline]
   1148    && ![proj-opt-was-provided editline]
   1149   } {
   1150     set dirlist ../linenoise
   1151     catch {lappend dirlist [file-normalize $::autosetup(srcdir)/../linenoise]}
   1152     catch {lappend dirlist $::env(HOME)/linenoise}
   1153     foreach d $dirlist {
   1154       if {[file exists $d/linenoise.c] && [file exists $d/linenoise.h]} {
   1155         set dirLn $d
   1156         break
   1157       }
   1158     }
   1159   }
   1160 
   1161   if {"" ne $dirLn} {
   1162     # Use linenoise from a copy of its sources (not a library)...
   1163     if {![file isdir $dirLn]} {
   1164       proj-fatal "--with-linenoise value is not a directory"
   1165     }
   1166     set lnH $dirLn/linenoise.h
   1167     if {![file exists $lnH] } {
   1168       proj-fatal "Cannot find linenoise.h in $dirLn"
   1169     }
   1170     set lnC ""
   1171     set lnCOpts {linenoise-ship.c linenoise.c}
   1172     foreach f $lnCOpts {
   1173       if {[file exists $dirLn/$f]} {
   1174         set lnC $dirLn/$f
   1175         break
   1176       }
   1177     }
   1178     if {"" eq $lnC} {
   1179       proj-fatal "Cannot find any of $lnCOpts in $dirLn"
   1180     }
   1181     set flavor ""
   1182     set lnVal [proj-which-linenoise $lnH]
   1183     switch -- $lnVal {
   1184       1 { set flavor "antirez" }
   1185       2 { set flavor "msteveb" }
   1186       default {
   1187         proj-fatal "Cannot determine the flavor of linenoise from $lnH"
   1188       }
   1189     }
   1190     define CFLAGS_READLINE "-I$dirLn $lnC"
   1191     define HAVE_LINENOISE $lnVal
   1192     sqlite-add-shell-opt -DHAVE_LINENOISE=$lnVal
   1193     if {$::sqliteConfig(use-jim-for-codegen) && 2 == $lnVal} {
   1194       define-append CFLAGS_JIMSH -DUSE_LINENOISE [get-define CFLAGS_READLINE]
   1195       user-notice "Adding linenoise support to jimsh."
   1196     } else {
   1197       msg-result "Using linenoise at [file-normalize $dirLn]"
   1198     }
   1199     return "linenoise ($flavor)"
   1200   } elseif {[opt-bool editline]} {
   1201     # libedit mimics libreadline and on some systems does not have its
   1202     # own header installed (instead, that of libreadline is used).
   1203     #
   1204     # shell.c historically expects HAVE_EDITLINE to be set for
   1205     # libedit, but it then expects to see <editline/readline.h>, which
   1206     # some system's don't actually have despite having libedit.  If we
   1207     # end up finding <editline/readline.h> below, we will use
   1208     # -DHAVE_EDITLINE=1, else we will use -DHAVE_READLINE=1. In either
   1209     # case, we will link against libedit.
   1210     set failIfNotFound 1
   1211     set libsForReadline {edit}
   1212     set editLibName editline
   1213   } elseif {![opt-bool readline]} {
   1214     msg-result "Readline support explicitly disabled with --disable-readline"
   1215     return "none"
   1216   } elseif {[proj-opt-was-provided readline]} {
   1217     # If an explicit --[enable-]readline was used, fail if it's not
   1218     # found, else treat the feature as optional.
   1219     set failIfNotFound 1
   1220   }
   1221 
   1222   # Transform with-readline-header=X to with-readline-cflags=-I...
   1223   set v [opt-val with-readline-header]
   1224   proj-opt-set with-readline-header ""
   1225   if {"" ne $v} {
   1226     if {"auto" eq $v} {
   1227       proj-opt-set with-readline-cflags auto
   1228     } else {
   1229       set v [file dirname $v]
   1230       if {[string match */readline $v]} {
   1231         # Special case: if the path includes .../readline/readline.h,
   1232         # set the -I to one dir up from that because our sources
   1233         # #include <readline/readline.h> or <editline/readline.h>.
   1234         set v [file dirname $v]
   1235       }
   1236       proj-opt-set with-readline-cflags "-I$v"
   1237     }
   1238   }
   1239 
   1240   # Look for readline.h
   1241   set rlInc [opt-val with-readline-cflags auto]
   1242   if {"auto" eq $rlInc} {
   1243     set rlInc ""
   1244     if {$::sqliteConfig(is-cross-compiling)} {
   1245       # ^^^ this check is derived from the legacy configure script.
   1246       proj-warn "Skipping check for readline.h because we're cross-compiling."
   1247     } else {
   1248       set dirs [sqlite-get-readline-dir-list]
   1249       set subdirs [list \
   1250                      include/$editLibName \
   1251                      readline]
   1252       if {"editline" eq $editLibName} {
   1253         lappend subdirs include/readline
   1254         # ^^^ editline, on some systems, does not have its own header,
   1255         # and uses libreadline's header.
   1256       }
   1257       lappend subdirs include
   1258       set rlInc [proj-search-for-header-dir readline.h \
   1259                    -dirs $dirs -subdirs $subdirs]
   1260       #proc-debug "rlInc=$rlInc"
   1261       if {"" ne $rlInc} {
   1262         if {[string match */readline $rlInc]} {
   1263           set rlInc [file dirname $rlInc]; # CLI shell: #include <readline/readline.h>
   1264         } elseif {[string match */editline $rlInc]} {
   1265           set editLibDef HAVE_EDITLINE
   1266           set rlInc [file dirname $rlInc]; # CLI shell: #include <editline/readline.h>
   1267         }
   1268         set rlInc "-I${rlInc}"
   1269       }
   1270     }
   1271   } elseif {"" ne $rlInc && ![string match *-I* $rlInc]} {
   1272     proj-fatal "Argument to --with-readline-cflags is intended to be CFLAGS and contain -I..."
   1273   }
   1274 
   1275   # If readline.h was found/specified, look for lib(readline|edit)...
   1276   #
   1277   # This is not quite straightforward because both libreadline and
   1278   # libedit typically require some other library which (according to
   1279   # legacy autotools-generated tests) provides tgetent(3). On some
   1280   # systems that's built into libreadline/edit, on some (most?) its in
   1281   # lib[n]curses, and on some it's in libtermcap.
   1282   set rlLib ""
   1283   if {"" ne $rlInc} {
   1284     set rlLib [opt-val with-readline-ldflags]
   1285     #proc-debug "rlLib=$rlLib"
   1286     if {$rlLib in {auto ""}} {
   1287       set rlLib ""  ; # make sure it's not "auto", as we may append to it below
   1288       set libTerm ""; # lib with tgetent(3)
   1289       if {[proj-check-function-in-lib tgetent [list $editLibName ncurses curses termcap]]} {
   1290         # ^^^ that libs list comes from the legacy configure script ^^^
   1291         set libTerm [get-define lib_tgetent]
   1292         undefine lib_tgetent
   1293       }
   1294       if {$editLibName eq $libTerm} {
   1295         # tgetent(3) was found in the editing library
   1296         set rlLib $libTerm
   1297       } elseif {[proj-check-function-in-lib readline $libsForReadline $libTerm]} {
   1298         # tgetent(3) was found in an external lib
   1299         set rlLib [get-define lib_readline]
   1300         lappend rlLib $libTerm
   1301         undefine lib_readline
   1302       }
   1303     }
   1304   }
   1305 
   1306   # If we found a library, configure the build to use it...
   1307   if {"" ne $rlLib} {
   1308     if {"editline" eq $editLibName && "HAVE_READLINE" eq $editLibDef} {
   1309       # Alert the user that, despite outward appearances, we won't be
   1310       # linking to the GPL'd libreadline. Presumably that distinction is
   1311       # significant for those using --editline.
   1312       proj-indented-notice {
   1313         NOTE: the local libedit uses <readline/readline.h> so we
   1314         will compile with -DHAVE_READLINE=1 but will link with
   1315         libedit.
   1316       }
   1317     }
   1318     set rlLib [join $rlLib]
   1319     set rlInc [join $rlInc]
   1320     define LDFLAGS_READLINE $rlLib
   1321     define CFLAGS_READLINE $rlInc
   1322     proj-assert {$editLibDef in {HAVE_READLINE HAVE_EDITLINE}}
   1323     proj-assert {$editLibName in {readline editline}}
   1324     sqlite-add-shell-opt -D${editLibDef}=1
   1325     msg-result "Using $editLibName flags: $rlInc $rlLib"
   1326     # Check whether rl_completion_matches() has a signature we can use
   1327     # and disable that sub-feature if it doesn't.
   1328     if {![cctest -cflags "$rlInc -D${editLibDef}" -libs $rlLib -nooutput 1 \
   1329             -source {
   1330              #include <stdio.h>
   1331              #ifdef HAVE_EDITLINE
   1332              #include <editline/readline.h>
   1333              #else
   1334              #include <readline/readline.h>
   1335              #endif
   1336              static char * rcg(const char *z, int i){(void)z; (void)i; return 0;}
   1337              int main(void) {
   1338                char ** x = rl_completion_matches("one", rcg);
   1339                (void)x;
   1340                return 0;
   1341              }
   1342            }]} {
   1343       proj-warn "readline-style completion disabled due to rl_completion_matches() signature mismatch"
   1344       sqlite-add-shell-opt -DSQLITE_OMIT_READLINE_COMPLETION
   1345     }
   1346     return $editLibName
   1347   }
   1348 
   1349   if {$failIfNotFound} {
   1350     proj-fatal "Explicit --$editLibName failed to find a matching library."
   1351   }
   1352   return "none"
   1353 }; # sqlite-check-line-editing
   1354 
   1355 ########################################################################
   1356 # Runs sqlite-check-line-editing and adds a message around it. In the
   1357 # canonical build this must not be called before
   1358 # sqlite-determine-codegen-tcl for reasons now lost to history (and
   1359 # might not still be applicable).
   1360 proc sqlite-handle-line-editing {} {
   1361   msg-result "Line-editing support for the sqlite3 shell: [sqlite-check-line-editing]"
   1362 }
   1363 
   1364 
   1365 ########################################################################
   1366 # ICU - International Components for Unicode
   1367 #
   1368 # Handles these flags:
   1369 #
   1370 #  --with-icu-ldflags=LDFLAGS
   1371 #  --with-icu-cflags=CFLAGS
   1372 #  --with-icu-config[=auto | pkg-config | /path/to/icu-config]
   1373 #  --enable-icu-collations
   1374 #
   1375 # --with-icu-config values:
   1376 #
   1377 #   - auto: use the first one of (pkg-config, icu-config) found on the
   1378 #     system.
   1379 #   - pkg-config: use only pkg-config to determine flags
   1380 #   - /path/to/icu-config: use that to determine flags
   1381 #
   1382 # If --with-icu-config is used and neither pkg-config nor icu-config
   1383 # are found, fail fatally.
   1384 #
   1385 # If both --with-icu-ldflags and --with-icu-config are provided, they
   1386 # are cumulative.  If neither are provided, icu-collations is not
   1387 # honored and a warning is emitted if it is provided.
   1388 #
   1389 # Design note: though we could automatically enable ICU if the
   1390 # icu-config binary or (pkg-config icu-io) are found, we specifically
   1391 # do not. ICU is always an opt-in feature.
   1392 proc sqlite-handle-icu {} {
   1393   define LDFLAGS_ICU [join [opt-val with-icu-ldflags ""]]
   1394   define CFLAGS_ICU [join [opt-val with-icu-cflags ""]]
   1395   if {[proj-opt-was-provided with-icu-config]} {
   1396     msg-result "Checking for ICU support..."
   1397     set icuConfigBin [opt-val with-icu-config]
   1398     set tryIcuConfigBin 1; # set to 0 if we end up using pkg-config
   1399     if {$icuConfigBin in {auto pkg-config}} {
   1400       if {[pkg-config-init 0] && [pkg-config icu-io]} {
   1401         # Maintenance reminder: historical docs say to use both of
   1402         # (icu-io, icu-uc). icu-uc lacks a required lib and icu-io has
   1403         # all of them on tested OSes.
   1404         set tryIcuConfigBin 0
   1405         define LDFLAGS_ICU [get-define PKG_ICU_IO_LDFLAGS]
   1406         define-append LDFLAGS_ICU [get-define PKG_ICU_IO_LIBS]
   1407         define CFLAGS_ICU [get-define PKG_ICU_IO_CFLAGS]
   1408       } elseif {"pkg-config" eq $icuConfigBin} {
   1409         proj-fatal "pkg-config cannot find package icu-io"
   1410       } else {
   1411         proj-assert {"auto" eq $icuConfigBin}
   1412       }
   1413     }
   1414     if {$tryIcuConfigBin} {
   1415       if {"auto" eq $icuConfigBin} {
   1416         set icuConfigBin [proj-first-bin-of \
   1417                             /usr/local/bin/icu-config \
   1418                             /usr/bin/icu-config]
   1419         if {"" eq $icuConfigBin} {
   1420           proj-indented-notice -error {
   1421             --with-icu-config=auto cannot find (pkg-config icu-io) or icu-config binary.
   1422             On Ubuntu-like systems try:
   1423             --with-icu-ldflags='-licui18n -licuuc -licudata'
   1424           }
   1425         }
   1426       }
   1427       if {[file-isexec $icuConfigBin]} {
   1428         set x [exec $icuConfigBin --ldflags]
   1429         if {"" eq $x} {
   1430           proj-indented-notice -error \
   1431             [subst {
   1432               $icuConfigBin --ldflags returned no data.
   1433               On Ubuntu-like systems try:
   1434               --with-icu-ldflags='-licui18n -licuuc -licudata'
   1435             }]
   1436         }
   1437         define-append LDFLAGS_ICU $x
   1438         set x [exec $icuConfigBin --cppflags]
   1439         define-append CFLAGS_ICU $x
   1440       } else {
   1441         proj-fatal "--with-icu-config=$icuConfigBin does not refer to an executable"
   1442       }
   1443     }
   1444   }
   1445   set ldflags [define LDFLAGS_ICU [string trim [get-define LDFLAGS_ICU]]]
   1446   set cflags [define CFLAGS_ICU [string trim [get-define CFLAGS_ICU]]]
   1447   if {"" ne $ldflags} {
   1448     sqlite-add-feature-flag -shell -DSQLITE_ENABLE_ICU
   1449     msg-result "Enabling ICU support with flags: $ldflags $cflags"
   1450     if {[opt-bool icu-collations]} {
   1451       msg-result "Enabling ICU collations."
   1452       sqlite-add-feature-flag -shell -DSQLITE_ENABLE_ICU_COLLATIONS
   1453       # Recall that shell.c builds with sqlite3.c except in the case
   1454       # of --disable-static-shell, a combination we do not
   1455       # specifically attempt to account for.
   1456     }
   1457   } elseif {[opt-bool icu-collations]} {
   1458     proj-warn "ignoring --enable-icu-collations because neither --with-icu-ldflags nor --with-icu-config provided any linker flags"
   1459   } else {
   1460     msg-result "ICU support is disabled."
   1461   }
   1462 }; # sqlite-handle-icu
   1463 
   1464 
   1465 ########################################################################
   1466 # Handles the --enable-load-extension flag. Returns 1 if the support
   1467 # is enabled, else 0. If support for that feature is not found, a
   1468 # fatal error is triggered if --enable-load-extension is explicitly
   1469 # provided, else a loud warning is instead emitted. If
   1470 # --disable-load-extension is used, no check is performed.
   1471 #
   1472 # Makes the following environment changes:
   1473 #
   1474 # - defines LDFLAGS_DLOPEN to any linker flags needed for this
   1475 #   feature.  It may legally be empty on (A) some systems where
   1476 #   dlopen() is in libc and (B) certain Unix-esque Windows
   1477 #   environments which identify as Windows for SQLite's purposes so
   1478 #   use LoadLibrary().
   1479 #
   1480 # - If the feature is not available, adds
   1481 #   -DSQLITE_OMIT_LOAD_EXTENSION=1 to the feature flags list.
   1482 proc sqlite-handle-load-extension {} {
   1483   define LDFLAGS_DLOPEN ""
   1484   set found 0
   1485   set suffix ""
   1486   proj-if-opt-truthy load-extension {
   1487     switch -glob -- [get-define host] {
   1488       *-*-mingw* - *windows* {
   1489         incr found
   1490         set suffix "Using LoadLibrary()"
   1491       }
   1492       default {
   1493         set found [proj-check-function-in-lib dlopen dl]
   1494         if {$found} {
   1495           set suffix [define LDFLAGS_DLOPEN [get-define lib_dlopen]]
   1496           undefine lib_dlopen
   1497         } else {
   1498           if {[proj-opt-was-provided load-extension]} {
   1499             # Explicit --enable-load-extension: fail if not found
   1500             proj-indented-notice -error {
   1501               --enable-load-extension was provided but dlopen()
   1502               not found. Use --disable-load-extension to bypass this
   1503               check.
   1504             }
   1505           } else {
   1506             # It was implicitly enabled: warn if not found
   1507             proj-indented-notice {
   1508               WARNING: dlopen() not found, so loadable module support will
   1509               be disabled. Use --disable-load-extension to bypass this
   1510               check.
   1511             }
   1512           }
   1513         }
   1514       }
   1515     }
   1516   }
   1517   if {$found} {
   1518     msg-result "Loadable extension support enabled. $suffix"
   1519   } else {
   1520     msg-result "Disabling loadable extension support. Use --enable-load-extension to enable them."
   1521     sqlite-add-feature-flag -DSQLITE_OMIT_LOAD_EXTENSION=1
   1522   }
   1523   return $found
   1524 }
   1525 
   1526 ########################################################################
   1527 # Handles the --enable-math flag.
   1528 proc sqlite-handle-math {} {
   1529   proj-if-opt-truthy math {
   1530     if {![proj-check-function-in-lib ceil m]} {
   1531       user-error "Cannot find libm functions. Use --disable-math to bypass this."
   1532     }
   1533     define LDFLAGS_MATH [get-define lib_ceil]
   1534     undefine lib_ceil
   1535     sqlite-add-feature-flag -DSQLITE_ENABLE_MATH_FUNCTIONS -DSQLITE_ENABLE_PERCENTILE
   1536     msg-result "Enabling math SQL functions"
   1537   } {
   1538     define LDFLAGS_MATH ""
   1539     msg-result "Disabling math SQL functions"
   1540   }
   1541 }
   1542 
   1543 ########################################################################
   1544 # If this OS looks like a Mac, checks for the Mac-specific
   1545 # -current_version and -compatibility_version linker flags. Defines
   1546 # LDFLAGS_MAC_CVERSION to an empty string and returns 0 if they're not
   1547 # supported, else defines that to the linker flags and returns 1.
   1548 #
   1549 # We don't check this on non-Macs because this whole thing is a
   1550 # libtool compatibility kludge to account for a version stamp which
   1551 # libtool applied only on Mac platforms.
   1552 #
   1553 # Based on https://sqlite.org/forum/forumpost/9dfd5b8fd525a5d7.
   1554 proc sqlite-handle-mac-cversion {} {
   1555   define LDFLAGS_MAC_CVERSION ""
   1556   set rc 0
   1557   if {[proj-looks-like-mac]} {
   1558     cc-with {-link 1} {
   1559       # These version numbers are historical libtool-defined values, not
   1560       # library-defined ones
   1561       if {[cc-check-flags "-Wl,-current_version,9.6.0"]
   1562           && [cc-check-flags "-Wl,-compatibility_version,9.0.0"]} {
   1563         define LDFLAGS_MAC_CVERSION "-Wl,-compatibility_version,9.0.0 -Wl,-current_version,9.6.0"
   1564         set rc 1
   1565       } elseif {[cc-check-flags "-compatibility_version 9.0.0"]
   1566                 && [cc-check-flags "-current_version 9.6.0"]} {
   1567         define LDFLAGS_MAC_CVERSION "-compatibility_version 9.0.0 -current_version 9.6.0"
   1568         set rc 1
   1569       }
   1570     }
   1571   }
   1572   return $rc
   1573 }
   1574 
   1575 ########################################################################
   1576 # If this is a Mac platform, check for support for
   1577 # -Wl,-install_name,...  and, if it's available, define
   1578 # LDFLAGS_MAC_INSTALL_NAME to a variant of that string which is
   1579 # intended to expand at make-time, else set LDFLAGS_MAC_INSTALL_NAME
   1580 # to an empty string.
   1581 #
   1582 # https://sqlite.org/forum/forumpost/5651662b8875ec0a
   1583 proc sqlite-handle-mac-install-name {} {
   1584   define LDFLAGS_MAC_INSTALL_NAME ""; # {-Wl,-install_name,"$(install-dir.lib)/$(libsqlite3.DLL)"}
   1585   set rc 0
   1586   if {[proj-looks-like-mac]} {
   1587     cc-with {-link 1} {
   1588       if {[cc-check-flags "-Wl,-install_name,/usr/local/lib/libsqlite3.dylib"]} {
   1589         define LDFLAGS_MAC_INSTALL_NAME {-Wl,-install_name,"$(install-dir.lib)/$(libsqlite3.DLL)"}
   1590         set rc 1
   1591       }
   1592     }
   1593   }
   1594   return $rc
   1595 }
   1596 
   1597 #
   1598 # Checks specific to HP-UX.
   1599 #
   1600 proc sqlite-handle-hpux {} {
   1601   switch -glob -- [get-define host] {
   1602     *hpux* {
   1603       if {[cc-check-flags "-Ae"]} {
   1604         define-append CFLAGS -Ae
   1605       }
   1606     }
   1607   }
   1608 }
   1609 
   1610 ########################################################################
   1611 # Handles the --dll-basename configure flag. [define]'s
   1612 # SQLITE_DLL_BASENAME to the DLL's preferred base name (minus
   1613 # extension). If --dll-basename is not provided (or programmatically
   1614 # set - see [sqlite-handle-env-quirks]) then this is always
   1615 # "libsqlite3", otherwise it may use a different value based on the
   1616 # value of [get-define host].
   1617 proc sqlite-handle-dll-basename {} {
   1618   if {[proj-opt-was-provided dll-basename]} {
   1619     set dn [join [opt-val dll-basename] ""]
   1620     if {$dn in {none default}} { set dn libsqlite3 }
   1621   } else {
   1622     set dn libsqlite3
   1623   }
   1624   if {$dn in {auto ""}} {
   1625     switch -glob -- [get-define host] {
   1626       *-*-cygwin  { set dn cygsqlite3-0 }
   1627       *-*-ming*   { set dn libsqlite3-0 }
   1628       *-*-msys    { set dn msys-sqlite3-0 }
   1629       default     { set dn libsqlite3 }
   1630     }
   1631   }
   1632   define SQLITE_DLL_BASENAME $dn
   1633 }
   1634 
   1635 ########################################################################
   1636 # [define]s LDFLAGS_OUT_IMPLIB to either an empty string or to a
   1637 # -Wl,... flag for the platform-specific --out-implib flag, which is
   1638 # used for building an "import library .dll.a" file on some platforms
   1639 # (e.g. msys2, mingw). SQLITE_OUT_IMPLIB is defined to the name of the
   1640 # import lib or an empty string. Returns 1 if supported, else 0.
   1641 #
   1642 # The name of the import library is [define]d in SQLITE_OUT_IMPLIB.
   1643 #
   1644 # If the configure flag --out-implib is not used (or programmatically
   1645 # set) then this simply sets the above-listed defines to empty strings
   1646 # (but see [sqlite-handle-env-quirks]).  If that flag is used but the
   1647 # capability is not available, a fatal error is triggered.
   1648 #
   1649 # This feature is specifically opt-in because it's supported on far
   1650 # more platforms than actually need it and enabling it causes creation
   1651 # of libsqlite3.so.a files which are unnecessary in most environments.
   1652 #
   1653 # Added in response to: https://sqlite.org/forum/forumpost/0c7fc097b2
   1654 #
   1655 # Platform notes:
   1656 #
   1657 # - cygwin sqlite packages historically install no .dll.a file.
   1658 #
   1659 # - msys2 and mingw sqlite packages historically install
   1660 #   /usr/lib/libsqlite3.dll.a despite the DLL being in
   1661 #   /usr/bin.
   1662 proc sqlite-handle-out-implib {} {
   1663   define LDFLAGS_OUT_IMPLIB ""
   1664   define SQLITE_OUT_IMPLIB ""
   1665   set rc 0
   1666   if {[proj-opt-was-provided out-implib]} {
   1667     set olBaseName [join [opt-val out-implib] ""]
   1668     if {$olBaseName in {auto ""}} {
   1669       set olBaseName "libsqlite3" ;# [get-define SQLITE_DLL_BASENAME]
   1670       # Based on discussions with mingw/msys users, the import lib
   1671       # should always be called libsqlite3.dll.a even on platforms
   1672       # which rename libsqlite3.dll to something else.
   1673     }
   1674     if {$olBaseName ne "none"} {
   1675       cc-with {-link 1} {
   1676         set dll "${olBaseName}[get-define TARGET_DLLEXT]"
   1677         set flags [proj-cc-check-Wl-flag --out-implib ${dll}.a]
   1678         if {"" ne $flags} {
   1679           define LDFLAGS_OUT_IMPLIB $flags
   1680           define SQLITE_OUT_IMPLIB ${dll}.a
   1681           set rc 1
   1682         }
   1683       }
   1684       if {!$rc} {
   1685         user-error "--out-implib is not supported on this platform"
   1686       }
   1687     }
   1688   }
   1689   return $rc
   1690 }
   1691 
   1692 ########################################################################
   1693 # If the given platform identifier (defaulting to [get-define host])
   1694 # appears to be one of the Unix-on-Windows environments, returns a
   1695 # brief symbolic name for that environment, else returns an empty
   1696 # string.
   1697 #
   1698 # It does not distinguish between msys and msys2, returning msys for
   1699 # both. The build does not, as of this writing, specifically support
   1700 # msys v1. Similarly, this function returns "mingw" for both "mingw32"
   1701 # and "mingw64".
   1702 proc sqlite-env-is-unix-on-windows {{envTuple ""}} {
   1703   if {"" eq $envTuple} {
   1704     set envTuple [get-define host]
   1705   }
   1706   set name ""
   1707   switch -glob -- $envTuple {
   1708     *-*-cygwin { set name cygwin }
   1709     *-*-ming*  { set name mingw }
   1710     *-*-msys   { set name msys }
   1711   }
   1712   return $name
   1713 }
   1714 
   1715 ########################################################################
   1716 # Performs various tweaks to the build which are only relevant on
   1717 # certain platforms, e.g. Mac and "Unix on Windows" platforms (msys2,
   1718 # cygwin, ...).
   1719 #
   1720 # 1) DLL installation:
   1721 #
   1722 # [define]s SQLITE_DLL_INSTALL_RULES to a symbolic name suffix for a
   1723 # set of "make install" rules to use for installation of the DLL
   1724 # deliverable. The makefile is tasked with providing rules named
   1725 # install-dll-NAME which runs the installation for that set, as well
   1726 # as providing a rule named install-dll which resolves to
   1727 # install-dll-NAME (perhaps indirectly, depending on whether the DLL
   1728 # is (de)activated).
   1729 #
   1730 # The default value is "unix-generic".
   1731 #
   1732 # 2) --out-implib:
   1733 #
   1734 # On platforms where an "import library" is conventionally used but
   1735 # --out-implib was not explicitly used, automatically add that flag.
   1736 # This conventionally applies only to the "Unix on Windows"
   1737 # environments like msys and cygwin.
   1738 #
   1739 # 3) --dll-basename:
   1740 #
   1741 # On the same platforms addressed by --out-implib, if --dll-basename
   1742 # is not explicitly specified, --dll-basename=auto is implied.
   1743 proc sqlite-handle-env-quirks {} {
   1744   set instName unix-generic; # name of installation rules set
   1745   set autoDll 0; # true if --out-implib/--dll-basename should be implied
   1746   set host [get-define host]
   1747   switch -glob -- $host {
   1748     *apple* -
   1749     *darwin*    { set instName darwin }
   1750     default {
   1751       set x [sqlite-env-is-unix-on-windows $host]
   1752       if {"" ne $x} {
   1753         set instName $x
   1754         set autoDll 1
   1755       }
   1756     }
   1757   }
   1758   define SQLITE_DLL_INSTALL_RULES $instName
   1759   if {$autoDll} {
   1760     if {![proj-opt-was-provided out-implib]} {
   1761       # Imply --out-implib=auto
   1762       proj-indented-notice [subst -nocommands -nobackslashes {
   1763         NOTICE: auto-enabling --out-implib for environment [$host].
   1764         Use --out-implib=none to disable this special case
   1765         or --out-implib=auto to squelch this notice.
   1766       }]
   1767       proj-opt-set out-implib auto
   1768     }
   1769     if {![proj-opt-was-provided dll-basename]} {
   1770       # Imply --dll-basename=auto
   1771       proj-indented-notice [subst -nocommands -nobackslashes {
   1772         NOTICE: auto-enabling --dll-basename for environment [$host].
   1773         Use --dll-basename=default to disable this special case
   1774         or --dll-basename=auto to squelch this notice.
   1775       }]
   1776       proj-opt-set dll-basename auto
   1777     }
   1778   }
   1779   sqlite-handle-dll-basename
   1780   sqlite-handle-out-implib
   1781   sqlite-handle-mac-cversion
   1782   sqlite-handle-mac-install-name
   1783   if {[llength [info proc sqlite-custom-handle-flags]] > 0} {
   1784     # sqlite-custom-handle-flags is assumed to be imported via a
   1785     # client-specific import: autosetup/sqlite-custom.tcl.
   1786     sqlite-custom-handle-flags
   1787   }
   1788 }
   1789 
   1790 ########################################################################
   1791 # Perform some late-stage work and generate the configure-process
   1792 # output file(s).
   1793 proc sqlite-process-dot-in-files {} {
   1794   ########################################################################
   1795   # "Re-export" the autoconf-conventional --XYZdir flags into something
   1796   # which is more easily overridable from a make invocation. See the docs
   1797   # for [proj-remap-autoconf-dir-vars] for the explanation of why.
   1798   #
   1799   # We do this late in the config process, immediately before we export
   1800   # the Makefile and other generated files, so that configure tests
   1801   # which make make use of the autotools-conventional flags
   1802   # (e.g. [proj-check-rpath]) may do so before we "mangle" them here.
   1803   proj-remap-autoconf-dir-vars
   1804 
   1805   proj-dot-ins-process -validate
   1806   make-config-header sqlite_cfg.h \
   1807     -bare {SIZEOF_* HAVE_DECL_*} \
   1808     -none {HAVE_CFLAG_* LDFLAGS_* SH_* SQLITE_AUTORECONFIG
   1809       TARGET_* USE_GCOV TCL_*} \
   1810     -auto {HAVE_* PACKAGE_*} \
   1811     -none *
   1812   proj-touch sqlite_cfg.h ; # help avoid frequent unnecessary @SQLITE_AUTORECONFIG@
   1813 }
   1814 
   1815 ########################################################################
   1816 # Handle --with-wasi-sdk[=DIR]
   1817 #
   1818 # This must be run relatively early on because it may change the
   1819 # toolchain and disable a number of config options. However, in the
   1820 # canonical build this must come after [sqlite-check-common-bins].
   1821 proc sqlite-handle-wasi-sdk {} {
   1822   set wasiSdkDir [opt-val with-wasi-sdk] ; # ??? [lindex [opt-val with-wasi-sdk] end]
   1823   define HAVE_WASI_SDK 0
   1824   if {$wasiSdkDir eq ""} {
   1825     return 0
   1826   } elseif {$::sqliteConfig(is-cross-compiling)} {
   1827     proj-fatal "Cannot combine --with-wasi-sdk with cross-compilation"
   1828   }
   1829   msg-result "Checking WASI SDK directory \[$wasiSdkDir]... "
   1830   proj-affirm-files-exist -v {*}[prefix "$wasiSdkDir/bin/" {clang wasm-ld ar}]
   1831   define HAVE_WASI_SDK 1
   1832   define WASI_SDK_DIR $wasiSdkDir
   1833   # Disable numerous options which we know either can't work or are
   1834   # not useful in this build...
   1835   msg-result "Using wasi-sdk clang. Disabling CLI shell and modifying config flags:"
   1836   # Boolean (--enable-/--disable-) flags which must be switched off:
   1837   foreach opt {
   1838     dynlink-tools
   1839     editline
   1840     gcov
   1841     icu-collations
   1842     load-extension
   1843     readline
   1844     shared
   1845     tcl
   1846     threadsafe
   1847   } {
   1848     if {[proj-opt-exists $opt] && [opt-bool $opt]} {
   1849       # -^^^^ not all builds define all of these flags
   1850       msg-result "  --disable-$opt"
   1851       proj-opt-set $opt 0
   1852     }
   1853   }
   1854   # Non-boolean flags which need to be cleared:
   1855   foreach opt {
   1856     with-emsdk
   1857     with-icu-config
   1858     with-icu-ldflags
   1859     with-icu-cflags
   1860     with-linenoise
   1861     with-tcl
   1862   } {
   1863     if {[proj-opt-was-provided $opt]} {
   1864       msg-result "  removing --$opt"
   1865       proj-opt-set $opt ""
   1866     }
   1867   }
   1868   # Remember that we now have a discrepancy between
   1869   # $::sqliteConfig(is-cross-compiling) and [proj-is-cross-compiling].
   1870   set ::sqliteConfig(is-cross-compiling) 1
   1871 
   1872   #
   1873   # Changing --host and --target have no effect here except to
   1874   # possibly cause confusion. Autosetup has finished processing them
   1875   # by this point.
   1876   #
   1877   #  host_alias=wasm32-wasi
   1878   #  target=wasm32-wasi
   1879   #
   1880   # Merely changing CC, LD, and AR to the wasi-sdk's is enough to get
   1881   # sqlite3.o building in WASM format.
   1882   #
   1883   define CC "${wasiSdkDir}/bin/clang"
   1884   define LD "${wasiSdkDir}/bin/wasm-ld"
   1885   define AR "${wasiSdkDir}/bin/ar"
   1886   #define STRIP "${wasiSdkDir}/bin/strip"
   1887   return 1
   1888 }; # sqlite-handle-wasi-sdk
   1889 
   1890 ########################################################################
   1891 # TCL...
   1892 #
   1893 # sqlite-check-tcl performs most of the --with-tcl and --with-tclsh
   1894 # handling. Some related bits and pieces are performed before and
   1895 # after that function is called.
   1896 #
   1897 # Important [define]'d vars:
   1898 #
   1899 #  - HAVE_TCL indicates whether we have a tclsh suitable for building
   1900 #    the TCL SQLite extension and, by extension, the testing
   1901 #    infrastructure. This must only be 1 for environments where
   1902 #    tclConfig.sh can be found.
   1903 #
   1904 #  - TCLSH_CMD is the path to the canonical tclsh or "". It never
   1905 #    refers to jimtcl.
   1906 #
   1907 #  - TCL_CONFIG_SH is the path to tclConfig.sh or "".
   1908 #
   1909 #  - TCLLIBDIR is the dir to which libtclsqlite3 gets installed.
   1910 #
   1911 #  - BTCLSH = the path to the tcl interpreter used for in-tree code
   1912 #    generation.  It may be jimtcl or the canonical tclsh but may not
   1913 #    be empty - this tree requires TCL to generated numerous
   1914 #    components.
   1915 #
   1916 # If --tcl or --with-tcl are provided but no TCL is found, this
   1917 # function fails fatally. If they are not explicitly provided then
   1918 # failure to find TCL is not fatal but a loud warning will be emitted.
   1919 #
   1920 proc sqlite-check-tcl {} {
   1921   define TCLSH_CMD false ; # Significant is that it exits with non-0
   1922   define HAVE_TCL 0      ; # Will be enabled via --tcl or a successful search
   1923   define TCLLIBDIR ""    ; # Installation dir for TCL extension lib
   1924   define TCL_CONFIG_SH ""; # full path to tclConfig.sh
   1925 
   1926   # Clear out all vars which would harvest from tclConfig.sh so that
   1927   # the late-config validation of @VARS@ works even if --disable-tcl
   1928   # is used.
   1929   proj-tclConfig-sh-to-autosetup ""
   1930 
   1931   file delete -force ".tclenv.sh"; # ensure no stale state from previous configures.
   1932   if {![opt-bool tcl]} {
   1933     proj-indented-notice {
   1934       NOTE: TCL is disabled via --disable-tcl. This means that none
   1935       of the TCL-based components will be built, including tests
   1936       and sqlite3_analyzer.
   1937     }
   1938     return
   1939   }
   1940   # TODO: document the steps this is taking.
   1941   set srcdir $::autosetup(srcdir)
   1942   msg-result "Checking for a suitable tcl... "
   1943   proj-assert [proj-opt-truthy tcl]
   1944   set use_tcl 1
   1945   set with_tclsh [opt-val with-tclsh]
   1946   set with_tcl [opt-val with-tcl]
   1947   if {"prefix" eq $with_tcl} {
   1948     set with_tcl [get-define prefix]
   1949   }
   1950   proc-debug "use_tcl ${use_tcl}"
   1951   proc-debug "with_tclsh=${with_tclsh}"
   1952   proc-debug "with_tcl=$with_tcl"
   1953   if {"" eq $with_tclsh && "" eq $with_tcl} {
   1954     # If neither --with-tclsh nor --with-tcl are provided, try to find
   1955     # a workable tclsh.
   1956     set with_tclsh [proj-first-bin-of tclsh9.1 tclsh9.0 tclsh8.6 tclsh]
   1957     proc-debug "with_tclsh=${with_tclsh}"
   1958   }
   1959 
   1960   set doConfigLookup 1 ; # set to 0 to test the tclConfig.sh-not-found cases
   1961   if {"" ne $with_tclsh} {
   1962     # --with-tclsh was provided or found above. Validate it and use it
   1963     # to trump any value passed via --with-tcl=DIR.
   1964     if {![file-isexec $with_tclsh]} {
   1965       proj-fatal "TCL shell $with_tclsh is not executable"
   1966     } else {
   1967       define TCLSH_CMD $with_tclsh
   1968       #msg-result "Using tclsh: $with_tclsh"
   1969     }
   1970     if {$doConfigLookup &&
   1971         [catch {exec $with_tclsh $::autosetup(libdir)/find_tclconfig.tcl} result] == 0} {
   1972       set with_tcl $result
   1973     }
   1974     if {"" ne $with_tcl && [file isdir $with_tcl]} {
   1975       msg-result "$with_tclsh recommends the tclConfig.sh from $with_tcl"
   1976     } else {
   1977       proj-warn "$with_tclsh is unable to recommend a tclConfig.sh"
   1978       set use_tcl 0
   1979     }
   1980   }
   1981   set cfg ""
   1982   set tclSubdirs {tcl9.1 tcl9.0 tcl8.6 lib}
   1983   while {$use_tcl} {
   1984     if {"" ne $with_tcl} {
   1985       # Ensure that we can find tclConfig.sh under ${with_tcl}/...
   1986       if {$doConfigLookup} {
   1987         if {[file readable "${with_tcl}/tclConfig.sh"]} {
   1988           set cfg "${with_tcl}/tclConfig.sh"
   1989         } else {
   1990           foreach i $tclSubdirs {
   1991             if {[file readable "${with_tcl}/$i/tclConfig.sh"]} {
   1992               set cfg "${with_tcl}/$i/tclConfig.sh"
   1993               break
   1994             }
   1995           }
   1996         }
   1997       }
   1998       if {"" eq $cfg} {
   1999         proj-fatal "No tclConfig.sh found under ${with_tcl}"
   2000       }
   2001     } else {
   2002       # If we have not yet found a tclConfig.sh file, look in $libdir
   2003       # which is set automatically by autosetup or via the --prefix
   2004       # command-line option.  See
   2005       # https://sqlite.org/forum/forumpost/e04e693439a22457
   2006       set libdir [get-define libdir]
   2007       if {[file readable "${libdir}/tclConfig.sh"]} {
   2008         set cfg "${libdir}/tclConfig.sh"
   2009       } else {
   2010         foreach i $tclSubdirs {
   2011           if {[file readable "${libdir}/$i/tclConfig.sh"]} {
   2012             set cfg "${libdir}/$i/tclConfig.sh"
   2013             break
   2014           }
   2015         }
   2016       }
   2017       if {![file readable $cfg]} {
   2018         break
   2019       }
   2020     }
   2021     msg-result "Using tclConfig.sh: $cfg"
   2022     break
   2023   }
   2024   define TCL_CONFIG_SH $cfg
   2025   # Export a subset of tclConfig.sh to the current TCL-space.  If $cfg
   2026   # is an empty string, this emits empty-string entries for the
   2027   # various options we're interested in.
   2028   proj-tclConfig-sh-to-autosetup $cfg
   2029 
   2030   if {"" eq $with_tclsh && $cfg ne ""} {
   2031     # We have tclConfig.sh but no tclsh. Attempt to locate a tclsh
   2032     # based on info from tclConfig.sh.
   2033     set tclExecPrefix [get-define TCL_EXEC_PREFIX]
   2034     proj-assert {"" ne $tclExecPrefix}
   2035     set tryThese [list \
   2036                     $tclExecPrefix/bin/tclsh[get-define TCL_VERSION] \
   2037                     $tclExecPrefix/bin/tclsh ]
   2038     foreach trySh $tryThese {
   2039       if {[file-isexec $trySh]} {
   2040         set with_tclsh $trySh
   2041         break
   2042       }
   2043     }
   2044     if {![file-isexec $with_tclsh]} {
   2045       proj-warn "Cannot find a usable tclsh (tried: $tryThese)
   2046     }
   2047   }
   2048   define TCLSH_CMD $with_tclsh
   2049   if {$use_tcl} {
   2050     # Set up the TCLLIBDIR
   2051     #
   2052     # 2024-10-28: calculation of TCLLIBDIR is now done via the shell
   2053     # in main.mk (search it for T.tcl.env.sh) so that
   2054     # static/hand-written makefiles which import main.mk do not have
   2055     # to define that before importing main.mk. Even so, we export
   2056     # TCLLIBDIR from here, which will cause the canonical makefile to
   2057     # use this one rather than to re-calculate it at make-time.
   2058     set tcllibdir [get-env TCLLIBDIR ""]
   2059     set sq3Ver [get-define PACKAGE_VERSION]
   2060     if {"" eq $tcllibdir} {
   2061       # Attempt to extract TCLLIBDIR from TCL's $auto_path
   2062       if {"" ne $with_tclsh &&
   2063           [catch {exec echo "puts stdout \$auto_path" | "$with_tclsh"} result] == 0} {
   2064         foreach i $result {
   2065           if {[file isdir $i]} {
   2066             set tcllibdir $i/sqlite${sq3Ver}
   2067             break
   2068           }
   2069         }
   2070       } else {
   2071         proj-warn "Cannot determine TCLLIBDIR."
   2072         # The makefile will fail fatally in this case if a target is
   2073         # invoked which requires TCLLIBDIR.
   2074       }
   2075     }
   2076     #if {"" ne $tcllibdir} { msg-result "TCLLIBDIR = ${tcllibdir}"; }
   2077     define TCLLIBDIR $tcllibdir
   2078   }; # find TCLLIBDIR
   2079 
   2080   if {[file-isexec $with_tclsh]} {
   2081     msg-result "Using tclsh: $with_tclsh"
   2082     if {$cfg ne ""} {
   2083       define HAVE_TCL 1
   2084     } else {
   2085       proj-warn "Found tclsh but no tclConfig.sh."
   2086     }
   2087   }
   2088   show-notices
   2089   # If TCL is not found: if it was explicitly requested then fail
   2090   # fatally, else just emit a warning. If we can find the APIs needed
   2091   # to generate a working JimTCL then that will suffice for build-time
   2092   # TCL purposes (see: proc sqlite-determine-codegen-tcl).
   2093   if {![get-define HAVE_TCL] &&
   2094       ([proj-opt-was-provided tcl] || [proj-opt-was-provided with-tcl])} {
   2095     proj-fatal "TCL support was requested but no tclConfig.sh could be found."
   2096   }
   2097   if {"" eq $cfg} {
   2098     proj-assert {0 == [get-define HAVE_TCL]}
   2099     proj-indented-notice {
   2100       WARNING: Cannot find a usable tclConfig.sh file.  Use
   2101       --with-tcl=DIR to specify a directory where tclConfig.sh can be
   2102       found.  SQLite does not use TCL internally, but some optional
   2103       components require TCL, including tests and sqlite3_analyzer.
   2104     }
   2105   }
   2106 }; # sqlite-check-tcl
   2107 
   2108 ########################################################################
   2109 # sqlite-determine-codegen-tcl checks which TCL to use as a code
   2110 # generator.  By default, prefer jimsh simply because we have it
   2111 # in-tree (it's part of autosetup) unless --with-tclsh=X is used, in
   2112 # which case prefer X.
   2113 #
   2114 # Returns the human-readable name of the TCL it selects. Fails fatally
   2115 # if it cannot detect a TCL appropriate for code generation.
   2116 #
   2117 # Defines:
   2118 #
   2119 #   - BTCLSH = the TCL shell used for code generation. It may set this
   2120 #     to an unexpanded makefile var name.
   2121 #
   2122 #   - CFLAGS_JIMSH = any flags needed for buildng a BTCLSH-compatible
   2123 #     jimsh. The defaults may be passed on to configure as
   2124 #     CFLAGS_JIMSH=...
   2125 proc sqlite-determine-codegen-tcl {} {
   2126   msg-result "Checking for TCL to use for code generation... "
   2127   define CFLAGS_JIMSH [proj-get-env CFLAGS_JIMSH {-O1}]
   2128   set cgtcl [opt-val with-tclsh jimsh]
   2129   if {"jimsh" ne $cgtcl} {
   2130     # When --with-tclsh=X is used, use that for all TCL purposes,
   2131     # including in-tree code generation, per developer request.
   2132     define BTCLSH "\$(TCLSH_CMD)"
   2133     return $cgtcl
   2134   }
   2135   set flagsToRestore {CC CFLAGS AS_CFLAGS CPPFLAGS AS_CPPFLAGS LDFLAGS LINKFLAGS LIBS CROSS}
   2136   define-push $flagsToRestore {
   2137     # We have to swap CC to CC_FOR_BUILD for purposes of the various
   2138     # [cc-...] tests below. Recall that --with-wasi-sdk may have
   2139     # swapped out CC with one which is not appropriate for this block.
   2140     # Per consulation with autosetup's creator, doing this properly
   2141     # requires us to [define-push] the whole $flagsToRestore list
   2142     # (plus a few others which are not relevant in this tree).
   2143     #
   2144     # These will get set to their previous values at the end of this
   2145     # block.
   2146     foreach flag $flagsToRestore {define $flag ""}
   2147     define CC [get-define CC_FOR_BUILD]
   2148     # These headers are technically optional for JimTCL but necessary if
   2149     # we want to use it for code generation:
   2150     set sysh [cc-check-includes dirent.h sys/time.h]
   2151     # jimsh0.c hard-codes #define's for HAVE_DIRENT_H and
   2152     # HAVE_SYS_TIME_H on the platforms it supports, so we do not
   2153     # need to add -D... flags for those. We check for them here only
   2154     # so that we can avoid the situation that we later, at
   2155     # make-time, try to compile jimsh but it then fails due to
   2156     # missing headers (i.e. fail earlier rather than later).
   2157     if {$sysh && [cc-check-functions realpath]} {
   2158       define-append CFLAGS_JIMSH -DHAVE_REALPATH
   2159       define BTCLSH "\$(JIMSH)"
   2160       set ::sqliteConfig(use-jim-for-codegen) 1
   2161     } elseif {$sysh && [cc-check-functions _fullpath]} {
   2162       # _fullpath() is a Windows API. It's not entirely clear
   2163       # whether we need to add {-DHAVE_SYS_TIME_H -DHAVE_DIRENT_H}
   2164       # to CFLAGS_JIMSH in this case. On MinGW32 we definitely do
   2165       # not want to because it already hard-codes them. On _MSC_VER
   2166       # builds it does not.
   2167       define-append CFLAGS_JIMSH -DHAVE__FULLPATH
   2168       define BTCLSH "\$(JIMSH)"
   2169       set ::sqliteConfig(use-jim-for-codegen) 1
   2170     } elseif {[file-isexec [get-define TCLSH_CMD]]} {
   2171       set cgtcl [get-define TCLSH_CMD]
   2172       define BTCLSH "\$(TCLSH_CMD)"
   2173     } else {
   2174       # One last-ditch effort to find TCLSH_CMD: use info from
   2175       # tclConfig.sh to try to find a tclsh
   2176       if {"" eq [get-define TCLSH_CMD]} {
   2177         set tpre [get-define TCL_EXEC_PREFIX]
   2178         if {"" ne $tpre} {
   2179           set tv [get-define TCL_VERSION]
   2180           if {[file-isexec "${tpre}/bin/tclsh${tv}"]} {
   2181             define TCLSH_CMD "${tpre}/bin/tclsh${tv}"
   2182           } elseif {[file-isexec "${tpre}/bin/tclsh"]} {
   2183             define TCLSH_CMD "${tpre}/bin/tclsh"
   2184           }
   2185         }
   2186       }
   2187       set cgtcl [get-define TCLSH_CMD]
   2188       if {![file-isexec $cgtcl]} {
   2189         proj-fatal "Cannot find a tclsh to use for code generation."
   2190       }
   2191       define BTCLSH "\$(TCLSH_CMD)"
   2192     }
   2193   }; # /define-push $flagsToRestore
   2194   return $cgtcl
   2195 }; # sqlite-determine-codegen-tcl
   2196 
   2197 ########################################################################
   2198 # Runs sqlite-check-tcl and, if this is the canonical build,
   2199 # sqlite-determine-codegen-tcl.
   2200 proc sqlite-handle-tcl {} {
   2201   sqlite-check-tcl
   2202   if {"canonical" ne $::sqliteConfig(build-mode)} return
   2203   msg-result "TCL for code generation: [sqlite-determine-codegen-tcl]"
   2204 
   2205   # Determine the base name of the Tcl extension's DLL
   2206   #
   2207   if {[get-define HAVE_TCL]} {
   2208     if {[string match *-cygwin [get-define host]]} {
   2209       set libname cyg
   2210     } else {
   2211       set libname lib
   2212     }
   2213     if {[get-define TCL_MAJOR_VERSION] > 8} {
   2214       append libname tcl9
   2215     }
   2216     append libname sqlite
   2217   } else {
   2218     set libname ""
   2219   }
   2220   define TCL_EXT_DLL_BASENAME $libname
   2221   # The extension is added in the makefile
   2222 }
   2223 
   2224 ########################################################################
   2225 # Handle the --enable/disable-rpath flag.
   2226 proc sqlite-handle-rpath {} {
   2227   # autosetup/cc-shared.tcl sets the rpath flag definition in
   2228   # [get-define SH_LINKRPATH], but it does so on a per-platform basis
   2229   # rather than as a compiler check. Though we should do a proper
   2230   # compiler check (as proj-check-rpath does), we may want to consider
   2231   # adopting its approach of clearing the rpath flags for environments
   2232   # for which sqlite-env-is-unix-on-windows returns a non-empty
   2233   # string.
   2234 
   2235   # https://sqlite.org/forum/forumpost/13cac3b56516f849
   2236   if {[proj-opt-truthy rpath]} {
   2237     proj-check-rpath
   2238   } else {
   2239     msg-result "Disabling use of rpath."
   2240     define LDFLAGS_RPATH ""
   2241   }
   2242 }
   2243 
   2244 ########################################################################
   2245 # If the --dump-defines configure flag is provided then emit a list of
   2246 # all [define] values to config.defines.txt, else do nothing.
   2247 proc sqlite-dump-defines {} {
   2248   proj-if-opt-truthy dump-defines {
   2249     make-config-header $::sqliteConfig(dump-defines-txt) \
   2250       -bare {SQLITE_OS* SQLITE_DEBUG USE_*} \
   2251       -str {BIN_* CC LD AR LDFLAG* OPT_*} \
   2252       -auto {*}
   2253     # achtung: ^^^^ whichever SQLITE_OS_foo flag which is set to 0 will
   2254     # get _undefined_ here unless it's part of the -bare set.
   2255     if {"" ne $::sqliteConfig(dump-defines-json)} {
   2256       msg-result "--dump-defines is creating $::sqliteConfig(dump-defines-json)"
   2257       ########################################################################
   2258       # Dump config-defines.json...
   2259       # Demonstrate (mis?)handling of spaces in JSON-export array values:
   2260       # define-append OPT_FOO.list {"-DFOO=bar baz" -DBAR="baz barre"}
   2261       define OPT_FEATURE_FLAGS.list [get-define OPT_FEATURE_FLAGS]
   2262       define OPT_SHELL.list [get-define OPT_SHELL]
   2263       set dumpDefsOpt {
   2264         -bare {SIZEOF_* HAVE_DECL_*}
   2265         -none {HAVE_CFLAG_* LDFLAGS_* SH_* SQLITE_AUTORECONFIG TARGET_* USE_GCOV TCL_*}
   2266         -array {*.list}
   2267         -auto {OPT_* PACKAGE_* HAVE_*}
   2268       }
   2269 #      if {$::sqliteConfig(dump-defines-json-include-lowercase)} {
   2270 #        lappend dumpDefsOpt -none {lib_*} ; # remnants from proj-check-function-in-lib and friends
   2271 #        lappend dumpDefsOpt -auto {[a-z]*}
   2272 #      }
   2273       lappend dumpDefsOpt -none *
   2274       proj-dump-defs-json $::sqliteConfig(dump-defines-json) {*}$dumpDefsOpt
   2275       undefine OPT_FEATURE_FLAGS.list
   2276       undefine OPT_SHELL.list
   2277     }
   2278   }
   2279 }
   2280