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: -
    -
  1. Java Development Kit (JDK) 7+ (http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
  2. -
  3. For Windows: Visual Studio 2015 and later
  4. -
  5. For Linux: GCC/Clang/Intel C++ Compiler 15 and later
  6. -
- ### 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
+ -* 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