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