#/usr/bin/tclsh # ^^^ help out editors which guess this file's content type. # # This is the main autosetup-compatible configure script for the # SQLite project. # # This script should be kept compatible with JimTCL, a copy of which # is included in this source tree as ./autosetup/jimsh0.c. The number # of incompatibilities between canonical TCL and JimTCL is very low # and alternative formulations of incompatible constructs have, so # far, been easy to find. # # JimTCL: https://jim.tcl.tk # use cc cc-db cc-shared cc-lib hwaci-common pkg-config # Are we cross-compiling? set cross_compiling 0 if {[get-define host] ne [get-define build]} { set cross_compiling 1 } elseif {1 && "nope" eq [get-env CC_FOR_BUILD "nope"] && [get-define CC] ne [get-define CC_FOR_BUILD]} { # Arguable/debatable... # # When _not_ cross-compiling and CC_FOR_BUILD is _not_ explcitely # specified, force CC_FOR_BUILD to be the same as CC, so that: # # ./configure CC=clang # # will use CC_FOR_BUILD=clang, instead of cc, for building in-tree # tools. This is based off of an email discussion and is thought to # be likely to cause less confusion than seeing 'cc' invocations # will when the user passes CC=clang. # # Sidebar: if we do this before the cc package is installed, it gets # reverted by that package. Ergo, the cc package init will tell the # user "Build C compiler...cc" shortly before we tell them: msg-result "Re-defining CC_FOR_BUILD to CC=[get-define CC]. To avoid this, explicitly pass CC_FOR_BUILD=..." define CC_FOR_BUILD [get-define CC] } # $DUMP_DEFINES_TXT is the file emitted by --dump-defines, intended # only for build debugging and not part of the public build interface. set DUMP_DEFINES_TXT ./config.defines.txt # $DUMP_DEFINES_JSON is the autosetup counterpart of the historical # "DEFS" var which was generated by the autotools in the pre-processed # autotools builds (but not in the canonical tree). This is used by at # least one high-profile client to extract build config info for use # in compiling a scripting-language binding, so its name should not be # arbitrarily changed. set DUMP_DEFINES_JSON ./config.defines.json ######################################################################## # Regarding flag compatibility with the historical autotool configure # script: # # A very long story made short, autosetup's --flag handling has # some behaviors which make it impossible to implement 100% identical # flags compared to the historical autotools build. The differences # are documented here: # # 1) --debug is used by autosetup itself, so we have to rename it to # --with-debug. We cannot use --enable-debug because that is, for # autosetup, and alias for --debug=1. # # 2) In autosetup, all flags starting with (--enable, --disable) are # forced to be booleans and receive special handling in how they're # resolved. Because of that we have to rename: # # 2.1) --enable-tempstore[=no] to --with-tempstore[=no]. # ######################################################################## # A gentle introduction to flags handling in autosetup # # Reference: https://msteveb.github.io/autosetup/developer/ # # All configure flags must be described in an 'options' call, which # must appear very early on in this script. The general syntax is: # # FLAG => {Help text} # # Where FLAG can have any of the following formats: # # boolopt => "a boolean option which defaults to disabled" # boolopt2=1 => "a boolean option which defaults to enabled" # stringopt: => "an option which takes an argument, e.g. --stringopt=value" # stringopt2:=value => "an option where the argument is optional and defaults to 'value'" # optalias booltopt3 => "a boolean with a hidden alias. --optalias is not shown in --help" # # Autosetup does no small amount of specialized handling for flags, # especially booleans. Each bool-type --FLAG implicitly gets # --enable-FLAG and --disable-FLAG forms, and explicitly adding flags # with those prefixes will force them to be boolean flags. e.g. we # define a flag "readline", which will be interpreted in one of two # ways, depending on how it's invoked and how its default is defined: # # --enable-readline ==> boolean true # --disable-readline ==> boolean false # # Trying to pass --readline or --readline=1 or --readline=0 will # result in an "unrecognized option" error, despite the the options # call listing the flag as "readline". # # The behavior described above can lead lead to some confusion when # writing help text. For example: # # options { json=1 {Disable JSON functions} } # # The reason the help text says "disable" is because a boolean option # defaulting to true is, in the --help text, rendered as: # # --disable-json Disable JSON functions # # Whereas a bool flag which defaults to false will instead render as: # # --enable-FLAG # # Non-boolean flags, in contrast, use the names specifically given to # them in the 'options' invocation. e.g. "with-tcl" is the --with-tcl # flag. Autosetup may, however, choose to automatically alter the help # text, as demonstrated here: # # options { # readline=1 => {Disable readline support} # with-readline-lib: => {Readline library} # with-readline-inc: => {Readline include paths} # } # # $ ./configure --help | grep readline # --disable-readline disable readline support # --with-readline-lib specify readline library # --with-readline-inc specify readline include paths # # Note that it prefixed and lower-case the help message. Whether # that's a feature or a bug can be debated. # # Fetching values for flags: # # booleans: use one of: # - [opt-bool FLAG] is autosetup's built-in command for this, but we # have some convenience variants: # - [hwaci-opt-truthy FLAG] # - [hwaci-opt-if-truthy FLAG {THEN} {ELSE}] # # Non-boolean (i.e. string) flags: # - [opt-val FLAG] # ######################################################################## options [subst { with-debug:=1 => {Enable debug build flags} with-tclsh:PATH => {Full pathname of tclsh to use} with-tcl:DIR => {Directory containing tclConfig.sh} tcl=1 => {Disable components which require TCL-dev} test-status => {Enable status of tests} threadsafe=1 => {Disable mutexing} with-tempstore:=no => {Use an in-ram database for temporary tables: never,no,yes,always} editline=0 => {BSD editline support} readline=1 => {Disable readline support} largefile=1 => {Disable large file support} with-readline-lib: => {Readline library} with-readline-inc: => {Readline include paths} with-linenoise:DIR => {} amalgamation=1 => {Disable the amalgamation and instead build all files separately} load-extension=1 => {Disable loading of external extensions} math=1 => {Disable math functions} json=1 => {Disable JSON functions} all => {Enable FTS4, FTS5, Geopoly, RTree, Sessions} memsys5 => {Enable MEMSYS5} memsys3 => {Enable MEMSYS3} fts3 => {Enable the FTS3 extension} fts4 => {Enable the FTS4 extension} fts5 => {Enable the FTS5 extension} update-limit => {Enable the UPDATE/DELETE LIMIT clause} geopoly => {Enable the GEOPOLY extension} rtree => {Enable the RTREE extension} session => {Enable the SESSION extension} gcov=0 => {Enable coverage testing using gcov} linemacros => {Enable #line macros in the amalgamation.} with-wasi-sdk:=/opt/wasi-sdk => {Top-most dir of the wasi-sdk for a WASI build} with-emsdk:DIR => {Top-most dir of the Emscripten SDK installation} defines-json-include-lowercase=0 => {Include lower-case defines (primarily system paths) in $DUMP_DEFINES_JSON} dump-defines=0 => {Dump autosetup defines to $DUMP_DEFINES_TXT (for build debugging)} }] ######################################################################## # Notes about certain historical flags: # # --releasemode: libtool-specific (which we don't have now) # # set srcdir $::autosetup(srcdir) set top_srcdir [get-define abs_top_srcdir] msg-result "srcdir = $srcdir" msg-result "top_srcdir = $top_srcdir" set PACKAGE_VERSION [readfile $::autosetup(srcdir)/VERSION] msg-result "VERSION = $PACKAGE_VERSION" define PACKAGE_NAME "sqlite" define PACKAGE_URL {https://sqlite.org} define PACKAGE_VERSION $PACKAGE_VERSION define PACKAGE_STRING "[get-define PACKAGE_NAME] $PACKAGE_VERSION" define PACKAGE_BUGREPORT [get-define PACKAGE_URL]/forum define-append SQLITE_AUTOREMAKE cd $::autosetup(srcdir) && $top_srcdir/configure {*}$::autosetup(argv) set outOfTreeBuild 0 if {![file exists sqlite3.pc.in]} { msg-result "This appears to be an out-of-tree build." set outOfTreeBuild 1 } cc-check-tools ld ar ######################################################################## # The build process allows for using a cross-compiler. But the default # action is to target the same platform that we are running on. The # configure script needs to discover the following properties of the # build and target systems: # # srcdir # # The is the name of the directory that contains the # "configure" shell script. All source files are # located relative to this directory. # # bindir # # The name of the directory where executables should be # written by the "install" target of the makefile. # # program_prefix # # Add this prefix to the names of all executables that run # on the target machine. Default: "" # # ENABLE_SHARED # # True if shared libraries should be generated. # # BUILD_CC # # The name of a command that is used to convert C # source files into executables that run on the build # platform. # # BUILD_CFLAGS # # Switches that the build compiler needs in order to construct # command-line programs. # # BUILD_LIBS # # Libraries that the build compiler needs in order to construct # command-line programs. # # TCL_* # # Lots of values are read in from the tclConfig.sh script, # if that script is available. This values are used for # constructing and installing the TCL extension. # # TARGET_READLINE_LIBS # # This is the library directives passed to the target linker # that cause the executable to link against the readline library. # This might be a switch like "-lreadline" or pathnames of library # file like "../../src/libreadline.a". # # TARGET_READLINE_INC # # This variables define the directory that contain header # files for the readline library. If the compiler is able # to find on its own, then this can be blank. # # OPT_FEATURE_FLAGS = -DSQLITE_OMIT/ENABLE flags. define OPT_FEATURE_FLAGS {} define OPT_SHELL {}; # CFLAGS for the sqlite3 CLI app # Adds $args, if not empty, to OPT_FEATURE_FLAGS. proc add-feature-flag {args} { if {"" ne $args} { define-append OPT_FEATURE_FLAGS {*}$args } } # add-feature-flag -DSQLITE_JUST_TESTING=3 # Adds $args, if not empty, to OPT_SHELL. proc add-shell-opt {args} { if {"" ne $args} { define-append OPT_SHELL {*}$args } } hwaci-file-extensions if {".exe" eq [get-define TARGET_EXEEXT]} { define SQLITE_OS_UNIX 0 define SQLITE_OS_WIN 1 # todo? add -DSQLITE_OS_WIN=1 to CFLAGS? } else { define SQLITE_OS_UNIX 1 define SQLITE_OS_WIN 0 # todo? add -DSQLITE_OS_UNIX=1 to CFLAGS? } ######### # Programs needed if {"" eq [hwaci-bin-define install]} { hwaci-warn "Cannot find install binary, so 'make install' will not work." # Reminder: we historically have ./install-sh in the source tree. # Can we not simply use that? # # define BIN_INSTALL "$top_srcdir/install-sh" # # Nope: it MOVES its source files over the target, which breaks the # installation in some cases, e.g. when libtclsqlite3.so is built in # response to 'make install' and libsqlite3.a is moved before # libtclsqlite3.so is linked. It's easy to hack to use cp instead # of mv (simply replace the instcmd=... bit) but that won't retain # the source timestamp and permissions unless we use cp's -p flag, # which may not be portable enough. } ######################################################################## # We differentiate between two C compilers: the one used for binaries # which are to run on the build system (BUILD_CC, a.k.a. BCC) and the # one used for compiling binaries for the target system (CC, # a.k.a. TCC). Normally they're the same, but they will differ when # cross-compiling. define BUILD_CC [get-define CC_FOR_BUILD] define BUILD_CFLAGS [get-env BUILD_CFLAGS {-g}] define ENABLE_SHARED 1 define HAVE_TCL 0 ######################################################################## # Handle --with-wasi-sdk=DIR # # This must be early because it may change the toolchain and disable # several config options. proc hwaci-check-wasi-sdk {} { set wasiSdkDir [opt-val with-wasi-sdk] ; # ??? [lindex [opt-val with-wasi-sdk] end] define HAVE_WASI_SDK 0 #puts "x wasiSdkDir=$wasiSdkDir foo=[lindex [opt-val with-wasi-sdk] end]" if {$wasiSdkDir eq ""} { return 0 } elseif {$::cross_compiling} { hwaci-fatal "Cannot combine --with-wasi-sdk with cross-compilation" } msg-result "Checking WASI SDK directory \[$wasiSdkDir]... " #puts "prefix = [prefix $wasiSdkDir/bin {clang ld}]" hwaci-affirm-files-exist -v {*}[prefix "$wasiSdkDir/bin/" {clang wasm-ld}] msg-result "Using wasi-sdk clang, disabling: tcl, CLI shell, DLL, loadable extensions, threading" define HAVE_WASI_SDK 1 define WASI_SDK_DIR $wasiSdkDir hwaci-opt-set load-extension 0; # ==> --disable-load-extension hwaci-opt-set threadsafe 0; # ==> --threadsafe=0 hwaci-opt-set tcl 0; # ==> --disable-tcl define HAVE_TCL 0 set cross_compiling 1 define ENABLE_SHARED 0 # Changing --host and --target have no effect here except to possibly # cause confusion. autoconf has finished processing them by this # point. # # host_alias=wasm32-wasi # target=wasm32-wasi # # Merely changing CC and LD to the wasi-sdk's is enough to get # sqlite3.o building in WASM format. # XXX CC="${wasiSdkDir}/bin/clang" # XXX LD="${wasiSdkDir}/bin/wasm-ld" # XXX RANLIB="${wasiSdkDir}/bin/llvm-ranlib" define CC "${wasiSdkDir}/bin/clang" define LD "${wasiSdkDir}/bin/wasm-ld" #define STRIP "${wasiSdkDir}/bin/strip" return 1 }; # hwaci-check-wasi-sdk hwaci-check-wasi-sdk # # Enable large file support (if special flags are necessary) cc-check-lfs # # Check for needed/wanted data types cc-check-types int8_t int16_t int32_t int64_t intptr_t \ uint8_t uint16_t uint32_t uint64_t uintptr_t # # Check for needed/wanted functions cc-check-functions gmtime_r isnan localtime_r localtime_s \ malloc_usable_size strchrnul usleep utime pread pread64 pwrite pwrite64 hwaci-check-function-in-lib fdatasync rt define LDFLAGS_FDATASYNC [get-define lib_fdatasync] undefine lib_fdatasync # # Check for needed/wanted headers cc-check-includes \ sys/types.h sys/stat.h dlfcn.h unistd.h \ stdlib.h malloc.h memory.h \ string.h strings.h \ stdint.h inttypes.h # These are optional for JimTCL but necessary if we want to use it for # code generation: cc-check-includes dirent.h sys/time.h if {[cc-check-includes zlib.h] && [hwaci-check-function-in-lib deflate z]} { # TODO: port over the more sophisticated zlib search from the fossil auto.def define HAVE_ZLIB 1; # "-DSQLITE_HAVE_ZLIB=1" define LDFLAGS_ZLIB -lz # Note that -DSQLITE_HAVE_ZLIB=1 is handled separately from the # other feature flags in the autotools build. Do we need to emulate # that? add-shell-opt -DSQLITE_HAVE_ZLIB=1 } else { define HAVE_ZLIB 0 define LDFLAGS_ZLIB "" } hwaci-define-if-opt-truthy amalgamation USE_AMALGAMATION \ "Use amalgamation for builds?" hwaci-define-if-opt-truthy gcov USE_GCOV "Use gcov?" hwaci-define-if-opt-truthy test-status TSTRNNR_OPTS \ "test-runner flags:" {--status} {} hwaci-define-if-opt-truthy linemacros AMALGAMATION_LINE_MACROS \ "Use #line macros in the amalgamation:" msg-checking "Debug build? " hwaci-if-opt-truthy with-debug { define SQLITE_DEBUG 1 define TARGET_DEBUG {-g -DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0 -Wall} msg-result yes } { define TARGET_DEBUG {-DNDEBUG} msg-result no } ######################################################################## # TCL... # # hwaci-check-tcl performs most of the --with-tcl and --with-tclsh # handling. Some related bits and pieces are performed before and # after that function is called. # # Important [define]'d vars: # # - HAVE_TCL indicates whether we have a tclsh suitable for building # the TCL SQLite extension and, by extension, the testing # infrastructure. This must only be 1 for environments where # tclConfig.sh can be found. # # - TCLSH_CMD is the path to the canonical tclsh or "". It never # refers to jimtcl. # # - TCL_CONFIG_SH is the path to tclConfig.sh or "". # # - TCLLIBDIR is the dir to which libtclsqlite3 gets installed. # # - TCLLIB_RPATH = the -rpath flag specific to libtclsqlite3, which # will usually differ from the rpath used by the rest of the lib. # # - BTCLSH = the path to the tcl interpreter used for in-tree code # generation. It may be jimtcl or the canonical tclsh but may not # be empty - this tree requires TCL to generated numerous # components. # define TCLSH_CMD {exit 1} proc hwaci-check-tcl {} { # TODO: document the steps this is taking. global top_srcdir puts "Checking for a suitable tcl... " set optTcl [hwaci-opt-truthy tcl] set use_tcl $optTcl set with_tclsh [opt-val with-tclsh] set with_tcl [opt-val with-tcl] #puts "hwaci-check-tcl: use_tcl ${use_tcl}" #puts "hwaci-check-tcl: with_tclsh=${with_tclsh}" #puts "hwaci-check-tcl: with_tcl=$with_tcl" if {"" eq $with_tclsh && "" eq $with_tcl} { set with_tclsh [hwaci-first-bin-of tclsh9.0 tclsh8.6 tclsh] } #puts "hwaci-check-tcl: with_tclsh=${with_tclsh}" if {"" ne $with_tclsh} { if {![file isfile $with_tclsh]} { hwaci-fatal "TCL shell $with_tclsh is not a file" } elseif {![file-isexec $with_tclsh]} { hwaci-fatal "TCL shell $with_tclsh is not executable" } else { define TCLSH_CMD $with_tclsh msg-result "Using tclsh: $with_tclsh" } if {$use_tcl} { if {[catch {exec $with_tclsh $top_srcdir/tool/find_tclconfig.tcl} result] == 0} { set with_tcl $result } if {"" ne $with_tcl && [file isdir $with_tcl]} { msg-result "$with_tclsh recommends the tclConfig.sh from $with_tcl" } else { hwaci-warn "$with_tclsh is unable to recommand a tclConfig.sh" set use_tcl 0 } } } set cfg "" set tclSubdirs {tcl9.0 tcl8.6 lib} while {1} { if {$use_tcl} { if {"" ne $with_tcl} { if {[file readable "${with_tcl}/tclConfig.sh"]} { set cfg "${with_tcl}/tclConfig.sh" } else { foreach i $tclSubdirs { if {[file readable "${with_tcl}/$i/tclConfig.sh"]} { set cfg "${with_tcl}/$i/tclConfig.sh" break } } } if {"" eq $cfg} { hwaci-fatal "No tclConfig.sh found under ${with_tcl}" } } else { # If we have not yet found a tclConfig.sh file, look in $libdir which is # set automatically by autosetup or by the --prefix command-line option. # See https://sqlite.org/forum/forumpost/e04e693439a22457 set libdir [get-define libdir] if {[file readable "${libdir}/tclConfig.sh"]} { set cfg "${libdir}/tclConfig.sh" } else { foreach i $tclSubdirs { if {[file readable "${libdir}/$i/tclConfig.sh"]} { set cfg "${libdir}/$i/tclConfig.sh" break } } } if {![file readable $cfg]} { hwaci-warn { Cannot find a usable tclConfig.sh file. Use --with-tcl=DIR to specify a directory where tclConfig.sh can be found. SQLite does not use TCL internally, but TCL is required to build SQLite from canonical sources and TCL is required for testing. } break } } msg-result "Using tclConfig.sh: $cfg" } elseif {!$optTcl} { hwaci-warn "Unable to run tests because of --disable-tcl" } else { hwaci-warn "Unable to run tests because no tclConfig.sh file could be located" } break } define TCL_CONFIG_SH $cfg # The historical configure.ac sources tclConfig.sh so that it can # use the several TCL_... env vars. We obviously cannot do that from # TCL, so we apply a level of indirection which sources that script # then emits the pieces we're interested in as TCL code. If the # config is not available, this emits empty-string entries for the # various options we're interested in. eval [exec "${top_srcdir}/tool/tclConfigShToTcl.sh" "[get-define TCL_CONFIG_SH]"] #puts "hwaci-check-tcl: with_tclsh=$with_tclsh" #puts "hwaci-check-tcl: with_tcl=$with_tcl" #puts "hwaci-check-tcl: cfg=$cfg" #puts "hwaci-check-tcl: use_tcl ${use_tcl}" if {"" eq $with_tclsh} { set with_tclsh [get-define TCL_EXEC_PREFIX]/bin/tclsh[get-define TCL_VERSION] if {![file-isexec $with_tclsh]} { set with_tclsh2 [get-define TCL_EXEC_PREFIX]/bin/tclsh if {![file-isexec $with_tclsh2]} { hwaci-warn "Cannot find a usable tclsh (tried: $with_tclsh $with_tclsh2)" } else { set with_tclsh $with_tclsh2 } } } define TCLSH_CMD $with_tclsh if {$use_tcl} { # Set up the TCLLIBDIR and TCLLIB_RPATH set tcllibdir [get-env TCLLIBDIR ""] if {"" eq $tcllibdir} { if {[catch {exec echo "puts stdout \$auto_path" | "$with_tclsh"} result] == 0} { foreach i $result { if {[file isdir $i]} { set tcllibdir $i break } } } else { hwaci-warn "Cannot determine TCLLIBDIR" } } set tclrpath "" if {"" ne $tcllibdir} { set tcllibdir "${tcllibdir}/sqlite3" set rp [get-define SH_LINKRPATH] set tclrpath [string map [list "%s" $tcllibdir] $rp] # Reminder: tclConfig.sh has TCL_LD_SEARCH_FLAGS to set the # rpath but (A) it includes an unexpand var ref to # ${LIB_RUNTIME_DIR}, which must be set in the makefile and (B) # that flag is inherently compiler-dependent so it's not as # portable as tclConfig.sh assumes. We'll instead use the rpath # flag which autosetup determines for the current compiler. } define TCLLIBDIR $tcllibdir define TCLLIB_RPATH $tclrpath #hwaci-fatal "TCLLIB_RPATH = [get-define TCLLIB_RPATH]" } else { define TCLLIBDIR "" define TCLLIB_RPATH "" } if {[file exists $with_tclsh]} { msg-result "Using tclsh: $with_tclsh" define HAVE_TCL 1 } else { hwaci-warn "Cannot find a usable tclsh, so cannot run tests." } }; # hwaci-check-tcl hwaci-check-tcl ######################################################################## # Check which TCL to use as a code generator. Prefer jimsh simply # because we have it in-tree (it's part of autosetup). # # Building jimsh0.c with -DJIM_COMPAT changes certain behavior to be # compatible with canonical TCL. Specifically: jim's [expr] only # accepts one arg unless JIM_COMPAT is defined. As of 2024-10-23, # jimsh0.c defines JIM_COMPAT automatically (prior to that it intended # to but a typo of JIM_TCL_COMPAT made it a no-op). define CFLAGS_JIMSH {} msg-result "Which TCL to use for code generation... " set cgtcl [opt-val with-tclsh jimsh] if {"jimsh" ne $cgtcl} { # When --with-tclsh=X is used, use that for all TCL purposes, # including in-tree code generation, per developer request. define BTCLSH "\$(TCLSH_CMD)" } else { if {[cc-check-functions realpath]} { define-append CFLAGS_JIMSH -DHAVE_REALPATH define BTCLSH "\$(JIMSH)" } elseif {[cc-check-functions _fullpath]} { # _fullpath() is a Windows API define-append CFLAGS_JIMSH -DHAVE__FULLPATH define BTCLSH "\$(JIMSH)" } elseif {[file exists [get-define TCLSH_CMD]]} { set cgtcl [get-define TCLSH_CMD] define BTCLSH "\$(TCLSH_CMD)" } else { # One last-ditch effort to find TCLSH_CMD: use info from # tclConfig.sh to try to find a tclsh if {"" eq [get-define TCLSH_CMD]} { set tpre [get-define TCL_EXEC_PREFIX] if {"" ne $tpre} { set tv [get-define TCL_VERSION] if {[file-isexec "${tpre}/bin/tclsh${tv}"]} { define TCLSH_CMD "${tpre}/bin/tclsh${tv}" } elseif {[file-isexec "${tpre}/bin/tclsh"]} { define TCLSH_CMD "${tpre}/bin/tclsh" } unset tv } unset tpre } set cgtcl [get-define TCLSH_CMD] if {![file exists $cgtcl]} { hwaci-fatal "Cannot find a tclsh to use for code generation." } define BTCLSH "\$(TCLSH_CMD)" } } msg-result "TCL for code generation: $cgtcl" unset cgtcl #define CFLAGS_JIMSH {-DJUST_TESTING} # /TCL ######################################################################## ######################################################################## # Thread safety? msg-checking "Support threadsafe operation? " hwaci-if-opt-truthy threadsafe { msg-result yes add-feature-flag -DSQLITE_THREADSAFE=1 if {![hwaci-check-function-in-lib pthread_create pthread] || ![hwaci-check-function-in-lib pthread_mutexattr_init pthread]} { user-error "Missing required pthread bits" } define LDFLAGS_PTHREAD [get-define lib_pthread_create] undefine lib_pthread_create } { msg-result no add-feature-flag -DSQLITE_THREADSAFE=0 define LDFLAGS_PTHREAD "" } ######################################################################## # Do we want temporary databases in memory? # if {1} { set ts [opt-val with-tempstore no] set tsn 1 msg-checking "Use an in-ram database for temporary tables? " switch -- $ts { never { set tsn 0 } no { set tsn 1 } yes { set tsn 2 } always { set tsn 3 } default { user-error "Invalid with-tempstore value \[$ts]. Use one of: never, no, yes, always" } } msg-result $ts define TEMP_STORE $tsn unset ts tsn } if {1} { ########## # Figure out what C libraries are required to compile programs # that use "readline()" library. add-shell-opt -DHAVE_READLINE=[hwaci-check-readline] } else { # Older impl solely for reference while porting... # # XXX TARGET_READLINE_LIBS="" # XXX TARGET_READLINE_INC="" # XXX TARGET_HAVE_READLINE=0 # XXX TARGET_HAVE_EDITLINE=0 if {[opt-bool editline]} { set with_editline $enableval } else { set with_editline auto } if {![opt-bool readline]} { set with_readline $enableval } else { set with_readline auto } # XXX if test x"$with_editline" != xno; then # XXX sLIBS=$LIBS # XXX LIBS="" # XXX TARGET_HAVE_EDITLINE=1 if {[hwaci-check-function-in-lib readline edit]} { set with_readline no } else { # XXX TARGET_HAVE_EDITLINE=0 } # XXX TARGET_READLINE_LIBS=$LIBS # XXX LIBS=$sLIBS # XXX fi # XXX if test x"$with_readline" != xno; then set found "yes" if {[opt-val with-readline-lib] ne {}} { set withval [lindex [opt-val with-readline-lib] end] set with_readline_lib $withval } else { set with_readline_lib "auto" } # XXX if test "x$with_readline_lib" = xauto; then # XXX save_LIBS="$LIBS" # XXX LIBS="" if {[hwaci-check-function-in-lib tgetent readline ncurses curses termcap]} { # XXX term_LIBS="$LIBS" } else { # XXX term_LIBS="" } if {[hwaci-check-function-in-lib readline readline]} { # XXX TARGET_READLINE_LIBS="-lreadline" } else { set found "no" } # XXX TARGET_READLINE_LIBS="$TARGET_READLINE_LIBS $term_LIBS" # XXX LIBS="$save_LIBS" # XXX else # XXX TARGET_READLINE_LIBS="$with_readline_lib" # XXX fi if {[opt-val with-readline-inc] ne {}} { set withval [lindex [opt-val with-readline-inc] end] set with_readline_inc $withval } else { set with_readline_inc "auto" } # XXX if test "x$with_readline_inc" = xauto; then if {[cc-check-includes readline.h]} { set found "yes" } else { set found "no" # XXX if test "$cross_compiling" != yes; then # XXX for dir in /usr /usr/local /usr/local/readline /usr/contrib /mingw; do # XXX for subdir in include include/readline; do # XXX AC_CHECK_FILE $dir/$subdir/readline.h found=yes # XXX if test "$found" = "yes"; then # XXX TARGET_READLINE_INC="-I$dir/$subdir" # XXX break # XXX fi # XXX done # XXX test "$found" = "yes" && break # XXX done # XXX fi } # XXX else # XXX TARGET_READLINE_INC="$with_readline_inc" # XXX fi # XXX if test x"$found" = xno; then # XXX TARGET_READLINE_LIBS="" # XXX TARGET_READLINE_INC="" # XXX TARGET_HAVE_READLINE=0 # XXX else # XXX TARGET_HAVE_READLINE=1 # XXX fi # XXX fi if {[opt-val with-linenoise] ne {}} { set withval [lindex [opt-val with-linenoise] end] set with_linenoise $withval } else { set with_linenoise "no" } # XXX if test "x$with_linenoise" != "xno"; then # XXX TARGET_HAVE_READLINE=0 # XXX TARGET_HAVE_EDITLINE=0 # XXX TARGET_HAVE_LINENOISE=1 # XXX TARGET_READLINE_INC="-I${with_linenoise}" # XXX TARGET_READLINE_LIBS="${with_linenoise}/linenoise.c" # XXX echo "using linenoise source code at ${with_linenoise}" # XXX else # XXX TARGET_HAVE_LINENOISE=0 # XXX echo "not using linenoise" # XXX fi # XXX AC_SUBST TARGET_READLINE_LIBS # XXX AC_SUBST TARGET_READLINE_INC # XXX AC_SUBST TARGET_HAVE_READLINE # XXX AC_SUBST TARGET_HAVE_EDITLINE # XXX AC_SUBST TARGET_HAVE_LINENOISE } hwaci-if-opt-truthy load-extension { if {[hwaci-check-function-in-lib dlopen dl]} { define LDFLAGS_DLOPEN [get-define lib_dlopen] undefine lib_dlopen } else { user-error "dlopen() not found. Use --disable-load-extension to bypass this check." } } { define LDFLAGS_DLOPEN "" add-feature-flag {-DSQLITE_OMIT_LOAD_EXTENSION=1} msg-result "Disabling loadable extensions." } hwaci-if-opt-truthy math { if {![hwaci-check-function-in-lib ceil m]} { user-error "Cannot find libm functions. Use --disable-math to bypass this." } define LDFLAGS_MATH [get-define lib_ceil] undefine lib_ceil add-feature-flag {-DSQLITE_ENABLE_MATH_FUNCTIONS} msg-result "Enabling math SQL functions [get-define LDFLAGS_MATH]" } { define LDFLAGS_MATH "" msg-result "Disabling math SQL functions" } define cross_compiling ${cross_compiling} ######################################################################## # Emscripten SDK for building the web-based wasm components. # set emccsh $srcdir/tool/emcc.sh if {![get-define HAVE_WASI_SDK] && [hwaci-check-emsdk]} { define EMCC_WRAPPER $emccsh hwaci-make-from-dot-in $emccsh catch {exec chmod u+x $emccsh} } else { define EMCC_WRAPPER "" file delete -force $emccsh } unset emccsh ######################################################################## # Check for log(3) in libm and die with an error if it is not # found. $why should be the feature name which requires that function # (it's used only in error messages). defines LDFLAGS_MATH to the # required linker flags (which may be empty even if the math APIs are # found, depending on the OS). proc affirm-have-math {why} { if {![hwaci-check-function-in-lib log m]} { user-error "Missing math APIs for $why" } define LDFLAGS_MATH [get-define lib_log ""] undefine lib_log } ######################################################################## # Handle various SQLITE_ENABLE_... feature flags. foreach {boolFlag featureFlag ifSetEvalThis} { all {} { hwaci-opt-set fts4 hwaci-opt-set fts5 hwaci-opt-set geopoly hwaci-opt-set rtree hwaci-opt-set session } fts4 -DSQLITE_ENABLE_FTS4 {affirm-have-math fts4} fts5 -DSQLITE_ENABLE_FTS5 {affirm-have-math fts5} geopoly -DSQLITE_ENABLE_GEOPOLY {hwaci-opt-set rtree} rtree -DSQLITE_ENABLE_RTREE {} session {-DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK} {} update-limit -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT {} memsys3 {} { if {[opt-bool memsys5]} { msg-result "NOT enabling memsys3 because memsys5 is enabled." } else { add-feature-flag -DSQLITE_ENABLE_MEMSYS3 } } memsys5 -DSQLITE_ENABLE_MEMSYS5 {} } { hwaci-if-opt-truthy $boolFlag { add-feature-flag $featureFlag eval $ifSetEvalThis if {"all" ne $boolFlag} { msg-result "Enabling $boolFlag" } } { msg-result "Not enabling $boolFlag" } } ######################################################################## # Invert the above loop's logic for some explicit SQLITE_OMIT_... # cases. If config option $boolFlag is set, [add-feature-flag # $featureFlag], where $featureFlag is intended to be # -DSQLITE_OMIT_... foreach {boolFlag featureFlag} { json -DSQLITE_OMIT_JSON } { if {[hwaci-opt-truthy $boolFlag]} { msg-result "Enabling $boolFlag" } else { add-feature-flag $featureFlag msg-result "Disabling $boolFlag" } } ######################################################################## # Maybe extend JimTCL a bit. As of this writing (2024-09-27) it only # needs (-DHAVE_REALPATH or -DHAVE__FULLPATH) and -DHAVE_DIRENT_H to # be compatible with our code generators. It can, however, be slightly # extended via easy-to-detect features, should we need them. if {0 && "" ne [get-define CFLAGS_JIMSH]} { foreach jimFunc {opendir fsync isascii} { if {[cc-check-functions $jimFunc]} { define-append CFLAGS_JIMSH -DHAVE_[string toupper $jimFunc] } } #These are hard-coded into jimsh0.c, so we must not -D them: #foreach jimDef {HAVE_UNISTD_H HAVE_DIRENT_H} { # if {[is-defined $jimDef]} { # define-append CFLAGS_JIMSH -D$jimDef # } #} define-append CFLAGS_JIMSH -DHAVE_LONG_LONG; # SQLite relies on long long, so we know it's available }; # JimTCL ######################################################################## # Determine proper rpath-handling flags hwaci-check-rpath ######################################################################## # Generate the output files. # hwaci-make-from-dot-in -touch Makefile sqlite3.pc if {0} { # Requires a hand-written sqlite_cfg.h.in... hwaci-make-from-dot-in sqlite_cfg.h # vs... } else { # Requires no input template... make-config-header sqlite_cfg.h \ -bare {SIZEOF_* HAVE_DECL_*} \ -none {HAVE_CFLAG_* LDFLAGS_* SH_* SQLITE_AUTOREMAKE TARGET_* USE_GCOV TCL_*} \ -auto {HAVE_* PACKAGE_*} \ -none * hwaci-touch sqlite_cfg.h ; # help avoid frequent unnecessary @SQLITE_AUTOREMAKE@ } #TODO hwaci-make-from-dot-in ext/wasm/GNUmakefile set oFF [get-define OPT_FEATURE_FLAGS] if {"" ne $oFF} { define OPT_FEATURE_FLAGS [lsort -unique $oFF] msg-result "Library feature flags: [get-define OPT_FEATURE_FLAGS]" } set oFF [get-define OPT_SHELL] if {"" ne $oFF} { define OPT_SHELL [lsort -unique $oFF] msg-result "Shell options: [get-define OPT_SHELL]" } unset oFF ######################################################################## # Dump config-defines.json... # Demonstrate (mis?)handling of spaces in JSON-export array values: # define-append OPT_FOO.list {"-DFOO=bar baz" -DBAR="baz barre"} define OPT_FEATURE_FLAGS.list [get-define OPT_FEATURE_FLAGS] define OPT_SHELL.list [get-define OPT_SHELL] set dumpDefsOpt { -bare {SIZEOF_* HAVE_DECL_*} -none {HAVE_CFLAG_* LDFLAGS_* SH_* SQLITE_AUTOREMAKE TARGET_* USE_GCOV TCL_*} -array {*.list} -auto {OPT_* PACKAGE_* HAVE_*} } if {[opt-bool defines-json-include-lowercase]} { lappend dumpDefsOpt -none {lib_*} ; # remnants from hwaci-check-function-in-lib and friends lappend dumpDefsOpt -auto {[a-z]*} } lappend dumpDefsOpt -none * hwaci-dump-defs-json $DUMP_DEFINES_JSON {*}$dumpDefsOpt undefine OPT_FEATURE_FLAGS.list undefine OPT_SHELL.list ######################################################################## # Some build-dev/debug-only output hwaci-if-opt-truthy dump-defines { global DUMP_DEFINES_TXT msg-result "--dump-defines is creating $DUMP_DEFINES_TXT" make-config-header $DUMP_DEFINES_TXT \ -bare {SQLITE_OS* SQLITE_DEBUG USE_*} \ -str {BIN_* CC LD AR LDFLAG* OPT_*} \ -auto {*} # achtung: ^^^^ whichever SQLITE_OS_foo flag which is set to 0 will # get _undefined_ here unless it's part of the -bare set. if {0} { foreach x [all-defines] { puts "\t$x" } } } msg-result "Done! Now run make."