You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
406 lines
13 KiB
406 lines
13 KiB
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: |
|
import os, sys |
|
|
|
# Simple extensions do not need to modify this file. |
|
|
|
class SDK(object): |
|
def __init__(self, sdk, ext, aDef, name, platform, dir): |
|
self.folder = 'hl2sdk-' + dir |
|
self.envvar = sdk |
|
self.ext = ext |
|
self.code = aDef |
|
self.define = name |
|
self.platform = platform |
|
self.name = dir |
|
self.path = None |
|
|
|
WinOnly = ['windows'] |
|
WinLinux = ['windows', 'linux'] |
|
WinLinuxMac = ['windows', 'linux', 'mac'] |
|
|
|
PossibleSDKs = { |
|
'css': SDK('HL2SDKCSS', '2.css', '6', 'CSS', WinLinuxMac, 'css'), |
|
} |
|
|
|
def ResolveEnvPath(env, folder): |
|
if env in os.environ: |
|
path = os.environ[env] |
|
if os.path.isdir(path): |
|
return path |
|
return None |
|
|
|
head = os.getcwd() |
|
oldhead = None |
|
while head != None and head != oldhead: |
|
path = os.path.join(head, folder) |
|
if os.path.isdir(path): |
|
return path |
|
oldhead = head |
|
head, tail = os.path.split(head) |
|
|
|
return None |
|
|
|
def Normalize(path): |
|
return os.path.abspath(os.path.normpath(path)) |
|
|
|
class ExtensionConfig(object): |
|
def __init__(self): |
|
self.sdks = {} |
|
self.binaries = [] |
|
self.extensions = [] |
|
self.generated_headers = None |
|
self.mms_root = None |
|
self.sm_root = None |
|
|
|
@property |
|
def tag(self): |
|
if builder.options.debug == '1': |
|
return 'Debug' |
|
return 'Release' |
|
|
|
def detectSDKs(self): |
|
sdk_list = builder.options.sdks.split(',') |
|
use_all = sdk_list[0] == 'all' |
|
use_present = sdk_list[0] == 'present' |
|
|
|
for sdk_name in PossibleSDKs: |
|
sdk = PossibleSDKs[sdk_name] |
|
if builder.target_platform in sdk.platform: |
|
if builder.options.hl2sdk_root: |
|
sdk_path = os.path.join(builder.options.hl2sdk_root, sdk.folder) |
|
else: |
|
sdk_path = ResolveEnvPath(sdk.envvar, sdk.folder) |
|
if sdk_path is None or not os.path.isdir(sdk_path): |
|
if use_all or sdk_name in sdk_list: |
|
raise Exception('Could not find a valid path for {0}'.format(sdk.envvar)) |
|
continue |
|
if use_all or use_present or sdk_name in sdk_list: |
|
sdk.path = Normalize(sdk_path) |
|
self.sdks[sdk_name] = sdk |
|
|
|
if len(self.sdks) < 1: |
|
raise Exception('At least one SDK must be available.') |
|
|
|
if builder.options.sm_path: |
|
self.sm_root = builder.options.sm_path |
|
else: |
|
self.sm_root = ResolveEnvPath('SOURCEMOD18', 'sourcemod-1.8') |
|
if not self.sm_root: |
|
self.sm_root = ResolveEnvPath('SOURCEMOD', 'sourcemod') |
|
if not self.sm_root: |
|
self.sm_root = ResolveEnvPath('SOURCEMOD_DEV', 'sourcemod-central') |
|
|
|
if not self.sm_root or not os.path.isdir(self.sm_root): |
|
raise Exception('Could not find a source copy of SourceMod') |
|
self.sm_root = Normalize(self.sm_root) |
|
|
|
if builder.options.mms_path: |
|
self.mms_root = builder.options.mms_path |
|
else: |
|
self.mms_root = ResolveEnvPath('MMSOURCE110', 'mmsource-1.10') |
|
if not self.mms_root: |
|
self.mms_root = ResolveEnvPath('MMSOURCE', 'metamod-source') |
|
if not self.mms_root: |
|
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'mmsource-central') |
|
|
|
if not self.mms_root or not os.path.isdir(self.mms_root): |
|
raise Exception('Could not find a source copy of Metamod:Source') |
|
self.mms_root = Normalize(self.mms_root) |
|
|
|
def configure(self): |
|
cxx = builder.DetectCompilers() |
|
|
|
if cxx.like('gcc'): |
|
cxx.defines += [ |
|
'stricmp=strcasecmp', |
|
'_stricmp=strcasecmp', |
|
'_snprintf=snprintf', |
|
'_vsnprintf=vsnprintf', |
|
'HAVE_STDINT_H', |
|
'GNUC', |
|
] |
|
cxx.cflags += [ |
|
'-pipe', |
|
'-fno-strict-aliasing', |
|
'-Wall', |
|
'-Werror', |
|
'-Wno-unused', |
|
'-Wno-switch', |
|
'-Wno-array-bounds', |
|
'-msse', |
|
'-m32', |
|
] |
|
cxx.cxxflags += [ |
|
'-std=c++11', |
|
] |
|
|
|
have_gcc = cxx.vendor == 'gcc' |
|
have_clang = cxx.vendor == 'clang' |
|
if have_clang or (have_gcc and cxx.version >= '4'): |
|
cxx.cflags += ['-fvisibility=hidden'] |
|
cxx.cxxflags += ['-fvisibility-inlines-hidden'] |
|
if have_clang or (have_gcc and cxx.version >= '4.6'): |
|
cxx.cflags += ['-Wno-narrowing'] |
|
if (have_gcc and cxx.version >= '4.7') or (have_clang and cxx.version >= '3'): |
|
cxx.cxxflags += ['-Wno-delete-non-virtual-dtor'] |
|
if have_gcc and cxx.version >= '4.8': |
|
cxx.cflags += ['-Wno-unused-result'] |
|
if have_clang: |
|
cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch'] |
|
if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4': |
|
cxx.cxxflags += ['-Wno-deprecated-register'] |
|
else: |
|
cxx.cxxflags += ['-Wno-deprecated'] |
|
cxx.cflags += ['-Wno-sometimes-uninitialized'] |
|
|
|
cxx.linkflags += ['-m32'] |
|
cxx.cxxflags += [ |
|
'-fno-exceptions', |
|
'-fno-threadsafe-statics', |
|
'-Wno-non-virtual-dtor', |
|
'-Wno-overloaded-virtual', |
|
] |
|
|
|
if have_gcc: |
|
cxx.cflags += ['-mfpmath=sse'] |
|
elif cxx.vendor == 'msvc': |
|
if builder.options.debug == '1': |
|
cxx.cflags += ['/MTd'] |
|
cxx.linkflags += ['/NODEFAULTLIB:libcmt'] |
|
else: |
|
cxx.cflags += ['/MT'] |
|
cxx.defines += [ |
|
'_CRT_SECURE_NO_DEPRECATE', |
|
'_CRT_SECURE_NO_WARNINGS', |
|
'_CRT_NONSTDC_NO_DEPRECATE', |
|
'_ITERATOR_DEBUG_LEVEL=0', |
|
] |
|
cxx.cflags += [ |
|
'/W3', |
|
] |
|
cxx.cxxflags += [ |
|
'/EHsc', |
|
'/GR-', |
|
'/TP', |
|
] |
|
cxx.linkflags += [ |
|
'/MACHINE:X86', |
|
'kernel32.lib', |
|
'user32.lib', |
|
'gdi32.lib', |
|
'winspool.lib', |
|
'comdlg32.lib', |
|
'advapi32.lib', |
|
'shell32.lib', |
|
'ole32.lib', |
|
'oleaut32.lib', |
|
'uuid.lib', |
|
'odbc32.lib', |
|
'odbccp32.lib', |
|
] |
|
|
|
# Optimization |
|
if builder.options.opt == '1': |
|
cxx.defines += ['NDEBUG'] |
|
if cxx.like('gcc'): |
|
cxx.cflags += ['-O3'] |
|
elif cxx.like('msvc'): |
|
cxx.cflags += ['/Ox', '/Zo'] |
|
cxx.linkflags += ['/OPT:ICF', '/OPT:REF'] |
|
|
|
# Debugging |
|
if builder.options.debug == '1': |
|
cxx.defines += ['DEBUG', '_DEBUG'] |
|
if cxx.like('msvc'): |
|
cxx.cflags += ['/Od', '/RTC1'] |
|
|
|
# This needs to be after our optimization flags which could otherwise disable it. |
|
if cxx.vendor == 'msvc': |
|
# Don't omit the frame pointer. |
|
cxx.cflags += ['/Oy-'] |
|
|
|
# Platform-specifics |
|
if builder.target_platform == 'linux': |
|
cxx.defines += ['_LINUX', 'POSIX'] |
|
cxx.linkflags += ['-lm'] |
|
if cxx.vendor == 'gcc': |
|
cxx.linkflags += ['-static-libgcc'] |
|
elif cxx.vendor == 'clang': |
|
cxx.linkflags += ['-lgcc_eh'] |
|
elif builder.target_platform == 'mac': |
|
cxx.defines += ['OSX', '_OSX', 'POSIX'] |
|
cxx.cflags += ['-mmacosx-version-min=10.5'] |
|
cxx.linkflags += [ |
|
'-mmacosx-version-min=10.5', |
|
'-arch', 'i386', |
|
'-lstdc++', |
|
'-stdlib=libstdc++', |
|
] |
|
cxx.cxxflags += ['-stdlib=libstdc++'] |
|
elif builder.target_platform == 'windows': |
|
cxx.defines += ['WIN32', '_WINDOWS'] |
|
|
|
# Finish up. |
|
cxx.includes += [ |
|
os.path.join(self.sm_root, 'public'), |
|
] |
|
|
|
def ConfigureForHL2(self, binary, sdk): |
|
compiler = binary.compiler |
|
|
|
if sdk.name == 'episode1': |
|
mms_path = os.path.join(self.mms_root, 'core-legacy') |
|
else: |
|
mms_path = os.path.join(self.mms_root, 'core') |
|
|
|
compiler.cxxincludes += [ |
|
os.path.join(mms_path), |
|
os.path.join(mms_path, 'sourcehook'), |
|
] |
|
|
|
defines = ['SE_' + PossibleSDKs[i].define + '=' + PossibleSDKs[i].code for i in PossibleSDKs] |
|
compiler.defines += defines |
|
|
|
paths = [ |
|
['public'], |
|
['public', 'engine'], |
|
['public', 'mathlib'], |
|
['public', 'vstdlib'], |
|
['public', 'tier0'], |
|
['public', 'tier1'] |
|
] |
|
if sdk.name == 'episode1' or sdk.name == 'darkm': |
|
paths.append(['public', 'dlls']) |
|
paths.append(['game_shared']) |
|
else: |
|
paths.append(['public', 'game', 'server']) |
|
paths.append(['public', 'toolframework']) |
|
paths.append(['game', 'shared']) |
|
paths.append(['common']) |
|
|
|
compiler.defines += ['SOURCE_ENGINE=' + sdk.code] |
|
|
|
if sdk.name in ['sdk2013', 'bms'] and compiler.like('gcc'): |
|
# The 2013 SDK already has these in public/tier0/basetypes.h |
|
compiler.defines.remove('stricmp=strcasecmp') |
|
compiler.defines.remove('_stricmp=strcasecmp') |
|
compiler.defines.remove('_snprintf=snprintf') |
|
compiler.defines.remove('_vsnprintf=vsnprintf') |
|
|
|
if compiler.like('msvc'): |
|
compiler.defines += ['COMPILER_MSVC', 'COMPILER_MSVC32'] |
|
else: |
|
compiler.defines += ['COMPILER_GCC'] |
|
|
|
# For everything after Swarm, this needs to be defined for entity networking |
|
# to work properly with sendprop value changes. |
|
if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']: |
|
compiler.defines += ['NETWORK_VARS_ENABLED'] |
|
|
|
if sdk.name in ['css', 'hl2dm', 'dods', 'sdk2013', 'bms', 'tf2', 'l4d', 'nucleardawn', 'l4d2', 'dota']: |
|
if builder.target_platform in ['linux', 'mac']: |
|
compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE'] |
|
|
|
if sdk.name == 'csgo' and builder.target_platform == 'linux': |
|
compiler.linkflags += ['-lstdc++'] |
|
|
|
for path in paths: |
|
compiler.cxxincludes += [os.path.join(sdk.path, *path)] |
|
|
|
if builder.target_platform == 'linux': |
|
if sdk.name == 'episode1': |
|
lib_folder = os.path.join(sdk.path, 'linux_sdk') |
|
elif sdk.name in ['sdk2013', 'bms']: |
|
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32') |
|
else: |
|
lib_folder = os.path.join(sdk.path, 'lib', 'linux') |
|
elif builder.target_platform == 'mac': |
|
if sdk.name in ['sdk2013', 'bms']: |
|
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32') |
|
else: |
|
lib_folder = os.path.join(sdk.path, 'lib', 'mac') |
|
|
|
if builder.target_platform in ['linux', 'mac']: |
|
if sdk.name in ['sdk2013', 'bms']: |
|
compiler.postlink += [ |
|
compiler.Dep(os.path.join(lib_folder, 'tier1.a')), |
|
compiler.Dep(os.path.join(lib_folder, 'mathlib.a')) |
|
] |
|
else: |
|
compiler.postlink += [ |
|
compiler.Dep(os.path.join(lib_folder, 'tier1_i486.a')), |
|
compiler.Dep(os.path.join(lib_folder, 'mathlib_i486.a')) |
|
] |
|
|
|
if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']: |
|
compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces_i486.a'))] |
|
|
|
dynamic_libs = [] |
|
if builder.target_platform == 'linux': |
|
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', 'sdk2013', 'bms', 'nucleardawn', 'l4d2']: |
|
dynamic_libs = ['libtier0_srv.so', 'libvstdlib_srv.so'] |
|
elif sdk.name in ['l4d', 'blade', 'insurgency', 'csgo', 'dota']: |
|
dynamic_libs = ['libtier0.so', 'libvstdlib.so'] |
|
else: |
|
dynamic_libs = ['tier0_i486.so', 'vstdlib_i486.so'] |
|
elif builder.target_platform == 'mac': |
|
compiler.linkflags.append('-liconv') |
|
dynamic_libs = ['libtier0.dylib', 'libvstdlib.dylib'] |
|
elif builder.target_platform == 'windows': |
|
libs = ['tier0', 'tier1', 'vstdlib', 'mathlib'] |
|
if sdk.name in ['swarm', 'blade', 'insurgency', 'csgo', 'dota']: |
|
libs.append('interfaces') |
|
for lib in libs: |
|
lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib' |
|
compiler.linkflags.append(compiler.Dep(lib_path)) |
|
|
|
for library in dynamic_libs: |
|
source_path = os.path.join(lib_folder, library) |
|
output_path = os.path.join(binary.localFolder, library) |
|
|
|
def make_linker(source_path, output_path): |
|
def link(context, binary): |
|
cmd_node, (output,) = context.AddSymlink(source_path, output_path) |
|
return output |
|
return link |
|
|
|
linker = make_linker(source_path, output_path) |
|
compiler.linkflags[0:0] = [compiler.Dep(library, linker)] |
|
|
|
return binary |
|
|
|
def ConfigureForExtension(self, context, compiler): |
|
compiler.cxxincludes += [ |
|
os.path.join(context.currentSourcePath), |
|
os.path.join(context.currentSourcePath, 'sdk'), |
|
os.path.join(self.sm_root, 'public'), |
|
os.path.join(self.sm_root, 'public', 'extensions'), |
|
os.path.join(self.sm_root, 'sourcepawn', 'include'), |
|
os.path.join(self.sm_root, 'public', 'amtl', 'include'), |
|
] |
|
return compiler |
|
|
|
def HL2Project(self, context, name): |
|
project = context.compiler.LibraryProject(name) |
|
self.ConfigureForExtension(context, project.compiler) |
|
return project |
|
|
|
def HL2Config(self, project, name, sdk): |
|
binary = project.Configure(name, '{0} - {1}'.format(self.tag, sdk.name)) |
|
return self.ConfigureForHL2(binary, sdk) |
|
|
|
Extension = ExtensionConfig() |
|
Extension.detectSDKs() |
|
Extension.configure() |
|
|
|
# Add additional buildscripts here |
|
BuildScripts = [ |
|
'AMBuilder', |
|
] |
|
|
|
if builder.backend == 'amb2': |
|
BuildScripts += [ |
|
'PackageScript', |
|
] |
|
|
|
builder.RunBuildScripts(BuildScripts, { 'Extension': Extension})
|
|
|