Package SCons :: Module Conftest
[hide private]
[frames] | no frames]

Source Code for Module SCons.Conftest

  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.SetLIBS(value) 
 70  #                       Set LIBS to "value".  The type of "value" is what 
 71  #                       AppendLIBS() returned. 
 72  #                       Return the value of LIBS before changing it (any type 
 73  #                       can be used, it is passed to SetLIBS() later. 
 74  # 
 75  # context.headerfilename 
 76  #                       Name of file to append configure results to, usually 
 77  #                       "confdefs.h". 
 78  #                       The file must not exist or be empty when starting. 
 79  #                       Empty or None to skip this (some tests will not work!). 
 80  # 
 81  # context.config_h      (may be missing). If present, must be a string, which 
 82  #                       will be filled with the contents of a config_h file. 
 83  # 
 84  # context.vardict       Dictionary holding variables used for the tests and 
 85  #                       stores results from the tests, used for the build 
 86  #                       commands. 
 87  #                       Normally contains "CC", "LIBS", "CPPFLAGS", etc. 
 88  # 
 89  # context.havedict      Dictionary holding results from the tests that are to 
 90  #                       be used inside a program. 
 91  #                       Names often start with "HAVE_".  These are zero 
 92  #                       (feature not present) or one (feature present).  Other 
 93  #                       variables may have any value, e.g., "PERLVERSION" can 
 94  #                       be a number and "SYSTEMNAME" a string. 
 95  # 
 96   
 97  import re 
 98  import string 
 99  from types import IntType 
100   
101  # 
102  # PUBLIC VARIABLES 
103  # 
104   
105  LogInputFiles = 1    # Set that to log the input files in case of a failed test 
106  LogErrorMessages = 1 # Set that to log Conftest-generated error messages 
107   
108  # 
109  # PUBLIC FUNCTIONS 
110  # 
111   
112  # Generic remarks: 
113  # - When a language is specified which is not supported the test fails.  The 
114  #   message is a bit different, because not all the arguments for the normal 
115  #   message are available yet (chicken-egg problem). 
116   
117   
118 -def CheckBuilder(context, text = None, language = None):
119 """ 120 Configure check to see if the compiler works. 121 Note that this uses the current value of compiler and linker flags, make 122 sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly. 123 "language" should be "C" or "C++" and is used to select the compiler. 124 Default is "C". 125 "text" may be used to specify the code to be build. 126 Returns an empty string for success, an error message for failure. 127 """ 128 lang, suffix, msg = _lang2suffix(language) 129 if msg: 130 context.Display("%s\n" % msg) 131 return msg 132 133 if not text: 134 text = """ 135 int main() { 136 return 0; 137 } 138 """ 139 140 context.Display("Checking if building a %s file works... " % lang) 141 ret = context.BuildProg(text, suffix) 142 _YesNoResult(context, ret, None, text) 143 return ret
144 145
146 -def CheckFunc(context, function_name, header = None, language = None):
147 """ 148 Configure check for a function "function_name". 149 "language" should be "C" or "C++" and is used to select the compiler. 150 Default is "C". 151 Optional "header" can be defined to define a function prototype, include a 152 header file or anything else that comes before main(). 153 Sets HAVE_function_name in context.havedict according to the result. 154 Note that this uses the current value of compiler and linker flags, make 155 sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly. 156 Returns an empty string for success, an error message for failure. 157 """ 158 159 # Remarks from autoconf: 160 # - Don't include <ctype.h> because on OSF/1 3.0 it includes <sys/types.h> 161 # which includes <sys/select.h> which contains a prototype for select. 162 # Similarly for bzero. 163 # - assert.h is included to define __stub macros and hopefully few 164 # prototypes, which can conflict with char $1(); below. 165 # - Override any gcc2 internal prototype to avoid an error. 166 # - We use char for the function declaration because int might match the 167 # return type of a gcc2 builtin and then its argument prototype would 168 # still apply. 169 # - The GNU C library defines this for functions which it implements to 170 # always fail with ENOSYS. Some functions are actually named something 171 # starting with __ and the normal name is an alias. 172 173 if context.headerfilename: 174 includetext = '#include "%s"' % context.headerfilename 175 else: 176 includetext = '' 177 if not header: 178 header = """ 179 #ifdef __cplusplus 180 extern "C" 181 #endif 182 char %s();""" % function_name 183 184 lang, suffix, msg = _lang2suffix(language) 185 if msg: 186 context.Display("Cannot check for %s(): %s\n" % (function_name, msg)) 187 return msg 188 189 text = """ 190 %(include)s 191 #include <assert.h> 192 %(hdr)s 193 194 int main() { 195 #if defined (__stub_%(name)s) || defined (__stub___%(name)s) 196 fail fail fail 197 #else 198 %(name)s(); 199 #endif 200 201 return 0; 202 } 203 """ % { 'name': function_name, 204 'include': includetext, 205 'hdr': header } 206 207 context.Display("Checking for %s function %s()... " % (lang, function_name)) 208 ret = context.BuildProg(text, suffix) 209 _YesNoResult(context, ret, "HAVE_" + function_name, text, 210 "Define to 1 if the system has the function `%s'." %\ 211 function_name) 212 return ret
213 214
215 -def CheckHeader(context, header_name, header = None, language = None, 216 include_quotes = None):
217 """ 218 Configure check for a C or C++ header file "header_name". 219 Optional "header" can be defined to do something before including the 220 header file (unusual, supported for consistency). 221 "language" should be "C" or "C++" and is used to select the compiler. 222 Default is "C". 223 Sets HAVE_header_name in context.havedict according to the result. 224 Note that this uses the current value of compiler and linker flags, make 225 sure $CFLAGS and $CPPFLAGS are set correctly. 226 Returns an empty string for success, an error message for failure. 227 """ 228 # Why compile the program instead of just running the preprocessor? 229 # It is possible that the header file exists, but actually using it may 230 # fail (e.g., because it depends on other header files). Thus this test is 231 # more strict. It may require using the "header" argument. 232 # 233 # Use <> by default, because the check is normally used for system header 234 # files. SCons passes '""' to overrule this. 235 236 # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H. 237 if context.headerfilename: 238 includetext = '#include "%s"\n' % context.headerfilename 239 else: 240 includetext = '' 241 if not header: 242 header = "" 243 244 lang, suffix, msg = _lang2suffix(language) 245 if msg: 246 context.Display("Cannot check for header file %s: %s\n" 247 % (header_name, msg)) 248 return msg 249 250 if not include_quotes: 251 include_quotes = "<>" 252 253 text = "%s%s\n#include %s%s%s\n\n" % (includetext, header, 254 include_quotes[0], header_name, include_quotes[1]) 255 256 context.Display("Checking for %s header file %s... " % (lang, header_name)) 257 ret = context.CompileProg(text, suffix) 258 _YesNoResult(context, ret, "HAVE_" + header_name, text, 259 "Define to 1 if you have the <%s> header file." % header_name) 260 return ret
261 262
263 -def CheckType(context, type_name, fallback = None, 264 header = None, language = None):
265 """ 266 Configure check for a C or C++ type "type_name". 267 Optional "header" can be defined to include a header file. 268 "language" should be "C" or "C++" and is used to select the compiler. 269 Default is "C". 270 Sets HAVE_type_name in context.havedict according to the result. 271 Note that this uses the current value of compiler and linker flags, make 272 sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly. 273 Returns an empty string for success, an error message for failure. 274 """ 275 276 # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H. 277 if context.headerfilename: 278 includetext = '#include "%s"' % context.headerfilename 279 else: 280 includetext = '' 281 if not header: 282 header = "" 283 284 lang, suffix, msg = _lang2suffix(language) 285 if msg: 286 context.Display("Cannot check for %s type: %s\n" % (type_name, msg)) 287 return msg 288 289 # Remarks from autoconf about this test: 290 # - Grepping for the type in include files is not reliable (grep isn't 291 # portable anyway). 292 # - Using "TYPE my_var;" doesn't work for const qualified types in C++. 293 # Adding an initializer is not valid for some C++ classes. 294 # - Using the type as parameter to a function either fails for K&$ C or for 295 # C++. 296 # - Using "TYPE *my_var;" is valid in C for some types that are not 297 # declared (struct something). 298 # - Using "sizeof(TYPE)" is valid when TYPE is actually a variable. 299 # - Using the previous two together works reliably. 300 text = """ 301 %(include)s 302 %(header)s 303 304 int main() { 305 if ((%(name)s *) 0) 306 return 0; 307 if (sizeof (%(name)s)) 308 return 0; 309 } 310 """ % { 'include': includetext, 311 'header': header, 312 'name': type_name } 313 314 context.Display("Checking for %s type %s... " % (lang, type_name)) 315 ret = context.BuildProg(text, suffix) 316 _YesNoResult(context, ret, "HAVE_" + type_name, text, 317 "Define to 1 if the system has the type `%s'." % type_name) 318 if ret and fallback and context.headerfilename: 319 f = open(context.headerfilename, "a") 320 f.write("typedef %s %s;\n" % (fallback, type_name)) 321 f.close() 322 323 return ret
324
325 -def CheckTypeSize(context, type_name, header = None, language = None, expect = None):
326 """This check can be used to get the size of a given type, or to check whether 327 the type is of expected size. 328 329 Arguments: 330 - type : str 331 the type to check 332 - includes : sequence 333 list of headers to include in the test code before testing the type 334 - language : str 335 'C' or 'C++' 336 - expect : int 337 if given, will test wether the type has the given number of bytes. 338 If not given, will automatically find the size. 339 340 Returns: 341 status : int 342 0 if the check failed, or the found size of the type if the check succeeded.""" 343 344 # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H. 345 if context.headerfilename: 346 includetext = '#include "%s"' % context.headerfilename 347 else: 348 includetext = '' 349 350 if not header: 351 header = "" 352 353 lang, suffix, msg = _lang2suffix(language) 354 if msg: 355 context.Display("Cannot check for %s type: %s\n" % (type_name, msg)) 356 return msg 357 358 src = includetext + header 359 if not expect is None: 360 # Only check if the given size is the right one 361 context.Display('Checking %s is %d bytes... ' % (type_name, expect)) 362 363 # test code taken from autoconf: this is a pretty clever hack to find that 364 # a type is of a given size using only compilation. This speeds things up 365 # quite a bit compared to straightforward code using TryRun 366 src = src + r""" 367 typedef %s scons_check_type; 368 369 int main() 370 { 371 static int test_array[1 - 2 * !(((long int) (sizeof(scons_check_type))) == %d)]; 372 test_array[0] = 0; 373 374 return 0; 375 } 376 """ 377 378 st = context.CompileProg(src % (type_name, expect), suffix) 379 if not st: 380 context.Display("yes\n") 381 _Have(context, "SIZEOF_%s" % type_name, expect, 382 "The size of `%s', as computed by sizeof." % type_name) 383 return expect 384 else: 385 context.Display("no\n") 386 _LogFailed(context, src, st) 387 return 0 388 else: 389 # Only check if the given size is the right one 390 context.Message('Checking size of %s ... ' % type_name) 391 392 # We have to be careful with the program we wish to test here since 393 # compilation will be attempted using the current environment's flags. 394 # So make sure that the program will compile without any warning. For 395 # example using: 'int main(int argc, char** argv)' will fail with the 396 # '-Wall -Werror' flags since the variables argc and argv would not be 397 # used in the program... 398 # 399 src = src + """ 400 #include <stdlib.h> 401 #include <stdio.h> 402 int main() { 403 printf("%d", (int)sizeof(""" + type_name + """)); 404 return 0; 405 } 406 """ 407 st, out = context.RunProg(src, suffix) 408 try: 409 size = int(out) 410 except ValueError: 411 # If cannot convert output of test prog to an integer (the size), 412 # something went wront, so just fail 413 st = 1 414 size = 0 415 416 if not st: 417 context.Display("yes\n") 418 _Have(context, "SIZEOF_%s" % type_name, size, 419 "The size of `%s', as computed by sizeof." % type_name) 420 return size 421 else: 422 context.Display("no\n") 423 _LogFailed(context, src, st) 424 return 0 425 426 return 0
427
428 -def CheckDeclaration(context, symbol, includes = None, language = None):
429 """Checks whether symbol is declared. 430 431 Use the same test as autoconf, that is test whether the symbol is defined 432 as a macro or can be used as an r-value. 433 434 Arguments: 435 symbol : str 436 the symbol to check 437 includes : str 438 Optional "header" can be defined to include a header file. 439 language : str 440 only C and C++ supported. 441 442 Returns: 443 status : bool 444 True if the check failed, False if succeeded.""" 445 446 # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H. 447 if context.headerfilename: 448 includetext = '#include "%s"' % context.headerfilename 449 else: 450 includetext = '' 451 452 if not includes: 453 includes = "" 454 455 lang, suffix, msg = _lang2suffix(language) 456 if msg: 457 context.Display("Cannot check for declaration %s: %s\n" % (type_name, msg)) 458 return msg 459 460 src = includetext + includes 461 context.Display('Checking whether %s is declared... ' % symbol) 462 463 src = src + r""" 464 int main() 465 { 466 #ifndef %s 467 (void) %s; 468 #endif 469 ; 470 return 0; 471 } 472 """ % (symbol, symbol) 473 474 st = context.CompileProg(src, suffix) 475 _YesNoResult(context, st, "HAVE_DECL_" + symbol, src, 476 "Set to 1 if %s is defined." % symbol) 477 return st
478
479 -def CheckLib(context, libs, func_name = None, header = None, 480 extra_libs = None, call = None, language = None, autoadd = 1):
481 """ 482 Configure check for a C or C++ libraries "libs". Searches through 483 the list of libraries, until one is found where the test succeeds. 484 Tests if "func_name" or "call" exists in the library. Note: if it exists 485 in another library the test succeeds anyway! 486 Optional "header" can be defined to include a header file. If not given a 487 default prototype for "func_name" is added. 488 Optional "extra_libs" is a list of library names to be added after 489 "lib_name" in the build command. To be used for libraries that "lib_name" 490 depends on. 491 Optional "call" replaces the call to "func_name" in the test code. It must 492 consist of complete C statements, including a trailing ";". 493 Both "func_name" and "call" arguments are optional, and in that case, just 494 linking against the libs is tested. 495 "language" should be "C" or "C++" and is used to select the compiler. 496 Default is "C". 497 Note that this uses the current value of compiler and linker flags, make 498 sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly. 499 Returns an empty string for success, an error message for failure. 500 """ 501 # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H. 502 if context.headerfilename: 503 includetext = '#include "%s"' % context.headerfilename 504 else: 505 includetext = '' 506 if not header: 507 header = "" 508 509 text = """ 510 %s 511 %s""" % (includetext, header) 512 513 # Add a function declaration if needed. 514 if func_name and func_name != "main": 515 if not header: 516 text = text + """ 517 #ifdef __cplusplus 518 extern "C" 519 #endif 520 char %s(); 521 """ % func_name 522 523 # The actual test code. 524 if not call: 525 call = "%s();" % func_name 526 527 # if no function to test, leave main() blank 528 text = text + """ 529 int 530 main() { 531 %s 532 return 0; 533 } 534 """ % (call or "") 535 536 if call: 537 i = string.find(call, "\n") 538 if i > 0: 539 calltext = call[:i] + ".." 540 elif call[-1] == ';': 541 calltext = call[:-1] 542 else: 543 calltext = call 544 545 for lib_name in libs: 546 547 lang, suffix, msg = _lang2suffix(language) 548 if msg: 549 context.Display("Cannot check for library %s: %s\n" % (lib_name, msg)) 550 return msg 551 552 # if a function was specified to run in main(), say it 553 if call: 554 context.Display("Checking for %s in %s library %s... " 555 % (calltext, lang, lib_name)) 556 # otherwise, just say the name of library and language 557 else: 558 context.Display("Checking for %s library %s... " 559 % (lang, lib_name)) 560 561 if lib_name: 562 l = [ lib_name ] 563 if extra_libs: 564 l.extend(extra_libs) 565 oldLIBS = context.AppendLIBS(l) 566 sym = "HAVE_LIB" + lib_name 567 else: 568 oldLIBS = -1 569 sym = None 570 571 ret = context.BuildProg(text, suffix) 572 573 _YesNoResult(context, ret, sym, text, 574 "Define to 1 if you have the `%s' library." % lib_name) 575 if oldLIBS != -1 and (ret or not autoadd): 576 context.SetLIBS(oldLIBS) 577 578 if not ret: 579 return ret 580 581 return ret
582 583 # 584 # END OF PUBLIC FUNCTIONS 585 # 586
587 -def _YesNoResult(context, ret, key, text, comment = None):
588 """ 589 Handle the result of a test with a "yes" or "no" result. 590 "ret" is the return value: empty if OK, error message when not. 591 "key" is the name of the symbol to be defined (HAVE_foo). 592 "text" is the source code of the program used for testing. 593 "comment" is the C comment to add above the line defining the symbol (the 594 comment is automatically put inside a /* */). If None, no comment is added. 595 """ 596 if key: 597 _Have(context, key, not ret, comment) 598 if ret: 599 context.Display("no\n") 600 _LogFailed(context, text, ret) 601 else: 602 context.Display("yes\n")
603 604
605 -def _Have(context, key, have, comment = None):
606 """ 607 Store result of a test in context.havedict and context.headerfilename. 608 "key" is a "HAVE_abc" name. It is turned into all CAPITALS and non- 609 alphanumerics are replaced by an underscore. 610 The value of "have" can be: 611 1 - Feature is defined, add "#define key". 612 0 - Feature is not defined, add "/* #undef key */". 613 Adding "undef" is what autoconf does. Not useful for the 614 compiler, but it shows that the test was done. 615 number - Feature is defined to this number "#define key have". 616 Doesn't work for 0 or 1, use a string then. 617 string - Feature is defined to this string "#define key have". 618 Give "have" as is should appear in the header file, include quotes 619 when desired and escape special characters! 620 """ 621 key_up = string.upper(key) 622 key_up = re.sub('[^A-Z0-9_]', '_', key_up) 623 context.havedict[key_up] = have 624 if have == 1: 625 line = "#define %s 1\n" % key_up 626 elif have == 0: 627 line = "/* #undef %s */\n" % key_up 628 elif type(have) == IntType: 629 line = "#define %s %d\n" % (key_up, have) 630 else: 631 line = "#define %s %s\n" % (key_up, str(have)) 632 633 if comment is not None: 634 lines = "\n/* %s */\n" % comment + line 635 else: 636 lines = "\n" + line 637 638 if context.headerfilename: 639 f = open(context.headerfilename, "a") 640 f.write(lines) 641 f.close() 642 elif hasattr(context,'config_h'): 643 context.config_h = context.config_h + lines
644 645
646 -def _LogFailed(context, text, msg):
647 """ 648 Write to the log about a failed program. 649 Add line numbers, so that error messages can be understood. 650 """ 651 if LogInputFiles: 652 context.Log("Failed program was:\n") 653 lines = string.split(text, '\n') 654 if len(lines) and lines[-1] == '': 655 lines = lines[:-1] # remove trailing empty line 656 n = 1 657 for line in lines: 658 context.Log("%d: %s\n" % (n, line)) 659 n = n + 1 660 if LogErrorMessages: 661 context.Log("Error message: %s\n" % msg)
662 663
664 -def _lang2suffix(lang):
665 """ 666 Convert a language name to a suffix. 667 When "lang" is empty or None C is assumed. 668 Returns a tuple (lang, suffix, None) when it works. 669 For an unrecognized language returns (None, None, msg). 670 Where: 671 lang = the unified language name 672 suffix = the suffix, including the leading dot 673 msg = an error message 674 """ 675 if not lang or lang in ["C", "c"]: 676 return ("C", ".c", None) 677 if lang in ["c++", "C++", "cpp", "CXX", "cxx"]: 678 return ("C++", ".cpp", None) 679 680 return None, None, "Unsupported language: %s" % lang
681 682 683 # vim: set sw=4 et sts=4 tw=79 fo+=l: 684