AMBuildScript
author John Schoenick <john@pointysoftware.net>
Wed Jun 01 20:36:16 2011 -0400 (2011-06-01)
changeset 3292 f428ffc8a3fe
parent 3280 7aea1316eff7
child 3297 89b6aa6e9d37
permissions -rw-r--r--
Fixed regression in FindEntityByClassname from bug 4899 (bug 4941, r=predcrab).
     1 # vim: set ts=2 sw=2 tw=99 noet ft=python:
     2 import os
     3 import sys
     4 from ambuild.command import SymlinkCommand
     5 
     6 class SM:
     7 	def __init__(self):
     8 		self.compiler = Cpp.Compiler()
     9 
    10 		#Build SDK info
    11 		self.sdkInfo = { }
    12 		self.sdkInfo['ep1'] =   {'sdk': 'HL2SDK',          'ext': '1.ep1',   'def': '1',
    13 		                         'name': 'EPISODEONE',     'platform': ['windows', 'linux']}
    14 		self.sdkInfo['ep2'] =   {'sdk': 'HL2SDKOB',        'ext': '2.ep2',   'def': '3',
    15 		                         'name': 'ORANGEBOX',      'platform': ['windows', 'linux']}
    16 		self.sdkInfo['ep2v'] =  {'sdk': 'HL2SDKOBVALVE',   'ext': '2.ep2v',  'def': '5',
    17 		                         'name': 'ORANGEBOXVALVE', 'platform': ['windows', 'linux', 'darwin']}
    18 		self.sdkInfo['l4d'] =   {'sdk': 'HL2SDKL4D',       'ext': '2.l4d',   'def': '6',
    19 		                         'name': 'LEFT4DEAD',      'platform': ['windows', 'linux', 'darwin']}
    20 		self.sdkInfo['l4d2'] =  {'sdk': 'HL2SDKL4D2',      'ext': '2.l4d2',  'def': '7',
    21 		                         'name': 'LEFT4DEAD2',     'platform': ['windows', 'linux', 'darwin']}
    22 		self.sdkInfo['darkm'] = {'sdk': 'HL2SDK-DARKM',    'ext': '2.darkm', 'def': '2',
    23 		                         'name': 'DARKMESSIAH',    'platform': ['windows']}
    24 		self.sdkInfo['swarm'] = {'sdk': 'HL2SDK-SWARM',    'ext': '2.swarm', 'def': '8',
    25 		                         'name': 'ALIENSWARM',     'platform': ['windows']}
    26 		self.sdkInfo['bgt'] =   {'sdk': 'HL2SDK-BGT',    'ext': '2.bgt', 'def': '4',
    27 		                         'name': 'BLOODYGOODTIME',     'platform': ['windows']}
    28 
    29 		if AMBuild.mode == 'config':
    30 			#Detect compilers
    31 			self.compiler.DetectAll(AMBuild)
    32 
    33 			#Detect variables
    34 			envvars = { 'MMSOURCE18':    'mmsource-1.8',
    35 									'HL2SDKOBVALVE': 'hl2sdk-ob-valve',
    36 									'HL2SDKL4D':     'hl2sdk-l4d',
    37 									'HL2SDKL4D2':    'hl2sdk-l4d2',
    38 									'MYSQL5':        'mysql-5.0'
    39 			}
    40 
    41 			if AMBuild.target['platform'] != 'darwin':
    42 				envvars['HL2SDK'] = 'hl2sdk'
    43 				envvars['HL2SDKOB'] = 'hl2sdk-ob'
    44 
    45 			#Dark Messiah is Windows-only
    46 			if AMBuild.target['platform'] == 'windows':
    47 				envvars['HL2SDK-DARKM'] = 'hl2sdk-darkm'
    48 				envvars['HL2SDK-SWARM'] = 'hl2sdk-swarm'
    49 				envvars['HL2SDK-BGT']   = 'hl2sdk-bgt'
    50 
    51 			#Must have a path for each envvar (file a bug if you don't like this)
    52 			for i in envvars:
    53 				if i in os.environ:
    54 					path = os.environ[i]
    55 					if not os.path.isdir(path):
    56 						raise Exception('Path for {0} was not found: {1}'.format(i, path))
    57 				else:
    58 					head = os.getcwd()
    59 					oldhead = None
    60 					while head != None and head != oldhead:
    61 						path = os.path.join(head, envvars[i])
    62 						if os.path.isdir(path):
    63 							break
    64 						oldhead = head
    65 						head, tail = os.path.split(head)
    66 					if head == None or head == oldhead:
    67 						raise Exception('Could not find a valid path for {0}'.format(i))
    68 				AMBuild.cache.CacheVariable(i, path)
    69 
    70 			#Set up defines
    71 			cxx = self.compiler.cxx
    72 			if isinstance(cxx, Cpp.CompatGCC):
    73 				if isinstance(cxx, Cpp.GCC):
    74 					self.vendor = 'gcc'
    75 				elif isinstance(cxx, Cpp.Clang):
    76 					self.vendor = 'clang'
    77 				self.compiler.AddToListVar('CDEFINES', 'stricmp=strcasecmp')
    78 				self.compiler.AddToListVar('CDEFINES', '_stricmp=strcasecmp')
    79 				self.compiler.AddToListVar('CDEFINES', '_snprintf=snprintf')
    80 				self.compiler.AddToListVar('CDEFINES', '_vsnprintf=vsnprintf')
    81 				self.compiler.AddToListVar('CFLAGS', '-pipe')
    82 				self.compiler.AddToListVar('CFLAGS', '-fno-strict-aliasing')
    83 				if (self.vendor == 'gcc' and cxx.majorVersion >= 4) or self.vendor == 'clang':
    84 					self.compiler.AddToListVar('CFLAGS', '-fvisibility=hidden')
    85 					self.compiler.AddToListVar('CXXFLAGS', '-fvisibility-inlines-hidden')
    86 				self.compiler.AddToListVar('CFLAGS', '-Wall')
    87 				self.compiler.AddToListVar('CFLAGS', '-Werror')
    88 				self.compiler.AddToListVar('CFLAGS', '-Wno-uninitialized')
    89 				self.compiler.AddToListVar('CFLAGS', '-Wno-unused')
    90 				self.compiler.AddToListVar('CFLAGS', '-Wno-switch')
    91 				self.compiler.AddToListVar('CFLAGS', '-msse')
    92 				self.compiler.AddToListVar('CFLAGS', '-m32')
    93 				self.compiler.AddToListVar('POSTLINKFLAGS', '-m32')
    94 				self.compiler.AddToListVar('CXXFLAGS', '-fno-exceptions')
    95 				self.compiler.AddToListVar('CXXFLAGS', '-fno-rtti')
    96 				self.compiler.AddToListVar('CXXFLAGS', '-fno-threadsafe-statics')
    97 				self.compiler.AddToListVar('CXXFLAGS', '-Wno-non-virtual-dtor')
    98 				self.compiler.AddToListVar('CXXFLAGS', '-Wno-overloaded-virtual')
    99 				self.compiler.AddToListVar('CDEFINES', 'HAVE_STDINT_H')
   100 				if self.vendor == 'gcc':
   101 					self.compiler.AddToListVar('CFLAGS', '-mfpmath=sse')
   102 					self.compiler.AddToListVar('POSTLINKFLAGS', '-static-libgcc')
   103 			elif isinstance(cxx, Cpp.MSVC):
   104 				self.vendor = 'msvc'
   105 				if AMBuild.options.debug == '1':
   106 					self.compiler.AddToListVar('CFLAGS', '/MTd')
   107 					self.compiler.AddToListVar('POSTLINKFLAGS', '/NODEFAULTLIB:libcmt')
   108 				else:
   109 					self.compiler.AddToListVar('CFLAGS', '/MT')
   110 				self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_DEPRECATE')
   111 				self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_WARNINGS')
   112 				self.compiler.AddToListVar('CDEFINES', '_CRT_NONSTDC_NO_DEPRECATE')
   113 				self.compiler.AddToListVar('CXXFLAGS', '/EHsc')
   114 				self.compiler.AddToListVar('CXXFLAGS', '/GR-')
   115 				self.compiler.AddToListVar('CFLAGS', '/W3')
   116 				self.compiler.AddToListVar('CFLAGS', '/nologo')
   117 				self.compiler.AddToListVar('CFLAGS', '/Zi')
   118 				self.compiler.AddToListVar('CXXFLAGS', '/TP')
   119 				self.compiler.AddToListVar('POSTLINKFLAGS', '/DEBUG')
   120 				self.compiler.AddToListVar('POSTLINKFLAGS', '/MACHINE:X86')
   121 				self.compiler.AddToListVar('POSTLINKFLAGS', '/SUBSYSTEM:WINDOWS')
   122 				self.compiler.AddToListVar('POSTLINKFLAGS', 'kernel32.lib')
   123 				self.compiler.AddToListVar('POSTLINKFLAGS', 'user32.lib')
   124 				self.compiler.AddToListVar('POSTLINKFLAGS', 'gdi32.lib')
   125 				self.compiler.AddToListVar('POSTLINKFLAGS', 'winspool.lib')
   126 				self.compiler.AddToListVar('POSTLINKFLAGS', 'comdlg32.lib')
   127 				self.compiler.AddToListVar('POSTLINKFLAGS', 'advapi32.lib')
   128 				self.compiler.AddToListVar('POSTLINKFLAGS', 'shell32.lib')
   129 				self.compiler.AddToListVar('POSTLINKFLAGS', 'ole32.lib')
   130 				self.compiler.AddToListVar('POSTLINKFLAGS', 'oleaut32.lib')
   131 				self.compiler.AddToListVar('POSTLINKFLAGS', 'uuid.lib')
   132 				self.compiler.AddToListVar('POSTLINKFLAGS', 'odbc32.lib')
   133 				self.compiler.AddToListVar('POSTLINKFLAGS', 'odbccp32.lib')
   134 
   135 			#Optimization
   136 			if AMBuild.options.opt == '1':
   137 				self.compiler.AddToListVar('CDEFINES', 'NDEBUG')
   138 				if self.vendor == 'gcc' or self.vendor == 'clang':
   139 					self.compiler.AddToListVar('CFLAGS', '-O3')
   140 				elif self.vendor == 'msvc':
   141 					self.compiler.AddToListVar('CFLAGS', '/Ox')
   142 					self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:ICF')
   143 					self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:REF')
   144 
   145 			#Debugging
   146 			if AMBuild.options.debug == '1':
   147 				self.compiler.AddToListVar('CDEFINES', 'DEBUG')
   148 				self.compiler.AddToListVar('CDEFINES', '_DEBUG')
   149 				if self.vendor == 'gcc' or self.vendor == 'clang':
   150 					self.compiler.AddToListVar('CFLAGS', '-g3')
   151 				elif self.vendor == 'msvc':
   152 					self.compiler.AddToListVar('CFLAGS', '/Od')
   153 					self.compiler.AddToListVar('CFLAGS', '/RTC1')
   154 
   155 			#Platform-specifics
   156 			if AMBuild.target['platform'] == 'linux':
   157 				self.compiler.AddToListVar('CDEFINES', '_LINUX')
   158 				if self.vendor == 'clang':
   159 					self.compiler.AddToListVar('POSTLINKFLAGS', '-lgcc_eh')
   160 			elif AMBuild.target['platform'] == 'darwin':
   161 				self.compiler.AddToListVar('CFLAGS', ['-isysroot',
   162 				                                      '/Developer/SDKs/MacOSX10.5.sdk'])
   163 				self.compiler.AddToListVar('POSTLINKFLAGS', '-mmacosx-version-min=10.5')
   164 				self.compiler.AddToListVar('POSTLINKFLAGS', ['-arch', 'i386'])
   165 				self.compiler.AddToListVar('POSTLINKFLAGS', '-lstdc++')
   166 
   167 				# For OS X dylib versioning
   168 				import re
   169 				productFile = open(os.path.join(AMBuild.sourceFolder, 'product.version'), 'r')
   170 				productContents = productFile.read()
   171 				productFile.close()
   172 				m = re.match('(\d+)\.(\d+)\.(\d+).*', productContents)
   173 				if m == None:
   174 					self.version = '1.0.0'
   175 				else:
   176 					major, minor, release = m.groups()
   177 					self.version = '{0}.{1}.{2}'.format(major, minor, release)
   178 				AMBuild.cache.CacheVariable('version', self.version)
   179 			elif AMBuild.target['platform'] == 'windows':
   180 				self.compiler.AddToListVar('CDEFINES', 'WIN32')
   181 				self.compiler.AddToListVar('CDEFINES', '_WINDOWS')
   182 
   183 			#Finish up
   184 			self.compiler.AddToListVar('CDEFINES', 'SOURCEMOD_BUILD')
   185 			self.compiler.AddToListVar('CDEFINES', 'SM_GENERATED_BUILD')
   186 			self.compiler.AddToListVar('CINCLUDES',
   187 			                           os.path.join(AMBuild.outputFolder, 'includes'))
   188 			self.compiler.ToConfig(AMBuild, 'compiler')
   189 			AMBuild.cache.CacheVariable('vendor', self.vendor)
   190 			self.targetMap = { }
   191 			AMBuild.cache.CacheVariable('targetMap', self.targetMap)
   192 		else:
   193 			self.compiler.FromConfig(AMBuild, 'compiler')
   194 			self.targetMap = AMBuild.cache['targetMap']
   195 
   196 		if AMBuild.target['platform'] == 'windows':
   197 			self.compiler.AddToListVar('RCINCLUDES', os.path.join(AMBuild.sourceFolder, 'public'))
   198 			self.compiler.AddToListVar('RCINCLUDES',
   199 			                           os.path.join(AMBuild.outputFolder, 'includes'))
   200 		self.mmsPath = AMBuild.cache['MMSOURCE18']
   201 
   202 	def DefaultCompiler(self):
   203 		return self.compiler.Clone()
   204 
   205 	def JobMatters(self, jobname):
   206 		file = sys._getframe().f_code.co_filename
   207 		if AMBuild.mode == 'config':
   208 			self.targetMap[jobname] = file
   209 			return True
   210 		if len(AMBuild.args) == 0:
   211 			return True
   212 		if not jobname in AMBuild.args:
   213 			return False
   214 
   215 	def DefaultExtCompiler(self, path):
   216 		compiler = self.DefaultCompiler()
   217 		compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path))
   218 		compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path, 'sdk'))
   219 		compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public'))
   220 		compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'extensions'))
   221 		compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'sourcepawn'))
   222 		return compiler
   223 
   224 	def AutoVersion(self, folder, binary):
   225 		if AMBuild.target['platform'] == 'windows':
   226 			env = {'RCDEFINES': ['BINARY_NAME="' + binary.binaryFile + '"', 'SM_GENERATED_BUILD']}
   227 			binary.AddResourceFile(os.path.join(folder, 'version.rc' ), env)
   228 		elif AMBuild.target['platform'] == 'darwin' and isinstance(binary, Cpp.LibraryBuilder):
   229 			binary.compiler['POSTLINKFLAGS'].extend(['-compatibility_version', '1.0.0'])
   230 			binary.compiler['POSTLINKFLAGS'].extend(['-current_version', AMBuild.cache['version']])
   231 		else:
   232 			return
   233 
   234 	def PreSetupHL2Job(self, job, builder, sdk):
   235 		info = self.sdkInfo[sdk]
   236 		sdkPath = AMBuild.cache[info['sdk']]
   237 		if AMBuild.target['platform'] == 'linux':
   238 			if sdk == 'ep1':
   239 				staticLibs = os.path.join(sdkPath, 'linux_sdk')
   240 			else:
   241 				staticLibs = os.path.join(sdkPath, 'lib', 'linux')
   242 			workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
   243 			if sdk in ['ep2v', 'l4d', 'l4d2']:
   244 				for i in ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.so', 'libtier0.so']:
   245 					link = os.path.join(workFolder, i)
   246 					target = os.path.join(staticLibs, i)
   247 					try:
   248 						os.lstat(link)
   249 					except:
   250 						job.AddCommand(SymlinkCommand(link, target))
   251 			else:
   252 				for i in ['tier1_i486.a', 'mathlib_i486.a', 'vstdlib_i486.so', 'tier0_i486.so']:
   253 					link = os.path.join(workFolder, i)
   254 					target = os.path.join(staticLibs, i)
   255 					try:
   256 						os.lstat(link)
   257 					except:
   258 						job.AddCommand(SymlinkCommand(link, target))
   259 		elif AMBuild.target['platform'] == 'darwin':
   260 			staticLibs = os.path.join(sdkPath, 'lib', 'mac')
   261 			workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
   262 			for i in ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.dylib', 'libtier0.dylib']:
   263 				link = os.path.join(workFolder, i)
   264 				target = os.path.join(staticLibs, i)
   265 				try:
   266 					os.lstat(link)
   267 				except:
   268 					job.AddCommand(SymlinkCommand(link, target))
   269 		elif AMBuild.target['platform'] == 'windows':
   270 			libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
   271 			if sdk == 'swarm':
   272 				libs.append('interfaces')
   273 			for lib in libs:
   274 				libPath = os.path.join(sdkPath, 'lib', 'public', lib) + '.lib'
   275 				builder.RebuildIfNewer(libPath)
   276 				builder['POSTLINKFLAGS'].append(libPath)
   277 
   278 	def PostSetupHL2Job(self, job, builder, sdk):
   279 		if AMBuild.target['platform'] in ['linux', 'darwin']:
   280 			builder.AddObjectFiles(['tier1_i486.a', 'mathlib_i486.a'])
   281 
   282 	def DefaultHL2Compiler(self, path, sdk, noLink = False, oldMms = '-legacy'):
   283 		compiler = self.DefaultExtCompiler(path)
   284 
   285 		mms = 'core'
   286 		if sdk == 'ep1':
   287 			mms += oldMms
   288 
   289 		compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms))
   290 		compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms, 'sourcehook'))
   291 
   292 		info = self.sdkInfo
   293 		compiler['CDEFINES'].extend(['SE_' + info[i]['name'] + '=' + info[i]['def'] for i in info])
   294 
   295 		paths = [['public'], ['public', 'engine'], ['public', 'mathlib'], ['public', 'vstdlib'],
   296 						 ['public', 'tier0'], ['public', 'tier1']]
   297 		if sdk == 'ep1' or sdk == 'darkm':
   298 			paths.append(['public', 'dlls'])
   299 			paths.append(['game_shared'])
   300 		else:
   301 			paths.append(['public', 'game', 'server'])
   302 			paths.append(['public', 'toolframework'])
   303 			paths.append(['game', 'shared'])
   304 			paths.append(['common'])
   305 
   306 		info = self.sdkInfo[sdk]
   307 		sdkPath = AMBuild.cache[info['sdk']]
   308 
   309 		compiler['CDEFINES'].append('SOURCE_ENGINE=' + info['def'])
   310 
   311 		if sdk == 'swarm' and AMBuild.target['platform'] == 'windows':
   312 			compiler['CDEFINES'].extend(['COMPILER_MSVC', 'COMPILER_MSVC32'])
   313 
   314 		if sdk == 'ep1':
   315 			if AMBuild.target['platform'] == 'linux':
   316 				staticLibs = os.path.join(sdkPath, 'linux_sdk')
   317 		else:
   318 			if AMBuild.target['platform'] == 'linux':
   319 				staticLibs = os.path.join(sdkPath, 'lib', 'linux')
   320 			elif AMBuild.target['platform'] == 'darwin':
   321 				staticLibs = os.path.join(sdkPath, 'lib', 'mac')
   322 
   323 		for i in paths:
   324 			compiler['CXXINCLUDES'].append(os.path.join(sdkPath, *i))
   325 
   326 		if not noLink:
   327 			if AMBuild.target['platform'] == 'linux':
   328 				compiler['POSTLINKFLAGS'][0:0] = ['-lm']
   329 				if sdk in ['ep2v', 'l4d', 'l4d2']:
   330 					compiler['POSTLINKFLAGS'][0:0] = ['libtier0.so']
   331 					compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.so']
   332 				else:
   333 					compiler['POSTLINKFLAGS'][0:0] = ['tier0_i486.so']
   334 					compiler['POSTLINKFLAGS'][0:0] = ['vstdlib_i486.so']
   335 			elif AMBuild.target['platform'] == 'darwin':
   336 				compiler['POSTLINKFLAGS'][0:0] = ['libtier0.dylib']
   337 				compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.dylib']
   338 
   339 		return compiler
   340 
   341 sm = SM()
   342 globals = {
   343 	'SM': sm
   344 }
   345 
   346 AMBuild.Include(os.path.join('tools', 'buildbot', 'Versioning'), globals)
   347 
   348 FileList = [
   349 		['loader', 'AMBuilder'],
   350 		['core', 'AMBuilder'],
   351 		['core', 'logic', 'AMBuilder'],
   352 		['extensions', 'bintools', 'AMBuilder'],
   353 		['extensions', 'clientprefs', 'AMBuilder'],
   354 		['extensions', 'cstrike', 'AMBuilder'],
   355 		['extensions', 'curl', 'AMBuilder'],
   356 		['extensions', 'geoip', 'AMBuilder'],
   357 		['extensions', 'mysql', 'AMBuilder'],
   358 		['extensions', 'sdktools', 'AMBuilder'],
   359 		['extensions', 'topmenus', 'AMBuilder'],
   360 		['extensions', 'updater', 'AMBuilder'],
   361 		['extensions', 'sqlite', 'AMBuilder'],
   362 		['extensions', 'regex', 'AMBuilder'],
   363 		['extensions', 'tf2', 'AMBuilder'],
   364 		['sourcepawn', 'jit', 'AMBuilder'],
   365 		['sourcepawn', 'compiler', 'AMBuilder'],
   366 		['plugins', 'AMBuilder'],
   367 		['tools', 'buildbot', 'PackageScript']
   368 	]
   369 
   370 for parts in FileList:
   371 	AMBuild.Include(os.path.join(*parts), globals)
   372