AMBuildScript
author Scott Ehlert <ds@alliedmods.net>
Fri May 14 01:04:17 2010 -0500 (2010-05-14)
changeset 2997 558d6fec66ad
parent 2993 76da4d93e0d6
child 2998 94e008ed3db9
permissions -rw-r--r--
Fixed loader on Mac OS X (bug 4392, r=dvander).
     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', '/Ot')
   130 					self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:ICF')
   131 
   132 			#Debugging
   133 			if AMBuild.options.debug == '1':
   134 				self.compiler.AddToListVar('CDEFINES', 'DEBUG')
   135 				self.compiler.AddToListVar('CDEFINES', '_DEBUG')
   136 				if self.vendor == 'gcc':
   137 					self.compiler.AddToListVar('CFLAGS', '-g3')
   138 				elif self.vendor == 'msvc':
   139 					self.compiler.AddToListVar('CFLAGS', '/Od')
   140 					self.compiler.AddToListVar('CFLAGS', '/RTC1')
   141 
   142 			#Platform-specifics
   143 			if AMBuild.target['platform'] == 'linux':
   144 				self.compiler.AddToListVar('CDEFINES', '_LINUX')
   145 			elif AMBuild.target['platform'] == 'darwin':
   146 				self.compiler.AddToListVar('CFLAGS', ['-isysroot',
   147 				                                      '/Developer/SDKs/MacOSX10.5.sdk'])
   148 				self.compiler.AddToListVar('POSTLINKFLAGS', '-mmacosx-version-min=10.5')
   149 				self.compiler.AddToListVar('POSTLINKFLAGS', ['-arch', 'i386'])
   150 				self.compiler.AddToListVar('POSTLINKFLAGS', '-lstdc++')
   151 			elif AMBuild.target['platform'] == 'windows':
   152 				self.compiler.AddToListVar('CDEFINES', 'WIN32')
   153 				self.compiler.AddToListVar('CDEFINES', '_WINDOWS')
   154 
   155 			#Finish up
   156 			self.compiler.AddToListVar('CDEFINES', 'SOURCEMOD_BUILD')
   157 			self.compiler.AddToListVar('CDEFINES', 'SM_GENERATED_BUILD')
   158 			self.compiler.AddToListVar('CINCLUDES',
   159 			                           os.path.join(AMBuild.outputFolder, 'includes'))
   160 			self.compiler.ToConfig(AMBuild, 'compiler')
   161 			AMBuild.cache.CacheVariable('vendor', self.vendor)
   162 			self.targetMap = { }
   163 			AMBuild.cache.CacheVariable('targetMap', self.targetMap)
   164 		else:
   165 			self.compiler.FromConfig(AMBuild, 'compiler')
   166 			self.targetMap = AMBuild.cache['targetMap']
   167 
   168 		if AMBuild.target['platform'] == 'windows':
   169 			self.compiler.AddToListVar('RCINCLUDES', os.path.join(AMBuild.sourceFolder, 'public'))
   170 			self.compiler.AddToListVar('RCINCLUDES',
   171 			                           os.path.join(AMBuild.outputFolder, 'includes'))
   172 		self.mmsPath = AMBuild.cache['MMSOURCE18']
   173 
   174 	def DefaultCompiler(self):
   175 		return self.compiler.Clone()
   176 
   177 	def JobMatters(self, jobname):
   178 		file = sys._getframe().f_code.co_filename
   179 		if AMBuild.mode == 'config':
   180 			self.targetMap[jobname] = file
   181 			return True
   182 		if len(AMBuild.args) == 0:
   183 			return True
   184 		if not jobname in AMBuild.args:
   185 			return False
   186 
   187 	def DefaultExtCompiler(self, path):
   188 		compiler = self.DefaultCompiler()
   189 		compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path))
   190 		compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path, 'sdk'))
   191 		compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public'))
   192 		compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'extensions'))
   193 		compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'sourcepawn'))
   194 		return compiler
   195 
   196 	def AutoVersion(self, folder, binary):
   197 		if AMBuild.target['platform'] != 'windows':
   198 			return
   199 		env = {'RCDEFINES': ['BINARY_NAME="' + binary.binaryFile + '"', 'SM_GENERATED_BUILD']}
   200 		binary.AddResourceFile(os.path.join(folder, 'version.rc' ), env)
   201 
   202 	def PreSetupHL2Job(self, job, builder, sdk):
   203 		info = self.sdkInfo[sdk]
   204 		sdkPath = AMBuild.cache[info['sdk']]
   205 		if AMBuild.target['platform'] == 'linux':
   206 			if sdk == 'ep1':
   207 				staticLibs = os.path.join(sdkPath, 'linux_sdk')
   208 			else:
   209 				staticLibs = os.path.join(sdkPath, 'lib', 'linux')
   210 			workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
   211 			if sdk == 'ep2v' or sdk == 'l4d2':
   212 				for i in ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.so', 'libtier0.so']:
   213 					link = os.path.join(workFolder, i)
   214 					target = os.path.join(staticLibs, i)
   215 					try:
   216 						os.lstat(link)
   217 					except:
   218 						job.AddCommand(SymlinkCommand(link, target))
   219 			else:
   220 				for i in ['tier1_i486.a', 'mathlib_i486.a', 'vstdlib_i486.so', 'tier0_i486.so']:
   221 					link = os.path.join(workFolder, i)
   222 					target = os.path.join(staticLibs, i)
   223 					try:
   224 						os.lstat(link)
   225 					except:
   226 						job.AddCommand(SymlinkCommand(link, target))
   227 		elif AMBuild.target['platform'] == 'darwin':
   228 			staticLibs = os.path.join(sdkPath, 'lib', 'mac')
   229 			workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
   230 			for i in ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.dylib', 'libtier0.dylib']:
   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 		elif AMBuild.target['platform'] == 'windows':
   238 			for lib in ['tier0', 'tier1', 'vstdlib', 'mathlib']:
   239 				libPath = os.path.join(sdkPath, 'lib', 'public', lib) + '.lib'
   240 				builder.RebuildIfNewer(libPath)
   241 				builder['POSTLINKFLAGS'].append(libPath)
   242 
   243 	def PostSetupHL2Job(self, job, builder, sdk):
   244 		if AMBuild.target['platform'] in ['linux', 'darwin']:
   245 			builder.AddObjectFiles(['tier1_i486.a', 'mathlib_i486.a'])
   246 
   247 	def DefaultHL2Compiler(self, path, sdk, noLink = False, oldMms = '-legacy'):
   248 		compiler = self.DefaultExtCompiler(path)
   249 
   250 		mms = 'core'
   251 		if sdk == 'ep1':
   252 			mms += oldMms
   253 
   254 		compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms))
   255 		compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms, 'sourcehook'))
   256 
   257 		info = self.sdkInfo
   258 		compiler['CDEFINES'].extend(['SE_' + info[i]['name'] + '=' + info[i]['def'] for i in info])
   259 
   260 		paths = [['public'], ['public', 'engine'], ['public', 'mathlib'], ['public', 'vstdlib'],
   261 						 ['public', 'tier0'], ['public', 'tier1']]
   262 		if sdk == 'ep1' or sdk == 'darkm':
   263 			paths.append(['public', 'dlls'])
   264 			paths.append(['game_shared'])
   265 		else:
   266 			paths.append(['public', 'game', 'server'])
   267 			paths.append(['game', 'shared'])
   268 			paths.append(['common'])
   269 
   270 		info = self.sdkInfo[sdk]
   271 		sdkPath = AMBuild.cache[info['sdk']]
   272 
   273 		compiler['CDEFINES'].append('SOURCE_ENGINE=' + info['def'])
   274 
   275 		if sdk == 'ep1':
   276 			if AMBuild.target['platform'] == 'linux':
   277 				staticLibs = os.path.join(sdkPath, 'linux_sdk')
   278 		else:
   279 			if AMBuild.target['platform'] == 'linux':
   280 				staticLibs = os.path.join(sdkPath, 'lib', 'linux')
   281 			elif AMBuild.target['platform'] == 'darwin':
   282 				staticLibs = os.path.join(sdkPath, 'lib', 'mac')
   283 
   284 		for i in paths:
   285 			compiler['CXXINCLUDES'].append(os.path.join(sdkPath, *i))
   286 
   287 		if not noLink:
   288 			if AMBuild.target['platform'] == 'linux':
   289 				compiler['POSTLINKFLAGS'][0:0] = ['-lm']
   290 				if sdk == 'ep2v' or sdk == 'l4d2':
   291 					compiler['POSTLINKFLAGS'][0:0] = ['libtier0.so']
   292 					compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.so']
   293 				else:
   294 					compiler['POSTLINKFLAGS'][0:0] = ['tier0_i486.so']
   295 					compiler['POSTLINKFLAGS'][0:0] = ['vstdlib_i486.so']
   296 			elif AMBuild.target['platform'] == 'darwin':
   297 				compiler['POSTLINKFLAGS'][0:0] = ['libtier0.dylib']
   298 				compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.dylib']
   299 
   300 		return compiler
   301 
   302 sm = SM()
   303 globals = {
   304 	'SM': sm
   305 }
   306 
   307 AMBuild.Include(os.path.join('tools', 'buildbot', 'Versioning'), globals)
   308 
   309 FileList = [
   310 		['loader', 'AMBuilder'],
   311 		['core', 'AMBuilder'],
   312 		['core', 'logic', 'AMBuilder'],
   313 		['extensions', 'bintools', 'AMBuilder'],
   314 		['extensions', 'clientprefs', 'AMBuilder'],
   315 		['extensions', 'cstrike', 'AMBuilder'],
   316 		['extensions', 'curl', 'AMBuilder'],
   317 		['extensions', 'geoip', 'AMBuilder'],
   318 		['extensions', 'mysql', 'AMBuilder'],
   319 		['extensions', 'sdktools', 'AMBuilder'],
   320 		['extensions', 'topmenus', 'AMBuilder'],
   321 		['extensions', 'updater', 'AMBuilder'],
   322 		['extensions', 'sqlite', 'AMBuilder'],
   323 		['extensions', 'regex', 'AMBuilder'],
   324 		['extensions', 'tf2', 'AMBuilder'],
   325 		['sourcepawn', 'jit', 'AMBuilder'],
   326 		['sourcepawn', 'compiler', 'AMBuilder'],
   327 		['plugins', 'AMBuilder'],
   328 		['tools', 'buildbot', 'PackageScript']
   329 	]
   330 
   331 for parts in FileList:
   332 	AMBuild.Include(os.path.join(*parts), globals)
   333