fix: crash when exiting linux listen server (#241)
fix: crash when loading on windows xp (#244) build: switched to github hosted runners, and get rid of self-hosted build: windows exe and dll is now code-signed build: drop support for intel icc compiler
This commit is contained in:
parent
c5bdc8dfec
commit
1e9bc3cb5f
9 changed files with 456 additions and 287 deletions
177
.github/workflows/build.yml
vendored
177
.github/workflows/build.yml
vendored
|
|
@ -1,51 +1,154 @@
|
|||
name: YaPB
|
||||
name: build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize]
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
name: Full Build
|
||||
runs-on: self-hosted
|
||||
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- os: windows-latest
|
||||
bin: yapb.dll
|
||||
name: windows
|
||||
|
||||
- os: ubuntu-latest
|
||||
bin: yapb.so
|
||||
name: linux
|
||||
clang: 12
|
||||
|
||||
name: ${{ matrix.name }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
||||
- name: Setup Windows x86
|
||||
if: startsWith (runner.os, 'windows')
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: amd64_x86
|
||||
|
||||
- name: Setup Linux x86
|
||||
if: startsWith (runner.os, 'linux')
|
||||
run: |
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
gcc-multilib g++-multilib libstdc++6 lib32stdc++6 \
|
||||
libc6-dev libc6-dev-i386 linux-libc-dev linux-libc-dev:i386
|
||||
|
||||
echo "CXX=clang-${{ matrix.clang }}" >> $GITHUB_ENV
|
||||
echo "CXX_LD=lld-${{ matrix.clang }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Setup Meson
|
||||
shell: bash
|
||||
run: |
|
||||
meson setup build_x86_win32 --cross-file=/actions/meson/windows-msvc-32bit.txt -Db_vscrt=mt
|
||||
meson setup build_x86_macos --cross-file=/actions/meson/darwin-clang-32bit.txt
|
||||
CXX=clang meson setup build_x86_linux
|
||||
|
||||
- name: Build Bot
|
||||
shell: bash
|
||||
run: |
|
||||
ninja -C build_x86_win32 -v
|
||||
ninja -C build_x86_macos -v
|
||||
ninja -C build_x86_linux -v
|
||||
|
||||
- name: Build Package
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
python -m pip install --upgrade meson ninja
|
||||
|
||||
- name: Configure Build
|
||||
run: |
|
||||
meson setup build
|
||||
|
||||
- name: Compile Source
|
||||
run: |
|
||||
meson compile -v -C build
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ matrix.bin }}
|
||||
path: build/${{ matrix.bin }}
|
||||
|
||||
macos:
|
||||
name: macos
|
||||
runs-on: ubuntu-latest
|
||||
container: j4sdk/macross-x86:latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
||||
- name: Configure Build
|
||||
run: |
|
||||
CXX_LD=/opt/osxcross/target/bin/i386-apple-darwin15-ld meson setup build --cross-file=x86-darwin
|
||||
|
||||
- name: Compile Source
|
||||
run: |
|
||||
meson compile -v -C build
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: yapb.dylib
|
||||
path: build/yapb.dylib
|
||||
|
||||
publish:
|
||||
if: |
|
||||
github.event_name == 'release' &&
|
||||
github.event.action == 'published'
|
||||
|
||||
name: publish
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build, macos]
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
||||
- name: Install Signing Tools
|
||||
run: |
|
||||
sudo apt-get update && sudo apt-get upgrade -y
|
||||
sudo apt-get install -y --no-install-recommends osslsigncode
|
||||
|
||||
- name: Get Artifacts
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Setup Meson
|
||||
run: |
|
||||
python -m pip install --upgrade meson ninja urllib3
|
||||
|
||||
- name: Create Packages
|
||||
run: |
|
||||
meson setup dist
|
||||
ninja -C dist package
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
name: Upload Artifacts
|
||||
env:
|
||||
CS_CERTIFICATE: ${{ secrets.CS_CERTIFICATE }}
|
||||
CS_CERTIFICATE_PASSWORD: ${{ secrets.CS_CERTIFICATE_PASSWORD }}
|
||||
|
||||
- name: Publish Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
name: yapb.zip
|
||||
path: |
|
||||
build_x86_win32/yapb.dll
|
||||
build_x86_linux/yapb.so
|
||||
build_x86_macos/yapb.dylib
|
||||
|
||||
files: pkg/*
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.API_TOKEN }}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
## YaPB
|
||||
[](https://github.com/yapb/yapb/releases/latest) [](https://github.com/yapb/yapb/actions) [](https://github.com/yapb/yapb/blob/master/LICENSE)
|
||||
[](https://github.com/yapb/yapb/releases/latest) [](https://github.com/yapb/yapb/actions) [](https://github.com/yapb/yapb/blob/master/LICENSE)
|
||||
|
||||
## ☉ About
|
||||
It's a computer controlled players (bots) for the Counter-Strike b6.6 - 1.6 and Counter-Strike: Condition Zero. Bots allows you to play that games without connecting any game server or even without internet.
|
||||
|
|
|
|||
22
inc/engine.h
22
inc/engine.h
|
|
@ -643,10 +643,12 @@ class EntityLinkage : public Singleton <EntityLinkage> {
|
|||
private:
|
||||
#if defined (CR_WINDOWS)
|
||||
# define DLSYM_FUNCTION GetProcAddress
|
||||
# define DLCLOSE_FUNCTION FreeLibrary
|
||||
# define DLSYM_RETURN FARPROC
|
||||
# define DLSYM_HANDLE HMODULE
|
||||
#else
|
||||
# define DLSYM_FUNCTION dlsym
|
||||
# define DLCLOSE_FUNCTION dlclose
|
||||
# define DLSYM_RETURN SharedLibrary::Handle
|
||||
# define DLSYM_HANDLE SharedLibrary::Handle
|
||||
#endif
|
||||
|
|
@ -655,6 +657,7 @@ private:
|
|||
bool m_paused { false };
|
||||
|
||||
Detour <decltype (DLSYM_FUNCTION)> m_dlsym;
|
||||
Detour <decltype (DLCLOSE_FUNCTION)> m_dlclose;
|
||||
HashMap <StringRef, DLSYM_RETURN> m_exports;
|
||||
|
||||
SharedLibrary m_self;
|
||||
|
|
@ -666,6 +669,15 @@ public:
|
|||
void initialize ();
|
||||
DLSYM_RETURN lookup (SharedLibrary::Handle module, const char *function);
|
||||
|
||||
int close (DLSYM_HANDLE module) {
|
||||
if (m_self.handle () == module) {
|
||||
disable ();
|
||||
|
||||
return m_dlclose (module);
|
||||
}
|
||||
return m_dlclose (module);
|
||||
}
|
||||
|
||||
public:
|
||||
void callPlayerFunction (edict_t *ent) {
|
||||
#if defined (CR_ANDROID) && defined (CR_ARCH_ARM)
|
||||
|
|
@ -699,16 +711,20 @@ public:
|
|||
}
|
||||
|
||||
public:
|
||||
static DLSYM_RETURN CR_STDCALL replacement (SharedLibrary::Handle module, const char *function) {
|
||||
static DLSYM_RETURN CR_STDCALL lookupHandler (SharedLibrary::Handle module, const char *function) {
|
||||
return EntityLinkage::instance ().lookup (module, function);
|
||||
}
|
||||
|
||||
static int CR_STDCALL closeHandler (DLSYM_HANDLE module) {
|
||||
return EntityLinkage::instance ().close (module);
|
||||
}
|
||||
|
||||
public:
|
||||
void clearExportTable () {
|
||||
void flush () {
|
||||
m_exports.clear ();
|
||||
}
|
||||
|
||||
bool isWorkaroundNeeded () {
|
||||
bool needsBypass () const {
|
||||
return !plat.win && !Game::instance ().isDedicated ();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,12 +9,12 @@
|
|||
|
||||
// generated by meson build system
|
||||
#ifndef MODULE_BUILD_HASH
|
||||
# define MODULE_BUILD_HASH "@commitHash@"
|
||||
# define MODULE_BUILD_AUTHOR @commitAuthor@
|
||||
# define MODULE_BUILD_COUNT "@commitCount@"
|
||||
# define MODULE_BUILD_MACHINE "@buildMachine@"
|
||||
# define MODULE_BUILD_COMPILER "@buildCompiler@"
|
||||
# define MODULE_BOT_VERSION "@buildVersion@"
|
||||
# define MODULE_BOT_VERSION_FILE @buildVersionWin@,@commitCount@
|
||||
# define MODULE_BOT_BUILD_ID "@commitCount@:@commitHash@"
|
||||
# define MODULE_BUILD_HASH "@hash@"
|
||||
# define MODULE_BUILD_AUTHOR @author@
|
||||
# define MODULE_BUILD_COUNT "@count@"
|
||||
# define MODULE_BUILD_MACHINE "@machine@"
|
||||
# define MODULE_BUILD_COMPILER "@compiler@"
|
||||
# define MODULE_BOT_VERSION "@version@"
|
||||
# define MODULE_BOT_VERSION_FILE @version_win@,@count@
|
||||
# define MODULE_BOT_BUILD_ID "@count@:@hash@"
|
||||
#endif
|
||||
|
|
|
|||
12
inc/yapb.h
12
inc/yapb.h
|
|
@ -1147,12 +1147,12 @@ public:
|
|||
template <typename ...Args> void issueCommand (const char *fmt, Args &&...args);
|
||||
};
|
||||
|
||||
#include <config.h>
|
||||
#include <support.h>
|
||||
#include <message.h>
|
||||
#include <engine.h>
|
||||
#include <manager.h>
|
||||
#include <control.h>
|
||||
#include "config.h"
|
||||
#include "support.h"
|
||||
#include "message.h"
|
||||
#include "engine.h"
|
||||
#include "manager.h"
|
||||
#include "control.h"
|
||||
|
||||
// very global convars
|
||||
extern ConVar cv_jasonmode;
|
||||
|
|
|
|||
168
meson.build
168
meson.build
|
|
@ -22,55 +22,59 @@ project (
|
|||
'strip=true',
|
||||
'optimization=3',
|
||||
'default_library=static',
|
||||
'cpp_eh=none'
|
||||
'cpp_eh=none',
|
||||
'b_vscrt=static_from_buildtype'
|
||||
],
|
||||
meson_version: '>=0.48.0')
|
||||
meson_version: '>=0.56.0')
|
||||
|
||||
find_program ('ninja', required: true)
|
||||
find_program ('git', required: true)
|
||||
find_program ('hostname', required: true)
|
||||
|
||||
buildCompiler = meson.get_compiler ('cpp')
|
||||
buildSystem = host_machine.system ()
|
||||
buildVersion = meson.project_version ()
|
||||
buildCount = run_command ('git', 'rev-list', '--count', 'HEAD').stdout ().strip ()
|
||||
cpp = meson.get_compiler ('cpp')
|
||||
sys = host_machine.system ()
|
||||
version = meson.project_version ()
|
||||
count = run_command ('git', 'rev-list', '--count', 'HEAD').stdout ().strip ()
|
||||
|
||||
compilerId = buildCompiler.get_id ()
|
||||
compilerVersion = buildCompiler.version ()
|
||||
cpp_id = cpp.get_id ()
|
||||
cpp_version = cpp.version ()
|
||||
|
||||
isOptimize = get_option ('buildtype') == 'release' or get_option ('buildtype') == 'debugoptimized'
|
||||
isVC = compilerId == 'msvc' or compilerId == 'intel-cl' or compilerId == 'clang-cl'
|
||||
isGCC = compilerId == 'gcc'
|
||||
isIntel = compilerId == 'intel' or compilerId == 'intel-cl'
|
||||
isCLang = compilerId == 'clang'
|
||||
isWindows = buildSystem == 'windows'
|
||||
isLinux = buildSystem == 'linux'
|
||||
isDarwin = buildSystem == 'darwin'
|
||||
optmize = get_option ('buildtype') == 'release' or get_option ('buildtype') == 'debugoptimized'
|
||||
|
||||
msvc = cpp_id == 'msvc' or cpp_id == 'clang-cl'
|
||||
gcc = cpp_id == 'gcc'
|
||||
clang = cpp_id == 'clang'
|
||||
|
||||
win32 = sys == 'windows'
|
||||
linux = sys == 'linux'
|
||||
mac = sys == 'darwin'
|
||||
|
||||
ldflags = []
|
||||
ccflags = []
|
||||
|
||||
cdata = configuration_data()
|
||||
|
||||
if isWindows
|
||||
cdata.set ('buildVersionWin', ','.join (buildVersion.split ('.')))
|
||||
if win32
|
||||
cdata.set ('version_win', ','.join (version.split ('.')))
|
||||
cdata.set ('machine', run_command ('hostname').stdout ().strip ())
|
||||
else
|
||||
cdata.set ('buildVersionWin', buildVersion)
|
||||
cdata.set ('version_win', version)
|
||||
cdata.set ('machine', run_command ('hostname', '-f').stdout ().strip ())
|
||||
endif
|
||||
|
||||
cdata.set ('commitHash', run_command ('git', 'rev-parse', '--short', 'HEAD').stdout ().strip ())
|
||||
cdata.set ('commitAuthor', run_command ('git', 'log', '--pretty="%ae"', '-1').stdout ().strip ())
|
||||
cdata.set ('hash', run_command ('git', 'rev-parse', '--short', 'HEAD').stdout ().strip ())
|
||||
cdata.set ('author', run_command ('git', 'log', '--pretty="%ae"', '-1').stdout ().strip ())
|
||||
|
||||
cdata.set ('commitCount', buildCount)
|
||||
cdata.set ('buildVersion', buildVersion)
|
||||
cdata.set ('buildMachine', run_command ('hostname', '-f').stdout ().strip ())
|
||||
cdata.set ('buildCompiler', compilerId + ' ' + compilerVersion)
|
||||
cdata.set ('count', count)
|
||||
cdata.set ('version', version)
|
||||
|
||||
cdata.set ('compiler', cpp_id + ' ' + cpp_version)
|
||||
|
||||
configure_file (input: 'inc/version.h.in', output: 'version.build.h', configuration: cdata)
|
||||
|
||||
ccflags += '-DVERSION_GENERATED'
|
||||
|
||||
if isCLang or isGCC or (isIntel and not isWindows)
|
||||
if clang or gcc
|
||||
ccflags += [
|
||||
'-m32',
|
||||
'-fno-threadsafe-statics',
|
||||
|
|
@ -78,36 +82,32 @@ if isCLang or isGCC or (isIntel and not isWindows)
|
|||
'-fno-rtti'
|
||||
]
|
||||
|
||||
if not isDarwin
|
||||
if not mac
|
||||
ccflags += [
|
||||
'-pedantic',
|
||||
]
|
||||
endif
|
||||
|
||||
if isOptimize
|
||||
ccflags += '-msse3'
|
||||
|
||||
if (isCLang or isGCC) and not isDarwin
|
||||
|
||||
if optmize
|
||||
if (clang or gcc) and not mac
|
||||
ccflags += [
|
||||
'-flto',
|
||||
'-fdata-sections',
|
||||
'-ffunction-sections'
|
||||
]
|
||||
|
||||
if isGCC
|
||||
if gcc
|
||||
ccflags += '-fgraphite-identity'
|
||||
ldflags += '-flto-partition=none'
|
||||
endif
|
||||
|
||||
ldflags += [
|
||||
'-flto',
|
||||
'-Wl,--version-script=../version_script.lds',
|
||||
'-Wl,--gc-sections'
|
||||
'-flto'
|
||||
]
|
||||
endif
|
||||
endif
|
||||
|
||||
if isLinux
|
||||
if linux
|
||||
ldflags += [
|
||||
'-m32',
|
||||
'-lm',
|
||||
|
|
@ -116,18 +116,10 @@ if isCLang or isGCC or (isIntel and not isWindows)
|
|||
endif
|
||||
endif
|
||||
|
||||
if isIntel and (isLinux or isDarwin)
|
||||
ldflags += [
|
||||
'-static-intel',
|
||||
'-no-intel-extensions'
|
||||
]
|
||||
endif
|
||||
|
||||
if isLinux or isDarwin
|
||||
if isDarwin
|
||||
if linux or mac or (win32 and (gcc or clang))
|
||||
if mac
|
||||
ccflags += '-mmacosx-version-min=10.9'
|
||||
ldflags += [
|
||||
'-dynamiclib',
|
||||
'-lstdc++',
|
||||
'-mmacosx-version-min=10.9'
|
||||
]
|
||||
|
|
@ -135,7 +127,7 @@ if isLinux or isDarwin
|
|||
ldflags += '-static-libgcc'
|
||||
endif
|
||||
|
||||
if not isOptimize
|
||||
if not optmize
|
||||
ccflags += [
|
||||
'-g3',
|
||||
'-ggdb',
|
||||
|
|
@ -144,7 +136,7 @@ if isLinux or isDarwin
|
|||
else
|
||||
ccflags += [
|
||||
'-mtune=generic',
|
||||
'-msse3',
|
||||
'-msse2',
|
||||
'-mfpmath=sse',
|
||||
'-fno-builtin',
|
||||
'-funroll-loops',
|
||||
|
|
@ -154,38 +146,24 @@ if isLinux or isDarwin
|
|||
'-fvisibility-inlines-hidden'
|
||||
]
|
||||
|
||||
if isIntel
|
||||
ccflags += [
|
||||
'-ipo',
|
||||
'-wd11076',
|
||||
'-wd11074'
|
||||
]
|
||||
if clang and not mac
|
||||
lld = find_program ('lld', required: false)
|
||||
|
||||
ldflags += [
|
||||
'-cxxlib-nostd',
|
||||
'-Wl,--no-undefined,-z,notext,--gc-sections',
|
||||
'-ipo'
|
||||
]
|
||||
elif isCLang and not isDarwin
|
||||
llvmLinker = find_program ('lld', required: false)
|
||||
|
||||
if llvmLinker.found() == true
|
||||
ldflags += '-fuse-ld=' + llvmLinker.path ().split ('/')[-1]
|
||||
endif
|
||||
|
||||
ldflags += [
|
||||
'-nostdlib++',
|
||||
'-Wunused-command-line-argument',
|
||||
'-Wl,-z,notext',
|
||||
'--no-undefined'
|
||||
]
|
||||
elif isGCC and not isDarwin
|
||||
ldflags += '-Wl,--no-undefined'
|
||||
if lld.found () == true
|
||||
ldflags += '-fuse-ld=' + lld.full_path ().split ('/')[-1]
|
||||
endif
|
||||
|
||||
ldflags += [
|
||||
'-nostdlib++',
|
||||
'-Wunused-command-line-argument'
|
||||
]
|
||||
elif gcc and not mac
|
||||
ldflags += '-Wl,--no-undefined'
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
if isWindows and (isVC or isIntel)
|
||||
if win32 and msvc
|
||||
ldflags += [
|
||||
'/MACHINE:X86',
|
||||
'user32.lib',
|
||||
|
|
@ -193,32 +171,34 @@ if isWindows and (isVC or isIntel)
|
|||
]
|
||||
|
||||
ccflags += [
|
||||
'/TP'
|
||||
'/TP',
|
||||
'/D _WIN32_WINNT=0x0501',
|
||||
'/D _USING_V110_SDK71_',
|
||||
'/Zc:threadSafeInit-'
|
||||
]
|
||||
|
||||
if isOptimize
|
||||
if optmize
|
||||
ccflags += [
|
||||
'/GL',
|
||||
'/arch:SSE2',
|
||||
'/GS-',
|
||||
'/Ob2',
|
||||
'/Oy',
|
||||
'/Oi'
|
||||
'/Oi',
|
||||
'/Ot',
|
||||
'/fp:precise',
|
||||
'/GF'
|
||||
]
|
||||
ldflags += '/LTCG'
|
||||
endif
|
||||
|
||||
elif isWindows and (isCLang or isGCC)
|
||||
if isCLang
|
||||
ldflags += '-Wl,/MACHINE:X86'
|
||||
else
|
||||
ldflags += [
|
||||
'-static-libgcc',
|
||||
'-Wl,--kill-at'
|
||||
]
|
||||
'/LTCG',
|
||||
'delayimp.lib',
|
||||
'/DELAYLOAD:user32.dll',
|
||||
'/SUBSYSTEM:WINDOWS,5.01',
|
||||
]
|
||||
endif
|
||||
|
||||
elif win32 and (clang or gcc)
|
||||
ldflags += [
|
||||
'-Wl,--kill-at',
|
||||
'-luser32',
|
||||
'-lws2_32'
|
||||
]
|
||||
|
|
@ -228,7 +208,6 @@ add_global_arguments (ccflags, language: 'cpp')
|
|||
add_global_link_arguments (ldflags, language: 'cpp')
|
||||
|
||||
sources = files (
|
||||
'src/android.cpp',
|
||||
'src/botlib.cpp',
|
||||
'src/chatlib.cpp',
|
||||
'src/combat.cpp',
|
||||
|
|
@ -245,10 +224,10 @@ sources = files (
|
|||
)
|
||||
|
||||
includes = include_directories ([
|
||||
'.', 'inc', 'ext',
|
||||
'.', 'inc', 'ext', 'ext/crlib'
|
||||
], is_system: true)
|
||||
|
||||
if isWindows and not isCLang
|
||||
if win32
|
||||
sources += import('windows').compile_resources (
|
||||
'vc/yapb.rc',
|
||||
include_directories: includes,
|
||||
|
|
@ -260,9 +239,8 @@ shared_library (
|
|||
meson.project_name (),
|
||||
sources,
|
||||
include_directories: includes,
|
||||
|
||||
gnu_symbol_visibility: 'hidden',
|
||||
name_prefix: '')
|
||||
|
||||
run_target ('package',
|
||||
command : ['python', meson.source_root() + '/package.py', '@0@.@1@'.format (buildVersion, buildCount)])
|
||||
command: ['python3', meson.project_source_root () + '/package.py', '@0@.@1@'.format (version, count)])
|
||||
326
package.py
326
package.py
|
|
@ -6,127 +6,223 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
import os, sys, subprocess
|
||||
from genericpath import isdir
|
||||
import os, sys, subprocess, base64
|
||||
import locale, urllib3
|
||||
import pathlib, shutil
|
||||
import zipfile, tarfile
|
||||
import datetime, calendar
|
||||
|
||||
from github import Github
|
||||
class CodeSign (object):
|
||||
def __init__(self, product, url, verify_signature=False):
|
||||
self.signing = True
|
||||
|
||||
self.ossl_path = "/usr/bin/osslsigncode"
|
||||
self.local_key = os.path.join (pathlib.Path ().absolute (), "key.pfx");
|
||||
|
||||
self.product = product
|
||||
self.url = url
|
||||
self.verify_signature = verify_signature
|
||||
|
||||
if not os.path.exists (self.ossl_path):
|
||||
self.signing = False
|
||||
|
||||
if not "CS_CERTIFICATE" in os.environ:
|
||||
self.signing = False
|
||||
|
||||
if not "CS_CERTIFICATE_PASSWORD" in os.environ:
|
||||
self.signing = False
|
||||
|
||||
if self.signing:
|
||||
self.password = os.environ.get ("CS_CERTIFICATE_PASSWORD")
|
||||
|
||||
encoded = os.environ.get ("CS_CERTIFICATE")
|
||||
|
||||
if len (encoded) < 64:
|
||||
print ('Damaged certificate. Signing disabled.')
|
||||
self.signing = False
|
||||
return
|
||||
|
||||
decoded = base64.b64decode (encoded)
|
||||
|
||||
with open (self.local_key, "wb") as key:
|
||||
key.write (decoded)
|
||||
|
||||
def has(self):
|
||||
return self.signing
|
||||
|
||||
def sign_file_inplace (self, filename):
|
||||
signed_filename = filename + ".signed"
|
||||
sign = []
|
||||
|
||||
sign.append (self.ossl_path)
|
||||
sign.append ("sign")
|
||||
sign.append ("-pkcs12")
|
||||
sign.append (self.local_key)
|
||||
sign.append ("-pass")
|
||||
sign.append (self.password)
|
||||
sign.append ("-n")
|
||||
sign.append (self.product)
|
||||
sign.append ("-i")
|
||||
sign.append (self.url)
|
||||
sign.append ("-h")
|
||||
sign.append ("sha256")
|
||||
sign.append ("-t")
|
||||
sign.append ("http://timestamp.sectigo.com")
|
||||
sign.append ("-in")
|
||||
sign.append (filename)
|
||||
sign.append ("-out")
|
||||
sign.append (signed_filename)
|
||||
|
||||
result = subprocess.run (sign, capture_output=True, text=True)
|
||||
|
||||
if result.returncode == 0:
|
||||
os.unlink (filename)
|
||||
shutil.move (signed_filename, filename)
|
||||
|
||||
print ("Signing result: {}".format (result.stdout))
|
||||
|
||||
if self.verify_signature:
|
||||
verify = []
|
||||
verify.append (self.ossl_path)
|
||||
verify.append ("verify")
|
||||
verify.append (filename)
|
||||
|
||||
verify = subprocess.run (verify, capture_output=True, text=True)
|
||||
print (verify.stdout)
|
||||
|
||||
else:
|
||||
print (result.stdout)
|
||||
|
||||
|
||||
class BotRelease (object):
|
||||
def __init__(self):
|
||||
print ("Initializing Packaging")
|
||||
|
||||
meson_src_root_env = "MESON_SOURCE_ROOT"
|
||||
|
||||
if meson_src_root_env in os.environ:
|
||||
os.chdir (os.environ.get (meson_src_root_env))
|
||||
|
||||
self.workDir = os.path.join (pathlib.Path ().absolute (), 'cfg')
|
||||
self.botDir = os.path.join (self.workDir, 'addons', 'yapb')
|
||||
self.distDir = os.path.join (pathlib.Path ().absolute (), 'dist');
|
||||
self.work_dir = os.path.join (pathlib.Path ().absolute (), "cfg")
|
||||
self.bot_dir = os.path.join (self.work_dir, "addons", "yapb")
|
||||
self.pkg_dir = os.path.join (pathlib.Path ().absolute (), "pkg")
|
||||
|
||||
if len (sys.argv) < 2:
|
||||
raise Exception('Missing required parameters.')
|
||||
raise Exception("Missing required parameters.")
|
||||
|
||||
self.version = sys.argv[1]
|
||||
self.artifacts = 'artifacts'
|
||||
|
||||
self.cs = CodeSign ("YaPB", "https://yapb.ru/")
|
||||
|
||||
if self.cs.has ():
|
||||
print ("Code Signing Enabled")
|
||||
else:
|
||||
print ("Code Signing Disabled")
|
||||
|
||||
os.makedirs (self.pkg_dir, exist_ok=True)
|
||||
|
||||
os.makedirs (self.distDir, exist_ok=True)
|
||||
self.pkg_win32 = os.path.join (self.pkg_dir, "yapb-{}-windows.zip".format (self.version))
|
||||
self.pkg_linux = os.path.join (self.pkg_dir, "yapb-{}-linux.tar.xz".format (self.version))
|
||||
self.pkg_macos = os.path.join (self.pkg_dir, "yapb-{}-macos.zip".format (self.version))
|
||||
|
||||
self.pkg_win32_sfx = self.pkg_win32.replace ("zip", "exe")
|
||||
self.pkg_win32_sfx_url = "https://github.com/yapb/setup/releases/latest/download/botsetup.exe"
|
||||
|
||||
self.outFileWin32 = os.path.join (self.distDir, "yapb-{}-windows.zip".format (self.version))
|
||||
self.outFileLinux = os.path.join (self.distDir, "yapb-{}-linux.tar.xz".format (self.version))
|
||||
self.outFileMacOS = os.path.join (self.distDir, "yapb-{}-macos.zip".format (self.version))
|
||||
|
||||
self.outFileWin32Setup = self.outFileWin32.replace ("zip", "exe")
|
||||
self.win32SetupUrl = "https://github.com/yapb/setup/releases/latest/download/botsetup.exe"
|
||||
|
||||
def makeDirs (self):
|
||||
def make_directories (self):
|
||||
dirs = [
|
||||
'bin',
|
||||
os.path.join ('data', 'pwf'),
|
||||
os.path.join ('data', 'train'),
|
||||
os.path.join ('data', 'graph'),
|
||||
os.path.join ('data', 'logs')
|
||||
"bin",
|
||||
os.path.join ("data", "pwf"),
|
||||
os.path.join ("data", "train"),
|
||||
os.path.join ("data", "graph"),
|
||||
os.path.join ("data", "logs")
|
||||
]
|
||||
|
||||
for dir in dirs:
|
||||
os.makedirs (os.path.join (self.botDir, dir), exist_ok=True)
|
||||
os.makedirs (os.path.join (self.bot_dir, dir), exist_ok=True)
|
||||
|
||||
def download (self, fromWhere, toFile):
|
||||
def http_pull (self, url, local_file):
|
||||
http = urllib3.PoolManager (10, headers = {"user-agent": "YaPB"})
|
||||
data = http.urlopen ('GET', fromWhere)
|
||||
data = http.urlopen ("GET", url)
|
||||
|
||||
with open (toFile, "wb") as file:
|
||||
with open (local_file, "wb") as file:
|
||||
file.write (data.data)
|
||||
|
||||
def getGraph (self, name):
|
||||
file = os.path.join (self.botDir, 'data', 'graph', "{}.graph".format (name))
|
||||
url = "http://graph.yapb.ru/graph/{}.graph".format (name);
|
||||
def get_graph_file (self, name):
|
||||
file = os.path.join (self.bot_dir, "data", "graph", "{}.graph".format (name))
|
||||
url = "http://graph.yapb.ru/graph/{}.graph".format (name)
|
||||
|
||||
if os.path.exists (file):
|
||||
return
|
||||
|
||||
self.download (url, file)
|
||||
self.http_pull (url, file)
|
||||
|
||||
def getGraphs (self):
|
||||
def get_default_graphs (self):
|
||||
print ("Downloading graphs: ")
|
||||
|
||||
files = ['as_oilrig', 'cs_747', 'cs_estate', 'cs_assault', 'cs_office',
|
||||
'cs_italy', 'cs_havana', 'cs_siege', 'cs_backalley', 'cs_militia',
|
||||
'cs_downed_cz', 'cs_havana_cz', 'cs_italy_cz', 'cs_militia_cz',
|
||||
'cs_office_cz', 'de_airstrip_cz', 'de_aztec_cz', 'de_cbble_cz',
|
||||
'de_chateau_cz', 'de_corruption_cz', 'de_dust_cz', 'de_dust2_cz',
|
||||
'de_fastline_cz', 'de_inferno_cz', 'de_piranesi_cz', 'de_prodigy_cz',
|
||||
'de_sienna_cz', 'de_stadium_cz', 'de_tides_cz', 'de_torn_cz',
|
||||
'de_truth_cz', 'de_vostok_cz', 'de_inferno', 'de_aztec', 'de_dust',
|
||||
'de_dust2', 'de_torn', 'de_storm', 'de_airstrip', 'de_piranesi',
|
||||
'de_prodigy', 'de_chateau', 'de_cbble', 'de_nuke', 'de_survivor',
|
||||
'de_vertigo', 'de_train']
|
||||
default_list = "default.graph.txt"
|
||||
self.http_pull ("http://graph.yapb.ru/DEFAULT.txt", default_list)
|
||||
|
||||
with open (default_list) as file:
|
||||
files = [line.rstrip () for line in file.readlines ()]
|
||||
|
||||
for file in files:
|
||||
print (" " + file)
|
||||
|
||||
self.getGraph (file)
|
||||
self.get_graph_file (file)
|
||||
|
||||
def unlinkBinaries (self):
|
||||
libs = ['yapb.so', 'yapb.dll', 'yapb.dylib']
|
||||
def unlink_binaries (self):
|
||||
libs = ["yapb.so", "yapb.dll", "yapb.dylib"]
|
||||
|
||||
for lib in libs:
|
||||
path = os.path.join (self.botDir, 'bin', lib)
|
||||
path = os.path.join (self.bot_dir, "bin", lib)
|
||||
|
||||
if os.path.exists (path):
|
||||
os.remove (path)
|
||||
|
||||
def copyBinary (self, path):
|
||||
shutil.copy (path, os.path.join (self.botDir, 'bin'))
|
||||
|
||||
def sign_binary (self, binary):
|
||||
if self.cs.has () and (binary.endswith ("dll") or binary.endswith ("exe")):
|
||||
print ("Signing {}".format (binary))
|
||||
self.cs.sign_file_inplace (binary)
|
||||
|
||||
def copy_binary (self, binary):
|
||||
dest_path = os.path.join (self.bot_dir, "bin", os.path.basename (binary))
|
||||
shutil.copy (binary, dest_path)
|
||||
|
||||
def zipDir (self, path, handle):
|
||||
self.sign_binary (dest_path)
|
||||
|
||||
def compress_directory (self, path, handle):
|
||||
length = len (path) + 1
|
||||
emptyDirs = []
|
||||
empty_dirs = []
|
||||
|
||||
for root, dirs, files in os.walk (path):
|
||||
emptyDirs.extend ([dir for dir in dirs if os.listdir (os.path.join (root, dir)) == []])
|
||||
empty_dirs.extend ([dir for dir in dirs if os.listdir (os.path.join (root, dir)) == []])
|
||||
|
||||
for file in files:
|
||||
filePath = os.path.join (root, file)
|
||||
handle.write (filePath, filePath[length:])
|
||||
file_path = os.path.join (root, file)
|
||||
handle.write (file_path, file_path[length:])
|
||||
|
||||
for dir in emptyDirs:
|
||||
dirPath = os.path.join (root, dir)
|
||||
for dir in empty_dirs:
|
||||
dir_path = os.path.join (root, dir)
|
||||
|
||||
zif = zipfile.ZipInfo (dirPath[length:] + "/")
|
||||
zif = zipfile.ZipInfo (dir_path[length:] + "/")
|
||||
handle.writestr (zif, "")
|
||||
|
||||
emptyDirs = []
|
||||
empty_dirs = []
|
||||
|
||||
def generateZip (self, dir):
|
||||
zipFile = zipfile.ZipFile (dir, 'w', zipfile.ZIP_DEFLATED)
|
||||
zipFile.comment = bytes (self.version, encoding = "ascii")
|
||||
def create_zip (self, dir):
|
||||
zf = zipfile.ZipFile (dir, "w", zipfile.ZIP_DEFLATED, compresslevel=9)
|
||||
zf.comment = bytes (self.version, encoding = "ascii")
|
||||
|
||||
self.zipDir (self.workDir, zipFile)
|
||||
zipFile.close ()
|
||||
self.compress_directory (self.work_dir, zf)
|
||||
zf.close ()
|
||||
|
||||
def convertZipToTXZ (self, zip, txz):
|
||||
def convert_zip_txz (self, zip, txz):
|
||||
timeshift = int ((datetime.datetime.now () - datetime.datetime.utcnow ()).total_seconds ())
|
||||
|
||||
with zipfile.ZipFile (zip) as zipf:
|
||||
with tarfile.open (txz, 'w:xz') as tarf:
|
||||
with tarfile.open (txz, "w:xz") as tarf:
|
||||
for zif in zipf.infolist ():
|
||||
tif = tarfile.TarInfo (name = zif.filename)
|
||||
tif.size = zif.file_size
|
||||
|
|
@ -135,91 +231,67 @@ class BotRelease (object):
|
|||
tarf.addfile (tarinfo = tif, fileobj = zipf.open (zif.filename))
|
||||
|
||||
os.remove (zip)
|
||||
|
||||
def generateWin32 (self):
|
||||
print ("Generating Win32 ZIP")
|
||||
|
||||
binary = os.path.join ('build_x86_win32', 'yapb.dll')
|
||||
|
||||
def install_binary (self, ext):
|
||||
lib = "yapb.{}".format (ext)
|
||||
binary = os.path.join (self.artifacts, lib)
|
||||
|
||||
if os.path.isdir (binary):
|
||||
binary = os.path.join (binary, lib)
|
||||
|
||||
if not os.path.exists (binary):
|
||||
return
|
||||
print ("Packaging failed for {}. Skipping...", lib)
|
||||
return False
|
||||
|
||||
self.unlinkBinaries ()
|
||||
self.unlink_binaries ()
|
||||
self.copy_binary (binary)
|
||||
|
||||
return True
|
||||
|
||||
self.copyBinary (binary)
|
||||
self.generateZip (self.outFileWin32)
|
||||
def create_pkg_win32 (self):
|
||||
print ("Generating Win32 ZIP")
|
||||
|
||||
self.download (self.win32SetupUrl, "botsetup.exe")
|
||||
if not self.install_binary ("dll"):
|
||||
return
|
||||
|
||||
self.create_zip (self.pkg_win32)
|
||||
self.http_pull (self.pkg_win32_sfx_url, "botsetup.exe")
|
||||
|
||||
print ("Generating Win32 EXE")
|
||||
|
||||
with open ("botsetup.exe", "rb") as sfx, open (self.outFileWin32, "rb") as zip, open (self.outFileWin32Setup, "wb") as exe:
|
||||
with open ("botsetup.exe", "rb") as sfx, open (self.pkg_win32, "rb") as zip, open (self.pkg_win32_sfx, "wb") as exe:
|
||||
exe.write (sfx.read ())
|
||||
exe.write (zip.read ())
|
||||
|
||||
self.sign_binary (self.pkg_win32_sfx)
|
||||
|
||||
def generateLinux (self):
|
||||
def create_pkg_linux (self):
|
||||
print ("Generating Linux TXZ")
|
||||
|
||||
binary = os.path.join ('build_x86_linux', 'yapb.so');
|
||||
|
||||
if not os.path.exists (binary):
|
||||
if not self.install_binary ("so"):
|
||||
return
|
||||
|
||||
self.unlinkBinaries ()
|
||||
self.copyBinary (binary)
|
||||
|
||||
tmpFile = "tmp.zip"
|
||||
tmp_file = "tmp.zip"
|
||||
|
||||
self.generateZip (tmpFile)
|
||||
self.convertZipToTXZ (tmpFile, self.outFileLinux)
|
||||
|
||||
def generateMac (self):
|
||||
self.create_zip (tmp_file)
|
||||
self.convert_zip_txz (tmp_file, self.pkg_linux)
|
||||
|
||||
def create_pkg_macos (self):
|
||||
print ("Generating macOS ZIP")
|
||||
|
||||
binary = os.path.join ('build_x86_macos', 'yapb.dylib')
|
||||
|
||||
if not os.path.exists (binary):
|
||||
if not self.install_binary ("dylib"):
|
||||
return
|
||||
|
||||
self.unlinkBinaries ()
|
||||
self.copyBinary (binary)
|
||||
|
||||
self.generateZip (self.outFileMacOS)
|
||||
self.create_zip (self.pkg_macos)
|
||||
|
||||
def generate (self):
|
||||
self.generateWin32 ()
|
||||
self.generateLinux ()
|
||||
self.generateMac ()
|
||||
|
||||
def createRelease (self, repository, version):
|
||||
print ("Creating Github Tag")
|
||||
|
||||
releases = [self.outFileLinux, self.outFileWin32, self.outFileMacOS, self.outFileWin32Setup]
|
||||
|
||||
for release in releases:
|
||||
if not os.path.exists (release):
|
||||
return
|
||||
|
||||
releaseName = "YaPB " + version
|
||||
releaseMessage = repository.get_commits()[0].commit.message
|
||||
releaseSha = repository.get_commits()[0].sha;
|
||||
def create_pkgs (self):
|
||||
self.create_pkg_linux ()
|
||||
self.create_pkg_win32 ()
|
||||
self.create_pkg_macos ()
|
||||
|
||||
ghr = repository.create_git_tag_and_release (tag = version, tag_message = version, release_name = releaseName, release_message = releaseMessage, type='commit', object = releaseSha, draft = False)
|
||||
|
||||
print ("Uploading packages to Github")
|
||||
|
||||
for release in releases:
|
||||
ghr.upload_asset( path = release, label = os.path.basename (release))
|
||||
|
||||
def uploadGithub (self):
|
||||
gh = Github (os.environ["GITHUB_TOKEN"])
|
||||
repo = gh.get_repo ("yapb/yapb")
|
||||
|
||||
self.createRelease (repo, self.version)
|
||||
|
||||
release = BotRelease ()
|
||||
|
||||
release.makeDirs ()
|
||||
release.getGraphs ()
|
||||
release.generate ()
|
||||
release.uploadGithub ()
|
||||
release.make_directories ()
|
||||
release.get_default_graphs ()
|
||||
release.create_pkgs ()
|
||||
|
||||
|
|
|
|||
|
|
@ -354,7 +354,7 @@ CR_EXPORT int GetEntityAPI (gamefuncs_t *table, int) {
|
|||
dllapi.pfnServerDeactivate ();
|
||||
|
||||
// refill export table
|
||||
ents.clearExportTable ();
|
||||
ents.flush ();
|
||||
};
|
||||
|
||||
table->pfnStartFrame = [] () {
|
||||
|
|
@ -500,7 +500,7 @@ CR_LINKAGE_C int GetEngineFunctions (enginefuncs_t *table, int *) {
|
|||
plat.bzero (table, sizeof (enginefuncs_t));
|
||||
}
|
||||
|
||||
if (ents.isWorkaroundNeeded () && !game.is (GameFlags::Metamod)) {
|
||||
if (ents.needsBypass () && !game.is (GameFlags::Metamod)) {
|
||||
table->pfnCreateNamedEntity = [] (int classname) -> edict_t * {
|
||||
|
||||
if (ents.isPaused ()) {
|
||||
|
|
@ -987,7 +987,7 @@ DLSYM_RETURN EntityLinkage::lookup (SharedLibrary::Handle module, const char *fu
|
|||
return reinterpret_cast <DLSYM_RETURN> (m_dlsym (static_cast <DLSYM_HANDLE> (handle), function));
|
||||
};
|
||||
|
||||
if (ents.isWorkaroundNeeded () && !strcmp (function, "CreateInterface")) {
|
||||
if (ents.needsBypass () && !strcmp (function, "CreateInterface")) {
|
||||
ents.setPaused (true);
|
||||
auto ret = resolve (module);
|
||||
|
||||
|
|
@ -1025,8 +1025,12 @@ void EntityLinkage::initialize () {
|
|||
}
|
||||
|
||||
m_dlsym.initialize ("kernel32.dll", "GetProcAddress", DLSYM_FUNCTION);
|
||||
m_dlsym.install (reinterpret_cast <void *> (EntityLinkage::replacement), true);
|
||||
m_dlsym.install (reinterpret_cast <void *> (EntityLinkage::lookupHandler), true);
|
||||
|
||||
if (needsBypass ()) {
|
||||
m_dlclose.initialize ("kernel32.dll", "FreeLibrary", DLCLOSE_FUNCTION);
|
||||
m_dlclose.install (reinterpret_cast <void *> (EntityLinkage::closeHandler), true);
|
||||
}
|
||||
m_self.locate (&engfuncs);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
YAPB_ABI_1.0 {
|
||||
global:
|
||||
Meta_*;
|
||||
GiveFnptrsToDll;
|
||||
GetBotAPI;
|
||||
GetEntityAPI;
|
||||
GetNewDLLFunctions;
|
||||
*;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue