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 if head != None and head != oldhead:
84 (info, sdk) = findDictByKey(self.possibleSdks, 'sdk', i)
85 self.sdkInfo[sdk] = info
86 elif head == None or head == oldhead:
87 raise Exception('Could not find a valid path for {0}'.format(i))
88 AMBuild.cache.CacheVariable(i, path)
90 if len(self.sdkInfo) < 1:
91 raise Exception('At least one SDK must be available.')
93 AMBuild.cache.CacheVariable('sdkInfo', self.sdkInfo)
96 cxx = self.compiler.cxx
97 if isinstance(cxx, Cpp.CompatGCC):
98 if isinstance(cxx, Cpp.GCC):
100 elif isinstance(cxx, Cpp.Clang):
101 self.vendor = 'clang'
102 self.compiler.AddToListVar('CDEFINES', 'stricmp=strcasecmp')
103 self.compiler.AddToListVar('CDEFINES', '_stricmp=strcasecmp')
104 self.compiler.AddToListVar('CDEFINES', '_snprintf=snprintf')
105 self.compiler.AddToListVar('CDEFINES', '_vsnprintf=vsnprintf')
106 self.compiler.AddToListVar('CFLAGS', '-pipe')
107 self.compiler.AddToListVar('CFLAGS', '-fno-strict-aliasing')
108 if (self.vendor == 'gcc' and cxx.majorVersion >= 4) or self.vendor == 'clang':
109 self.compiler.AddToListVar('CFLAGS', '-fvisibility=hidden')
110 self.compiler.AddToListVar('CXXFLAGS', '-fvisibility-inlines-hidden')
111 self.compiler.AddToListVar('CFLAGS', '-Wall')
112 self.compiler.AddToListVar('CFLAGS', '-Werror')
113 self.compiler.AddToListVar('CFLAGS', '-Wno-uninitialized')
114 self.compiler.AddToListVar('CFLAGS', '-Wno-unused')
115 self.compiler.AddToListVar('CFLAGS', '-Wno-switch')
116 self.compiler.AddToListVar('CFLAGS', '-msse')
117 self.compiler.AddToListVar('CFLAGS', '-m32')
118 self.compiler.AddToListVar('CFLAGS', '-g3')
119 self.compiler.AddToListVar('POSTLINKFLAGS', '-m32')
120 self.compiler.AddToListVar('CXXFLAGS', '-fno-exceptions')
121 self.compiler.AddToListVar('CXXFLAGS', '-fno-rtti')
122 self.compiler.AddToListVar('CXXFLAGS', '-fno-threadsafe-statics')
123 self.compiler.AddToListVar('CXXFLAGS', '-Wno-non-virtual-dtor')
124 self.compiler.AddToListVar('CXXFLAGS', '-Wno-overloaded-virtual')
125 self.compiler.AddToListVar('CDEFINES', 'HAVE_STDINT_H')
126 self.compiler.AddToListVar('CDEFINES', 'GNUC')
127 if self.vendor == 'gcc':
128 self.compiler.AddToListVar('CFLAGS', '-mfpmath=sse')
129 elif isinstance(cxx, Cpp.MSVC):
131 if AMBuild.options.debug == '1':
132 self.compiler.AddToListVar('CFLAGS', '/MTd')
133 self.compiler.AddToListVar('POSTLINKFLAGS', '/NODEFAULTLIB:libcmt')
135 self.compiler.AddToListVar('CFLAGS', '/MT')
136 self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_DEPRECATE')
137 self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_WARNINGS')
138 self.compiler.AddToListVar('CDEFINES', '_CRT_NONSTDC_NO_DEPRECATE')
139 self.compiler.AddToListVar('CXXFLAGS', '/EHsc')
140 self.compiler.AddToListVar('CXXFLAGS', '/GR-')
141 self.compiler.AddToListVar('CFLAGS', '/W3')
142 self.compiler.AddToListVar('CFLAGS', '/nologo')
143 self.compiler.AddToListVar('CFLAGS', '/Zi')
144 self.compiler.AddToListVar('CXXFLAGS', '/TP')
145 self.compiler.AddToListVar('POSTLINKFLAGS', '/DEBUG')
146 self.compiler.AddToListVar('POSTLINKFLAGS', '/MACHINE:X86')
147 self.compiler.AddToListVar('POSTLINKFLAGS', '/SUBSYSTEM:WINDOWS')
148 self.compiler.AddToListVar('POSTLINKFLAGS', 'kernel32.lib')
149 self.compiler.AddToListVar('POSTLINKFLAGS', 'user32.lib')
150 self.compiler.AddToListVar('POSTLINKFLAGS', 'gdi32.lib')
151 self.compiler.AddToListVar('POSTLINKFLAGS', 'winspool.lib')
152 self.compiler.AddToListVar('POSTLINKFLAGS', 'comdlg32.lib')
153 self.compiler.AddToListVar('POSTLINKFLAGS', 'advapi32.lib')
154 self.compiler.AddToListVar('POSTLINKFLAGS', 'shell32.lib')
155 self.compiler.AddToListVar('POSTLINKFLAGS', 'ole32.lib')
156 self.compiler.AddToListVar('POSTLINKFLAGS', 'oleaut32.lib')
157 self.compiler.AddToListVar('POSTLINKFLAGS', 'uuid.lib')
158 self.compiler.AddToListVar('POSTLINKFLAGS', 'odbc32.lib')
159 self.compiler.AddToListVar('POSTLINKFLAGS', 'odbccp32.lib')
162 if AMBuild.options.opt == '1':
163 self.compiler.AddToListVar('CDEFINES', 'NDEBUG')
164 if self.vendor == 'gcc' or self.vendor == 'clang':
165 self.compiler.AddToListVar('CFLAGS', '-O3')
166 elif self.vendor == 'msvc':
167 self.compiler.AddToListVar('CFLAGS', '/Ox')
168 self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:ICF')
169 self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:REF')
172 if AMBuild.options.debug == '1':
173 self.compiler.AddToListVar('CDEFINES', 'DEBUG')
174 self.compiler.AddToListVar('CDEFINES', '_DEBUG')
175 if self.vendor == 'msvc':
176 self.compiler.AddToListVar('CFLAGS', '/Od')
177 self.compiler.AddToListVar('CFLAGS', '/RTC1')
180 if AMBuild.target['platform'] == 'linux':
181 self.compiler.AddToListVar('CDEFINES', '_LINUX')
182 if self.vendor == 'gcc':
183 self.compiler.AddToListVar('POSTLINKFLAGS', '-static-libgcc')
184 if self.vendor == 'clang':
185 self.compiler.AddToListVar('POSTLINKFLAGS', '-lgcc_eh')
186 elif AMBuild.target['platform'] == 'darwin':
187 self.compiler.AddToListVar('POSTLINKFLAGS', '-mmacosx-version-min=10.5')
188 self.compiler.AddToListVar('POSTLINKFLAGS', ['-arch', 'i386'])
189 self.compiler.AddToListVar('POSTLINKFLAGS', '-lstdc++')
191 # For OS X dylib versioning
193 productFile = open(os.path.join(AMBuild.sourceFolder, 'product.version'), 'r')
194 productContents = productFile.read()
196 m = re.match('(\d+)\.(\d+)\.(\d+).*', productContents)
198 self.version = '1.0.0'
200 major, minor, release = m.groups()
201 self.version = '{0}.{1}.{2}'.format(major, minor, release)
202 AMBuild.cache.CacheVariable('version', self.version)
203 elif AMBuild.target['platform'] == 'windows':
204 self.compiler.AddToListVar('CDEFINES', 'WIN32')
205 self.compiler.AddToListVar('CDEFINES', '_WINDOWS')
208 self.compiler.AddToListVar('CDEFINES', 'SOURCEMOD_BUILD')
209 self.compiler.AddToListVar('CDEFINES', 'SM_GENERATED_BUILD')
210 self.compiler.AddToListVar('CINCLUDES',
211 os.path.join(AMBuild.outputFolder, 'includes'))
212 self.compiler.ToConfig(AMBuild, 'compiler')
213 AMBuild.cache.CacheVariable('vendor', self.vendor)
215 AMBuild.cache.CacheVariable('targetMap', self.targetMap)
217 self.sdkInfo = AMBuild.cache['sdkInfo']
218 self.compiler.FromConfig(AMBuild, 'compiler')
219 self.targetMap = AMBuild.cache['targetMap']
221 if AMBuild.target['platform'] == 'windows':
222 self.compiler.AddToListVar('RCINCLUDES', os.path.join(AMBuild.sourceFolder, 'public'))
223 self.compiler.AddToListVar('RCINCLUDES',
224 os.path.join(AMBuild.outputFolder, 'includes'))
225 self.mmsPath = AMBuild.cache['MMSOURCE18']
227 def DefaultCompiler(self):
228 return self.compiler.Clone()
230 def JobMatters(self, jobname):
231 file = sys._getframe().f_code.co_filename
232 if AMBuild.mode == 'config':
233 self.targetMap[jobname] = file
235 if len(AMBuild.args) == 0:
237 if not jobname in AMBuild.args:
240 def DefaultExtCompiler(self, path):
241 compiler = self.DefaultCompiler()
242 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path))
243 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path, 'sdk'))
244 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public'))
245 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'extensions'))
246 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'sourcepawn'))
249 def AutoVersion(self, folder, binary):
250 if AMBuild.target['platform'] == 'windows':
251 env = {'RCDEFINES': ['BINARY_NAME="' + binary.binaryFile + '"', 'SM_GENERATED_BUILD']}
252 binary.AddResourceFile(os.path.join(folder, 'version.rc' ), env)
253 elif AMBuild.target['platform'] == 'darwin' and isinstance(binary, Cpp.LibraryBuilder):
254 binary.compiler['POSTLINKFLAGS'].extend(['-compatibility_version', '1.0.0'])
255 binary.compiler['POSTLINKFLAGS'].extend(['-current_version', AMBuild.cache['version']])
259 def StripBinary(self, job, binary):
260 workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
261 src = os.path.join('..', workFolder, binary.binaryFile)
262 if not binary.NeedsRelink(src):
264 if AMBuild.target['platform'] == 'linux':
265 job.AddCommand(ShellCommand('objcopy --only-keep-debug ' + src + ' ' + src + '.dbg'))
266 job.AddCommand(ShellCommand('objcopy --strip-debug ' + src))
267 job.AddCommand(ShellCommand('objcopy --add-gnu-debuglink=' + src + '.dbg ' + src))
268 elif AMBuild.target['platform'] == 'darwin':
269 job.AddCommand(ShellCommand('dsymutil ' + src))
270 job.AddCommand(ShellCommand('strip -S ' + src))
272 def PreSetupHL2Job(self, job, builder, sdk):
273 info = self.sdkInfo[sdk]
274 sdkPath = AMBuild.cache[info['sdk']]
275 if AMBuild.target['platform'] == 'linux':
277 staticLibs = os.path.join(sdkPath, 'linux_sdk')
279 staticLibs = os.path.join(sdkPath, 'lib', 'linux')
280 workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
281 if sdk in ['ep2v', 'l4d', 'l4d2']:
282 for i in ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.so', 'libtier0.so']:
283 link = os.path.join(workFolder, i)
284 target = os.path.join(staticLibs, i)
288 job.AddCommand(SymlinkCommand(link, target))
290 for i in ['tier1_i486.a', 'mathlib_i486.a', 'vstdlib_i486.so', 'tier0_i486.so']:
291 link = os.path.join(workFolder, i)
292 target = os.path.join(staticLibs, i)
296 job.AddCommand(SymlinkCommand(link, target))
297 elif AMBuild.target['platform'] == 'darwin':
298 staticLibs = os.path.join(sdkPath, 'lib', 'mac')
299 workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
300 for i in ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.dylib', 'libtier0.dylib']:
301 link = os.path.join(workFolder, i)
302 target = os.path.join(staticLibs, i)
306 job.AddCommand(SymlinkCommand(link, target))
307 elif AMBuild.target['platform'] == 'windows':
308 libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
310 libs.append('interfaces')
312 libPath = os.path.join(sdkPath, 'lib', 'public', lib) + '.lib'
313 builder.RebuildIfNewer(libPath)
314 builder['POSTLINKFLAGS'].append(libPath)
316 def PostSetupHL2Job(self, job, builder, sdk):
317 if AMBuild.target['platform'] in ['linux', 'darwin']:
318 builder.AddObjectFiles(['tier1_i486.a', 'mathlib_i486.a'])
320 def DefaultHL2Compiler(self, path, sdk, noLink = False, oldMms = '-legacy'):
321 compiler = self.DefaultExtCompiler(path)
327 compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms))
328 compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms, 'sourcehook'))
330 info = self.possibleSdks
331 compiler['CDEFINES'].extend(['SE_' + info[i]['name'] + '=' + info[i]['def'] for i in info])
333 paths = [['public'], ['public', 'engine'], ['public', 'mathlib'], ['public', 'vstdlib'],
334 ['public', 'tier0'], ['public', 'tier1']]
335 if sdk == 'ep1' or sdk == 'darkm':
336 paths.append(['public', 'dlls'])
337 paths.append(['game_shared'])
339 paths.append(['public', 'game', 'server'])
340 paths.append(['public', 'toolframework'])
341 paths.append(['game', 'shared'])
342 paths.append(['common'])
344 info = self.sdkInfo[sdk]
345 sdkPath = AMBuild.cache[info['sdk']]
347 compiler['CDEFINES'].append('SOURCE_ENGINE=' + info['def'])
349 if sdk == 'swarm' and AMBuild.target['platform'] == 'windows':
350 compiler['CDEFINES'].extend(['COMPILER_MSVC', 'COMPILER_MSVC32'])
353 if AMBuild.target['platform'] == 'linux':
354 staticLibs = os.path.join(sdkPath, 'linux_sdk')
356 if AMBuild.target['platform'] == 'linux':
357 staticLibs = os.path.join(sdkPath, 'lib', 'linux')
358 elif AMBuild.target['platform'] == 'darwin':
359 staticLibs = os.path.join(sdkPath, 'lib', 'mac')
362 compiler['CXXINCLUDES'].append(os.path.join(sdkPath, *i))
365 if AMBuild.target['platform'] == 'linux':
366 compiler['POSTLINKFLAGS'][0:0] = ['-lm']
367 if sdk in ['ep2v', 'l4d', 'l4d2']:
368 compiler['POSTLINKFLAGS'][0:0] = ['libtier0.so']
369 compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.so']
371 compiler['POSTLINKFLAGS'][0:0] = ['tier0_i486.so']
372 compiler['POSTLINKFLAGS'][0:0] = ['vstdlib_i486.so']
373 elif AMBuild.target['platform'] == 'darwin':
374 compiler['POSTLINKFLAGS'][0:0] = ['libtier0.dylib']
375 compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.dylib']
384 AMBuild.Include(os.path.join('tools', 'buildbot', 'Versioning'), globals)
387 ['loader', 'AMBuilder'],
388 ['core', 'AMBuilder'],
389 ['core', 'logic', 'AMBuilder'],
390 ['extensions', 'bintools', 'AMBuilder'],
391 ['extensions', 'clientprefs', 'AMBuilder'],
392 ['extensions', 'cstrike', 'AMBuilder'],
393 ['extensions', 'curl', 'AMBuilder'],
394 ['extensions', 'geoip', 'AMBuilder'],
395 ['extensions', 'mysql', 'AMBuilder'],
396 ['extensions', 'sdktools', 'AMBuilder'],
397 ['extensions', 'topmenus', 'AMBuilder'],
398 ['extensions', 'updater', 'AMBuilder'],
399 ['extensions', 'sqlite', 'AMBuilder'],
400 ['extensions', 'regex', 'AMBuilder'],
401 ['extensions', 'tf2', 'AMBuilder'],
402 ['sourcepawn', 'jit', 'AMBuilder'],
403 ['sourcepawn', 'compiler', 'AMBuilder'],
404 ['plugins', 'AMBuilder'],
405 ['tools', 'buildbot', 'PackageScript'],
406 ['tools', 'buildbot', 'BreakpadSymbols']
409 for parts in FileList:
410 AMBuild.Include(os.path.join(*parts), globals)