Home | History | Annotate | Line # | Download | only in teaish
      1 ########################################################################
      2 # 2025 April 7
      3 #
      4 # The author disclaims copyright to this source code.  In place of
      5 # a legal notice, here is a blessing:
      6 #
      7 #  * May you do good and not evil.
      8 #  * May you find forgiveness for yourself and forgive others.
      9 #  * May you share freely, never taking more than you give.
     10 #
     11 ########################################################################
     12 # ----- @module feature-tests.tcl -----
     13 # @section TEA-ish collection of feature tests.
     14 #
     15 # Functions in this file with a prefix of teaish__ are
     16 # private/internal APIs. Those with a prefix of teaish- are
     17 # public APIs.
     18 
     19 
     20 # @teaish-check-libz
     21 #
     22 # Checks for zlib.h and the function deflate in libz. If found,
     23 # prepends -lz to the extension's ldflags and returns 1, else returns
     24 # 0. It also defines LDFLAGS_LIBZ to the libs flag.
     25 #
     26 proc teaish-check-libz {} {
     27   teaish-check-cached "Checking for libz" {
     28     set rc 0
     29     if {[msg-quiet cc-check-includes zlib.h] && [msg-quiet proj-check-function-in-lib deflate z]} {
     30       teaish-ldflags-prepend [define LDFLAGS_LIBZ [get-define lib_deflate]]
     31       undefine lib_deflate
     32       incr rc
     33     }
     34     expr $rc
     35   }
     36 }
     37 
     38 # @teaish-check-librt ?funclist?
     39 #
     40 # Checks whether -lrt is needed for any of the given functions.  If
     41 # so, appends -lrt via [teaish-ldflags-prepend] and returns 1, else
     42 # returns 0. It also defines LDFLAGS_LIBRT to the libs flag or an
     43 # empty string.
     44 #
     45 # Some systems (ex: SunOS) require -lrt in order to use nanosleep.
     46 #
     47 proc teaish-check-librt {{funclist {fdatasync nanosleep}}} {
     48   teaish-check-cached -nostatus "Checking whether ($funclist) need librt" {
     49     define LDFLAGS_LIBRT ""
     50     foreach func $funclist {
     51       if {[msg-quiet proj-check-function-in-lib $func rt]} {
     52         set ldrt [get-define lib_${func}]
     53         undefine lib_${func}
     54         if {"" ne $ldrt} {
     55           teaish-ldflags-prepend -r [define LDFLAGS_LIBRT $ldrt]
     56           msg-result $ldrt
     57           return 1
     58         } else {
     59           msg-result "no lib needed"
     60           return 1
     61         }
     62       }
     63     }
     64     msg-result "not found"
     65     return 0
     66   }
     67 }
     68 
     69 # @teaish-check-stdint
     70 #
     71 # A thin proxy for [cc-with] which checks for <stdint.h> and the
     72 # various fixed-size int types it declares. It defines HAVE_STDINT_T
     73 # to 0 or 1 and (if it's 1) defines HAVE_XYZ_T for each XYZ int type
     74 # to 0 or 1, depending on whether its available.
     75 proc teaish-check-stdint {} {
     76   teaish-check-cached "Checking for stdint.h" {
     77     msg-quiet cc-with {-includes stdint.h} \
     78       {cc-check-types int8_t int16_t int32_t int64_t intptr_t \
     79          uint8_t uint16_t uint32_t uint64_t uintptr_t}
     80   }
     81 }
     82 
     83 # @teaish-is-mingw
     84 #
     85 # Returns 1 if building for mingw, else 0.
     86 proc teaish-is-mingw {} {
     87   return [expr {
     88     [string match *mingw* [get-define host]] &&
     89     ![file exists /dev/null]
     90   }]
     91 }
     92 
     93 # @teaish-check-libdl
     94 #
     95 # Checks for whether dlopen() can be found and whether it requires
     96 # -ldl for linking. If found, returns 1, defines LDFLAGS_DLOPEN to the
     97 # linker flags (if any), and passes those flags to
     98 # teaish-ldflags-prepend. It unconditionally defines HAVE_DLOPEN to 0
     99 # or 1 (the its return result value).
    100 proc teaish-check-dlopen {} {
    101   teaish-check-cached -nostatus "Checking for dlopen()" {
    102     set rc 0
    103     set lfl ""
    104     if {[cc-with {-includes dlfcn.h} {
    105       cctest -link 1 -declare "extern char* dlerror(void);" -code "dlerror();"}]} {
    106       msg-result "-ldl not needed"
    107       incr rc
    108     } elseif {[cc-check-includes dlfcn.h]} {
    109       incr rc
    110       if {[cc-check-function-in-lib dlopen dl]} {
    111         set lfl [get-define lib_dlopen]
    112         undefine lib_dlopen
    113         msg-result " dlopen() needs $lfl"
    114       } else {
    115         msg-result " - dlopen() not found in libdl. Assuming dlopen() is built-in."
    116       }
    117     } else {
    118       msg-result "not found"
    119     }
    120     teaish-ldflags-prepend [define LDFLAGS_DLOPEN $lfl]
    121     define HAVE_DLOPEN $rc
    122   }
    123 }
    124 
    125 #
    126 # @teaish-check-libmath
    127 #
    128 # Handles the --enable-math flag. Returns 1 if found, else 0.
    129 # If found, it prepends -lm (if needed) to the linker flags.
    130 proc teaish-check-libmath {} {
    131   teaish-check-cached "Checking for libc math library" {
    132     set lfl ""
    133     set rc 0
    134     if {[msg-quiet proj-check-function-in-lib ceil m]} {
    135       incr rc
    136       set lfl [get-define lib_ceil]
    137       undefine lib_ceil
    138       teaish-ldflags-prepend $lfl
    139       msg-checking "$lfl "
    140     }
    141     define LDFLAGS_LIBMATH $lfl
    142     expr $rc
    143   }
    144 }
    145 
    146 # @teaish-import-features ?-flags? feature-names...
    147 #
    148 # For each $name in feature-names... it invokes:
    149 #
    150 #   use teaish/feature/$name
    151 #
    152 # to load TEAISH_AUTOSETUP_DIR/feature/$name.tcl
    153 #
    154 # By default, if a proc named teaish-check-${name}-options is defined
    155 # after sourcing a file, it is called and its result is passed to
    156 # proj-append-options. This can be suppressed with the -no-options
    157 # flag.
    158 #
    159 # Flags:
    160 #
    161 #   -no-options: disables the automatic running of
    162 #    teaish-check-NAME-options,
    163 #
    164 #   -run: if the function teaish-check-NAME exists after importing
    165 #    then it is called. This flag must not be used when calling this
    166 #    function from teaish-options. This trumps both -pre and -post.
    167 #
    168 #   -pre: if the function teaish-check-NAME exists after importing
    169 #    then it is passed to [teaish-checks-queue -pre].
    170 #
    171 #   -post: works like -pre but instead uses[teaish-checks-queue -post].
    172 proc teaish-import-features {args} {
    173   set pk ""
    174   set doOpt 1
    175   proj-parse-simple-flags args flags {
    176     -no-options 0 {set doOpt 0}
    177     -run        0 {expr 1}
    178     -pre        0 {set pk -pre}
    179     -post       0 {set pk -post}
    180   }
    181   #
    182   # TODO: never import the same module more than once. The "use"
    183   # command is smart enough to not do that but we would need to
    184   # remember whether or not any teaish-check-${arg}* procs have been
    185   # called before, and skip them.
    186   #
    187   if {$flags(-run) && "" ne $pk} {
    188     proj-error "Cannot use both -run and $pk" \
    189       " (called from [proj-scope 1])"
    190   }
    191 
    192   foreach arg $args {
    193     uplevel "use teaish/feature/$arg"
    194     if {$doOpt} {
    195       set n "teaish-check-${arg}-options"
    196       if {[llength [info proc $n]] > 0} {
    197         if {"" ne [set x [$n]]} {
    198           options-add $x
    199         }
    200       }
    201     }
    202     if {$flags(-run)} {
    203       set n "teaish-check-${arg}"
    204       if {[llength [info proc $n]] > 0} {
    205         uplevel 1 $n
    206       }
    207     } elseif {"" ne $pk} {
    208       set n "teaish-check-${arg}"
    209       if {[llength [info proc $n]] > 0} {
    210         teaish-checks-queue {*}$pk $n
    211       }
    212     }
    213   }
    214 }
    215