1# a waf tool to add autoconf-like macros to the configure section 2 3import os, sys 4from waflib import Build, Options, Logs, Context 5from waflib.Configure import conf 6from waflib.TaskGen import feature 7from waflib.Tools import c_preproc as preproc 8from samba_utils import TO_LIST, GET_TARGET_TYPE, SET_TARGET_TYPE, unique_list, mkdir_p 9 10missing_headers = set() 11 12#################################################### 13# some autoconf like helpers, to make the transition 14# to waf a bit easier for those used to autoconf 15# m4 files 16 17@conf 18def DEFINE(conf, d, v, add_to_cflags=False, quote=False): 19 '''define a config option''' 20 conf.define(d, v, quote=quote) 21 if add_to_cflags: 22 conf.env.append_value('CFLAGS', '-D%s=%s' % (d, str(v))) 23 24def hlist_to_string(conf, headers=None): 25 '''convert a headers list to a set of #include lines''' 26 hlist = conf.env.hlist 27 if headers: 28 hlist = hlist[:] 29 hlist.extend(TO_LIST(headers)) 30 hdrs = "\n".join('#include <%s>' % h for h in hlist) 31 32 return hdrs 33 34 35@conf 36def COMPOUND_START(conf, msg): 37 '''start a compound test''' 38 def null_check_message_1(self,*k,**kw): 39 return 40 def null_check_message_2(self,*k,**kw): 41 return 42 43 v = getattr(conf.env, 'in_compound', []) 44 if v != [] and v != 0: 45 conf.env.in_compound = v + 1 46 return 47 conf.start_msg(msg) 48 conf.saved_check_message_1 = conf.start_msg 49 conf.start_msg = null_check_message_1 50 conf.saved_check_message_2 = conf.end_msg 51 conf.end_msg = null_check_message_2 52 conf.env.in_compound = 1 53 54 55@conf 56def COMPOUND_END(conf, result): 57 '''start a compound test''' 58 conf.env.in_compound -= 1 59 if conf.env.in_compound != 0: 60 return 61 conf.start_msg = conf.saved_check_message_1 62 conf.end_msg = conf.saved_check_message_2 63 p = conf.end_msg 64 if result is True: 65 p('ok') 66 elif not result: 67 p('not found', 'YELLOW') 68 else: 69 p(result) 70 71 72@feature('nolink') 73def nolink(self): 74 '''using the nolink type in conf.check() allows us to avoid 75 the link stage of a test, thus speeding it up for tests 76 that where linking is not needed''' 77 pass 78 79 80def CHECK_HEADER(conf, h, add_headers=False, lib=None): 81 '''check for a header''' 82 if h in missing_headers and lib is None: 83 return False 84 d = h.upper().replace('/', '_') 85 d = d.replace('.', '_') 86 d = d.replace('-', '_') 87 d = 'HAVE_%s' % d 88 if CONFIG_SET(conf, d): 89 if add_headers: 90 if not h in conf.env.hlist: 91 conf.env.hlist.append(h) 92 return True 93 94 (ccflags, ldflags, cpppath) = library_flags(conf, lib) 95 96 hdrs = hlist_to_string(conf, headers=h) 97 if lib is None: 98 lib = "" 99 ret = conf.check(fragment='%s\nint main(void) { return 0; }\n' % hdrs, 100 type='nolink', 101 execute=0, 102 cflags=ccflags, 103 mandatory=False, 104 includes=cpppath, 105 uselib=lib.upper(), 106 msg="Checking for header %s" % h) 107 if not ret: 108 missing_headers.add(h) 109 return False 110 111 conf.DEFINE(d, 1) 112 if add_headers and not h in conf.env.hlist: 113 conf.env.hlist.append(h) 114 return ret 115 116 117@conf 118def CHECK_HEADERS(conf, headers, add_headers=False, together=False, lib=None): 119 '''check for a list of headers 120 121 when together==True, then the headers accumulate within this test. 122 This is useful for interdependent headers 123 ''' 124 ret = True 125 if not add_headers and together: 126 saved_hlist = conf.env.hlist[:] 127 set_add_headers = True 128 else: 129 set_add_headers = add_headers 130 for hdr in TO_LIST(headers): 131 if not CHECK_HEADER(conf, hdr, set_add_headers, lib=lib): 132 ret = False 133 if not add_headers and together: 134 conf.env.hlist = saved_hlist 135 return ret 136 137 138def header_list(conf, headers=None, lib=None): 139 '''form a list of headers which exist, as a string''' 140 hlist=[] 141 if headers is not None: 142 for h in TO_LIST(headers): 143 if CHECK_HEADER(conf, h, add_headers=False, lib=lib): 144 hlist.append(h) 145 return hlist_to_string(conf, headers=hlist) 146 147 148@conf 149def CHECK_TYPE(conf, t, alternate=None, headers=None, define=None, lib=None, msg=None): 150 '''check for a single type''' 151 if define is None: 152 define = 'HAVE_' + t.upper().replace(' ', '_') 153 if msg is None: 154 msg='Checking for %s' % t 155 ret = CHECK_CODE(conf, '%s _x' % t, 156 define, 157 execute=False, 158 headers=headers, 159 local_include=False, 160 msg=msg, 161 lib=lib, 162 link=False) 163 if not ret and alternate: 164 conf.DEFINE(t, alternate) 165 return ret 166 167 168@conf 169def CHECK_TYPES(conf, list, headers=None, define=None, alternate=None, lib=None): 170 '''check for a list of types''' 171 ret = True 172 for t in TO_LIST(list): 173 if not CHECK_TYPE(conf, t, headers=headers, 174 define=define, alternate=alternate, lib=lib): 175 ret = False 176 return ret 177 178 179@conf 180def CHECK_TYPE_IN(conf, t, headers=None, alternate=None, define=None): 181 '''check for a single type with a header''' 182 return CHECK_TYPE(conf, t, headers=headers, alternate=alternate, define=define) 183 184 185@conf 186def CHECK_VARIABLE(conf, v, define=None, always=False, 187 headers=None, msg=None, lib=None): 188 '''check for a variable declaration (or define)''' 189 if define is None: 190 define = 'HAVE_%s' % v.upper() 191 192 if msg is None: 193 msg="Checking for variable %s" % v 194 195 return CHECK_CODE(conf, 196 # we need to make sure the compiler doesn't 197 # optimize it out... 198 ''' 199 #ifndef %s 200 void *_x; _x=(void *)&%s; return (int)_x; 201 #endif 202 return 0 203 ''' % (v, v), 204 execute=False, 205 link=False, 206 msg=msg, 207 local_include=False, 208 lib=lib, 209 headers=headers, 210 define=define, 211 always=always) 212 213 214@conf 215def CHECK_DECLS(conf, vars, reverse=False, headers=None, always=False): 216 '''check a list of variable declarations, using the HAVE_DECL_xxx form 217 of define 218 219 When reverse==True then use HAVE_xxx_DECL instead of HAVE_DECL_xxx 220 ''' 221 ret = True 222 for v in TO_LIST(vars): 223 if not reverse: 224 define='HAVE_DECL_%s' % v.upper() 225 else: 226 define='HAVE_%s_DECL' % v.upper() 227 if not CHECK_VARIABLE(conf, v, 228 define=define, 229 headers=headers, 230 msg='Checking for declaration of %s' % v, 231 always=always): 232 if not CHECK_CODE(conf, 233 ''' 234 return (int)%s; 235 ''' % (v), 236 execute=False, 237 link=False, 238 msg='Checking for declaration of %s (as enum)' % v, 239 local_include=False, 240 headers=headers, 241 define=define, 242 always=always): 243 ret = False 244 return ret 245 246 247def CHECK_FUNC(conf, f, link=True, lib=None, headers=None): 248 '''check for a function''' 249 define='HAVE_%s' % f.upper() 250 251 ret = False 252 253 in_lib_str = "" 254 if lib: 255 in_lib_str = " in %s" % lib 256 conf.COMPOUND_START('Checking for %s%s' % (f, in_lib_str)) 257 258 if link is None or link: 259 ret = CHECK_CODE(conf, 260 # this is based on the autoconf strategy 261 ''' 262 #define %s __fake__%s 263 #ifdef HAVE_LIMITS_H 264 # include <limits.h> 265 #else 266 # include <assert.h> 267 #endif 268 #undef %s 269 #if defined __stub_%s || defined __stub___%s 270 #error "bad glibc stub" 271 #endif 272 extern char %s(); 273 int main() { return %s(); } 274 ''' % (f, f, f, f, f, f, f), 275 execute=False, 276 link=True, 277 addmain=False, 278 add_headers=False, 279 define=define, 280 local_include=False, 281 lib=lib, 282 headers=headers, 283 msg='Checking for %s' % f) 284 285 if not ret: 286 ret = CHECK_CODE(conf, 287 # it might be a macro 288 # we need to make sure the compiler doesn't 289 # optimize it out... 290 'void *__x = (void *)%s; return (int)__x' % f, 291 execute=False, 292 link=True, 293 addmain=True, 294 add_headers=True, 295 define=define, 296 local_include=False, 297 lib=lib, 298 headers=headers, 299 msg='Checking for macro %s' % f) 300 301 if not ret and (link is None or not link): 302 ret = CHECK_VARIABLE(conf, f, 303 define=define, 304 headers=headers, 305 msg='Checking for declaration of %s' % f) 306 conf.COMPOUND_END(ret) 307 return ret 308 309 310@conf 311def CHECK_FUNCS(conf, list, link=True, lib=None, headers=None): 312 '''check for a list of functions''' 313 ret = True 314 for f in TO_LIST(list): 315 if not CHECK_FUNC(conf, f, link=link, lib=lib, headers=headers): 316 ret = False 317 return ret 318 319 320@conf 321def CHECK_SIZEOF(conf, vars, headers=None, define=None, critical=True): 322 '''check the size of a type''' 323 for v in TO_LIST(vars): 324 v_define = define 325 ret = False 326 if v_define is None: 327 v_define = 'SIZEOF_%s' % v.upper().replace(' ', '_') 328 for size in list((1, 2, 4, 8, 16, 32, 64)): 329 if CHECK_CODE(conf, 330 'static int test_array[1 - 2 * !(((long int)(sizeof(%s))) <= %d)];' % (v, size), 331 define=v_define, 332 quote=False, 333 headers=headers, 334 local_include=False, 335 msg="Checking if size of %s == %d" % (v, size)): 336 conf.DEFINE(v_define, size) 337 ret = True 338 break 339 if not ret and critical: 340 Logs.error("Couldn't determine size of '%s'" % v) 341 sys.exit(1) 342 return ret 343 344@conf 345def CHECK_VALUEOF(conf, v, headers=None, define=None): 346 '''check the value of a variable/define''' 347 ret = True 348 v_define = define 349 if v_define is None: 350 v_define = 'VALUEOF_%s' % v.upper().replace(' ', '_') 351 if CHECK_CODE(conf, 352 'printf("%%u", (unsigned)(%s))' % v, 353 define=v_define, 354 execute=True, 355 define_ret=True, 356 quote=False, 357 headers=headers, 358 local_include=False, 359 msg="Checking value of %s" % v): 360 return int(conf.env[v_define]) 361 362 return None 363 364@conf 365def CHECK_CODE(conf, code, define, 366 always=False, execute=False, addmain=True, 367 add_headers=True, mandatory=False, 368 headers=None, msg=None, cflags='', includes='# .', 369 local_include=True, lib=None, link=True, 370 define_ret=False, quote=False, 371 on_target=True, strict=False): 372 '''check if some code compiles and/or runs''' 373 374 if CONFIG_SET(conf, define): 375 return True 376 377 if headers is not None: 378 CHECK_HEADERS(conf, headers=headers, lib=lib) 379 380 if add_headers: 381 hdrs = header_list(conf, headers=headers, lib=lib) 382 else: 383 hdrs = '' 384 if execute: 385 execute = 1 386 else: 387 execute = 0 388 389 if addmain: 390 fragment='%s\n int main(void) { %s; return 0; }\n' % (hdrs, code) 391 else: 392 fragment='%s\n%s\n' % (hdrs, code) 393 394 if msg is None: 395 msg="Checking for %s" % define 396 397 cflags = TO_LIST(cflags) 398 399 # Be strict when relying on a compiler check 400 # Some compilers (e.g. xlc) ignore non-supported features as warnings 401 if strict: 402 if 'WERROR_CFLAGS' in conf.env: 403 cflags.extend(conf.env['WERROR_CFLAGS']) 404 405 if local_include: 406 cflags.append('-I%s' % conf.path.abspath()) 407 408 if not link: 409 type='nolink' 410 else: 411 type='cprogram' 412 413 uselib = TO_LIST(lib) 414 415 (ccflags, ldflags, cpppath) = library_flags(conf, uselib) 416 417 includes = TO_LIST(includes) 418 includes.extend(cpppath) 419 420 uselib = [l.upper() for l in uselib] 421 422 cflags.extend(ccflags) 423 424 if on_target: 425 test_args = conf.SAMBA_CROSS_ARGS(msg=msg) 426 else: 427 test_args = [] 428 429 conf.COMPOUND_START(msg) 430 431 try: 432 ret = conf.check(fragment=fragment, 433 execute=execute, 434 define_name = define, 435 cflags=cflags, 436 ldflags=ldflags, 437 includes=includes, 438 uselib=uselib, 439 type=type, 440 msg=msg, 441 quote=quote, 442 test_args=test_args, 443 define_ret=define_ret) 444 except Exception: 445 if always: 446 conf.DEFINE(define, 0) 447 else: 448 conf.undefine(define) 449 conf.COMPOUND_END(False) 450 if mandatory: 451 raise 452 return False 453 else: 454 # Success is indicated by ret but we should unset 455 # defines set by WAF's c_config.check() because it 456 # defines it to int(ret) and we want to undefine it 457 if not ret: 458 conf.undefine(define) 459 conf.COMPOUND_END(False) 460 return False 461 if not define_ret: 462 conf.DEFINE(define, 1) 463 conf.COMPOUND_END(True) 464 else: 465 conf.DEFINE(define, ret, quote=quote) 466 conf.COMPOUND_END(ret) 467 return True 468 469 470@conf 471def CHECK_STRUCTURE_MEMBER(conf, structname, member, 472 always=False, define=None, headers=None, 473 lib=None): 474 '''check for a structure member''' 475 if define is None: 476 define = 'HAVE_%s' % member.upper() 477 return CHECK_CODE(conf, 478 '%s s; void *_x; _x=(void *)&s.%s' % (structname, member), 479 define, 480 execute=False, 481 link=False, 482 lib=lib, 483 always=always, 484 headers=headers, 485 local_include=False, 486 msg="Checking for member %s in %s" % (member, structname)) 487 488 489@conf 490def CHECK_CFLAGS(conf, cflags, fragment='int main(void) { return 0; }\n', 491 mandatory=False): 492 '''check if the given cflags are accepted by the compiler 493 ''' 494 check_cflags = TO_LIST(cflags) 495 if 'WERROR_CFLAGS' in conf.env: 496 check_cflags.extend(conf.env['WERROR_CFLAGS']) 497 return conf.check(fragment=fragment, 498 execute=0, 499 mandatory=mandatory, 500 type='nolink', 501 cflags=check_cflags, 502 msg="Checking compiler accepts %s" % cflags) 503 504@conf 505def CHECK_LDFLAGS(conf, ldflags, 506 mandatory=False): 507 '''check if the given ldflags are accepted by the linker 508 ''' 509 return conf.check(fragment='int main(void) { return 0; }\n', 510 execute=0, 511 ldflags=ldflags, 512 mandatory=mandatory, 513 msg="Checking linker accepts %s" % ldflags) 514 515 516@conf 517def CONFIG_GET(conf, option): 518 '''return True if a configuration option was found''' 519 if (option in conf.env): 520 return conf.env[option] 521 else: 522 return None 523 524@conf 525def CONFIG_SET(conf, option): 526 '''return True if a configuration option was found''' 527 if option not in conf.env: 528 return False 529 v = conf.env[option] 530 if v is None: 531 return False 532 if v == []: 533 return False 534 if v == (): 535 return False 536 return True 537 538@conf 539def CONFIG_RESET(conf, option): 540 if option not in conf.env: 541 return 542 del conf.env[option] 543 544Build.BuildContext.CONFIG_RESET = CONFIG_RESET 545Build.BuildContext.CONFIG_SET = CONFIG_SET 546Build.BuildContext.CONFIG_GET = CONFIG_GET 547 548 549def library_flags(self, libs): 550 '''work out flags from pkg_config''' 551 ccflags = [] 552 ldflags = [] 553 cpppath = [] 554 for lib in TO_LIST(libs): 555 # note that we do not add the -I and -L in here, as that is added by the waf 556 # core. Adding it here would just change the order that it is put on the link line 557 # which can cause system paths to be added before internal libraries 558 extra_ccflags = TO_LIST(getattr(self.env, 'CFLAGS_%s' % lib.upper(), [])) 559 extra_ldflags = TO_LIST(getattr(self.env, 'LDFLAGS_%s' % lib.upper(), [])) 560 extra_cpppath = TO_LIST(getattr(self.env, 'CPPPATH_%s' % lib.upper(), [])) 561 ccflags.extend(extra_ccflags) 562 ldflags.extend(extra_ldflags) 563 cpppath.extend(extra_cpppath) 564 565 extra_cpppath = TO_LIST(getattr(self.env, 'INCLUDES_%s' % lib.upper(), [])) 566 cpppath.extend(extra_cpppath) 567 if 'EXTRA_LDFLAGS' in self.env: 568 ldflags.extend(self.env['EXTRA_LDFLAGS']) 569 570 ccflags = unique_list(ccflags) 571 ldflags = unique_list(ldflags) 572 cpppath = unique_list(cpppath) 573 return (ccflags, ldflags, cpppath) 574 575 576@conf 577def CHECK_LIB(conf, libs, mandatory=False, empty_decl=True, set_target=True, shlib=False, msg=None): 578 '''check if a set of libraries exist as system libraries 579 580 returns the sublist of libs that do exist as a syslib or [] 581 ''' 582 583 fragment= ''' 584int foo() 585{ 586 int v = 2; 587 return v*2; 588} 589''' 590 ret = [] 591 liblist = TO_LIST(libs) 592 for lib in liblist[:]: 593 if GET_TARGET_TYPE(conf, lib) == 'SYSLIB': 594 ret.append(lib) 595 continue 596 597 if msg is None: 598 msg = 'Checking for library %s' % lib 599 600 (ccflags, ldflags, cpppath) = library_flags(conf, lib) 601 602 if shlib: 603 res = conf.check(features='c cshlib', 604 fragment=fragment, 605 lib=lib, 606 uselib_store=lib, 607 cflags=ccflags, 608 ldflags=ldflags, 609 uselib=lib.upper(), 610 mandatory=False, 611 msg=msg) 612 else: 613 res = conf.check(lib=lib, 614 uselib_store=lib, 615 cflags=ccflags, 616 ldflags=ldflags, 617 uselib=lib.upper(), 618 mandatory=False, 619 msg=msg) 620 621 if not res: 622 if mandatory: 623 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list)) 624 sys.exit(1) 625 if empty_decl: 626 # if it isn't a mandatory library, then remove it from dependency lists 627 if set_target: 628 SET_TARGET_TYPE(conf, lib, 'EMPTY') 629 else: 630 conf.define('HAVE_LIB%s' % lib.upper().replace('-','_').replace('.','_'), 1) 631 conf.env['LIB_' + lib.upper()] = lib 632 if set_target: 633 conf.SET_TARGET_TYPE(lib, 'SYSLIB') 634 ret.append(lib) 635 636 return ret 637 638 639 640@conf 641def CHECK_FUNCS_IN(conf, list, library, mandatory=False, checklibc=False, 642 headers=None, link=True, empty_decl=True, set_target=True): 643 """ 644 check that the functions in 'list' are available in 'library' 645 if they are, then make that library available as a dependency 646 647 if the library is not available and mandatory==True, then 648 raise an error. 649 650 If the library is not available and mandatory==False, then 651 add the library to the list of dependencies to remove from 652 build rules 653 654 optionally check for the functions first in libc 655 """ 656 remaining = TO_LIST(list) 657 liblist = TO_LIST(library) 658 659 # check if some already found 660 for f in remaining[:]: 661 if CONFIG_SET(conf, 'HAVE_%s' % f.upper()): 662 remaining.remove(f) 663 664 # see if the functions are in libc 665 if checklibc: 666 for f in remaining[:]: 667 if CHECK_FUNC(conf, f, link=True, headers=headers): 668 remaining.remove(f) 669 670 if remaining == []: 671 for lib in liblist: 672 if GET_TARGET_TYPE(conf, lib) != 'SYSLIB' and empty_decl: 673 SET_TARGET_TYPE(conf, lib, 'EMPTY') 674 return True 675 676 checklist = conf.CHECK_LIB(liblist, empty_decl=empty_decl, set_target=set_target) 677 for lib in liblist[:]: 678 if not lib in checklist and mandatory: 679 Logs.error("Mandatory library '%s' not found for functions '%s'" % (lib, list)) 680 sys.exit(1) 681 682 ret = True 683 for f in remaining: 684 if not CHECK_FUNC(conf, f, lib=' '.join(checklist), headers=headers, link=link): 685 ret = False 686 687 return ret 688 689 690@conf 691def IN_LAUNCH_DIR(conf): 692 '''return True if this rule is being run from the launch directory''' 693 return os.path.realpath(conf.path.abspath()) == os.path.realpath(Context.launch_dir) 694Options.OptionsContext.IN_LAUNCH_DIR = IN_LAUNCH_DIR 695 696 697@conf 698def SAMBA_CONFIG_H(conf, path=None): 699 '''write out config.h in the right directory''' 700 # we don't want to produce a config.h in places like lib/replace 701 # when we are building projects that depend on lib/replace 702 if not IN_LAUNCH_DIR(conf): 703 return 704 705 # we need to build real code that can't be optimized away to test 706 stack_protect_list = ['-fstack-protector-strong', '-fstack-protector'] 707 for stack_protect_flag in stack_protect_list: 708 flag_supported = conf.check(fragment=''' 709 #include <stdio.h> 710 711 int main(void) 712 { 713 char t[100000]; 714 while (fgets(t, sizeof(t), stdin)); 715 return 0; 716 } 717 ''', 718 execute=0, 719 cflags=[ '-Werror', '-Wp,-D_FORTIFY_SOURCE=2', stack_protect_flag], 720 mandatory=False, 721 msg='Checking if compiler accepts %s' % (stack_protect_flag)) 722 if flag_supported: 723 conf.ADD_CFLAGS('%s' % (stack_protect_flag)) 724 break 725 726 flag_supported = conf.check(fragment=''' 727 #include <stdio.h> 728 729 int main(void) 730 { 731 char t[100000]; 732 while (fgets(t, sizeof(t), stdin)); 733 return 0; 734 } 735 ''', 736 execute=0, 737 cflags=[ '-Werror', '-fstack-clash-protection'], 738 mandatory=False, 739 msg='Checking if compiler accepts -fstack-clash-protection') 740 if flag_supported: 741 conf.ADD_CFLAGS('-fstack-clash-protection') 742 743 if Options.options.debug: 744 conf.ADD_CFLAGS('-g', testflags=True) 745 746 if Options.options.pidl_developer: 747 conf.env.PIDL_DEVELOPER_MODE = True 748 749 if Options.options.developer: 750 conf.env.DEVELOPER_MODE = True 751 752 conf.ADD_CFLAGS('-g', testflags=True) 753 conf.ADD_CFLAGS('-Wall', testflags=True) 754 conf.ADD_CFLAGS('-Wshadow', testflags=True) 755 conf.ADD_CFLAGS('-Wmissing-prototypes', testflags=True) 756 if CHECK_CODE(conf, 757 'struct a { int b; }; struct c { struct a d; } e = { };', 758 'CHECK_C99_INIT', 759 link=False, 760 cflags='-Wmissing-field-initializers -Werror=missing-field-initializers', 761 msg="Checking C99 init of nested structs."): 762 conf.ADD_CFLAGS('-Wmissing-field-initializers', testflags=True) 763 conf.ADD_CFLAGS('-Wformat-overflow=2', testflags=True) 764 conf.ADD_CFLAGS('-Wformat-zero-length', testflags=True) 765 conf.ADD_CFLAGS('-Wcast-align -Wcast-qual', testflags=True) 766 conf.ADD_CFLAGS('-fno-common', testflags=True) 767 768 conf.ADD_CFLAGS('-Werror=address', testflags=True) 769 # we add these here to ensure that -Wstrict-prototypes is not set during configure 770 conf.ADD_CFLAGS('-Werror=strict-prototypes -Wstrict-prototypes', 771 testflags=True) 772 conf.ADD_CFLAGS('-Werror=write-strings -Wwrite-strings', 773 testflags=True) 774 conf.ADD_CFLAGS('-Werror-implicit-function-declaration', 775 testflags=True) 776 conf.ADD_CFLAGS('-Werror=pointer-arith -Wpointer-arith', 777 testflags=True) 778 conf.ADD_CFLAGS('-Werror=declaration-after-statement -Wdeclaration-after-statement', 779 testflags=True) 780 conf.ADD_CFLAGS('-Werror=return-type -Wreturn-type', 781 testflags=True) 782 conf.ADD_CFLAGS('-Werror=uninitialized -Wuninitialized', 783 testflags=True) 784 conf.ADD_CFLAGS('-Wimplicit-fallthrough', 785 testflags=True) 786 conf.ADD_CFLAGS('-Werror=strict-overflow -Wstrict-overflow=2', 787 testflags=True) 788 789 conf.ADD_CFLAGS('-Wformat=2 -Wno-format-y2k', testflags=True) 790 conf.ADD_CFLAGS('-Wno-format-zero-length', testflags=True) 791 conf.ADD_CFLAGS('-Werror=format-security -Wformat-security', 792 testflags=True, prereq_flags='-Wformat') 793 # This check is because for ldb_search(), a NULL format string 794 # is not an error, but some compilers complain about that. 795 if CHECK_CFLAGS(conf, ["-Werror=format", "-Wformat=2"], ''' 796int testformat(char *format, ...) __attribute__ ((format (__printf__, 1, 2))); 797 798int main(void) { 799 testformat(0); 800 return 0; 801} 802 803'''): 804 if not 'EXTRA_CFLAGS' in conf.env: 805 conf.env['EXTRA_CFLAGS'] = [] 806 conf.env['EXTRA_CFLAGS'].extend(TO_LIST("-Werror=format")) 807 808 if not Options.options.disable_warnings_as_errors: 809 conf.ADD_NAMED_CFLAGS('PICKY_CFLAGS', '-Werror -Wno-error=deprecated-declarations', testflags=True) 810 conf.ADD_NAMED_CFLAGS('PICKY_CFLAGS', '-Wno-error=tautological-compare', testflags=True) 811 812 if Options.options.fatal_errors: 813 conf.ADD_CFLAGS('-Wfatal-errors', testflags=True) 814 815 if Options.options.pedantic: 816 conf.ADD_CFLAGS('-W', testflags=True) 817 818 if (Options.options.address_sanitizer or 819 Options.options.undefined_sanitizer): 820 conf.ADD_CFLAGS('-g -O1', testflags=True) 821 if Options.options.address_sanitizer: 822 conf.ADD_CFLAGS('-fno-omit-frame-pointer', testflags=True) 823 conf.ADD_CFLAGS('-fsanitize=address', testflags=True) 824 conf.ADD_LDFLAGS('-fsanitize=address', testflags=True) 825 conf.env['ADDRESS_SANITIZER'] = True 826 if Options.options.undefined_sanitizer: 827 conf.ADD_CFLAGS('-fsanitize=undefined', testflags=True) 828 conf.ADD_CFLAGS('-fsanitize=null', testflags=True) 829 conf.ADD_CFLAGS('-fsanitize=alignment', testflags=True) 830 conf.ADD_LDFLAGS('-fsanitize=undefined', testflags=True) 831 conf.env['UNDEFINED_SANITIZER'] = True 832 833 834 # Let people pass an additional ADDITIONAL_{CFLAGS,LDFLAGS} 835 # environment variables which are only used the for final build. 836 # 837 # The CFLAGS and LDFLAGS environment variables are also 838 # used for the configure checks which might impact their results. 839 # 840 # If these variables don't pass a smoke test, fail the configure 841 842 conf.add_os_flags('ADDITIONAL_CFLAGS') 843 if conf.env.ADDITIONAL_CFLAGS: 844 conf.CHECK_CFLAGS(conf.env['ADDITIONAL_CFLAGS'], 845 mandatory=True) 846 conf.env['EXTRA_CFLAGS'].extend(conf.env['ADDITIONAL_CFLAGS']) 847 848 conf.add_os_flags('ADDITIONAL_LDFLAGS') 849 if conf.env.ADDITIONAL_LDFLAGS: 850 conf.CHECK_LDFLAGS(conf.env['ADDITIONAL_LDFLAGS'], 851 mandatory=True) 852 conf.env['EXTRA_LDFLAGS'].extend(conf.env['ADDITIONAL_LDFLAGS']) 853 854 if path is None: 855 conf.write_config_header('default/config.h', top=True, remove=False) 856 else: 857 conf.write_config_header(os.path.join(conf.variant, path), remove=False) 858 for key in conf.env.define_key: 859 conf.undefine(key, from_env=False) 860 conf.env.define_key = [] 861 conf.SAMBA_CROSS_CHECK_COMPLETE() 862 863 864@conf 865def CONFIG_PATH(conf, name, default): 866 '''setup a configurable path''' 867 if not name in conf.env: 868 if default[0] == '/': 869 conf.env[name] = default 870 else: 871 conf.env[name] = conf.env['PREFIX'] + default 872 873@conf 874def ADD_NAMED_CFLAGS(conf, name, flags, testflags=False, prereq_flags=[]): 875 '''add some CFLAGS to the command line 876 optionally set testflags to ensure all the flags work 877 ''' 878 prereq_flags = TO_LIST(prereq_flags) 879 if testflags: 880 ok_flags=[] 881 for f in flags.split(): 882 if CHECK_CFLAGS(conf, [f] + prereq_flags): 883 ok_flags.append(f) 884 flags = ok_flags 885 if not name in conf.env: 886 conf.env[name] = [] 887 conf.env[name].extend(TO_LIST(flags)) 888 889@conf 890def ADD_CFLAGS(conf, flags, testflags=False, prereq_flags=[]): 891 '''add some CFLAGS to the command line 892 optionally set testflags to ensure all the flags work 893 ''' 894 ADD_NAMED_CFLAGS(conf, 'EXTRA_CFLAGS', flags, testflags=testflags, 895 prereq_flags=prereq_flags) 896 897@conf 898def ADD_LDFLAGS(conf, flags, testflags=False): 899 '''add some LDFLAGS to the command line 900 optionally set testflags to ensure all the flags work 901 902 this will return the flags that are added, if any 903 ''' 904 if testflags: 905 ok_flags=[] 906 for f in flags.split(): 907 if CHECK_LDFLAGS(conf, f): 908 ok_flags.append(f) 909 flags = ok_flags 910 if not 'EXTRA_LDFLAGS' in conf.env: 911 conf.env['EXTRA_LDFLAGS'] = [] 912 conf.env['EXTRA_LDFLAGS'].extend(TO_LIST(flags)) 913 return flags 914 915 916@conf 917def ADD_EXTRA_INCLUDES(conf, includes): 918 '''add some extra include directories to all builds''' 919 if not 'EXTRA_INCLUDES' in conf.env: 920 conf.env['EXTRA_INCLUDES'] = [] 921 conf.env['EXTRA_INCLUDES'].extend(TO_LIST(includes)) 922 923 924 925def CURRENT_CFLAGS(bld, target, cflags, allow_warnings=False, hide_symbols=False): 926 '''work out the current flags. local flags are added first''' 927 ret = TO_LIST(cflags) 928 if not 'EXTRA_CFLAGS' in bld.env: 929 list = [] 930 else: 931 list = bld.env['EXTRA_CFLAGS']; 932 ret.extend(list) 933 if not allow_warnings and 'PICKY_CFLAGS' in bld.env: 934 list = bld.env['PICKY_CFLAGS']; 935 ret.extend(list) 936 if hide_symbols and bld.env.HAVE_VISIBILITY_ATTR: 937 ret.append(bld.env.VISIBILITY_CFLAGS) 938 return ret 939 940 941@conf 942def CHECK_CC_ENV(conf): 943 """trim whitespaces from 'CC'. 944 The build farm sometimes puts a space at the start""" 945 if os.environ.get('CC'): 946 conf.env.CC = TO_LIST(os.environ.get('CC')) 947 948 949@conf 950def SETUP_CONFIGURE_CACHE(conf, enable): 951 '''enable/disable cache of configure results''' 952 if enable: 953 # when -C is chosen, we will use a private cache and will 954 # not look into system includes. This roughtly matches what 955 # autoconf does with -C 956 cache_path = os.path.join(conf.bldnode.abspath(), '.confcache') 957 mkdir_p(cache_path) 958 Options.cache_global = os.environ['WAFCACHE'] = cache_path 959 else: 960 # when -C is not chosen we will not cache configure checks 961 # We set the recursion limit low to prevent waf from spending 962 # a lot of time on the signatures of the files. 963 Options.cache_global = os.environ['WAFCACHE'] = '' 964 preproc.recursion_limit = 1 965 # in either case we don't need to scan system includes 966 preproc.go_absolute = False 967 968 969@conf 970def SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS(conf): 971 if Options.options.address_sanitizer or Options.options.enable_libfuzzer: 972 # Sanitizers can rely on symbols undefined at library link time and the 973 # symbols used for fuzzers are only defined by compiler wrappers. 974 return 975 976 if not sys.platform.startswith("openbsd"): 977 # we don't want any libraries or modules to rely on runtime 978 # resolution of symbols 979 conf.env.undefined_ldflags = conf.ADD_LDFLAGS('-Wl,-no-undefined', testflags=True) 980 981 if (conf.env.undefined_ignore_ldflags == [] and 982 conf.CHECK_LDFLAGS(['-undefined', 'dynamic_lookup'] + conf.env.WERROR_CFLAGS)): 983 conf.env.undefined_ignore_ldflags = ['-undefined', 'dynamic_lookup'] 984