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