Home | History | Annotate | Line # | Download | only in autosetup
cc.tcl revision 1.1
      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 proc cc-init {} {
    681 	global autosetup
    682 
    683 	# Initialise some values from the environment or commandline or default settings
    684 	foreach i {LDFLAGS LIBS CPPFLAGS LINKFLAGS CFLAGS} {
    685 		lassign $i var default
    686 		define $var [get-env $var $default]
    687 	}
    688 
    689 	if {[env-is-set CC]} {
    690 		# Set by the user, so don't try anything else
    691 		set try [list [get-env CC ""]]
    692 	} else {
    693 		# Try some reasonable options
    694 		set try [list [get-define cross]cc [get-define cross]gcc]
    695 	}
    696 	define CC [find-an-executable {*}$try]
    697 	if {[get-define CC] eq ""} {
    698 		user-error "Could not find a C compiler. Tried: [join $try ", "]"
    699 	}
    700 
    701 	define CPP [get-env CPP "[get-define CC] -E"]
    702 
    703 	# XXX: Could avoid looking for a C++ compiler until requested
    704 	# If CXX isn't found, it is set to the empty string.
    705 	if {[env-is-set CXX]} {
    706 		define CXX [find-an-executable -required [get-env CXX ""]]
    707 	} else {
    708 		define CXX [find-an-executable [get-define cross]c++ [get-define cross]g++]
    709 	}
    710 
    711 	# CXXFLAGS default to CFLAGS if not specified
    712 	define CXXFLAGS [get-env CXXFLAGS [get-define CFLAGS]]
    713 
    714 	# May need a CC_FOR_BUILD, so look for one
    715 	define CC_FOR_BUILD [find-an-executable [get-env CC_FOR_BUILD ""] cc gcc false]
    716 
    717 	# These start empty and never come from the user or environment
    718 	define AS_CFLAGS ""
    719 	define AS_CPPFLAGS ""
    720 	define AS_CXXFLAGS ""
    721 
    722 	define CCACHE [find-an-executable [get-env CCACHE ccache]]
    723 
    724 	# If any of these are set in the environment, propagate them to the AUTOREMAKE commandline
    725 	foreach i {CC CXX CCACHE CPP CFLAGS CXXFLAGS CXXFLAGS LDFLAGS LIBS CROSS CPPFLAGS LINKFLAGS CC_FOR_BUILD LD} {
    726 		if {[env-is-set $i]} {
    727 			# Note: If the variable is set on the command line, get-env will return that value
    728 			# so the command line will continue to override the environment
    729 			define-append-argv AUTOREMAKE $i=[get-env $i ""]
    730 		}
    731 	}
    732 
    733 	# Initial cctest settings
    734 	cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {} -nooutput 0}
    735 	set autosetup(cc-include-deps) {}
    736 
    737 	msg-result "C compiler...[get-define CCACHE] [get-define CC] [get-define CFLAGS] [get-define CPPFLAGS]"
    738 	if {[get-define CXX] ne "false"} {
    739 		msg-result "C++ compiler...[get-define CCACHE] [get-define CXX] [get-define CXXFLAGS] [get-define CPPFLAGS]"
    740 	}
    741 	msg-result "Build C compiler...[get-define CC_FOR_BUILD]"
    742 
    743 	# On Darwin, we prefer to use -g0 to avoid creating .dSYM directories
    744 	# but some compilers may not support it, so test here.
    745 	switch -glob -- [get-define host] {
    746 		*-*-darwin* {
    747 			if {[cctest -cflags {-g0}]} {
    748 				define cc-default-debug -g0
    749 			}
    750 		}
    751 	}
    752 
    753 	if {![cc-check-includes stdlib.h]} {
    754 		user-error "Compiler does not work. See config.log"
    755 	}
    756 }
    757 
    758 cc-init
    759