PageRenderTime 65ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

/usb-modeswitch-1.2.3/jim/autosetup/cc.tcl

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