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