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