1# Teaish configure script for the SQLite Tcl extension 2 3# 4# State for disparate config-time pieces. 5# 6array set sqlite__Config [proj-strip-hash-comments { 7 # 8 # The list of feature --flags which the --all flag implies. This 9 # requires special handling in a few places. 10 # 11 all-flag-enables {fts3 fts4 fts5 rtree geopoly} 12 13 # >0 if building in the canonical tree. -1=undetermined 14 is-canonical -1 15}] 16 17# 18# Set up the package info for teaish... 19# 20apply {{dir} { 21 # Figure out the version number... 22 set version "" 23 if {[file exists $dir/../VERSION]} { 24 # The canonical SQLite TEA(ish) build 25 set version [proj-file-content -trim $dir/../VERSION] 26 set ::sqlite__Config(is-canonical) 1 27 set distname sqlite-tcl 28 } elseif {[file exists $dir/generic/tclsqlite3.c]} { 29 # The copy from the teaish tree, used as a dev/test bed before 30 # updating SQLite's tree. 31 set ::sqlite__Config(is-canonical) 0 32 set fd [open $dir/generic/tclsqlite3.c rb] 33 while {[gets $fd line] >=0} { 34 if {[regexp {^#define[ ]+SQLITE_VERSION[ ]+"(3.+)"} \ 35 $line - version]} { 36 set distname sqlite-teaish 37 break 38 } 39 } 40 close $fd 41 } 42 43 if {"" eq $version} { 44 proj-fatal "Cannot determine the SQLite version number" 45 } 46 47 proj-assert {$::sqlite__Config(is-canonical) > -1} 48 proj-assert {[string match 3.*.* $version]} \ 49 "Unexpected SQLite version: $version" 50 51 set pragmas {} 52 if {$::sqlite__Config(is-canonical)} { 53 # Disable "make dist" in the canonical tree. That tree is 54 # generated from several pieces and creating/testing working 55 # "dist" rules for that sub-build currently feels unnecessary. The 56 # copy in the teaish tree, though, should be able to "make dist". 57 lappend pragmas no-dist 58 } else { 59 lappend pragmas full-dist 60 } 61 62 teaish-pkginfo-set -vars { 63 -name sqlite 64 -name.pkg sqlite3 65 -version $version 66 -name.dist $distname 67 -vsatisfies 8.6- 68 -libDir sqlite$version 69 -pragmas $pragmas 70 } 71}} [teaish-get -dir] 72 73# 74# Must return either an empty string or a list in the form accepted by 75# autosetup's [options] function. 76# 77proc teaish-options {} { 78 # These flags and defaults mostly derive from the historical TEA 79 # build. Some, like ICU, are taken from the canonical SQLite tree. 80 return [subst -nocommands -nobackslashes { 81 with-system-sqlite=0 82 => {Use the system-level SQLite instead of the copy in this tree. 83 Also requires use of --override-sqlite-version so that the build 84 knows what version number to associate with the system-level SQLite.} 85 override-sqlite-version:VERSION 86 => {For use with --with-system-sqlite to set the version number.} 87 threadsafe=1 => {Disable mutexing} 88 with-tempstore:=no => {Use an in-RAM database for temporary tables: never,no,yes,always} 89 load-extension=0 => {Enable loading of external extensions} 90 math=1 => {Disable math functions} 91 json=1 => {Disable JSON functions} 92 fts3 => {Enable the FTS3 extension} 93 fts4 => {Enable the FTS4 extension} 94 fts5 => {Enable the FTS5 extension} 95 update-limit => {Enable the UPDATE/DELETE LIMIT clause} 96 geopoly => {Enable the GEOPOLY extension} 97 rtree => {Enable the RTREE extension} 98 session => {Enable the SESSION extension} 99 all=1 => {Disable $::sqlite__Config(all-flag-enables)} 100 with-icu-ldflags:LDFLAGS 101 => {Enable SQLITE_ENABLE_ICU and add the given linker flags for the 102 ICU libraries. e.g. on Ubuntu systems, try '-licui18n -licuuc -licudata'.} 103 with-icu-cflags:CFLAGS 104 => {Apply extra CFLAGS/CPPFLAGS necessary for building with ICU. 105 e.g. -I/usr/local/include} 106 with-icu-config:=auto 107 => {Enable SQLITE_ENABLE_ICU. Value must be one of: auto, pkg-config, 108 /path/to/icu-config} 109 icu-collations=0 110 => {Enable SQLITE_ENABLE_ICU_COLLATIONS. Requires --with-icu-ldflags=... 111 or --with-icu-config} 112 }] 113} 114 115# 116# Gets called by tea-configure-core. Must perform any configuration 117# work needed for this extension. 118# 119proc teaish-configure {} { 120 use teaish/feature 121 122 teaish-src-add -dist -dir generic/tclsqlite3.c 123 124 if {[proj-opt-was-provided override-sqlite-version]} { 125 teaish-pkginfo-set -version [opt-val override-sqlite-version] 126 proj-warn "overriding sqlite version number:" [teaish-pkginfo-get -version] 127 } elseif {[proj-opt-was-provided with-system-sqlite] 128 && [opt-val with-system-sqlite] ne "0"} { 129 proj-fatal "when using --with-system-sqlite also use" \ 130 "--override-sqlite-version to specify a library version number." 131 } 132 133 define CFLAGS [proj-get-env CFLAGS {-O2}] 134 sqlite-munge-cflags 135 136 # 137 # Add feature flags from legacy configure.ac which are not covered by 138 # --flags. 139 # 140 sqlite-add-feature-flag { 141 -DSQLITE_3_SUFFIX_ONLY=1 142 -DSQLITE_ENABLE_DESERIALIZE=1 143 -DSQLITE_ENABLE_DBPAGE_VTAB=1 144 -DSQLITE_ENABLE_BYTECODE_VTAB=1 145 -DSQLITE_ENABLE_DBSTAT_VTAB=1 146 } 147 148 if {[opt-bool with-system-sqlite]} { 149 msg-result "Using system-level sqlite3." 150 teaish-cflags-add -DUSE_SYSTEM_SQLITE 151 teaish-ldflags-add -lsqlite3 152 } elseif {$::sqlite__Config(is-canonical)} { 153 teaish-cflags-add -I[teaish-get -dir]/.. 154 } 155 156 teaish-check-librt 157 teaish-check-libz 158 sqlite-handle-threadsafe 159 sqlite-handle-tempstore 160 sqlite-handle-load-extension 161 sqlite-handle-math 162 sqlite-handle-icu 163 164 sqlite-handle-common-feature-flags; # must be late in the process 165}; # teaish-configure 166 167define OPT_FEATURE_FLAGS {} ; # -DSQLITE_OMIT/ENABLE flags. 168# 169# Adds $args, if not empty, to OPT_FEATURE_FLAGS. This is intended only for holding 170# -DSQLITE_ENABLE/OMIT/... flags, but that is not enforced here. 171proc sqlite-add-feature-flag {args} { 172 if {"" ne $args} { 173 define-append OPT_FEATURE_FLAGS {*}$args 174 } 175} 176 177# 178# Check for log(3) in libm and die with an error if it is not 179# found. $featureName should be the feature name which requires that 180# function (it's used only in error messages). defines LDFLAGS_MATH to 181# the required linker flags (which may be empty even if the math APIs 182# are found, depending on the OS). 183proc sqlite-affirm-have-math {featureName} { 184 if {"" eq [get-define LDFLAGS_MATH ""]} { 185 if {![msg-quiet proj-check-function-in-lib log m]} { 186 user-error "Missing math APIs for $featureName" 187 } 188 set lfl [get-define lib_log ""] 189 undefine lib_log 190 if {"" ne $lfl} { 191 user-notice "Forcing requirement of $lfl for $featureName" 192 } 193 define LDFLAGS_MATH $lfl 194 teaish-ldflags-prepend $lfl 195 } 196} 197 198# 199# Handle various SQLITE_ENABLE/OMIT_... feature flags. 200proc sqlite-handle-common-feature-flags {} { 201 msg-result "Feature flags..." 202 if {![opt-bool all]} { 203 # Special handling for --disable-all 204 foreach flag $::sqlite__Config(all-flag-enables) { 205 if {![proj-opt-was-provided $flag]} { 206 proj-opt-set $flag 0 207 } 208 } 209 } 210 foreach {boolFlag featureFlag ifSetEvalThis} [proj-strip-hash-comments { 211 all {} { 212 # The 'all' option must be first in this list. This impl makes 213 # an effort to only apply flags which the user did not already 214 # apply, so that combinations like (--all --disable-geopoly) 215 # will indeed disable geopoly. There are corner cases where 216 # flags which depend on each other will behave in non-intuitive 217 # ways: 218 # 219 # --all --disable-rtree 220 # 221 # Will NOT disable geopoly, though geopoly depends on rtree. 222 # The --geopoly flag, though, will automatically re-enable 223 # --rtree, so --disable-rtree won't actually disable anything in 224 # that case. 225 foreach k $::sqlite__Config(all-flag-enables) { 226 if {![proj-opt-was-provided $k]} { 227 proj-opt-set $k 1 228 } 229 } 230 } 231 fts3 -DSQLITE_ENABLE_FTS3 {sqlite-affirm-have-math fts3} 232 fts4 -DSQLITE_ENABLE_FTS4 {sqlite-affirm-have-math fts4} 233 fts5 -DSQLITE_ENABLE_FTS5 {sqlite-affirm-have-math fts5} 234 geopoly -DSQLITE_ENABLE_GEOPOLY {proj-opt-set rtree} 235 rtree -DSQLITE_ENABLE_RTREE {} 236 session {-DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK} {} 237 update-limit -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT {} 238 scanstatus -DSQLITE_ENABLE_STMT_SCANSTATUS {} 239 }] { 240 if {$boolFlag ni $::autosetup(options)} { 241 # Skip flags which are in the canonical build but not 242 # the autoconf bundle. 243 continue 244 } 245 proj-if-opt-truthy $boolFlag { 246 sqlite-add-feature-flag $featureFlag 247 if {0 != [eval $ifSetEvalThis] && "all" ne $boolFlag} { 248 msg-result " + $boolFlag" 249 } 250 } { 251 if {"all" ne $boolFlag} { 252 msg-result " - $boolFlag" 253 } 254 } 255 } 256 # 257 # Invert the above loop's logic for some SQLITE_OMIT_... cases. If 258 # config option $boolFlag is false, [sqlite-add-feature-flag 259 # $featureFlag], where $featureFlag is intended to be 260 # -DSQLITE_OMIT_... 261 foreach {boolFlag featureFlag} { 262 json -DSQLITE_OMIT_JSON 263 } { 264 if {[proj-opt-truthy $boolFlag]} { 265 msg-result " + $boolFlag" 266 } else { 267 sqlite-add-feature-flag $featureFlag 268 msg-result " - $boolFlag" 269 } 270 } 271 272 ## 273 # Remove duplicates from the final feature flag sets and show them 274 # to the user. 275 set oFF [get-define OPT_FEATURE_FLAGS] 276 if {"" ne $oFF} { 277 define OPT_FEATURE_FLAGS [lsort -unique $oFF] 278 msg-result "Library feature flags: [get-define OPT_FEATURE_FLAGS]" 279 } 280 if {[lsearch [get-define TARGET_DEBUG ""] -DSQLITE_DEBUG=1] > -1} { 281 msg-result "Note: this is a debug build, so performance will suffer." 282 } 283 teaish-cflags-add -define OPT_FEATURE_FLAGS 284}; # sqlite-handle-common-feature-flags 285 286# 287# If --enable-threadsafe is set, this adds -DSQLITE_THREADSAFE=1 to 288# OPT_FEATURE_FLAGS and sets LDFLAGS_PTHREAD to the linker flags 289# needed for linking pthread (possibly an empty string). If 290# --enable-threadsafe is not set, adds -DSQLITE_THREADSAFE=0 to 291# OPT_FEATURE_FLAGS and sets LDFLAGS_PTHREAD to an empty string. 292# 293# It prepends the flags to the global LDFLAGS. 294proc sqlite-handle-threadsafe {} { 295 msg-checking "Support threadsafe operation? " 296 define LDFLAGS_PTHREAD "" 297 set enable 0 298 if {[proj-opt-was-provided threadsafe]} { 299 proj-if-opt-truthy threadsafe { 300 if {[proj-check-function-in-lib pthread_create pthread] 301 && [proj-check-function-in-lib pthread_mutexattr_init pthread]} { 302 incr enable 303 set ldf [get-define lib_pthread_create] 304 define LDFLAGS_PTHREAD $ldf 305 teaish-ldflags-prepend $ldf 306 undefine lib_pthread_create 307 undefine lib_pthread_mutexattr_init 308 } else { 309 user-error "Missing required pthread libraries. Use --disable-threadsafe to disable this check." 310 } 311 # Recall that LDFLAGS_PTHREAD might be empty even if pthreads if 312 # found because it's in -lc on some platforms. 313 } { 314 msg-result "Disabled using --disable-threadsafe" 315 } 316 } else { 317 # 318 # If user does not specify --[disable-]threadsafe then select a 319 # default based on whether it looks like Tcl has threading 320 # support. 321 # 322 catch { 323 scan [exec echo {puts [tcl::pkgconfig get threaded]} | [get-define TCLSH_CMD]] \ 324 %d enable 325 } 326 if {$enable} { 327 set flagName "--threadsafe" 328 set lblAbled "enabled" 329 msg-result yes 330 } else { 331 set flagName "--disable-threadsafe" 332 set lblAbled "disabled" 333 msg-result no 334 } 335 msg-result "Defaulting to ${flagName} because Tcl has threading ${lblAbled}." 336 # ^^^ We (probably) don't need to link against -lpthread in the 337 # is-enabled case. We might in the case of static linking. Unsure. 338 } 339 sqlite-add-feature-flag -DSQLITE_THREADSAFE=${enable} 340 return $enable 341} 342 343# 344# Handles the --enable-load-extension flag. Returns 1 if the support 345# is enabled, else 0. If support for that feature is not found, a 346# fatal error is triggered if --enable-load-extension is explicitly 347# provided, else a loud warning is instead emitted. If 348# --disable-load-extension is used, no check is performed. 349# 350# Makes the following environment changes: 351# 352# - defines LDFLAGS_DLOPEN to any linker flags needed for this 353# feature. It may legally be empty on some systems where dlopen() 354# is in libc. 355# 356# - If the feature is not available, adds 357# -DSQLITE_OMIT_LOAD_EXTENSION=1 to the feature flags list. 358proc sqlite-handle-load-extension {} { 359 define LDFLAGS_DLOPEN "" 360 set found 0 361 proj-if-opt-truthy load-extension { 362 set found [proj-check-function-in-lib dlopen dl] 363 if {$found} { 364 set ldf [get-define lib_dlopen] 365 define LDFLAGS_DLOPEN $ldf 366 teaish-ldflags-prepend $ldf 367 undefine lib_dlopen 368 } else { 369 if {[proj-opt-was-provided load-extension]} { 370 # Explicit --enable-load-extension: fail if not found 371 proj-indented-notice -error { 372 --enable-load-extension was provided but dlopen() 373 not found. Use --disable-load-extension to bypass this 374 check. 375 } 376 } else { 377 # It was implicitly enabled: warn if not found 378 proj-indented-notice { 379 WARNING: dlopen() not found, so loadable module support will 380 be disabled. Use --disable-load-extension to bypass this 381 check. 382 } 383 } 384 } 385 } 386 if {$found} { 387 msg-result "Loadable extension support enabled." 388 } else { 389 msg-result "Disabling loadable extension support. Use --enable-load-extension to enable them." 390 sqlite-add-feature-flag -DSQLITE_OMIT_LOAD_EXTENSION=1 391 } 392 return $found 393} 394 395# 396# ICU - International Components for Unicode 397# 398# Handles these flags: 399# 400# --with-icu-ldflags=LDFLAGS 401# --with-icu-cflags=CFLAGS 402# --with-icu-config[=auto | pkg-config | /path/to/icu-config] 403# --enable-icu-collations 404# 405# --with-icu-config values: 406# 407# - auto: use the first one of (pkg-config, icu-config) found on the 408# system. 409# - pkg-config: use only pkg-config to determine flags 410# - /path/to/icu-config: use that to determine flags 411# 412# If --with-icu-config is used as neither pkg-config nor icu-config 413# are found, fail fatally. 414# 415# If both --with-icu-ldflags and --with-icu-config are provided, they 416# are cumulative. If neither are provided, icu-collations is not 417# honored and a warning is emitted if it is provided. 418# 419# Design note: though we could automatically enable ICU if the 420# icu-config binary or (pkg-config icu-io) are found, we specifically 421# do not. ICU is always an opt-in feature. 422proc sqlite-handle-icu {} { 423 define LDFLAGS_LIBICU [join [opt-val with-icu-ldflags ""]] 424 define CFLAGS_LIBICU [join [opt-val with-icu-cflags ""]] 425 if {[proj-opt-was-provided with-icu-config]} { 426 msg-result "Checking for ICU support..." 427 set icuConfigBin [opt-val with-icu-config] 428 set tryIcuConfigBin 1; # set to 0 if we end up using pkg-config 429 if {$icuConfigBin in {auto pkg-config}} { 430 uplevel 3 { use pkg-config } 431 if {[pkg-config-init 0] && [pkg-config icu-io]} { 432 # Maintenance reminder: historical docs say to use both of 433 # (icu-io, icu-uc). icu-uc lacks a required lib and icu-io has 434 # all of them on tested OSes. 435 set tryIcuConfigBin 0 436 define LDFLAGS_LIBICU [get-define PKG_ICU_IO_LDFLAGS] 437 define-append LDFLAGS_LIBICU [get-define PKG_ICU_IO_LIBS] 438 define CFLAGS_LIBICU [get-define PKG_ICU_IO_CFLAGS] 439 } elseif {"pkg-config" eq $icuConfigBin} { 440 proj-fatal "pkg-config cannot find package icu-io" 441 } else { 442 proj-assert {"auto" eq $icuConfigBin} 443 } 444 } 445 if {$tryIcuConfigBin} { 446 if {"auto" eq $icuConfigBin} { 447 set icuConfigBin [proj-first-bin-of \ 448 /usr/local/bin/icu-config \ 449 /usr/bin/icu-config] 450 if {"" eq $icuConfigBin} { 451 proj-indented-notice -error { 452 --with-icu-config=auto cannot find (pkg-config icu-io) or icu-config binary. 453 On Ubuntu-like systems try: 454 --with-icu-ldflags='-licui18n -licuuc -licudata' 455 } 456 } 457 } 458 if {[file-isexec $icuConfigBin]} { 459 set x [exec $icuConfigBin --ldflags] 460 if {"" eq $x} { 461 proj-indented-notice -error \ 462 [subst { 463 $icuConfigBin --ldflags returned no data. 464 On Ubuntu-like systems try: 465 --with-icu-ldflags='-licui18n -licuuc -licudata' 466 }] 467 } 468 define-append LDFLAGS_LIBICU $x 469 set x [exec $icuConfigBin --cppflags] 470 define-append CFLAGS_LIBICU $x 471 } else { 472 proj-fatal "--with-icu-config=$icuConfigBin does not refer to an executable" 473 } 474 } 475 } 476 set ldflags [define LDFLAGS_LIBICU [string trim [get-define LDFLAGS_LIBICU]]] 477 set cflags [define CFLAGS_LIBICU [string trim [get-define CFLAGS_LIBICU]]] 478 if {"" ne $ldflags} { 479 sqlite-add-feature-flag -DSQLITE_ENABLE_ICU 480 msg-result "Enabling ICU support with flags: $ldflags $cflags" 481 if {[opt-bool icu-collations]} { 482 msg-result "Enabling ICU collations." 483 sqlite-add-feature-flag -DSQLITE_ENABLE_ICU_COLLATIONS 484 } 485 teaish-ldflags-prepend $ldflags 486 teaish-cflags-add $cflags 487 } elseif {[opt-bool icu-collations]} { 488 proj-warn "ignoring --enable-icu-collations because neither --with-icu-ldflags nor --with-icu-config provided any linker flags" 489 } else { 490 msg-result "ICU support is disabled." 491 } 492}; # sqlite-handle-icu 493 494 495# 496# Handles the --with-tempstore flag. 497# 498# The test fixture likes to set SQLITE_TEMP_STORE on its own, so do 499# not set that feature flag unless it was explicitly provided to the 500# configure script. 501proc sqlite-handle-tempstore {} { 502 if {[proj-opt-was-provided with-tempstore]} { 503 set ts [opt-val with-tempstore no] 504 set tsn 1 505 msg-checking "Use an in-RAM database for temporary tables? " 506 switch -exact -- $ts { 507 never { set tsn 0 } 508 no { set tsn 1 } 509 yes { set tsn 2 } 510 always { set tsn 3 } 511 default { 512 user-error "Invalid --with-tempstore value '$ts'. Use one of: never, no, yes, always" 513 } 514 } 515 msg-result $ts 516 sqlite-add-feature-flag -DSQLITE_TEMP_STORE=$tsn 517 } 518} 519 520# 521# Handles the --enable-math flag. 522proc sqlite-handle-math {} { 523 proj-if-opt-truthy math { 524 if {![proj-check-function-in-lib ceil m]} { 525 user-error "Cannot find libm functions. Use --disable-math to bypass this." 526 } 527 set lfl [get-define lib_ceil] 528 undefine lib_ceil 529 define LDFLAGS_MATH $lfl 530 teaish-ldflags-prepend $lfl 531 sqlite-add-feature-flag -DSQLITE_ENABLE_MATH_FUNCTIONS 532 msg-result "Enabling math SQL functions" 533 } { 534 define LDFLAGS_MATH "" 535 msg-result "Disabling math SQL functions" 536 } 537} 538 539# 540# Move -DSQLITE_OMIT... and -DSQLITE_ENABLE... flags from CFLAGS and 541# CPPFLAGS to OPT_FEATURE_FLAGS and remove them from BUILD_CFLAGS. 542proc sqlite-munge-cflags {} { 543 # Move CFLAGS and CPPFLAGS entries matching -DSQLITE_OMIT* and 544 # -DSQLITE_ENABLE* to OPT_FEATURE_FLAGS. This behavior is derived 545 # from the pre-3.48 build. 546 # 547 # If any configure flags for features are in conflict with 548 # CFLAGS/CPPFLAGS-specified feature flags, all bets are off. There 549 # are no guarantees about which one will take precedence. 550 foreach flagDef {CFLAGS CPPFLAGS} { 551 set tmp "" 552 foreach cf [get-define $flagDef ""] { 553 switch -glob -- $cf { 554 -DSQLITE_OMIT* - 555 -DSQLITE_ENABLE* { 556 sqlite-add-feature-flag $cf 557 } 558 default { 559 lappend tmp $cf 560 } 561 } 562 } 563 define $flagDef $tmp 564 } 565} 566