New buildsystem (#197)

This commit is contained in:
Lion 2023-12-05 18:21:20 +01:00 committed by GitHub
commit 872c2d410d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
58 changed files with 926 additions and 777 deletions

View File

@ -1,78 +0,0 @@
name: CMake Linux Build
on: [push]
env:
BUILD_TYPE: Release
jobs:
linux-build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
with:
submodules: "recursive"
- name: Install Dependencies
env:
beammp_sentry_url: ${{ secrets.BEAMMP_SECRET_SENTRY_URL }}
run: |
echo ${#beammp_sentry_url}
sudo apt-get update
sudo apt-get install -y libz-dev rapidjson-dev liblua5.3 libssl-dev libwebsocketpp-dev libcurl4-openssl-dev cmake g++-10 libboost1.74-all-dev
- name: Create Build Environment
run: cmake -E make_directory ${{github.workspace}}/build-linux
- name: Configure CMake
shell: bash
working-directory: ${{github.workspace}}/build-linux
env:
beammp_sentry_url: ${{ secrets.BEAMMP_SECRET_SENTRY_URL }}
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_CXX_COMPILER=g++-10 -DBEAMMP_SECRET_SENTRY_URL="$beammp_sentry_url"
- name: Build Server
working-directory: ${{github.workspace}}/build-linux
shell: bash
run: cmake --build . --config $BUILD_TYPE -t BeamMP-Server --parallel
- name: Build Tests
working-directory: ${{github.workspace}}/build-linux
shell: bash
run: cmake --build . --config $BUILD_TYPE -t BeamMP-Server-tests --parallel
- name: Archive server artifact
uses: actions/upload-artifact@v2
with:
name: BeamMP-Server-linux
path: ${{github.workspace}}/build-linux/BeamMP-Server
- name: Archive test artifact
uses: actions/upload-artifact@v2
with:
name: BeamMP-Server-linux-tests
path: ${{github.workspace}}/build-linux/BeamMP-Server-tests
run-tests:
needs: linux-build
runs-on: ubuntu-22.04
steps:
- uses: actions/download-artifact@master
with:
name: BeamMP-Server-linux-tests
path: ${{github.workspace}}
- name: Install Runtime Dependencies
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y liblua5.3-0 libssl3 curl
- name: Test
working-directory: ${{github.workspace}}
shell: bash
run: |
chmod +x ./BeamMP-Server-tests
./BeamMP-Server-tests

View File

@ -1,58 +0,0 @@
name: CMake Windows Build
on: [push]
env:
BUILD_TYPE: Release
jobs:
windows-build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Restore artifacts, or run vcpkg, build and cache artifacts
uses: lukka/run-vcpkg@v7
id: runvcpkg
with:
vcpkgArguments: 'lua zlib rapidjson openssl websocketpp curl'
vcpkgDirectory: '${{ runner.workspace }}/b/vcpkg'
vcpkgGitCommitId: "06b5f4a769d848d1a20fa0acd556019728b56273"
vcpkgTriplet: 'x64-windows-static'
- name: Create Build Environment
run: cmake -E make_directory ${{github.workspace}}/build-windows
- name: Configure CMake
shell: bash
working-directory: ${{github.workspace}}/build-windows
env:
beammp_sentry_url: ${{ secrets.BEAMMP_SECRET_SENTRY_URL }}
run: cmake $GITHUB_WORKSPACE -DSENTRY_BACKEND=breakpad -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_TOOLCHAIN_FILE='${{ runner.workspace }}/b/vcpkg/scripts/buildsystems/vcpkg.cmake' -DVCPKG_TARGET_TRIPLET=x64-windows-static -DBEAMMP_SECRET_SENTRY_URL="$beammp_sentry_url"
- name: Build
working-directory: ${{github.workspace}}/build-windows
shell: bash
run: cmake --build . --config $BUILD_TYPE
- name: Archive artifacts
uses: actions/upload-artifact@v2
with:
name: BeamMP-Server.exe
path: ${{github.workspace}}/build-windows/Release/BeamMP-Server.exe
- name: Build debug
working-directory: ${{github.workspace}}/build-windows
shell: bash
run: |
cmake --build . --config Debug
- name: Archive debug artifacts
uses: actions/upload-artifact@v2
with:
name: BeamMP-Server-debug.exe
path: ${{github.workspace}}/build-windows/Debug/BeamMP-Server.exe

150
.github/workflows/linux.yml vendored Normal file
View File

@ -0,0 +1,150 @@
name: Linux
on: [push]
env:
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
jobs:
debian-11-build:
runs-on: ubuntu-latest
container:
image: debian:11
steps:
- name: Export GitHub Actions cache environment variables
uses: actions/github-script@v6
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- name: Install git
run: |
apt-get update -y
apt-get install -y git
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Git config safe directory
shell: bash
run: bash ./scripts/debian-11/1.5-git-safe.sh
- name: Install Dependencies
run: bash ./scripts/debian-11/1-install-deps.sh
- name: Create Build Environment
run: bash ./scripts/debian-11/2-configure.sh '-DCMAKE_TOOLCHAIN_FILE=./vcpkg/scripts/buildsystems/vcpkg.cmake'
- name: Build Server
run: bash ./scripts/debian-11/3-build.sh
- name: Archive server artifact
uses: actions/upload-artifact@v2
with:
name: BeamMP-Server-debian
path: ./bin/BeamMP-Server
- name: Build Tests
run: bash ./scripts/debian-11/3-build-tests.sh
- name: Archive server tests artifact
uses: actions/upload-artifact@v2
with:
name: BeamMP-Server-debian-tests
path: ./bin/BeamMP-Server-tests
ubuntu-22-04-build:
runs-on: ubuntu-latest
container:
image: ubuntu:22.04
steps:
- name: Export GitHub Actions cache environment variables
uses: actions/github-script@v6
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- name: Install git
run: |
apt-get update -y
apt-get install -y git
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Git config safe directory
shell: bash
run: bash ./scripts/ubuntu-22.04/1.5-git-safe.sh
- name: Install Dependencies
run: bash ./scripts/ubuntu-22.04/1-install-deps.sh
- name: Setup vcpkg
uses: lukka/run-vcpkg@v11
with:
runVcpkgInstall: true
- name: Create Build Environment
run: bash ./scripts/ubuntu-22.04/2-configure.sh '-DCMAKE_TOOLCHAIN_FILE=./vcpkg/scripts/buildsystems/vcpkg.cmake'
- name: Build Server
run: bash ./scripts/ubuntu-22.04/3-build.sh
- name: Archive server artifact
uses: actions/upload-artifact@v2
with:
name: BeamMP-Server-ubuntu
path: ./bin/BeamMP-Server
- name: Build Tests
run: bash ./scripts/ubuntu-22.04/3-build-tests.sh
- name: Archive server tests artifact
uses: actions/upload-artifact@v2
with:
name: BeamMP-Server-ubuntu-tests
path: ./bin/BeamMP-Server-tests
run-debian-11-tests:
needs: debian-11-build
runs-on: ubuntu-latest
container:
image: debian:11
steps:
- uses: actions/download-artifact@master
with:
name: BeamMP-Server-debian-tests
- name: Install Runtime Dependencies
run: |
apt-get update -y
apt-get install -y liblua5.3-0
- name: Test
run: |
chmod +x ./BeamMP-Server-tests
./BeamMP-Server-tests
run-ubuntu-22-04-tests:
needs: ubuntu-22-04-build
runs-on: ubuntu-latest
container:
image: ubuntu:22.04
steps:
- uses: actions/download-artifact@master
with:
name: BeamMP-Server-ubuntu-tests
- name: Install Runtime Dependencies
run: |
apt-get update -y
apt-get install -y liblua5.3-0
- name: Test
run: |
chmod +x ./BeamMP-Server-tests
./BeamMP-Server-tests

View File

@ -1,115 +0,0 @@
name: Release Create & Build
on:
push:
# Sequence of patterns matched against refs/tags
tags:
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
env:
BUILD_TYPE: Release
jobs:
create-release:
runs-on: ubuntu-latest
name: Create Release
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
steps:
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: ${{ github.ref }}
draft: false
prerelease: true
body: |
Files included in this release:
- `BeamMP-Server.exe` is the windows build
- `BeamMP-Server-linux` is a ubuntu build, so you need the dependencies listed in README.md to run it. For any other distros please build from source as described in README.md.
upload-release-files-linux:
name: Upload Linux Release Files
runs-on: ubuntu-22.04
needs: create-release
steps:
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install -y libz-dev rapidjson-dev liblua5.3 libssl-dev libwebsocketpp-dev libcurl4-openssl-dev libboost-dev libboost1.74-all-dev libboost1.74-dev
- name: Create Build Environment
run: cmake -E make_directory ${{github.workspace}}/build-linux
- name: Configure CMake
shell: bash
working-directory: ${{github.workspace}}/build-linux
env:
beammp_sentry_url: ${{ secrets.BEAMMP_SECRET_SENTRY_URL }}
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_CXX_COMPILER=g++-10 -DBEAMMP_SECRET_SENTRY_URL="$beammp_sentry_url"
- name: Build
working-directory: ${{github.workspace}}/build-linux
shell: bash
run: cmake --build . --config $BUILD_TYPE
- name: Upload Release Asset
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
asset_path: ${{github.workspace}}/build-linux/BeamMP-Server
asset_name: BeamMP-Server-linux
asset_content_type: application/x-elf
upload-release-files-windows:
name: Upload Windows Release Files
runs-on: windows-latest
needs: create-release
steps:
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Restore artifacts, or run vcpkg, build and cache artifacts
uses: lukka/run-vcpkg@v7
id: runvcpkg
with:
vcpkgArguments: 'lua zlib rapidjson openssl websocketpp curl'
vcpkgDirectory: '${{ runner.workspace }}/b/vcpkg'
vcpkgGitCommitId: '06b5f4a769d848d1a20fa0acd556019728b56273'
vcpkgTriplet: 'x64-windows-static'
- name: Create Build Environment
run: cmake -E make_directory ${{github.workspace}}/build-windows
- name: Configure CMake
shell: bash
working-directory: ${{github.workspace}}/build-windows
env:
beammp_sentry_url: ${{ secrets.BEAMMP_SECRET_SENTRY_URL }}
run: cmake $GITHUB_WORKSPACE -DSENTRY_BACKEND=breakpad -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_TOOLCHAIN_FILE='${{ runner.workspace }}/b/vcpkg/scripts/buildsystems/vcpkg.cmake' -DVCPKG_TARGET_TRIPLET=x64-windows-static -DBEAMMP_SECRET_SENTRY_URL="$beammp_sentry_url"
- name: Build
working-directory: ${{github.workspace}}/build-windows
shell: bash
run: cmake --build . --config $BUILD_TYPE
- name: Upload Release Asset
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
asset_path: ${{github.workspace}}/build-windows/Release/BeamMP-Server.exe
asset_name: BeamMP-Server.exe
asset_content_type: application/vnd.microsoft.portable-executable

168
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,168 @@
name: Release Create & Build
on:
push:
# Sequence of patterns matched against refs/tags
tags:
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
env:
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
jobs:
create-release:
runs-on: ubuntu-latest
name: Create Release
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
steps:
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: ${{ github.ref }}
draft: false
prerelease: true
body: |
Files included in this release:
- `BeamMP-Server.exe` is the windows build.
- `BeamMP-Server-debian` is a Debian 11 build, requires `liblua5.3-0`.
- `BeamMP-Server-ubuntu` is a Ubuntu 22.04 build, requires `liblua5.3-0`.
upload-release-files-debian-11:
name: Build and upload Debian 11 Release Files
runs-on: ubuntu-22.04
needs: create-release
container:
image: debian:11
steps:
- name: Export GitHub Actions cache environment variables
uses: actions/github-script@v6
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- name: Install git
run: |
apt-get update -y
apt-get install -y git
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Git config safe directory
shell: bash
run: bash ./scripts/debian-11/1.5-git-safe.sh
- name: Install Dependencies
run: bash ./scripts/debian-11/1-install-deps.sh
- name: Setup vcpkg
uses: lukka/run-vcpkg@v11
with:
runVcpkgInstall: true
- name: Create Build Environment
run: bash ./scripts/debian-11/2-configure.sh '-DCMAKE_TOOLCHAIN_FILE=./vcpkg/scripts/buildsystems/vcpkg.cmake'
- name: Build Server
run: bash ./scripts/debian-11/3-build.sh
- name: Upload Release Asset
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: ./bin/BeamMP-Server
asset_name: BeamMP-Server-debian
asset_content_type: application/x-elf
upload-release-files-ubuntu-22-04:
name: Build and upload Ubuntu 22.04 Release Files
runs-on: ubuntu-22.04
needs: create-release
container:
image: ubuntu:22.04
steps:
- name: Export GitHub Actions cache environment variables
uses: actions/github-script@v6
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- name: Install git
run: |
apt-get update -y
apt-get install -y git
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Git config safe directory
shell: bash
run: bash ./scripts/ubuntu-22.04/1.5-git-safe.sh
- name: Install Dependencies
run: bash ./scripts/ubuntu-22.04/1-install-deps.sh
- name: Create Build Environment
run: bash ./scripts/ubuntu-22.04/2-configure.sh '-DCMAKE_TOOLCHAIN_FILE=./vcpkg/scripts/buildsystems/vcpkg.cmake'
- name: Build Server
run: bash ./scripts/ubuntu-22.04/3-build.sh
- name: Upload Release Asset
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: ./bin/BeamMP-Server
asset_name: BeamMP-Server-ubuntu
asset_content_type: application/x-elf
upload-release-files-windows:
name: Build and upload Windows Release Files
runs-on: windows-latest
needs: create-release
env:
VCPKG_DEFAULT_TRIPLET: x64-windows-static
steps:
- name: Export GitHub Actions cache environment variables
uses: actions/github-script@v6
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Create Build Environment
shell: bash
run: ./scripts/windows/1-configure.sh
- name: Build Server
shell: bash
run: bash ./scripts/windows/2-build.sh
- name: Upload Release Asset
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: ./bin/BeamMP-Server.exe
asset_name: BeamMP-Server.exe
asset_content_type: application/vnd.microsoft.portable-executable

42
.github/workflows/windows.yml vendored Normal file
View File

@ -0,0 +1,42 @@
name: Windows
on: [push]
env:
VCPKG_DEFAULT_TRIPLET: x64-windows-static
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
jobs:
windows-build:
runs-on: windows-latest
steps:
- name: Export GitHub Actions cache environment variables
uses: actions/github-script@v6
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Setup vcpkg
uses: lukka/run-vcpkg@v11
with:
runVcpkgInstall: true
- name: Create Build Environment
shell: bash
run: ./scripts/windows/1-configure.sh
- name: Build Server
shell: bash
run: bash ./scripts/windows/2-build.sh
- name: Archive server artifact
uses: actions/upload-artifact@v2
with:
name: BeamMP-Server-windows
path: ./bin/BeamMP-Server.exe

33
.gitmodules vendored
View File

@ -1,33 +1,6 @@
[submodule "deps/commandline"]
path = deps/commandline
url = https://github.com/lionkor/commandline
[submodule "deps/asio"]
path = deps/asio
url = https://github.com/chriskohlhoff/asio
[submodule "deps/rapidjson"]
path = deps/rapidjson
url = https://github.com/Tencent/rapidjson
[submodule "deps/toml11"]
path = deps/toml11
url = https://github.com/ToruNiina/toml11
[submodule "deps/sentry-native"]
path = deps/sentry-native
url = https://github.com/getsentry/sentry-native
[submodule "deps/sol2"]
path = deps/sol2
url = https://github.com/ThePhD/sol2
[submodule "deps/libzip"]
path = deps/libzip
url = https://github.com/nih-at/libzip
[submodule "deps/cpp-httplib"]
path = deps/cpp-httplib
url = https://github.com/yhirose/cpp-httplib
[submodule "deps/json"]
path = deps/json
url = https://github.com/nlohmann/json
[submodule "deps/fmt"]
path = deps/fmt
url = https://github.com/fmtlib/fmt
[submodule "deps/doctest"]
path = deps/doctest
url = https://github.com/doctest/doctest
[submodule "vcpkg"]
path = vcpkg
url = https://github.com/Microsoft/vcpkg.git

View File

@ -1,262 +1,212 @@
# 3.4 is required for imported targets.
cmake_minimum_required(VERSION 3.4 FATAL_ERROR)
cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
message(STATUS "You can find build instructions and a list of dependencies in the README at \
https://github.com/BeamMP/BeamMP-Server")
project(BeamMP-Server
DESCRIPTION "Server for BeamMP - The Multiplayer Mod for BeamNG.drive"
HOMEPAGE_URL https://beammp.com
LANGUAGES CXX C)
find_package(Git REQUIRED)
# Update submodules as needed
option(GIT_SUBMODULE "Check submodules during build" ON)
if(GIT_SUBMODULE)
message(STATUS "Submodule update")
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE GIT_SUBMOD_RESULT)
if(NOT GIT_SUBMOD_RESULT EQUAL "0")
message(FATAL_ERROR "git submodule update --init --recursive failed with ${GIT_SUBMOD_RESULT}, please checkout submodules")
endif()
if (WIN32)
set(VCPKG_TARGET_TRIPLET x64-windows-static)
endif()
include(cmake/Vcpkg.cmake) # needs to happen before project()
set(HTTPLIB_REQUIRE_OPENSSL ON)
set(SENTRY_BUILD_SHARED_LIBS OFF)
project(
"BeamMP-Server" # replace this
VERSION 3.3.0
)
add_compile_definitions(CPPHTTPLIB_OPENSSL_SUPPORT=1)
include(cmake/StandardSettings.cmake)
include(cmake/StaticAnalyzers.cmake)
include(cmake/Git.cmake)
option(WIN32_STATIC_RUNTIME "Build statically-linked runtime on windows (don't touch unless you know what you're doing)" ON)
# below are options which should be changed
# ------------------------ APPLE ---------------------------------
if(APPLE)
if(IS_DIRECTORY /opt/homebrew/Cellar/lua@5.3/5.3.6)
set(LUA_INCLUDE_DIR /opt/homebrew/Cellar/lua@5.3/5.3.6/include/lua5.3)
link_directories(/opt/homebrew/Cellar/lua@5.3/5.3.6/lib)
else()
set(LUA_INCLUDE_DIR /usr/local/Cellar/lua@5.3/5.3.6/include/lua5.3)
link_directories(/usr/local/Cellar/lua@5.3/5.3.6/lib)
endif()
set(LUA_LIBRARIES lua)
if(IS_DIRECTORY /opt/homebrew/opt/openssl@1.1)
include_directories(/opt/homebrew/opt/openssl@1.1/include)
link_directories(/opt/homebrew/opt/openssl@1.1/lib)
else()
include_directories(/usr/local/opt/openssl@1.1/include)
link_directories(/usr/local/opt/openssl@1.1/lib)
endif()
# ------------------------ WINDOWS ---------------------------------
elseif (WIN32)
if (WIN32_STATIC_RUNTIME)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()
# ------------------------ UNIX ------------------------------------
elseif (UNIX)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2")
option(SANITIZE "Turns on thread and UB sanitizers" OFF)
if (SANITIZE)
message(STATUS "sanitize is ON")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize={address,thread,undefined}")
endif (SANITIZE)
endif ()
### SETTINGS ###
set(BUILD_SHARED_LIBS OFF)
# ------------------------ SENTRY ---------------------------------
message(STATUS "Checking for Sentry URL")
# this is set by the build system.
# IMPORTANT: if you're building from source, just leave this empty
if (NOT DEFINED BEAMMP_SECRET_SENTRY_URL)
message(WARNING "No sentry URL configured. Sentry logging is disabled for this build. \
This is not an error, and if you're building the BeamMP-Server yourself, this is expected and can be ignored.")
set(BEAMMP_SECRET_SENTRY_URL "")
set(SENTRY_BACKEND none)
else()
set(SENTRY_BACKEND breakpad)
endif()
add_subdirectory("deps/sentry-native")
# ------------------------ C++ SETUP ---------------------------------
set(CMAKE_CXX_STANDARD 17)
# ------------------------ DEPENDENCIES ------------------------------
message(STATUS "Adding local source dependencies")
# this has to happen before -DDEBUG since it wont compile properly with -DDEBUG
add_subdirectory(deps)
# ------------------------ VARIABLES ---------------------------------
include(FindLua)
include(FindOpenSSL)
include(FindThreads)
include(FindZLIB)
find_package(Boost 1.70 REQUIRED COMPONENTS system)
set(BeamMP_Sources
include/TConsole.h src/TConsole.cpp
include/TServer.h src/TServer.cpp
include/Compat.h src/Compat.cpp
include/Common.h src/Common.cpp
include/Client.h src/Client.cpp
include/VehicleData.h src/VehicleData.cpp
include/TConfig.h src/TConfig.cpp
include/TLuaEngine.h src/TLuaEngine.cpp
include/TLuaPlugin.h src/TLuaPlugin.cpp
include/TResourceManager.h src/TResourceManager.cpp
include/THeartbeatThread.h src/THeartbeatThread.cpp
include/Http.h src/Http.cpp
include/TSentry.h src/TSentry.cpp
include/TPPSMonitor.h src/TPPSMonitor.cpp
include/TNetwork.h src/TNetwork.cpp
include/LuaAPI.h src/LuaAPI.cpp
include/TScopedTimer.h src/TScopedTimer.cpp
include/SignalHandling.h src/SignalHandling.cpp
include/ArgsParser.h src/ArgsParser.cpp
include/TPluginMonitor.h src/TPluginMonitor.cpp
include/Environment.h
# add all headers (.h, .hpp) to this
set(PRJ_HEADERS
include/ArgsParser.h
include/BoostAliases.h
include/Client.h
include/Common.h
include/Compat.h
include/Cryptography.h
include/CustomAssert.h
include/Defer.h
include/Environment.h
include/Http.h
include/IThreaded.h
include/Json.h
include/LuaAPI.h
include/RWMutex.h
include/SignalHandling.h
include/TConfig.h
include/TConsole.h
include/THeartbeatThread.h
include/TLuaEngine.h
include/TLuaPlugin.h
include/TNetwork.h
include/TPluginMonitor.h
include/TPPSMonitor.h
include/TResourceManager.h
include/TScopedTimer.h
include/TServer.h
include/VehicleData.h
)
# add all source files (.cpp) to this, except the one with main()
set(PRJ_SOURCES
src/ArgsParser.cpp
src/Client.cpp
src/Common.cpp
src/Compat.cpp
src/Http.cpp
src/LuaAPI.cpp
src/SignalHandling.cpp
src/TConfig.cpp
src/TConsole.cpp
src/THeartbeatThread.cpp
src/TLuaEngine.cpp
src/TLuaPlugin.cpp
src/TNetwork.cpp
src/TPluginMonitor.cpp
src/TPPSMonitor.cpp
src/TResourceManager.cpp
src/TScopedTimer.cpp
src/TServer.cpp
src/VehicleData.cpp
)
set(BeamMP_Includes
${LUA_INCLUDE_DIR}
${CURL_INCLUDE_DIRS}
"${CMAKE_CURRENT_SOURCE_DIR}/deps/cpp-httplib"
"${CMAKE_CURRENT_SOURCE_DIR}/deps/commandline"
"${CMAKE_CURRENT_SOURCE_DIR}/deps/json/single_include"
"${CMAKE_CURRENT_SOURCE_DIR}/deps/sol2/include"
"${CMAKE_CURRENT_SOURCE_DIR}/deps/rapidjson/include"
"${CMAKE_CURRENT_SOURCE_DIR}/deps/asio/asio/include"
"${CMAKE_CURRENT_SOURCE_DIR}/deps"
)
find_package(Lua REQUIRED)
set(BeamMP_Definitions
SECRET_SENTRY_URL="${BEAMMP_SECRET_SENTRY_URL}"
)
if (WIN32)
list(APPEND BeamMP_Definitions _WIN32_WINNT=0x0601)
list(APPEND BeamMP_Definitions _CRT_SECURE_NO_WARNINGS)
endif()
if (UNIX)
set(BeamMP_CompileOptions
-Wall
-Wextra
-Wpedantic
-Werror=uninitialized
-Werror=float-equal
-Werror=pointer-arith
-Werror=double-promotion
-Werror=write-strings
-Werror=cast-qual
-Werror=init-self
-Werror=cast-align
-Werror=unreachable-code
-Werror=strict-aliasing -fstrict-aliasing
-Werror=redundant-decls
-Werror=missing-declarations
-Werror=missing-field-initializers
-Werror=write-strings
-Werror=ctor-dtor-privacy
-Werror=switch-enum
-Werror=switch-default
-Werror=old-style-cast
-Werror=overloaded-virtual
-Werror=overloaded-virtual
-Werror=missing-include-dirs
-Werror=unused-result
-fstack-protector
-Wzero-as-null-pointer-constant
)
else()
set(BeamMP_CompileOptions
/bigobj
/INCREMENTAL:NO /NODEFAULTLIB:MSVCRT /NODEFAULTLIB:LIBCMT
)
endif()
set(BeamMP_Libraries
Boost::boost
Boost::system
doctest::doctest
OpenSSL::SSL
OpenSSL::Crypto
sol2::sol2
# set the source file containing main()
set(PRJ_MAIN src/main.cpp)
# set the source file containing the test's main
set(PRJ_TEST_MAIN test/test_main.cpp)
# set include paths not part of libraries
set(PRJ_INCLUDE_DIRS ${LUA_INCLUDE_DIR})
# set compile features (e.g. standard version)
set(PRJ_COMPILE_FEATURES cxx_std_20)
# set #defines (test enable/disable not included here)
set(PRJ_DEFINITIONS CPPHTTPLIB_OPENSSL_SUPPORT)
# add all libraries used by the project (WARNING: also set them in vcpkg.json!)
set(PRJ_LIBRARIES
fmt::fmt
doctest::doctest
Threads::Threads
ZLIB::ZLIB
commandline_static
toml11::toml11
rapidjson
sol2
httplib::httplib
libzip::zip
OpenSSL::SSL OpenSSL::Crypto
${LUA_LIBRARIES}
commandline
sentry
)
if (WIN32)
set(BeamMP_PlatformLibs wsock32 ws2_32)
endif ()
# add dependency find_package calls and similar here
find_package(fmt CONFIG REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(doctest CONFIG REQUIRED)
find_package(Boost REQUIRED)
find_package(httplib CONFIG REQUIRED)
find_package(libzip CONFIG REQUIRED)
find_package(RapidJSON CONFIG REQUIRED)
find_package(sol2 CONFIG REQUIRED)
find_package(toml11 CONFIG REQUIRED)
# ------------------------ BEAMMP SERVER -----------------------------
include_directories(include)
add_executable(BeamMP-Server
src/main.cpp
${BeamMP_Sources}
)
# to enable multithreading and the Threads::Threads dependency
include(FindThreads)
target_compile_definitions(BeamMP-Server PRIVATE
${BeamMP_Definitions}
DOCTEST_CONFIG_DISABLE
)
### END SETTINGS ###
target_compile_options(BeamMP-Server PRIVATE
${BeamMP_CompileOptions}
)
# DONT change anything beyond this point unless you've read the cmake bible and
# swore on it not to bonk up the ci/cd pipelines with your changes.
target_include_directories(BeamMP-Server PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/include"
)
####################
target_include_directories(BeamMP-Server SYSTEM PRIVATE
${BeamMP_Includes}
)
target_link_libraries(BeamMP-Server
${BeamMP_Libraries}
${BeamMP_PlatformLibs}
)
# enables compile_commands.json for clang-related tools (such as the clang LS)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# ------------------------ BEAMMP SERVER TESTS -----------------------
option(BUILD_TESTS "Build BeamMP-Server tests" ON)
if(BUILD_TESTS)
add_executable(BeamMP-Server-tests
test/test_main.cpp
${BeamMP_Sources}
)
target_compile_definitions(BeamMP-Server-tests PRIVATE
${BeamMP_Definitions}
)
target_compile_options(BeamMP-Server-tests PRIVATE
${BeamMP_CompileOptions}
)
target_include_directories(BeamMP-Server-tests PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/include"
)
target_include_directories(BeamMP-Server-tests SYSTEM PRIVATE
${BeamMP_Includes}
)
target_link_libraries(BeamMP-Server-tests
${BeamMP_Libraries}
${BeamMP_PlatformLibs}
)
# build debug builds by default (if not specified otherwise)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug")
endif()
if(UNIX)
# this will allow to use same _DEBUG macro available in both Linux as well as Windows - MSCV environment. Easy to put Debug specific code.
add_compile_options("$<$<CONFIG:DEBUG>:-D_DEBUG>")
endif(UNIX)
if (WIN32)
add_compile_options("-D_WIN32_WINNT=0x0601")
endif(WIN32)
include(cmake/CompilerWarnings.cmake)
# set MT library for msvc - this is required (says documentation)
# linux/mac/etc should simply ignore this by default.
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
set(PRJ_DEFINITIONS ${PRJ_DEFINITIONS}
PRJ_VERSION_MAJOR=${PROJECT_VERSION_MAJOR}
PRJ_VERSION_MINOR=${PROJECT_VERSION_MINOR}
PRJ_VERSION_PATCH=${PROJECT_VERSION_PATCH}
)
# build commandline manually for funky windows flags to carry over without a custom toolchain file
add_library(commandline_static
deps/commandline/src/impls.h
deps/commandline/src/windows_impl.cpp
deps/commandline/src/linux_impl.cpp
deps/commandline/src/backends/InteractiveBackend.cpp
deps/commandline/src/backends/InteractiveBackend.h
deps/commandline/src/backends/Backend.cpp
deps/commandline/src/backends/Backend.h
deps/commandline/src/commandline.h
deps/commandline/src/commandline.cpp
deps/commandline/src/backends/BufferedBackend.cpp
deps/commandline/src/backends/BufferedBackend.h
)
if (WIN32)
target_compile_definitions(commandline_static PRIVATE -DPLATFORM_WINDOWS=1)
else ()
target_compile_definitions(commandline_static PRIVATE -DPLATFORM_LINUX=1)
endif ()
target_include_directories(commandline_static PUBLIC "deps/commandline/src")
target_link_libraries(commandline_static Threads::Threads)
# end of commandline custom build
add_executable(${PROJECT_NAME} ${PRJ_HEADERS} ${PRJ_SOURCES} ${PRJ_MAIN})
set_target_properties(${PROJECT_NAME} PROPERTIES
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
target_include_directories(${PROJECT_NAME} PRIVATE ${PRJ_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} ${PRJ_LIBRARIES})
target_compile_features(${PROJECT_NAME} PRIVATE ${PRJ_COMPILE_FEATURES})
target_compile_definitions(${PROJECT_NAME} PRIVATE ${PRJ_DEFINITIONS} ${PRJ_WARNINGS}
DOCTEST_CONFIG_DISABLE # disables all test code in the final executable
)
if(MSVC)
target_link_options(${PROJECT_NAME} PRIVATE "/SUBSYSTEM:CONSOLE")
endif(MSVC)
# setup all warnings (from cmake/CompilerWarnings.cmake)
set_project_warnings(${PROJECT_NAME})
if(${PROJECT_NAME}_ENABLE_UNIT_TESTING)
message(STATUS "Unit tests are enabled and will be built as '${PROJECT_NAME}-tests'")
add_executable(${PROJECT_NAME}-tests ${PRJ_HEADERS} ${PRJ_SOURCES} ${PRJ_TEST_MAIN})
target_include_directories(${PROJECT_NAME}-tests PRIVATE ${PRJ_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME}-tests ${PRJ_LIBRARIES})
target_compile_features(${PROJECT_NAME}-tests PRIVATE ${PRJ_COMPILE_FEATURES})
target_compile_definitions(${PROJECT_NAME}-tests PRIVATE ${PRJ_DEFINITIONS} ${PRJ_WARNINGS})
set_project_warnings(${PROJECT_NAME}-tests)
if(MSVC)
target_link_options(${PROJECT_NAME}-tests PRIVATE "/SUBSYSTEM:CONSOLE")
endif(MSVC)
endif()

View File

@ -0,0 +1,115 @@
# from here:
#
# https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md
# Courtesy of Jason Turner
# License here: https://github.com/cpp-best-practices/cppbestpractices/blob/master/LICENSE
#
# This version has been modified by the owners of the current respository.
# Modifications have mostly been marked with "modified" or similar, though this is not
# strictly required.
function(set_project_warnings project_name)
set(MSVC_WARNINGS
/W4 # Baseline reasonable warnings
/w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss
# of data
/w14254 # 'operator': conversion from 'type1:field_bits' to
# 'type2:field_bits', possible loss of data
/w14263 # 'function': member function does not override any base class
# virtual member function
/w14265 # 'classname': class has virtual functions, but destructor is not
# virtual instances of this class may not be destructed correctly
/w14287 # 'operator': unsigned/negative constant mismatch
/we4289 # nonstandard extension used: 'variable': loop control variable
# declared in the for-loop is used outside the for-loop scope
/w14296 # 'operator': expression is always 'boolean_value'
/w14311 # 'variable': pointer truncation from 'type1' to 'type2'
/w14545 # expression before comma evaluates to a function which is missing
# an argument list
/w14546 # function call before comma missing argument list
/w14547 # 'operator': operator before comma has no effect; expected
# operator with side-effect
/w14549 # 'operator': operator before comma has no effect; did you intend
# 'operator'?
/w14555 # expression has no effect; expected expression with side- effect
/w14619 # pragma warning: there is no warning number 'number'
/w14640 # Enable warning on thread un-safe static member initialization
/w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may
# cause unexpected runtime behavior.
/w14905 # wide string literal cast to 'LPSTR'
/w14906 # string literal cast to 'LPWSTR'
/w14928 # illegal copy-initialization; more than one user-defined
# conversion has been implicitly applied
/permissive- # standards conformance mode for MSVC compiler.
)
set(CLANG_WARNINGS
-Wall
-Wextra # reasonable and standard
-Wshadow # warn the user if a variable declaration shadows one from a
# parent context
-Wnon-virtual-dtor # warn the user if a class with virtual functions has a
# non-virtual destructor. This helps catch hard to
# track down memory errors
-Wold-style-cast # warn for c-style casts
-Wcast-align # warn for potential performance problem casts
-Wunused # warn on anything being unused
-Woverloaded-virtual # warn if you overload (not override) a virtual
# function
-Wpedantic # warn if non-standard C++ is used
-Wconversion # warn on type conversions that may lose data
-Wsign-conversion # warn on sign conversions
-Wnull-dereference # warn if a null dereference is detected
-Wdouble-promotion # warn if float is implicit promoted to double
-Wformat=2 # warn on security issues around functions that format output
# (ie printf)
# modified; added more errors / warnings
# some have been set to be errors, but the option _WARNINGS_AS_ERRORS
# (see below) should still be used in strict pipelines.
-Werror=uninitialized
-Werror=float-equal
-Werror=write-strings
-Werror=strict-aliasing -fstrict-aliasing
-Werror=missing-declarations
-Werror=missing-field-initializers
-Werror=ctor-dtor-privacy
-Werror=switch-enum
-Wswitch-default
-Werror=unused-result
-Werror=implicit-fallthrough
-Werror=return-type
-Wmissing-include-dirs
)
if (${PROJECT_NAME}_WARNINGS_AS_ERRORS)
set(CLANG_WARNINGS ${CLANG_WARNINGS} -Werror)
set(MSVC_WARNINGS ${MSVC_WARNINGS} /WX)
endif()
set(GCC_WARNINGS
${CLANG_WARNINGS}
-Wmisleading-indentation # warn if indentation implies blocks where blocks
# do not exist
-Wduplicated-cond # warn if if / else chain has duplicated conditions
-Wduplicated-branches # warn if if / else branches have duplicated code
-Wlogical-op # warn about logical operations being used where bitwise were
# probably wanted
# -Wuseless-cast # warn if you perform a cast to the same type (modified: removed)
)
if(MSVC)
set(PRJ_WARNINGS ${MSVC_WARNINGS})
elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
set(PRJ_WARNINGS ${CLANG_WARNINGS})
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(PRJ_WARNINGS ${GCC_WARNINGS})
else()
message(AUTHOR_WARNING "No compiler warnings set for '${CMAKE_CXX_COMPILER_ID}' compiler.")
endif()
target_compile_options(${project_name} PUBLIC ${PRJ_WARNINGS})
if(NOT TARGET ${project_name})
message(AUTHOR_WARNING "${project_name} is not a target, thus no compiler warning were added.")
endif()
endfunction()

21
cmake/Git.cmake Normal file
View File

@ -0,0 +1,21 @@
find_package(Git)
if(${PROJECT_NAME}_CHECKOUT_GIT_SUBMODULES)
if(Git_FOUND)
message(STATUS "Git found, submodule update and init")
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE GIT_SUBMOD_RESULT)
if(NOT GIT_SUBMOD_RESULT EQUAL "0")
message(SEND_ERROR "git submodule update --init --recursive failed with ${GIT_SUBMOD_RESULT}, please checkout submodules. This may result in missing dependencies.")
endif()
else()
message(SEND_ERROR "git required for checking out submodules, but not found. Submodules will not be checked out - this may result in missing dependencies.")
endif()
endif()
if(Git_FOUND)
else()
message(STATUS "Git not found - the version will not include a git hash.")
set(PRJ_GIT_HASH "unknown")
endif()

View File

@ -0,0 +1,44 @@
# Modified, original version from https://github.com/filipdutescu/modern-cpp-template (Unlicense)
option(${PROJECT_NAME}_WARNINGS_AS_ERRORS "Treat compiler warnings as errors." OFF)
option(${PROJECT_NAME}_CHECKOUT_GIT_SUBMODULES "If git is found, initialize all submodules." ON)
option(${PROJECT_NAME}_ENABLE_UNIT_TESTING "Enable unit tests for the projects (from the `test` subfolder)." ON)
option(${PROJECT_NAME}_ENABLE_CLANG_TIDY "Enable static analysis with Clang-Tidy." OFF)
option(${PROJECT_NAME}_ENABLE_CPPCHECK "Enable static analysis with Cppcheck." OFF)
# TODO Implement code coverage
# option(${PROJECT_NAME}_ENABLE_CODE_COVERAGE "Enable code coverage through GCC." OFF)
option(${PROJECT_NAME}_ENABLE_DOXYGEN "Enable Doxygen documentation builds of source." OFF)
# Generate compile_commands.json for clang based tools
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Export all symbols when building a shared library
if(BUILD_SHARED_LIBS)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS OFF)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
endif()
option(${PROJECT_NAME}_ENABLE_LTO "Enable Interprocedural Optimization, aka Link Time Optimization (LTO)." OFF)
if(${PROJECT_NAME}_ENABLE_LTO)
include(CheckIPOSupported)
check_ipo_supported(RESULT result OUTPUT output)
if(result)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
else()
message(SEND_ERROR "IPO is not supported: ${output}.")
endif()
endif()
option(${PROJECT_NAME}_ENABLE_CCACHE "Enable the usage of Ccache, in order to speed up rebuild times." ON)
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
endif()
option(${PROJECT_NAME}_ENABLE_SANITIZER "Enable sanitizer to detect memory errors, undefined behavior, etc. (slows down the executable)." OFF)
if(${PROJECT_NAME}_ENABLE_SANITIZER)
add_compile_options(-fsanitize=address,undefined)
add_link_options(-fsanitize=address,undefined)
endif()

View File

@ -0,0 +1,20 @@
if(${PROJECT_NAME}_ENABLE_CLANG_TIDY)
find_program(CLANGTIDY clang-tidy)
if(CLANGTIDY)
set(CMAKE_CXX_CLANG_TIDY ${CLANGTIDY} -extra-arg=-Wno-unknown-warning-option)
message("Clang-Tidy finished setting up.")
else()
message(SEND_ERROR "Clang-Tidy requested but executable not found.")
endif()
endif()
if(${PROJECT_NAME}_ENABLE_CPPCHECK)
find_program(CPPCHECK cppcheck)
if(CPPCHECK)
set(CMAKE_CXX_CPPCHECK ${CPPCHECK} --suppress=missingInclude --enable=all
--inline-suppr --inconclusive)
message("Cppcheck finished setting up.")
else()
message(SEND_ERROR "Cppcheck requested but executable not found.")
endif()
endif()

17
cmake/Vcpkg.cmake Normal file
View File

@ -0,0 +1,17 @@
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
if(NOT EXISTS ${CMAKE_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake)
find_package(Git)
if(Git_FOUND)
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive vcpkg
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE GIT_SUBMOD_RESULT)
if(NOT GIT_SUBMOD_RESULT EQUAL "0")
message(SEND_ERROR "Checking out vcpkg in source tree failed with ${GIT_SUBMOD_RESULT}.")
endif()
else()
message(FATAL_ERROR "Could not find git or vcpkg.cmake. Please either, install git and re-run cmake (or run `git submodule update --init --recursive`), or install vcpkg and add `-DCMAKE_TOOLCHAIN_FILE=<path-to-vcpkg>/scripts/buildsystems/vcpkg.cmake` to your cmake invocation. Please try again after making those changes.")
endif()
endif()
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake)
endif()

6
deps/CMakeLists.txt vendored
View File

@ -1,6 +0,0 @@
include_directories("${PROJECT_SOURCE_DIR}/deps")
add_subdirectory("${PROJECT_SOURCE_DIR}/deps/commandline")
add_subdirectory("${PROJECT_SOURCE_DIR}/deps/fmt")
add_subdirectory("${PROJECT_SOURCE_DIR}/deps/sol2")
add_subdirectory("${PROJECT_SOURCE_DIR}/deps/doctest")

1
deps/asio vendored

@ -1 +0,0 @@
Subproject commit 4915cfd8a1653c157a1480162ae5601318553eb8

2
deps/commandline vendored

@ -1 +1 @@
Subproject commit 470cf2df4a6c94847b3a22868139095ae51902e6
Subproject commit 0ff46d25b16b116dcdfcc665774f5e535d217141

1
deps/cpp-httplib vendored

@ -1 +0,0 @@
Subproject commit d92c31446687cfa336a6332b1015b4fe289fbdec

1
deps/doctest vendored

@ -1 +0,0 @@
Subproject commit b7c21ec5ceeadb4951b00396fc1e4642dd347e5f

1
deps/fmt vendored

@ -1 +0,0 @@
Subproject commit c4ee726532178e556d923372f29163bd206d7732

1
deps/json vendored

@ -1 +0,0 @@
Subproject commit 69d744867f8847c91a126fa25e9a6a3d67b3be41

1
deps/libzip vendored

@ -1 +0,0 @@
Subproject commit 5532f9baa0c44cc5435ad135686a4ea009075b9a

1
deps/rapidjson vendored

@ -1 +0,0 @@
Subproject commit 00dbcf2c6e03c47d6c399338b6de060c71356464

1
deps/sentry-native vendored

@ -1 +0,0 @@
Subproject commit 28be51f5e3acb01327b1164206d3145464577670

1
deps/sol2 vendored

@ -1 +0,0 @@
Subproject commit eba86625b707e3c8c99bbfc4624e51f42dc9e561

1
deps/toml11 vendored

@ -1 +0,0 @@
Subproject commit c7627ff6a1eb6f34fbd98369990a9442e2836c25

View File

@ -1,8 +1,5 @@
#pragma once
#include "TSentry.h"
extern TSentry Sentry;
#include <array>
#include <atomic>
#include <cstring>
@ -138,7 +135,7 @@ private:
static inline std::mutex mShutdownHandlersMutex {};
static inline std::deque<TShutdownHandler> mShutdownHandlers {};
static inline Version mVersion { 3, 1, 1 };
static inline Version mVersion { 3, 1, 2 };
};
std::string ThreadName(bool DebugModeOverride = false);
@ -193,7 +190,6 @@ void RegisterThread(const std::string& str);
#define beammp_error(x) \
do { \
Application::Console().Write(_this_location + std::string("[ERROR] ") + (x)); \
Sentry.AddErrorBreadcrumb((x), _file_basename, _line); \
} while (false)
#define beammp_lua_error(x) \
do { \

View File

@ -63,12 +63,10 @@ inline void _assert([[maybe_unused]] const char* file, [[maybe_unused]] const ch
bool result = (cond); \
if (!result) { \
beammp_errorf("Assertion failed in '{}:{}': {}.", __func__, _line, #cond); \
Sentry.LogAssert(#cond, _file_basename, _line, __func__); \
} \
} while (false)
#define beammp_assert_not_reachable() \
do { \
beammp_errorf("Assertion failed in '{}:{}': Unreachable code reached. This may result in a crash or undefined state of the program.", __func__, _line); \
Sentry.LogAssert("code is unreachable", _file_basename, _line, __func__); \
} while (false)
#endif // DEBUG

View File

@ -8,7 +8,7 @@ public:
IThreaded()
// invokes operator() on this object
: mThread() { }
~IThreaded() noexcept {
virtual ~IThreaded() noexcept {
if (mThread.joinable()) {
mThread.join();
}

View File

@ -6,7 +6,7 @@
#include <filesystem>
#define TOML11_PRESERVE_COMMENTS_BY_DEFAULT
#include <toml11/toml.hpp> // header-only version of TOML++
#include <toml.hpp> // header-only version of TOML++
namespace fs = std::filesystem;

View File

@ -5,6 +5,7 @@
#include <atomic>
#include <fstream>
#include <functional>
#include <mutex>
#include <string>
#include <tuple>
#include <unordered_map>

View File

@ -13,7 +13,7 @@
#include <queue>
#include <random>
#include <set>
#include <toml11/toml.hpp>
#include <toml.hpp>
#include <unordered_map>
#include <vector>

View File

@ -9,6 +9,7 @@ class TNetwork;
class TPPSMonitor : public IThreaded {
public:
explicit TPPSMonitor(TServer& Server);
virtual ~TPPSMonitor() {}
void operator()() override;

View File

@ -1,38 +0,0 @@
#ifndef SENTRY_H
#define SENTRY_H
#include <mutex>
#include <string>
#include <unordered_map>
enum class SentryLevel {
Debug = -1,
Info = 0,
Warning = 1,
Error = 2,
Fatal = 3,
};
// singleton, dont make this twice
class TSentry final {
public:
TSentry();
~TSentry();
void PrintWelcome();
void SetupUser();
void Log(SentryLevel level, const std::string& logger, const std::string& text);
void LogError(const std::string& text, const std::string& file, const std::string& line);
void SetContext(const std::string& context_name, const std::unordered_map<std::string, std::string>& map);
void LogException(const std::exception& e, const std::string& file, const std::string& line);
void LogAssert(const std::string& condition_string, const std::string& file, const std::string& line, const std::string& function);
void AddErrorBreadcrumb(const std::string& msg, const std::string& file, const std::string& line);
// cleared when Logged
void SetTransaction(const std::string& id);
[[nodiscard]] std::unique_lock<std::mutex> CreateExclusiveContext();
private:
bool mValid { true };
std::mutex mMutex;
};
#endif // SENTRY_H

View File

@ -0,0 +1,7 @@
#!/bin/bash
set -ex
apt-get update -y
apt-get install -y liblua5.3-0 liblua5.3-dev curl zip unzip tar cmake make git g++

View File

@ -0,0 +1,7 @@
#!/bin/bash
set -ex
git config --global --add safe.directory $(pwd)
git config --global --add safe.directory $(pwd)/vcpkg
git config --global --add safe.directory $(pwd)/deps/commandline

View File

@ -0,0 +1,5 @@
#!/bin/bash
set -ex
cmake . -B bin $1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-O3 -s -Wl,-z,norelro -Wl,--hash-style=gnu -Wl,--build-id=none -Wl,-z,noseparate-code -ffunction-sections -fdata-sections -Wl,--gc-sections" -DBeamMP-Server_ENABLE_LTO=ON

View File

@ -0,0 +1,5 @@
#!/bin/bash
set -ex
cmake --build bin --parallel -t BeamMP-Server-tests

5
scripts/debian-11/3-build.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
set -ex
cmake --build bin --parallel -t BeamMP-Server

View File

@ -0,0 +1,8 @@
#!/bin/bash
set -ex
apt-get update -y
apt-get install -y liblua5.3-0 curl

View File

@ -0,0 +1,7 @@
#!/bin/bash
set -ex
apt-get update -y
apt-get install -y liblua5.3-0 liblua5.3-dev curl zip unzip tar cmake make git g++

View File

@ -0,0 +1,7 @@
#!/bin/bash
set -ex
git config --global --add safe.directory $(pwd)
git config --global --add safe.directory $(pwd)/vcpkg
git config --global --add safe.directory $(pwd)/deps/commandline

View File

@ -0,0 +1,5 @@
#!/bin/bash
set -ex
cmake . -B bin $1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-O3 -s -Wl,-z,norelro -Wl,--hash-style=gnu -Wl,--build-id=none -Wl,-z,noseparate-code -ffunction-sections -fdata-sections -Wl,--gc-sections" -DBeamMP-Server_ENABLE_LTO=ON

View File

@ -0,0 +1,5 @@
#!/bin/bash
set -ex
cmake --build bin --parallel -t BeamMP-Server-tests

View File

@ -0,0 +1,5 @@
#!/bin/bash
set -ex
cmake --build bin --parallel -t BeamMP-Server

View File

@ -0,0 +1,8 @@
#!/bin/bash
set -ex
apt-get update -y
apt-get install -y liblua5.3-0 curl

View File

@ -0,0 +1,5 @@
#!/bin/bash
set -ex
cmake . -B bin $1 -DCMAKE_BUILD_TYPE=Release -DBeamMP-Server_ENABLE_LTO=ON -DVCPKG_TARGET_TRIPLET=x64-windows-static

View File

@ -0,0 +1,5 @@
#!/bin/bash
set -ex
cmake --build bin --parallel -t BeamMP-Server-tests

5
scripts/windows/2-build.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
set -ex
cmake --build bin --parallel -t BeamMP-Server

View File

@ -51,7 +51,7 @@ TClient::TVehicleDataLockPair TClient::GetAllCars() {
std::string TClient::GetCarPositionRaw(int Ident) {
std::unique_lock lock(mVehiclePositionMutex);
try {
return mVehiclePosition.at(Ident);
return mVehiclePosition.at(size_t(Ident));
} catch (const std::out_of_range& oor) {
return "";
}
@ -73,7 +73,7 @@ void TClient::Disconnect(std::string_view Reason) {
void TClient::SetCarPosition(int Ident, const std::string& Data) {
std::unique_lock lock(mVehiclePositionMutex);
mVehiclePosition[Ident] = Data;
mVehiclePosition[size_t(Ident)] = Data;
}
std::string TClient::GetCarData(int Ident) {

View File

@ -13,9 +13,6 @@
#include "CustomAssert.h"
#include "Http.h"
// global, yes, this is ugly, no, it cant be done another way
TSentry Sentry {};
Application::TSettings Application::Settings = {};
void Application::RegisterShutdownHandler(const TShutdownHandler& Handler) {
@ -217,9 +214,6 @@ void Application::CheckForUpdates() {
if (FirstTime) {
beammp_debug("Failed to fetch version from: " + url);
beammp_trace("got " + Response);
auto Lock = Sentry.CreateExclusiveContext();
Sentry.SetContext("get-response", { { "response", Response } });
Sentry.LogError("failed to get server version", _file_basename, _line);
Application::SetSubsystemStatus("UpdateCheck", Application::Status::Bad);
}
}

View File

@ -8,6 +8,7 @@
#include "TLuaEngine.h"
#include <ctime>
#include <mutex>
#include <sstream>
static inline bool StringStartsWith(const std::string& What, const std::string& StartsWith) {
@ -353,7 +354,6 @@ void TConsole::Command_Settings(const std::string&, const std::vector<std::strin
if (!EnsureArgsCount(args, 1, 2)) {
return;
}
}
void TConsole::Command_Say(const std::string& FullCmd) {

View File

@ -40,16 +40,6 @@ void THeartbeatThread::operator()() {
Body += "&ip=" + Application::Settings.CustomIP;
}
auto SentryReportError = [&](const std::string& transaction, int status) {
auto Lock = Sentry.CreateExclusiveContext();
Sentry.SetContext("heartbeat",
{ { "response-body", T },
{ "request-body", Body } });
Sentry.SetTransaction(transaction);
beammp_trace("sending log to sentry: " + std::to_string(status) + " for " + transaction);
Sentry.Log(SentryLevel::Error, "default", Http::Status::ToString(status) + " (" + std::to_string(status) + ")");
};
auto Target = "/heartbeat";
unsigned int ResponseCode = 0;
@ -63,10 +53,8 @@ void THeartbeatThread::operator()() {
beammp_trace("Backend response failed to parse as valid json");
beammp_trace("Response was: `" + T + "`");
}
Sentry.SetContext("JSON Response", { { "reponse", T } });
SentryReportError(Url + Target, ResponseCode);
} else if (ResponseCode != 200) {
SentryReportError(Url + Target, ResponseCode);
beammp_errorf("Response code from the heartbeat: {}", ResponseCode);
} else {
// all ok
Ok = true;
@ -85,24 +73,20 @@ void THeartbeatThread::operator()() {
if (Doc.HasMember(StatusKey) && Doc[StatusKey].IsString()) {
Status = Doc[StatusKey].GetString();
} else {
Sentry.SetContext("JSON Response", { { StatusKey, "invalid string / missing" } });
Ok = false;
}
if (Doc.HasMember(CodeKey) && Doc[CodeKey].IsString()) {
Code = Doc[CodeKey].GetString();
} else {
Sentry.SetContext("JSON Response", { { CodeKey, "invalid string / missing" } });
Ok = false;
}
if (Doc.HasMember(MessageKey) && Doc[MessageKey].IsString()) {
Message = Doc[MessageKey].GetString();
} else {
Sentry.SetContext("JSON Response", { { MessageKey, "invalid string / missing" } });
Ok = false;
}
if (!Ok) {
beammp_error("Missing/invalid json members in backend response");
Sentry.LogError("Missing/invalid json members in backend response", __FILE__, std::to_string(__LINE__));
}
} else {
if (!Application::Settings.Private) {

View File

@ -153,7 +153,6 @@ void TNetwork::TCPServerMain() {
if (ec) {
beammp_errorf("failed to accept: {}", ec.message());
}
ClientSocket.set_option(rcv_timeout_option{ 120000 }); //timeout of 120seconds
TConnection Conn { std::move(ClientSocket), ClientEp };
std::thread ID(&TNetwork::Identify, this, std::move(Conn));
ID.detach(); // TODO: Add to a queue and attempt to join periodically
@ -180,16 +179,29 @@ void TNetwork::Identify(TConnection&& RawConnection) {
return;
}
std::shared_ptr<TClient> Client { nullptr };
if (Code == 'C') {
Client = Authentication(std::move(RawConnection));
} else if (Code == 'D') {
HandleDownload(std::move(RawConnection));
} else if (Code == 'P') {
try {
if (Code == 'C') {
Client = Authentication(std::move(RawConnection));
} else if (Code == 'D') {
HandleDownload(std::move(RawConnection));
} else if (Code == 'P') {
boost::system::error_code ec;
write(RawConnection.Socket, buffer("P"), ec);
return;
} else {
beammp_errorf("Invalid code got in Identify: '{}'", Code);
}
} catch(const std::exception& e) {
beammp_errorf("Error during handling of code {} - client left in invalid state, closing socket", Code);
boost::system::error_code ec;
write(RawConnection.Socket, buffer("P"), ec);
return;
} else {
beammp_errorf("Invalid code got in Identify: '{}'", Code);
RawConnection.Socket.shutdown(socket_base::shutdown_both, ec);
if (ec) {
beammp_debugf("Failed to shutdown client socket: {}", ec.message());
}
RawConnection.Socket.close(ec);
if (ec) {
beammp_debugf("Failed to close client socket: {}", ec.message());
}
}
}
@ -259,12 +271,24 @@ std::shared_ptr<TClient> TNetwork::Authentication(TConnection&& RawConnection) {
return nullptr;
}
nlohmann::json AuthReq {
{ "key", std::string(reinterpret_cast<const char*>(Data.data()), Data.size()) }
};
auto Target = "/pkToUser";
unsigned int ResponseCode = 0;
const auto AuthResStr = Http::POST(Application::GetBackendUrlForAuth(), 443, Target, AuthReq.dump(), "application/json", &ResponseCode);
std::string key(reinterpret_cast<const char*>(Data.data()), Data.size());
nlohmann::json AuthReq{};
std::string AuthResStr{};
try {
AuthReq = nlohmann::json {
{ "key", key }
};
auto Target = "/pkToUser";
unsigned int ResponseCode = 0;
AuthResStr = Http::POST(Application::GetBackendUrlForAuth(), 443, Target, AuthReq.dump(), "application/json", &ResponseCode);
} catch (const std::exception& e) {
beammp_debugf("Invalid json sent by client, kicking: {}", e.what());
ClientKick(*Client, "Invalid Key (invalid UTF8 string)!");
return nullptr;
}
try {
nlohmann::json AuthRes = nlohmann::json::parse(AuthResStr);

View File

@ -1,138 +0,0 @@
#include "TSentry.h"
#include "Common.h"
#include <cstring>
#include <sentry.h>
#include <sstream>
TSentry::TSentry() {
if (std::strlen(S_DSN) == /* DISABLES CODE */ (0)) {
mValid = false;
} else {
mValid = true;
sentry_options_t* options = sentry_options_new();
sentry_options_set_dsn(options, S_DSN);
auto ReleaseString = "BeamMP-Server@" + Application::ServerVersionString();
sentry_options_set_symbolize_stacktraces(options, true);
sentry_options_set_release(options, ReleaseString.c_str());
sentry_options_set_max_breadcrumbs(options, 10);
sentry_init(options);
}
}
TSentry::~TSentry() {
if (mValid) {
sentry_close();
}
}
void TSentry::PrintWelcome() {
if (mValid) {
if (!Application::Settings.SendErrors) {
mValid = false;
if (Application::Settings.SendErrorsMessageEnabled) {
beammp_info("Opted out of error reporting (SendErrors), Sentry disabled.");
} else {
beammp_info("Sentry disabled");
}
} else {
if (Application::Settings.SendErrorsMessageEnabled) {
beammp_info("Sentry started! Reporting errors automatically. This sends data to the developers in case of errors and crashes. You can learn more, turn this message off or opt-out of this in the ServerConfig.toml.");
} else {
beammp_info("Sentry started");
}
}
} else {
if (Application::Settings.SendErrorsMessageEnabled) {
beammp_info("Sentry disabled in unofficial build. Automatic error reporting disabled.");
} else {
beammp_info("Sentry disabled in unofficial build");
}
}
}
void TSentry::SetupUser() {
if (!mValid) {
return;
}
Application::SetSubsystemStatus("Sentry", Application::Status::Good);
sentry_value_t user = sentry_value_new_object();
if (Application::Settings.Key.size() == 36) {
sentry_value_set_by_key(user, "id", sentry_value_new_string(Application::Settings.Key.c_str()));
} else {
sentry_value_set_by_key(user, "id", sentry_value_new_string("unauthenticated"));
}
sentry_set_user(user);
}
void TSentry::Log(SentryLevel level, const std::string& logger, const std::string& text) {
if (!mValid) {
return;
}
SetContext("threads", { { "thread-name", ThreadName(true) } });
auto Msg = sentry_value_new_message_event(sentry_level_t(level), logger.c_str(), text.c_str());
sentry_capture_event(Msg);
sentry_set_transaction(nullptr);
}
void TSentry::LogError(const std::string& text, const std::string& file, const std::string& line) {
if (!mValid) {
return;
}
SetTransaction(file + ":" + line);
Log(SentryLevel::Error, "default", file + ": " + text);
}
void TSentry::SetContext(const std::string& context_name, const std::unordered_map<std::string, std::string>& map) {
if (!mValid) {
return;
}
auto ctx = sentry_value_new_object();
for (const auto& pair : map) {
std::string key = pair.first;
if (key == "type") {
// `type` is reserved
key = "_type";
}
sentry_value_set_by_key(ctx, key.c_str(), sentry_value_new_string(pair.second.c_str()));
}
sentry_set_context(context_name.c_str(), ctx);
}
void TSentry::LogException(const std::exception& e, const std::string& file, const std::string& line) {
if (!mValid) {
return;
}
SetTransaction(file + ":" + line);
Log(SentryLevel::Fatal, "exceptions", std::string(e.what()) + " @ " + file + ":" + line);
}
void TSentry::LogAssert(const std::string& condition_string, const std::string& file, const std::string& line, const std::string& function) {
if (!mValid) {
return;
}
SetTransaction(file + ":" + line + ":" + function);
std::stringstream ss;
ss << "\"" << condition_string << "\" failed @ " << file << ":" << line;
Log(SentryLevel::Fatal, "asserts", ss.str());
}
void TSentry::AddErrorBreadcrumb(const std::string& msg, const std::string& file, const std::string& line) {
if (!mValid) {
return;
}
auto crumb = sentry_value_new_breadcrumb("default", (msg + " @ " + file + ":" + line).c_str());
sentry_value_set_by_key(crumb, "level", sentry_value_new_string("error"));
sentry_add_breadcrumb(crumb);
}
void TSentry::SetTransaction(const std::string& id) {
if (!mValid) {
return;
}
sentry_set_transaction(id.c_str());
}
std::unique_lock<std::mutex> TSentry::CreateExclusiveContext() {
return std::unique_lock<std::mutex>(mMutex);
}

View File

@ -382,23 +382,13 @@ void TServer::Apply(TClient& c, int VID, const std::string& pckt) {
std::string VD = c.GetCarData(VID);
if (VD.empty()) {
beammp_error("Tried to apply change to vehicle that does not exist");
auto Lock = Sentry.CreateExclusiveContext();
Sentry.SetContext("vehicle-change",
{ { "packet", Packet },
{ "vehicle-id", std::to_string(VID) },
{ "client-car-count", std::to_string(c.GetCarCount()) } });
Sentry.LogError("attempt to apply change to nonexistent vehicle", _file_basename, _line);
return;
}
std::string Header = VD.substr(0, VD.find('{'));
FoundPos = VD.find('{');
if (FoundPos == std::string::npos) {
auto Lock = Sentry.CreateExclusiveContext();
Sentry.SetContext("vehicle-change-packet",
{ { "packet", VD } });
Sentry.LogError("malformed packet", _file_basename, _line);
return;
return;
}
VD = VD.substr(FoundPos);
rapidjson::Document Veh, Pack;

View File

@ -1,5 +1,3 @@
#include "TSentry.h"
#include "ArgsParser.h"
#include "Common.h"
#include "Http.h"
@ -64,7 +62,6 @@ int main(int argc, char** argv) {
} catch (const std::exception& e) {
beammp_error("A fatal exception has occurred and the server is forcefully shutting down.");
beammp_error(e.what());
Sentry.LogException(e, _file_basename, _line);
MainRet = -1;
}
std::exit(MainRet);
@ -148,8 +145,6 @@ int BeamMPServerMain(MainArguments Arguments) {
RegisterThread("Main");
beammp_trace("Running in debug mode on a debug build");
Sentry.SetupUser();
Sentry.PrintWelcome();
TResourceManager ResourceManager;
TPPSMonitor PPSMonitor(Server);
THeartbeatThread Heartbeat(ResourceManager, Server);

1
vcpkg Submodule

@ -0,0 +1 @@
Subproject commit 72010900b7cee36cea77aebb97695095c9358eaf

19
vcpkg.json Normal file
View File

@ -0,0 +1,19 @@
{
"name": "server",
"version-string": "0.1.0",
"dependencies": [
"fmt",
"doctest",
"boost-asio",
"boost-variant",
"boost-spirit",
"boost-uuid",
"cpp-httplib",
"toml11",
"libzip",
"rapidjson",
"nlohmann-json",
"openssl",
"sol2"
]
}