AMBuildScript
author FlaminSarge <laftrykung@yahoo.com>
Thu May 12 11:33:50 2011 -0400 (2011-05-12)
changeset 3269 2139ba334ae0
parent 3267 622ef46cd089
child 3280 7aea1316eff7
permissions -rw-r--r--
Added TF2 megaheal cond defines to tf2 incs (bug 4916, r=psychonic).
     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(['game', 'shared'])
   303 			paths.append(['common'])
   304 
   305 		info = self.sdkInfo[sdk]
   306 		sdkPath = AMBuild.cache[info['sdk']]
   307 
   308 		compiler['CDEFINES'].append('SOURCE_ENGINE=' + info['def'])
   309 
   310 		if sdk == 'swarm' and AMBuild.target['platform'] == 'windows':
   311 			compiler['CDEFINES'].extend(['COMPILER_MSVC', 'COMPILER_MSVC32'])
   312 
   313 		if sdk == 'ep1':
   314 			if AMBuild.target['platform'] == 'linux':
   315 				staticLibs = os.path.join(sdkPath, 'linux_sdk')
   316 		else:
   317 			if AMBuild.target['platform'] == 'linux':
   318 				staticLibs = os.path.join(sdkPath, 'lib', 'linux')
   319 			elif AMBuild.target['platform'] == 'darwin':
   320 				staticLibs = os.path.join(sdkPath, 'lib', 'mac')
   321 
   322 		for i in paths:
   323 			compiler['CXXINCLUDES'].append(os.path.join(sdkPath, *i))
   324 
   325 		if not noLink:
   326 			if AMBuild.target['platform'] == 'linux':
   327 				compiler['POSTLINKFLAGS'][0:0] = ['-lm']
   328 				if sdk in ['ep2v', 'l4d', 'l4d2']:
   329 					compiler['POSTLINKFLAGS'][0:0] = ['libtier0.so']
   330 					compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.so']
   331 				else:
   332 					compiler['POSTLINKFLAGS'][0:0] = ['tier0_i486.so']
   333 					compiler['POSTLINKFLAGS'][0:0] = ['vstdlib_i486.so']
   334 			elif AMBuild.target['platform'] == 'darwin':
   335 				compiler['POSTLINKFLAGS'][0:0] = ['libtier0.dylib']
   336 				compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.dylib']
   337 
   338 		return compiler
   339 
   340 sm = SM()
   341 globals = {
   342 	'SM': sm
   343 }
   344 
   345 AMBuild.Include(os.path.join('tools', 'buildbot', 'Versioning'), globals)
   346 
   347 FileList = [
   348 		['loader', 'AMBuilder'],
   349 		['core', 'AMBuilder'],
   350 		['core', 'logic', 'AMBuilder'],
   351 		['extensions', 'bintools', 'AMBuilder'],
   352 		['extensions', 'clientprefs', 'AMBuilder'],
   353 		['extensions', 'cstrike', 'AMBuilder'],
   354 		['extensions', 'curl', 'AMBuilder'],
   355 		['extensions', 'geoip', 'AMBuilder'],
   356 		['extensions', 'mysql', 'AMBuilder'],
   357 		['extensions', 'sdktools', 'AMBuilder'],
   358 		['extensions', 'topmenus', 'AMBuilder'],
   359 		['extensions', 'updater', 'AMBuilder'],
   360 		['extensions', 'sqlite', 'AMBuilder'],
   361 		['extensions', 'regex', 'AMBuilder'],
   362 		['extensions', 'tf2', 'AMBuilder'],
   363 		['sourcepawn', 'jit', 'AMBuilder'],
   364 		['sourcepawn', 'compiler', 'AMBuilder'],
   365 		['plugins', 'AMBuilder'],
   366 		['tools', 'buildbot', 'PackageScript']
   367 	]
   368 
   369 for parts in FileList:
   370 	AMBuild.Include(os.path.join(*parts), globals)
   371