1 # vim: set ts=2 sw=2 tw=99 noet ft=python:
4 from ambuild.command import SymlinkCommand
5 from ambuild.command import ShellCommand
9 self.compiler = Cpp.Compiler()
12 self.possibleSdks = { }
13 self.possibleSdks['ep1'] = {'sdk': 'HL2SDK', 'ext': '1.ep1', 'def': '1',
14 'name': 'EPISODEONE', 'platform': ['windows', 'linux']}
15 self.possibleSdks['ep2'] = {'sdk': 'HL2SDKOB', 'ext': '2.ep2', 'def': '3',
16 'name': 'ORANGEBOX', 'platform': ['windows', 'linux']}
17 self.possibleSdks['ep2v'] = {'sdk': 'HL2SDKOBVALVE', 'ext': '2.ep2v', 'def': '6',
18 'name': 'ORANGEBOXVALVE', 'platform': ['windows', 'linux', 'darwin']}
19 self.possibleSdks['l4d'] = {'sdk': 'HL2SDKL4D', 'ext': '2.l4d', 'def': '7',
20 'name': 'LEFT4DEAD', 'platform': ['windows', 'linux', 'darwin']}
21 self.possibleSdks['l4d2'] = {'sdk': 'HL2SDKL4D2', 'ext': '2.l4d2', 'def': '8',
22 'name': 'LEFT4DEAD2', 'platform': ['windows', 'linux', 'darwin']}
23 self.possibleSdks['darkm'] = {'sdk': 'HL2SDK-DARKM', 'ext': '2.darkm', 'def': '2',
24 'name': 'DARKMESSIAH', 'platform': ['windows']}
25 self.possibleSdks['swarm'] = {'sdk': 'HL2SDK-SWARM', 'ext': '2.swarm', 'def': '9',
26 'name': 'ALIENSWARM', 'platform': ['windows']}
27 self.possibleSdks['bgt'] = {'sdk': 'HL2SDK-BGT', 'ext': '2.bgt', 'def': '4',
28 'name': 'BLOODYGOODTIME', 'platform': ['windows']}
29 self.possibleSdks['eye'] = {'sdk': 'HL2SDK-EYE', 'ext': '2.eye', 'def': '5',
30 'name': 'EYE', 'platform': ['windows']}
34 if AMBuild.mode == 'config':
36 self.compiler.DetectAll(AMBuild)
39 envvars = { 'MMSOURCE18': 'mmsource-1.8',
40 'HL2SDKOBVALVE': 'hl2sdk-ob-valve',
41 'HL2SDKL4D': 'hl2sdk-l4d',
42 'HL2SDKL4D2': 'hl2sdk-l4d2',
46 if AMBuild.target['platform'] != 'darwin':
47 envvars['HL2SDK'] = 'hl2sdk'
48 envvars['HL2SDKOB'] = 'hl2sdk-ob'
50 #Dark Messiah is Windows-only
51 if AMBuild.target['platform'] == 'windows':
52 envvars['HL2SDK-DARKM'] = 'hl2sdk-darkm'
53 envvars['HL2SDK-SWARM'] = 'hl2sdk-swarm'
54 envvars['HL2SDK-BGT'] = 'hl2sdk-bgt'
55 envvars['HL2SDK-EYE'] = 'hl2sdk-eye'
57 # Finds if a dict with `key` set to `value` is present on the dict of dicts `dictionary`
58 def findDictByKey(dictionary, key, value):
59 for index in dictionary:
60 elem = dictionary[index]
61 if elem[key] == value:
68 if not os.path.isdir(path):
69 raise Exception('Path for {0} was not found: {1}'.format(i, path))
70 elif i.startswith('HL2SDK'):
71 (info, sdk) = findDictByKey(self.possibleSdks, 'sdk', i)
72 self.sdkInfo[sdk] = info
76 while head != None and head != oldhead:
77 path = os.path.join(head, envvars[i])
78 if os.path.isdir(path):
81 head, tail = os.path.split(head)
82 if i.startswith('HL2SDK'):
83 (info, sdk) = findDictByKey(self.possibleSdks, 'sdk', i)
84 self.sdkInfo[sdk] = info
85 elif head == None or head == oldhead:
86 raise Exception('Could not find a valid path for {0}'.format(i))
87 AMBuild.cache.CacheVariable(i, path)
89 if len(self.sdkInfo) < 1:
90 raise Exception('At least one SDK must be available.')
92 AMBuild.cache.CacheVariable('sdkInfo', self.sdkInfo)
95 cxx = self.compiler.cxx
96 if isinstance(cxx, Cpp.CompatGCC):
97 if isinstance(cxx, Cpp.GCC):
99 elif isinstance(cxx, Cpp.Clang):
100 self.vendor = 'clang'
101 self.compiler.AddToListVar('CDEFINES', 'stricmp=strcasecmp')
102 self.compiler.AddToListVar('CDEFINES', '_stricmp=strcasecmp')
103 self.compiler.AddToListVar('CDEFINES', '_snprintf=snprintf')
104 self.compiler.AddToListVar('CDEFINES', '_vsnprintf=vsnprintf')
105 self.compiler.AddToListVar('CFLAGS', '-pipe')
106 self.compiler.AddToListVar('CFLAGS', '-fno-strict-aliasing')
107 if (self.vendor == 'gcc' and cxx.majorVersion >= 4) or self.vendor == 'clang':
108 self.compiler.AddToListVar('CFLAGS', '-fvisibility=hidden')
109 self.compiler.AddToListVar('CXXFLAGS', '-fvisibility-inlines-hidden')
110 self.compiler.AddToListVar('CFLAGS', '-Wall')
111 self.compiler.AddToListVar('CFLAGS', '-Werror')
112 self.compiler.AddToListVar('CFLAGS', '-Wno-uninitialized')
113 self.compiler.AddToListVar('CFLAGS', '-Wno-unused')
114 self.compiler.AddToListVar('CFLAGS', '-Wno-switch')
115 self.compiler.AddToListVar('CFLAGS', '-msse')
116 self.compiler.AddToListVar('CFLAGS', '-m32')
117 self.compiler.AddToListVar('CFLAGS', '-g3')
118 self.compiler.AddToListVar('POSTLINKFLAGS', '-m32')
119 self.compiler.AddToListVar('CXXFLAGS', '-fno-exceptions')
120 self.compiler.AddToListVar('CXXFLAGS', '-fno-rtti')
121 self.compiler.AddToListVar('CXXFLAGS', '-fno-threadsafe-statics')
122 self.compiler.AddToListVar('CXXFLAGS', '-Wno-non-virtual-dtor')
123 self.compiler.AddToListVar('CXXFLAGS', '-Wno-overloaded-virtual')
124 self.compiler.AddToListVar('CDEFINES', 'HAVE_STDINT_H')
125 self.compiler.AddToListVar('CDEFINES', 'GNUC')
126 if self.vendor == 'gcc':
127 self.compiler.AddToListVar('CFLAGS', '-mfpmath=sse')
128 elif isinstance(cxx, Cpp.MSVC):
130 if AMBuild.options.debug == '1':
131 self.compiler.AddToListVar('CFLAGS', '/MTd')
132 self.compiler.AddToListVar('POSTLINKFLAGS', '/NODEFAULTLIB:libcmt')
134 self.compiler.AddToListVar('CFLAGS', '/MT')
135 self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_DEPRECATE')
136 self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_WARNINGS')
137 self.compiler.AddToListVar('CDEFINES', '_CRT_NONSTDC_NO_DEPRECATE')
138 self.compiler.AddToListVar('CXXFLAGS', '/EHsc')
139 self.compiler.AddToListVar('CXXFLAGS', '/GR-')
140 self.compiler.AddToListVar('CFLAGS', '/W3')
141 self.compiler.AddToListVar('CFLAGS', '/nologo')
142 self.compiler.AddToListVar('CFLAGS', '/Zi')
143 self.compiler.AddToListVar('CXXFLAGS', '/TP')
144 self.compiler.AddToListVar('POSTLINKFLAGS', '/DEBUG')
145 self.compiler.AddToListVar('POSTLINKFLAGS', '/MACHINE:X86')
146 self.compiler.AddToListVar('POSTLINKFLAGS', '/SUBSYSTEM:WINDOWS')
147 self.compiler.AddToListVar('POSTLINKFLAGS', 'kernel32.lib')
148 self.compiler.AddToListVar('POSTLINKFLAGS', 'user32.lib')
149 self.compiler.AddToListVar('POSTLINKFLAGS', 'gdi32.lib')
150 self.compiler.AddToListVar('POSTLINKFLAGS', 'winspool.lib')
151 self.compiler.AddToListVar('POSTLINKFLAGS', 'comdlg32.lib')
152 self.compiler.AddToListVar('POSTLINKFLAGS', 'advapi32.lib')
153 self.compiler.AddToListVar('POSTLINKFLAGS', 'shell32.lib')
154 self.compiler.AddToListVar('POSTLINKFLAGS', 'ole32.lib')
155 self.compiler.AddToListVar('POSTLINKFLAGS', 'oleaut32.lib')
156 self.compiler.AddToListVar('POSTLINKFLAGS', 'uuid.lib')
157 self.compiler.AddToListVar('POSTLINKFLAGS', 'odbc32.lib')
158 self.compiler.AddToListVar('POSTLINKFLAGS', 'odbccp32.lib')
161 if AMBuild.options.opt == '1':
162 self.compiler.AddToListVar('CDEFINES', 'NDEBUG')
163 if self.vendor == 'gcc' or self.vendor == 'clang':
164 self.compiler.AddToListVar('CFLAGS', '-O3')
165 elif self.vendor == 'msvc':
166 self.compiler.AddToListVar('CFLAGS', '/Ox')
167 self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:ICF')
168 self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:REF')
171 if AMBuild.options.debug == '1':
172 self.compiler.AddToListVar('CDEFINES', 'DEBUG')
173 self.compiler.AddToListVar('CDEFINES', '_DEBUG')
174 if self.vendor == 'msvc':
175 self.compiler.AddToListVar('CFLAGS', '/Od')
176 self.compiler.AddToListVar('CFLAGS', '/RTC1')
179 if AMBuild.target['platform'] == 'linux':
180 self.compiler.AddToListVar('CDEFINES', '_LINUX')
181 if self.vendor == 'gcc':
182 self.compiler.AddToListVar('POSTLINKFLAGS', '-static-libgcc')
183 if self.vendor == 'clang':
184 self.compiler.AddToListVar('POSTLINKFLAGS', '-lgcc_eh')
185 elif AMBuild.target['platform'] == 'darwin':
186 self.compiler.AddToListVar('CFLAGS', ['-isysroot',
187 '/Developer/SDKs/MacOSX10.5.sdk'])
188 self.compiler.AddToListVar('POSTLINKFLAGS', '-mmacosx-version-min=10.5')
189 self.compiler.AddToListVar('POSTLINKFLAGS', ['-arch', 'i386'])
190 self.compiler.AddToListVar('POSTLINKFLAGS', '-lstdc++')
192 # For OS X dylib versioning
194 productFile = open(os.path.join(AMBuild.sourceFolder, 'product.version'), 'r')
195 productContents = productFile.read()
197 m = re.match('(\d+)\.(\d+)\.(\d+).*', productContents)
199 self.version = '1.0.0'
201 major, minor, release = m.groups()
202 self.version = '{0}.{1}.{2}'.format(major, minor, release)
203 AMBuild.cache.CacheVariable('version', self.version)
204 elif AMBuild.target['platform'] == 'windows':
205 self.compiler.AddToListVar('CDEFINES', 'WIN32')
206 self.compiler.AddToListVar('CDEFINES', '_WINDOWS')
209 self.compiler.AddToListVar('CDEFINES', 'SOURCEMOD_BUILD')
210 self.compiler.AddToListVar('CDEFINES', 'SM_GENERATED_BUILD')
211 self.compiler.AddToListVar('CINCLUDES',
212 os.path.join(AMBuild.outputFolder, 'includes'))
213 self.compiler.ToConfig(AMBuild, 'compiler')
214 AMBuild.cache.CacheVariable('vendor', self.vendor)
216 AMBuild.cache.CacheVariable('targetMap', self.targetMap)
218 self.sdkInfo = AMBuild.cache['sdkInfo']
219 self.compiler.FromConfig(AMBuild, 'compiler')
220 self.targetMap = AMBuild.cache['targetMap']
222 if AMBuild.target['platform'] == 'windows':
223 self.compiler.AddToListVar('RCINCLUDES', os.path.join(AMBuild.sourceFolder, 'public'))
224 self.compiler.AddToListVar('RCINCLUDES',
225 os.path.join(AMBuild.outputFolder, 'includes'))
226 self.mmsPath = AMBuild.cache['MMSOURCE18']
228 def DefaultCompiler(self):
229 return self.compiler.Clone()
231 def JobMatters(self, jobname):
232 file = sys._getframe().f_code.co_filename
233 if AMBuild.mode == 'config':
234 self.targetMap[jobname] = file
236 if len(AMBuild.args) == 0:
238 if not jobname in AMBuild.args:
241 def DefaultExtCompiler(self, path):
242 compiler = self.DefaultCompiler()
243 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path))
244 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path, 'sdk'))
245 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public'))
246 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'extensions'))
247 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'sourcepawn'))
250 def AutoVersion(self, folder, binary):
251 if AMBuild.target['platform'] == 'windows':
252 env = {'RCDEFINES': ['BINARY_NAME="' + binary.binaryFile + '"', 'SM_GENERATED_BUILD']}
253 binary.AddResourceFile(os.path.join(folder, 'version.rc' ), env)
254 elif AMBuild.target['platform'] == 'darwin' and isinstance(binary, Cpp.LibraryBuilder):
255 binary.compiler['POSTLINKFLAGS'].extend(['-compatibility_version', '1.0.0'])
256 binary.compiler['POSTLINKFLAGS'].extend(['-current_version', AMBuild.cache['version']])
260 def StripBinary(self, job, binary):
261 workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
262 src = os.path.join('..', workFolder, binary.binaryFile)
263 if AMBuild.target['platform'] == 'linux':
264 job.AddCommand(ShellCommand('objcopy --only-keep-debug ' + src + ' ' + src + '.dbg'))
265 job.AddCommand(ShellCommand('objcopy --strip-debug ' + src))
266 job.AddCommand(ShellCommand('objcopy --add-gnu-debuglink=' + src + '.dbg ' + src))
267 elif AMBuild.target['platform'] == 'darwin':
268 job.AddCommand(ShellCommand('dsymutil ' + src))
269 job.AddCommand(ShellCommand('strip -S ' + src))
271 def PreSetupHL2Job(self, job, builder, sdk):
272 info = self.sdkInfo[sdk]
273 sdkPath = AMBuild.cache[info['sdk']]
274 if AMBuild.target['platform'] == 'linux':
276 staticLibs = os.path.join(sdkPath, 'linux_sdk')
278 staticLibs = os.path.join(sdkPath, 'lib', 'linux')
279 workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
280 if sdk in ['ep2v', 'l4d', 'l4d2']:
281 for i in ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.so', 'libtier0.so']:
282 link = os.path.join(workFolder, i)
283 target = os.path.join(staticLibs, i)
287 job.AddCommand(SymlinkCommand(link, target))
289 for i in ['tier1_i486.a', 'mathlib_i486.a', 'vstdlib_i486.so', 'tier0_i486.so']:
290 link = os.path.join(workFolder, i)
291 target = os.path.join(staticLibs, i)
295 job.AddCommand(SymlinkCommand(link, target))
296 elif AMBuild.target['platform'] == 'darwin':
297 staticLibs = os.path.join(sdkPath, 'lib', 'mac')
298 workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
299 for i in ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.dylib', 'libtier0.dylib']:
300 link = os.path.join(workFolder, i)
301 target = os.path.join(staticLibs, i)
305 job.AddCommand(SymlinkCommand(link, target))
306 elif AMBuild.target['platform'] == 'windows':
307 libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
309 libs.append('interfaces')
311 libPath = os.path.join(sdkPath, 'lib', 'public', lib) + '.lib'
312 builder.RebuildIfNewer(libPath)
313 builder['POSTLINKFLAGS'].append(libPath)
315 def PostSetupHL2Job(self, job, builder, sdk):
316 if AMBuild.target['platform'] in ['linux', 'darwin']:
317 builder.AddObjectFiles(['tier1_i486.a', 'mathlib_i486.a'])
319 def DefaultHL2Compiler(self, path, sdk, noLink = False, oldMms = '-legacy'):
320 compiler = self.DefaultExtCompiler(path)
326 compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms))
327 compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms, 'sourcehook'))
329 info = self.possibleSdks
330 compiler['CDEFINES'].extend(['SE_' + info[i]['name'] + '=' + info[i]['def'] for i in info])
332 paths = [['public'], ['public', 'engine'], ['public', 'mathlib'], ['public', 'vstdlib'],
333 ['public', 'tier0'], ['public', 'tier1']]
334 if sdk == 'ep1' or sdk == 'darkm':
335 paths.append(['public', 'dlls'])
336 paths.append(['game_shared'])
338 paths.append(['public', 'game', 'server'])
339 paths.append(['public', 'toolframework'])
340 paths.append(['game', 'shared'])
341 paths.append(['common'])
343 info = self.sdkInfo[sdk]
344 sdkPath = AMBuild.cache[info['sdk']]
346 compiler['CDEFINES'].append('SOURCE_ENGINE=' + info['def'])
348 if sdk == 'swarm' and AMBuild.target['platform'] == 'windows':
349 compiler['CDEFINES'].extend(['COMPILER_MSVC', 'COMPILER_MSVC32'])
352 if AMBuild.target['platform'] == 'linux':
353 staticLibs = os.path.join(sdkPath, 'linux_sdk')
355 if AMBuild.target['platform'] == 'linux':
356 staticLibs = os.path.join(sdkPath, 'lib', 'linux')
357 elif AMBuild.target['platform'] == 'darwin':
358 staticLibs = os.path.join(sdkPath, 'lib', 'mac')
361 compiler['CXXINCLUDES'].append(os.path.join(sdkPath, *i))
364 if AMBuild.target['platform'] == 'linux':
365 compiler['POSTLINKFLAGS'][0:0] = ['-lm']
366 if sdk in ['ep2v', 'l4d', 'l4d2']:
367 compiler['POSTLINKFLAGS'][0:0] = ['libtier0.so']
368 compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.so']
370 compiler['POSTLINKFLAGS'][0:0] = ['tier0_i486.so']
371 compiler['POSTLINKFLAGS'][0:0] = ['vstdlib_i486.so']
372 elif AMBuild.target['platform'] == 'darwin':
373 compiler['POSTLINKFLAGS'][0:0] = ['libtier0.dylib']
374 compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.dylib']
383 AMBuild.Include(os.path.join('tools', 'buildbot', 'Versioning'), globals)
386 ['loader', 'AMBuilder'],
387 ['core', 'AMBuilder'],
388 ['core', 'logic', 'AMBuilder'],
389 ['extensions', 'bintools', 'AMBuilder'],
390 ['extensions', 'clientprefs', 'AMBuilder'],
391 ['extensions', 'cstrike', 'AMBuilder'],
392 ['extensions', 'curl', 'AMBuilder'],
393 ['extensions', 'geoip', 'AMBuilder'],
394 ['extensions', 'mysql', 'AMBuilder'],
395 ['extensions', 'sdktools', 'AMBuilder'],
396 ['extensions', 'topmenus', 'AMBuilder'],
397 ['extensions', 'updater', 'AMBuilder'],
398 ['extensions', 'sqlite', 'AMBuilder'],
399 ['extensions', 'regex', 'AMBuilder'],
400 ['extensions', 'tf2', 'AMBuilder'],
401 ['sourcepawn', 'jit', 'AMBuilder'],
402 ['sourcepawn', 'compiler', 'AMBuilder'],
403 ['plugins', 'AMBuilder'],
404 ['tools', 'buildbot', 'PackageScript'],
405 ['tools', 'buildbot', 'BreakpadSymbols']
408 for parts in FileList:
409 AMBuild.Include(os.path.join(*parts), globals)