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