diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3d94e71 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# AMBuild2 build outputs +build/ diff --git a/AMBuildScript b/AMBuildScript new file mode 100644 index 0000000..84e8509 --- /dev/null +++ b/AMBuildScript @@ -0,0 +1,631 @@ +# 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 # Actual path + self.platformSpec = platform + + # By default, nothing supports x64. + if type(platform) is list: + self.platformSpec = {p: ["x86"] for p in platform} + else: + self.platformSpec = platform + + def shouldBuild(self, targets): + for cxx in targets: + if cxx.target.platform in self.platformSpec: + if cxx.target.arch in self.platformSpec[cxx.target.platform]: + return True + return False + + +WinLinux = ["windows", "linux"] +TF2 = {"windows": ["x86", "x86_64"], "linux": ["x86", "x86_64"]} +CSGO = {"windows": ["x86"], "linux": ["x86", "x86_64"]} + +PossibleSDKs = { + # 'episode1': SDK('HL2SDK', '1.ep1', '1', 'EPISODEONE', WinLinux, 'episode1'), + # 'darkm': SDK('HL2SDK-DARKM', '2.darkm', '2', 'DARKMESSIAH', WinOnly, 'darkm'), + # 'orangebox': SDK('HL2SDKOB', '2.ep2', '3', 'ORANGEBOX', WinLinux, 'orangebox'), + # 'bgt': SDK('HL2SDK-BGT', '2.bgt', '4', 'BLOODYGOODTIME', WinOnly, 'bgt'), + # 'eye': SDK('HL2SDK-EYE', '2.eye', '5', 'EYE', WinOnly, 'eye'), + "css": SDK("HL2SDKCSS", "2.css", "6", "CSS", WinLinux, "css"), + "hl2dm": SDK("HL2SDKHL2DM", "2.hl2dm", "7", "HL2DM", WinLinux, "hl2dm"), + "dods": SDK("HL2SDKDODS", "2.dods", "8", "DODS", WinLinux, "dods"), + "sdk2013": SDK("HL2SDK2013", "2.sdk2013", "9", "SDK2013", WinLinux, "sdk2013"), + # 'bms': SDK('HL2SDKBMS', '2.bms', '11', 'BMS', WinLinux, 'bms'), + "tf2": SDK("HL2SDKTF2", "2.tf2", "12", "TF2", TF2, "tf2"), + "l4d": SDK("HL2SDKL4D", "2.l4d", "13", "LEFT4DEAD", WinLinux, "l4d"), + # 'nucleardawn': SDK('HL2SDKND', '2.nd', '14', 'NUCLEARDAWN', WinLinuxMac, 'nucleardawn'), + # 'contagion': SDK('HL2SDKCONTAGION', '2.contagion', '15', 'CONTAGION', WinOnly, 'contagion'), + "l4d2": SDK("HL2SDKL4D2", "2.l4d2", "16", "LEFT4DEAD2", WinLinux, "l4d2"), + # 'swarm': SDK('HL2SDK-SWARM', '2.swarm', '17', 'ALIENSWARM', WinOnly, 'swarm'), + # 'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '18', 'PORTAL2', [], 'portal2'), + # 'insurgency': SDK('HL2SDKINSURGENCY', '2.insurgency', '19', 'INSURGENCY', WinLinuxMac, 'insurgency'), + # 'blade': SDK('HL2SDKBLADE', '2.blade', '21', 'BLADE', WinLinux, 'blade'), + "csgo": SDK("HL2SDKCSGO", "2.csgo", "23", "CSGO", CSGO, "csgo"), +} + + +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)) + + +def SetArchFlags(compiler): + if compiler.behavior == "gcc": + if compiler.target.arch == "x86_64": + compiler.cflags += ["-fPIC"] + elif compiler.like("msvc"): + if compiler.target.arch == "x86_64": + compiler.defines += ["WIN64"] + + +class ExtensionConfig(object): + def __init__(self): + self.sdks = {} + self.binaries = [] + self.extensions = [] + self.generated_headers = None + self.productVersion = None + self.mms_root = None + self.sm_root = None + self.all_targets = [] + self.target_archs = set() + + 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 use_auto_versioning(self): + return not getattr(builder.options, "disable_auto_versioning", False) + + def AddVersioning(self, binary): + if binary.compiler.target.platform == "windows": + binary.sources += ["version.rc"] + binary.compiler.rcdefines += [ + 'BINARY_NAME="{0}"'.format(binary.outputFile), + "RC_COMPILE", + ] + elif binary.compiler.target.platform == "mac": + if binary.type == "library": + binary.compiler.postlink += [ + "-compatibility_version", + "1.0.0", + "-current_version", + self.productVersion, + ] + if self.use_auto_versioning(): + binary.compiler.sourcedeps += self.generated_headers + return binary + + @property + def tag(self): + if builder.options.debug == "1": + return "Debug" + return "Release" + + def detectProductVersion(self): + builder.AddConfigureFile("product.version") + + # For OS X dylib versioning + import re + + with open(os.path.join(builder.sourcePath, "product.version"), "r") as fp: + productContents = fp.read() + m = re.match("(\\d+)\.(\\d+)\.(\\d+).*", productContents) + if m == None: + self.productVersion = "1.0.0" + else: + major, minor, release = m.groups() + self.productVersion = "{0}.{1}.{2}".format(major, minor, 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 sdk.shouldBuild(self.all_targets): + if builder.options.hl2sdk_root: + sdk_path = os.path.join( + os.path.realpath(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 = os.path.realpath(builder.options.sm_path) + else: + 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): + + if not set(self.target_archs).issubset(["x86", "x86_64"]): + raise Exception( + "Unknown target architecture: {0}".format(self.target_archs) + ) + + for cxx in self.all_targets: + self.configure_cxx(cxx) + + def configure_cxx(self, cxx): + if cxx.family == "msvc": + if cxx.version < 1900: + raise Exception( + "Only MSVC 2015 and later are supported, c++14 support is required." + ) + if cxx.family == "gcc": + if cxx.version < "gcc-4.9": + raise Exception( + "Only GCC versions 4.9 or greater are supported, c++14 support is required." + ) + if cxx.family == "clang": + if cxx.version < "clang-3.4": + raise Exception( + "Only clang versions 3.4 or greater are supported, c++14 support is required." + ) + + if cxx.like("gcc"): + self.configure_gcc(cxx) + elif cxx.family == "msvc": + self.configure_msvc(cxx) + cxx.defines += ["HAVE_STRING_H"] + + # Optimizaiton + if builder.options.opt == "1": + cxx.defines += ["NDEBUG"] + + # Debugging + if builder.options.debug == "1": + cxx.defines += ["DEBUG", "_DEBUG"] + + # Platform-specifics + if cxx.target.platform == "linux": + self.configure_linux(cxx) + elif cxx.target.platform == "mac": + self.configure_mac(cxx) + elif cxx.target.platform == "windows": + self.configure_windows(cxx) + + cxx.includes += [ + os.path.join(self.sm_root, "public"), + ] + + if self.use_auto_versioning(): + cxx.defines += ["SM_GENERATED_BUILD"] + cxx.includes += [os.path.join(builder.buildPath, "includes")] + + def configure_gcc(self, cxx): + cxx.defines += [ + "stricmp=strcasecmp", + "_stricmp=strcasecmp", + "_snprintf=snprintf", + "_vsnprintf=vsnprintf", + "typeof=__typeof__", + "HAVE_STDINT_H", + "GNUC", + ] + cxx.cflags += [ + "-pipe", + "-fno-strict-aliasing", + "-Wall", + "-Wno-unused", + "-Wno-switch", + "-Wno-array-bounds", + "-msse", + "-fvisibility=hidden", + ] + cxx.cxxflags += [ + "-std=c++14", + "-fno-threadsafe-statics", + "-Wno-non-virtual-dtor", + "-Wno-overloaded-virtual", + "-fvisibility-inlines-hidden", + "-fpermissive", + ] + + have_gcc = cxx.vendor == "gcc" + have_clang = cxx.vendor == "clang" + if ( + cxx.version >= "clang-3.9" + or cxx.version == "clang-3.4" + or cxx.version > "apple-clang-6.0" + ): + cxx.cxxflags += ["-Wno-expansion-to-defined"] + if cxx.version == "clang-3.9" or cxx.version == "apple-clang-8.0": + cxx.cflags += ["-Wno-varargs"] + if cxx.version >= "clang-3.4" or cxx.version >= "apple-clang-7.0": + cxx.cxxflags += ["-Wno-inconsistent-missing-override"] + if cxx.version >= "clang-2.9" or cxx.version >= "apple-clang-3.0": + cxx.cxxflags += ["-Wno-null-dereference"] + if have_clang or (cxx.version >= "gcc-4.6"): + cxx.cflags += ["-Wno-narrowing"] + if have_clang or (cxx.version >= "gcc-4.7"): + cxx.cxxflags += ["-Wno-delete-non-virtual-dtor"] + if cxx.version >= "gcc-4.8": + cxx.cflags += ["-Wno-unused-result"] + if cxx.version >= "gcc-9.0": + cxx.cxxflags += ["-Wno-class-memaccess", "-Wno-packed-not-aligned"] + + 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"] + + # Work around SDK warnings. + if cxx.version >= "clang-10.0": + cxx.cflags += [ + "-Wno-implicit-int-float-conversion", + "-Wno-tautological-overlap-compare", + ] + + if have_gcc: + cxx.cflags += ["-mfpmath=sse"] + + if builder.options.opt == "1": + cxx.cflags += ["-O3"] + + def configure_msvc(self, cxx): + 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", + "/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", + ] + + if builder.options.opt == "1": + cxx.cflags += ["/Ox", "/Zo"] + cxx.linkflags += ["/OPT:ICF", "/OPT:REF"] + + if builder.options.debug == "1": + cxx.cflags += ["/Od", "/RTC1"] + + # This needs to be after our optimization flags which could otherwise disable it. + # Don't omit the frame pointer. + cxx.cflags += ["/Oy-"] + + def configure_linux(self, cxx): + cxx.defines += ["_LINUX", "POSIX"] + cxx.linkflags += ["-Wl,--exclude-libs,ALL", "-lm"] + if cxx.vendor == "gcc": + cxx.linkflags += ["-static-libgcc"] + elif cxx.vendor == "clang": + cxx.linkflags += ["-lgcc_eh"] + cxx.linkflags += ["-static-libstdc++"] + + def configure_mac(self, cxx): + cxx.defines += ["OSX", "_OSX", "POSIX"] + cxx.cflags += ["-mmacosx-version-min=10.7"] + cxx.linkflags += [ + "-mmacosx-version-min=10.7", + "-arch", + "i386", + "-lstdc++", + "-stdlib=libstdc++", + ] + cxx.cxxflags += ["-stdlib=libstdc++"] + + def configure_windows(self, cxx): + cxx.defines += ["WIN32", "_WINDOWS"] + + 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", "amtl"), + os.path.join(self.sm_root, "public", "amtl"), + ] + return compiler + + def ConfigureForHL2(self, context, binary, sdk): + compiler = binary.compiler + SetArchFlags(compiler) + + compiler.cxxincludes += [ + os.path.join(self.mms_root, "core"), + os.path.join(self.mms_root, "core", "sourcehook"), + ] + + defines = ["RAD_TELEMETRY_DISABLED"] + 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"] + if compiler.target.arch == "x86": + compiler.defines += ["COMPILER_MSVC32"] + elif compiler.target.arch == "x86_64": + compiler.defines += ["COMPILER_MSVC64"] + compiler.linkflags += ["legacy_stdio_definitions.lib"] + else: + compiler.defines += ["COMPILER_GCC"] + + if compiler.target.arch == "x86_64": + compiler.defines += ["X64BITS", "PLATFORM_64BITS"] + + # 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", "doi", "csgo"]: + compiler.defines += ["NETWORK_VARS_ENABLED"] + + if sdk.name in [ + "css", + "hl2dm", + "dods", + "sdk2013", + "bms", + "tf2", + "l4d", + "nucleardawn", + "l4d2", + ]: + if compiler.target.platform in ["linux", "mac"]: + compiler.defines += ["NO_HOOK_MALLOC", "NO_MALLOC_OVERRIDE"] + + if compiler.target.platform == "linux": + if sdk.name in ["csgo", "blade"]: + compiler.linkflags.remove("-static-libstdc++") + compiler.defines += ["_GLIBCXX_USE_CXX11_ABI=0"] + + for path in paths: + compiler.cxxincludes += [os.path.join(sdk.path, *path)] + + if compiler.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") + elif compiler.target.arch == "x86_64": + lib_folder = os.path.join(sdk.path, "lib", "linux64") + else: + lib_folder = os.path.join(sdk.path, "lib", "linux") + elif compiler.target.platform == "mac": + if sdk.name in ["sdk2013", "bms"]: + lib_folder = os.path.join(sdk.path, "lib", "public", "osx32") + elif compiler.target.arch == "x86_64": + lib_folder = os.path.join(sdk.path, "lib", "osx64") + else: + lib_folder = os.path.join(sdk.path, "lib", "mac") + + if compiler.target.platform in ["linux", "mac"]: + if sdk.name in ["sdk2013", "bms"] or compiler.target.arch == "x86_64": + compiler.postlink += [ + os.path.join(lib_folder, "tier1.a"), + os.path.join(lib_folder, "mathlib.a"), + ] + else: + compiler.postlink += [ + os.path.join(lib_folder, "tier1_i486.a"), + os.path.join(lib_folder, "mathlib_i486.a"), + ] + + if sdk.name in ["blade", "insurgency", "doi", "csgo"]: + if compiler.target.arch == "x86_64": + compiler.postlink += [os.path.join(lib_folder, "interfaces.a")] + else: + compiler.postlink += [os.path.join(lib_folder, "interfaces_i486.a")] + + dynamic_libs = [] + if compiler.target.platform == "linux": + if sdk.name in [ + "css", + "hl2dm", + "dods", + "tf2", + "sdk2013", + "bms", + "nucleardawn", + "l4d2", + "insurgency", + "doi", + ]: + dynamic_libs = ["libtier0_srv.so", "libvstdlib_srv.so"] + elif compiler.target.arch == "x86_64" and sdk.name in ["csgo", "mock"]: + dynamic_libs = ["libtier0_client.so", "libvstdlib_client.so"] + elif sdk.name in ["l4d", "blade", "insurgency", "doi", "csgo"]: + dynamic_libs = ["libtier0.so", "libvstdlib.so"] + else: + dynamic_libs = ["tier0_i486.so", "vstdlib_i486.so"] + elif compiler.target.platform == "mac": + compiler.linkflags.append("-liconv") + dynamic_libs = ["libtier0.dylib", "libvstdlib.dylib"] + elif compiler.target.platform == "windows": + libs = ["tier0", "tier1", "vstdlib", "mathlib"] + if sdk.name in ["swarm", "blade", "insurgency", "doi", "csgo"]: + libs.append("interfaces") + for lib in libs: + if compiler.target.arch == "x86": + lib_path = os.path.join(sdk.path, "lib", "public", lib) + ".lib" + elif compiler.target.arch == "x86_64": + lib_path = ( + os.path.join(sdk.path, "lib", "public", "win64", lib) + ".lib" + ) + compiler.linkflags.append(lib_path) + + for library in dynamic_libs: + source_path = os.path.join(lib_folder, library) + output_path = os.path.join(binary.localFolder, library) + + # Ensure the output path exists. + context.AddFolder(binary.localFolder) + output = context.AddSymlink(source_path, output_path) + + compiler.weaklinkdeps += [output] + compiler.linkflags[0:0] = [library] + + return binary + + def HL2Config(self, project, context, compiler, name, sdk): + binary = project.Configure( + compiler, + name, + "{0} - {1} {2}".format(self.tag, sdk.name, compiler.target.arch), + ) + self.AddVersioning(binary) + return self.ConfigureForHL2(context, binary, sdk) + + def HL2ExtConfig(self, project, context, compiler, name, sdk): + binary = project.Configure( + compiler, + name, + "{0} - {1} {2}".format(self.tag, sdk.name, compiler.target.arch), + ) + self.AddVersioning(binary) + self.ConfigureForHL2(context, binary, sdk) + self.ConfigureForExtension(context, binary.compiler) + return binary + + +Extension = ExtensionConfig() +Extension.detectProductVersion() +Extension.detectSDKs() +Extension.configure() + +if Extension.use_auto_versioning(): + Extension.generated_headers = builder.Build("buildbot/Versioning") + +builder.targets = builder.CloneableList(Extension.all_targets) +# Add additional buildscripts here +BuildScripts = ["src/AMBuilder", "buildbot/PackageScript", "buildbot/BreakpadSymbols"] + +builder.Build(BuildScripts, {"Extension": Extension}) diff --git a/buildbot/BreakpadSymbols b/buildbot/BreakpadSymbols new file mode 100644 index 0000000..a85f0bf --- /dev/null +++ b/buildbot/BreakpadSymbols @@ -0,0 +1,39 @@ +# vim: set ts=2 sw=2 tw=99 noet ft=python: +import os, sys + +UPLOAD_SCRIPT = os.path.join(Extension.sm_root, 'tools', 'buildbot', 'upload_symbols.py') + +if 'BREAKPAD_SYMBOL_SERVER' in os.environ: + symbolServer = os.environ['BREAKPAD_SYMBOL_SERVER'] + builder.SetBuildFolder('breakpad-symbols') + + for cxx_task in Extension.extensions: + if cxx_task.target.platform in ['windows']: + debug_entry = cxx_task.debug + else: + debug_entry = cxx_task.binary + + debug_file = os.path.join(builder.buildPath, debug_entry.path) + if cxx_task.target.platform == 'linux': + argv = ['dump_syms', debug_file, os.path.dirname(debug_file)] + elif cxx_task.target.platform == 'mac': + # Required once dump_syms is updated on the slaves. + #argv = ['dump_syms', '-g', debug_file + '.dSYM', debug_file] + argv = ['dump_syms', debug_file + '.dSYM'] + elif cxx_task.target.platform == 'windows': + argv = ['dump_syms.exe', debug_file] + + plat_dir = os.path.dirname(debug_file) + bin_dir = os.path.split(plat_dir)[0] + + symbol_file = '{}-{}-{}.breakpad'.format( + os.path.split(bin_dir)[1], + cxx_task.target.platform, + cxx_task.target.arch) + + argv = [sys.executable, UPLOAD_SCRIPT, symbol_file] + argv + builder.AddCommand( + inputs = [UPLOAD_SCRIPT, debug_entry], + argv = argv, + outputs = [symbol_file] + ) \ No newline at end of file diff --git a/buildbot/PackageScript b/buildbot/PackageScript new file mode 100644 index 0000000..22db35f --- /dev/null +++ b/buildbot/PackageScript @@ -0,0 +1,59 @@ +# vim: set ts=2 sw=2 tw=99 noet ft=python: +import os +import shutil +import ambuild.osutil as osutil +from ambuild.command import Command + +builder.SetBuildFolder("package") + + +def CreateFolders(folders): + dict = {} + for folder in folders: + path = os.path.normpath(folder) + dict[folder] = builder.AddFolder(path) + return dict + + +def CopyFiles(src, dest, filter_ext=None): + source_path = os.path.join(builder.sourcePath, src) + if os.path.isfile(source_path): + builder.AddCopy(source_path, dest) + return + for entry in os.listdir(source_path): + entry_path = os.path.join(source_path, entry) + if not os.path.isfile(entry_path): + continue + if filter_ext: + _, ext = os.path.splitext(entry) + if filter_ext != ext: + continue + builder.AddCopy(entry_path, dest) + + +folders = CreateFolders( + [ + "addons/sourcemod/extensions", + "addons/sourcemod/extensions/x64", + "addons/sourcemod/gamedata", + "addons/sourcemod/scripting", + "addons/sourcemod/scripting/include", + ] +) + +pdblog = open(os.path.join(builder.buildPath, "pdblog.txt"), "wt") +for cxx_task in Extension.extensions: + if cxx_task.target.arch == "x86_64": + builder.AddCopy(cxx_task.binary, folders["addons/sourcemod/extensions/x64"]) + else: + builder.AddCopy(cxx_task.binary, folders["addons/sourcemod/extensions"]) + pdblog.write(cxx_task.debug.path + "\n") +pdblog.close() + +CopyFiles("sourcemod/gamedata/collisionhook.txt", folders["addons/sourcemod/gamedata"]) +CopyFiles( + "sourcemod/scripting/include/collisionhook.inc", + folders["addons/sourcemod/scripting/include"], +) + +debug_info = [] diff --git a/buildbot/Versioning b/buildbot/Versioning new file mode 100644 index 0000000..e3647da --- /dev/null +++ b/buildbot/Versioning @@ -0,0 +1,50 @@ +# vim: set ts=8 sts=2 sw=2 tw=99 et ft=python: +import os, sys +import re + +builder.SetBuildFolder('/') +includes = builder.AddFolder('includes') + +argv = [ + sys.executable, + os.path.join(builder.sourcePath, 'buildbot', 'generate_header.py'), + os.path.join(builder.sourcePath), + os.path.join(builder.buildPath, 'includes'), +] + +outputs = [ + os.path.join(builder.buildFolder, 'includes', 'version_auto.h') +] + +repo_head_path = os.path.join(builder.sourcePath, 'product.version') +if os.path.exists(os.path.join(builder.sourcePath, '.git')): + with open(os.path.join(builder.sourcePath, '.git', 'HEAD')) as fp: + head_contents = fp.read().strip() + if re.search('^[a-fA-F0-9]{40}$', head_contents): + repo_head_path = os.path.join(builder.sourcePath, '.git', 'HEAD') + else: + git_state = head_contents.split(':')[1].strip() + repo_head_path = os.path.join(builder.sourcePath, '.git', git_state) + if not os.path.exists(repo_head_path): + repo_head_path = os.path.join(builder.sourcePath, '.git', 'HEAD') + +sources = [ + os.path.join(builder.sourcePath, 'product.version'), + repo_head_path, + argv[1] +] + +for source in sources: + if not os.path.exists(source): + print(source) +for source in sources: + if not os.path.exists(source): + print(source) + +output_nodes = builder.AddCommand( + inputs=sources, + argv=argv, + outputs=outputs +) + +rvalue = output_nodes \ No newline at end of file diff --git a/buildbot/generate_header.py b/buildbot/generate_header.py new file mode 100644 index 0000000..eeb508b --- /dev/null +++ b/buildbot/generate_header.py @@ -0,0 +1,61 @@ +# vim: set ts=2 sw=2 tw=99 noet ft=python: +import os, sys +import re +import subprocess + +argv = sys.argv[1:] +if len(argv) < 2: + sys.stderr.write('Usage: generate_header.py \n') + sys.exit(1) + +SourceFolder = os.path.abspath(os.path.normpath(argv[0])) +OutputFolder = os.path.normpath(argv[1]) + +def run_and_return(argv): + text = subprocess.check_output(argv) + if str != bytes: + text = str(text, 'utf-8') + return text.strip() + +def GetGHVersion(): + p = run_and_return(['hg', 'parent', '-R', SourceFolder]) + m = re.match('changeset:\s+(\d+):(.+)', p.stdoutText) + if m == None: + raise Exception('Could not determine repository version') + return m.groups() + +def GetGitVersion(): + revision_count = run_and_return(['git', 'rev-list', '--count', 'HEAD']) + revision_hash = run_and_return(['git', 'log', '--pretty=format:%h:%H', '-n', '1']) + shorthash, longhash = revision_hash.split(':') + + return revision_count, shorthash + +rev = None +cset = None +rev, cset = GetGitVersion() + +productFile = open(os.path.join(SourceFolder, 'product.version'), 'r') +productContents = productFile.read() +productFile.close() +m = re.match('(\d+)\.(\d+)\.(\d+)(.*)', productContents) +if m == None: + raise Exception('Could not detremine product version') +major, minor, release, tag = m.groups() + +incFile = open(os.path.join(OutputFolder, 'version_auto.h'), 'w') +incFile.write(""" +#ifndef _AUTO_VERSION_INFORMATION_H_ +#define _AUTO_VERSION_INFORMATION_H_ +#define SM_BUILD_TAG \"{0}\" +#define SM_BUILD_UNIQUEID \"{1}:{2}\" SM_BUILD_TAG +#define SM_VERSION \"{3}.{4}.{5}\" +#define SM_FULL_VERSION SM_VERSION SM_BUILD_TAG +#define SM_FILE_VERSION {6},{7},{8},0 +#endif /* _AUTO_VERSION_INFORMATION_H_ */ +""".format(tag, rev, cset, major, minor, release, major, minor, release)) +incFile.close() + +filename_versioning = open(os.path.join(OutputFolder, 'filename_versioning.txt'), 'w') +filename_versioning.write("{0}.{1}.{2}-git{3}-{4}".format(major, minor, release, rev, cset)) +filename_versioning.close() \ No newline at end of file diff --git a/buildbot/pushbuild.txt b/buildbot/pushbuild.txt new file mode 100644 index 0000000..87e1ac9 --- /dev/null +++ b/buildbot/pushbuild.txt @@ -0,0 +1 @@ +Lemons. diff --git a/configure.py b/configure.py new file mode 100644 index 0000000..3e48de3 --- /dev/null +++ b/configure.py @@ -0,0 +1,58 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +import sys +from ambuild2 import run + +# Simple extensions do not need to modify this file. + +parser = run.BuildParser(sourcePath=sys.path[0], api="2.2") + +parser.options.add_argument( + "--hl2sdk-root", + type=str, + dest="hl2sdk_root", + default=None, + help="Root search folder for HL2SDKs", +) +parser.options.add_argument( + "--mms-path", type=str, dest="mms_path", default=None, help="Path to Metamod:Source" +) +parser.options.add_argument( + "--sm-path", type=str, dest="sm_path", default=None, help="Path to SourceMod" +) +parser.options.add_argument( + "--enable-debug", + action="store_const", + const="1", + dest="debug", + help="Enable debugging symbols", +) +parser.options.add_argument( + "--enable-optimize", + action="store_const", + const="1", + dest="opt", + help="Enable optimization", +) +parser.options.add_argument( + "--enable-auto-versioning", + action="store_false", + dest="disable_auto_versioning", + default=True, + help="Enables the auto versioning script", +) +parser.options.add_argument( + "-s", + "--sdks", + default="all", + dest="sdks", + help='Build against specified SDKs; valid args are "all", "present", or ' + "space-delimited list of engine names (default: %default)", +) +parser.options.add_argument( + "--targets", + type=str, + dest="targets", + default=None, + help="Override the target architecture (use commas to separate multiple targets).", +) +parser.Configure() diff --git a/product.version b/product.version new file mode 100644 index 0000000..afaf360 --- /dev/null +++ b/product.version @@ -0,0 +1 @@ +1.0.0 \ No newline at end of file diff --git a/src/AMBuilder b/src/AMBuilder new file mode 100644 index 0000000..87f0d9a --- /dev/null +++ b/src/AMBuilder @@ -0,0 +1,31 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: +import os, sys + +projectname = "collisionhook" + +project = builder.LibraryProject(projectname + ".ext") +project.sources = [ + "extension.cpp", + os.path.join(Extension.sm_root, "public", "smsdk_ext.cpp"), + os.path.join(Extension.sm_root, "public", "CDetour", "detours.cpp"), + os.path.join(Extension.sm_root, "public", "asm", "asm.c"), + os.path.join(Extension.sm_root, "public", "libudis86", "decode.c"), + os.path.join(Extension.sm_root, "public", "libudis86", "itab.c"), + os.path.join(Extension.sm_root, "public", "libudis86", "syn-att.c"), + os.path.join(Extension.sm_root, "public", "libudis86", "syn-intel.c"), + os.path.join(Extension.sm_root, "public", "libudis86", "syn.c"), + os.path.join(Extension.sm_root, "public", "libudis86", "udis86.c"), +] + +for sdk_name in Extension.sdks: + sdk = Extension.sdks[sdk_name] + + for cxx in builder.targets: + if not cxx.target.arch in sdk.platformSpec[cxx.target.platform]: + continue + + binary = Extension.HL2ExtConfig( + project, builder, cxx, projectname + ".ext." + sdk.ext, sdk + ) + +Extension.extensions = builder.Add(project) diff --git a/src/extension.cpp b/src/extension.cpp index 70507d6..a809bd9 100644 --- a/src/extension.cpp +++ b/src/extension.cpp @@ -3,7 +3,7 @@ #include "extension.h" #include "sourcehook.h" -#include "detours.h" +#include "CDetour/detours.h" #include "vphysics_interface.h" #include "ihandleentity.h" diff --git a/src/smsdk_config.h b/src/smsdk_config.h new file mode 100644 index 0000000..3cff7b7 --- /dev/null +++ b/src/smsdk_config.h @@ -0,0 +1,84 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod Sample Extension + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ +#define _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ + +/** + * @file smsdk_config.h + * @brief Contains macros for configuring basic extension information. + */ + + #include "version.h" // SM_FULL_VERSION + +/* Basic information exposed publicly */ +#define SMEXT_CONF_NAME "CollisionHook" +#define SMEXT_CONF_DESCRIPTION "Hook on entity collision" +#define SMEXT_CONF_VERSION SM_FULL_VERSION +#define SMEXT_CONF_AUTHOR "VoiDeD" +#define SMEXT_CONF_URL "http://saxtonhell.com" +#define SMEXT_CONF_LOGTAG "CLHOOK" +#define SMEXT_CONF_LICENSE "GPL" +#define SMEXT_CONF_DATESTRING __DATE__ + +/** + * @brief Exposes plugin's main interface. + */ +#define SMEXT_LINK(name) SDKExtension *g_pExtensionIface = name; + +/** + * @brief Sets whether or not this plugin required Metamod. + * NOTE: Uncomment to enable, comment to disable. + */ +#define SMEXT_CONF_METAMOD + +/** Enable interfaces you want to use here by uncommenting lines */ +#define SMEXT_ENABLE_FORWARDSYS +//#define SMEXT_ENABLE_HANDLESYS +//#define SMEXT_ENABLE_PLAYERHELPERS +//#define SMEXT_ENABLE_DBMANAGER +#define SMEXT_ENABLE_GAMECONF +//#define SMEXT_ENABLE_MEMUTILS +#define SMEXT_ENABLE_GAMEHELPERS +//#define SMEXT_ENABLE_TIMERSYS +//#define SMEXT_ENABLE_THREADER +//#define SMEXT_ENABLE_LIBSYS +//#define SMEXT_ENABLE_MENUS +//#define SMEXT_ENABLE_ADTFACTORY +//#define SMEXT_ENABLE_PLUGINSYS +//#define SMEXT_ENABLE_ADMINSYS +//#define SMEXT_ENABLE_TEXTPARSERS +//#define SMEXT_ENABLE_USERMSGS +//#define SMEXT_ENABLE_TRANSLATOR +//#define SMEXT_ENABLE_NINVOKE +//#define SMEXT_ENABLE_ROOTCONSOLEMENU + +#endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ diff --git a/src/version.h b/src/version.h new file mode 100644 index 0000000..11591f5 --- /dev/null +++ b/src/version.h @@ -0,0 +1,27 @@ +#ifndef _INCLUDE_VERSION_INFORMATION_H_ +#define _INCLUDE_VERSION_INFORMATION_H_ + +/** + * @file Contains version information. + * @brief This file will redirect to an autogenerated version if being compiled via + * the build scripts. + */ + +#if defined SM_GENERATED_BUILD +#include "version_auto.h" +#else + +#ifndef SM_GENERATED_BUILD +#undef BINARY_NAME +#define BINARY_NAME "collisionhook.ext.dll\0" +#endif + +#define SM_BUILD_TAG "-manual" +#define SM_BUILD_UNIQUEID "[MANUAL BUILD]" +#define SM_VERSION "1.0.0" +#define SM_FULL_VERSION SM_VERSION SM_BUILD_TAG +#define SM_FILE_VERSION 1,0,0,0 + +#endif + +#endif /* _INCLUDE_VERSION_INFORMATION_H_ */ diff --git a/src/version.rc b/src/version.rc new file mode 100644 index 0000000..8b40f5b --- /dev/null +++ b/src/version.rc @@ -0,0 +1,45 @@ +#include "winres.h" + +#include + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif + +#ifndef SM_GENERATED_BUILD +#define BINARY_NAME "collisionhook.ext.dll\0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION SM_FILE_VERSION + PRODUCTVERSION SM_FILE_VERSION + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "CollisionHook Extension" + VALUE "FileDescription", "SourceMod CollisionHook Extension" + VALUE "FileVersion", SM_BUILD_UNIQUEID + VALUE "InternalName", "CollisionHook" + VALUE "LegalCopyright", "Copyright (c) 2012, Ryan Stecker" + VALUE "OriginalFilename", BINARY_NAME + VALUE "ProductName", "CollisionHook Extension" + VALUE "ProductVersion", SM_FULL_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04B0 + END +END