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