scons_utils.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. # -*- mode: python -*-
  2. import sys, os, string, time, commands, re, pickle, StringIO, popen2, commands, pdb, zipfile, tempfile
  3. import SCons
  4. # need an Environment and a matching buffered_spawn API .. encapsulate
  5. class idBuffering:
  6. silent = False
  7. def buffered_spawn( self, sh, escape, cmd, args, env ):
  8. stderr = StringIO.StringIO()
  9. stdout = StringIO.StringIO()
  10. command_string = ''
  11. for i in args:
  12. if ( len( command_string ) ):
  13. command_string += ' '
  14. command_string += i
  15. try:
  16. retval = self.env['PSPAWN']( sh, escape, cmd, args, env, stdout, stderr )
  17. except OSError, x:
  18. if x.errno != 10:
  19. raise x
  20. print 'OSError ignored on command: %s' % command_string
  21. retval = 0
  22. print command_string
  23. if ( retval != 0 or not self.silent ):
  24. sys.stdout.write( stdout.getvalue() )
  25. sys.stderr.write( stderr.getvalue() )
  26. return retval
  27. class idSetupBase:
  28. def SimpleCommand( self, cmd ):
  29. print cmd
  30. ret = commands.getstatusoutput( cmd )
  31. if ( len( ret[ 1 ] ) ):
  32. sys.stdout.write( ret[ 1 ] )
  33. sys.stdout.write( '\n' )
  34. if ( ret[ 0 ] != 0 ):
  35. raise 'command failed'
  36. return ret[ 1 ]
  37. def TrySimpleCommand( self, cmd ):
  38. print cmd
  39. ret = commands.getstatusoutput( cmd )
  40. sys.stdout.write( ret[ 1 ] )
  41. def M4Processing( self, file, d ):
  42. file_out = file[:-3]
  43. cmd = 'm4 '
  44. for ( key, val ) in d.items():
  45. cmd += '--define=%s="%s" ' % ( key, val )
  46. cmd += '%s > %s' % ( file, file_out )
  47. self.SimpleCommand( cmd )
  48. def ExtractProtocolVersion( self ):
  49. f = open( 'framework/Licensee.h' )
  50. l = f.readlines()
  51. f.close()
  52. major = 'X'
  53. p = re.compile( '^#define ASYNC_PROTOCOL_MAJOR\t*(.*)' )
  54. for i in l:
  55. if ( p.match( i ) ):
  56. major = p.match( i ).group(1)
  57. break
  58. f = open( 'framework/async/AsyncNetwork.h' )
  59. l = f.readlines()
  60. f.close()
  61. minor = 'X'
  62. p = re.compile( '^const int ASYNC_PROTOCOL_MINOR\t*= (.*);' )
  63. for i in l:
  64. if ( p.match( i ) ):
  65. minor = p.match( i ).group(1)
  66. break
  67. return '%s.%s' % ( major, minor )
  68. def ExtractEngineVersion( self ):
  69. f = open( 'framework/Licensee.h' )
  70. l = f.readlines()
  71. f.close()
  72. version = 'X'
  73. p = re.compile( '^#define.*ENGINE_VERSION\t*"DOOM (.*)"' )
  74. for i in l:
  75. if ( p.match( i ) ):
  76. version = p.match( i ).group(1)
  77. break
  78. return version
  79. def ExtractBuildVersion( self ):
  80. f = open( 'framework/BuildVersion.h' )
  81. l = f.readlines()[ 4 ]
  82. f.close()
  83. pat = re.compile( '.* = (.*);\n' )
  84. return pat.split( l )[ 1 ]
  85. def checkLDD( target, source, env ):
  86. file = target[0]
  87. if (not os.path.isfile(file.abspath)):
  88. print('ERROR: CheckLDD: target %s not found\n' % target[0])
  89. Exit(1)
  90. ( status, output ) = commands.getstatusoutput( 'ldd -r %s' % file )
  91. if ( status != 0 ):
  92. print 'ERROR: ldd command returned with exit code %d' % ldd_ret
  93. os.system( 'rm %s' % target[ 0 ] )
  94. sys.exit(1)
  95. lines = string.split( output, '\n' )
  96. have_undef = 0
  97. for i_line in lines:
  98. #print repr(i_line)
  99. regex = re.compile('undefined symbol: (.*)\t\\((.*)\\)')
  100. if ( regex.match(i_line) ):
  101. symbol = regex.sub('\\1', i_line)
  102. try:
  103. env['ALLOWED_SYMBOLS'].index(symbol)
  104. except:
  105. have_undef = 1
  106. if ( have_undef ):
  107. print output
  108. print "ERROR: undefined symbols"
  109. os.system('rm %s' % target[0])
  110. sys.exit(1)
  111. def SharedLibrarySafe( env, target, source ):
  112. ret = env.SharedLibrary( target, source )
  113. env.AddPostAction( ret, checkLDD )
  114. return ret
  115. def NotImplementedStub( *whatever ):
  116. print 'Not Implemented'
  117. sys.exit( 1 )
  118. # --------------------------------------------------------------------
  119. class idGamePaks( idSetupBase ):
  120. def BuildGamePak( self, target = None, source = None, env = None ):
  121. # NOTE: ew should have done with zipfile module
  122. temp_dir = tempfile.mkdtemp( prefix = 'gamepak' )
  123. self.SimpleCommand( 'cp %s %s' % ( source[0].abspath, os.path.join( temp_dir, 'gamex86.so' ) ) )
  124. self.SimpleCommand( 'strip %s' % os.path.join( temp_dir, 'gamex86.so' ) )
  125. self.SimpleCommand( 'echo 2 > %s' % ( os.path.join( temp_dir, 'binary.conf' ) ) )
  126. self.SimpleCommand( 'cd %s ; zip %s gamex86.so binary.conf' % ( temp_dir, os.path.join( temp_dir, target[0].abspath ) ) )
  127. self.SimpleCommand( 'rm -r %s' % temp_dir )
  128. return None
  129. # --------------------------------------------------------------------
  130. # get a clean error output when running multiple jobs
  131. def SetupBufferedOutput( env, silent ):
  132. buf = idBuffering()
  133. buf.silent = silent
  134. buf.env = env
  135. env['SPAWN'] = buf.buffered_spawn
  136. # setup utilities on an environement
  137. def SetupUtils( env ):
  138. gamepaks = idGamePaks()
  139. env.BuildGamePak = gamepaks.BuildGamePak
  140. env.SharedLibrarySafe = SharedLibrarySafe
  141. try:
  142. import SDK
  143. sdk = SDK.idSDK()
  144. env.PreBuildSDK = sdk.PreBuildSDK
  145. env.BuildSDK = sdk.BuildSDK
  146. except:
  147. print 'SDK.py hookup failed'
  148. env.PreBuildSDK = NotImplementedStub
  149. env.BuildSDK = NotImplementedStub
  150. try:
  151. import Setup
  152. setup = Setup.idSetup()
  153. env.BuildSetup = setup.BuildSetup
  154. except:
  155. print 'Setup.py hookup failed'
  156. env.BuildSetup = NotImplementedStub
  157. def BuildList( s_prefix, s_string ):
  158. s_list = string.split( s_string )
  159. for i in range( len( s_list ) ):
  160. s_list[ i ] = s_prefix + '/' + s_list[ i ]
  161. return s_list