diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 000000000..a54b0628e
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,276 @@
+name: C/C++ CI
+
+on:
+ push:
+ branches: [master]
+ paths-ignore:
+ - '**.md'
+
+ pull_request:
+ types: [opened, reopened, synchronize]
+ release:
+ types: [published]
+
+jobs:
+ windows:
+ name: 'Windows'
+ runs-on: windows-latest
+
+ env:
+ solution: 'msvc/ReGameDLL.sln'
+ buildPlatform: 'Win32'
+ buildRelease: 'Release'
+ buildReleasePlay: 'Release Play'
+ buildTests: 'Tests'
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+
+ - name: Setup Nuget
+ uses: nuget/setup-nuget@v1
+ with:
+ nuget-api-key: ${{ secrets.NuGetAPIKey }}
+ nuget-version: '5.x'
+
+ - run: nuget restore '${{ env.solution }}'
+
+ - name: Setup MSBuild
+ uses: microsoft/setup-msbuild@v1.0.2
+ with:
+ vs-version: '16.8'
+
+ - name: Build and Run unittests
+ run: |
+ msbuild ${{ env.solution }} -p:Configuration="${{ env.buildTests }}" /t:Clean,Build /p:Platform=${{ env.buildPlatform }} /p:PlatformToolset=v140_xp /p:XPDeprecationWarning=false
+ .\"msvc\Tests\mp.exe"
+ If ($LASTEXITCODE -ne 0 -And
+ $LASTEXITCODE -ne 3)
+ {[Environment]::Exit(1)}
+ shell: "pwsh"
+
+ - name: Build
+ run: |
+ msbuild ${{ env.solution }} -p:Configuration="${{ env.buildRelease }}" /t:Clean,Build /p:Platform=${{ env.buildPlatform }} /p:PlatformToolset=v140_xp /p:XPDeprecationWarning=false
+ msbuild ${{ env.solution }} -p:Configuration="${{ env.buildReleasePlay }}" /t:Clean,Build /p:Platform=${{ env.buildPlatform }} /p:PlatformToolset=v140_xp /p:XPDeprecationWarning=false
+
+ - name: Move files
+ run: |
+ mkdir publish\debug
+ mkdir publish\tests
+ mkdir publish\bin\win32\cstrike\dlls
+ move "msvc\${{ env.buildReleasePlay }}\mp.dll" publish\tests\mp.dll
+ move msvc\${{ env.buildRelease }}\mp.dll publish\bin\win32\cstrike\dlls\mp.dll
+ move msvc\${{ env.buildRelease }}\mp.pdb publish\debug\mp.pdb
+
+ - name: Deploy artifacts
+ uses: actions/upload-artifact@v2
+ with:
+ name: win32
+ path: publish/*
+
+ testdemos:
+ name: 'Test demos'
+ runs-on: ubuntu-latest
+ container: s1lentq/testdemos:latest
+ needs: [windows]
+
+ env:
+ WINEDEBUG: -all
+ WINEDLLOVERRIDES: mshtml=
+
+ defaults:
+ run:
+ shell: bash
+ working-directory: ../../../opt/HLDS
+
+ steps:
+ - name: Deploying windows artifacts
+ uses: actions/download-artifact@v2
+ with:
+ name: win32
+
+ - name: Play demos
+ run: |
+ chown root ~
+ cp -r deps/regamedll/* .
+ mv $GITHUB_WORKSPACE/tests/mp.dll cstrike/dlls/mp.dll
+
+ descs=(
+ "CS: Testing jumping, scenarios, shooting etc"
+ )
+
+ demos=(
+ "cstrike-basic-1"
+ )
+
+ retVal=0
+ for i in "${!demos[@]}"; do
+ params=$(cat "testdemos/${demos[i]}.params")
+
+ echo -e "\e[1m[$((i + 1))/${#demos[@]}] \e[1;36m${descs[i]} testing...\e[0m"
+ echo -e " - \e[0;33mParameters $params\e[0m"
+
+ wine hlds.exe --rehlds-enable-all-hooks --rehlds-test-play "testdemos/${demos[i]}.bin" $params &> result.log || retVal=$?
+
+ if [ $retVal -ne 777 ] && [ $retVal -ne 9 ]; then
+ # Print with catchy messages
+ while read line; do
+ echo -e " \e[0;33m$line"
+ done <<< $(cat result.log | sed '0,/demo failed/I!d;/wine:/d;/./,$!d')
+
+ echo " 🔸 🔸 🔸 🔸 🔸 🔸 🔸 🔸 🔸 🔸"
+ while read line; do
+ echo -e " \e[1;31m$line";
+ done < rehlds_demo_error.txt
+ echo -e " \e[30;41mExit code: $retVal\e[0m"
+ echo -e "\e[1m[$((i + 1))/${#demos[@]}] \e[1;36m${descs[i]} testing...\e[1;31m Failed ❌"
+ exit 6 # Test demo failed
+ else
+ # Print result HLDS console
+ while read line; do
+ echo -e " \e[0;33m$line"
+ done <<< $(cat result.log | sed '/wine:/d;/./,$!d')
+ echo -e " \e[30;43mExit code: $retVal\e[0m"
+ echo -e "\e[1m[$((i + 1))/${#demos[@]}] \e[1;36m${descs[i]} testing...\e[1;32m Succeed ✔"
+ fi
+ done
+
+ linux:
+ name: 'Linux'
+ runs-on: ubuntu-latest
+ container: s1lentq/linux86buildtools:latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+ submodules: true
+
+ - name: Build and Run unittests
+ run: |
+ rm -rf build && CC=icc CXX=icpc cmake -DCMAKE_BUILD_TYPE=Unittests -B build && cmake --build build -j8
+ retVal=0
+ ./build/regamedll/cs 2> /dev/null > result.log || retVal=$?
+ while read line; do
+ if [[ ${line} == *"Warning in test"* ]] ; then
+ echo -e "\e[2;38m$line"
+ elif [[ ${line} == *"Failure in test"* ]] ; then
+ echo -e "\e[1;31m$line"
+ else
+ echo -e "\e[0;33m$line"
+ fi
+ done <<< $(cat result.log)
+
+ if [ $retVal -ne 0 ] && [ $retVal -ne 3 ]; then
+ echo -e "\e[30;41mExit code: $retVal\e[0m"
+ exit 1 # Unittest failed
+ else
+ echo -e "\e[30;43mExit code: $retVal\e[0m"
+ fi
+ shell: bash
+
+ - name: Build using Intel C++ Compiler 19.0
+ run: |
+ rm -rf build-icc && CC=icc CXX=icpc cmake -B build-icc && cmake --build build-icc -j8
+
+ - name: Build using GCC Compiler 9.3
+ run: |
+ rm -rf build-gcc && CC=gcc CXX=g++ cmake -B build-gcc && cmake --build build-gcc -j8
+
+ - name: Prepare CSSDK
+ run: |
+ mkdir -p publish/cssdk
+ rsync -a regamedll/extra/cssdk/ publish/cssdk/ --exclude=.git --exclude=LICENSE --exclude=README.md
+
+ - name: Move files
+ run: |
+ mkdir -p publish/bin/linux32/cstrike/dlls
+ mv build-icc/regamedll/cs.so publish/bin/linux32/cstrike/dlls/cs.so
+ mv build-gcc/regamedll/cs.so publish/cs-gcc.so
+ mv regamedll/version/appversion.h publish/appversion.h
+
+ - name: Run GLIBC/ABI version compat test
+ run: |
+ binaries=(
+ "publish/bin/linux32/cstrike/dlls/cs.so"
+ "publish/cs-gcc.so"
+ )
+ bash ./regamedll/version/glibc_test.sh ${binaries[@]}
+ if [[ $? -ne 0 ]]; then
+ exit 1 # Assertion failed
+ fi
+ shell: bash
+
+ - name: Deploy artifacts
+ uses: actions/upload-artifact@v2
+ id: upload-job
+ with:
+ name: linux32
+ path: publish/*
+
+ - name: Cleanup temporary artifacts
+ if: success() && steps.upload-job.outcome == 'success'
+ run: |
+ rm -rf cssdk
+ rm -f appversion.h
+
+ publish:
+ name: 'Publish'
+ runs-on: ubuntu-latest
+ needs: [windows, testdemos, linux]
+
+ steps:
+ - name: Deploying linux artifacts
+ uses: actions/download-artifact@v2
+ with:
+ name: linux32
+
+ - name: Deploying windows artifacts
+ uses: actions/download-artifact@v2
+ with:
+ name: win32
+
+ - name: Reading appversion.h
+ run: |
+ if [ -e appversion.h ]; then
+ APP_VERSION=$(cat appversion.h | grep -wi '#define APP_VERSION_STRD' | sed -e 's/#define APP_VERSION_STRD[ \t\r\n\v\f]\+\(.*\)/\1/i' -e 's/\r//g')
+ if [ $? -ne 0 ]; then
+ APP_VERSION=""
+ else
+ # Remove quotes
+ APP_VERSION=$(echo $APP_VERSION | xargs)
+ echo "APP_VERSION=${APP_VERSION}" >> $GITHUB_ENV
+ fi
+ fi
+ rm -f appversion.h
+
+ - name: Packaging bin/dbg
+ id: packaging-job
+ if: |
+ github.event_name == 'release' &&
+ github.event.action == 'published' &&
+ startsWith(github.ref, 'refs/tags/')
+ run: |
+ 7z a -tzip regamedll-bin-${{ env.APP_VERSION }}.zip bin/ cssdk/
+
+ - name: Publish artifacts
+ uses: softprops/action-gh-release@v1
+ id: publish-job
+ if: |
+ startsWith(github.ref, 'refs/tags/') &&
+ steps.packaging-job.outcome == 'success'
+ with:
+ files: |
+ *.zip
+ env:
+ GITHUB_TOKEN: ${{ secrets.API_TOKEN }}
+
+ - name: Cleanup temporary artifacts
+ if: success() && steps.publish-job.outcome == 'success'
+ run: |
+ rm -rf bin debug cssdk
+ rm -f *.zip appversion.h
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 000000000..5fe6d8874
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "regamedll/extra/cssdk"]
+ path = regamedll/extra/cssdk
+ url = https://github.com/s1lentq/CSSDK.git
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 000000000..e8bfc73d9
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,12 @@
+cmake_minimum_required(VERSION 3.1)
+project(regamedll CXX)
+
+if (WIN32)
+ message(FATAL_ERROR "CMakeLists.txt Windows platform isn't supported yet. Use msvc/ReGameDLL.sln instead it!")
+endif()
+
+add_custom_target(appversion DEPENDS
+ COMMAND "${PROJECT_SOURCE_DIR}/regamedll/version/appversion.sh" "${PROJECT_SOURCE_DIR}"
+)
+
+add_subdirectory(regamedll)
diff --git a/README.md b/README.md
index 37f44c15f..11f3b0a13 100644
--- a/README.md
+++ b/README.md
@@ -105,72 +105,81 @@ Archive's bin directory contains 2 subdirectories, 'bugfixed' and 'pure'
* Enter `-bots` option at the command line HLDS
## Build instructions
-There are several software requirements for building Regamedll_CS:
-
-- Java Development Kit (JDK) 7+ (http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
-- For Windows: Visual Studio 2015 and later
-- For Linux: GCC/Clang/Intel C++ Compiler 15 and later
-
-
### Checking requirements
-#### JDK version
-Windows> %JAVA_HOME%\bin\javac -version
-javac 1.8.0_25
+There are several software requirements for building ReGameDLL_CS:
+
+#### Windows
+
+Visual Studio 2013 and later
-Linux
-$ javac -version
-javac 1.7.0_65
+#### Linux
+
+git >= 1.8.5
+cmake >= 3.10
+GCC >= 4.9.2 (Optional)
+ICC >= 15.0.1 20141023 (Optional)
+LLVM (Clang) >= 6.0 (Optional)
-#### Visual Studio
-Help -> About
+### Building
-#### ICC
-$ icc --version
-icc (ICC) 15.0.1 20141023
-
+#### Windows
+Use `Visual Studio` to build, open `msvc/ReGameDLL.sln` and just select from the solution configurations list `Release` or `Debug`
-### Building and run unit tests using gradle
-#### On Windows:
-gradlew --max-workers=1 clean buildRelease
-* For faster building without unit tests use this:exclamation:
-gradlew --max-workers=1 clean buildFixes
+#### Linux
-#### On Linux (ICC):
-./gradlew --max-workers=1 clean buildRelease
+* Optional options using `build.sh --compiler=[gcc] --jobs=[4]` (without square brackets)
+
+-c=|--compiler=[icc|gcc|clang] - Select preferred C/C++ compiler to build
+-j=|--jobs=[N] - Specifies the number of jobs (commands) to run simultaneously (For faster building)
+
-* For faster building without unit tests use this:exclamation:
-./gradlew --max-workers=1 clean buildFixes
+* Optional definitions using `build.sh -D[option]=[ON or OFF]` (without square brackets)
+
+DEBUG - Enables debugging mode
+USE_STATIC_LIBSTDC - Enables static linking library libstdc++
+
-#### On Linux (Clang):
-./gradlew --max-workers=1 clean -PuseClang buildRelease
+
./gradlew --max-workers=1 clean -PuseClang buildFixes
+
+LLVM (Clang):
+./build.sh --compiler=clang
+
-#### On Linux (GCC):
-./gradlew --max-workers=1 clean -PuseGcc buildRelease
+
+GCC:
+./build.sh --compiler=gcc
+
+
-* For faster building without unit tests use this:exclamation:
-./gradlew --max-workers=1 clean -PuseGcc buildFixes
+##### Checking build environment (Debian / Ubuntu)
-Compiled binaries will be placed in the build/binaries/ directory
+
+Click to expand
-### Simplified building using CMake 3.1 and later
-#### On Windows:
-Open solution msvc\ReGameDLL.sln and build it
+* Installing required packages
+
+sudo dpkg --add-architecture i386
+sudo apt-get update
+sudo apt-get install -y gcc-multilib g++-multilib
+sudo apt-get install -y build-essential
+sudo apt-get install -y libc6-dev libc6-dev-i386
+
-#### On Linux:
-* Run script `regamedll/compile.sh`
-* Options using `regamedll/compile.sh -D[option]=[ON or OFF]` (without square brackets)
+* Select the preferred C/C++ Compiler installation
-DEBUG - Enables debugging mode
-USE_INTEL_COMPILER - Switch main compiler to ICC
-USE_CLANG_COMPILER - Switch main compiler to Clang
-USE_STATIC_LIBSTDC - Enables static linking library libstdc++
+1) sudo apt-get install -y gcc g++
+2) sudo apt-get install -y clang
+
+
### Credits
Thanks to the project [ReHLDS](https://github.com/dreamstalker/rehlds) ( ReGameDLL_CS was created on the basis of ReHLDS )
diff --git a/build.sh b/build.sh
new file mode 100755
index 000000000..9b49a8dac
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+CC=gcc
+CXX=g++
+
+n=0
+args=()
+for i in "$@"
+do
+case $i in
+ -j=*|--jobs=*)
+ jobs="-j${i#*=}"
+ shift
+ ;;
+ -c=*|--compiler=*)
+ C="${i#*=}"
+ shift
+ ;;
+ *)
+ args[$n]="$i"
+ ((++n))
+ ;;
+esac
+done
+
+case "$C" in
+ ("intel"|"icc") CC=icc CXX=icpc ;;
+ ("gcc"|"g++") CC=gcc CXX=g++ ;;
+ ("clang|llvm") CC=clang CXX=clang++ ;;
+ *)
+ ;;
+esac
+
+rm -rf build
+mkdir build
+pushd build &> /dev/null
+CC=$CC CXX=$CXX cmake ${args[@]} ..
+make ${jobs}
+popd > /dev/null
diff --git a/dep/cppunitlite/CMakeLists.txt b/dep/cppunitlite/CMakeLists.txt
new file mode 100644
index 000000000..10047e7eb
--- /dev/null
+++ b/dep/cppunitlite/CMakeLists.txt
@@ -0,0 +1,25 @@
+cmake_minimum_required(VERSION 3.1)
+project(cppunitlite CXX)
+
+add_library(cppunitlite STATIC)
+
+target_sources(cppunitlite PRIVATE
+ src/Test.cpp
+ src/TestResult.cpp
+ src/TestRegistry.cpp
+ src/Assertions.cpp
+ src/MainAdapter.cpp
+)
+
+target_include_directories(cppunitlite PRIVATE
+ "${PROJECT_SOURCE_DIR}/src"
+ "${PROJECT_SOURCE_DIR}/include"
+)
+
+target_compile_definitions(cppunitlite PRIVATE
+ _GLIBCXX_USE_CXX11_ABI=0
+)
+
+target_compile_options(cppunitlite PRIVATE
+ -m32
+)
diff --git a/regamedll/CMakeLists.txt b/regamedll/CMakeLists.txt
index c357185bb..3bee15750 100644
--- a/regamedll/CMakeLists.txt
+++ b/regamedll/CMakeLists.txt
@@ -1,70 +1,105 @@
+#----------------------------------------
+# 1. Preparing build:
+# rm -rf build
+# mkdir build && cd build
+#
+# 2. Select compiler and build it
+# - Compile with Clang:
+# CC="clang" CXX="clang++" cmake ..
+# make
+#
+# - Compile with Intel C++ Compiler:
+# CC="icc" CXX="icpc" cmake ..
+# make
+#
+# - Compile with GCC Compiler:
+# cmake ..
+# make
+#----------------------------------------
+
cmake_minimum_required(VERSION 3.1)
project(regamedll CXX)
-option(DEBUG "Build debug application." OFF)
-option(USE_INTEL_COMPILER "Use the Intel compiler." OFF)
-option(USE_CLANG_COMPILER "Use the Clang compiler." OFF)
+option(DEBUG "Build with debug information." OFF)
option(USE_STATIC_LIBSTDC "Enables static linking libstdc++." OFF)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
-if (USE_INTEL_COMPILER)
- set(CMAKE_C_COMPILER "/opt/intel/bin/icc")
- set(CMAKE_CXX_COMPILER "/opt/intel/bin/icpc")
-elseif (USE_CLANG_COMPILER)
- set(CMAKE_C_COMPILER "/usr/bin/clang")
- set(CMAKE_CXX_COMPILER "/usr/bin/clang++")
-endif()
+# Avoid -rdynamic -fPIC options
+set(CMAKE_SHARED_LIBRARY_CXX_FLAGS "")
+set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
+set(COMPILE_FLAGS "-m32 -U_FORTIFY_SOURCE")
+set(LINK_FLAGS "-m32 -s")
-if (USE_INTEL_COMPILER OR USE_CLANG_COMPILER)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fasm-blocks")
-endif()
+set(COMPILE_FLAGS "${COMPILE_FLAGS} -Wall -fno-exceptions -fno-builtin -Wno-unknown-pragmas")
+
+# Remove noxref code and data
+set(COMPILE_FLAGS "${COMPILE_FLAGS} -ffunction-sections -fdata-sections")
if (DEBUG)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3 -ggdb -O3 -Wall -ffunction-sections -fdata-sections")
+ set(COMPILE_FLAGS "${COMPILE_FLAGS} -g3 -O3 -ggdb")
else()
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g0 -O3 -fno-rtti -ffunction-sections -fdata-sections")
+ set(COMPILE_FLAGS "${COMPILE_FLAGS} -g0 -O3 -fno-stack-protector")
endif()
-if (USE_INTEL_COMPILER)
- set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-intel -no-intel-extensions")
+# Check Intel C++ compiler
+if ("$ENV{CXX}" MATCHES "icpc")
+ # -fp-model=precise
+ # ICC uses -fp-model fast=1 by default for more aggressive optimizations on floating-point calculations
+ # https://software.intel.com/content/www/us/en/develop/documentation/cpp-compiler-developer-guide-and-reference/top/compiler-reference/compiler-options/compiler-option-details/floating-point-options/fp-model-fp.html#fp-model-fp_GUID-99936BBA-1508-4E9F-AC09-FA98613CE2F5
+ set(COMPILE_FLAGS "${COMPILE_FLAGS} \
+ -fp-model=precise\
+ -fasm-blocks\
+ -Qoption,cpp,--treat_func_as_string_literal_cpp")
+
+ set(LINK_FLAGS "${LINK_FLAGS} -static-intel -no-intel-extensions")
+
+ if (NOT DEBUG)
+ set(COMPILE_FLAGS "${COMPILE_FLAGS} -ipo")
+ set(LINK_FLAGS "${LINK_FLAGS} -ipo")
+ endif()
else()
- ## Produce code optimized for the most common IA32/AMD64/EM64T processors.
- ## As new processors are deployed in the marketplace, the behavior of this option will change.
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}\
+ # Produce code optimized for the most common IA32/AMD64/EM64T processors.
+ # As new processors are deployed in the marketplace, the behavior of this option will change.
+ set(COMPILE_FLAGS "${COMPILE_FLAGS} \
-mtune=generic -msse3\
- -Wno-write-strings -Wno-invalid-offsetof\
- -Wno-unused-variable -Wno-unused-function\
- -Wno-unused-result -Wno-invalid-offsetof\
- -fpermissive -Wno-switch -Wno-enum-compare\
- -Wno-unknown-pragmas -Wno-unused-value")
-
- if (USE_CLANG_COMPILER)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}\
+ -fpermissive -fno-sized-deallocation\
+ -Wno-delete-non-virtual-dtor -Wno-invalid-offsetof\
+ -Wno-unused-variable -Wno-unused-value -Wno-unused-result -Wno-unused-function\
+ -Wno-write-strings -Wno-switch -Wno-enum-compare\
+ -Wno-sign-compare -Wno-format -Wno-ignored-attributes -Wno-strict-aliasing")
+
+ # Check Clang compiler
+ if ("$ENV{CXX}" MATCHES "clang")
+ set(COMPILE_FLAGS "${COMPILE_FLAGS} \
-Wno-unused-local-typedef\
-Wno-unused-private-field\
-fno-strict-vtable-pointers\
-Wno-overloaded-virtual")
else()
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}\
+ set(COMPILE_FLAGS "${COMPILE_FLAGS} \
+ -fno-plt\
+ -fno-devirtualize\
-Wno-unused-local-typedefs\
- -Wno-sign-compare\
- -Wno-strict-aliasing\
- -Wno-unused-but-set-variable\
- -fno-devirtualize")
+ -Wno-unused-but-set-variable")
+
+ # GCC >= 8.3
+ if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0)
+ set(COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-stringop-truncation -Wno-format-truncation -Wno-class-memaccess")
+ endif()
endif()
endif()
-if (NOT DEBUG AND USE_STATIC_LIBSTDC)
- set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-gc-sections -Wl,--version-script=\"${PROJECT_SOURCE_DIR}/../version_script.lds\"")
+# GCC >= 8.3
+if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0)
+ set(COMPILE_FLAGS "${COMPILE_FLAGS} -fcf-protection=none")
endif()
-if (USE_STATIC_LIBSTDC)
- add_definitions(-DBUILD_STATIC_LIBSTDC)
- set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libgcc -static-libstdc++")
+if (NOT DEBUG)
+ set(LINK_FLAGS "${LINK_FLAGS} \
+ -Wl,-gc-sections -Wl,--version-script=\"${PROJECT_SOURCE_DIR}/../version_script.lds\"")
endif()
set(PROJECT_SRC_DIR
@@ -75,6 +110,11 @@ set(PROJECT_SRC_DIR
"${PROJECT_SOURCE_DIR}/game_shared"
"${PROJECT_SOURCE_DIR}/pm_shared"
"${PROJECT_SOURCE_DIR}/regamedll"
+ "${PROJECT_SOURCE_DIR}/unittests"
+)
+
+set(PROJECT_CPPUNITLITE_DIR
+ "${PROJECT_SOURCE_DIR}/../dep/cppunitlite/include"
)
set(PROJECT_PUBLIC_DIR
@@ -86,63 +126,244 @@ set(ENGINE_SRCS
"engine/unicode_strtools.cpp"
)
-file(GLOB SHARED_SRCS
- "game_shared/bot/*.cpp"
- "game_shared/*.cpp"
- "pm_shared/*.cpp"
- "regamedll/*.cpp"
+set(SHARED_SRCS
+ "game_shared/shared_util.cpp"
+ "game_shared/voice_gamemgr.cpp"
+ "game_shared/bot/bot.cpp"
+ "game_shared/bot/bot_manager.cpp"
+ "game_shared/bot/bot_profile.cpp"
+ "game_shared/bot/bot_util.cpp"
+ "game_shared/bot/nav_area.cpp"
+ "game_shared/bot/nav_file.cpp"
+ "game_shared/bot/nav_node.cpp"
+ "game_shared/bot/nav_path.cpp"
+ "pm_shared/pm_debug.cpp"
+ "pm_shared/pm_math.cpp"
+ "pm_shared/pm_shared.cpp"
+ "regamedll/regamedll.cpp"
+ "regamedll/precompiled.cpp"
+ "regamedll/public_amalgamation.cpp"
+ "regamedll/hookchains_impl.cpp"
+ "regamedll/sse_mathfun.cpp"
"public/FileSystem.cpp"
"public/interface.cpp"
"public/MemPool.cpp"
- "version/version.cpp"
)
-list(REMOVE_ITEM SHARED_SRCS EXCLUDE "${PROJECT_SOURCE_DIR}/regamedll/classes_dummy.cpp")
-
-file(GLOB GAMEDLL_SRCS
- "dlls/*.cpp"
- "dlls/API/*.cpp"
- "dlls/addons/*.cpp"
- "dlls/wpn_shared/*.cpp"
- "dlls/bot/*.cpp"
- "dlls/bot/states/*.cpp"
- "dlls/hostage/*.cpp"
- "dlls/hostage/states/*.cpp"
+set(GAMEDLL_SRCS
+ "dlls/airtank.cpp"
+ "dlls/ammo.cpp"
+ "dlls/animating.cpp"
+ "dlls/animation.cpp"
+ "dlls/basemonster.cpp"
+ "dlls/bmodels.cpp"
+ "dlls/buttons.cpp"
+ "dlls/career_tasks.cpp"
+ "dlls/cbase.cpp"
+ "dlls/client.cpp"
+ "dlls/cmdhandler.cpp"
+ "dlls/combat.cpp"
+ "dlls/debug.cpp"
+ "dlls/doors.cpp"
+ "dlls/effects.cpp"
+ "dlls/explode.cpp"
+ "dlls/func_break.cpp"
+ "dlls/func_tank.cpp"
+ "dlls/game.cpp"
+ "dlls/gamerules.cpp"
+ "dlls/ggrenade.cpp"
+ "dlls/gib.cpp"
+ "dlls/globals.cpp"
+ "dlls/h_battery.cpp"
+ "dlls/h_cycler.cpp"
+ "dlls/h_export.cpp"
+ "dlls/healthkit.cpp"
+ "dlls/hintmessage.cpp"
+ "dlls/items.cpp"
+ "dlls/lights.cpp"
+ "dlls/mapinfo.cpp"
+ "dlls/maprules.cpp"
+ "dlls/mortar.cpp"
+ "dlls/multiplay_gamerules.cpp"
+ "dlls/observer.cpp"
+ "dlls/pathcorner.cpp"
+ "dlls/plats.cpp"
+ "dlls/player.cpp"
+ "dlls/revert_saved.cpp"
+ "dlls/saverestore.cpp"
+ "dlls/singleplay_gamerules.cpp"
+ "dlls/skill.cpp"
+ "dlls/sound.cpp"
+ "dlls/soundent.cpp"
+ "dlls/spectator.cpp"
+ "dlls/subs.cpp"
+ "dlls/training_gamerules.cpp"
+ "dlls/triggers.cpp"
+ "dlls/tutor.cpp"
+ "dlls/tutor_base_states.cpp"
+ "dlls/tutor_base_tutor.cpp"
+ "dlls/tutor_cs_states.cpp"
+ "dlls/tutor_cs_tutor.cpp"
+ "dlls/util.cpp"
+ "dlls/vehicle.cpp"
+ "dlls/weapons.cpp"
+ "dlls/weapontype.cpp"
+ "dlls/world.cpp"
+ "dlls/API/CAPI_Impl.cpp"
+ "dlls/API/CSEntity.cpp"
+ "dlls/API/CSPlayer.cpp"
+ "dlls/API/CSPlayerItem.cpp"
+ "dlls/addons/item_airbox.cpp"
+ "dlls/addons/point_command.cpp"
+ "dlls/addons/trigger_random.cpp"
+ "dlls/addons/trigger_setorigin.cpp"
+ "dlls/wpn_shared/wpn_ak47.cpp"
+ "dlls/wpn_shared/wpn_aug.cpp"
+ "dlls/wpn_shared/wpn_awp.cpp"
+ "dlls/wpn_shared/wpn_c4.cpp"
+ "dlls/wpn_shared/wpn_deagle.cpp"
+ "dlls/wpn_shared/wpn_elite.cpp"
+ "dlls/wpn_shared/wpn_famas.cpp"
+ "dlls/wpn_shared/wpn_fiveseven.cpp"
+ "dlls/wpn_shared/wpn_flashbang.cpp"
+ "dlls/wpn_shared/wpn_g3sg1.cpp"
+ "dlls/wpn_shared/wpn_galil.cpp"
+ "dlls/wpn_shared/wpn_glock18.cpp"
+ "dlls/wpn_shared/wpn_hegrenade.cpp"
+ "dlls/wpn_shared/wpn_knife.cpp"
+ "dlls/wpn_shared/wpn_m3.cpp"
+ "dlls/wpn_shared/wpn_m4a1.cpp"
+ "dlls/wpn_shared/wpn_m249.cpp"
+ "dlls/wpn_shared/wpn_mac10.cpp"
+ "dlls/wpn_shared/wpn_mp5navy.cpp"
+ "dlls/wpn_shared/wpn_p90.cpp"
+ "dlls/wpn_shared/wpn_p228.cpp"
+ "dlls/wpn_shared/wpn_scout.cpp"
+ "dlls/wpn_shared/wpn_sg550.cpp"
+ "dlls/wpn_shared/wpn_sg552.cpp"
+ "dlls/wpn_shared/wpn_smokegrenade.cpp"
+ "dlls/wpn_shared/wpn_tmp.cpp"
+ "dlls/wpn_shared/wpn_ump45.cpp"
+ "dlls/wpn_shared/wpn_usp.cpp"
+ "dlls/wpn_shared/wpn_xm1014.cpp"
+ "dlls/bot/cs_bot.cpp"
+ "dlls/bot/cs_bot_chatter.cpp"
+ "dlls/bot/cs_bot_event.cpp"
+ "dlls/bot/cs_bot_init.cpp"
+ "dlls/bot/cs_bot_learn.cpp"
+ "dlls/bot/cs_bot_listen.cpp"
+ "dlls/bot/cs_bot_manager.cpp"
+ "dlls/bot/cs_bot_nav.cpp"
+ "dlls/bot/cs_bot_pathfind.cpp"
+ "dlls/bot/cs_bot_radio.cpp"
+ "dlls/bot/cs_bot_statemachine.cpp"
+ "dlls/bot/cs_bot_update.cpp"
+ "dlls/bot/cs_bot_vision.cpp"
+ "dlls/bot/cs_bot_weapon.cpp"
+ "dlls/bot/cs_gamestate.cpp"
+ "dlls/bot/states/cs_bot_attack.cpp"
+ "dlls/bot/states/cs_bot_buy.cpp"
+ "dlls/bot/states/cs_bot_defuse_bomb.cpp"
+ "dlls/bot/states/cs_bot_escape_from_bomb.cpp"
+ "dlls/bot/states/cs_bot_fetch_bomb.cpp"
+ "dlls/bot/states/cs_bot_follow.cpp"
+ "dlls/bot/states/cs_bot_hide.cpp"
+ "dlls/bot/states/cs_bot_hunt.cpp"
+ "dlls/bot/states/cs_bot_idle.cpp"
+ "dlls/bot/states/cs_bot_investigate_noise.cpp"
+ "dlls/bot/states/cs_bot_move_to.cpp"
+ "dlls/bot/states/cs_bot_plant_bomb.cpp"
+ "dlls/bot/states/cs_bot_use_entity.cpp"
+ "dlls/hostage/hostage.cpp"
+ "dlls/hostage/hostage_improv.cpp"
+ "dlls/hostage/hostage_localnav.cpp"
+ "dlls/hostage/states/hostage_animate.cpp"
+ "dlls/hostage/states/hostage_escape.cpp"
+ "dlls/hostage/states/hostage_follow.cpp"
+ "dlls/hostage/states/hostage_idle.cpp"
+ "dlls/hostage/states/hostage_retreat.cpp"
+)
+
+set(UNITTESTS_SRCS
+ "unittests/animation_tests.cpp"
+ "unittests/struct_offsets_tests.cpp"
+ "unittests/TestRunner.cpp"
)
-include_directories(
+if (CMAKE_BUILD_TYPE MATCHES Unittests)
+ if (NOT TARGET cppunitlite)
+ add_subdirectory(../dep/cppunitlite cppunitlite)
+ endif()
+
+ set(LINK_FLAGS "${LINK_FLAGS} -no-pie -Wl,--no-export-dynamic")
+ add_executable(regamedll ${appversion.sh})
+ target_link_libraries(regamedll PRIVATE cppunitlite)
+else()
+ add_library(regamedll SHARED ${appversion.sh})
+endif()
+
+if (NOT TARGET appversion)
+ add_custom_target(appversion DEPENDS COMMAND "${PROJECT_SOURCE_DIR}/version/appversion.sh" "${PROJECT_SOURCE_DIR}/..")
+endif()
+
+add_dependencies(regamedll appversion)
+
+target_include_directories(regamedll PRIVATE
${PROJECT_SRC_DIR}
+ ${PROJECT_CPPUNITLITE_DIR}
${PROJECT_PUBLIC_DIR}
)
-link_directories(${PROJECT_SOURCE_DIR}/lib/linux32)
-
-add_definitions(
- -DREGAMEDLL_FIXES
- -DBUILD_LATEST
- -DREGAMEDLL_ADD
- -DREGAMEDLL_API
- -DUNICODE_FIXES
- -DCLIENT_WEAPONS
- -DUSE_QSTRING
- -DGNUC
- -DPOSIX
- -D_LINUX
- -DLINUX
- -D_stricmp=strcasecmp
- -D_strnicmp=strncasecmp
- -D_strdup=strdup
- -D_unlink=unlink
- -D_vsnprintf=vsnprintf
- -D_write=write
- -D_close=close
- -D_access=access
- -D_vsnwprintf=vswprintf
+target_compile_definitions(regamedll PRIVATE
+ REGAMEDLL_FIXES
+ REGAMEDLL_API
+ REGAMEDLL_ADD
+ UNICODE_FIXES
+ BUILD_LATEST
+ CLIENT_WEAPONS
+ USE_QSTRING
+ _LINUX
+ LINUX
+ NDEBUG
+ _GLIBCXX_USE_CXX11_ABI=0
+ _stricmp=strcasecmp
+ _strnicmp=strncasecmp
+ _strdup=strdup
+ _unlink=unlink
+ _vsnprintf=vsnprintf
+ _write=write
+ _close=close
+ _access=access
+ _vsnwprintf=vswprintf
)
-add_library(regamedll SHARED ${appversion.sh} ${GAMEDLL_SRCS} ${ENGINE_SRCS} ${SHARED_SRCS})
-set_property(TARGET regamedll PROPERTY LIBRARY_OUTPUT_NAME cs)
-add_custom_target(appversion DEPENDS COMMAND "${PROJECT_SOURCE_DIR}/version/appversion.sh" "${PROJECT_SOURCE_DIR}")
-set_target_properties(regamedll PROPERTIES PREFIX "" COMPILE_FLAGS "-m32" LINK_FLAGS "-m32" POSITION_INDEPENDENT_CODE ON)
-target_link_libraries(regamedll dl aelf32)
-add_dependencies(regamedll appversion)
+target_sources(regamedll PRIVATE
+ ${GAMEDLL_SRCS}
+ ${ENGINE_SRCS}
+ ${SHARED_SRCS}
+
+ $<$:
+ ${UNITTESTS_SRCS}>
+)
+
+target_link_libraries(regamedll PRIVATE
+ dl
+ aelf32
+)
+
+if (USE_STATIC_LIBSTDC)
+ target_compile_definitions(regamedll PRIVATE BUILD_STATIC_LIBSTDC)
+ set(LINK_FLAGS "${LINK_FLAGS} -static-libgcc -static-libstdc++")
+endif()
+
+set(LINK_FLAGS "${LINK_FLAGS} \
+ -Wl,-rpath,'$ORIGIN/.' \
+ -L${PROJECT_SOURCE_DIR}/lib/linux32")
+
+set_target_properties(regamedll PROPERTIES
+ OUTPUT_NAME cs
+ PREFIX ""
+ COMPILE_FLAGS ${COMPILE_FLAGS}
+ LINK_FLAGS ${LINK_FLAGS}
+ POSITION_INDEPENDENT_CODE OFF
+)
diff --git a/regamedll/common/stdc++compat.cpp b/regamedll/common/stdc++compat.cpp
index 27dc579ed..1937b9b3a 100644
--- a/regamedll/common/stdc++compat.cpp
+++ b/regamedll/common/stdc++compat.cpp
@@ -1,15 +1,23 @@
#include
+#include
-#if !defined(_WIN32)
-void NORETURN Sys_Error(const char *error, ...);
+#if !defined(_WIN32) && !defined(BUILD_STATIC_LIBSTDC) // if build with static libstdc++ then ignore
// This file adds the necessary compatibility tricks to avoid symbols with
// version GLIBCXX_3.4.16 and bigger, keeping binary compatibility with libstdc++ 4.6.1.
namespace std
{
+
+#if __cpp_exceptions
+ logic_error::logic_error(const char *__arg) : exception(), _M_msg(__arg) {}
+ out_of_range::out_of_range(const char *__arg) : logic_error(__arg) {}
+ out_of_range::~out_of_range() _GLIBCXX_USE_NOEXCEPT {}
+#endif // #if __cpp_exceptions
+
// We shouldn't be throwing exceptions at all, but it sadly turns out we call STL (inline) functions that do.
void __throw_out_of_range_fmt(const char *fmt, ...)
{
+ #if __cpp_exceptions
va_list ap;
char buf[1024]; // That should be big enough.
@@ -18,34 +26,42 @@ namespace std
buf[sizeof(buf) - 1] = '\0';
va_end(ap);
- Sys_Error(buf);
+ throw std::out_of_range(buf);
+ #else
+ abort();
+ #endif
}
}; // namespace std
-// Technically, this symbol is not in GLIBCXX_3.4.20, but in CXXABI_1.3.8,
-// but that's equivalent, version-wise. Those calls are added by the compiler
+// Was added in GCC 4.9
+// Technically, this symbol is not in GLIBCXX_3.4.20, but in CXXABI_1.3.8, but that's equivalent, version-wise.
+// Those calls are added by the compiler
// itself on `new Class[n]` calls.
extern "C"
void __cxa_throw_bad_array_new_length()
{
- Sys_Error("Bad array new length.");
+#if __cpp_exceptions
+ throw std::bad_array_new_length();
+#else
+ abort();
+#endif
}
-#if __cplusplus >= 201402L
+#if defined(__INTEL_COMPILER) && __cplusplus >= 201402L
// This operator delete sized deallocations was added in c++14
// and required at least not less than CXXABI_1.3.9
// we should to keep CXXABI_1.3.8 for binary compatibility with oldest libstdc++.
-// G++ and clang allow to compile C++14 code with -fno-sized-deallocation to disable the new feature,
+// GCC and Clang allow to compile C++14 code with -fno-sized-deallocation to disable the new feature, but ICC isn't allow
// so that our C++14 library code would never call that version of operator delete,
-// for other compilers we must override those operators for static linking to the library.
+// for ICC compiler we must override those operators for static linking to the library.
void operator delete[](void *ptr, std::size_t size) noexcept
{
- ::operator delete(ptr);
+ ::operator delete(ptr);
}
void operator delete(void *ptr, std::size_t size) noexcept
{
- ::operator delete(ptr);
+ ::operator delete(ptr);
}
#endif
diff --git a/regamedll/compile.sh b/regamedll/compile.sh
deleted file mode 100755
index c75a2eedd..000000000
--- a/regamedll/compile.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-
-rm -rf build
-mkdir build
-cd build
-cmake ../ $*
-make
diff --git a/regamedll/dlls/bot/cs_bot_learn.cpp b/regamedll/dlls/bot/cs_bot_learn.cpp
index 63e6db28c..bb6df51d2 100644
--- a/regamedll/dlls/bot/cs_bot_learn.cpp
+++ b/regamedll/dlls/bot/cs_bot_learn.cpp
@@ -489,14 +489,14 @@ void CCSBot::UpdateSaveProcess()
HintMessageToAllPlayers("Saving...");
SaveNavigationMap(filename);
- Q_sprintf(msg, "Navigation file '%s' saved.", filename);
+ Q_snprintf(msg, sizeof(msg), "Navigation file '%s' saved.", filename);
HintMessageToAllPlayers(msg);
hideProgressMeter();
StartNormalProcess();
#ifndef REGAMEDLL_FIXES
- Q_sprintf(cmd, "map %s\n", STRING(gpGlobals->mapname));
+ Q_snprintf(cmd, sizeof(cmd), "map %s\n", STRING(gpGlobals->mapname));
#else
Q_snprintf(cmd, sizeof(cmd), "changelevel %s\n", STRING(gpGlobals->mapname));
#endif
diff --git a/regamedll/engine/unicode_strtools.cpp b/regamedll/engine/unicode_strtools.cpp
index d19c92f0d..e7e113ba6 100644
--- a/regamedll/engine/unicode_strtools.cpp
+++ b/regamedll/engine/unicode_strtools.cpp
@@ -748,7 +748,7 @@ int Q_UnicodeConvertT(const SrcType *pIn, int nInChars, DstType *pOut, int nOutB
{
while (bStopAtNull ? (*pIn) : (nInChars-- > 0))
{
- uchar32 uVal;
+ uchar32 uVal = '?';
bool bErr = false; // Initialize in order to avoid /analyze warnings.
pIn += DecodeSrc(pIn, uVal, bErr);
@@ -782,7 +782,7 @@ int Q_UnicodeConvertT(const SrcType *pIn, int nInChars, DstType *pOut, int nOutB
int nMaxOut = nOutElems - 1; // print symbols count
while (bStopAtNull ? (*pIn) : (nInChars-- > 0))
{
- uchar32 uVal;
+ uchar32 uVal = '?';
bool bErr = false; // Initialize in order to avoid /analyze warnings.
pIn += DecodeSrc(pIn, uVal, bErr);
diff --git a/regamedll/lib/linux32/libm.so b/regamedll/lib/linux32/libm.so
new file mode 100644
index 000000000..b0430eb9f
Binary files /dev/null and b/regamedll/lib/linux32/libm.so differ
diff --git a/regamedll/lib/linux32/librt.so b/regamedll/lib/linux32/librt.so
new file mode 100644
index 000000000..4b39fa4ab
Binary files /dev/null and b/regamedll/lib/linux32/librt.so differ
diff --git a/regamedll/pm_shared/pm_shared.cpp b/regamedll/pm_shared/pm_shared.cpp
index bbe213e53..b50fde669 100644
--- a/regamedll/pm_shared/pm_shared.cpp
+++ b/regamedll/pm_shared/pm_shared.cpp
@@ -23,13 +23,13 @@ void PM_SwapTextures(int i, int j)
char chTemp;
char szTemp[MAX_TEXTURENAME_LENGHT];
- Q_strcpy(szTemp, pm_grgszTextureName[i]);
+ Q_strlcpy(szTemp, pm_grgszTextureName[i]);
chTemp = pm_grgchTextureType[i];
- Q_strcpy(pm_grgszTextureName[i], pm_grgszTextureName[j]);
+ Q_strcpy_s(pm_grgszTextureName[i], pm_grgszTextureName[j]);
pm_grgchTextureType[i] = pm_grgchTextureType[j];
- Q_strcpy(pm_grgszTextureName[j], szTemp);
+ Q_strlcpy(pm_grgszTextureName[j], szTemp);
pm_grgchTextureType[j] = chTemp;
}
diff --git a/regamedll/version/glibc_test.sh b/regamedll/version/glibc_test.sh
new file mode 100755
index 000000000..74d41d2c3
--- /dev/null
+++ b/regamedll/version/glibc_test.sh
@@ -0,0 +1,83 @@
+#!/bin/bash
+
+main()
+{
+ files=($@)
+
+ declare -A threshold_version
+ threshold_version[CXXABI]="1.3.5"
+ threshold_version[GLIBCXX]="3.4.15"
+ threshold_version[GLIBC]="2.11"
+
+ for k in "${!threshold_version[@]}"; do
+ for f in "${files[@]}"
+ do
+ :
+ version=$(readelf -sV $f | sed -n 's/.*@'$k'_//p' | sort -u -V | tail -1 | cut -d ' ' -f 1)
+
+ # version no present - skipped
+ if [[ -z "$version" ]]; then
+ version="UND"
+ # version is private - skipped
+ elif [ "$version" = "PRIVATE" ]; then
+ version="PRV"
+ # ensure numeric
+ elif [[ $version =~ ^([0-9]+\.){0,2}(\*|[0-9]+)$ ]]; then
+ check_version_greater $version ${threshold_version[$k]}
+ if [[ $? -eq 1 ]]; then
+ echo -e "\033[0;31mAssertion failed:\033[0m Binary \033[0;32m${f}\033[0m has ${k}_\033[0;33m$version\033[0m greater than max version ${k}_\033[0;33m${threshold_version[$k]}\033[0m"
+ exit -1
+ fi
+ fi
+ done
+
+ if [[ "$version" = "PRV" || "$version" = "UND" ]]; then
+ echo -e "[\033[0;90mSKIP\033[0m] \033[0;33m${version}\033[0m < ${k}_\033[0;33m${threshold_version[$k]}\033[0m"
+ else
+ echo -e "[\033[0;32mOK\033[0m] \033[0;33m${version}\033[0m < ${k}_\033[0;33m${threshold_version[$k]}\033[0m"
+ fi
+ done
+}
+
+check_version_greater()
+{
+ if [[ -z "$1" || $1 == $2 ]]; then
+ return 0
+ fi
+
+ local IFS=.
+ local i ver1=($1) ver2=($2)
+
+ # fill empty fields in ver1 with zeros
+ for ((i = ${#ver1[@]}; i < ${#ver2[@]}; i++))
+ do
+ ver1[i]=0
+ done
+
+ for ((i = 0; i < ${#ver1[@]}; i++))
+ do
+ if [[ -z ${ver2[i]} ]]
+ then
+ # fill empty fields in ver2 with zeros
+ ver2[i]=0
+ fi
+
+ if ((10#${ver1[i]} > 10#${ver2[i]}))
+ then
+ return 1
+ fi
+
+ if ((10#${ver1[i]} < 10#${ver2[i]}))
+ then
+ break
+ fi
+ done
+
+ return 0
+}
+
+# Initialize
+main $*
+
+# Exit normally
+exit 0