aboutsummaryrefslogtreecommitdiff
path: root/autosetup/teaish/feature.tcl
diff options
context:
space:
mode:
Diffstat (limited to 'autosetup/teaish/feature.tcl')
-rw-r--r--autosetup/teaish/feature.tcl214
1 files changed, 214 insertions, 0 deletions
diff --git a/autosetup/teaish/feature.tcl b/autosetup/teaish/feature.tcl
new file mode 100644
index 000000000..6c927d1a7
--- /dev/null
+++ b/autosetup/teaish/feature.tcl
@@ -0,0 +1,214 @@
+########################################################################
+# 2025 April 7
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# * May you do good and not evil.
+# * May you find forgiveness for yourself and forgive others.
+# * May you share freely, never taking more than you give.
+#
+########################################################################
+# ----- @module feature-tests.tcl -----
+# @section TEA-ish collection of feature tests.
+#
+# Functions in this file with a prefix of teaish__ are
+# private/internal APIs. Those with a prefix of teaish- are
+# public APIs.
+
+
+# @teaish-check-libz
+#
+# Checks for zlib.h and the function deflate in libz. If found,
+# prepends -lz to the extension's ldflags and returns 1, else returns
+# 0. It also defines LDFLAGS_LIBZ to the libs flag.
+#
+proc teaish-check-libz {} {
+ teaish-check-cached "Checking for libz" {
+ set rc 0
+ if {[msg-quiet cc-check-includes zlib.h] && [msg-quiet proj-check-function-in-lib deflate z]} {
+ teaish-ldflags-prepend [define LDFLAGS_LIBZ [get-define lib_deflate]]
+ undefine lib_deflate
+ incr rc
+ }
+ expr $rc
+ }
+}
+
+# @teaish-check-librt ?funclist?
+#
+# Checks whether -lrt is needed for any of the given functions. If
+# so, appends -lrt via [teaish-ldflags-prepend] and returns 1, else
+# returns 0. It also defines LDFLAGS_LIBRT to the libs flag or an
+# empty string.
+#
+# Some systems (ex: SunOS) require -lrt in order to use nanosleep.
+#
+proc teaish-check-librt {{funclist {fdatasync nanosleep}}} {
+ teaish-check-cached -nostatus "Checking whether ($funclist) need librt" {
+ define LDFLAGS_LIBRT ""
+ foreach func $funclist {
+ if {[msg-quiet proj-check-function-in-lib $func rt]} {
+ set ldrt [get-define lib_${func}]
+ undefine lib_${func}
+ if {"" ne $ldrt} {
+ teaish-ldflags-prepend -r [define LDFLAGS_LIBRT $ldrt]
+ msg-result $ldrt
+ return 1
+ } else {
+ msg-result "no lib needed"
+ return 1
+ }
+ }
+ }
+ msg-result "not found"
+ return 0
+ }
+}
+
+# @teaish-check-stdint
+#
+# A thin proxy for [cc-with] which checks for <stdint.h> and the
+# various fixed-size int types it declares. It defines HAVE_STDINT_T
+# to 0 or 1 and (if it's 1) defines HAVE_XYZ_T for each XYZ int type
+# to 0 or 1, depending on whether its available.
+proc teaish-check-stdint {} {
+ teaish-check-cached "Checking for stdint.h" {
+ msg-quiet cc-with {-includes stdint.h} \
+ {cc-check-types int8_t int16_t int32_t int64_t intptr_t \
+ uint8_t uint16_t uint32_t uint64_t uintptr_t}
+ }
+}
+
+# @teaish-is-mingw
+#
+# Returns 1 if building for mingw, else 0.
+proc teaish-is-mingw {} {
+ return [expr {
+ [string match *mingw* [get-define host]] &&
+ ![file exists /dev/null]
+ }]
+}
+
+# @teaish-check-libdl
+#
+# Checks for whether dlopen() can be found and whether it requires
+# -ldl for linking. If found, returns 1, defines LDFLAGS_DLOPEN to the
+# linker flags (if any), and passes those flags to
+# teaish-ldflags-prepend. It unconditionally defines HAVE_DLOPEN to 0
+# or 1 (the its return result value).
+proc teaish-check-dlopen {} {
+ teaish-check-cached -nostatus "Checking for dlopen()" {
+ set rc 0
+ set lfl ""
+ if {[cc-with {-includes dlfcn.h} {
+ cctest -link 1 -declare "extern char* dlerror(void);" -code "dlerror();"}]} {
+ msg-result "-ldl not needed"
+ incr rc
+ } elseif {[cc-check-includes dlfcn.h]} {
+ incr rc
+ if {[cc-check-function-in-lib dlopen dl]} {
+ set lfl [get-define lib_dlopen]
+ undefine lib_dlopen
+ msg-result " dlopen() needs $lfl"
+ } else {
+ msg-result " - dlopen() not found in libdl. Assuming dlopen() is built-in."
+ }
+ } else {
+ msg-result "not found"
+ }
+ teaish-ldflags-prepend [define LDFLAGS_DLOPEN $lfl]
+ define HAVE_DLOPEN $rc
+ }
+}
+
+#
+# @teaish-check-libmath
+#
+# Handles the --enable-math flag. Returns 1 if found, else 0.
+# If found, it prepends -lm (if needed) to the linker flags.
+proc teaish-check-libmath {} {
+ teaish-check-cached "Checking for libc math library" {
+ set lfl ""
+ set rc 0
+ if {[msg-quiet proj-check-function-in-lib ceil m]} {
+ incr rc
+ set lfl [get-define lib_ceil]
+ undefine lib_ceil
+ teaish-ldflags-prepend $lfl
+ msg-checking "$lfl "
+ }
+ define LDFLAGS_LIBMATH $lfl
+ expr $rc
+ }
+}
+
+# @teaish-import-features ?-flags? feature-names...
+#
+# For each $name in feature-names... it invokes:
+#
+# use teaish/feature/$name
+#
+# to load TEAISH_AUTOSETUP_DIR/feature/$name.tcl
+#
+# By default, if a proc named teaish-check-${name}-options is defined
+# after sourcing a file, it is called and its result is passed to
+# proj-append-options. This can be suppressed with the -no-options
+# flag.
+#
+# Flags:
+#
+# -no-options: disables the automatic running of
+# teaish-check-NAME-options,
+#
+# -run: if the function teaish-check-NAME exists after importing
+# then it is called. This flag must not be used when calling this
+# function from teaish-options. This trumps both -pre and -post.
+#
+# -pre: if the function teaish-check-NAME exists after importing
+# then it is passed to [teaish-checks-queue -pre].
+#
+# -post: works like -pre but instead uses[teaish-checks-queue -post].
+proc teaish-import-features {args} {
+ set pk ""
+ set doOpt 1
+ proj-parse-simple-flags args flags {
+ -no-options 0 {set doOpt 0}
+ -run 0 {expr 1}
+ -pre 0 {set pk -pre}
+ -post 0 {set pk -post}
+ }
+ #
+ # TODO: never import the same module more than once. The "use"
+ # command is smart enough to not do that but we would need to
+ # remember whether or not any teaish-check-${arg}* procs have been
+ # called before, and skip them.
+ #
+ if {$flags(-run) && "" ne $pk} {
+ proj-error "Cannot use both -run and $pk" \
+ " (called from [proj-scope 1])"
+ }
+
+ foreach arg $args {
+ uplevel "use teaish/feature/$arg"
+ if {$doOpt} {
+ set n "teaish-check-${arg}-options"
+ if {[llength [info proc $n]] > 0} {
+ if {"" ne [set x [$n]]} {
+ options-add $x
+ }
+ }
+ }
+ if {$flags(-run)} {
+ set n "teaish-check-${arg}"
+ if {[llength [info proc $n]] > 0} {
+ uplevel 1 $n
+ }
+ } elseif {"" ne $pk} {
+ set n "teaish-check-${arg}"
+ if {[llength [info proc $n]] > 0} {
+ teaish-checks-queue {*}$pk $n
+ }
+ }
+ }
+}