OLD | NEW |
(Empty) | |
| 1 """SCons.Conftest |
| 2 |
| 3 Autoconf-like configuration support; low level implementation of tests. |
| 4 """ |
| 5 |
| 6 # |
| 7 # Copyright (c) 2003 Stichting NLnet Labs |
| 8 # Copyright (c) 2001, 2002, 2003 Steven Knight |
| 9 # |
| 10 # Permission is hereby granted, free of charge, to any person obtaining |
| 11 # a copy of this software and associated documentation files (the |
| 12 # "Software"), to deal in the Software without restriction, including |
| 13 # without limitation the rights to use, copy, modify, merge, publish, |
| 14 # distribute, sublicense, and/or sell copies of the Software, and to |
| 15 # permit persons to whom the Software is furnished to do so, subject to |
| 16 # the following conditions: |
| 17 # |
| 18 # The above copyright notice and this permission notice shall be included |
| 19 # in all copies or substantial portions of the Software. |
| 20 # |
| 21 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY |
| 22 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
| 23 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 24 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
| 25 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| 26 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| 27 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 28 # |
| 29 |
| 30 # |
| 31 # The purpose of this module is to define how a check is to be performed. |
| 32 # Use one of the Check...() functions below. |
| 33 # |
| 34 |
| 35 # |
| 36 # A context class is used that defines functions for carrying out the tests, |
| 37 # logging and messages. The following methods and members must be present: |
| 38 # |
| 39 # context.Display(msg) Function called to print messages that are normally |
| 40 # displayed for the user. Newlines are explicitly used. |
| 41 # The text should also be written to the logfile! |
| 42 # |
| 43 # context.Log(msg) Function called to write to a log file. |
| 44 # |
| 45 # context.BuildProg(text, ext) |
| 46 # Function called to build a program, using "ext" for the |
| 47 # file extention. Must return an empty string for |
| 48 # success, an error message for failure. |
| 49 # For reliable test results building should be done just |
| 50 # like an actual program would be build, using the same |
| 51 # command and arguments (including configure results so |
| 52 # far). |
| 53 # |
| 54 # context.CompileProg(text, ext) |
| 55 # Function called to compile a program, using "ext" for |
| 56 # the file extention. Must return an empty string for |
| 57 # success, an error message for failure. |
| 58 # For reliable test results compiling should be done just |
| 59 # like an actual source file would be compiled, using the |
| 60 # same command and arguments (including configure results |
| 61 # so far). |
| 62 # |
| 63 # context.AppendLIBS(lib_name_list) |
| 64 # Append "lib_name_list" to the value of LIBS. |
| 65 # "lib_namelist" is a list of strings. |
| 66 # Return the value of LIBS before changing it (any type |
| 67 # can be used, it is passed to SetLIBS() later.) |
| 68 # |
| 69 # context.PrependLIBS(lib_name_list) |
| 70 # Prepend "lib_name_list" to the value of LIBS. |
| 71 # "lib_namelist" is a list of strings. |
| 72 # Return the value of LIBS before changing it (any type |
| 73 # can be used, it is passed to SetLIBS() later.) |
| 74 # |
| 75 # context.SetLIBS(value) |
| 76 # Set LIBS to "value". The type of "value" is what |
| 77 # AppendLIBS() returned. |
| 78 # Return the value of LIBS before changing it (any type |
| 79 # can be used, it is passed to SetLIBS() later.) |
| 80 # |
| 81 # context.headerfilename |
| 82 # Name of file to append configure results to, usually |
| 83 # "confdefs.h". |
| 84 # The file must not exist or be empty when starting. |
| 85 # Empty or None to skip this (some tests will not work!). |
| 86 # |
| 87 # context.config_h (may be missing). If present, must be a string, which |
| 88 # will be filled with the contents of a config_h file. |
| 89 # |
| 90 # context.vardict Dictionary holding variables used for the tests and |
| 91 # stores results from the tests, used for the build |
| 92 # commands. |
| 93 # Normally contains "CC", "LIBS", "CPPFLAGS", etc. |
| 94 # |
| 95 # context.havedict Dictionary holding results from the tests that are to |
| 96 # be used inside a program. |
| 97 # Names often start with "HAVE_". These are zero |
| 98 # (feature not present) or one (feature present). Other |
| 99 # variables may have any value, e.g., "PERLVERSION" can |
| 100 # be a number and "SYSTEMNAME" a string. |
| 101 # |
| 102 |
| 103 import re |
| 104 from types import IntType |
| 105 |
| 106 # |
| 107 # PUBLIC VARIABLES |
| 108 # |
| 109 |
| 110 LogInputFiles = 1 # Set that to log the input files in case of a failed test |
| 111 LogErrorMessages = 1 # Set that to log Conftest-generated error messages |
| 112 |
| 113 # |
| 114 # PUBLIC FUNCTIONS |
| 115 # |
| 116 |
| 117 # Generic remarks: |
| 118 # - When a language is specified which is not supported the test fails. The |
| 119 # message is a bit different, because not all the arguments for the normal |
| 120 # message are available yet (chicken-egg problem). |
| 121 |
| 122 |
| 123 def CheckBuilder(context, text = None, language = None): |
| 124 """ |
| 125 Configure check to see if the compiler works. |
| 126 Note that this uses the current value of compiler and linker flags, make |
| 127 sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly. |
| 128 "language" should be "C" or "C++" and is used to select the compiler. |
| 129 Default is "C". |
| 130 "text" may be used to specify the code to be build. |
| 131 Returns an empty string for success, an error message for failure. |
| 132 """ |
| 133 lang, suffix, msg = _lang2suffix(language) |
| 134 if msg: |
| 135 context.Display("%s\n" % msg) |
| 136 return msg |
| 137 |
| 138 if not text: |
| 139 text = """ |
| 140 int main() { |
| 141 return 0; |
| 142 } |
| 143 """ |
| 144 |
| 145 context.Display("Checking if building a %s file works... " % lang) |
| 146 ret = context.BuildProg(text, suffix) |
| 147 _YesNoResult(context, ret, None, text) |
| 148 return ret |
| 149 |
| 150 def CheckCC(context): |
| 151 """ |
| 152 Configure check for a working C compiler. |
| 153 |
| 154 This checks whether the C compiler, as defined in the $CC construction |
| 155 variable, can compile a C source file. It uses the current $CCCOM value |
| 156 too, so that it can test against non working flags. |
| 157 |
| 158 """ |
| 159 context.Display("Checking whether the C compiler works") |
| 160 text = """ |
| 161 int main() |
| 162 { |
| 163 return 0; |
| 164 } |
| 165 """ |
| 166 ret = _check_empty_program(context, 'CC', text, 'C') |
| 167 _YesNoResult(context, ret, None, text) |
| 168 return ret |
| 169 |
| 170 def CheckSHCC(context): |
| 171 """ |
| 172 Configure check for a working shared C compiler. |
| 173 |
| 174 This checks whether the C compiler, as defined in the $SHCC construction |
| 175 variable, can compile a C source file. It uses the current $SHCCCOM value |
| 176 too, so that it can test against non working flags. |
| 177 |
| 178 """ |
| 179 context.Display("Checking whether the (shared) C compiler works") |
| 180 text = """ |
| 181 int foo() |
| 182 { |
| 183 return 0; |
| 184 } |
| 185 """ |
| 186 ret = _check_empty_program(context, 'SHCC', text, 'C', use_shared = True) |
| 187 _YesNoResult(context, ret, None, text) |
| 188 return ret |
| 189 |
| 190 def CheckCXX(context): |
| 191 """ |
| 192 Configure check for a working CXX compiler. |
| 193 |
| 194 This checks whether the CXX compiler, as defined in the $CXX construction |
| 195 variable, can compile a CXX source file. It uses the current $CXXCOM value |
| 196 too, so that it can test against non working flags. |
| 197 |
| 198 """ |
| 199 context.Display("Checking whether the C++ compiler works") |
| 200 text = """ |
| 201 int main() |
| 202 { |
| 203 return 0; |
| 204 } |
| 205 """ |
| 206 ret = _check_empty_program(context, 'CXX', text, 'C++') |
| 207 _YesNoResult(context, ret, None, text) |
| 208 return ret |
| 209 |
| 210 def CheckSHCXX(context): |
| 211 """ |
| 212 Configure check for a working shared CXX compiler. |
| 213 |
| 214 This checks whether the CXX compiler, as defined in the $SHCXX construction |
| 215 variable, can compile a CXX source file. It uses the current $SHCXXCOM value |
| 216 too, so that it can test against non working flags. |
| 217 |
| 218 """ |
| 219 context.Display("Checking whether the (shared) C++ compiler works") |
| 220 text = """ |
| 221 int main() |
| 222 { |
| 223 return 0; |
| 224 } |
| 225 """ |
| 226 ret = _check_empty_program(context, 'SHCXX', text, 'C++', use_shared = True) |
| 227 _YesNoResult(context, ret, None, text) |
| 228 return ret |
| 229 |
| 230 def _check_empty_program(context, comp, text, language, use_shared = False): |
| 231 """Return 0 on success, 1 otherwise.""" |
| 232 if comp not in context.env or not context.env[comp]: |
| 233 # The compiler construction variable is not set or empty |
| 234 return 1 |
| 235 |
| 236 lang, suffix, msg = _lang2suffix(language) |
| 237 if msg: |
| 238 return 1 |
| 239 |
| 240 if use_shared: |
| 241 return context.CompileSharedObject(text, suffix) |
| 242 else: |
| 243 return context.CompileProg(text, suffix) |
| 244 |
| 245 |
| 246 def CheckFunc(context, function_name, header = None, language = None): |
| 247 """ |
| 248 Configure check for a function "function_name". |
| 249 "language" should be "C" or "C++" and is used to select the compiler. |
| 250 Default is "C". |
| 251 Optional "header" can be defined to define a function prototype, include a |
| 252 header file or anything else that comes before main(). |
| 253 Sets HAVE_function_name in context.havedict according to the result. |
| 254 Note that this uses the current value of compiler and linker flags, make |
| 255 sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly. |
| 256 Returns an empty string for success, an error message for failure. |
| 257 """ |
| 258 |
| 259 # Remarks from autoconf: |
| 260 # - Don't include <ctype.h> because on OSF/1 3.0 it includes <sys/types.h> |
| 261 # which includes <sys/select.h> which contains a prototype for select. |
| 262 # Similarly for bzero. |
| 263 # - assert.h is included to define __stub macros and hopefully few |
| 264 # prototypes, which can conflict with char $1(); below. |
| 265 # - Override any gcc2 internal prototype to avoid an error. |
| 266 # - We use char for the function declaration because int might match the |
| 267 # return type of a gcc2 builtin and then its argument prototype would |
| 268 # still apply. |
| 269 # - The GNU C library defines this for functions which it implements to |
| 270 # always fail with ENOSYS. Some functions are actually named something |
| 271 # starting with __ and the normal name is an alias. |
| 272 |
| 273 if context.headerfilename: |
| 274 includetext = '#include "%s"' % context.headerfilename |
| 275 else: |
| 276 includetext = '' |
| 277 if not header: |
| 278 header = """ |
| 279 #ifdef __cplusplus |
| 280 extern "C" |
| 281 #endif |
| 282 char %s();""" % function_name |
| 283 |
| 284 lang, suffix, msg = _lang2suffix(language) |
| 285 if msg: |
| 286 context.Display("Cannot check for %s(): %s\n" % (function_name, msg)) |
| 287 return msg |
| 288 |
| 289 text = """ |
| 290 %(include)s |
| 291 #include <assert.h> |
| 292 %(hdr)s |
| 293 |
| 294 int main() { |
| 295 #if defined (__stub_%(name)s) || defined (__stub___%(name)s) |
| 296 fail fail fail |
| 297 #else |
| 298 %(name)s(); |
| 299 #endif |
| 300 |
| 301 return 0; |
| 302 } |
| 303 """ % { 'name': function_name, |
| 304 'include': includetext, |
| 305 'hdr': header } |
| 306 |
| 307 context.Display("Checking for %s function %s()... " % (lang, function_name)) |
| 308 ret = context.BuildProg(text, suffix) |
| 309 _YesNoResult(context, ret, "HAVE_" + function_name, text, |
| 310 "Define to 1 if the system has the function `%s'." %\ |
| 311 function_name) |
| 312 return ret |
| 313 |
| 314 |
| 315 def CheckHeader(context, header_name, header = None, language = None, |
| 316 include_quotes = None): |
| 317 """ |
| 318 Configure check for a C or C++ header file "header_name". |
| 319 Optional "header" can be defined to do something before including the |
| 320 header file (unusual, supported for consistency). |
| 321 "language" should be "C" or "C++" and is used to select the compiler. |
| 322 Default is "C". |
| 323 Sets HAVE_header_name in context.havedict according to the result. |
| 324 Note that this uses the current value of compiler and linker flags, make |
| 325 sure $CFLAGS and $CPPFLAGS are set correctly. |
| 326 Returns an empty string for success, an error message for failure. |
| 327 """ |
| 328 # Why compile the program instead of just running the preprocessor? |
| 329 # It is possible that the header file exists, but actually using it may |
| 330 # fail (e.g., because it depends on other header files). Thus this test is |
| 331 # more strict. It may require using the "header" argument. |
| 332 # |
| 333 # Use <> by default, because the check is normally used for system header |
| 334 # files. SCons passes '""' to overrule this. |
| 335 |
| 336 # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H. |
| 337 if context.headerfilename: |
| 338 includetext = '#include "%s"\n' % context.headerfilename |
| 339 else: |
| 340 includetext = '' |
| 341 if not header: |
| 342 header = "" |
| 343 |
| 344 lang, suffix, msg = _lang2suffix(language) |
| 345 if msg: |
| 346 context.Display("Cannot check for header file %s: %s\n" |
| 347 % (header_name, msg)) |
| 348 return msg |
| 349 |
| 350 if not include_quotes: |
| 351 include_quotes = "<>" |
| 352 |
| 353 text = "%s%s\n#include %s%s%s\n\n" % (includetext, header, |
| 354 include_quotes[0], header_name, include_quotes[1]) |
| 355 |
| 356 context.Display("Checking for %s header file %s... " % (lang, header_name)) |
| 357 ret = context.CompileProg(text, suffix) |
| 358 _YesNoResult(context, ret, "HAVE_" + header_name, text, |
| 359 "Define to 1 if you have the <%s> header file." % header_name) |
| 360 return ret |
| 361 |
| 362 |
| 363 def CheckType(context, type_name, fallback = None, |
| 364 header = None, language = None): |
| 365 """ |
| 366 Configure check for a C or C++ type "type_name". |
| 367 Optional "header" can be defined to include a header file. |
| 368 "language" should be "C" or "C++" and is used to select the compiler. |
| 369 Default is "C". |
| 370 Sets HAVE_type_name in context.havedict according to the result. |
| 371 Note that this uses the current value of compiler and linker flags, make |
| 372 sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly. |
| 373 Returns an empty string for success, an error message for failure. |
| 374 """ |
| 375 |
| 376 # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H. |
| 377 if context.headerfilename: |
| 378 includetext = '#include "%s"' % context.headerfilename |
| 379 else: |
| 380 includetext = '' |
| 381 if not header: |
| 382 header = "" |
| 383 |
| 384 lang, suffix, msg = _lang2suffix(language) |
| 385 if msg: |
| 386 context.Display("Cannot check for %s type: %s\n" % (type_name, msg)) |
| 387 return msg |
| 388 |
| 389 # Remarks from autoconf about this test: |
| 390 # - Grepping for the type in include files is not reliable (grep isn't |
| 391 # portable anyway). |
| 392 # - Using "TYPE my_var;" doesn't work for const qualified types in C++. |
| 393 # Adding an initializer is not valid for some C++ classes. |
| 394 # - Using the type as parameter to a function either fails for K&$ C or for |
| 395 # C++. |
| 396 # - Using "TYPE *my_var;" is valid in C for some types that are not |
| 397 # declared (struct something). |
| 398 # - Using "sizeof(TYPE)" is valid when TYPE is actually a variable. |
| 399 # - Using the previous two together works reliably. |
| 400 text = """ |
| 401 %(include)s |
| 402 %(header)s |
| 403 |
| 404 int main() { |
| 405 if ((%(name)s *) 0) |
| 406 return 0; |
| 407 if (sizeof (%(name)s)) |
| 408 return 0; |
| 409 } |
| 410 """ % { 'include': includetext, |
| 411 'header': header, |
| 412 'name': type_name } |
| 413 |
| 414 context.Display("Checking for %s type %s... " % (lang, type_name)) |
| 415 ret = context.BuildProg(text, suffix) |
| 416 _YesNoResult(context, ret, "HAVE_" + type_name, text, |
| 417 "Define to 1 if the system has the type `%s'." % type_name) |
| 418 if ret and fallback and context.headerfilename: |
| 419 f = open(context.headerfilename, "a") |
| 420 f.write("typedef %s %s;\n" % (fallback, type_name)) |
| 421 f.close() |
| 422 |
| 423 return ret |
| 424 |
| 425 def CheckTypeSize(context, type_name, header = None, language = None, expect = N
one): |
| 426 """This check can be used to get the size of a given type, or to check wheth
er |
| 427 the type is of expected size. |
| 428 |
| 429 Arguments: |
| 430 - type : str |
| 431 the type to check |
| 432 - includes : sequence |
| 433 list of headers to include in the test code before testing the type |
| 434 - language : str |
| 435 'C' or 'C++' |
| 436 - expect : int |
| 437 if given, will test wether the type has the given number of bytes. |
| 438 If not given, will automatically find the size. |
| 439 |
| 440 Returns: |
| 441 status : int |
| 442 0 if the check failed, or the found size of the type if the chec
k succeeded.""" |
| 443 |
| 444 # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H. |
| 445 if context.headerfilename: |
| 446 includetext = '#include "%s"' % context.headerfilename |
| 447 else: |
| 448 includetext = '' |
| 449 |
| 450 if not header: |
| 451 header = "" |
| 452 |
| 453 lang, suffix, msg = _lang2suffix(language) |
| 454 if msg: |
| 455 context.Display("Cannot check for %s type: %s\n" % (type_name, msg)) |
| 456 return msg |
| 457 |
| 458 src = includetext + header |
| 459 if not expect is None: |
| 460 # Only check if the given size is the right one |
| 461 context.Display('Checking %s is %d bytes... ' % (type_name, expect)) |
| 462 |
| 463 # test code taken from autoconf: this is a pretty clever hack to find th
at |
| 464 # a type is of a given size using only compilation. This speeds things u
p |
| 465 # quite a bit compared to straightforward code using TryRun |
| 466 src = src + r""" |
| 467 typedef %s scons_check_type; |
| 468 |
| 469 int main() |
| 470 { |
| 471 static int test_array[1 - 2 * !(((long int) (sizeof(scons_check_type))) == %
d)]; |
| 472 test_array[0] = 0; |
| 473 |
| 474 return 0; |
| 475 } |
| 476 """ |
| 477 |
| 478 st = context.CompileProg(src % (type_name, expect), suffix) |
| 479 if not st: |
| 480 context.Display("yes\n") |
| 481 _Have(context, "SIZEOF_%s" % type_name, expect, |
| 482 "The size of `%s', as computed by sizeof." % type_name) |
| 483 return expect |
| 484 else: |
| 485 context.Display("no\n") |
| 486 _LogFailed(context, src, st) |
| 487 return 0 |
| 488 else: |
| 489 # Only check if the given size is the right one |
| 490 context.Message('Checking size of %s ... ' % type_name) |
| 491 |
| 492 # We have to be careful with the program we wish to test here since |
| 493 # compilation will be attempted using the current environment's flags. |
| 494 # So make sure that the program will compile without any warning. For |
| 495 # example using: 'int main(int argc, char** argv)' will fail with the |
| 496 # '-Wall -Werror' flags since the variables argc and argv would not be |
| 497 # used in the program... |
| 498 # |
| 499 src = src + """ |
| 500 #include <stdlib.h> |
| 501 #include <stdio.h> |
| 502 int main() { |
| 503 printf("%d", (int)sizeof(""" + type_name + """)); |
| 504 return 0; |
| 505 } |
| 506 """ |
| 507 st, out = context.RunProg(src, suffix) |
| 508 try: |
| 509 size = int(out) |
| 510 except ValueError: |
| 511 # If cannot convert output of test prog to an integer (the size), |
| 512 # something went wront, so just fail |
| 513 st = 1 |
| 514 size = 0 |
| 515 |
| 516 if not st: |
| 517 context.Display("yes\n") |
| 518 _Have(context, "SIZEOF_%s" % type_name, size, |
| 519 "The size of `%s', as computed by sizeof." % type_name) |
| 520 return size |
| 521 else: |
| 522 context.Display("no\n") |
| 523 _LogFailed(context, src, st) |
| 524 return 0 |
| 525 |
| 526 return 0 |
| 527 |
| 528 def CheckDeclaration(context, symbol, includes = None, language = None): |
| 529 """Checks whether symbol is declared. |
| 530 |
| 531 Use the same test as autoconf, that is test whether the symbol is defined |
| 532 as a macro or can be used as an r-value. |
| 533 |
| 534 Arguments: |
| 535 symbol : str |
| 536 the symbol to check |
| 537 includes : str |
| 538 Optional "header" can be defined to include a header file. |
| 539 language : str |
| 540 only C and C++ supported. |
| 541 |
| 542 Returns: |
| 543 status : bool |
| 544 True if the check failed, False if succeeded.""" |
| 545 |
| 546 # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H. |
| 547 if context.headerfilename: |
| 548 includetext = '#include "%s"' % context.headerfilename |
| 549 else: |
| 550 includetext = '' |
| 551 |
| 552 if not includes: |
| 553 includes = "" |
| 554 |
| 555 lang, suffix, msg = _lang2suffix(language) |
| 556 if msg: |
| 557 context.Display("Cannot check for declaration %s: %s\n" % (type_name, ms
g)) |
| 558 return msg |
| 559 |
| 560 src = includetext + includes |
| 561 context.Display('Checking whether %s is declared... ' % symbol) |
| 562 |
| 563 src = src + r""" |
| 564 int main() |
| 565 { |
| 566 #ifndef %s |
| 567 (void) %s; |
| 568 #endif |
| 569 ; |
| 570 return 0; |
| 571 } |
| 572 """ % (symbol, symbol) |
| 573 |
| 574 st = context.CompileProg(src, suffix) |
| 575 _YesNoResult(context, st, "HAVE_DECL_" + symbol, src, |
| 576 "Set to 1 if %s is defined." % symbol) |
| 577 return st |
| 578 |
| 579 def CheckLib(context, libs, func_name = None, header = None, |
| 580 extra_libs = None, call = None, language = None, autoadd = 1, |
| 581 append = True): |
| 582 """ |
| 583 Configure check for a C or C++ libraries "libs". Searches through |
| 584 the list of libraries, until one is found where the test succeeds. |
| 585 Tests if "func_name" or "call" exists in the library. Note: if it exists |
| 586 in another library the test succeeds anyway! |
| 587 Optional "header" can be defined to include a header file. If not given a |
| 588 default prototype for "func_name" is added. |
| 589 Optional "extra_libs" is a list of library names to be added after |
| 590 "lib_name" in the build command. To be used for libraries that "lib_name" |
| 591 depends on. |
| 592 Optional "call" replaces the call to "func_name" in the test code. It must |
| 593 consist of complete C statements, including a trailing ";". |
| 594 Both "func_name" and "call" arguments are optional, and in that case, just |
| 595 linking against the libs is tested. |
| 596 "language" should be "C" or "C++" and is used to select the compiler. |
| 597 Default is "C". |
| 598 Note that this uses the current value of compiler and linker flags, make |
| 599 sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly. |
| 600 Returns an empty string for success, an error message for failure. |
| 601 """ |
| 602 # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H. |
| 603 if context.headerfilename: |
| 604 includetext = '#include "%s"' % context.headerfilename |
| 605 else: |
| 606 includetext = '' |
| 607 if not header: |
| 608 header = "" |
| 609 |
| 610 text = """ |
| 611 %s |
| 612 %s""" % (includetext, header) |
| 613 |
| 614 # Add a function declaration if needed. |
| 615 if func_name and func_name != "main": |
| 616 if not header: |
| 617 text = text + """ |
| 618 #ifdef __cplusplus |
| 619 extern "C" |
| 620 #endif |
| 621 char %s(); |
| 622 """ % func_name |
| 623 |
| 624 # The actual test code. |
| 625 if not call: |
| 626 call = "%s();" % func_name |
| 627 |
| 628 # if no function to test, leave main() blank |
| 629 text = text + """ |
| 630 int |
| 631 main() { |
| 632 %s |
| 633 return 0; |
| 634 } |
| 635 """ % (call or "") |
| 636 |
| 637 if call: |
| 638 i = call.find("\n") |
| 639 if i > 0: |
| 640 calltext = call[:i] + ".." |
| 641 elif call[-1] == ';': |
| 642 calltext = call[:-1] |
| 643 else: |
| 644 calltext = call |
| 645 |
| 646 for lib_name in libs: |
| 647 |
| 648 lang, suffix, msg = _lang2suffix(language) |
| 649 if msg: |
| 650 context.Display("Cannot check for library %s: %s\n" % (lib_name, msg
)) |
| 651 return msg |
| 652 |
| 653 # if a function was specified to run in main(), say it |
| 654 if call: |
| 655 context.Display("Checking for %s in %s library %s... " |
| 656 % (calltext, lang, lib_name)) |
| 657 # otherwise, just say the name of library and language |
| 658 else: |
| 659 context.Display("Checking for %s library %s... " |
| 660 % (lang, lib_name)) |
| 661 |
| 662 if lib_name: |
| 663 l = [ lib_name ] |
| 664 if extra_libs: |
| 665 l.extend(extra_libs) |
| 666 if append: |
| 667 oldLIBS = context.AppendLIBS(l) |
| 668 else: |
| 669 oldLIBS = context.PrependLIBS(l) |
| 670 sym = "HAVE_LIB" + lib_name |
| 671 else: |
| 672 oldLIBS = -1 |
| 673 sym = None |
| 674 |
| 675 ret = context.BuildProg(text, suffix) |
| 676 |
| 677 _YesNoResult(context, ret, sym, text, |
| 678 "Define to 1 if you have the `%s' library." % lib_name) |
| 679 if oldLIBS != -1 and (ret or not autoadd): |
| 680 context.SetLIBS(oldLIBS) |
| 681 |
| 682 if not ret: |
| 683 return ret |
| 684 |
| 685 return ret |
| 686 |
| 687 # |
| 688 # END OF PUBLIC FUNCTIONS |
| 689 # |
| 690 |
| 691 def _YesNoResult(context, ret, key, text, comment = None): |
| 692 """ |
| 693 Handle the result of a test with a "yes" or "no" result. |
| 694 "ret" is the return value: empty if OK, error message when not. |
| 695 "key" is the name of the symbol to be defined (HAVE_foo). |
| 696 "text" is the source code of the program used for testing. |
| 697 "comment" is the C comment to add above the line defining the symbol (the |
| 698 comment is automatically put inside a /* */). If None, no comment is added. |
| 699 """ |
| 700 if key: |
| 701 _Have(context, key, not ret, comment) |
| 702 if ret: |
| 703 context.Display("no\n") |
| 704 _LogFailed(context, text, ret) |
| 705 else: |
| 706 context.Display("yes\n") |
| 707 |
| 708 |
| 709 def _Have(context, key, have, comment = None): |
| 710 """ |
| 711 Store result of a test in context.havedict and context.headerfilename. |
| 712 "key" is a "HAVE_abc" name. It is turned into all CAPITALS and non- |
| 713 alphanumerics are replaced by an underscore. |
| 714 The value of "have" can be: |
| 715 1 - Feature is defined, add "#define key". |
| 716 0 - Feature is not defined, add "/* #undef key */". |
| 717 Adding "undef" is what autoconf does. Not useful for the |
| 718 compiler, but it shows that the test was done. |
| 719 number - Feature is defined to this number "#define key have". |
| 720 Doesn't work for 0 or 1, use a string then. |
| 721 string - Feature is defined to this string "#define key have". |
| 722 Give "have" as is should appear in the header file, include quotes |
| 723 when desired and escape special characters! |
| 724 """ |
| 725 key_up = key.upper() |
| 726 key_up = re.sub('[^A-Z0-9_]', '_', key_up) |
| 727 context.havedict[key_up] = have |
| 728 if have == 1: |
| 729 line = "#define %s 1\n" % key_up |
| 730 elif have == 0: |
| 731 line = "/* #undef %s */\n" % key_up |
| 732 elif isinstance(have, IntType): |
| 733 line = "#define %s %d\n" % (key_up, have) |
| 734 else: |
| 735 line = "#define %s %s\n" % (key_up, str(have)) |
| 736 |
| 737 if comment is not None: |
| 738 lines = "\n/* %s */\n" % comment + line |
| 739 else: |
| 740 lines = "\n" + line |
| 741 |
| 742 if context.headerfilename: |
| 743 f = open(context.headerfilename, "a") |
| 744 f.write(lines) |
| 745 f.close() |
| 746 elif hasattr(context,'config_h'): |
| 747 context.config_h = context.config_h + lines |
| 748 |
| 749 |
| 750 def _LogFailed(context, text, msg): |
| 751 """ |
| 752 Write to the log about a failed program. |
| 753 Add line numbers, so that error messages can be understood. |
| 754 """ |
| 755 if LogInputFiles: |
| 756 context.Log("Failed program was:\n") |
| 757 lines = text.split('\n') |
| 758 if len(lines) and lines[-1] == '': |
| 759 lines = lines[:-1] # remove trailing empty line |
| 760 n = 1 |
| 761 for line in lines: |
| 762 context.Log("%d: %s\n" % (n, line)) |
| 763 n = n + 1 |
| 764 if LogErrorMessages: |
| 765 context.Log("Error message: %s\n" % msg) |
| 766 |
| 767 |
| 768 def _lang2suffix(lang): |
| 769 """ |
| 770 Convert a language name to a suffix. |
| 771 When "lang" is empty or None C is assumed. |
| 772 Returns a tuple (lang, suffix, None) when it works. |
| 773 For an unrecognized language returns (None, None, msg). |
| 774 Where: |
| 775 lang = the unified language name |
| 776 suffix = the suffix, including the leading dot |
| 777 msg = an error message |
| 778 """ |
| 779 if not lang or lang in ["C", "c"]: |
| 780 return ("C", ".c", None) |
| 781 if lang in ["c++", "C++", "cpp", "CXX", "cxx"]: |
| 782 return ("C++", ".cpp", None) |
| 783 |
| 784 return None, None, "Unsupported language: %s" % lang |
| 785 |
| 786 |
| 787 # vim: set sw=4 et sts=4 tw=79 fo+=l: |
| 788 |
| 789 # Local Variables: |
| 790 # tab-width:4 |
| 791 # indent-tabs-mode:nil |
| 792 # End: |
| 793 # vim: set expandtab tabstop=4 shiftwidth=4: |
OLD | NEW |