1 # vim: set ts=2 sw=2 tw=99 noet ft=python:
4 from ambuild.command import SymlinkCommand
8 self.compiler = Cpp.Compiler()
11 self.possibleSdks = { }
12 self.possibleSdks['ep1'] = {'sdk': 'HL2SDK', 'ext': '1.ep1', 'def': '1',
13 'name': 'EPISODEONE', 'platform': ['windows', 'linux']}
14 self.possibleSdks['ep2'] = {'sdk': 'HL2SDKOB', 'ext': '2.ep2', 'def': '3',
15 'name': 'ORANGEBOX', 'platform': ['windows', 'linux']}
16 self.possibleSdks['ep2v'] = {'sdk': 'HL2SDKOBVALVE', 'ext': '2.ep2v', 'def': '6',
17 'name': 'ORANGEBOXVALVE', 'platform': ['windows', 'linux', 'darwin']}
18 self.possibleSdks['l4d'] = {'sdk': 'HL2SDKL4D', 'ext': '2.l4d', 'def': '7',
19 'name': 'LEFT4DEAD', 'platform': ['windows', 'linux', 'darwin']}
20 self.possibleSdks['l4d2'] = {'sdk': 'HL2SDKL4D2', 'ext': '2.l4d2', 'def': '8',
21 'name': 'LEFT4DEAD2', 'platform': ['windows', 'linux', 'darwin']}
22 self.possibleSdks['darkm'] = {'sdk': 'HL2SDK-DARKM', 'ext': '2.darkm', 'def': '2',
23 'name': 'DARKMESSIAH', 'platform': ['windows']}
24 self.possibleSdks['swarm'] = {'sdk': 'HL2SDK-SWARM', 'ext': '2.swarm', 'def': '9',
25 'name': 'ALIENSWARM', 'platform': ['windows']}
26 self.possibleSdks['bgt'] = {'sdk': 'HL2SDK-BGT', 'ext': '2.bgt', 'def': '4',
27 'name': 'BLOODYGOODTIME', 'platform': ['windows']}
28 self.possibleSdks['eye'] = {'sdk': 'HL2SDK-EYE', 'ext': '2.eye', 'def': '5',
29 'name': 'EYE', 'platform': ['windows']}
30 self.possibleSdks['csgo'] = {'sdk': 'HL2SDKCSGO', 'ext': '2.csgo', 'def': '11',
31 'name': 'CSGO', 'platform': ['windows', 'linux']}
32 # self.possibleSdks['portal2'] = {'sdk': 'HL2SDK-PORTAL2', 'ext': '2.portal2', 'def': '10',
33 # 'name': 'PORTAL2', 'platform': ['windows']}
37 if AMBuild.mode == 'config':
39 self.compiler.DetectAll(AMBuild)
42 envvars = { 'MMSOURCE19': 'mmsource-1.9',
43 'HL2SDKOBVALVE': 'hl2sdk-ob-valve',
44 'HL2SDKL4D': 'hl2sdk-l4d',
45 'HL2SDKL4D2': 'hl2sdk-l4d2',
49 if AMBuild.target['platform'] != 'darwin':
50 envvars['HL2SDK'] = 'hl2sdk'
51 envvars['HL2SDKOB'] = 'hl2sdk-ob'
52 envvars['HL2SDKCSGO'] = 'hl2sdk-csgo'
54 #Dark Messiah is Windows-only
55 if AMBuild.target['platform'] == 'windows':
56 envvars['HL2SDK-DARKM'] = 'hl2sdk-darkm'
57 envvars['HL2SDK-SWARM'] = 'hl2sdk-swarm'
58 envvars['HL2SDK-BGT'] = 'hl2sdk-bgt'
59 envvars['HL2SDK-EYE'] = 'hl2sdk-eye'
61 # Finds if a dict with `key` set to `value` is present on the dict of dicts `dictionary`
62 def findDictByKey(dictionary, key, value):
63 for index in dictionary:
64 elem = dictionary[index]
65 if elem[key] == value:
72 if not os.path.isdir(path):
73 raise Exception('Path for {0} was not found: {1}'.format(i, path))
74 elif i.startswith('HL2SDK'):
75 (info, sdk) = findDictByKey(self.possibleSdks, 'sdk', i)
76 self.sdkInfo[sdk] = info
80 while head != None and head != oldhead:
81 path = os.path.join(head, envvars[i])
82 if os.path.isdir(path):
85 head, tail = os.path.split(head)
86 if i.startswith('HL2SDK'):
87 if head != None and head != oldhead:
88 (info, sdk) = findDictByKey(self.possibleSdks, 'sdk', i)
89 self.sdkInfo[sdk] = info
90 elif head == None or head == oldhead:
91 raise Exception('Could not find a valid path for {0}'.format(i))
92 AMBuild.cache.CacheVariable(i, path)
94 if len(self.sdkInfo) < 1:
95 raise Exception('At least one SDK must be available.')
97 AMBuild.cache.CacheVariable('sdkInfo', self.sdkInfo)
100 cxx = self.compiler.cxx
101 if isinstance(cxx, Cpp.CompatGCC):
102 if isinstance(cxx, Cpp.GCC):
104 elif isinstance(cxx, Cpp.Clang):
105 self.vendor = 'clang'
106 self.compiler.AddToListVar('CDEFINES', 'stricmp=strcasecmp')
107 self.compiler.AddToListVar('CDEFINES', '_stricmp=strcasecmp')
108 self.compiler.AddToListVar('CDEFINES', '_snprintf=snprintf')
109 self.compiler.AddToListVar('CDEFINES', '_vsnprintf=vsnprintf')
110 self.compiler.AddToListVar('CFLAGS', '-pipe')
111 self.compiler.AddToListVar('CFLAGS', '-fno-strict-aliasing')
112 if (self.vendor == 'gcc' and cxx.majorVersion >= 4) or self.vendor == 'clang':
113 self.compiler.AddToListVar('CFLAGS', '-fvisibility=hidden')
114 self.compiler.AddToListVar('CXXFLAGS', '-fvisibility-inlines-hidden')
115 self.compiler.AddToListVar('CFLAGS', '-Wall')
116 self.compiler.AddToListVar('CFLAGS', '-Werror')
117 self.compiler.AddToListVar('CFLAGS', '-Wno-uninitialized')
118 self.compiler.AddToListVar('CFLAGS', '-Wno-unused')
119 self.compiler.AddToListVar('CFLAGS', '-Wno-switch')
120 self.compiler.AddToListVar('CFLAGS', '-msse')
121 self.compiler.AddToListVar('CFLAGS', '-m32')
122 self.compiler.AddToListVar('POSTLINKFLAGS', '-m32')
123 self.compiler.AddToListVar('CXXFLAGS', '-fno-exceptions')
124 self.compiler.AddToListVar('CXXFLAGS', '-fno-rtti')
125 self.compiler.AddToListVar('CXXFLAGS', '-fno-threadsafe-statics')
126 self.compiler.AddToListVar('CXXFLAGS', '-Wno-non-virtual-dtor')
127 self.compiler.AddToListVar('CXXFLAGS', '-Wno-overloaded-virtual')
128 if (self.vendor == 'gcc' and cxx.majorVersion >= 4 and cxx.minorVersion >= 7) or \
129 (self.vendor == 'clang' and cxx.majorVersion >= 3):
130 self.compiler.AddToListVar('CXXFLAGS', '-Wno-delete-non-virtual-dtor')
131 self.compiler.AddToListVar('CDEFINES', 'HAVE_STDINT_H')
132 self.compiler.AddToListVar('CDEFINES', 'GNUC')
133 if self.vendor == 'gcc':
134 self.compiler.AddToListVar('CFLAGS', '-mfpmath=sse')
135 elif isinstance(cxx, Cpp.MSVC):
137 if AMBuild.options.debug == '1':
138 self.compiler.AddToListVar('CFLAGS', '/MTd')
139 self.compiler.AddToListVar('POSTLINKFLAGS', '/NODEFAULTLIB:libcmt')
141 self.compiler.AddToListVar('CFLAGS', '/MT')
142 self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_DEPRECATE')
143 self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_WARNINGS')
144 self.compiler.AddToListVar('CDEFINES', '_CRT_NONSTDC_NO_DEPRECATE')
145 self.compiler.AddToListVar('CXXFLAGS', '/EHsc')
146 self.compiler.AddToListVar('CXXFLAGS', '/GR-')
147 self.compiler.AddToListVar('CFLAGS', '/W3')
148 self.compiler.AddToListVar('CFLAGS', '/nologo')
149 self.compiler.AddToListVar('CFLAGS', '/Zi')
150 self.compiler.AddToListVar('CXXFLAGS', '/TP')
151 self.compiler.AddToListVar('POSTLINKFLAGS', '/DEBUG')
152 self.compiler.AddToListVar('POSTLINKFLAGS', '/MACHINE:X86')
153 self.compiler.AddToListVar('POSTLINKFLAGS', '/SUBSYSTEM:WINDOWS')
154 self.compiler.AddToListVar('POSTLINKFLAGS', 'kernel32.lib')
155 self.compiler.AddToListVar('POSTLINKFLAGS', 'user32.lib')
156 self.compiler.AddToListVar('POSTLINKFLAGS', 'gdi32.lib')
157 self.compiler.AddToListVar('POSTLINKFLAGS', 'winspool.lib')
158 self.compiler.AddToListVar('POSTLINKFLAGS', 'comdlg32.lib')
159 self.compiler.AddToListVar('POSTLINKFLAGS', 'advapi32.lib')
160 self.compiler.AddToListVar('POSTLINKFLAGS', 'shell32.lib')
161 self.compiler.AddToListVar('POSTLINKFLAGS', 'ole32.lib')
162 self.compiler.AddToListVar('POSTLINKFLAGS', 'oleaut32.lib')
163 self.compiler.AddToListVar('POSTLINKFLAGS', 'uuid.lib')
164 self.compiler.AddToListVar('POSTLINKFLAGS', 'odbc32.lib')
165 self.compiler.AddToListVar('POSTLINKFLAGS', 'odbccp32.lib')
168 if AMBuild.options.opt == '1':
169 self.compiler.AddToListVar('CDEFINES', 'NDEBUG')
170 if self.vendor == 'gcc' or self.vendor == 'clang':
171 self.compiler.AddToListVar('CFLAGS', '-O3')
172 elif self.vendor == 'msvc':
173 self.compiler.AddToListVar('CFLAGS', '/Ox')
174 self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:ICF')
175 self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:REF')
178 if AMBuild.options.debug == '1':
179 self.compiler.AddToListVar('CDEFINES', 'DEBUG')
180 self.compiler.AddToListVar('CDEFINES', '_DEBUG')
181 if self.vendor == 'gcc' or self.vendor == 'clang':
182 self.compiler.AddToListVar('CFLAGS', '-g3')
183 elif self.vendor == 'msvc':
184 self.compiler.AddToListVar('CFLAGS', '/Od')
185 self.compiler.AddToListVar('CFLAGS', '/RTC1')
188 if AMBuild.target['platform'] == 'linux':
189 self.compiler.AddToListVar('CDEFINES', '_LINUX')
190 if self.vendor == 'gcc':
191 self.compiler.AddToListVar('POSTLINKFLAGS', '-static-libgcc')
192 if self.vendor == 'clang':
193 self.compiler.AddToListVar('POSTLINKFLAGS', '-lgcc_eh')
194 elif AMBuild.target['platform'] == 'darwin':
195 self.compiler.AddToListVar('POSTLINKFLAGS', '-mmacosx-version-min=10.5')
196 self.compiler.AddToListVar('POSTLINKFLAGS', ['-arch', 'i386'])
197 self.compiler.AddToListVar('POSTLINKFLAGS', '-lstdc++')
199 # For OS X dylib versioning
201 productFile = open(os.path.join(AMBuild.sourceFolder, 'product.version'), 'r')
202 productContents = productFile.read()
204 m = re.match('(\d+)\.(\d+)\.(\d+).*', productContents)
206 self.version = '1.0.0'
208 major, minor, release = m.groups()
209 self.version = '{0}.{1}.{2}'.format(major, minor, release)
210 AMBuild.cache.CacheVariable('version', self.version)
211 elif AMBuild.target['platform'] == 'windows':
212 self.compiler.AddToListVar('CDEFINES', 'WIN32')
213 self.compiler.AddToListVar('CDEFINES', '_WINDOWS')
216 self.compiler.AddToListVar('CDEFINES', 'SOURCEMOD_BUILD')
217 self.compiler.AddToListVar('CDEFINES', 'SM_GENERATED_BUILD')
218 self.compiler.AddToListVar('CINCLUDES',
219 os.path.join(AMBuild.outputFolder, 'includes'))
220 self.compiler.ToConfig(AMBuild, 'compiler')
221 AMBuild.cache.CacheVariable('vendor', self.vendor)
223 AMBuild.cache.CacheVariable('targetMap', self.targetMap)
225 self.sdkInfo = AMBuild.cache['sdkInfo']
226 self.compiler.FromConfig(AMBuild, 'compiler')
227 self.targetMap = AMBuild.cache['targetMap']
229 if AMBuild.target['platform'] == 'windows':
230 self.compiler.AddToListVar('RCINCLUDES', os.path.join(AMBuild.sourceFolder, 'public'))
231 self.compiler.AddToListVar('RCINCLUDES',
232 os.path.join(AMBuild.outputFolder, 'includes'))
233 self.mmsPath = AMBuild.cache['MMSOURCE19']
235 def DefaultCompiler(self):
236 return self.compiler.Clone()
238 def JobMatters(self, jobname):
239 file = sys._getframe().f_code.co_filename
240 if AMBuild.mode == 'config':
241 self.targetMap[jobname] = file
243 if len(AMBuild.args) == 0:
245 if not jobname in AMBuild.args:
248 def DefaultExtCompiler(self, path):
249 compiler = self.DefaultCompiler()
250 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path))
251 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path, 'sdk'))
252 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public'))
253 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'extensions'))
254 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'sourcepawn'))
257 def AutoVersion(self, folder, binary):
258 if AMBuild.target['platform'] == 'windows':
259 env = {'RCDEFINES': ['BINARY_NAME="' + binary.binaryFile + '"', 'SM_GENERATED_BUILD']}
260 binary.AddResourceFile(os.path.join(folder, 'version.rc' ), env)
261 elif AMBuild.target['platform'] == 'darwin' and isinstance(binary, Cpp.LibraryBuilder):
262 binary.compiler['POSTLINKFLAGS'].extend(['-compatibility_version', '1.0.0'])
263 binary.compiler['POSTLINKFLAGS'].extend(['-current_version', AMBuild.cache['version']])
267 def PreSetupHL2Job(self, job, builder, sdk):
268 info = self.sdkInfo[sdk]
269 sdkPath = AMBuild.cache[info['sdk']]
270 if AMBuild.target['platform'] == 'linux':
272 staticLibs = os.path.join(sdkPath, 'linux_sdk')
274 staticLibs = os.path.join(sdkPath, 'lib', 'linux')
275 workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
276 if sdk in ['ep2v', 'l4d', 'l4d2', 'csgo']:
277 libs = ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.so', 'libtier0.so']
279 libs.append('interfaces_i486.a')
281 link = os.path.join(workFolder, lib)
282 target = os.path.join(staticLibs, lib)
286 job.AddCommand(SymlinkCommand(link, target))
288 libs = ['tier1_i486.a', 'mathlib_i486.a', 'vstdlib_i486.so', 'tier0_i486.so']
290 link = os.path.join(workFolder, lib)
291 target = os.path.join(staticLibs, lib)
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 libs = ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.dylib', 'libtier0.dylib']
301 libs.append('interfaces_i486.a')
303 link = os.path.join(workFolder, lib)
304 target = os.path.join(staticLibs, lib)
308 job.AddCommand(SymlinkCommand(link, target))
309 elif AMBuild.target['platform'] == 'windows':
310 libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
311 if sdk in ['swarm', 'csgo']:
312 libs.append('interfaces')
314 libPath = os.path.join(sdkPath, 'lib', 'public', lib) + '.lib'
315 builder.RebuildIfNewer(libPath)
316 builder['POSTLINKFLAGS'].append(libPath)
318 def PostSetupHL2Job(self, job, builder, sdk):
319 if AMBuild.target['platform'] in ['linux', 'darwin']:
320 builder.AddObjectFiles(['tier1_i486.a', 'mathlib_i486.a'])
322 builder.AddObjectFiles(['interfaces_i486.a'])
324 def DefaultHL2Compiler(self, path, sdk, noLink = False, oldMms = '-legacy'):
325 compiler = self.DefaultExtCompiler(path)
331 compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms))
332 compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms, 'sourcehook'))
334 info = self.possibleSdks
335 compiler['CDEFINES'].extend(['SE_' + info[i]['name'] + '=' + info[i]['def'] for i in info])
337 # We don't build for Portal 2 (yet?, ever?), but using this define in code as
338 # it saves trouble if we ever need to
339 compiler['CDEFINES'].append('SE_PORTAL2=10')
341 paths = [['public'], ['public', 'engine'], ['public', 'mathlib'], ['public', 'vstdlib'],
342 ['public', 'tier0'], ['public', 'tier1']]
343 if sdk == 'ep1' or sdk == 'darkm':
344 paths.append(['public', 'dlls'])
345 paths.append(['game_shared'])
347 paths.append(['public', 'game', 'server'])
348 paths.append(['public', 'toolframework'])
349 paths.append(['game', 'shared'])
350 paths.append(['common'])
352 info = self.sdkInfo[sdk]
353 sdkPath = AMBuild.cache[info['sdk']]
355 compiler['CDEFINES'].append('SOURCE_ENGINE=' + info['def'])
357 if sdk in ['swarm','csgo']:
358 if AMBuild.target['platform'] == 'windows':
359 compiler['CDEFINES'].extend(['COMPILER_MSVC', 'COMPILER_MSVC32'])
361 compiler['CDEFINES'].extend(['COMPILER_GCC', 'POSIX'])
364 if AMBuild.target['platform'] == 'linux':
365 staticLibs = os.path.join(sdkPath, 'linux_sdk')
367 if AMBuild.target['platform'] == 'linux':
368 staticLibs = os.path.join(sdkPath, 'lib', 'linux')
369 elif AMBuild.target['platform'] == 'darwin':
370 staticLibs = os.path.join(sdkPath, 'lib', 'mac')
373 compiler['CXXINCLUDES'].append(os.path.join(sdkPath, *i))
376 if AMBuild.target['platform'] == 'linux':
377 compiler['POSTLINKFLAGS'][0:0] = ['-lm']
378 if sdk in ['ep2v', 'l4d', 'l4d2', 'csgo']:
379 compiler['POSTLINKFLAGS'][0:0] = ['libtier0.so']
380 compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.so']
382 compiler['POSTLINKFLAGS'][0:0] = ['tier0_i486.so']
383 compiler['POSTLINKFLAGS'][0:0] = ['vstdlib_i486.so']
384 elif AMBuild.target['platform'] == 'darwin':
385 compiler['POSTLINKFLAGS'][0:0] = ['libtier0.dylib']
386 compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.dylib']
395 AMBuild.Include(os.path.join('tools', 'buildbot', 'Versioning'), globals)
398 ['loader', 'AMBuilder'],
399 ['core', 'AMBuilder'],
400 ['core', 'logic', 'AMBuilder'],
401 ['extensions', 'bintools', 'AMBuilder'],
402 ['extensions', 'clientprefs', 'AMBuilder'],
403 ['extensions', 'cstrike', 'AMBuilder'],
404 ['extensions', 'curl', 'AMBuilder'],
405 ['extensions', 'geoip', 'AMBuilder'],
406 ['extensions', 'mysql', 'AMBuilder'],
407 ['extensions', 'sdktools', 'AMBuilder'],
408 ['extensions', 'topmenus', 'AMBuilder'],
409 ['extensions', 'updater', 'AMBuilder'],
410 ['extensions', 'sqlite', 'AMBuilder'],
411 ['extensions', 'regex', 'AMBuilder'],
412 ['extensions', 'tf2', 'AMBuilder'],
413 ['sourcepawn', 'jit', 'AMBuilder'],
414 ['sourcepawn', 'compiler', 'AMBuilder'],
415 ['plugins', 'AMBuilder'],
416 ['tools', 'buildbot', 'PackageScript'],
417 ['tools', 'buildbot', 'BreakpadSymbols']
420 for parts in FileList:
421 AMBuild.Include(os.path.join(*parts), globals)