1
0
mirror of https://github.com/alliedmodders/metamod-source.git synced 2024-11-29 11:24:19 +01:00
HLMetaModOfficial/AMBuildScript
Scott Ehlert 95aad72edc Added --sdks option to configure script to specify which SDKs to build againt (bug 5676, r=psychonic).
Valid arguments are "all", "present", or a comma delimited list of engine names.

The "all" option will try to build against all supported SDKs. (This is the default.)
The "present" option will only attempt to build against SDKs that exist on the system.

Examples:

configure.py --sdks=css,csgo,ep2v
configure.py --sdks=l4d
configure.py -s present
2013-03-23 23:12:16 -05:00

409 lines
17 KiB
Python

# vim: set ts=2 sw=2 tw=99 noet ft=python:
import os
import sys
from ambuild.command import SymlinkCommand
class MMS:
def __init__(self):
self.compiler = Cpp.Compiler()
#Build SDK info
self.possibleSdks = { }
self.possibleSdks['ep1'] = {'sdk': 'HL2SDK', 'ext': '1.ep1', 'def': '1',
'name': 'EPISODEONE', 'platform': ['windows', 'linux'],
'dir': 'hl2sdk'}
self.possibleSdks['ep2'] = {'sdk': 'HL2SDKOB', 'ext': '2.ep2', 'def': '3',
'name': 'ORANGEBOX', 'platform': ['windows', 'linux'],
'dir': 'hl2sdk-ob'}
self.possibleSdks['css'] = {'sdk': 'HL2SDKCSS', 'ext': '2.css', 'def': '6',
'name': 'CSS', 'platform': ['windows', 'linux', 'darwin'],
'dir': 'hl2sdk-css'}
self.possibleSdks['ep2v'] = {'sdk': 'HL2SDKOBVALVE', 'ext': '2.ep2v', 'def': '7',
'name': 'ORANGEBOXVALVE', 'platform': ['windows', 'linux', 'darwin'],
'dir': 'hl2sdk-ob-valve'}
self.possibleSdks['l4d'] = {'sdk': 'HL2SDKL4D', 'ext': '2.l4d', 'def': '8',
'name': 'LEFT4DEAD', 'platform': ['windows', 'linux', 'darwin'],
'dir': 'hl2sdk-l4d'}
self.possibleSdks['l4d2'] = {'sdk': 'HL2SDKL4D2', 'ext': '2.l4d2', 'def': '9',
'name': 'LEFT4DEAD2', 'platform': ['windows', 'linux', 'darwin'],
'dir': 'hl2sdk-l4d2'}
self.possibleSdks['darkm'] = {'sdk': 'HL2SDK-DARKM', 'ext': '2.darkm', 'def': '2',
'name': 'DARKMESSIAH', 'platform': ['windows'],
'dir': 'hl2sdk-darkm'}
self.possibleSdks['swarm'] = {'sdk': 'HL2SDK-SWARM', 'ext': '2.swarm', 'def': '10',
'name': 'ALIENSWARM', 'platform': ['windows'],
'dir': 'hl2sdk-swarm'}
self.possibleSdks['bgt'] = {'sdk': 'HL2SDK-BGT', 'ext': '2.bgt', 'def': '4',
'name': 'BLOODYGOODTIME', 'platform': ['windows'],
'dir': 'hl2sdk-bgt'}
self.possibleSdks['eye'] = {'sdk': 'HL2SDK-EYE', 'ext': '2.eye', 'def': '5',
'name': 'EYE', 'platform': ['windows'],
'dir': 'hl2sdk-eye'}
self.possibleSdks['csgo'] = {'sdk': 'HL2SDKCSGO', 'ext': '2.csgo', 'def': '12',
'name': 'CSGO', 'platform': ['windows', 'linux', 'darwin'],
'dir': 'hl2sdk-csgo'}
self.possibleSdks['dota'] = {'sdk': 'HL2SDKDOTA', 'ext': '2.dota', 'def': '13',
'name': 'DOTA', 'platform': ['windows'],
'dir': 'hl2sdk-dota'}
# self.possibleSdks['portal2'] = {'sdk': 'HL2SDK-PORTAL2', 'ext': '2.portal2', 'def': '11',
# 'name': 'PORTAL2', 'platform': ['windows'],
# 'dir': 'hl2sdk-portal2'}
self.sdkInfo = { }
if AMBuild.mode == 'config':
#Detect compilers
self.compiler.DetectAll(AMBuild)
#Look for SDK directories
for sdk in self.possibleSdks:
#Get list of SDKs to build against or 'all' or 'present'
sdkList = AMBuild.options.sdks.split(',')
#Build against all supported SDKs?
useAll = sdkList[0] == 'all'
#Build against supported SDKs that exist?
usePresent = sdkList[0] == 'present'
info = self.possibleSdks[sdk]
if AMBuild.target['platform'] in info['platform']:
env = info['sdk']
dir = info['dir']
sdkPath = self.ResolveEnvPath(env, dir)
if sdkPath == None:
if useAll or sdk in sdkList:
raise Exception('Could not find a valid path for {0}'.format(env))
else:
continue
if useAll or usePresent or sdk in sdkList:
self.sdkInfo[sdk] = info
AMBuild.cache.CacheVariable(env, sdkPath)
if len(self.sdkInfo) < 1:
raise Exception('At least one SDK must be available.')
AMBuild.cache.CacheVariable('sdkInfo', self.sdkInfo)
#Set up defines
cxx = self.compiler.cxx
if isinstance(cxx, Cpp.CompatGCC):
if isinstance(cxx, Cpp.GCC):
self.vendor = 'gcc'
elif isinstance(cxx, Cpp.Clang):
self.vendor = 'clang'
self.compiler.AddToListVar('CDEFINES', 'stricmp=strcasecmp')
self.compiler.AddToListVar('CDEFINES', '_stricmp=strcasecmp')
self.compiler.AddToListVar('CDEFINES', '_snprintf=snprintf')
self.compiler.AddToListVar('CDEFINES', '_vsnprintf=vsnprintf')
self.compiler.AddToListVar('CFLAGS', '-pipe')
self.compiler.AddToListVar('CFLAGS', '-fno-strict-aliasing')
if (self.vendor == 'gcc' and cxx.majorVersion >= 4) or self.vendor == 'clang':
self.compiler.AddToListVar('CFLAGS', '-fvisibility=hidden')
self.compiler.AddToListVar('CXXFLAGS', '-fvisibility-inlines-hidden')
self.compiler.AddToListVar('CFLAGS', '-Wall')
self.compiler.AddToListVar('CFLAGS', '-Werror')
self.compiler.AddToListVar('CFLAGS', '-Wno-uninitialized')
self.compiler.AddToListVar('CFLAGS', '-Wno-unused')
self.compiler.AddToListVar('CFLAGS', '-Wno-switch')
self.compiler.AddToListVar('CFLAGS', '-msse')
self.compiler.AddToListVar('CFLAGS', '-m32')
self.compiler.AddToListVar('POSTLINKFLAGS', '-m32')
self.compiler.AddToListVar('CXXFLAGS', '-fno-exceptions')
self.compiler.AddToListVar('CXXFLAGS', '-fno-rtti')
self.compiler.AddToListVar('CXXFLAGS', '-fno-threadsafe-statics')
self.compiler.AddToListVar('CXXFLAGS', '-Wno-non-virtual-dtor')
self.compiler.AddToListVar('CXXFLAGS', '-Wno-overloaded-virtual')
if (self.vendor == 'gcc' and cxx.majorVersion >= 4 and cxx.minorVersion >= 7) or \
(self.vendor == 'clang' and cxx.majorVersion >= 3):
self.compiler.AddToListVar('CXXFLAGS', '-Wno-delete-non-virtual-dtor')
self.compiler.AddToListVar('CDEFINES', 'HAVE_STDINT_H')
if self.vendor == 'gcc':
self.compiler.AddToListVar('CFLAGS', '-mfpmath=sse')
elif isinstance(cxx, Cpp.MSVC):
self.vendor = 'msvc'
if AMBuild.options.debug == '1':
self.compiler.AddToListVar('CFLAGS', '/MTd')
self.compiler.AddToListVar('POSTLINKFLAGS', '/NODEFAULTLIB:libcmt')
else:
self.compiler.AddToListVar('CFLAGS', '/MT')
self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_DEPRECATE')
self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_WARNINGS')
self.compiler.AddToListVar('CDEFINES', '_CRT_NONSTDC_NO_DEPRECATE')
self.compiler.AddToListVar('CXXFLAGS', '/EHsc')
self.compiler.AddToListVar('CXXFLAGS', '/GR-')
self.compiler.AddToListVar('CFLAGS', '/W3')
self.compiler.AddToListVar('CFLAGS', '/nologo')
self.compiler.AddToListVar('CFLAGS', '/Zi')
self.compiler.AddToListVar('CXXFLAGS', '/TP')
self.compiler.AddToListVar('POSTLINKFLAGS', '/DEBUG')
self.compiler.AddToListVar('POSTLINKFLAGS', '/MACHINE:X86')
self.compiler.AddToListVar('POSTLINKFLAGS', '/SUBSYSTEM:WINDOWS')
self.compiler.AddToListVar('POSTLINKFLAGS', 'kernel32.lib')
self.compiler.AddToListVar('POSTLINKFLAGS', 'user32.lib')
self.compiler.AddToListVar('POSTLINKFLAGS', 'gdi32.lib')
self.compiler.AddToListVar('POSTLINKFLAGS', 'winspool.lib')
self.compiler.AddToListVar('POSTLINKFLAGS', 'comdlg32.lib')
self.compiler.AddToListVar('POSTLINKFLAGS', 'advapi32.lib')
self.compiler.AddToListVar('POSTLINKFLAGS', 'shell32.lib')
self.compiler.AddToListVar('POSTLINKFLAGS', 'ole32.lib')
self.compiler.AddToListVar('POSTLINKFLAGS', 'oleaut32.lib')
self.compiler.AddToListVar('POSTLINKFLAGS', 'uuid.lib')
self.compiler.AddToListVar('POSTLINKFLAGS', 'odbc32.lib')
self.compiler.AddToListVar('POSTLINKFLAGS', 'odbccp32.lib')
#Optimization
if AMBuild.options.opt == '1':
self.compiler.AddToListVar('CDEFINES', 'NDEBUG')
if self.vendor == 'gcc' or self.vendor == 'clang':
self.compiler.AddToListVar('CFLAGS', '-O3')
elif self.vendor == 'msvc':
self.compiler.AddToListVar('CFLAGS', '/Ox')
self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:ICF')
self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:REF')
#Debugging
if AMBuild.options.debug == '1':
self.compiler.AddToListVar('CDEFINES', 'DEBUG')
self.compiler.AddToListVar('CDEFINES', '_DEBUG')
if self.vendor == 'gcc' or self.vendor == 'clang':
self.compiler.AddToListVar('CFLAGS', '-g3')
elif self.vendor == 'msvc':
self.compiler.AddToListVar('CFLAGS', '/Od')
self.compiler.AddToListVar('CFLAGS', '/RTC1')
#Platform-specifics
if AMBuild.target['platform'] == 'linux':
self.compiler.AddToListVar('CDEFINES', '_LINUX')
if self.vendor == 'gcc':
self.compiler.AddToListVar('POSTLINKFLAGS', '-static-libgcc')
if self.vendor == 'clang':
self.compiler.AddToListVar('POSTLINKFLAGS', '-lgcc_eh')
elif AMBuild.target['platform'] == 'darwin':
self.compiler.AddToListVar('CDEFINES', 'OSX')
self.compiler.AddToListVar('CDEFINES', '_OSX')
self.compiler.AddToListVar('POSTLINKFLAGS', '-mmacosx-version-min=10.5')
self.compiler.AddToListVar('POSTLINKFLAGS', ['-arch', 'i386'])
self.compiler.AddToListVar('POSTLINKFLAGS', '-lstdc++')
# For OS X dylib versioning
import re
productFile = open(os.path.join(AMBuild.sourceFolder, 'product.version'), 'r')
productContents = productFile.read()
productFile.close()
m = re.match('(\d+)\.(\d+)\.(\d+).*', productContents)
if m == None:
self.version = '1.0.0'
else:
major, minor, release = m.groups()
self.version = '{0}.{1}.{2}'.format(major, minor, release)
AMBuild.cache.CacheVariable('version', self.version)
elif AMBuild.target['platform'] == 'windows':
self.compiler.AddToListVar('CDEFINES', 'WIN32')
self.compiler.AddToListVar('CDEFINES', '_WINDOWS')
#Finish up
self.compiler.AddToListVar('CDEFINES', 'MMS_GENERATED_BUILD')
self.compiler.AddToListVar('CINCLUDES',
os.path.join(AMBuild.outputFolder, 'includes'))
self.compiler.ToConfig(AMBuild, 'compiler')
AMBuild.cache.CacheVariable('vendor', self.vendor)
self.targetMap = { }
AMBuild.cache.CacheVariable('targetMap', self.targetMap)
else:
self.sdkInfo = AMBuild.cache['sdkInfo']
self.compiler.FromConfig(AMBuild, 'compiler')
self.targetMap = AMBuild.cache['targetMap']
if AMBuild.target['platform'] == 'windows':
self.compiler.AddToListVar('RCINCLUDES', os.path.join(AMBuild.sourceFolder, 'public'))
self.compiler.AddToListVar('RCINCLUDES',
os.path.join(AMBuild.outputFolder, 'includes'))
def DefaultCompiler(self):
compiler = self.compiler.Clone()
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public'))
return compiler
def JobMatters(self, jobname):
file = sys._getframe().f_code.co_filename
if AMBuild.mode == 'config':
self.targetMap[jobname] = file
return True
if len(AMBuild.args) == 0:
return True
if not jobname in AMBuild.args:
return False
def AutoVersion(self, folder, binary):
if AMBuild.target['platform'] == 'windows':
env = {'RCDEFINES': ['BINARY_NAME="' + binary.binaryFile + '"', 'MMS_GENERATED_BUILD']}
binary.AddResourceFile(os.path.join(folder, 'version.rc' ), env)
elif AMBuild.target['platform'] == 'darwin' and isinstance(binary, Cpp.LibraryBuilder):
binary.compiler['POSTLINKFLAGS'].extend(['-compatibility_version', '1.0.0'])
binary.compiler['POSTLINKFLAGS'].extend(['-current_version', AMBuild.cache['version']])
else:
return
def PreSetupHL2Job(self, job, builder, sdk):
info = self.sdkInfo[sdk]
sdkPath = AMBuild.cache[info['sdk']]
if AMBuild.target['platform'] == 'linux':
if sdk == 'ep1':
staticLibs = os.path.join(sdkPath, 'linux_sdk')
else:
staticLibs = os.path.join(sdkPath, 'lib', 'linux')
workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
if sdk in ['ep2v', 'css']:
libs = ['tier1_i486.a', 'libvstdlib_srv.so', 'libtier0_srv.so']
for lib in libs:
link = os.path.join(workFolder, lib)
target = os.path.join(staticLibs, lib)
try:
os.lstat(link)
except:
job.AddCommand(SymlinkCommand(link, target))
elif sdk in ['l4d', 'l4d2', 'csgo']:
libs = ['tier1_i486.a', 'libvstdlib.so', 'libtier0.so']
if sdk == 'csgo':
libs.insert(0, 'interfaces_i486.a')
for lib in libs:
link = os.path.join(workFolder, lib)
target = os.path.join(staticLibs, lib)
try:
os.lstat(link)
except:
job.AddCommand(SymlinkCommand(link, target))
else:
for i in ['tier1_i486.a', 'vstdlib_i486.so', 'tier0_i486.so']:
link = os.path.join(workFolder, i)
target = os.path.join(staticLibs, i)
try:
os.lstat(link)
except:
job.AddCommand(SymlinkCommand(link, target))
elif AMBuild.target['platform'] == 'darwin':
staticLibs = os.path.join(sdkPath, 'lib', 'mac')
workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
libs = ['tier1_i486.a', 'libvstdlib.dylib', 'libtier0.dylib']
if sdk == 'csgo':
libs.append('interfaces_i486.a')
for lib in libs:
link = os.path.join(workFolder, lib)
target = os.path.join(staticLibs, lib)
try:
os.lstat(link)
except:
job.AddCommand(SymlinkCommand(link, target))
elif AMBuild.target['platform'] == 'windows':
libs = ['tier0', 'tier1', 'vstdlib']
if sdk in ['swarm', 'csgo', 'dota']:
libs.append('interfaces')
for lib in libs:
libPath = os.path.join(sdkPath, 'lib', 'public', lib) + '.lib'
builder.RebuildIfNewer(libPath)
builder['POSTLINKFLAGS'].append(libPath)
def PostSetupHL2Job(self, job, builder, sdk):
if AMBuild.target['platform'] in ['linux', 'darwin']:
builder.AddObjectFiles(['tier1_i486.a'])
if( sdk in ['csgo', 'dota'] ):
builder.AddObjectFiles(['interfaces_i486.a'])
def DefaultHL2Compiler(self, path, sdk, noLink = False):
compiler = self.DefaultCompiler()
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path))
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path, 'sourcehook'))
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'loader'))
info = self.possibleSdks
compiler['CDEFINES'].extend(['SE_' + info[i]['name'] + '=' + info[i]['def'] for i in info])
# We don't build for Portal 2 (yet?, ever?), but using this define in code as
# it saves trouble if we ever need to
compiler['CDEFINES'].append('SE_PORTAL2=11')
paths = [['public'], ['public', 'engine'], ['public', 'mathlib'], ['public', 'vstdlib'],
['public', 'tier0'], ['public', 'tier1']]
if sdk == 'ep1' or sdk == 'darkm':
paths.append(['public', 'dlls'])
paths.append(['game_shared'])
else:
paths.append(['public', 'game', 'server'])
paths.append(['game', 'shared'])
paths.append(['common'])
info = self.sdkInfo[sdk]
sdkPath = AMBuild.cache[info['sdk']]
compiler['CDEFINES'].append('SOURCE_ENGINE=' + info['def'])
if sdk in ['swarm', 'csgo', 'dota']:
if AMBuild.target['platform'] == 'windows':
compiler['CDEFINES'].extend(['COMPILER_MSVC', 'COMPILER_MSVC32'])
else:
compiler['CDEFINES'].extend(['COMPILER_GCC', 'POSIX'])
if sdk == 'ep1':
if AMBuild.target['platform'] == 'linux':
staticLibs = os.path.join(sdkPath, 'linux_sdk')
else:
if AMBuild.target['platform'] == 'linux':
staticLibs = os.path.join(sdkPath, 'lib', 'linux')
elif AMBuild.target['platform'] == 'darwin':
staticLibs = os.path.join(sdkPath, 'lib', 'mac')
for i in paths:
compiler['CXXINCLUDES'].append(os.path.join(sdkPath, *i))
if not noLink:
if AMBuild.target['platform'] == 'linux':
compiler['POSTLINKFLAGS'][0:0] = ['-lm']
if sdk in ['ep2v', 'css']:
compiler['POSTLINKFLAGS'][0:0] = ['libtier0_srv.so']
compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib_srv.so']
elif sdk in ['l4d', 'l4d2', 'csgo']:
compiler['POSTLINKFLAGS'][0:0] = ['libtier0.so']
compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.so']
else:
compiler['POSTLINKFLAGS'][0:0] = ['tier0_i486.so']
compiler['POSTLINKFLAGS'][0:0] = ['vstdlib_i486.so']
elif AMBuild.target['platform'] == 'darwin':
compiler['POSTLINKFLAGS'][0:0] = ['libtier0.dylib']
compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.dylib']
return compiler
def ResolveEnvPath(self, env, defaultDir):
if env in os.environ:
path = os.environ[env]
if os.path.isdir(path):
return path
else:
head = os.getcwd()
oldhead = None
while head != None and head != oldhead:
path = os.path.join(head, defaultDir)
if os.path.isdir(path):
return path
oldhead = head
head, tail = os.path.split(head)
return None
mms = MMS()
globals = {
'MMS': mms
}
AMBuild.Include(os.path.join('support', 'buildbot', 'Versioning'), globals)
FileList = [
['loader', 'AMBuilder'],
['core', 'AMBuilder'],
['core-legacy', 'AMBuilder'],
['support', 'buildbot', 'PackageScript']
]
for parts in FileList:
AMBuild.Include(os.path.join(*parts), globals)