Modernize build/CI, support SourceMod 1.13, deprecate ForceHeartbeat

Rework the build and CI: swap to SourceMod's safetyhook-based CDetour and
drop the vendored CDetour/asm sources, the old Makefile, Travis config, and
buildbot perl scripts. Add GitHub Actions building and releasing x86 and
x86_64 against SM 1.12 and 1.13, plus dependabot. Split the Windows and Linux
packages and tidy naming.

Gate IPluginManager::FindPluginByContext on the extension API version so the
extension builds against both SM 1.12 (API 8) and 1.13 (API 9), and shim
DETOUR_CREATE_STATIC_FIXED over the address overload safetyhook exposes.

Deprecate SteamWorks_ForceHeartbeat: newer Steamworks SDKs removed
ISteamGameServer::ForceHeartbeat, so make the native a no-op and mark it
deprecated in the include.
This commit is contained in:
Nicholas Hastings
2026-07-12 10:56:36 -04:00
parent f0c1b62dff
commit 39fcfa564e
21 changed files with 332 additions and 1842 deletions
+37 -31
View File
@@ -1,31 +1,37 @@
# vim: set ts=8 sts=2 sw=2 tw=99 et ft=python:
import os
builder.SetBuildFolder('package')
folder_list = [
'addons/sourcemod/extensions',
'addons/sourcemod/scripting',
'addons/sourcemod/scripting/include',
]
# Create the distribution folder hierarchy.
folder_map = {}
for folder in folder_list:
norm_folder = os.path.normpath(folder)
folder_map[folder] = builder.AddFolder(norm_folder)
for extension in SteamWorks.extensions:
builder.AddCopy(extension.binary, folder_map['addons/sourcemod/extensions'])
# Do all straight-up file copies from the source tree.
def CopyFiles(src, dest, files):
if not dest:
dest = src
dest_entry = folder_map[dest]
for source_file in files:
source_path = os.path.join(builder.sourcePath, src, source_file)
builder.AddCopy(source_path, dest_entry)
CopyFiles('Pawn', 'addons/sourcemod/scripting', ['swag.sp'])
CopyFiles('Pawn/includes', 'addons/sourcemod/scripting/include', ['SteamWorks.inc'])
# vim: set ts=8 sts=2 sw=2 tw=99 et ft=python:
import os
builder.SetBuildFolder('package')
# 64-bit extensions live under an x64/ subfolder; 32-bit sit directly in
# extensions/. Only one architecture is built per configure, so pick the
# matching destination here.
if builder.cxx.target.arch == 'x86_64':
ext_folder = 'addons/sourcemod/extensions/x64'
else:
ext_folder = 'addons/sourcemod/extensions'
folder_list = [
ext_folder,
'addons/sourcemod/scripting/include',
]
# Create the distribution folder hierarchy.
folder_map = {}
for folder in folder_list:
norm_folder = os.path.normpath(folder)
folder_map[folder] = builder.AddFolder(norm_folder)
for extension in SteamWorks.extensions:
builder.AddCopy(extension.binary, folder_map[ext_folder])
# Do all straight-up file copies from the source tree.
def CopyFiles(src, dest, files):
if not dest:
dest = src
dest_entry = folder_map[dest]
for source_file in files:
source_path = os.path.join(builder.sourcePath, src, source_file)
builder.AddCopy(source_path, dest_entry)
CopyFiles('Pawn/includes', 'addons/sourcemod/scripting/include', ['SteamWorks.inc'])
-174
View File
@@ -1,174 +0,0 @@
#!/usr/bin/perl
use strict;
use Cwd;
package Build;
our $SVN = "/usr/bin/svn";
our $SVN_USER = 'dvander';
our $SVN_ARGS = '';
sub GitRevNum
{
my ($path) = (@_);
my ($cd, $text, $rev);
$cd = Cwd::cwd();
chdir($path);
$text = `git rev-list --count HEAD`;
chdir($cd);
chomp $text;
if ($text =~ /^(\d+)/) {
return $1;
}
return 0;
}
sub HgRevNum
{
my ($path) = (@_);
my ($cd, $text, $rev);
$cd = Cwd::cwd();
chdir($path);
$text = `hg identify -n`;
chdir($cd);
chomp $text;
if ($text =~ /^(\d+)/)
{
return $1;
}
return 0;
}
sub SvnRevNum
{
my ($str)=(@_);
my $data = Command('svnversion -c ' . $str);
if ($data =~ /(\d+):(\d+)/)
{
return $2;
} elsif ($data =~ /(\d+)/) {
return $1;
} else {
return 0;
}
}
sub ProductVersion
{
my ($file) = (@_);
my ($version);
open(FILE, $file) or die "Could not open $file: $!\n";
$version = <FILE>;
close(FILE);
chomp $version;
return $version;
}
sub Delete
{
my ($str)=(@_);
if ($^O =~ /MSWin/)
{
Command("del /S /F /Q \"$str\"");
Command("rmdir /S /Q \"$str\"");
} else {
Command("rm -rf $str");
}
return !(-e $str);
}
sub Copy
{
my ($src,$dest)=(@_);
if ($^O =~ /MSWin/)
{
Command("copy \"$src\" \"$dest\" /y");
} else {
Command("cp \"$src\" \"$dest\"");
}
return (-e $dest);
}
sub Move
{
my ($src,$dest)=(@_);
if ($^O =~ /MSWin/)
{
Command("move \"$src\" \"$dest\"");
} else {
Command("mv \"$src\" \"$dest\"");
}
return (-e $dest);
}
sub Command
{
my($cmd)=(@_);
print "$cmd\n";
return `$cmd`;
}
sub PathFormat
{
my ($str)=(@_);
if ($^O =~ /MSWin/)
{
$str =~ s#/#\\#g;
} else {
$str =~ s#\\#/#g;
}
return $str;
}
sub SVN_Remove
{
my ($file)=(@_);
my ($path, $name);
if ($^O =~ /MSWin/)
{
($path, $name) = ($file =~ /(.+)\/([^\/]+)$/);
} else {
($path, $name) = ($file =~ /(.+)\\([^\\]+)$/);
}
my $dir = Cwd::cwd();
chdir($path);
Command($SVN . ' ' . $SVN_ARGS . ' delete ' . $name);
chdir($dir);
}
sub SVN_Add
{
my ($file)=(@_);
my ($path, $name);
if ($^O =~ /MSWin/)
{
($path, $name) = ($file =~ /(.+)\/([^\/]+)$/);
} else {
($path, $name) = ($file =~ /(.+)\\([^\\]+)$/);
}
my $dir = Cwd::cwd();
chdir($path);
Command($SVN . ' ' . $SVN_ARGS . ' add ' . $name);
chdir($dir);
}
sub GetBuildType
{
my ($file)=(@_);
my ($type);
open(TYPE, $file) or die("Could not open file: $!\n");
$type = <TYPE>;
close(TYPE);
chomp $type;
return $type;
}
return 1;
-106
View File
@@ -1,106 +0,0 @@
# Pastebin eziGmKtQ
#!/usr/bin/perl
use strict;
use Cwd;
use File::Basename;
use File::Copy;
use File::Path;
use Net::FTP;
my ($ftp_file, $ftp_host, $ftp_user, $ftp_pass, $ftp_path, $tag);
$ftp_file = shift;
$tag = shift;
open(FTP, $ftp_file) or die "Unable to read FTP config file $ftp_file: $!\n";
$ftp_host = <FTP>;
$ftp_user = <FTP>;
$ftp_pass = <FTP>;
$ftp_path = <FTP>;
close(FTP);
chomp $ftp_host;
chomp $ftp_user;
chomp $ftp_pass;
chomp $ftp_path;
my ($myself, $path) = fileparse($0);
chdir($path);
require 'helpers.pm';
my ($version, $ext);
$version .= '-git' . Build::GitRevNum('.');
# Append OS to package version
if ($^O eq "darwin")
{
$ext = ".dylib";
$version .= '-mac';
}
elsif ($^O =~ /MSWin/)
{
$ext = ".dll";
$version .= '-windows';
}
elsif ($^O eq "linux")
{
$ext = ".so";
$version .= '-linux';
}
else
{
$version .= '-' . $^O;
}
#Switch to the output folder.
chdir(Build::PathFormat('../build/package'));
my ($dirlist, $filename, $cmd);
$dirlist = "addons";
$filename = 'SteamWorks' . $version;
if ($^O eq "linux")
{
$filename .= '.tar.gz';
$cmd = "tar zcvf $filename $dirlist";
}
else
{
$filename .= '.zip';
$cmd = "zip -r $filename $dirlist";
}
print "$cmd\n";
system($cmd);
$ftp_path .= "/SteamWorks";
my ($ftp);
$ftp = Net::FTP->new($ftp_host, Debug => 0, Passive => 1)
or die "Cannot connect to host $ftp_host: $@";
$ftp->login($ftp_user, $ftp_pass)
or die "Cannot connect to host $ftp_host as $ftp_user: " . $ftp->message . "\n";
if ($ftp_path ne '')
{
# YOU LEAVE ME NO CHOICE
$ftp->mkdir($ftp_path, 1);
$ftp->cwd($ftp_path)
or die "Cannot change to folder $ftp_path: " . $ftp->message . "\n";
}
$ftp->binary();
$ftp->put($filename)
or die "Cannot drop file $filename ($ftp_path): " . $ftp->message . "\n";
$ftp->close();
print "File sent to drop site as $filename -- build succeeded.\n";
exit(0);