xref: /freebsd/contrib/sqlite3/autosetup/sqlite-config.tcl (revision 675382f12b67e8b7b2f35bd1f8dfd96b8d8e4aae)
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
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
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 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.
97proc 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].
466proc 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.
513proc 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.
546proc 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.
555proc proc-debug {msg} {
556  msg-debug "\[[proj-scope 1]\]: $msg"
557}
558
559define 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.
565define 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.
585proc 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.
600proc 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).
612proc 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].
629proc 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.
644proc 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.
692proc 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.
738proc 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.
761proc 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.
851proc 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.
875proc 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
891proc 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.
933proc 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.
965proc 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#
1006proc 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.
1052proc 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.
1125proc 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).
1360proc 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.
1392proc 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.
1482proc 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.
1528proc 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.
1554proc 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
1583proc 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#
1600proc 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].
1617proc 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.
1662proc 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".
1702proc 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.
1743proc 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).
1793proc 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].
1821proc 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#
1920proc 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=...
2125proc 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.
2200proc 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.
2226proc 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.
2247proc 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