1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
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
}
}
}
}
|