AMBuildScript
author David Anderson <dvander@alliedmods.net>
Sun Aug 30 00:46:56 2009 -0700 (2009-08-30)
changeset 2784 8903397125e6
child 2785 9e3d5ec34f33
permissions -rw-r--r--
More changes for new build system.
     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'}
    14 		self.sdkInfo['ep2'] =   {'sdk': 'HL2SDKOB',      'ext': '2.ep2',   'def': '3',
    15 		                         'name': 'ORANGEBOX'}
    16 		self.sdkInfo['ep2v'] =  {'sdk': 'HL2SDKOBVALVE', 'ext': '2.ep2v',  'def': '4',
    17 		                         'name': 'ORANGEBOXVALVE'}
    18 		self.sdkInfo['l4d'] =   {'sdk': 'HL2SDKL4D',     'ext': '2.l4d',   'def': '5',
    19 		                         'name': 'LEFT4DEAD'}
    20 		if AMBuild.target['platform'] == 'windows':
    21 			self.sdkInfo['darkm'] = {'sdk': 'HL2SDK-DARKM',  'ext': '2.darkm', 'def': '2',
    22 		                           'name': 'DARKMESSIAH'}
    23 
    24 		if AMBuild.mode == 'config':
    25 			#Detect compilers
    26 			self.compiler.DetectAll(AMBuild)
    27 
    28 			#Detect variables
    29 			envvars = { 'MMSOURCE17':    'mmsource-1.7',
    30 									'HL2SDK':        'hl2sdk',
    31 									'HL2SDKOB':      'hl2sdk-ob',
    32 									'HL2SDKL4D':     'hl2sdk-l4d',
    33 									'HL2SDKOBVALVE': 'hl2sdk-ob-valve',
    34 									'MYSQL5':        'mysql-5.0'
    35 			}
    36 
    37 			#Dark Messiah is Windows-only
    38 			if AMBuild.target['platform'] == 'windows':
    39 				envvars['HL2SDK-DARKM'] = 'hl2sdk-darkm'
    40 
    41 			#Must have a path for each envvar (file a bug if you don't like this)
    42 			for i in envvars:
    43 				if i in os.environ:
    44 					path = os.environ[i]
    45 					if not os.path.isdir(path):
    46 						raise Exception('Path for {0} was not found: {1}'.format(i, path))
    47 				else:
    48 					head = os.getcwd()
    49 					while head != None and head != '/':
    50 						path = os.path.join(head, envvars[i])
    51 						if os.path.isdir(path):
    52 							break
    53 						head, tail = os.path.split(head)
    54 					if head == None or head == '/':
    55 						raise Exception('Could not find a valid path for {0}'.format(i))
    56 				AMBuild.cache.CacheVariable(i, path)
    57 
    58 			#Set up defines
    59 			cxx = self.compiler.cxx
    60 			if isinstance(cxx, Cpp.GCC):
    61 				self.vendor = 'gcc'
    62 				self.compiler.AddToListVar('CDEFINES', 'stricmp=strcasecmp')
    63 				self.compiler.AddToListVar('CDEFINES', '_stricmp=strcasecmp')
    64 				self.compiler.AddToListVar('CDEFINES', '_snprintf=snprintf')
    65 				self.compiler.AddToListVar('CDEFINES', '_vsnprintf=vsnprintf')
    66 				self.compiler.AddToListVar('CFLAGS', '-pipe')
    67 				self.compiler.AddToListVar('CFLAGS', '-fno-strict-aliasing')
    68 				if cxx.majorVersion >= 4:
    69 					self.compiler.AddToListVar('CFLAGS', '-fvisibility=hidden')
    70 					self.compiler.AddToListVar('CXXFLAGS', '-fvisibility-inlines-hidden')
    71 				self.compiler.AddToListVar('CFLAGS', '-Wall')
    72 				self.compiler.AddToListVar('CFLAGS', '-Werror')
    73 				self.compiler.AddToListVar('CFLAGS', '-Wno-uninitialized')
    74 				self.compiler.AddToListVar('CFLAGS', '-Wno-unused')
    75 				self.compiler.AddToListVar('CFLAGS', '-Wno-switch')
    76 				self.compiler.AddToListVar('CFLAGS', '-mfpmath=sse')
    77 				self.compiler.AddToListVar('CFLAGS', '-msse')
    78 				self.compiler.AddToListVar('CFLAGS', '-m32')
    79 				self.compiler.AddToListVar('CFLAGS', '-static-libgcc')
    80 				self.compiler.AddToListVar('CXXFLAGS', '-fno-exceptions')
    81 				self.compiler.AddToListVar('CXXFLAGS', '-fno-rtti')
    82 				self.compiler.AddToListVar('CXXFLAGS', '-fno-threadsafe-statics')
    83 				self.compiler.AddToListVar('CXXFLAGS', '-Wno-non-virtual-dtor')
    84 				self.compiler.AddToListVar('CDEFINES', 'HAVE_STDINT_H')
    85 			elif isinstance(cxx, Cpp.MSVC):
    86 				self.vendor = 'msvc'
    87 				if AMBuild.options.debug == '1':
    88 					self.compiler.AddToListVar('CFLAGS', '/MTd')
    89 				else:
    90 					self.compiler.AddToListVar('CFLAGS', '/MT')
    91 				self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_DEPRECATE')
    92 				self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_WARNINGS')
    93 				self.compiler.AddToListVar('CDEFINES', '_CRT_NONSTDC_NO_DEPRECATE')
    94 				self.compiler.AddToListVar('CXXFLAGS', '/EHsc')
    95 				self.compiler.AddToListVar('CXXFLAGS', '/GR-')
    96 				self.compiler.AddToListVar('CFLAGS', '/W3')
    97 				self.compiler.AddToListVar('CFLAGS', '/nologo')
    98 				self.compiler.AddToListVar('CFLAGS', '/Zi')
    99 				self.compiler.AddToListVar('CXXFLAGS', '/TP')
   100 				self.compiler.AddToListVar('POSTLINKFLAGS', '/MACHINE:X86')
   101 				self.compiler.AddToListVar('POSTLINKFLAGS', '/SUBSYSTEM:WINDOWS')
   102 				self.compiler.AddToListVar('POSTLINKFLAGS', 'kernel32.lib')
   103 				self.compiler.AddToListVar('POSTLINKFLAGS', 'user32.lib')
   104 				self.compiler.AddToListVar('POSTLINKFLAGS', 'gdi32.lib')
   105 				self.compiler.AddToListVar('POSTLINKFLAGS', 'winspool.lib')
   106 				self.compiler.AddToListVar('POSTLINKFLAGS', 'comdlg32.lib')
   107 				self.compiler.AddToListVar('POSTLINKFLAGS', 'advapi32.lib')
   108 				self.compiler.AddToListVar('POSTLINKFLAGS', 'shell32.lib')
   109 				self.compiler.AddToListVar('POSTLINKFLAGS', 'ole32.lib')
   110 				self.compiler.AddToListVar('POSTLINKFLAGS', 'oleaut32.lib')
   111 				self.compiler.AddToListVar('POSTLINKFLAGS', 'uuid.lib')
   112 				self.compiler.AddToListVar('POSTLINKFLAGS', 'odbc32.lib')
   113 				self.compiler.AddToListVar('POSTLINKFLAGS', 'odbccp32.lib')
   114 
   115 			#Optimization
   116 			if AMBuild.options.opt == '1':
   117 				self.compiler.AddToListVar('CDEFINES', 'NDEBUG')
   118 				if self.vendor == 'gcc':
   119 					self.compiler.AddToListVar('CFLAGS', '-O3')
   120 				elif self.vendor == 'msvc':
   121 					self.compiler.AddToListVar('CFLAGS', '/Ot')
   122 					self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:ICF')
   123 
   124 			#Debugging
   125 			if AMBuild.options.debug == '1':
   126 				self.compiler.AddToListVar('CDEFINES', 'DEBUG')
   127 				self.compiler.AddToListVar('CDEFINES', '_DEBUG')
   128 				if self.vendor == 'gcc':
   129 					self.compiler.AddToListVar('CFLAGS', '-g3')
   130 				elif self.vendor == 'msvc':
   131 					self.compiler.AddToListVar('CFLAGS', '/Od')
   132 					self.compiler.AddToListVar('CFLAGS', '/RTC1')
   133 
   134 			#Platform-specifics
   135 			if AMBuild.target['platform'] == 'linux':
   136 				self.compiler.AddToListVar('CDEFINES', '_LINUX')
   137 			elif AMBuild.target['platform'] == 'windows':
   138 				self.compiler.AddToListVar('CDEFINES', 'WIN32')
   139 				self.compiler.AddToListVar('CDEFINES', '_WINDOWS')
   140 
   141 			#Finish up
   142 			self.compiler.AddToListVar('CDEFINES', 'SOURCEMOD_BUILD')
   143 			self.compiler.AddToListVar('CDEFINES', 'SM_GENERATED_BUILD')
   144 			self.compiler.AddToListVar('CINCLUDES',
   145 			                           os.path.join(AMBuild.outputFolder, 'includes'))
   146 			self.compiler.ToConfig(AMBuild, 'compiler')
   147 			AMBuild.cache.CacheVariable('vendor', self.vendor)
   148 			self.targetMap = { }
   149 			AMBuild.cache.CacheVariable('targetMap', self.targetMap)
   150 		else:
   151 			self.compiler.FromConfig(AMBuild, 'compiler')
   152 			self.targetMap = AMBuild.cache['targetMap']
   153 
   154 		if AMBuild.target['platform'] == 'windows':
   155 			self.compiler.AddToListVar('RCINCLUDES', os.path.join(AMBuild.sourceFolder, 'public'))
   156 		self.mmsPath = AMBuild.cache['MMSOURCE17']
   157 
   158 	def DefaultCompiler(self):
   159 		return self.compiler.Clone()
   160 
   161 	def JobMatters(self, jobname):
   162 		file = sys._getframe().f_code.co_filename
   163 		if AMBuild.mode == 'config':
   164 			self.targetMap[jobname] = file
   165 			return True
   166 		if len(AMBuild.args) == 0:
   167 			return True
   168 		if not jobname in AMBuild.args:
   169 			return False
   170 
   171 	def DefaultExtCompiler(self, path):
   172 		compiler = self.DefaultCompiler()
   173 		compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path))
   174 		compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path, 'sdk'))
   175 		compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public'))
   176 		compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'extensions'))
   177 		compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'sourcepawn'))
   178 		return compiler
   179 
   180 	def AutoVersion(self, folder, binary):
   181 		if AMBuild.target['platform'] != 'windows':
   182 			return
   183 		env = {'RCDEFINES': ['BINARY_NAME="' + binary.binaryFile + '"']}
   184 		binary.AddResourceFile(os.path.join(folder, 'version.rc' ), env)
   185 
   186 	def PreSetupHL2Job(self, job, builder, sdk):
   187 		info = self.sdkInfo[sdk]
   188 		sdkPath = AMBuild.cache[info['sdk']]
   189 		if AMBuild.target['platform'] == 'linux':
   190 			if sdk == 'ep1':
   191 				staticLibs = os.path.join(sdkPath, 'linux_sdk')
   192 			else:
   193 				staticLibs = os.path.join(sdkPath, 'lib', 'linux')
   194 			workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
   195 			for i in ['tier1_i486.a', 'mathlib_i486.a', 'vstdlib_i486.so', 'tier0_i486.so']:
   196 				link = os.path.join(workFolder, i)
   197 				target = os.path.join(staticLibs, i)
   198 				try:
   199 					os.lstat(link)
   200 				except:
   201 					job.AddCommand(SymlinkCommand(link, target))
   202 		elif AMBuild.target['platform'] == 'windows':
   203 			for lib in ['tier0', 'tier1', 'vstdlib', 'mathlib']:
   204 				libPath = os.path.join(sdkPath, 'lib', 'public', lib) + '.lib'
   205 				builder.RebuildIfNewer(libPath)
   206 				builder['POSTLINKFLAGS'].append(libPath)
   207 
   208 	def PostSetupHL2Job(self, job, builder, sdk):
   209 		if AMBuild.target['platform'] == 'linux':
   210 			builder.AddObjectFiles(['tier1_i486.a', 'mathlib_i486.a'])
   211 
   212 	def DefaultHL2Compiler(self, path, sdk, noLink = False, oldMms = '-legacy'):
   213 		compiler = self.DefaultExtCompiler(path)
   214 
   215 		mms = 'core'
   216 		if sdk == 'ep1':
   217 			mms += oldMms
   218 
   219 		compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms))
   220 		compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms, 'sourcehook'))
   221 
   222 		info = self.sdkInfo
   223 		compiler['CDEFINES'].extend(['SE_' + info[i]['name'] + '=' + info[i]['def'] for i in info])
   224 		compiler['CDEFINES'].append('SE_DARKMESSIAH=2')
   225 
   226 		paths = [['public'], ['public', 'engine'], ['public', 'mathlib'], ['public', 'vstdlib'],
   227 						 ['public', 'tier0'], ['public', 'tier1']]
   228 		if sdk == 'ep1' or sdk == 'darkm':
   229 			paths.append(['public', 'dlls'])
   230 			paths.append(['game_shared'])
   231 		else:
   232 			paths.append(['public', 'game', 'server'])
   233 			paths.append(['public', 'game', 'shared'])
   234 			paths.append(['common'])
   235 
   236 		info = self.sdkInfo[sdk]
   237 		sdkPath = AMBuild.cache[info['sdk']]
   238 
   239 		compiler['CDEFINES'].append('SOURCE_ENGINE=' + info['def'])
   240 
   241 		if sdk == 'ep1':
   242 			if AMBuild.target['platform'] == 'linux':
   243 				staticLibs = os.path.join(sdkPath, 'linux_sdk')
   244 		else:
   245 			if AMBuild.target['platform'] == 'linux':
   246 				staticLibs = os.path.join(sdkPath, 'lib', 'linux')
   247 
   248 		for i in paths:
   249 			compiler['CXXINCLUDES'].append(os.path.join(sdkPath, *i))
   250 
   251 		if not noLink:
   252 			if AMBuild.target['platform'] == 'linux':
   253 				compiler['POSTLINKFLAGS'][0:0] = ['-lm']
   254 				compiler['POSTLINKFLAGS'][0:0] = ['tier0_i486.so']
   255 				compiler['POSTLINKFLAGS'][0:0] = ['vstdlib_i486.so']
   256 
   257 		return compiler
   258 
   259 sm = SM()
   260 globals = {
   261 	'SM': sm
   262 }
   263 
   264 AMBuild.Include(os.path.join('tools', 'buildbot', 'Versioning'), globals)
   265 
   266 FileList = [
   267 		['loader', 'AMBuilder'],
   268 		['core', 'AMBuilder'],
   269 		['core', 'logic', 'AMBuilder'],
   270 		['extensions', 'bintools', 'AMBuilder'],
   271 		['extensions', 'clientprefs', 'AMBuilder'],
   272 		['extensions', 'cstrike', 'AMBuilder'],
   273 		['extensions', 'curl', 'AMBuilder'],
   274 		['extensions', 'geoip', 'AMBuilder'],
   275 		['extensions', 'mysql', 'AMBuilder'],
   276 		['extensions', 'sdktools', 'AMBuilder'],
   277 		['extensions', 'topmenus', 'AMBuilder'],
   278 		['extensions', 'updater', 'AMBuilder'],
   279 		['extensions', 'sqlite', 'AMBuilder'],
   280 		['extensions', 'regex', 'AMBuilder'],
   281 		['extensions', 'tf2', 'AMBuilder'],
   282 		['sourcepawn', 'jit', 'AMBuilder'],
   283 		['sourcepawn', 'compiler', 'AMBuilder'],
   284 		['plugins', 'AMBuilder'],
   285 		['tools', 'buildbot', 'PackageScript']
   286 	]
   287 
   288 for parts in FileList:
   289 	AMBuild.Include(os.path.join(*parts), globals)
   290