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['css'] = {'sdk': 'HL2SDKCSS', 'ext': '2.css', 'def': '6',
17 'name': 'CSS', 'platform': ['windows', 'linux', 'darwin']}
18 self.possibleSdks['ep2v'] = {'sdk': 'HL2SDKOBVALVE', 'ext': '2.ep2v', 'def': '7',
19 'name': 'ORANGEBOXVALVE', 'platform': ['windows', 'linux', 'darwin']}
20 self.possibleSdks['l4d'] = {'sdk': 'HL2SDKL4D', 'ext': '2.l4d', 'def': '8',
21 'name': 'LEFT4DEAD', 'platform': ['windows', 'linux', 'darwin']}
22 self.possibleSdks['l4d2'] = {'sdk': 'HL2SDKL4D2', 'ext': '2.l4d2', 'def': '9',
23 'name': 'LEFT4DEAD2', 'platform': ['windows', 'linux', 'darwin']}
24 self.possibleSdks['darkm'] = {'sdk': 'HL2SDK-DARKM', 'ext': '2.darkm', 'def': '2',
25 'name': 'DARKMESSIAH', 'platform': ['windows']}
26 self.possibleSdks['swarm'] = {'sdk': 'HL2SDK-SWARM', 'ext': '2.swarm', 'def': '10',
27 'name': 'ALIENSWARM', 'platform': ['windows']}
28 self.possibleSdks['bgt'] = {'sdk': 'HL2SDK-BGT', 'ext': '2.bgt', 'def': '4',
29 'name': 'BLOODYGOODTIME', 'platform': ['windows']}
30 self.possibleSdks['eye'] = {'sdk': 'HL2SDK-EYE', 'ext': '2.eye', 'def': '5',
31 'name': 'EYE', 'platform': ['windows']}
32 self.possibleSdks['csgo'] = {'sdk': 'HL2SDKCSGO', 'ext': '2.csgo', 'def': '12',
33 'name': 'CSGO', 'platform': ['windows', 'linux']}
34 # self.possibleSdks['portal2'] = {'sdk': 'HL2SDK-PORTAL2', 'ext': '2.portal2', 'def': '11',
35 # 'name': 'PORTAL2', 'platform': ['windows']}
39 if AMBuild.mode == 'config':
41 self.compiler.DetectAll(AMBuild)
44 envvars = { 'MMSOURCE19': 'mmsource-1.9',
45 'HL2SDKCSS': 'hl2sdk-css',
46 'HL2SDKOBVALVE': 'hl2sdk-ob-valve',
47 'HL2SDKL4D': 'hl2sdk-l4d',
48 'HL2SDKL4D2': 'hl2sdk-l4d2',
52 if AMBuild.target['platform'] != 'darwin':
53 envvars['HL2SDK'] = 'hl2sdk'
54 envvars['HL2SDKOB'] = 'hl2sdk-ob'
55 envvars['HL2SDKCSGO'] = 'hl2sdk-csgo'
57 #Dark Messiah is Windows-only
58 if AMBuild.target['platform'] == 'windows':
59 envvars['HL2SDK-DARKM'] = 'hl2sdk-darkm'
60 envvars['HL2SDK-SWARM'] = 'hl2sdk-swarm'
61 envvars['HL2SDK-BGT'] = 'hl2sdk-bgt'
62 envvars['HL2SDK-EYE'] = 'hl2sdk-eye'
64 # Finds if a dict with `key` set to `value` is present on the dict of dicts `dictionary`
65 def findDictByKey(dictionary, key, value):
66 for index in dictionary:
67 elem = dictionary[index]
68 if elem[key] == value:
75 if not os.path.isdir(path):
76 raise Exception('Path for {0} was not found: {1}'.format(i, path))
77 elif i.startswith('HL2SDK'):
78 (info, sdk) = findDictByKey(self.possibleSdks, 'sdk', i)
79 self.sdkInfo[sdk] = info
83 while head != None and head != oldhead:
84 path = os.path.join(head, envvars[i])
85 if os.path.isdir(path):
88 head, tail = os.path.split(head)
89 if i.startswith('HL2SDK'):
90 if head != None and head != oldhead:
91 (info, sdk) = findDictByKey(self.possibleSdks, 'sdk', i)
92 self.sdkInfo[sdk] = info
93 elif head == None or head == oldhead:
94 raise Exception('Could not find a valid path for {0}'.format(i))
95 AMBuild.cache.CacheVariable(i, path)
97 if len(self.sdkInfo) < 1:
98 raise Exception('At least one SDK must be available.')
100 AMBuild.cache.CacheVariable('sdkInfo', self.sdkInfo)
103 cxx = self.compiler.cxx
104 if isinstance(cxx, Cpp.CompatGCC):
105 if isinstance(cxx, Cpp.GCC):
107 elif isinstance(cxx, Cpp.Clang):
108 self.vendor = 'clang'
109 self.compiler.AddToListVar('CDEFINES', 'stricmp=strcasecmp')
110 self.compiler.AddToListVar('CDEFINES', '_stricmp=strcasecmp')
111 self.compiler.AddToListVar('CDEFINES', '_snprintf=snprintf')
112 self.compiler.AddToListVar('CDEFINES', '_vsnprintf=vsnprintf')
113 self.compiler.AddToListVar('CFLAGS', '-pipe')
114 self.compiler.AddToListVar('CFLAGS', '-fno-strict-aliasing')
115 if (self.vendor == 'gcc' and cxx.majorVersion >= 4) or self.vendor == 'clang':
116 self.compiler.AddToListVar('CFLAGS', '-fvisibility=hidden')
117 self.compiler.AddToListVar('CXXFLAGS', '-fvisibility-inlines-hidden')
118 self.compiler.AddToListVar('CFLAGS', '-Wall')
119 self.compiler.AddToListVar('CFLAGS', '-Werror')
120 self.compiler.AddToListVar('CFLAGS', '-Wno-uninitialized')
121 self.compiler.AddToListVar('CFLAGS', '-Wno-unused')
122 self.compiler.AddToListVar('CFLAGS', '-Wno-switch')
123 self.compiler.AddToListVar('CFLAGS', '-msse')
124 self.compiler.AddToListVar('CFLAGS', '-m32')
125 self.compiler.AddToListVar('POSTLINKFLAGS', '-m32')
126 self.compiler.AddToListVar('CXXFLAGS', '-fno-exceptions')
127 self.compiler.AddToListVar('CXXFLAGS', '-fno-rtti')
128 self.compiler.AddToListVar('CXXFLAGS', '-fno-threadsafe-statics')
129 self.compiler.AddToListVar('CXXFLAGS', '-Wno-non-virtual-dtor')
130 self.compiler.AddToListVar('CXXFLAGS', '-Wno-overloaded-virtual')
131 if (self.vendor == 'gcc' and cxx.majorVersion >= 4 and cxx.minorVersion >= 7) or \
132 (self.vendor == 'clang' and cxx.majorVersion >= 3):
133 self.compiler.AddToListVar('CXXFLAGS', '-Wno-delete-non-virtual-dtor')
134 self.compiler.AddToListVar('CDEFINES', 'HAVE_STDINT_H')
135 self.compiler.AddToListVar('CDEFINES', 'GNUC')
136 if self.vendor == 'gcc':
137 self.compiler.AddToListVar('CFLAGS', '-mfpmath=sse')
138 elif isinstance(cxx, Cpp.MSVC):
140 if AMBuild.options.debug == '1':
141 self.compiler.AddToListVar('CFLAGS', '/MTd')
142 self.compiler.AddToListVar('POSTLINKFLAGS', '/NODEFAULTLIB:libcmt')
144 self.compiler.AddToListVar('CFLAGS', '/MT')
145 self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_DEPRECATE')
146 self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_WARNINGS')
147 self.compiler.AddToListVar('CDEFINES', '_CRT_NONSTDC_NO_DEPRECATE')
148 self.compiler.AddToListVar('CXXFLAGS', '/EHsc')
149 self.compiler.AddToListVar('CXXFLAGS', '/GR-')
150 self.compiler.AddToListVar('CFLAGS', '/W3')
151 self.compiler.AddToListVar('CFLAGS', '/nologo')
152 self.compiler.AddToListVar('CFLAGS', '/Zi')
153 self.compiler.AddToListVar('CXXFLAGS', '/TP')
154 self.compiler.AddToListVar('POSTLINKFLAGS', '/DEBUG')
155 self.compiler.AddToListVar('POSTLINKFLAGS', '/MACHINE:X86')
156 self.compiler.AddToListVar('POSTLINKFLAGS', '/SUBSYSTEM:WINDOWS')
157 self.compiler.AddToListVar('POSTLINKFLAGS', 'kernel32.lib')
158 self.compiler.AddToListVar('POSTLINKFLAGS', 'user32.lib')
159 self.compiler.AddToListVar('POSTLINKFLAGS', 'gdi32.lib')
160 self.compiler.AddToListVar('POSTLINKFLAGS', 'winspool.lib')
161 self.compiler.AddToListVar('POSTLINKFLAGS', 'comdlg32.lib')
162 self.compiler.AddToListVar('POSTLINKFLAGS', 'advapi32.lib')
163 self.compiler.AddToListVar('POSTLINKFLAGS', 'shell32.lib')
164 self.compiler.AddToListVar('POSTLINKFLAGS', 'ole32.lib')
165 self.compiler.AddToListVar('POSTLINKFLAGS', 'oleaut32.lib')
166 self.compiler.AddToListVar('POSTLINKFLAGS', 'uuid.lib')
167 self.compiler.AddToListVar('POSTLINKFLAGS', 'odbc32.lib')
168 self.compiler.AddToListVar('POSTLINKFLAGS', 'odbccp32.lib')
171 if AMBuild.options.opt == '1':
172 self.compiler.AddToListVar('CDEFINES', 'NDEBUG')
173 if self.vendor == 'gcc' or self.vendor == 'clang':
174 self.compiler.AddToListVar('CFLAGS', '-O3')
175 elif self.vendor == 'msvc':
176 self.compiler.AddToListVar('CFLAGS', '/Ox')
177 self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:ICF')
178 self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:REF')
181 if AMBuild.options.debug == '1':
182 self.compiler.AddToListVar('CDEFINES', 'DEBUG')
183 self.compiler.AddToListVar('CDEFINES', '_DEBUG')
184 if self.vendor == 'gcc' or self.vendor == 'clang':
185 self.compiler.AddToListVar('CFLAGS', '-g3')
186 elif self.vendor == 'msvc':
187 self.compiler.AddToListVar('CFLAGS', '/Od')
188 self.compiler.AddToListVar('CFLAGS', '/RTC1')
191 if AMBuild.target['platform'] == 'linux':
192 self.compiler.AddToListVar('CDEFINES', '_LINUX')
193 if self.vendor == 'gcc':
194 self.compiler.AddToListVar('POSTLINKFLAGS', '-static-libgcc')
195 if self.vendor == 'clang':
196 self.compiler.AddToListVar('POSTLINKFLAGS', '-lgcc_eh')
197 elif AMBuild.target['platform'] == 'darwin':
198 self.compiler.AddToListVar('POSTLINKFLAGS', '-mmacosx-version-min=10.5')
199 self.compiler.AddToListVar('POSTLINKFLAGS', ['-arch', 'i386'])
200 self.compiler.AddToListVar('POSTLINKFLAGS', '-lstdc++')
202 # For OS X dylib versioning
204 productFile = open(os.path.join(AMBuild.sourceFolder, 'product.version'), 'r')
205 productContents = productFile.read()
207 m = re.match('(\d+)\.(\d+)\.(\d+).*', productContents)
209 self.version = '1.0.0'
211 major, minor, release = m.groups()
212 self.version = '{0}.{1}.{2}'.format(major, minor, release)
213 AMBuild.cache.CacheVariable('version', self.version)
214 elif AMBuild.target['platform'] == 'windows':
215 self.compiler.AddToListVar('CDEFINES', 'WIN32')
216 self.compiler.AddToListVar('CDEFINES', '_WINDOWS')
219 self.compiler.AddToListVar('CDEFINES', 'SOURCEMOD_BUILD')
220 self.compiler.AddToListVar('CDEFINES', 'SM_GENERATED_BUILD')
221 self.compiler.AddToListVar('CINCLUDES',
222 os.path.join(AMBuild.outputFolder, 'includes'))
223 self.compiler.ToConfig(AMBuild, 'compiler')
224 AMBuild.cache.CacheVariable('vendor', self.vendor)
226 AMBuild.cache.CacheVariable('targetMap', self.targetMap)
228 self.sdkInfo = AMBuild.cache['sdkInfo']
229 self.compiler.FromConfig(AMBuild, 'compiler')
230 self.targetMap = AMBuild.cache['targetMap']
232 if AMBuild.target['platform'] == 'windows':
233 self.compiler.AddToListVar('RCINCLUDES', os.path.join(AMBuild.sourceFolder, 'public'))
234 self.compiler.AddToListVar('RCINCLUDES',
235 os.path.join(AMBuild.outputFolder, 'includes'))
236 self.mmsPath = AMBuild.cache['MMSOURCE19']
238 def DefaultCompiler(self):
239 return self.compiler.Clone()
241 def JobMatters(self, jobname):
242 file = sys._getframe().f_code.co_filename
243 if AMBuild.mode == 'config':
244 self.targetMap[jobname] = file
246 if len(AMBuild.args) == 0:
248 if not jobname in AMBuild.args:
251 def DefaultExtCompiler(self, path):
252 compiler = self.DefaultCompiler()
253 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path))
254 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path, 'sdk'))
255 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public'))
256 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'extensions'))
257 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'sourcepawn'))
260 def AutoVersion(self, folder, binary):
261 if AMBuild.target['platform'] == 'windows':
262 env = {'RCDEFINES': ['BINARY_NAME="' + binary.binaryFile + '"', 'SM_GENERATED_BUILD']}
263 binary.AddResourceFile(os.path.join(folder, 'version.rc' ), env)
264 elif AMBuild.target['platform'] == 'darwin' and isinstance(binary, Cpp.LibraryBuilder):
265 binary.compiler['POSTLINKFLAGS'].extend(['-compatibility_version', '1.0.0'])
266 binary.compiler['POSTLINKFLAGS'].extend(['-current_version', AMBuild.cache['version']])
270 def PreSetupHL2Job(self, job, builder, sdk):
271 info = self.sdkInfo[sdk]
272 sdkPath = AMBuild.cache[info['sdk']]
273 if AMBuild.target['platform'] == 'linux':
275 staticLibs = os.path.join(sdkPath, 'linux_sdk')
277 staticLibs = os.path.join(sdkPath, 'lib', 'linux')
278 workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
279 if sdk in ['css', 'ep2v', 'l4d', 'l4d2', 'csgo']:
280 libs = ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.so', 'libtier0.so']
282 libs.append('interfaces_i486.a')
284 link = os.path.join(workFolder, lib)
285 target = os.path.join(staticLibs, lib)
289 job.AddCommand(SymlinkCommand(link, target))
291 libs = ['tier1_i486.a', 'mathlib_i486.a', 'vstdlib_i486.so', 'tier0_i486.so']
293 link = os.path.join(workFolder, lib)
294 target = os.path.join(staticLibs, lib)
298 job.AddCommand(SymlinkCommand(link, target))
299 elif AMBuild.target['platform'] == 'darwin':
300 staticLibs = os.path.join(sdkPath, 'lib', 'mac')
301 workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
302 libs = ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.dylib', 'libtier0.dylib']
304 libs.append('interfaces_i486.a')
306 link = os.path.join(workFolder, lib)
307 target = os.path.join(staticLibs, lib)
311 job.AddCommand(SymlinkCommand(link, target))
312 elif AMBuild.target['platform'] == 'windows':
313 libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
314 if sdk in ['swarm', 'csgo']:
315 libs.append('interfaces')
317 libPath = os.path.join(sdkPath, 'lib', 'public', lib) + '.lib'
318 builder.RebuildIfNewer(libPath)
319 builder['POSTLINKFLAGS'].append(libPath)
321 def PostSetupHL2Job(self, job, builder, sdk):
322 if AMBuild.target['platform'] in ['linux', 'darwin']:
323 builder.AddObjectFiles(['tier1_i486.a', 'mathlib_i486.a'])
325 builder.AddObjectFiles(['interfaces_i486.a'])
327 def DefaultHL2Compiler(self, path, sdk, noLink = False, oldMms = '-legacy'):
328 compiler = self.DefaultExtCompiler(path)
334 compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms))
335 compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms, 'sourcehook'))
337 info = self.possibleSdks
338 compiler['CDEFINES'].extend(['SE_' + info[i]['name'] + '=' + info[i]['def'] for i in info])
340 # We don't build for Portal 2 (yet?, ever?), but using this define in code as
341 # it saves trouble if we ever need to
342 compiler['CDEFINES'].append('SE_PORTAL2=11')
344 paths = [['public'], ['public', 'engine'], ['public', 'mathlib'], ['public', 'vstdlib'],
345 ['public', 'tier0'], ['public', 'tier1']]
346 if sdk == 'ep1' or sdk == 'darkm':
347 paths.append(['public', 'dlls'])
348 paths.append(['game_shared'])
350 paths.append(['public', 'game', 'server'])
351 paths.append(['public', 'toolframework'])
352 paths.append(['game', 'shared'])
353 paths.append(['common'])
355 info = self.sdkInfo[sdk]
356 sdkPath = AMBuild.cache[info['sdk']]
358 compiler['CDEFINES'].append('SOURCE_ENGINE=' + info['def'])
360 if sdk in ['swarm','csgo']:
361 if AMBuild.target['platform'] == 'windows':
362 compiler['CDEFINES'].extend(['COMPILER_MSVC', 'COMPILER_MSVC32'])
364 compiler['CDEFINES'].extend(['COMPILER_GCC', 'POSIX'])
367 if AMBuild.target['platform'] == 'linux':
368 staticLibs = os.path.join(sdkPath, 'linux_sdk')
370 if AMBuild.target['platform'] == 'linux':
371 staticLibs = os.path.join(sdkPath, 'lib', 'linux')
372 elif AMBuild.target['platform'] == 'darwin':
373 staticLibs = os.path.join(sdkPath, 'lib', 'mac')
376 compiler['CXXINCLUDES'].append(os.path.join(sdkPath, *i))
379 if AMBuild.target['platform'] == 'linux':
380 compiler['POSTLINKFLAGS'][0:0] = ['-lm']
381 if sdk in ['css', 'ep2v', 'l4d', 'l4d2', 'csgo']:
382 compiler['POSTLINKFLAGS'][0:0] = ['libtier0.so']
383 compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.so']
385 compiler['POSTLINKFLAGS'][0:0] = ['tier0_i486.so']
386 compiler['POSTLINKFLAGS'][0:0] = ['vstdlib_i486.so']
387 elif AMBuild.target['platform'] == 'darwin':
388 compiler['POSTLINKFLAGS'][0:0] = ['libtier0.dylib']
389 compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.dylib']
398 AMBuild.Include(os.path.join('tools', 'buildbot', 'Versioning'), globals)
401 ['loader', 'AMBuilder'],
402 ['core', 'AMBuilder'],
403 ['core', 'logic', 'AMBuilder'],
404 ['extensions', 'bintools', 'AMBuilder'],
405 ['extensions', 'clientprefs', 'AMBuilder'],
406 ['extensions', 'cstrike', 'AMBuilder'],
407 ['extensions', 'curl', 'AMBuilder'],
408 ['extensions', 'geoip', 'AMBuilder'],
409 ['extensions', 'mysql', 'AMBuilder'],
410 ['extensions', 'sdktools', 'AMBuilder'],
411 ['extensions', 'topmenus', 'AMBuilder'],
412 ['extensions', 'updater', 'AMBuilder'],
413 ['extensions', 'sqlite', 'AMBuilder'],
414 ['extensions', 'regex', 'AMBuilder'],
415 ['extensions', 'tf2', 'AMBuilder'],
416 ['sourcepawn', 'jit', 'AMBuilder'],
417 ['sourcepawn', 'compiler', 'AMBuilder'],
418 ['plugins', 'AMBuilder'],
419 ['tools', 'buildbot', 'PackageScript'],
420 ['tools', 'buildbot', 'BreakpadSymbols']
423 for parts in FileList:
424 AMBuild.Include(os.path.join(*parts), globals)