# System autoconfiguration. Try: ./configure --help # This must be above "options" below because it implicitly brings in the # default Autosetup options, things like --prefix. use cc cc-lib local options { with-openssl:path|auto|tree|none => {Look for OpenSSL in the given path, automatically, in the source tree, or none} with-zlib:path|auto|tree => {Look for zlib in the given path, automatically, or in the source tree} with-sqlite:path|auto|tree => {Look for sqlite in the given path, automatically, or in the source tree.} with-exec-rel-paths=0 => {Enable relative paths for external diff/gdiff} with-sanitizer: => {Build with C compiler's -fsanitize=LIST; e.g. address,enum,null,undefined} with-th1-docs=0 => {Enable TH1 for embedded documentation pages} with-th1-hooks=0 => {Enable TH1 hooks for commands and web pages} with-tcl:path => {Enable Tcl integration, with Tcl in the specified path} with-tcl-stubs=0 => {Enable Tcl integration via stubs library mechanism} with-tcl-private-stubs=0 => {Enable Tcl integration via private stubs mechanism} with-mman=0 => {Enable use of POSIX memory APIs from "sys/mman.h"} with-see=0 => {Enable the SQLite Encryption Extension (SEE)} print-minimum-sqlite-version=0 => {print the minimum SQLite version number required, and exit} internal-sqlite=1 => {Don't use the internal SQLite, use the system one} static=0 => {Link a static executable} fusefs=1 => {Disable the Fuse Filesystem} fossil-debug=0 => {Build with fossil debugging enabled} no-opt=0 => {Build without optimization} json=0 => {Build with fossil JSON API enabled} with-emsdk:path => {Directory containing the Emscripten SDK} compile-commands=0 => "Check for compile_commands.json support." } # Update the minimum required SQLite version number here, and also # in src/main.c near the sqlite3_libversion_number() call. Take care # that both places agree! define MINIMUM_SQLITE_VERSION "3.54.0" # This is useful for people wanting Fossil to use an external SQLite library # to compare the one they have against the minimum required if {[opt-bool print-minimum-sqlite-version]} { puts [get-define MINIMUM_SQLITE_VERSION] exit 0 } # Space characters have never been allowed in either the source # tree nor the build directory. But the resulting error messages # could be confusing. The following checks make the reason for the # failure clear. # set ::dirSrc $::autosetup(srcdir) if {[string first " " $$::dirSrc] != -1} { user-error "The pathname of the source tree\ may not contain space characters" } if {[string first " " $autosetup(builddir)] != -1} { user-error "The pathname of the build directory\ may not contain space characters" } set outOfTreeBuild 0 if {![file exists fossil.1]} { puts "This appears to be an out-of-tree build." set outOfTreeBuild 1 } # sqlite wants these types if possible cc-with {-includes {stdint.h inttypes.h}} { cc-check-types uint32_t uint16_t int16_t uint8_t } # Use pread/pwrite system calls in place of seek + read/write if possible define USE_PREAD [cc-check-functions pread] # If we have cscope here, we'll use it in the "tags" target if {[cc-check-progs cscope]} { define COLLECT_CSCOPE_DATA "cscope -bR $$::dirSrc/src/*.\[ch\]" } else { define COLLECT_CSCOPE_DATA "" } # Find tclsh for the test suite. # # We can't use jimsh for this: the test suite uses features of Tcl that # Jim doesn't support, either statically or due to the way it's built by # autosetup. For example, Jim supports `file normalize`, but only if # you build it with HAVE_REALPATH, which won't ever be defined in this # context because autosetup doesn't try to discover platform-specific # details like that before it decides to build jimsh0. Besides which, # autosetup won't build jimsh0 at all if it can find tclsh itself. # Ironically, this means we may right now be running under either jimsh0 # or a version of tclsh that we find unsuitable below! cc-check-progs tclsh set hbtd /usr/local/Cellar/tcl-tk if {[string equal false [get-define TCLSH]]} { msg-result "WARNING: 'make test' will not run here." set v 8.6 } else { set v [exec sh -c "echo 'puts \$tcl_version' | tclsh"] if {$v >= 8.6} { msg-result "Found Tclsh version $v in the PATH." define TCLSH tclsh } elseif {[file isdirectory $hbtd]} { # This is a macOS system with the Homebrew version of Tcl/Tk # installed. Select the newest version. It won't normally be # in the PATH to avoid shadowing /usr/bin/tclsh, and even if it # were in the PATH, it's bad practice to put /usr/local/bin (the # Homebrew default) ahead of /usr/bin, especially given that # it's user-writeable by default with Homebrew. Thus, we can be # pretty sure the only way to call it is with an absolute path. set v [exec ls -tr $hbtd | tail -1] set path "$hbtd/$v/bin/tclsh" define TCLSH $path msg-result "Using Homebrew Tcl/Tk version $path." } else { msg-result "WARNING: tclsh $v found; need >= 8.6 for 'make test'." define TCLSH false ;# force "make test" failure via /usr/bin/false } } define CFLAGS [get-env CFLAGS "-g -Os"] define EXTRA_CFLAGS "-Wall" define EXTRA_LDFLAGS "" define USE_SYSTEM_SQLITE 0 define USE_LINENOISE 0 define USE_MMAN_H 0 define USE_SEE 0 define SQLITE3_ORIGIN 0 # SQLITE3_ORIGIN 0 = src/sqlite3, 1=src/sqlite3-see.c, 2=client-provided define SQLITE_OPTIONS_EXT "" # SQLITE_OPTIONS_EXT => build-dependent CFLAGS for sqlite3.c and shell.c # Maintain the C89/C90-style order of variable declarations before statements. # Check if the compiler supports the respective warning flag. if {[cctest -cflags -Wdeclaration-after-statement]} { define-append EXTRA_CFLAGS -Wdeclaration-after-statement } # This procedure is a customized version of "cc-check-function-in-lib", # that does not modify the LIBS variable. Its use prevents prematurely # pulling in libraries that will be added later anyhow (e.g. "-ldl"). proc check-function-in-lib {function libs {otherlibs {}}} { if {[string length $otherlibs]} { msg-checking "Checking for $function in $libs with $otherlibs..." } else { msg-checking "Checking for $function in $libs..." } set found 0 cc-with [list -libs $otherlibs] { if {[cctest_function $function]} { msg-result "none needed" define lib_$function "" incr found } else { foreach lib $libs { cc-with [list -libs -l$lib] { if {[cctest_function $function]} { msg-result -l$lib define lib_$function -l$lib incr found break } } } } } if {$found} { define [feature-define-name $function] } else { msg-result "no" } return $found } if {![opt-bool internal-sqlite]} { proc find_system_sqlite {} { # On some systems (slackware), libsqlite3 requires -ldl to link. So # search for the system SQLite once with -ldl, and once without. If # the library can only be found with $extralibs set to -ldl, then # the code below will append -ldl to LIBS. # foreach extralibs {{} {-ldl}} { # Locate the system SQLite by searching for sqlite3_open(). Then check # if sqlite3_stmt_isexplain can be found as well. If we can find open() but # not stmt_isexplain(), then the system SQLite is too old to link against # fossil. # if {[check-function-in-lib sqlite3_open sqlite3 $extralibs]} { # Success. Update symbols and return. # define USE_SYSTEM_SQLITE 1 define-append LIBS -lsqlite3 define-append LIBS $extralibs return } } user-error "system sqlite3 not found" } find_system_sqlite proc test_system_sqlite {} { # Check compatibility of the system SQLite library by running the # sqlcompttest.c program in the source tree passes # MINIMUM_SQLITE_VERSION set at the top of this file to # sqlcompttest.c # set cmdline {} lappend cmdline {*}[get-define CCACHE] lappend cmdline {*}[get-define CC] {*}[get-define CFLAGS] lappend cmdline $::dirSrc/tools/sqlcompattest.c lappend cmdline -o conftest__ lappend cmdline {*}[get-define LDFLAGS] lappend cmdline {*}[get-define LIBS] set sqlite-version [string cat "-D MINIMUM_SQLITE_VERSION=" [get-define MINIMUM_SQLITE_VERSION]] lappend cmdline {*}[set sqlite-version] set ok 1 set err [catch {exec-with-stderr {*}$cmdline} result errinfo] if {$err} { configlog "Failed: [join $cmdline]" if {[string length $result]>0} {configlog $result} configlog "============" set ok 0 } elseif {$::autosetup(debug)} { configlog "Compiled OK: [join $cmdline]" configlog "============" } if {!$ok} { user-error "unable to compile SQLite compatibility test program" } set err [catch {exec-with-stderr ./conftest__} result errinfo] if {[get-define build] eq [get-define host]} { set err [catch {exec-with-stderr ./conftest__} result errinfo] if {$err} { user-error $result } } file delete ./conftest__ } test_system_sqlite } proc is_mingw {} { return [expr { [string match *mingw* [get-define host]] && ![file exists "/dev/null"] }] } if {[is_mingw]} { define-append EXTRA_CFLAGS -DBROKEN_MINGW_CMDLINE define-append LIBS -lkernel32 -lws2_32 } else { # # NOTE: All platforms except MinGW should use the linenoise # package. It is currently unsupported on Win32. # define USE_LINENOISE 1 } if {[string match *-solaris* [get-define host]]} { define-append EXTRA_CFLAGS {-D__EXTENSIONS__} } if {[opt-bool fossil-debug]} { define CFLAGS {-g -O0 -Wall} define-append CFLAGS -DFOSSIL_DEBUG msg-result "Debugging support enabled" } if {[opt-bool no-opt]} { define CFLAGS {-g -O0 -Wall} msg-result "Builting without compiler optimization" if {[opt-bool fossil-debug]} { define-append CFLAGS -DFOSSIL_DEBUG } } if {[opt-bool with-mman]} { define-append EXTRA_CFLAGS -DUSE_MMAN_H define USE_MMAN_H 1 msg-result "Enabling \"sys/mman.h\" support" } if {[opt-bool with-see]} { define-append EXTRA_CFLAGS -DUSE_SEE define USE_SEE 1 define SQLITE3_ORIGIN 1 msg-result "Enabling encryption support" } if {[opt-bool json]} { # Reminder/FIXME (stephan): FOSSIL_ENABLE_JSON # is required in the CFLAGS because json*.c # have #ifdef guards around the whole file without # reading config.h first. define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_JSON define FOSSIL_ENABLE_JSON msg-result "JSON support enabled" } if {[opt-bool with-exec-rel-paths]} { define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_EXEC_REL_PATHS define FOSSIL_ENABLE_EXEC_REL_PATHS msg-result "Relative paths in external diff/gdiff enabled" } if {[opt-bool with-th1-docs]} { define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_TH1_DOCS define FOSSIL_ENABLE_TH1_DOCS msg-result "TH1 embedded documentation support enabled" } if {[opt-bool with-th1-hooks]} { define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_TH1_HOOKS define FOSSIL_ENABLE_TH1_HOOKS msg-result "TH1 hooks support enabled" } #if {[opt-bool markdown]} { # # no-op. Markdown is now enabled by default. # msg-result "Markdown support enabled" #} if {[opt-bool static]} { # XXX: This will not work on all systems. define-append EXTRA_LDFLAGS -static msg-result "Trying to link statically" } else { define-append EXTRA_CFLAGS -DFOSSIL_DYNAMIC_BUILD=1 define FOSSIL_DYNAMIC_BUILD } # Check for libraries that need to be sorted out early cc-check-function-in-lib iconv iconv cc-check-function-in-lib sin m cc-check-function-in-lib dlopen dl # Helper for OpenSSL checking proc check-for-openssl {msg {cflags {}} {libs {-lssl -lcrypto -lpthread}}} { msg-checking "Checking for $msg..." set rc 0 if {[is_mingw]} { lappend libs -lgdi32 -lwsock32 -lcrypt32 } if {[info exists ::zlib_lib]} { lappend libs $::zlib_lib } msg-quiet cc-with [list -cflags $cflags -libs $libs] { if {[cc-check-includes openssl/ssl.h] && \ [cc-check-functions SSL_new]} { incr rc } } if {!$rc && ![is_mingw]} { # On some systems, OpenSSL appears to require -ldl to link. lappend libs -ldl msg-quiet cc-with [list -cflags $cflags -libs $libs] { if {[cc-check-includes openssl/ssl.h] && \ [cc-check-functions SSL_new]} { incr rc } } } if {$rc} { msg-result "ok" return 1 } else { msg-result "no" return 0 } } # # Check for zlib, using the given location if specified # proc handle-zlib {} { set ::zlibpath [opt-val with-zlib]; # used by downstream tcl tests if {$::zlibpath eq "tree"} { set ::zlibdir [file dirname $::autosetup(dir)]/compat/zlib if {![file isdirectory $::zlibdir]} { user-error "The zlib in source tree directory does not exist" } elseif { ([llength [glob -nocomplain -directory $::zlibdir libz*]] == 0) } { user-error "With --with-zlib=tree, $::zlibdir must be configured and built first." } cc-with [list -cflags "-I$::zlibdir -L$::zlibdir"] define-append EXTRA_CFLAGS -I$::zlibdir define-append LIBS $::zlibdir/libz.a set ::zlib_lib $::zlibdir/libz.a msg-result "Using zlib in source tree" } else { set cftry {""} set ldtry {""} if {$::zlibpath ni {auto ""}} { lappend cftry "-I$::zlibpath" lappend cftry "-I$::zlibpath/include" lappend ldtry "-L$::zlibpath" lappend ldtry "-L$::zlibpath/lib" } # Reverse the list of tests so we check most-specific to least, else # platform devel files will shadow local --with-zlib overrides. foreach c [lreverse $cftry] { if {[cc-with [list -cflags $c] {cc-check-includes zlib.h}]} { if {$c eq ""} { msg-result "Found zlib.h in default include path" } else { define-append EXTRA_CFLAGS "$c" msg-result "Found zlib.h via $c" } set cfound $c break } } if {![info exists cfound]} { user-error "zlib.h not found; either install it or specify its location via --with-zlib" } foreach lcheck [lreverse $ldtry] { if {[cc-with [list -cflags "$cfound $lcheck"] {check-function-in-lib inflateEnd z}]} { if {$lcheck eq ""} { msg-result "Linked to zlib via default library path" } else { define-append EXTRA_LDFLAGS "$lcheck" msg-result "Linked to zlib via $lcheck" } if {![check-function-in-lib compressBound z]} { puts "Notice: disabling zlib compression in the SQL shell" define-append SQLITE_OPTIONS_EXT {-USQLITE_HAVE_ZLIB} } break } } set ::zlib_lib -lz } }; # handle-zlib handle-zlib # # Handle the --with-openssl flag and, incidentally, update @LIBS@ for # zlib if openssl is _not_ used (if it is, we get zlib via libssl). # # This function should be called as late as possible in the configure # script to avoid that its updates to @LIBS@ break tests which follow # it when a custom local build of openssl is used, as discussed in # . # proc handle-with-openssl {} { set ssldirs [opt-val with-openssl] if {$ssldirs ne "none"} { set found 0 if {$ssldirs eq "tree"} { set ssldir [file dirname $::autosetup(dir)]/compat/openssl if {![file isdirectory $ssldir]} { user-error "The OpenSSL in source tree directory does not exist" } set msg "openssl in $ssldir" set cflags "-I$ssldir/include" set ldflags "-L$ssldir" set ssllibs "$ssldir/libssl.a $ssldir/libcrypto.a -lpthread" set found [check-for-openssl "openssl in source tree" "$cflags $ldflags" $ssllibs] } else { if {$ssldirs in {auto ""}} { catch { # TODO?: use autosetup's pkg-config support set cflags [exec pkg-config openssl --cflags-only-I] set ldflags [exec pkg-config openssl --libs-only-L] set found [check-for-openssl "ssl via pkg-config" "$cflags $ldflags"] } msg if {!$found} { set ssldirs "{} /usr/sfw /usr/local/ssl /usr/lib/ssl /usr/ssl \ /usr/pkg /usr/local /usr /usr/local/opt/openssl \ /opt/homebrew/opt/openssl" } } if {!$found} { foreach dir $ssldirs { if {$dir eq ""} { set msg "system openssl" set cflags "" set ldflags "" } else { set msg "openssl in $dir" set cflags "-I$dir/include" if {[file readable $dir/libssl.a]} { set ldflags -L$dir } elseif {[file readable $dir/lib/libssl.a]} { set ldflags -L$dir/lib } elseif {[file isdir $dir/lib]} { set ldflags "-L$dir -L$dir/lib" } else { set ldflags -L$dir } } if {[check-for-openssl $msg "$cflags $ldflags"]} { incr found break } if {$dir ne ""} { set ldflags "" set msg "static build of openssl in $dir" set ssllibs "$dir/libssl.a $dir/libcrypto.a -lpthread" if {[check-for-openssl $msg "$cflags $ldflags" $ssllibs]} { incr found break } # This test should arguably fail here if --with-openssl=X # points to an invalid X. } } } } if {$found} { define FOSSIL_ENABLE_SSL define-append EXTRA_CFLAGS $cflags define-append EXTRA_LDFLAGS $ldflags if {[info exists ssllibs]} { define-append LIBS $ssllibs } else { define-append LIBS -lssl -lcrypto } if {[info exists ::zlib_lib]} { define-append LIBS $::zlib_lib } if {[is_mingw]} { define-append LIBS -lgdi32 -lwsock32 -lcrypt32 } msg-result "HTTPS support enabled" # Silence OpenSSL deprecation warnings on Mac OS X 10.7. if {[string match *-darwin* [get-define host]]} { if {[cctest -cflags {-Wdeprecated-declarations}]} { define-append EXTRA_CFLAGS -Wdeprecated-declarations } } } else { user-error "OpenSSL not found. Consider --with-openssl=none to disable HTTPS support" } } else { if {[info exists ::zlib_lib]} { define-append LIBS $::zlib_lib } } }; # handle-with-openssl # # CFLAGS_INCLUDE is ONLY for -I... flags and their order is # significant so that --with-sqlite=PATH's header can shadow our # own. One caveat with this is that we cannot point # --with-sqlite=PATH to the root of sqlite3's own build tree because # that dir has a config.h which ends up shadowing src/config.h, # breaking our build. (That is no longer true: that that config.h # was renamed to sqlite_cfg.h at some point.) # define CFLAGS_INCLUDE {} ######################################################################## # --with-sqlite=PATH checks for the first it finds of the following... # - PATH/sqlite3.c and PATH/sqlite3.h # - PATH/sqlite3.o (and assumes sqlite3.h is with it) # - PATH/lib/libsqlite3* and PATH/include/sqlite3.h proc handle-with-sqlite {} { set sq3path [opt-val with-sqlite] define SQLITE3_SRC.2 {} define SQLITE3_OBJ.2 {} define SQLITE3_SHELL_SRC.2 {$(SQLITE3_SHELL_SRC.0)} if {$sq3path in {tree ""}} { msg-result "Using sqlite3.c from this source tree." } else { # SQLITE3_ORIGIN: # 0 = local source tree # 1 = use external lib or sqlite3.o # 2 = use external sqlite3.c and (if found) shell.c define USE_SYSTEM_SQLITE 1 define SQLITE3_ORIGIN 2 if {$sq3path != "auto"} { if {([file exists $sq3path/sqlite3.c]) && ([file exists $sq3path/sqlite3.h]) } { # Prefer sqlite3.[ch] if found. define SQLITE3_SRC.2 $sq3path/sqlite3.c define SQLITE3_OBJ.2 {$(SQLITE3_OBJ.0)} define USE_SYSTEM_SQLITE 2 define SQLITE3_ORIGIN 2 if {[file exists $sq3path/shell.c]} { define SQLITE3_SHELL_SRC.2 $sq3path/shell.c } define-append CFLAGS_INCLUDE -I$sq3path define-append EXTRA_LDFLAGS -lpthread # ^^^ additional -lXXX flags are conservative estimates msg-result "Using sqlite3.c and sqlite3.h from $sq3path" } elseif {[file exists $sq3path/sqlite3.o]} { # Use sqlite3.o if found. define SQLITE3_OBJ.2 $sq3path/sqlite3.o define-append CFLAGS_INCLUDE -I$sq3path define-append EXTRA_LDFLAGS $sq3path/sqlite3.o -lpthread # ^^^ additional -lXXX flags are conservative estimates msg-result "Using sqlite3.o from $sq3path" } elseif { ([llength [glob -nocomplain -directory $sq3path/lib libsqlite3*]] != 0) \ && ([file exists $sq3path/include/sqlite3.h]) } { # e.g. --with-sqlite=/usr/local. Try $sq3path/lib/libsqlite3* # and $sq3path/include/sqlite3.h define-append CFLAGS_INCLUDE -I$sq3path/include define-append EXTRA_LDFLAGS -L$sq3path/lib -lsqlite3 -lpthread # ^^^ additional -lXXX flags are conservative estimates msg-result "Using -lsqlite3 from $sq3path" } else { # Assume $sq3path holds both the lib and header cc-with [list -cflags "-I$sq3path -L$sq3path"] define-append CFLAGS_INCLUDE -I$sq3path define-append EXTRA_LDFLAGS -L$sq3path -lsqlite3 -lpthread # ^^^ additional -lXXX flags are conservative estimates msg-result "Using -lsqlite3 from $sq3path" } } elseif {![cc-check-includes sqlite3.h] || ![check-function-in-lib sqlite3_open_v2 sqlite3]} { user-error "libsqlite3 not found please install it or specify the location with --with-sqlite" } } }; # handle-with-sqlite handle-with-sqlite define-append CFLAGS_INCLUDE {-I. -I$(SRCDIR) -I$(SRCDIR_extsrc)}; # must be after handle-with-sqlite # # Handle the --with-tcl flag. # proc handle-with-tcl {} { global v set tclpath [opt-val with-tcl] if {$tclpath eq ""} { return } set tclprivatestubs [opt-bool with-tcl-private-stubs] # Note parse-tclconfig-sh is in autosetup/local.tcl if {$tclpath eq "1"} { if {$v >= 9.0} { set tcldir [file dirname $::autosetup(dir)]/compat/tcl-9.0 } else { set tcldir [file dirname $::autosetup(dir)]/compat/tcl-8.6 } if {$tclprivatestubs} { set tclconfig(TCL_INCLUDE_SPEC) -I$tcldir/generic set tclconfig(TCL_VERSION) {Private Stubs} set tclconfig(TCL_PATCH_LEVEL) {} set tclconfig(TCL_PREFIX) $tcldir set tclconfig(TCL_LD_FLAGS) { } } else { # Use the system Tcl. Look in some likely places. array set tclconfig [parse-tclconfig-sh \ $tcldir/unix $tcldir/win \ /usr /usr/local /usr/share /opt/local] set msg "on your system" } } else { array set tclconfig [parse-tclconfig-sh $tclpath] set msg "at $tclpath" } if {[opt-bool static]} { set tclconfig(TCL_LD_FLAGS) { } } if {![info exists tclconfig(TCL_INCLUDE_SPEC)]} { user-error "Cannot find Tcl $msg" } set tclstubs [opt-bool with-tcl-stubs] if {$tclprivatestubs} { define FOSSIL_ENABLE_TCL_PRIVATE_STUBS define USE_TCL_STUBS } elseif {$tclstubs && $tclconfig(TCL_SUPPORTS_STUBS)} { set libs "$tclconfig(TCL_STUB_LIB_SPEC)" define FOSSIL_ENABLE_TCL_STUBS define USE_TCL_STUBS } else { set libs "$tclconfig(TCL_LIB_SPEC) $tclconfig(TCL_LIBS)" } set cflags $tclconfig(TCL_INCLUDE_SPEC) if {!$tclprivatestubs} { set foundtcl 0; # Did we find a working Tcl library? cc-with [list -cflags $cflags -libs $libs] { if {$tclstubs} { if {[cc-check-functions Tcl_InitStubs]} { set foundtcl 1 } } else { if {[cc-check-functions Tcl_CreateInterp]} { set foundtcl 1 } } } if {!$foundtcl && [string match *-lieee* $libs]} { # On some systems, using "-lieee" from TCL_LIB_SPEC appears # to cause issues. msg-result "Removing \"-lieee\" and retrying for Tcl..." set libs [string map [list -lieee ""] $libs] cc-with [list -cflags $cflags -libs $libs] { if {$tclstubs} { if {[cc-check-functions Tcl_InitStubs]} { set foundtcl 1 } } else { if {[cc-check-functions Tcl_CreateInterp]} { set foundtcl 1 } } } } if {!$foundtcl && ![string match *-lpthread* $libs]} { # On some systems, TCL_LIB_SPEC appears to be missing # "-lpthread". Try adding it. msg-result "Adding \"-lpthread\" and retrying for Tcl..." set libs "$libs -lpthread" cc-with [list -cflags $cflags -libs $libs] { if {$tclstubs} { if {[cc-check-functions Tcl_InitStubs]} { set foundtcl 1 } } else { if {[cc-check-functions Tcl_CreateInterp]} { set foundtcl 1 } } } } if {!$foundtcl} { if {$tclstubs} { user-error "Cannot find a usable Tcl stubs library $msg" } else { user-error "Cannot find a usable Tcl library $msg" } } } set version $tclconfig(TCL_VERSION)$tclconfig(TCL_PATCH_LEVEL) msg-result "Found Tcl $version at $tclconfig(TCL_PREFIX)" if {!$tclprivatestubs} { define-append LIBS $libs } define-append EXTRA_CFLAGS $cflags define-append CFLAGS $cflags if {[info exists ::zlibpath] && $::zlibpath eq "tree"} { # # NOTE: When using zlib in the source tree, prevent Tcl from # pulling in the system one. # set tclconfig(TCL_LD_FLAGS) [string map [list -lz ""] \ $tclconfig(TCL_LD_FLAGS)] } # # NOTE: Remove "-ldl" from the TCL_LD_FLAGS because it will be # be checked for near the bottom of this file. # set tclconfig(TCL_LD_FLAGS) [string map [list -ldl ""] \ $tclconfig(TCL_LD_FLAGS)] define-append EXTRA_LDFLAGS $tclconfig(TCL_LD_FLAGS) define FOSSIL_ENABLE_TCL }; # handle-with-tcl handle-with-tcl # Network functions require libraries on some systems cc-check-function-in-lib gethostbyname nsl if {![cc-check-function-in-lib socket {socket network}]} { # Last resort, may be Windows if {[is_mingw]} { define-append LIBS -lwsock32 } } # Some systems (ex: SunOS) require -lrt in order to use nanosleep cc-check-function-in-lib nanosleep rt # The SMTP module requires special libraries and headers for MX DNS # record lookups and such. cc-check-includes arpa/nameser.h cc-include-needs bind/resolv.h netinet/in.h cc-check-includes bind/resolv.h cc-check-includes resolv.h if { !(([cc-check-function-in-lib dn_expand resolv] || [cc-check-function-in-lib ns_name_uncompress {bind resolv}] || [cc-check-function-in-lib __ns_name_uncompress {bind resolv}]) && ([cc-check-function-in-lib ns_parserr {bind resolv}] || [cc-check-function-in-lib __ns_parserr {bind resolv}]) && ([cc-check-function-in-lib res_query {bind resolv}] || [cc-check-function-in-lib __res_query {bind resolv}]))} { msg-result "WARNING: SMTP feature will not be able to look up local MX." } cc-check-function-in-lib res_9_ns_initparse resolv # Other nonstandard function checks cc-check-functions utime cc-check-functions usleep cc-check-functions strchrnul cc-check-functions pledge cc-check-functions backtrace # Termux on Android adds "getpass(char *)" to unistd.h, so check this so we # guard against including it again; use cctest as cc-check-functions and # cctest_function check for "getpass()" with no args and fail if {[cctest -link 1 -includes {unistd.h} -code "getpass(0);"]} { define FOSSIL_HAVE_GETPASS 1 msg-result "Found getpass() with unistd.h" } # Check for getloadavg(), and if it doesn't exist, define FOSSIL_OMIT_LOAD_AVERAGE if {![cc-check-functions getloadavg] || ![cctest -link 1 -includes {unistd.h} -code "double a\[3\]; getloadavg(a,3);"]} { define FOSSIL_OMIT_LOAD_AVERAGE 1 msg-result "Load average support unavailable" } # Check for getpassphrase() for Solaris 10 where getpass() truncates to 10 chars if {![cc-check-functions getpassphrase]} { # Haiku needs this cc-check-function-in-lib getpass bsd } # Check for the FuseFS library if {[opt-bool fusefs]} { if {[opt-bool static]} { msg-result "FuseFS support disabled due to -static" } elseif {[cc-check-function-in-lib fuse_mount fuse]} { define-append EXTRA_CFLAGS -DFOSSIL_HAVE_FUSEFS define FOSSIL_HAVE_FUSEFS 1 msg-result "FuseFS support enabled" } } ######################################################################## # Checks the compiler for compile_commands.json support. # # Returns 1 if supported, else 0. Defines MAKE_COMPILATION_DB to "yes" # if supported, "no" if not. proc check-compile-commands {} { msg-checking "compile_commands.json support... " if {[cctest -lang c -cflags {/dev/null -MJ} -source {}]} { # This test reportedly incorrectly succeeds on one of # Martin G.'s older systems. msg-result "compiler supports compile_commands.json" define MAKE_COMPILATION_DB yes return 1 } else { msg-result "compiler does not support compile_commands.json" define MAKE_COMPILATION_DB no return 0 } } define MAKE_COMPILATION_DB no if {!$outOfTreeBuild} { if {[opt-bool compile-commands]} { check-compile-commands } else { puts "Use --compile-commands to enable check for compile-commands-capable compiler." } } else { puts "Disabling compile_commands.json check for out-of-tree build." # This is an attempt to resolve the problem reported at # https://fossil-scm.org/forum/forumpost/d19061d09a8179d0 } # Add -fsanitize compile and link options late: we don't want the C # checks above to run with those sanitizers enabled. It can not only # be pointless, it can actually break correct tests. set fsan [opt-val with-sanitizer] if {[string length $fsan]} { define-append EXTRA_CFLAGS -fsanitize=$fsan define-append EXTRA_LDFLAGS -fsanitize=$fsan if {[string first "undefined" $fsan] != -1} { # We need to link with libubsan if we're compiling under # GCC with -fsanitize=undefined. cc-check-function-in-lib __ubsan_handle_add_overflow ubsan } } ######################################################################## # @proj-check-emsdk # # Emscripten is used for doing in-tree builds of web-based WASM stuff, # as opposed to WASI-based WASM or WASM binaries we import from other # places. This is only set up for Unix-style OSes and is untested # anywhere but Linux. Requires that the --with-emsdk flag be # registered with autosetup. # # It looks for the SDK in the location specified by --with-emsdk. # Values of "" or "auto" mean to check for the environment var EMSDK # (which gets set by the emsdk_env.sh script from the SDK) or that # same var passed to configure. # # If the given directory is found, it expects to find emsdk_env.sh in # that directory, as well as the emcc compiler somewhere under there. # # If the --with-emsdk flag is explicitly provided and the SDK is not # found then a fatal error is generated, otherwise failure to find the # SDK is not fatal. # # Defines the following: # # - EMSDK_HOME = top dir of the emsdk or "". # - EMSDK_ENV_SH = path to EMSDK_HOME/emsdk_env.sh or "" # - BIN_EMCC = $EMSDK_HOME/upstream/emscripten/emcc or "" # - HAVE_EMSDK = 0 or 1 (this function's return value) # # Returns 1 if EMSDK_ENV_SH is found, else 0. If EMSDK_HOME is not empty # but BIN_EMCC is then emcc was not found in the EMSDK_HOME, in which # case we have to rely on the fact that sourcing $EMSDK_ENV_SH from a # shell will add emcc to the $PATH. proc proj-check-emsdk {} { set emsdkHome [opt-val with-emsdk] define EMSDK_HOME "" define EMSDK_ENV_SH "" define BIN_EMCC "" set hadValue [llength $emsdkHome] msg-checking "Emscripten SDK? " if {$emsdkHome in {"" "auto"}} { # Check the environment. $EMSDK gets set by sourcing emsdk_env.sh. set emsdkHome [get-env EMSDK ""] } set rc 0 if {$emsdkHome ne ""} { define EMSDK_HOME $emsdkHome set emsdkEnv "$emsdkHome/emsdk_env.sh" if {[file exists $emsdkEnv]} { msg-result "$emsdkHome" define EMSDK_ENV_SH $emsdkEnv set rc 1 set emcc "$emsdkHome/upstream/emscripten/emcc" if {[file exists $emcc]} { define BIN_EMCC $emcc } } else { msg-result "emsdk_env.sh not found in $emsdkHome" } } else { msg-result "not found" } if {$hadValue && 0 == $rc} { # Fail if it was explicitly requested but not found proj-fatal "Cannot find the Emscripten SDK" } define HAVE_EMSDK $rc return $rc } if {!$outOfTreeBuild && [proj-check-emsdk]} { # Maintenance note: the WASM-related pieces are only for in-tree # maintenance, not out-of-tree builds. define EMCC_WRAPPER $::dirSrc/tools/emcc.sh define EMCC_OPT [get-env EMCC_OPT "-Oz"]; # optional flags to pass to emcc make-template tools/emcc.sh.in catch {exec chmod u+x [get-define EMCC_WRAPPER]} } else { define EMCC_WRAPPER "" define EMCC_OPT "" } handle-with-openssl # Finally, append libraries that must be last. This matters more on some # OSes than others, but is most broadly required for static linking. if {[opt-bool static]} { # Linux can only infer the dependency on pthread from OpenSSL when # doing dynamic linkage. define-append LIBS -lpthread } apply {{} { # This started out as a workaround for getting the ordering of -ldl # correct in conjunction with openssl in some environments. Then it # evolved into a more generic preemptive portability workaround to # ensure that certain libraries are always appended to the global # LIBS list if they exist on the system. Based on a /chat discussion # on 2025-02-27 in the context of check-in [8d3b9bf4d4]. # # Note that [move-lib-to-end] and [lib-actually-exists] are in # autosetup/local.tcl. set libs [get-define LIBS] #puts "**** 1 LIBS: $libs" foreach ll {-ldl -lpthread -lm} { if {![move-lib-to-end $ll $libs libs]} { # $ll was not in the list if {[lib-actually-exists $ll]} { # Add it to the list "just in case." This will be a no-op on # systems where the lib is not actually used. lappend libs $ll } } } #puts "**** 2 LIBS: $libs" define LIBS [join $libs " "] }} # Tag container builds with a prefix of the checkin ID of the version # of Fossil each one contains. This not only allows multiple images # to coexist and multiple containers to be created unamgiguosly from # them, it also changes the URL we fetch the source tarball from, so # repeated builds of a given version generate and fetch the source # tarball once only, keeping it in the local Docker/Podman cache. set ci [readfile "$::dirSrc/manifest.uuid"] define FOSSIL_CI_PFX [string range $ci 0 11] make-template Makefile.in make-config-header autoconfig.h -auto {USE_* FOSSIL_*}