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'],
15 self.possibleSdks['ep2'] = {'sdk': 'HL2SDKOB', 'ext': '2.ep2', 'def': '3',
16 'name': 'ORANGEBOX', 'platform': ['windows', 'linux'],
18 self.possibleSdks['css'] = {'sdk': 'HL2SDKCSS', 'ext': '2.css', 'def': '6',
19 'name': 'CSS', 'platform': ['windows', 'linux', 'darwin'],
21 self.possibleSdks['ep2v'] = {'sdk': 'HL2SDKOBVALVE', 'ext': '2.ep2v', 'def': '7',
22 'name': 'ORANGEBOXVALVE', 'platform': ['windows', 'linux', 'darwin'],
23 'dir': 'hl2sdk-ob-valve'}
24 self.possibleSdks['l4d'] = {'sdk': 'HL2SDKL4D', 'ext': '2.l4d', 'def': '8',
25 'name': 'LEFT4DEAD', 'platform': ['windows', 'linux', 'darwin'],
27 self.possibleSdks['l4d2'] = {'sdk': 'HL2SDKL4D2', 'ext': '2.l4d2', 'def': '9',
28 'name': 'LEFT4DEAD2', 'platform': ['windows', 'linux', 'darwin'],
30 self.possibleSdks['darkm'] = {'sdk': 'HL2SDK-DARKM', 'ext': '2.darkm', 'def': '2',
31 'name': 'DARKMESSIAH', 'platform': ['windows'],
32 'dir': 'hl2sdk-darkm'}
33 self.possibleSdks['swarm'] = {'sdk': 'HL2SDK-SWARM', 'ext': '2.swarm', 'def': '10',
34 'name': 'ALIENSWARM', 'platform': ['windows'],
35 'dir': 'hl2sdk-swarm'}
36 self.possibleSdks['bgt'] = {'sdk': 'HL2SDK-BGT', 'ext': '2.bgt', 'def': '4',
37 'name': 'BLOODYGOODTIME', 'platform': ['windows'],
39 self.possibleSdks['eye'] = {'sdk': 'HL2SDK-EYE', 'ext': '2.eye', 'def': '5',
40 'name': 'EYE', 'platform': ['windows'],
42 self.possibleSdks['csgo'] = {'sdk': 'HL2SDKCSGO', 'ext': '2.csgo', 'def': '12',
43 'name': 'CSGO', 'platform': ['windows', 'linux', 'darwin'],
45 # self.possibleSdks['portal2'] = {'sdk': 'HL2SDK-PORTAL2', 'ext': '2.portal2', 'def': '11',
46 # 'name': 'PORTAL2', 'platform': ['windows'],
47 # 'dir': 'hl2sdk-portal2'}
51 if AMBuild.mode == 'config':
53 self.compiler.DetectAll(AMBuild)
56 envvars = { 'MMSOURCE19': 'mmsource-1.9', 'MYSQL5': 'mysql-5.0' }
58 #Look for Metamod:Source and MySQL directories
60 path = self.ResolveEnvPath(env, envvars[env])
62 raise Exception('Could not find a valid path for {0}'.format(env))
63 AMBuild.cache.CacheVariable(env, path)
65 #Look for SDK directories
66 for sdk in self.possibleSdks:
67 #Get list of SDKs to build against or 'all' or 'present'
68 sdkList = AMBuild.options.sdks.split(',')
69 #Build against all supported SDKs?
70 useAll = sdkList[0] == 'all'
71 #Build against supported SDKs that exist?
72 usePresent = sdkList[0] == 'present'
74 info = self.possibleSdks[sdk]
75 if AMBuild.target['platform'] in info['platform']:
78 sdkPath = self.ResolveEnvPath(env, dir)
80 if useAll or sdk in sdkList:
81 raise Exception('Could not find a valid path for {0}'.format(env))
84 if useAll or usePresent or sdk in sdkList:
85 self.sdkInfo[sdk] = info
86 AMBuild.cache.CacheVariable(env, sdkPath)
88 if len(self.sdkInfo) < 1:
89 raise Exception('At least one SDK must be available.')
91 AMBuild.cache.CacheVariable('sdkInfo', self.sdkInfo)
94 cxx = self.compiler.cxx
95 if isinstance(cxx, Cpp.CompatGCC):
96 if isinstance(cxx, Cpp.GCC):
98 elif isinstance(cxx, Cpp.Clang):
100 self.compiler.AddToListVar('CDEFINES', 'stricmp=strcasecmp')
101 self.compiler.AddToListVar('CDEFINES', '_stricmp=strcasecmp')
102 self.compiler.AddToListVar('CDEFINES', '_snprintf=snprintf')
103 self.compiler.AddToListVar('CDEFINES', '_vsnprintf=vsnprintf')
104 self.compiler.AddToListVar('CFLAGS', '-pipe')
105 self.compiler.AddToListVar('CFLAGS', '-fno-strict-aliasing')
106 if (self.vendor == 'gcc' and cxx.majorVersion >= 4) or self.vendor == 'clang':
107 self.compiler.AddToListVar('CFLAGS', '-fvisibility=hidden')
108 self.compiler.AddToListVar('CXXFLAGS', '-fvisibility-inlines-hidden')
109 self.compiler.AddToListVar('CFLAGS', '-Wall')
110 self.compiler.AddToListVar('CFLAGS', '-Werror')
111 self.compiler.AddToListVar('CFLAGS', '-Wno-uninitialized')
112 self.compiler.AddToListVar('CFLAGS', '-Wno-unused')
113 self.compiler.AddToListVar('CFLAGS', '-Wno-switch')
114 self.compiler.AddToListVar('CFLAGS', '-msse')
115 self.compiler.AddToListVar('CFLAGS', '-m32')
116 self.compiler.AddToListVar('POSTLINKFLAGS', '-m32')
117 self.compiler.AddToListVar('CXXFLAGS', '-fno-exceptions')
118 self.compiler.AddToListVar('CXXFLAGS', '-fno-threadsafe-statics')
119 self.compiler.AddToListVar('CXXFLAGS', '-Wno-non-virtual-dtor')
120 self.compiler.AddToListVar('CXXFLAGS', '-Wno-overloaded-virtual')
121 if (self.vendor == 'gcc' and cxx.majorVersion >= 4 and cxx.minorVersion >= 7) or \
122 (self.vendor == 'clang' and cxx.majorVersion >= 3):
123 self.compiler.AddToListVar('CXXFLAGS', '-Wno-delete-non-virtual-dtor')
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 == 'gcc' or self.vendor == 'clang':
175 self.compiler.AddToListVar('CFLAGS', '-g3')
176 elif self.vendor == 'msvc':
177 self.compiler.AddToListVar('CFLAGS', '/Od')
178 self.compiler.AddToListVar('CFLAGS', '/RTC1')
181 if AMBuild.target['platform'] == 'linux':
182 self.compiler.AddToListVar('CDEFINES', '_LINUX')
183 if self.vendor == 'gcc':
184 self.compiler.AddToListVar('POSTLINKFLAGS', '-static-libgcc')
185 if self.vendor == 'clang':
186 self.compiler.AddToListVar('POSTLINKFLAGS', '-lgcc_eh')
187 elif AMBuild.target['platform'] == 'darwin':
188 self.compiler.AddToListVar('CDEFINES', 'OSX')
189 self.compiler.AddToListVar('CDEFINES', '_OSX')
190 self.compiler.AddToListVar('POSTLINKFLAGS', '-mmacosx-version-min=10.5')
191 self.compiler.AddToListVar('POSTLINKFLAGS', ['-arch', 'i386'])
192 self.compiler.AddToListVar('POSTLINKFLAGS', '-lstdc++')
194 # For OS X dylib versioning
196 productFile = open(os.path.join(AMBuild.sourceFolder, 'product.version'), 'r')
197 productContents = productFile.read()
199 m = re.match('(\d+)\.(\d+)\.(\d+).*', productContents)
201 self.version = '1.0.0'
203 major, minor, release = m.groups()
204 self.version = '{0}.{1}.{2}'.format(major, minor, release)
205 AMBuild.cache.CacheVariable('version', self.version)
206 elif AMBuild.target['platform'] == 'windows':
207 self.compiler.AddToListVar('CDEFINES', 'WIN32')
208 self.compiler.AddToListVar('CDEFINES', '_WINDOWS')
211 self.compiler.AddToListVar('CDEFINES', 'SOURCEMOD_BUILD')
212 self.compiler.AddToListVar('CDEFINES', 'SM_GENERATED_BUILD')
213 self.compiler.AddToListVar('CINCLUDES',
214 os.path.join(AMBuild.outputFolder, 'includes'))
215 self.compiler.ToConfig(AMBuild, 'compiler')
216 AMBuild.cache.CacheVariable('vendor', self.vendor)
218 AMBuild.cache.CacheVariable('targetMap', self.targetMap)
220 self.sdkInfo = AMBuild.cache['sdkInfo']
221 self.compiler.FromConfig(AMBuild, 'compiler')
222 self.targetMap = AMBuild.cache['targetMap']
224 if AMBuild.target['platform'] == 'windows':
225 self.compiler.AddToListVar('RCINCLUDES', os.path.join(AMBuild.sourceFolder, 'public'))
226 self.compiler.AddToListVar('RCINCLUDES',
227 os.path.join(AMBuild.outputFolder, 'includes'))
228 self.mmsPath = AMBuild.cache['MMSOURCE19']
230 def DefaultCompiler(self):
231 return self.compiler.Clone()
233 def JobMatters(self, jobname):
234 file = sys._getframe().f_code.co_filename
235 if AMBuild.mode == 'config':
236 self.targetMap[jobname] = file
238 if len(AMBuild.args) == 0:
240 if not jobname in AMBuild.args:
243 def DefaultExtCompiler(self, path):
244 compiler = self.DefaultCompiler()
245 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path))
246 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path, 'sdk'))
247 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public'))
248 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'extensions'))
249 compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'sourcepawn'))
252 def AutoVersion(self, folder, binary):
253 if AMBuild.target['platform'] == 'windows':
254 env = {'RCDEFINES': ['BINARY_NAME="' + binary.binaryFile + '"', 'SM_GENERATED_BUILD']}
255 binary.AddResourceFile(os.path.join(folder, 'version.rc' ), env)
256 elif AMBuild.target['platform'] == 'darwin' and isinstance(binary, Cpp.LibraryBuilder):
257 binary.compiler['POSTLINKFLAGS'].extend(['-compatibility_version', '1.0.0'])
258 binary.compiler['POSTLINKFLAGS'].extend(['-current_version', AMBuild.cache['version']])
262 def PreSetupHL2Job(self, job, builder, sdk):
263 info = self.sdkInfo[sdk]
264 sdkPath = AMBuild.cache[info['sdk']]
265 if AMBuild.target['platform'] == 'linux':
267 staticLibs = os.path.join(sdkPath, 'linux_sdk')
269 staticLibs = os.path.join(sdkPath, 'lib', 'linux')
270 workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
271 if sdk in ['ep2v', 'css']:
272 libs = ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib_srv.so', 'libtier0_srv.so']
274 link = os.path.join(workFolder, lib)
275 target = os.path.join(staticLibs, lib)
279 job.AddCommand(SymlinkCommand(link, target))
280 elif sdk in ['l4d', 'l4d2', 'csgo']:
281 libs = ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.so', 'libtier0.so']
283 libs.append('interfaces_i486.a')
285 link = os.path.join(workFolder, lib)
286 target = os.path.join(staticLibs, lib)
290 job.AddCommand(SymlinkCommand(link, target))
292 libs = ['tier1_i486.a', 'mathlib_i486.a', 'vstdlib_i486.so', 'tier0_i486.so']
294 link = os.path.join(workFolder, lib)
295 target = os.path.join(staticLibs, lib)
299 job.AddCommand(SymlinkCommand(link, target))
300 elif AMBuild.target['platform'] == 'darwin':
301 staticLibs = os.path.join(sdkPath, 'lib', 'mac')
302 workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
303 libs = ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.dylib', 'libtier0.dylib']
305 libs.append('interfaces_i486.a')
307 link = os.path.join(workFolder, lib)
308 target = os.path.join(staticLibs, lib)
312 job.AddCommand(SymlinkCommand(link, target))
313 elif AMBuild.target['platform'] == 'windows':
314 libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
315 if sdk in ['swarm', 'csgo']:
316 libs.append('interfaces')
318 libPath = os.path.join(sdkPath, 'lib', 'public', lib) + '.lib'
319 builder.RebuildIfNewer(libPath)
320 builder['POSTLINKFLAGS'].append(libPath)
322 def PostSetupHL2Job(self, job, builder, sdk):
323 if AMBuild.target['platform'] in ['linux', 'darwin']:
324 builder.AddObjectFiles(['tier1_i486.a', 'mathlib_i486.a'])
326 builder.AddObjectFiles(['interfaces_i486.a'])
328 def DefaultHL2Compiler(self, path, sdk, noLink = False, oldMms = '-legacy'):
329 compiler = self.DefaultExtCompiler(path)
335 compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms))
336 compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms, 'sourcehook'))
338 info = self.possibleSdks
339 compiler['CDEFINES'].extend(['SE_' + info[i]['name'] + '=' + info[i]['def'] for i in info])
341 # We don't build for Portal 2 (yet?, ever?), but using this define in code as
342 # it saves trouble if we ever need to
343 compiler['CDEFINES'].append('SE_PORTAL2=11')
345 paths = [['public'], ['public', 'engine'], ['public', 'mathlib'], ['public', 'vstdlib'],
346 ['public', 'tier0'], ['public', 'tier1']]
347 if sdk == 'ep1' or sdk == 'darkm':
348 paths.append(['public', 'dlls'])
349 paths.append(['game_shared'])
351 paths.append(['public', 'game', 'server'])
352 paths.append(['public', 'toolframework'])
353 paths.append(['game', 'shared'])
354 paths.append(['common'])
356 info = self.sdkInfo[sdk]
357 sdkPath = AMBuild.cache[info['sdk']]
359 compiler['CDEFINES'].append('SOURCE_ENGINE=' + info['def'])
361 if sdk in ['swarm','csgo']:
362 if AMBuild.target['platform'] == 'windows':
363 compiler['CDEFINES'].extend(['COMPILER_MSVC', 'COMPILER_MSVC32'])
365 compiler['CDEFINES'].extend(['COMPILER_GCC', 'POSIX'])
368 if AMBuild.target['platform'] == 'linux':
369 staticLibs = os.path.join(sdkPath, 'linux_sdk')
371 if AMBuild.target['platform'] == 'linux':
372 staticLibs = os.path.join(sdkPath, 'lib', 'linux')
373 elif AMBuild.target['platform'] == 'darwin':
374 staticLibs = os.path.join(sdkPath, 'lib', 'mac')
377 compiler['CXXINCLUDES'].append(os.path.join(sdkPath, *i))
380 if AMBuild.target['platform'] == 'linux':
381 compiler['POSTLINKFLAGS'][0:0] = ['-lm']
382 if sdk in ['ep2v', 'css']:
383 compiler['POSTLINKFLAGS'][0:0] = ['libtier0_srv.so']
384 compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib_srv.so']
385 elif sdk in ['l4d', 'l4d2', 'csgo']:
386 compiler['POSTLINKFLAGS'][0:0] = ['libtier0.so']
387 compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.so']
389 compiler['POSTLINKFLAGS'][0:0] = ['tier0_i486.so']
390 compiler['POSTLINKFLAGS'][0:0] = ['vstdlib_i486.so']
391 elif AMBuild.target['platform'] == 'darwin':
392 compiler['POSTLINKFLAGS'][0:0] = ['libtier0.dylib']
393 compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.dylib']
397 def ResolveEnvPath(self, env, defaultDir):
398 if env in os.environ:
399 path = os.environ[env]
400 if os.path.isdir(path):
405 while head != None and head != oldhead:
406 path = os.path.join(head, defaultDir)
407 if os.path.isdir(path):
410 head, tail = os.path.split(head)
418 AMBuild.Include(os.path.join('tools', 'buildbot', 'Versioning'), globals)
421 ['loader', 'AMBuilder'],
422 ['core', 'AMBuilder'],
423 ['core', 'logic', 'AMBuilder'],
424 ['extensions', 'bintools', 'AMBuilder'],
425 ['extensions', 'clientprefs', 'AMBuilder'],
426 ['extensions', 'cstrike', 'AMBuilder'],
427 ['extensions', 'curl', 'AMBuilder'],
428 ['extensions', 'geoip', 'AMBuilder'],
429 ['extensions', 'mysql', 'AMBuilder'],
430 ['extensions', 'sdkhooks', 'AMBuilder'],
431 ['extensions', 'sdktools', 'AMBuilder'],
432 ['extensions', 'topmenus', 'AMBuilder'],
433 ['extensions', 'updater', 'AMBuilder'],
434 ['extensions', 'sqlite', 'AMBuilder'],
435 ['extensions', 'regex', 'AMBuilder'],
436 ['extensions', 'tf2', 'AMBuilder'],
437 ['sourcepawn', 'jit', 'AMBuilder'],
438 ['sourcepawn', 'compiler', 'AMBuilder'],
439 ['plugins', 'AMBuilder'],
440 ['tools', 'buildbot', 'PackageScript'],
441 ['tools', 'buildbot', 'BreakpadSymbols']
444 for parts in FileList:
445 AMBuild.Include(os.path.join(*parts), globals)