# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: import os, sys additional_libs = [ # Path should be relative either to hl2sdk folder or to build folder #'path/to/lib/example.lib', ] additional_defines = [ #'EXAMPLE_DEFINE=2' ] additional_includes = [ # Path should be absolute only! #'D:/absolute/path/to/include/folder/' ] def ResolveEnvPath(env, folder): 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, folder) if os.path.isdir(path): return path oldhead = head head, tail = os.path.split(head) return None def ResolveMMSRoot(): prenormalized_path = None if builder.options.mms_path: prenormalized_path = builder.options.mms_path else: prenormalized_path = ResolveEnvPath('MMSOURCE112', 'mmsource-1.12') if not prenormalized_path: prenormalized_path = ResolveEnvPath('MMSOURCE111', 'mmsource-1.11') if not prenormalized_path: prenormalized_path = ResolveEnvPath('MMSOURCE110', 'mmsource-1.10') if not prenormalized_path: prenormalized_path = ResolveEnvPath('MMSOURCE_DEV', 'metamod-source') if not prenormalized_path: prenormalized_path = ResolveEnvPath('MMSOURCE_DEV', 'mmsource-central') if not prenormalized_path or not os.path.isdir(prenormalized_path): raise Exception('Could not find a source copy of Metamod:Source') return os.path.abspath(os.path.normpath(prenormalized_path)) mms_root = ResolveMMSRoot() SdkHelpers = builder.Eval('hl2sdk-manifests/SdkHelpers.ambuild', { 'Project': 'metamod' }) class MMSPluginConfig(object): def __init__(self): self.sdk_manifests = [] self.sdks = {} self.sdk_targets = [] self.binaries = [] self.mms_root = mms_root self.all_targets = [] self.target_archs = set() if builder.options.plugin_name is not None: self.plugin_name = builder.options.plugin_name else: self.plugin_name = 'sample_mm' if builder.options.plugin_alias is not None: self.plugin_alias = builder.options.plugin_alias else: self.plugin_alias = 'sample' if builder.options.targets: target_archs = builder.options.targets.split(',') else: target_archs = ['x86', 'x86_64'] for arch in target_archs: try: cxx = builder.DetectCxx(target_arch = arch) self.target_archs.add(cxx.target.arch) except Exception as e: # Error if archs were manually overridden. if builder.options.targets: raise print('Skipping target {}: {}'.format(arch, e)) continue self.all_targets.append(cxx) if not self.all_targets: raise Exception('No suitable C/C++ compiler was found.') def findSdkPath(self, sdk_name): dir_name = 'hl2sdk-{}'.format(sdk_name) if builder.options.hl2sdk_root: sdk_path = os.path.join(builder.options.hl2sdk_root, dir_name) if os.path.exists(sdk_path): return sdk_path return ResolveEnvPath('HL2SDK{}'.format(sdk_name.upper()), dir_name) def detectSDKs(self): sdk_list = [s for s in builder.options.sdks.split(',') if s] SdkHelpers.find_sdk_path = self.findSdkPath SdkHelpers.findSdks(builder, self.all_targets, sdk_list) self.sdks = SdkHelpers.sdks self.sdk_manifests = SdkHelpers.sdk_manifests self.sdk_targets = SdkHelpers.sdk_targets if len(self.sdks) > 1: raise Exception('Only one sdk at a time is supported, for multi-sdk approach use loader based solution.') def configure(self): for cxx in self.all_targets: if cxx.target.arch not in ['x86', 'x86_64']: raise Exception('Unknown target architecture: {0}'.format(arch)) self.configure_cxx(cxx) def configure_cxx(self, cxx): if cxx.behavior == 'gcc': cxx.defines += [ 'stricmp=strcasecmp', '_stricmp=strcasecmp', '_snprintf=snprintf', '_vsnprintf=vsnprintf', 'HAVE_STDINT_H', 'GNUC', ] cxx.cflags += [ '-pipe', '-fno-strict-aliasing', '-Wall', '-Werror', '-Wno-uninitialized', '-Wno-unused', '-Wno-switch', '-msse', '-fPIC', ] cxx.cxxflags += ['-std=c++17'] if (cxx.version >= 'gcc-4.0') or cxx.family == 'clang': cxx.cflags += ['-fvisibility=hidden'] cxx.cxxflags += ['-fvisibility-inlines-hidden'] cxx.cxxflags += [ '-fno-exceptions', '-fno-rtti', '-fno-threadsafe-statics', '-Wno-non-virtual-dtor', '-Wno-overloaded-virtual', '-Wno-register', ] if (cxx.version >= 'gcc-4.7' or cxx.family == 'clang'): cxx.cxxflags += ['-Wno-delete-non-virtual-dtor'] if cxx.family == 'gcc': cxx.cflags += ['-mfpmath=sse'] if cxx.family == 'clang': cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch'] if cxx.version >= 'clang-3.9': cxx.cxxflags += ['-Wno-expansion-to-defined'] if cxx.version >= 'clang-3.6': cxx.cxxflags += ['-Wno-inconsistent-missing-override'] if cxx.version >= 'clang-3.4': cxx.cxxflags += ['-Wno-deprecated-register'] else: cxx.cxxflags += ['-Wno-deprecated'] # Work around SDK warnings. if cxx.version >= 'clang-10.0': cxx.cflags += [ '-Wno-implicit-int-float-conversion', '-Wno-tautological-overlap-compare', ] elif cxx.like('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', ] cxx.cflags += [ '/W3', '/Zi', '/std:c++17', ] cxx.cxxflags += ['/TP'] cxx.linkflags += [ '/SUBSYSTEM:WINDOWS', '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.behavior == 'gcc': cxx.cflags += ['-O3'] elif cxx.behavior == 'msvc': cxx.cflags += ['/Ox', '/Zo'] cxx.linkflags += ['/OPT:ICF', '/OPT:REF'] # Debugging if builder.options.debug == '1': cxx.defines += ['DEBUG', '_DEBUG'] if cxx.behavior == 'gcc': cxx.cflags += ['-g3'] elif cxx.behavior == 'msvc': cxx.cflags += ['/Od', '/RTC1'] # Don't omit the frame pointer. # This needs to be after our optimization flags which could otherwise disable it. if cxx.behavior == 'gcc': cxx.cflags += ['-fno-omit-frame-pointer'] elif cxx.behavior == 'msvc': cxx.cflags += ['/Oy-'] # Platform-specifics if cxx.target.platform == 'linux': cxx.defines += ['_LINUX', 'POSIX', '_FILE_OFFSET_BITS=64'] if cxx.family == 'gcc': cxx.linkflags += ['-static-libgcc'] elif cxx.family == 'clang': cxx.linkflags += ['-lgcc_eh'] cxx.linkflags += ['-static-libstdc++'] elif cxx.target.platform == 'windows': cxx.defines += ['WIN32', '_WINDOWS'] # Finish up. # Custom defines here cxx.defines += [ ] # Custom includes here cxx.includes += [ ] def Library(self, cxx, name): binary = cxx.Library(name) return binary def HL2Library(self, context, compiler, name, sdk): binary = self.Library(compiler, name) mms_core_path = os.path.join(self.mms_root, 'core') cxx = binary.compiler cxx.cxxincludes += [ os.path.join(context.currentSourcePath), os.path.join(mms_core_path), os.path.join(mms_core_path, 'sourcehook'), ] defines = [] for other_sdk in self.sdk_manifests: cxx.defines += ['SE_{}={}'.format(other_sdk['define'], other_sdk['code'])] if sdk['source2']: cxx.defines += ['META_IS_SOURCE2'] binary.sources += [ os.path.join(sdk['path'], 'tier0_perproject', 'memoverride.cpp'), os.path.join(sdk['path'], 'tier1', 'convar.cpp'), ] SdkHelpers.configureCxx(context, binary, sdk) cxx.linkflags += additional_libs cxx.defines += additional_defines cxx.cxxincludes += additional_includes return binary MMSPlugin = MMSPluginConfig() MMSPlugin.detectSDKs() MMSPlugin.configure() BuildScripts = [ 'AMBuilder', 'PackageScript', ] builder.Build(BuildScripts, { 'MMSPlugin': MMSPlugin })