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