1"""SCons.SConf 2 3Autoconf-like configuration support. 4 5In other words, SConf allows to run tests on the build machine to detect 6capabilities of system and do some things based on result: generate config 7files, header files for C/C++, update variables in environment. 8 9Tests on the build system can detect if compiler sees header files, if 10libraries are installed, if some command line options are supported etc. 11 12""" 13 14# 15# Copyright (c) 2001 - 2014 The SCons Foundation 16# 17# Permission is hereby granted, free of charge, to any person obtaining 18# a copy of this software and associated documentation files (the 19# "Software"), to deal in the Software without restriction, including 20# without limitation the rights to use, copy, modify, merge, publish, 21# distribute, sublicense, and/or sell copies of the Software, and to 22# permit persons to whom the Software is furnished to do so, subject to 23# the following conditions: 24# 25# The above copyright notice and this permission notice shall be included 26# in all copies or substantial portions of the Software. 27# 28# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 29# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 30# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 31# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 32# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 33# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 34# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 35# 36 37__revision__="src/engine/SCons/SConf.py 2014/09/27 12:51:43 garyo" 38 39importSCons.compat 40 41importio 42importos 43importre 44importsys 45importtraceback 46 47importSCons.Action 48importSCons.Builder 49importSCons.Errors 50importSCons.Job 51importSCons.Node.FS 52importSCons.Taskmaster 53importSCons.Util 54importSCons.Warnings 55importSCons.Conftest 56 57fromSCons.DebugimportTrace 58 59# Turn off the Conftest error logging 60SCons.Conftest.LogInputFiles=0 61SCons.Conftest.LogErrorMessages=0 62 63# Set 64build_type=None 65build_types=['clean','help'] 66

70 71# to be set, if we are in dry-run mode 72dryrun=0 73 74AUTO=0# use SCons dependency scanning for up-to-date checks 75FORCE=1# force all tests to be rebuilt 76CACHE=2# force all tests to be taken from cache (raise an error, if necessary) 77cache_mode=AUTO 78

173""" 174 Special build info for targets of configure tests. Additional members 175 are result (did the builder succeed last time?) and string, which 176 contains messages of the original build phase. 177 """ 178result=None# -> 0/None -> no error, != 0 error 179string=None# the stdout / stderr output when building the target 180

341ifenv.decide_source.func_codeisnotforce_build.func_code: 342env.Decider(force_build) 343env['PSTDOUT']=env['PSTDERR']=s 344try: 345sconf.cached=0 346self.targets[0].build() 347finally: 348sys.stdout=sys.stderr=env['PSTDOUT']= \ 349env['PSTDERR']=sconf.logstream 350exceptKeyboardInterrupt: 351raise 352exceptSystemExit: 353exc_value=sys.exc_info()[1] 354raiseSCons.Errors.ExplicitExit(self.targets[0],exc_value.code) 355exceptException,e: 356fortinself.targets: 357binfo=t.get_binfo() 358binfo.__class__=SConfBuildInfo 359binfo.set_build_result(1,s.getvalue()) 360sconsign_entry=SCons.SConsign.SConsignEntry() 361sconsign_entry.binfo=binfo 362#sconsign_entry.ninfo = self.get_ninfo() 363# We'd like to do this as follows: 364# t.store_info(binfo) 365# However, we need to store it as an SConfBuildInfo 366# object, and store_info() will turn it into a 367# regular FileNodeInfo if the target is itself a 368# regular File. 369sconsign=t.dir.sconsign() 370sconsign.set_entry(t.name,sconsign_entry) 371sconsign.merge() 372raisee 373else: 374fortinself.targets: 375binfo=t.get_binfo() 376binfo.__class__=SConfBuildInfo 377binfo.set_build_result(0,s.getvalue()) 378sconsign_entry=SCons.SConsign.SConsignEntry() 379sconsign_entry.binfo=binfo 380#sconsign_entry.ninfo = self.get_ninfo() 381# We'd like to do this as follows: 382# t.store_info(binfo) 383# However, we need to store it as an SConfBuildInfo 384# object, and store_info() will turn it into a 385# regular FileNodeInfo if the target is itself a 386# regular File. 387sconsign=t.dir.sconsign() 388sconsign.set_entry(t.name,sconsign_entry) 389sconsign.merge() 390

392"""This is simply a class to represent a configure context. After 393 creating a SConf object, you can call any tests. After finished with your 394 tests, be sure to call the Finish() method, which returns the modified 395 environment. 396 Some words about caching: In most cases, it is not necessary to cache 397 Test results explicitely. Instead, we use the scons dependency checking 398 mechanism. For example, if one wants to compile a test program 399 (SConf.TryLink), the compiler is only called, if the program dependencies 400 have changed. However, if the program could not be compiled in a former 401 SConf run, we need to explicitely cache this error. 402 """ 403

459""" 460 Define a pre processor symbol name, with the optional given value in the 461 current config header. 462 463 If value is None (default), then #define name is written. If value is not 464 none, then #define name value is written. 465 466 comment is a string which will be put as a C comment in the 467 header, to explain the meaning of the value (appropriate C comments /* and 468 */ will be put automatically.""" 469lines=[] 470ifcomment: 471comment_str="/* %s */"%comment 472lines.append(comment_str) 473 474ifvalueisnotNone: 475define_str="#define %s %s"%(name,value) 476else: 477define_str="#define %s"%name 478lines.append(define_str) 479lines.append('') 480 481self.config_h_text=self.config_h_text+'\n'.join(lines)

537"""Wrapper function for handling piped spawns. 538 539 This looks to the calling interface (in Action.py) like a "normal" 540 spawn, but associates the call with the PSPAWN variable from 541 the construction environment and with the streams to which we 542 want the output logged. This gets slid into the construction 543 environment as the SPAWN variable so Action.py doesn't have to 544 know or care whether it's spawning a piped command or not. 545 """ 546returnself.pspawn(sh,escape,cmd,args,env,self.logstream,self.logstream)

621"""Compiles the program given in text to an env.Object, using extension 622 as file extension (e.g. '.c'). Returns 1, if compilation was 623 successful, 0 otherwise. The target is saved in self.lastTarget (for 624 further processing). 625 """ 626returnself.TryBuild(self.env.Object,text,extension)

629"""Compiles the program given in text to an executable env.Program, 630 using extension as file extension (e.g. '.c'). Returns 1, if 631 compilation was successful, 0 otherwise. The target is saved in 632 self.lastTarget (for further processing). 633 """ 634returnself.TryBuild(self.env.Program,text,extension)

692"""Private method. Set up logstream, and set the environment 693 variables necessary for a piped build 694 """ 695global_ac_config_logs 696globalsconf_global 697globalSConfFS 698 699self.lastEnvFs=self.env.fs 700self.env.fs=SConfFS 701self._createDir(self.confdir) 702self.confdir.up().add_ignore([self.confdir]) 703 704ifself.logfileisnotNoneandnotdryrun: 705# truncate logfile, if SConf.Configure is called for the first time 706# in a build 707ifself.logfilein_ac_config_logs: 708log_mode="a" 709else: 710_ac_config_logs[self.logfile]=None 711log_mode="w" 712fp=open(str(self.logfile),log_mode) 713self.logstream=SCons.Util.Unbuffered(fp) 714# logfile may stay in a build directory, so we tell 715# the build system not to override it with a eventually 716# existing file with the same name in the source directory 717self.logfile.dir.add_ignore([self.logfile]) 718 719tb=traceback.extract_stack()[-3-self.depth] 720old_fs_dir=SConfFS.getcwd() 721SConfFS.chdir(SConfFS.Top,change_os_dir=0) 722self.logstream.write('file %s,line %d:\n\tConfigure(confdir = %s)\n'% 723(tb[0],tb[1],str(self.confdir))) 724SConfFS.chdir(old_fs_dir) 725else: 726self.logstream=None 727# we use a special builder to create source files from TEXT 728action=SCons.Action.Action(_createSource, 729_stringSource) 730sconfSrcBld=SCons.Builder.Builder(action=action) 731self.env.Append(BUILDERS={'SConfSourceBuilder':sconfSrcBld}) 732self.config_h_text=_ac_config_hs.get(self.config_h,"") 733self.active=1 734# only one SConf instance should be active at a time ... 735sconf_global=self

758"""Provides a context for configure tests. Defines how a test writes to the 759 screen and log file. 760 761 A typical test is just a callable with an instance of CheckContext as 762 first argument: 763 764 def CheckCustom(context, ...) 765 context.Message('Checking my weird test ... ') 766 ret = myWeirdTestFunction(...) 767 context.Result(ret) 768 769 Often, myWeirdTestFunction will be one of 770 context.TryCompile/context.TryLink/context.TryRun. The results of 771 those are cached, for they are only rebuild, if the dependencies have 772 changed. 773 """ 774

785# we don't regenerate the config.h file after each test. That means, 786# that tests won't be able to include the config.h file, and so 787# they can't do an #ifdef HAVE_XXX_H. This shouldn't be a major 788# issue, though. If it turns out, that we need to include config.h 789# in tests, we must ensure, that the dependencies are worked out 790# correctly. Note that we can't use Conftest.py's support for config.h, 791# cause we will need to specify a builder for the config.h file ... 792

802"""Inform about the result of the test. If res is not a string, displays 803 'yes' or 'no' depending on whether res is evaluated as true or false. 804 The result is only displayed when self.did_show_result is not set. 805 """ 806ifisinstance(res,str): 807text=res 808elifres: 809text="yes" 810else: 811text="no" 812 813ifself.did_show_result==0: 814# Didn't show result yet, do it now. 815self.Display(text+"\n") 816self.did_show_result=1

880ifself.sconf.cached: 881# We assume that Display is called twice for each test here 882# once for the Checking for ... message and once for the result. 883# The self.sconf.cached flag can only be set between those calls 884msg="(cached) "+msg 885self.sconf.cached=0 886progress_display(msg,append_newline=0) 887self.Log("scons: Configure: "+msg+"\n")

1002"""1003 A test for a library. See also CheckLibWithHeader.1004 Note that library may also be None to test whether the given symbol1005 compiles without flags.1006 """10071008iflibrary==[]:1009library=[None]10101011ifnotSCons.Util.is_List(library):1012library=[library]10131014# ToDo: accept path for the library1015res=SCons.Conftest.CheckLib(context,library,symbol,header=header,1016language=language,autoadd=autoadd)1017context.did_show_result=11018returnnotres

10191020# XXX1021# Bram: Can only include one header and can't use #ifdef HAVE_HEADER_H.1022

1025# ToDo: accept path for library. Support system header files.1026"""1027 Another (more sophisticated) test for a library.1028 Checks, if library and header is available for language (may be 'C'1029 or 'CXX'). Call maybe be a valid expression _with_ a trailing ';'.1030 As in CheckLib, we support library=None, to test if the call compiles1031 without extra link flags.1032 """1033prog_prefix,dummy= \ 1034createIncludesFromHeaders(header,0)1035iflibs==[]:1036libs=[None]10371038ifnotSCons.Util.is_List(libs):1039libs=[libs]10401041res=SCons.Conftest.CheckLib(context,libs,None,prog_prefix,1042call=call,language=language,autoadd=autoadd)1043context.did_show_result=11044returnnotres