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