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']}
33 if AMBuild.mode == 'config':
35 self.compiler.DetectAll(AMBuild)
38 envvars = { 'MMSOURCE18': 'mmsource-1.8',
39 'HL2SDKOBVALVE': 'hl2sdk-ob-valve',
40 'HL2SDKL4D': 'hl2sdk-l4d',
41 'HL2SDKL4D2': 'hl2sdk-l4d2',
45 if AMBuild.target['platform'] != 'darwin':
46 envvars['HL2SDK'] = 'hl2sdk'
47 envvars['HL2SDKOB'] = 'hl2sdk-ob'
49 #Dark Messiah is Windows-only
50 if AMBuild.target['platform'] == 'windows':
51 envvars['HL2SDK-DARKM'] = 'hl2sdk-darkm'
52 envvars['HL2SDK-SWARM'] = 'hl2sdk-swarm'
53 envvars['HL2SDK-BGT'] = 'hl2sdk-bgt'
54 envvars['HL2SDK-EYE'] = 'hl2sdk-eye'
56 # Finds if a dict with `key` set to `value` is present on the dict of dicts `dictionary`
57 def findDictByKey(dictionary, key, value):
58 for index in dictionary:
59 elem = dictionary[index]
60 if elem[key] == value:
67 if not os.path.isdir(path):
68 raise Exception('Path for {0} was not found: {1}'.format(i, path))
69 elif i.startswith('HL2SDK'):
70 (info, sdk) = findDictByKey(self.possibleSdks, 'sdk', i)
71 self.sdkInfo[sdk] = info
75 while head != None and head != oldhead:
76 path = os.path.join(head, envvars[i])
77 if os.path.isdir(path):
80 head, tail = os.path.split(head)
81 if i.startswith('HL2SDK'):
82 if head != None and head != oldhead:
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('POSTLINKFLAGS', '-m32')
118 self.compiler.AddToListVar('CXXFLAGS', '-fno-exceptions')
119 self.compiler.AddToListVar('CXXFLAGS', '-fno-rtti')
120 self.compiler.AddToListVar('CXXFLAGS', '-fno-threadsafe-statics')
121 self.compiler.AddToListVar('CXXFLAGS', '-Wno-non-virtual-dtor')
122 self.compiler.AddToListVar('CXXFLAGS', '-Wno-overloaded-virtual')
123 if (self.vendor == 'gcc' and cxx.majorVersion >= 4 and cxx.minorVersion >= 7) or \
124 (self.vendor == 'clang' and cxx.majorVersion >= 3):
125 self.compiler.AddToListVar('CXXFLAGS', '-Wno-delete-non-virtual-dtor')
126 self.compiler.AddToListVar('CDEFINES', 'HAVE_STDINT_H')
127 self.compiler.AddToListVar('CDEFINES', 'GNUC')
128 if self.vendor == 'gcc':
129 self.compiler.AddToListVar('CFLAGS', '-mfpmath=sse')
130 elif isinstance(cxx, Cpp.MSVC):
132 if AMBuild.options.debug == '1':
133 self.compiler.AddToListVar('CFLAGS', '/MTd')
134 self.compiler.AddToListVar('POSTLINKFLAGS', '/NODEFAULTLIB:libcmt')
136 self.compiler.AddToListVar('CFLAGS', '/MT')
137 self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_DEPRECATE')
138 self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_WARNINGS')
139 self.compiler.AddToListVar('CDEFINES', '_CRT_NONSTDC_NO_DEPRECATE')
140 self.compiler.AddToListVar('CXXFLAGS', '/EHsc')
141 self.compiler.AddToListVar('CXXFLAGS', '/GR-')
142 self.compiler.AddToListVar('CFLAGS', '/W3')
143 self.compiler.AddToListVar('CFLAGS', '/nologo')
144 self.compiler.AddToListVar('CFLAGS', '/Zi')
145 self.compiler.AddToListVar('CXXFLAGS', '/TP')
146 self.compiler.AddToListVar('POSTLINKFLAGS', '/DEBUG')
147 self.compiler.AddToListVar('POSTLINKFLAGS', '/MACHINE:X86')
148 self.compiler.AddToListVar('POSTLINKFLAGS', '/SUBSYSTEM:WINDOWS')
149 self.compiler.AddToListVar('POSTLINKFLAGS', 'kernel32.lib')
150 self.compiler.AddToListVar('POSTLINKFLAGS', 'user32.lib')
151 self.compiler.AddToListVar('POSTLINKFLAGS', 'gdi32.lib')
152 self.compiler.AddToListVar('POSTLINKFLAGS', 'winspool.lib')
153 self.compiler.AddToListVar('POSTLINKFLAGS', 'comdlg32.lib')
154 self.compiler.AddToListVar('POSTLINKFLAGS', 'advapi32.lib')
155 self.compiler.AddToListVar('POSTLINKFLAGS', 'shell32.lib')
156 self.compiler.AddToListVar('POSTLINKFLAGS', 'ole32.lib')
157 self.compiler.AddToListVar('POSTLINKFLAGS', 'oleaut32.lib')
158 self.compiler.AddToListVar('POSTLINKFLAGS', 'uuid.lib')
159 self.compiler.AddToListVar('POSTLINKFLAGS', 'odbc32.lib')
160 self.compiler.AddToListVar('POSTLINKFLAGS', 'odbccp32.lib')
163 if AMBuild.options.opt == '1':
164 self.compiler.AddToListVar('CDEFINES', 'NDEBUG')
165 if self.vendor == 'gcc' or self.vendor == 'clang':
166 self.compiler.AddToListVar('CFLAGS', '-O3')
167 elif self.vendor == 'msvc':
168 self.compiler.AddToListVar('CFLAGS', '/Ox')
169 self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:ICF')
170 self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:REF')
173 if AMBuild.options.debug == '1':
174 self.compiler.AddToListVar('CDEFINES', 'DEBUG')
175 self.compiler.AddToListVar('CDEFINES', '_DEBUG')
176 if self.vendor == 'gcc' or self.vendor == 'clang':
177 self.compiler.AddToListVar('CFLAGS', '-g3')
178 elif self.vendor == 'msvc':
179 self.compiler.AddToListVar('CFLAGS', '/Od')
180 self.compiler.AddToListVar('CFLAGS', '/RTC1')
183 if AMBuild.target['platform'] == 'linux':
184 self.compiler.AddToListVar('CDEFINES', '_LINUX')
185 if self.vendor == 'gcc':
186 self.compiler.AddToListVar('POSTLINKFLAGS', '-static-libgcc')
187 if self.vendor == 'clang':
188 self.compiler.AddToListVar('POSTLINKFLAGS', '-lgcc_eh')
189 elif AMBuild.target['platform'] == 'darwin':
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['MMSOURCE18']
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', 'l4d', 'l4d2']:
272 for i in ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.so', 'libtier0.so']:
273 link = os.path.join(workFolder, i)
274 target = os.path.join(staticLibs, i)
278 job.AddCommand(SymlinkCommand(link, target))
280 for i in ['tier1_i486.a', 'mathlib_i486.a', 'vstdlib_i486.so', 'tier0_i486.so']:
281 link = os.path.join(workFolder, i)
282 target = os.path.join(staticLibs, i)
286 job.AddCommand(SymlinkCommand(link, target))
287 elif AMBuild.target['platform'] == 'darwin':
288 staticLibs = os.path.join(sdkPath, 'lib', 'mac')
289 workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
290 for i in ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.dylib', 'libtier0.dylib']:
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'] == 'windows':
298 libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
300 libs.append('interfaces')
302 libPath = os.path.join(sdkPath, 'lib', 'public', lib) + '.lib'
303 builder.RebuildIfNewer(libPath)
304 builder['POSTLINKFLAGS'].append(libPath)
306 def PostSetupHL2Job(self, job, builder, sdk):
307 if AMBuild.target['platform'] in ['linux', 'darwin']:
308 builder.AddObjectFiles(['tier1_i486.a', 'mathlib_i486.a'])
310 def DefaultHL2Compiler(self, path, sdk, noLink = False, oldMms = '-legacy'):
311 compiler = self.DefaultExtCompiler(path)
317 compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms))
318 compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms, 'sourcehook'))
320 info = self.possibleSdks
321 compiler['CDEFINES'].extend(['SE_' + info[i]['name'] + '=' + info[i]['def'] for i in info])
323 paths = [['public'], ['public', 'engine'], ['public', 'mathlib'], ['public', 'vstdlib'],
324 ['public', 'tier0'], ['public', 'tier1']]
325 if sdk == 'ep1' or sdk == 'darkm':
326 paths.append(['public', 'dlls'])
327 paths.append(['game_shared'])
329 paths.append(['public', 'game', 'server'])
330 paths.append(['public', 'toolframework'])
331 paths.append(['game', 'shared'])
332 paths.append(['common'])
334 info = self.sdkInfo[sdk]
335 sdkPath = AMBuild.cache[info['sdk']]
337 compiler['CDEFINES'].append('SOURCE_ENGINE=' + info['def'])
339 if sdk == 'swarm' and AMBuild.target['platform'] == 'windows':
340 compiler['CDEFINES'].extend(['COMPILER_MSVC', 'COMPILER_MSVC32'])
343 if AMBuild.target['platform'] == 'linux':
344 staticLibs = os.path.join(sdkPath, 'linux_sdk')
346 if AMBuild.target['platform'] == 'linux':
347 staticLibs = os.path.join(sdkPath, 'lib', 'linux')
348 elif AMBuild.target['platform'] == 'darwin':
349 staticLibs = os.path.join(sdkPath, 'lib', 'mac')
352 compiler['CXXINCLUDES'].append(os.path.join(sdkPath, *i))
355 if AMBuild.target['platform'] == 'linux':
356 compiler['POSTLINKFLAGS'][0:0] = ['-lm']
357 if sdk in ['ep2v', 'l4d', 'l4d2']:
358 compiler['POSTLINKFLAGS'][0:0] = ['libtier0.so']
359 compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.so']
361 compiler['POSTLINKFLAGS'][0:0] = ['tier0_i486.so']
362 compiler['POSTLINKFLAGS'][0:0] = ['vstdlib_i486.so']
363 elif AMBuild.target['platform'] == 'darwin':
364 compiler['POSTLINKFLAGS'][0:0] = ['libtier0.dylib']
365 compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.dylib']
374 AMBuild.Include(os.path.join('tools', 'buildbot', 'Versioning'), globals)
377 ['loader', 'AMBuilder'],
378 ['core', 'AMBuilder'],
379 ['core', 'logic', 'AMBuilder'],
380 ['extensions', 'bintools', 'AMBuilder'],
381 ['extensions', 'clientprefs', 'AMBuilder'],
382 ['extensions', 'cstrike', 'AMBuilder'],
383 ['extensions', 'curl', 'AMBuilder'],
384 ['extensions', 'geoip', 'AMBuilder'],
385 ['extensions', 'mysql', 'AMBuilder'],
386 ['extensions', 'sdktools', 'AMBuilder'],
387 ['extensions', 'topmenus', 'AMBuilder'],
388 ['extensions', 'updater', 'AMBuilder'],
389 ['extensions', 'sqlite', 'AMBuilder'],
390 ['extensions', 'regex', 'AMBuilder'],
391 ['extensions', 'tf2', 'AMBuilder'],
392 ['sourcepawn', 'jit', 'AMBuilder'],
393 ['sourcepawn', 'compiler', 'AMBuilder'],
394 ['plugins', 'AMBuilder'],
395 ['tools', 'buildbot', 'PackageScript'],
396 ['tools', 'buildbot', 'BreakpadSymbols']
399 for parts in FileList:
400 AMBuild.Include(os.path.join(*parts), globals)