cc.tcl revision 1.1 1 1.1 christos # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
2 1.1 christos # All rights reserved
3 1.1 christos
4 1.1 christos # @synopsis:
5 1.1 christos #
6 1.1 christos # The 'cc' module supports checking various 'features' of the C or C++
7 1.1 christos # compiler/linker environment. Common commands are 'cc-check-includes',
8 1.1 christos # 'cc-check-types', 'cc-check-functions', 'cc-with' and 'make-config-header'
9 1.1 christos #
10 1.1 christos # The following environment variables are used if set:
11 1.1 christos #
12 1.1 christos ## CC - C compiler
13 1.1 christos ## CXX - C++ compiler
14 1.1 christos ## CPP - C preprocessor
15 1.1 christos ## CCACHE - Set to "none" to disable automatic use of ccache
16 1.1 christos ## CPPFLAGS - Additional C preprocessor compiler flags (C and C++), before CFLAGS, CXXFLAGS
17 1.1 christos ## CFLAGS - Additional C compiler flags
18 1.1 christos ## CXXFLAGS - Additional C++ compiler flags
19 1.1 christos ## LDFLAGS - Additional compiler flags during linking
20 1.1 christos ## LINKFLAGS - ?How is this different from LDFLAGS?
21 1.1 christos ## LIBS - Additional libraries to use (for all tests)
22 1.1 christos ## CROSS - Tool prefix for cross compilation
23 1.1 christos #
24 1.1 christos # The following variables are defined from the corresponding
25 1.1 christos # environment variables if set.
26 1.1 christos #
27 1.1 christos ## CC_FOR_BUILD
28 1.1 christos ## LD
29 1.1 christos
30 1.1 christos use system
31 1.1 christos
32 1.1 christos options {}
33 1.1 christos
34 1.1 christos # Checks for the existence of the given function by linking
35 1.1 christos #
36 1.1 christos proc cctest_function {function} {
37 1.1 christos cctest -link 1 -declare "extern void $function\(void);" -code "$function\();"
38 1.1 christos }
39 1.1 christos
40 1.1 christos # Checks for the existence of the given type by compiling
41 1.1 christos proc cctest_type {type} {
42 1.1 christos cctest -code "$type _x;"
43 1.1 christos }
44 1.1 christos
45 1.1 christos # Checks for the existence of the given type/structure member.
46 1.1 christos # e.g. "struct stat.st_mtime"
47 1.1 christos proc cctest_member {struct_member} {
48 1.1 christos # split at the first dot
49 1.1 christos regexp {^([^.]+)[.](.*)$} $struct_member -> struct member
50 1.1 christos cctest -code "static $struct _s; return sizeof(_s.$member);"
51 1.1 christos }
52 1.1 christos
53 1.1 christos # Checks for the existence of the given define by compiling
54 1.1 christos #
55 1.1 christos proc cctest_define {name} {
56 1.1 christos cctest -code "#ifndef $name\n#error not defined\n#endif"
57 1.1 christos }
58 1.1 christos
59 1.1 christos # Checks for the existence of the given name either as
60 1.1 christos # a macro (#define) or an rvalue (such as an enum)
61 1.1 christos #
62 1.1 christos proc cctest_decl {name} {
63 1.1 christos cctest -code "#ifndef $name\n(void)$name;\n#endif"
64 1.1 christos }
65 1.1 christos
66 1.1 christos # @cc-check-sizeof type ...
67 1.1 christos #
68 1.1 christos # Checks the size of the given types (between 1 and 32, inclusive).
69 1.1 christos # Defines a variable with the size determined, or 'unknown' otherwise.
70 1.1 christos # e.g. for type 'long long', defines 'SIZEOF_LONG_LONG'.
71 1.1 christos # Returns the size of the last type.
72 1.1 christos #
73 1.1 christos proc cc-check-sizeof {args} {
74 1.1 christos foreach type $args {
75 1.1 christos msg-checking "Checking for sizeof $type..."
76 1.1 christos set size unknown
77 1.1 christos # Try the most common sizes first
78 1.1 christos foreach i {4 8 1 2 16 32} {
79 1.1 christos if {[cctest -code "static int _x\[sizeof($type) == $i ? 1 : -1\] = { 1 };"]} {
80 1.1 christos set size $i
81 1.1 christos break
82 1.1 christos }
83 1.1 christos }
84 1.1 christos msg-result $size
85 1.1 christos set define [feature-define-name $type SIZEOF_]
86 1.1 christos define $define $size
87 1.1 christos }
88 1.1 christos # Return the last result
89 1.1 christos get-define $define
90 1.1 christos }
91 1.1 christos
92 1.1 christos # Checks for each feature in $list by using the given script.
93 1.1 christos #
94 1.1 christos # When the script is evaluated, $each is set to the feature
95 1.1 christos # being checked, and $extra is set to any additional cctest args.
96 1.1 christos #
97 1.1 christos # Returns 1 if all features were found, or 0 otherwise.
98 1.1 christos proc cc-check-some-feature {list script} {
99 1.1 christos set ret 1
100 1.1 christos foreach each $list {
101 1.1 christos if {![check-feature $each $script]} {
102 1.1 christos set ret 0
103 1.1 christos }
104 1.1 christos }
105 1.1 christos return $ret
106 1.1 christos }
107 1.1 christos
108 1.1 christos # @cc-check-includes includes ...
109 1.1 christos #
110 1.1 christos # Checks that the given include files can be used.
111 1.1 christos proc cc-check-includes {args} {
112 1.1 christos cc-check-some-feature $args {
113 1.1 christos set with {}
114 1.1 christos if {[dict exists $::autosetup(cc-include-deps) $each]} {
115 1.1 christos set deps [dict keys [dict get $::autosetup(cc-include-deps) $each]]
116 1.1 christos msg-quiet cc-check-includes {*}$deps
117 1.1 christos foreach i $deps {
118 1.1 christos if {[have-feature $i]} {
119 1.1 christos lappend with $i
120 1.1 christos }
121 1.1 christos }
122 1.1 christos }
123 1.1 christos if {[llength $with]} {
124 1.1 christos cc-with [list -includes $with] {
125 1.1 christos cctest -includes $each
126 1.1 christos }
127 1.1 christos } else {
128 1.1 christos cctest -includes $each
129 1.1 christos }
130 1.1 christos }
131 1.1 christos }
132 1.1 christos
133 1.1 christos # @cc-include-needs include required ...
134 1.1 christos #
135 1.1 christos # Ensures that when checking for '$include', a check is first
136 1.1 christos # made for each '$required' file, and if found, it is included with '#include'.
137 1.1 christos proc cc-include-needs {file args} {
138 1.1 christos foreach depfile $args {
139 1.1 christos dict set ::autosetup(cc-include-deps) $file $depfile 1
140 1.1 christos }
141 1.1 christos }
142 1.1 christos
143 1.1 christos # @cc-check-types type ...
144 1.1 christos #
145 1.1 christos # Checks that the types exist.
146 1.1 christos proc cc-check-types {args} {
147 1.1 christos cc-check-some-feature $args {
148 1.1 christos cctest_type $each
149 1.1 christos }
150 1.1 christos }
151 1.1 christos
152 1.1 christos # @cc-check-defines define ...
153 1.1 christos #
154 1.1 christos # Checks that the given preprocessor symbols are defined.
155 1.1 christos proc cc-check-defines {args} {
156 1.1 christos cc-check-some-feature $args {
157 1.1 christos cctest_define $each
158 1.1 christos }
159 1.1 christos }
160 1.1 christos
161 1.1 christos # @cc-check-decls name ...
162 1.1 christos #
163 1.1 christos # Checks that each given name is either a preprocessor symbol or rvalue
164 1.1 christos # such as an enum. Note that the define used is 'HAVE_DECL_xxx'
165 1.1 christos # rather than 'HAVE_xxx'.
166 1.1 christos proc cc-check-decls {args} {
167 1.1 christos set ret 1
168 1.1 christos foreach name $args {
169 1.1 christos msg-checking "Checking for $name..."
170 1.1 christos set r [cctest_decl $name]
171 1.1 christos define-feature "decl $name" $r
172 1.1 christos if {$r} {
173 1.1 christos msg-result "ok"
174 1.1 christos } else {
175 1.1 christos msg-result "not found"
176 1.1 christos set ret 0
177 1.1 christos }
178 1.1 christos }
179 1.1 christos return $ret
180 1.1 christos }
181 1.1 christos
182 1.1 christos # @cc-check-functions function ...
183 1.1 christos #
184 1.1 christos # Checks that the given functions exist (can be linked).
185 1.1 christos proc cc-check-functions {args} {
186 1.1 christos cc-check-some-feature $args {
187 1.1 christos cctest_function $each
188 1.1 christos }
189 1.1 christos }
190 1.1 christos
191 1.1 christos # @cc-check-members type.member ...
192 1.1 christos #
193 1.1 christos # Checks that the given type/structure members exist.
194 1.1 christos # A structure member is of the form 'struct stat.st_mtime'.
195 1.1 christos proc cc-check-members {args} {
196 1.1 christos cc-check-some-feature $args {
197 1.1 christos cctest_member $each
198 1.1 christos }
199 1.1 christos }
200 1.1 christos
201 1.1 christos # @cc-check-function-in-lib function libs ?otherlibs?
202 1.1 christos #
203 1.1 christos # Checks that the given function can be found in one of the libs.
204 1.1 christos #
205 1.1 christos # First checks for no library required, then checks each of the libraries
206 1.1 christos # in turn.
207 1.1 christos #
208 1.1 christos # If the function is found, the feature is defined and 'lib_$function' is defined
209 1.1 christos # to '-l$lib' where the function was found, or "" if no library required.
210 1.1 christos # In addition, '-l$lib' is prepended to the 'LIBS' define.
211 1.1 christos #
212 1.1 christos # If additional libraries may be needed for linking, they should be specified
213 1.1 christos # with '$extralibs' as '-lotherlib1 -lotherlib2'.
214 1.1 christos # These libraries are not automatically added to 'LIBS'.
215 1.1 christos #
216 1.1 christos # Returns 1 if found or 0 if not.
217 1.1 christos #
218 1.1 christos proc cc-check-function-in-lib {function libs {otherlibs {}}} {
219 1.1 christos msg-checking "Checking libs for $function..."
220 1.1 christos set found 0
221 1.1 christos cc-with [list -libs $otherlibs] {
222 1.1 christos if {[cctest_function $function]} {
223 1.1 christos msg-result "none needed"
224 1.1 christos define lib_$function ""
225 1.1 christos incr found
226 1.1 christos } else {
227 1.1 christos foreach lib $libs {
228 1.1 christos cc-with [list -libs -l$lib] {
229 1.1 christos if {[cctest_function $function]} {
230 1.1 christos msg-result -l$lib
231 1.1 christos define lib_$function -l$lib
232 1.1 christos # prepend to LIBS
233 1.1 christos define LIBS "-l$lib [get-define LIBS]"
234 1.1 christos incr found
235 1.1 christos break
236 1.1 christos }
237 1.1 christos }
238 1.1 christos }
239 1.1 christos }
240 1.1 christos }
241 1.1 christos define-feature $function $found
242 1.1 christos if {!$found} {
243 1.1 christos msg-result "no"
244 1.1 christos }
245 1.1 christos return $found
246 1.1 christos }
247 1.1 christos
248 1.1 christos # @cc-check-tools tool ...
249 1.1 christos #
250 1.1 christos # Checks for existence of the given compiler tools, taking
251 1.1 christos # into account any cross compilation prefix.
252 1.1 christos #
253 1.1 christos # For example, when checking for 'ar', first 'AR' is checked on the command
254 1.1 christos # line and then in the environment. If not found, '${host}-ar' or
255 1.1 christos # simply 'ar' is assumed depending upon whether cross compiling.
256 1.1 christos # The path is searched for this executable, and if found 'AR' is defined
257 1.1 christos # to the executable name.
258 1.1 christos # Note that even when cross compiling, the simple 'ar' is used as a fallback,
259 1.1 christos # but a warning is generated. This is necessary for some toolchains.
260 1.1 christos #
261 1.1 christos # It is an error if the executable is not found.
262 1.1 christos #
263 1.1 christos proc cc-check-tools {args} {
264 1.1 christos foreach tool $args {
265 1.1 christos set TOOL [string toupper $tool]
266 1.1 christos set exe [get-env $TOOL [get-define cross]$tool]
267 1.1 christos if {[find-executable $exe]} {
268 1.1 christos define $TOOL $exe
269 1.1 christos continue
270 1.1 christos }
271 1.1 christos if {[find-executable $tool]} {
272 1.1 christos msg-result "Warning: Failed to find $exe, falling back to $tool which may be incorrect"
273 1.1 christos define $TOOL $tool
274 1.1 christos continue
275 1.1 christos }
276 1.1 christos user-error "Failed to find $exe"
277 1.1 christos }
278 1.1 christos }
279 1.1 christos
280 1.1 christos # @cc-check-progs prog ...
281 1.1 christos #
282 1.1 christos # Checks for existence of the given executables on the path.
283 1.1 christos #
284 1.1 christos # For example, when checking for 'grep', the path is searched for
285 1.1 christos # the executable, 'grep', and if found 'GREP' is defined as 'grep'.
286 1.1 christos #
287 1.1 christos # If the executable is not found, the variable is defined as 'false'.
288 1.1 christos # Returns 1 if all programs were found, or 0 otherwise.
289 1.1 christos #
290 1.1 christos proc cc-check-progs {args} {
291 1.1 christos set failed 0
292 1.1 christos foreach prog $args {
293 1.1 christos set PROG [string toupper $prog]
294 1.1 christos msg-checking "Checking for $prog..."
295 1.1 christos if {![find-executable $prog]} {
296 1.1 christos msg-result no
297 1.1 christos define $PROG false
298 1.1 christos incr failed
299 1.1 christos } else {
300 1.1 christos msg-result ok
301 1.1 christos define $PROG $prog
302 1.1 christos }
303 1.1 christos }
304 1.1 christos expr {!$failed}
305 1.1 christos }
306 1.1 christos
307 1.1 christos # @cc-path-progs prog ...
308 1.1 christos #
309 1.1 christos # Like cc-check-progs, but sets the define to the full path rather
310 1.1 christos # than just the program name.
311 1.1 christos #
312 1.1 christos proc cc-path-progs {args} {
313 1.1 christos set failed 0
314 1.1 christos foreach prog $args {
315 1.1 christos set PROG [string toupper $prog]
316 1.1 christos msg-checking "Checking for $prog..."
317 1.1 christos set path [find-executable-path $prog]
318 1.1 christos if {$path eq ""} {
319 1.1 christos msg-result no
320 1.1 christos define $PROG false
321 1.1 christos incr failed
322 1.1 christos } else {
323 1.1 christos msg-result $path
324 1.1 christos define $PROG $path
325 1.1 christos }
326 1.1 christos }
327 1.1 christos expr {!$failed}
328 1.1 christos }
329 1.1 christos
330 1.1 christos # Adds the given settings to $::autosetup(ccsettings) and
331 1.1 christos # returns the old settings.
332 1.1 christos #
333 1.1 christos proc cc-add-settings {settings} {
334 1.1 christos if {[llength $settings] % 2} {
335 1.1 christos autosetup-error "settings list is missing a value: $settings"
336 1.1 christos }
337 1.1 christos
338 1.1 christos set prev [cc-get-settings]
339 1.1 christos # workaround a bug in some versions of jimsh by forcing
340 1.1 christos # conversion of $prev to a list
341 1.1 christos llength $prev
342 1.1 christos
343 1.1 christos array set new $prev
344 1.1 christos
345 1.1 christos foreach {name value} $settings {
346 1.1 christos switch -exact -- $name {
347 1.1 christos -cflags - -includes {
348 1.1 christos # These are given as lists
349 1.1 christos lappend new($name) {*}[list-non-empty $value]
350 1.1 christos }
351 1.1 christos -declare {
352 1.1 christos lappend new($name) $value
353 1.1 christos }
354 1.1 christos -libs {
355 1.1 christos # Note that new libraries are added before previous libraries
356 1.1 christos set new($name) [list {*}[list-non-empty $value] {*}$new($name)]
357 1.1 christos }
358 1.1 christos -link - -lang - -nooutput {
359 1.1 christos set new($name) $value
360 1.1 christos }
361 1.1 christos -source - -sourcefile - -code {
362 1.1 christos # XXX: These probably are only valid directly from cctest
363 1.1 christos set new($name) $value
364 1.1 christos }
365 1.1 christos default {
366 1.1 christos autosetup-error "unknown cctest setting: $name"
367 1.1 christos }
368 1.1 christos }
369 1.1 christos }
370 1.1 christos
371 1.1 christos cc-store-settings [array get new]
372 1.1 christos
373 1.1 christos return $prev
374 1.1 christos }
375 1.1 christos
376 1.1 christos proc cc-store-settings {new} {
377 1.1 christos set ::autosetup(ccsettings) $new
378 1.1 christos }
379 1.1 christos
380 1.1 christos proc cc-get-settings {} {
381 1.1 christos return $::autosetup(ccsettings)
382 1.1 christos }
383 1.1 christos
384 1.1 christos # Similar to cc-add-settings, but each given setting
385 1.1 christos # simply replaces the existing value.
386 1.1 christos #
387 1.1 christos # Returns the previous settings
388 1.1 christos proc cc-update-settings {args} {
389 1.1 christos set prev [cc-get-settings]
390 1.1 christos cc-store-settings [dict merge $prev $args]
391 1.1 christos return $prev
392 1.1 christos }
393 1.1 christos
394 1.1 christos # @cc-with settings ?{ script }?
395 1.1 christos #
396 1.1 christos # Sets the given 'cctest' settings and then runs the tests in '$script'.
397 1.1 christos # Note that settings such as '-lang' replace the current setting, while
398 1.1 christos # those such as '-includes' are appended to the existing setting.
399 1.1 christos #
400 1.1 christos # If no script is given, the settings become the default for the remainder
401 1.1 christos # of the 'auto.def' file.
402 1.1 christos #
403 1.1 christos ## cc-with {-lang c++} {
404 1.1 christos ## # This will check with the C++ compiler
405 1.1 christos ## cc-check-types bool
406 1.1 christos ## cc-with {-includes signal.h} {
407 1.1 christos ## # This will check with the C++ compiler, signal.h and any existing includes.
408 1.1 christos ## ...
409 1.1 christos ## }
410 1.1 christos ## # back to just the C++ compiler
411 1.1 christos ## }
412 1.1 christos #
413 1.1 christos # The '-libs' setting is special in that newer values are added *before* earlier ones.
414 1.1 christos #
415 1.1 christos ## cc-with {-libs {-lc -lm}} {
416 1.1 christos ## cc-with {-libs -ldl} {
417 1.1 christos ## cctest -libs -lsocket ...
418 1.1 christos ## # libs will be in this order: -lsocket -ldl -lc -lm
419 1.1 christos ## }
420 1.1 christos ## }
421 1.1 christos #
422 1.1 christos # If you wish to invoke something like cc-check-flags but not have -cflags updated,
423 1.1 christos # use the following idiom:
424 1.1 christos #
425 1.1 christos ## cc-with {} {
426 1.1 christos ## cc-check-flags ...
427 1.1 christos ## }
428 1.1 christos proc cc-with {settings args} {
429 1.1 christos if {[llength $args] == 0} {
430 1.1 christos cc-add-settings $settings
431 1.1 christos } elseif {[llength $args] > 1} {
432 1.1 christos autosetup-error "usage: cc-with settings ?script?"
433 1.1 christos } else {
434 1.1 christos set save [cc-add-settings $settings]
435 1.1 christos set rc [catch {uplevel 1 [lindex $args 0]} result info]
436 1.1 christos cc-store-settings $save
437 1.1 christos if {$rc != 0} {
438 1.1 christos return -code [dict get $info -code] $result
439 1.1 christos }
440 1.1 christos return $result
441 1.1 christos }
442 1.1 christos }
443 1.1 christos
444 1.1 christos # @cctest ?settings?
445 1.1 christos #
446 1.1 christos # Low level C/C++ compiler checker. Compiles and or links a small C program
447 1.1 christos # according to the arguments and returns 1 if OK, or 0 if not.
448 1.1 christos #
449 1.1 christos # Supported settings are:
450 1.1 christos #
451 1.1 christos ## -cflags cflags A list of flags to pass to the compiler
452 1.1 christos ## -includes list A list of includes, e.g. {stdlib.h stdio.h}
453 1.1 christos ## -declare code Code to declare before main()
454 1.1 christos ## -link 1 Don't just compile, link too
455 1.1 christos ## -lang c|c++ Use the C (default) or C++ compiler
456 1.1 christos ## -libs liblist List of libraries to link, e.g. {-ldl -lm}
457 1.1 christos ## -code code Code to compile in the body of main()
458 1.1 christos ## -source code Compile a complete program. Ignore -includes, -declare and -code
459 1.1 christos ## -sourcefile file Shorthand for -source [readfile [get-define srcdir]/$file]
460 1.1 christos ## -nooutput 1 Treat any compiler output (e.g. a warning) as an error
461 1.1 christos #
462 1.1 christos # Unless '-source' or '-sourcefile' is specified, the C program looks like:
463 1.1 christos #
464 1.1 christos ## #include <firstinclude> /* same for remaining includes in the list */
465 1.1 christos ## declare-code /* any code in -declare, verbatim */
466 1.1 christos ## int main(void) {
467 1.1 christos ## code /* any code in -code, verbatim */
468 1.1 christos ## return 0;
469 1.1 christos ## }
470 1.1 christos #
471 1.1 christos # And the command line looks like:
472 1.1 christos #
473 1.1 christos ## CC -cflags CFLAGS CPPFLAGS conftest.c -o conftest.o
474 1.1 christos ## CXX -cflags CXXFLAGS CPPFLAGS conftest.cpp -o conftest.o
475 1.1 christos #
476 1.1 christos # And if linking:
477 1.1 christos #
478 1.1 christos ## CC LDFLAGS -cflags CFLAGS conftest.c -o conftest -libs LIBS
479 1.1 christos ## CXX LDFLAGS -cflags CXXFLAGS conftest.c -o conftest -libs LIBS
480 1.1 christos #
481 1.1 christos # Any failures are recorded in 'config.log'
482 1.1 christos #
483 1.1 christos proc cctest {args} {
484 1.1 christos set tmp conftest__
485 1.1 christos
486 1.1 christos # Easiest way to merge in the settings
487 1.1 christos cc-with $args {
488 1.1 christos array set opts [cc-get-settings]
489 1.1 christos }
490 1.1 christos
491 1.1 christos if {[info exists opts(-sourcefile)]} {
492 1.1 christos set opts(-source) [readfile [get-define srcdir]/$opts(-sourcefile) "#error can't find $opts(-sourcefile)"]
493 1.1 christos }
494 1.1 christos if {[info exists opts(-source)]} {
495 1.1 christos set lines $opts(-source)
496 1.1 christos } else {
497 1.1 christos foreach i $opts(-includes) {
498 1.1 christos if {$opts(-code) ne "" && ![feature-checked $i]} {
499 1.1 christos # Compiling real code with an unchecked header file
500 1.1 christos # Quickly (and silently) check for it now
501 1.1 christos
502 1.1 christos # Remove all -includes from settings before checking
503 1.1 christos set saveopts [cc-update-settings -includes {}]
504 1.1 christos msg-quiet cc-check-includes $i
505 1.1 christos cc-store-settings $saveopts
506 1.1 christos }
507 1.1 christos if {$opts(-code) eq "" || [have-feature $i]} {
508 1.1 christos lappend source "#include <$i>"
509 1.1 christos }
510 1.1 christos }
511 1.1 christos lappend source {*}$opts(-declare)
512 1.1 christos lappend source "int main(void) {"
513 1.1 christos lappend source $opts(-code)
514 1.1 christos lappend source "return 0;"
515 1.1 christos lappend source "}"
516 1.1 christos
517 1.1 christos set lines [join $source \n]
518 1.1 christos }
519 1.1 christos
520 1.1 christos # Build the command line
521 1.1 christos set cmdline {}
522 1.1 christos lappend cmdline {*}[get-define CCACHE]
523 1.1 christos switch -exact -- $opts(-lang) {
524 1.1 christos c++ {
525 1.1 christos set src conftest__.cpp
526 1.1 christos lappend cmdline {*}[get-define CXX]
527 1.1 christos set cflags [get-define CXXFLAGS]
528 1.1 christos }
529 1.1 christos c {
530 1.1 christos set src conftest__.c
531 1.1 christos lappend cmdline {*}[get-define CC]
532 1.1 christos set cflags [get-define CFLAGS]
533 1.1 christos }
534 1.1 christos default {
535 1.1 christos autosetup-error "cctest called with unknown language: $opts(-lang)"
536 1.1 christos }
537 1.1 christos }
538 1.1 christos
539 1.1 christos if {$opts(-link)} {
540 1.1 christos lappend cmdline {*}[get-define LDFLAGS]
541 1.1 christos } else {
542 1.1 christos lappend cflags {*}[get-define CPPFLAGS]
543 1.1 christos set tmp conftest__.o
544 1.1 christos lappend cmdline -c
545 1.1 christos }
546 1.1 christos lappend cmdline {*}$opts(-cflags) {*}[get-define cc-default-debug ""] {*}$cflags
547 1.1 christos lappend cmdline $src -o $tmp
548 1.1 christos if {$opts(-link)} {
549 1.1 christos lappend cmdline {*}$opts(-libs) {*}[get-define LIBS]
550 1.1 christos }
551 1.1 christos
552 1.1 christos # At this point we have the complete command line and the
553 1.1 christos # complete source to be compiled. Get the result from cache if
554 1.1 christos # we can
555 1.1 christos if {[info exists ::cc_cache($cmdline,$lines)]} {
556 1.1 christos msg-checking "(cached) "
557 1.1 christos set ok $::cc_cache($cmdline,$lines)
558 1.1 christos if {$::autosetup(debug)} {
559 1.1 christos configlog "From cache (ok=$ok): [join $cmdline]"
560 1.1 christos configlog "============"
561 1.1 christos configlog $lines
562 1.1 christos configlog "============"
563 1.1 christos }
564 1.1 christos return $ok
565 1.1 christos }
566 1.1 christos
567 1.1 christos writefile $src $lines\n
568 1.1 christos
569 1.1 christos set ok 1
570 1.1 christos set err [catch {exec-with-stderr {*}$cmdline} result errinfo]
571 1.1 christos if {$err || ($opts(-nooutput) && [string length $result])} {
572 1.1 christos configlog "Failed: [join $cmdline]"
573 1.1 christos configlog $result
574 1.1 christos configlog "============"
575 1.1 christos configlog "The failed code was:"
576 1.1 christos configlog $lines
577 1.1 christos configlog "============"
578 1.1 christos set ok 0
579 1.1 christos } elseif {$::autosetup(debug)} {
580 1.1 christos configlog "Compiled OK: [join $cmdline]"
581 1.1 christos configlog "============"
582 1.1 christos configlog $lines
583 1.1 christos configlog "============"
584 1.1 christos }
585 1.1 christos file delete $src
586 1.1 christos file delete $tmp
587 1.1 christos
588 1.1 christos # cache it
589 1.1 christos set ::cc_cache($cmdline,$lines) $ok
590 1.1 christos
591 1.1 christos return $ok
592 1.1 christos }
593 1.1 christos
594 1.1 christos # @make-autoconf-h outfile ?auto-patterns=HAVE_*? ?bare-patterns=SIZEOF_*?
595 1.1 christos #
596 1.1 christos # Deprecated - see 'make-config-header'
597 1.1 christos proc make-autoconf-h {file {autopatterns {HAVE_*}} {barepatterns {SIZEOF_* HAVE_DECL_*}}} {
598 1.1 christos user-notice "*** make-autoconf-h is deprecated -- use make-config-header instead"
599 1.1 christos make-config-header $file -auto $autopatterns -bare $barepatterns
600 1.1 christos }
601 1.1 christos
602 1.1 christos # @make-config-header outfile ?-auto patternlist? ?-bare patternlist? ?-none patternlist? ?-str patternlist? ...
603 1.1 christos #
604 1.1 christos # Examines all defined variables which match the given patterns
605 1.1 christos # and writes an include file, '$file', which defines each of these.
606 1.1 christos # Variables which match '-auto' are output as follows:
607 1.1 christos # - defines which have the value '0' are ignored.
608 1.1 christos # - defines which have integer values are defined as the integer value.
609 1.1 christos # - any other value is defined as a string, e.g. '"value"'
610 1.1 christos # Variables which match '-bare' are defined as-is.
611 1.1 christos # Variables which match '-str' are defined as a string, e.g. '"value"'
612 1.1 christos # Variables which match '-none' are omitted.
613 1.1 christos #
614 1.1 christos # Note that order is important. The first pattern that matches is selected.
615 1.1 christos # Default behaviour is:
616 1.1 christos #
617 1.1 christos ## -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_* -none *
618 1.1 christos #
619 1.1 christos # If the file would be unchanged, it is not written.
620 1.1 christos proc make-config-header {file args} {
621 1.1 christos set guard _[string toupper [regsub -all {[^a-zA-Z0-9]} [file tail $file] _]]
622 1.1 christos file mkdir [file dirname $file]
623 1.1 christos set lines {}
624 1.1 christos lappend lines "#ifndef $guard"
625 1.1 christos lappend lines "#define $guard"
626 1.1 christos
627 1.1 christos # Add some defaults
628 1.1 christos lappend args -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_*
629 1.1 christos
630 1.1 christos foreach n [lsort [dict keys [all-defines]]] {
631 1.1 christos set value [get-define $n]
632 1.1 christos set type [calc-define-output-type $n $args]
633 1.1 christos switch -exact -- $type {
634 1.1 christos -bare {
635 1.1 christos # Just output the value unchanged
636 1.1 christos }
637 1.1 christos -none {
638 1.1 christos continue
639 1.1 christos }
640 1.1 christos -str {
641 1.1 christos set value \"[string map [list \\ \\\\ \" \\\"] $value]\"
642 1.1 christos }
643 1.1 christos -auto {
644 1.1 christos # Automatically determine the type
645 1.1 christos if {$value eq "0"} {
646 1.1 christos lappend lines "/* #undef $n */"
647 1.1 christos continue
648 1.1 christos }
649 1.1 christos if {![string is integer -strict $value]} {
650 1.1 christos set value \"[string map [list \\ \\\\ \" \\\"] $value]\"
651 1.1 christos }
652 1.1 christos }
653 1.1 christos "" {
654 1.1 christos continue
655 1.1 christos }
656 1.1 christos default {
657 1.1 christos autosetup-error "Unknown type in make-config-header: $type"
658 1.1 christos }
659 1.1 christos }
660 1.1 christos lappend lines "#define $n $value"
661 1.1 christos }
662 1.1 christos lappend lines "#endif"
663 1.1 christos set buf [join $lines \n]
664 1.1 christos write-if-changed $file $buf {
665 1.1 christos msg-result "Created $file"
666 1.1 christos }
667 1.1 christos }
668 1.1 christos
669 1.1 christos proc calc-define-output-type {name spec} {
670 1.1 christos foreach {type patterns} $spec {
671 1.1 christos foreach pattern $patterns {
672 1.1 christos if {[string match $pattern $name]} {
673 1.1 christos return $type
674 1.1 christos }
675 1.1 christos }
676 1.1 christos }
677 1.1 christos return ""
678 1.1 christos }
679 1.1 christos
680 1.1 christos proc cc-init {} {
681 1.1 christos global autosetup
682 1.1 christos
683 1.1 christos # Initialise some values from the environment or commandline or default settings
684 1.1 christos foreach i {LDFLAGS LIBS CPPFLAGS LINKFLAGS CFLAGS} {
685 1.1 christos lassign $i var default
686 1.1 christos define $var [get-env $var $default]
687 1.1 christos }
688 1.1 christos
689 1.1 christos if {[env-is-set CC]} {
690 1.1 christos # Set by the user, so don't try anything else
691 1.1 christos set try [list [get-env CC ""]]
692 1.1 christos } else {
693 1.1 christos # Try some reasonable options
694 1.1 christos set try [list [get-define cross]cc [get-define cross]gcc]
695 1.1 christos }
696 1.1 christos define CC [find-an-executable {*}$try]
697 1.1 christos if {[get-define CC] eq ""} {
698 1.1 christos user-error "Could not find a C compiler. Tried: [join $try ", "]"
699 1.1 christos }
700 1.1 christos
701 1.1 christos define CPP [get-env CPP "[get-define CC] -E"]
702 1.1 christos
703 1.1 christos # XXX: Could avoid looking for a C++ compiler until requested
704 1.1 christos # If CXX isn't found, it is set to the empty string.
705 1.1 christos if {[env-is-set CXX]} {
706 1.1 christos define CXX [find-an-executable -required [get-env CXX ""]]
707 1.1 christos } else {
708 1.1 christos define CXX [find-an-executable [get-define cross]c++ [get-define cross]g++]
709 1.1 christos }
710 1.1 christos
711 1.1 christos # CXXFLAGS default to CFLAGS if not specified
712 1.1 christos define CXXFLAGS [get-env CXXFLAGS [get-define CFLAGS]]
713 1.1 christos
714 1.1 christos # May need a CC_FOR_BUILD, so look for one
715 1.1 christos define CC_FOR_BUILD [find-an-executable [get-env CC_FOR_BUILD ""] cc gcc false]
716 1.1 christos
717 1.1 christos # These start empty and never come from the user or environment
718 1.1 christos define AS_CFLAGS ""
719 1.1 christos define AS_CPPFLAGS ""
720 1.1 christos define AS_CXXFLAGS ""
721 1.1 christos
722 1.1 christos define CCACHE [find-an-executable [get-env CCACHE ccache]]
723 1.1 christos
724 1.1 christos # If any of these are set in the environment, propagate them to the AUTOREMAKE commandline
725 1.1 christos foreach i {CC CXX CCACHE CPP CFLAGS CXXFLAGS CXXFLAGS LDFLAGS LIBS CROSS CPPFLAGS LINKFLAGS CC_FOR_BUILD LD} {
726 1.1 christos if {[env-is-set $i]} {
727 1.1 christos # Note: If the variable is set on the command line, get-env will return that value
728 1.1 christos # so the command line will continue to override the environment
729 1.1 christos define-append-argv AUTOREMAKE $i=[get-env $i ""]
730 1.1 christos }
731 1.1 christos }
732 1.1 christos
733 1.1 christos # Initial cctest settings
734 1.1 christos cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {} -nooutput 0}
735 1.1 christos set autosetup(cc-include-deps) {}
736 1.1 christos
737 1.1 christos msg-result "C compiler...[get-define CCACHE] [get-define CC] [get-define CFLAGS] [get-define CPPFLAGS]"
738 1.1 christos if {[get-define CXX] ne "false"} {
739 1.1 christos msg-result "C++ compiler...[get-define CCACHE] [get-define CXX] [get-define CXXFLAGS] [get-define CPPFLAGS]"
740 1.1 christos }
741 1.1 christos msg-result "Build C compiler...[get-define CC_FOR_BUILD]"
742 1.1 christos
743 1.1 christos # On Darwin, we prefer to use -g0 to avoid creating .dSYM directories
744 1.1 christos # but some compilers may not support it, so test here.
745 1.1 christos switch -glob -- [get-define host] {
746 1.1 christos *-*-darwin* {
747 1.1 christos if {[cctest -cflags {-g0}]} {
748 1.1 christos define cc-default-debug -g0
749 1.1 christos }
750 1.1 christos }
751 1.1 christos }
752 1.1 christos
753 1.1 christos if {![cc-check-includes stdlib.h]} {
754 1.1 christos user-error "Compiler does not work. See config.log"
755 1.1 christos }
756 1.1 christos }
757 1.1 christos
758 1.1 christos cc-init
759