Merge pull request #8334 from Robyt3/Android-Building-Fix

Fix the Android build and improve the Android building `README.md`
This commit is contained in:
heinrich5991 2024-05-22 21:19:40 +00:00 committed by GitHub
commit 848f4a846b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 305 additions and 166 deletions

3
.gitignore vendored
View file

@ -43,6 +43,9 @@ testrunner\[1\]_include.cmake
/SDL2.framework /SDL2.framework
# Android
local.properties
# Ignore all the generated executables without extensions (for non-Windows # Ignore all the generated executables without extensions (for non-Windows
# systems). # systems).
DDNet DDNet

View file

@ -870,9 +870,15 @@ set_glob(RUST_MASTERSRV GLOB "rs;toml" src/mastersrv/src
add_library(rust-bridge-shared EXCLUDE_FROM_ALL OBJECT ${RUST_BRIDGE_SHARED}) add_library(rust-bridge-shared EXCLUDE_FROM_ALL OBJECT ${RUST_BRIDGE_SHARED})
list(APPEND TARGETS_OWN rust-bridge-shared) list(APPEND TARGETS_OWN rust-bridge-shared)
if(TARGET_OS STREQUAL "android")
set(CARGO_BUILD_DIR "${CARGO_NDK_TARGET}/")
set(CARGO_BUILD ${CMAKE_COMMAND} -E env CARGO_TARGET_DIR=${PROJECT_BINARY_DIR} DDNET_TEST_NO_LINK=1 ${RUST_CARGO} ndk -t ${CARGO_NDK_TARGET} -p ${CARGO_NDK_API} build)
set(CARGO_TEST ${CMAKE_COMMAND} -E env CARGO_TARGET_DIR=${PROJECT_BINARY_DIR} ${RUST_CARGO} ndk -t ${CARGO_NDK_TARGET} -p ${CARGO_NDK_API} test)
else()
set(CARGO_BUILD_DIR "") set(CARGO_BUILD_DIR "")
set(CARGO_BUILD ${CMAKE_COMMAND} -E env CARGO_TARGET_DIR=${PROJECT_BINARY_DIR} DDNET_TEST_NO_LINK=1 ${RUST_CARGO} build) set(CARGO_BUILD ${CMAKE_COMMAND} -E env CARGO_TARGET_DIR=${PROJECT_BINARY_DIR} DDNET_TEST_NO_LINK=1 ${RUST_CARGO} build)
set(CARGO_TEST ${CMAKE_COMMAND} -E env CARGO_TARGET_DIR=${PROJECT_BINARY_DIR} ${RUST_CARGO} test) set(CARGO_TEST ${CMAKE_COMMAND} -E env CARGO_TARGET_DIR=${PROJECT_BINARY_DIR} ${RUST_CARGO} test)
endif()
if(MSVC) if(MSVC)
list(INSERT CARGO_BUILD 0 ${CMAKE_COMMAND} -E env $<$<CONFIG:Debug>:CFLAGS=/MTd> $<$<CONFIG:Debug>:CXXFLAGS=/MTd>) list(INSERT CARGO_BUILD 0 ${CMAKE_COMMAND} -E env $<$<CONFIG:Debug>:CFLAGS=/MTd> $<$<CONFIG:Debug>:CXXFLAGS=/MTd>)
list(INSERT CARGO_TEST 0 ${CMAKE_COMMAND} -E env RUSTFLAGS=-Ctarget-feature=+crt-static) list(INSERT CARGO_TEST 0 ${CMAKE_COMMAND} -E env RUSTFLAGS=-Ctarget-feature=+crt-static)

View file

@ -1,53 +1,145 @@
Requirements for building: Requirements for building for Android
========================== =====================================
- Android NDK (tested with NDK 23), must be in the same location in which Android studio would unpack it (~/Android/Sdk/ndk/)
at least version 23
- Android SDK build tools
version 30.0.3
- ddnet-libs with Android libs
- Java -- JDK 11+
- 7zip (for ddnet-libs building)
- ninja
- curl runtime
How to build: - At least 10-15 GiB of free disk space.
============= - First follow the general instructions for setting up https://github.com/ddnet/ddnet for building on Linux.
- run a terminal inside the source directory: This guide has only been tested on Linux.
`scripts/android/cmake_android.sh <x86/x86_64/arm/arm64/all> <Game name> <Debug/Release>` - Install the Android NDK (version 26) in the same location
where the first parameter is the arch (all for all arches), the second is the apk name, which must be equal to the library name (if you want to rename the APK do it after the build) where Android Studio would unpack it (`~/Android/Sdk/ndk/`):
and the third parameter which simply defines the build type ```shell
mkdir ~/Android
- if you build with a signing key for the APK cd ~/Android
Generate one with mkdir Sdk
`keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias` cd Sdk
export environment variables for the script mkdir ndk
cd ndk
wget https://dl.google.com/android/repository/android-ndk-r26d-linux.zip
unzip android-ndk-r26d-linux.zip
unlink android-ndk-r26d-linux.zip
``` ```
- Install the Android SDK build tools (version 30.0.3) in the same location
where Android Studio would unpack them (`~/Android/Sdk/build-tools/`):
```shell
# Assuming you already created the Android/Sdk folders in the previous step
cd ~/Android/Sdk
mkdir build-tools
cd build-tools
wget https://dl.google.com/android/repository/build-tools_r30.0.3-linux.zip
unzip build-tools_r30.0.3-linux.zip
unlink build-tools_r30.0.3-linux.zip
mv android-11 30.0.3
```
- Install the Android command-line tools and accept the licenses using the SDK manager,
otherwise the Gradle build will fail if the licenses have not been accepted:
```shell
# Assuming you already created the Android/Sdk folders in the previous step
cd ~/Android/Sdk
mkdir cmdline-tools
cd cmdline-tools
wget https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip
unzip commandlinetools-linux-11076708_latest.zip
unlink commandlinetools-linux-11076708_latest.zip
mv cmdline-tools latest
yes | latest/bin/sdkmanager --licenses
```
- Install cargo-ndk and add Android targets to rustup to build Rust with the Android NDK:
```shell
cargo install cargo-ndk
rustup target add armv7-linux-androideabi
rustup target add i686-linux-android
rustup target add aarch64-linux-android
rustup target add x86_64-linux-android
```
- Install OpenJDK 21:
```shell
sudo apt install openjdk-21-jdk
```
- Install 7zip for building `ddnet-libs`:
```shell
sudo apt install p7zip-full
```
- Install ninja:
```shell
sudo apt install ninja-build
```
- Install curl:
```shell
sudo apt install curl
```
- *(macOS only)* Install coreutils so `nproc` is available:
```shell
brew install coreutils
```
- Build the `ddnet-libs` for Android (see below). Follow all above steps first.
How to build the `ddnet-libs` for Android
=========================================
- There is a script to automatically download and build all repositories,
this requires an active internet connection and can take around 30 minutes:
```shell
mkdir build-android-libs
scripts/compile_libs/gen_libs.sh build-android-libs android
```
**Warning**: Do not choose a directory inside the `src` folder!
- If you see several red error messages in the first few minutes,
abort the compilation with repeated Ctrl+C presses.
Examine the output and ensure that you installed the NDK to the correct location.
- After the script finished executing, it should have created a `ddnet-libs` directory
in your selected output folder, which contains all libraries in the correct directory
format and can be merged with the `ddnet-libs` folder in the source directory:
```shell
cp -r build-android-libs/ddnet-libs/. ddnet-libs/
```
How to build the DDNet client for Android
=========================================
- Open a terminal inside the `ddnet` project root directory and run the following:
```shell
scripts/android/cmake_android.sh <x86/x86_64/arm/arm64/all> <Game name> <Package name> <Debug/Release> <Build folder>
```
- The first parameter denotes the architecture.
Use `all` to compile for all architectures.
Note that all architectures will be compiled in parallel.
For testing, only compile for one architecture initially to get readable output.
- The second parameter denotes the APK name, which must be equal to the library name.
If you want to rename the APK, do it after the build.
- The third parameter denotes the package name of the APK.
- The fourth parameter denotes the build type.
- The fifth parameter denotes the build folder.
- Example to build only for `x86_64` architecture in debug mode:
```shell
scripts/android/cmake_android.sh x86_64 DDNet org.ddnet.client Debug build-android-debug
```
- To build a signed APK, generate a signing key and export environment variables before running the build script:
```shell
keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias
export TW_KEY_NAME=<key name> export TW_KEY_NAME=<key name>
export TW_KEY_PW=<key password> export TW_KEY_PW=<key password>
export TW_KEY_ALIAS=<key alias> export TW_KEY_ALIAS=<key alias>
``` ```
so for example: - By default, the version code and name of the APK will be determined automatically
``` based on the definitions in `src/game/version.h`.
keytool -genkey -v -keystore Teeworlds.jks -keyalg RSA -keysize 2048 -validity 10000 -alias Teeworlds-Key You can also specify the build version code and name manually before running the build script, e.g.:
(it will prompt an input:) ```shell
Input keystore-password: mypassword
export TW_KEY_NAME=Teeworlds.jks
export TW_KEY_PW=mypassword
export TW_KEY_ALIAS=Teeworlds-Key
scripts/android/cmake_android.sh all DDNet Release
```
You can also specify the build version code and build version string before running the build script, e.g.:
```
export TW_VERSION_CODE=20210819 export TW_VERSION_CODE=20210819
export TW_VERSION_NAME="1.0" export TW_VERSION_NAME="1.0"
``` ```
The version code must increase for newer version in order for users to automatically update to them.
How to build the ddnet-libs for Android: The version name is the string that will be displayed to the user, e.g. `1.2.3-snapshot4`.
======================================== - Example to build a signed APK in release mode for all architectures:
- There is a script to automatically download and build all repositories, this requires an active internet connection: ```shell
`scripts/compile_libs/gen_libs.sh <directory to build in> android` keytool -genkey -v -keystore Teeworlds.jks -keyalg RSA -keysize 2048 -validity 10000 -alias Teeworlds-Key
Warning!: DO NOT CHOOSE A DIRECTORY INSIDE THE SOURCE TREE # It will prompt for the password, input for example "mypassword"
export TW_KEY_NAME=Teeworlds.jks
After the script finished executing it should have created a ddnet-libs directory which created all libs in the right directory format and can be merged with ddnet-libs in the source directory export TW_KEY_PW=mypassword
export TW_KEY_ALIAS=Teeworlds-Key
# Version code and name will be determined automatically
scripts/android/cmake_android.sh all DDNet org.ddnet.client Release build-android-release
```
- Note that you should only generate a signing key once (and make backups).
Users can only update apps automatically if the same package name and signing key have been used,
else they must manually uninstall the old app.

View file

@ -1,17 +1,23 @@
#!/bin/bash #!/bin/bash
export ANDROID_HOME=~/Android/Sdk # $HOME must be used instead of ~ else cargo-ndk cannot find the folder
export MAKEFLAGS=-j32 export ANDROID_HOME=$HOME/Android/Sdk
MAKEFLAGS=-j$(nproc)
export MAKEFLAGS
ANDROID_NDK_VERSION="$(cd "$ANDROID_HOME/ndk" && find . -maxdepth 1 | sort -n | tail -1)" ANDROID_NDK_VERSION="$(cd "$ANDROID_HOME/ndk" && find . -maxdepth 1 | sort -n | tail -1)"
ANDROID_NDK_VERSION="${ANDROID_NDK_VERSION:2}" ANDROID_NDK_VERSION="${ANDROID_NDK_VERSION:2}"
# ANDROID_NDK_VERSION must be exported for build.sh step
export ANDROID_NDK_VERSION export ANDROID_NDK_VERSION
ANDROID_NDK="$ANDROID_HOME/ndk/$ANDROID_NDK_VERSION" # ANDROID_NDK_HOME must be exported for cargo-ndk
export ANDROID_NDK_HOME="$ANDROID_HOME/ndk/$ANDROID_NDK_VERSION"
_DEFAULT_ANDROID_BUILD=x86 _DEFAULT_ANDROID_BUILD=x86
_DEFAULT_GAME_NAME=DDNet _DEFAULT_GAME_NAME=DDNet
_DEFAULT_PACKAGE_NAME=org.ddnet.client
_DEFAULT_BUILD_TYPE=Debug _DEFAULT_BUILD_TYPE=Debug
_ANDROID_API_LEVEL=android-24 _DEFAULT_BUILD_FOLDER=build-android
_ANDROID_API_LEVEL=34
_ANDROID_SUB_BUILD_DIR=build_arch _ANDROID_SUB_BUILD_DIR=build_arch
@ -32,10 +38,24 @@ else
fi fi
if [ -z ${3+x} ]; then if [ -z ${3+x} ]; then
printf "\e[31m%s\e[30m\n" "Did not pass package name, using default: ${_DEFAULT_PACKAGE_NAME}"
_SHOW_USAGE_INFO=1
else
_DEFAULT_PACKAGE_NAME=$3
fi
if [ -z ${4+x} ]; then
printf "\e[31m%s\e[30m\n" "Did not pass build type, using default: ${_DEFAULT_BUILD_TYPE}" printf "\e[31m%s\e[30m\n" "Did not pass build type, using default: ${_DEFAULT_BUILD_TYPE}"
_SHOW_USAGE_INFO=1 _SHOW_USAGE_INFO=1
else else
_DEFAULT_BUILD_TYPE=$3 _DEFAULT_BUILD_TYPE=$4
fi
if [ -z ${5+x} ]; then
printf "\e[31m%s\e[30m\n" "Did not pass build folder, using default: ${_DEFAULT_BUILD_FOLDER}"
_SHOW_USAGE_INFO=1
else
_DEFAULT_BUILD_FOLDER=$5
fi fi
_ANDROID_JAR_KEY_NAME=~/.android/debug.keystore _ANDROID_JAR_KEY_NAME=~/.android/debug.keystore
@ -64,6 +84,10 @@ export TW_KEY_ALIAS=$_ANDROID_JAR_KEY_ALIAS
_ANDROID_VERSION_CODE=1 _ANDROID_VERSION_CODE=1
if [ -z ${TW_VERSION_CODE+x} ]; then if [ -z ${TW_VERSION_CODE+x} ]; then
_ANDROID_VERSION_CODE=$(grep '#define DDNET_VERSION_NUMBER' src/game/version.h | awk '{print $3}')
if [ -z ${_ANDROID_VERSION_CODE+x} ]; then
_ANDROID_VERSION_CODE=1
fi
printf "\e[31m%s\e[30m\n" "Did not pass a version code, using default: ${_ANDROID_VERSION_CODE}" printf "\e[31m%s\e[30m\n" "Did not pass a version code, using default: ${_ANDROID_VERSION_CODE}"
else else
_ANDROID_VERSION_CODE=$TW_VERSION_CODE _ANDROID_VERSION_CODE=$TW_VERSION_CODE
@ -73,6 +97,10 @@ export TW_VERSION_CODE=$_ANDROID_VERSION_CODE
_ANDROID_VERSION_NAME="1.0" _ANDROID_VERSION_NAME="1.0"
if [ -z ${TW_VERSION_NAME+x} ]; then if [ -z ${TW_VERSION_NAME+x} ]; then
_ANDROID_VERSION_NAME="$(grep '#define GAME_RELEASE_VERSION' src/game/version.h | awk '{print $3}' | tr -d '"')"
if [ -z ${_ANDROID_VERSION_NAME+x} ]; then
_ANDROID_VERSION_NAME="1.0"
fi
printf "\e[31m%s\e[30m\n" "Did not pass a version name, using default: ${_ANDROID_VERSION_NAME}" printf "\e[31m%s\e[30m\n" "Did not pass a version name, using default: ${_ANDROID_VERSION_NAME}"
else else
_ANDROID_VERSION_NAME=$TW_VERSION_NAME _ANDROID_VERSION_NAME=$TW_VERSION_NAME
@ -80,10 +108,10 @@ fi
export TW_VERSION_NAME=$_ANDROID_VERSION_NAME export TW_VERSION_NAME=$_ANDROID_VERSION_NAME
printf "\e[31m%s\e[1m\n" "Building with setting, for arch: ${_DEFAULT_ANDROID_BUILD}, with build type: ${_DEFAULT_BUILD_TYPE}, with name: ${_DEFAULT_GAME_NAME}" printf "\e[31m%s\e[1m\n" "Building with setting, for arch: ${_DEFAULT_ANDROID_BUILD}, with build type: ${_DEFAULT_BUILD_TYPE}, with name: ${_DEFAULT_GAME_NAME} (${_DEFAULT_PACKAGE_NAME})"
if [ $_SHOW_USAGE_INFO == 1 ]; then if [ $_SHOW_USAGE_INFO == 1 ]; then
printf "\e[31m%s\e[1m\n" "Usage: ./cmake_android.sh <x86/x86_64/arm/arm64/all> <Game name> <Debug/Release>" printf "\e[31m%s\e[1m\n" "Usage: ./cmake_android.sh <x86/x86_64/arm/arm64/all> <Game name> <Package name> <Debug/Release> <Build folder>"
fi fi
printf "\e[33mBuilding cmake\e[0m\n" printf "\e[33mBuilding cmake\e[0m\n"
@ -94,12 +122,19 @@ function build_for_type() {
-G "Ninja" \ -G "Ninja" \
-DPREFER_BUNDLED_LIBS=ON \ -DPREFER_BUNDLED_LIBS=ON \
-DCMAKE_BUILD_TYPE="${_DEFAULT_BUILD_TYPE}" \ -DCMAKE_BUILD_TYPE="${_DEFAULT_BUILD_TYPE}" \
-DANDROID_NATIVE_API_LEVEL="$_ANDROID_API_LEVEL" \ -DANDROID_PLATFORM="android-${_ANDROID_API_LEVEL}" \
-DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" \ -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake" \
-DANDROID_NDK="$ANDROID_NDK" \ -DANDROID_NDK="$ANDROID_NDK_HOME" \
-DANDROID_ABI="${2}" \ -DANDROID_ABI="${2}" \
-DANDROID_ARM_NEON=TRUE \ -DANDROID_ARM_NEON=TRUE \
-Bbuild_android/"$_ANDROID_SUB_BUILD_DIR/$1" \ -DCMAKE_ANDROID_NDK="$ANDROID_NDK_HOME" \
-DCMAKE_SYSTEM_NAME=Android \
-DCMAKE_SYSTEM_VERSION="$_ANDROID_API_LEVEL" \
-DCMAKE_ANDROID_ARCH_ABI="${2}" \
-DCARGO_NDK_TARGET="${3}" \
-DCARGO_NDK_API="$_ANDROID_API_LEVEL" \
-DDDNET_TEST_NO_LINK=ON \
-B"${_DEFAULT_BUILD_FOLDER}/$_ANDROID_SUB_BUILD_DIR/$1" \
-DSERVER=OFF \ -DSERVER=OFF \
-DTOOLS=OFF \ -DTOOLS=OFF \
-DDEV=TRUE \ -DDEV=TRUE \
@ -107,34 +142,34 @@ function build_for_type() {
-DVULKAN=ON \ -DVULKAN=ON \
-DVIDEORECORDER=OFF -DVIDEORECORDER=OFF
( (
cd "build_android/$_ANDROID_SUB_BUILD_DIR/$1" || exit 1 cd "${_DEFAULT_BUILD_FOLDER}/$_ANDROID_SUB_BUILD_DIR/$1" || exit 1
cmake --build . --target DDNet cmake --build . --target game-client
) )
} }
mkdir build_android mkdir "${_DEFAULT_BUILD_FOLDER}"
if [[ "${_DEFAULT_ANDROID_BUILD}" == "arm" || "${_DEFAULT_ANDROID_BUILD}" == "all" ]]; then if [[ "${_DEFAULT_ANDROID_BUILD}" == "arm" || "${_DEFAULT_ANDROID_BUILD}" == "all" ]]; then
build_for_type arm armeabi-v7a arm eabi & build_for_type arm armeabi-v7a armv7-linux-androideabi &
fi fi
if [[ "${_DEFAULT_ANDROID_BUILD}" == "arm64" || "${_DEFAULT_ANDROID_BUILD}" == "all" ]]; then if [[ "${_DEFAULT_ANDROID_BUILD}" == "arm64" || "${_DEFAULT_ANDROID_BUILD}" == "all" ]]; then
build_for_type arm64 arm64-v8a aarch64 & build_for_type arm64 arm64-v8a aarch64-linux-android &
fi fi
if [[ "${_DEFAULT_ANDROID_BUILD}" == "x86" || "${_DEFAULT_ANDROID_BUILD}" == "all" ]]; then if [[ "${_DEFAULT_ANDROID_BUILD}" == "x86" || "${_DEFAULT_ANDROID_BUILD}" == "all" ]]; then
build_for_type x86 x86 i686 & build_for_type x86 x86 i686-linux-android &
fi fi
if [[ "${_DEFAULT_ANDROID_BUILD}" == "x86_64" || "${_DEFAULT_ANDROID_BUILD}" == "x64" || "${_DEFAULT_ANDROID_BUILD}" == "all" ]]; then if [[ "${_DEFAULT_ANDROID_BUILD}" == "x86_64" || "${_DEFAULT_ANDROID_BUILD}" == "x64" || "${_DEFAULT_ANDROID_BUILD}" == "all" ]]; then
build_for_type x86_64 x86_64 x86_64 & build_for_type x86_64 x86_64 x86_64-linux-android &
fi fi
wait wait
printf "\e[36mPreparing gradle build\n" printf "\e[36mPreparing gradle build\n"
cd build_android || exit 1 cd "${_DEFAULT_BUILD_FOLDER}" || exit 1
mkdir -p src/main mkdir -p src/main
mkdir -p src/main/res/mipmap mkdir -p src/main/res/mipmap
@ -154,7 +189,6 @@ copy_dummy_files scripts/android/files/gradle-wrapper.jar gradle-wrapper.jar
copy_dummy_files scripts/android/files/build.gradle build.gradle copy_dummy_files scripts/android/files/build.gradle build.gradle
copy_dummy_files scripts/android/files/gradle-wrapper.properties gradle-wrapper.properties copy_dummy_files scripts/android/files/gradle-wrapper.properties gradle-wrapper.properties
copy_dummy_files scripts/android/files/gradle.properties gradle.properties copy_dummy_files scripts/android/files/gradle.properties gradle.properties
copy_dummy_files scripts/android/files/local.properties local.properties
copy_dummy_files scripts/android/files/proguard-rules.pro proguard-rules.pro copy_dummy_files scripts/android/files/proguard-rules.pro proguard-rules.pro
copy_dummy_files scripts/android/files/settings.gradle settings.gradle copy_dummy_files scripts/android/files/settings.gradle settings.gradle
copy_dummy_files scripts/android/files/AndroidManifest.xml src/main/AndroidManifest.xml copy_dummy_files scripts/android/files/AndroidManifest.xml src/main/AndroidManifest.xml
@ -170,19 +204,19 @@ function copy_libs() {
} }
if [[ "${_DEFAULT_ANDROID_BUILD}" == "arm" || "${_DEFAULT_ANDROID_BUILD}" == "all" ]]; then if [[ "${_DEFAULT_ANDROID_BUILD}" == "arm" || "${_DEFAULT_ANDROID_BUILD}" == "all" ]]; then
copy_libs arm armeabi-v7a arm eabi copy_libs arm armeabi-v7a
fi fi
if [[ "${_DEFAULT_ANDROID_BUILD}" == "arm64" || "${_DEFAULT_ANDROID_BUILD}" == "all" ]]; then if [[ "${_DEFAULT_ANDROID_BUILD}" == "arm64" || "${_DEFAULT_ANDROID_BUILD}" == "all" ]]; then
copy_libs arm64 arm64-v8a aarch64 copy_libs arm64 arm64-v8a
fi fi
if [[ "${_DEFAULT_ANDROID_BUILD}" == "x86" || "${_DEFAULT_ANDROID_BUILD}" == "all" ]]; then if [[ "${_DEFAULT_ANDROID_BUILD}" == "x86" || "${_DEFAULT_ANDROID_BUILD}" == "all" ]]; then
copy_libs x86 x86 i686 copy_libs x86 x86
fi fi
if [[ "${_DEFAULT_ANDROID_BUILD}" == "x86_64" || "${_DEFAULT_ANDROID_BUILD}" == "x64" || "${_DEFAULT_ANDROID_BUILD}" == "all" ]]; then if [[ "${_DEFAULT_ANDROID_BUILD}" == "x86_64" || "${_DEFAULT_ANDROID_BUILD}" == "x64" || "${_DEFAULT_ANDROID_BUILD}" == "all" ]]; then
copy_libs x86_64 x86_64 x86_64 copy_libs x86_64 x86_64
fi fi
_DEFAULT_ANDROID_BUILD_DUMMY=$_DEFAULT_ANDROID_BUILD _DEFAULT_ANDROID_BUILD_DUMMY=$_DEFAULT_ANDROID_BUILD
@ -220,15 +254,12 @@ printf "\e[0m"
echo "Building..." echo "Building..."
rm -R src/main/java/tw
mkdir -p src/main/java/tw/DDNet
cp ../scripts/android/files/java/tw/DDNet/NativeMain.java src/main/java/tw/DDNet/NativeMain.java
rm -R src/main/java/org rm -R src/main/java/org
mkdir -p src/main/java
cp -R ../scripts/android/files/java/org src/main/java/ cp -R ../scripts/android/files/java/org src/main/java/
cp -R ../ddnet-libs/sdl/java/org src/main/java/ cp -R ../ddnet-libs/sdl/java/org src/main/java/
# shellcheck disable=SC1091 # shellcheck disable=SC1091
source ./build.sh "$ANDROID_HOME" "$_DEFAULT_GAME_NAME" "$_DEFAULT_BUILD_TYPE" source ./build.sh "$_DEFAULT_GAME_NAME" "$_DEFAULT_PACKAGE_NAME" "$_DEFAULT_BUILD_TYPE"
cd .. cd ..

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android">
package="tw.DDNet">
<uses-feature <uses-feature
android:glEsVersion="0x00030000" /> android:glEsVersion="0x00030000" />
<uses-feature <uses-feature
@ -21,24 +20,23 @@
android:usesCleartextTraffic="true" android:usesCleartextTraffic="true"
android:label="@string/app_name" android:label="@string/app_name"
android:hasCode="true" android:hasCode="true"
android:extractNativeLibs="true"
android:supportsRtl="true" android:supportsRtl="true"
android:isGame="true" android:isGame="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"> android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
<activity <activity
android:name=".NativeMain" android:name="org.ddnet.client.NativeMain"
android:exported="true"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden" android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
android:screenOrientation="landscape"> android:screenOrientation="landscape">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
<meta-data android:name="android.app.lib_name" <meta-data
android:name="android.app.lib_name"
android:value="DDNet" /> android:value="DDNet" />
</activity> </activity>
</application> </application>
</manifest> </manifest>

View file

@ -10,19 +10,25 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:7.2.1' classpath 'com.android.tools.build:gradle:8.3.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
} }
} }
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(21))
}
}
android { android {
compileSdkVersion 30 compileSdkVersion 34
buildToolsVersion "30.0.3"
ndkVersion "TW_NDK_VERSION" ndkVersion "TW_NDK_VERSION"
defaultConfig { defaultConfig {
applicationId "tw.DDNet" applicationId "org.ddnet.client"
namespace("org.ddnet.client")
minSdkVersion 24 minSdkVersion 24
targetSdkVersion 30 targetSdkVersion 34
versionCode TW_VERSION_CODE versionCode TW_VERSION_CODE
versionName "TW_VERSION_NAME" versionName "TW_VERSION_NAME"
} }
@ -46,7 +52,11 @@ android {
shrinkResources false shrinkResources false
} }
} }
packagingOptions {
jniLibs {
useLegacyPackaging = true
}
}
sourceSets { sourceSets {
main { main {
assets.srcDirs = ['assets'] assets.srcDirs = ['assets']

View file

@ -1,12 +1,12 @@
#!/bin/bash #!/bin/bash
[ "$1" == "" ] && { [ "$1" == "" ] && {
printf '\e[31mDid not pass ANDROID_SDK_ROOT to build script\e[30m\n' printf '\e[31mDid not pass APK name to build script\e[30m\n'
exit 1 exit 1
} }
[ "$2" == "" ] && { [ "$2" == "" ] && {
printf '\e[31mDid not pass APK name to build script\e[30m\n' printf '\e[31mDid not pass package name to build script\e[30m\n'
exit 1 exit 1
} }
@ -15,13 +15,15 @@
exit 1 exit 1
} }
_APK_BASENAME="$2" _APK_BASENAME="$1"
_APK_PACKAGE_NAME="$2"
_APK_BUILD_TYPE="$3"
sed -i "s/DDNet/${2}/g" settings.gradle _APK_PACKAGE_FOLDER=$(echo "$_APK_PACKAGE_NAME"|sed 's/\./\//g')
_REPLACE_PACKAGE_NAME_STR="tw.${2,,}" sed -i "s/DDNet/${_APK_BASENAME}/g" settings.gradle
sed -i "s/tw.DDNet/${_REPLACE_PACKAGE_NAME_STR}/g" build.gradle sed -i "s/org.ddnet.client/${_APK_PACKAGE_NAME}/g" build.gradle
TW_KEY_NAME_ESCAPED=$(echo "$TW_KEY_NAME"|sed 's/\//\\\//g') TW_KEY_NAME_ESCAPED=$(echo "$TW_KEY_NAME"|sed 's/\//\\\//g')
TW_KEY_PW_ESCAPED=$(echo "$TW_KEY_PW"|sed 's/\//\\\//g') TW_KEY_PW_ESCAPED=$(echo "$TW_KEY_PW"|sed 's/\//\\\//g')
@ -31,38 +33,35 @@ sed -i "s/TW_KEY_NAME/${TW_KEY_NAME_ESCAPED}/g" build.gradle
sed -i "s/TW_KEY_PW/${TW_KEY_PW_ESCAPED}/g" build.gradle sed -i "s/TW_KEY_PW/${TW_KEY_PW_ESCAPED}/g" build.gradle
sed -i "s/TW_KEY_ALIAS/${TW_KEY_ALIAS_ESCAPED}/g" build.gradle sed -i "s/TW_KEY_ALIAS/${TW_KEY_ALIAS_ESCAPED}/g" build.gradle
sed -i "s/DDNet/${2}/g" src/main/res/values/strings.xml
sed -i "s/\"DDNet\"/\"${2}\"/g" src/main/AndroidManifest.xml
sed -i "s/tw.DDNet/${_REPLACE_PACKAGE_NAME_STR}/g" src/main/AndroidManifest.xml
__TW_HOME_DIR=$(echo "$HOME"|sed 's/\//\\\//g')
sed -i "s/TW_HOME_DIR/${__TW_HOME_DIR}/g" local.properties
sed -i "s/TW_NDK_VERSION/${ANDROID_NDK_VERSION}/g" build.gradle sed -i "s/TW_NDK_VERSION/${ANDROID_NDK_VERSION}/g" build.gradle
sed -i "s/TW_VERSION_CODE/${TW_VERSION_CODE}/g" build.gradle sed -i "s/TW_VERSION_CODE/${TW_VERSION_CODE}/g" build.gradle
sed -i "s/TW_VERSION_NAME/${TW_VERSION_NAME}/g" build.gradle sed -i "s/TW_VERSION_NAME/${TW_VERSION_NAME}/g" build.gradle
mv src/main/java/tw/DDNet src/main/java/tw/"${2}" sed -i "s/DDNet/${_APK_BASENAME}/g" src/main/res/values/strings.xml
sed -i "s/tw.DDNet/${_REPLACE_PACKAGE_NAME_STR}/g" src/main/java/tw/"${2}"/NativeMain.java sed -i "s/\"DDNet\"/\"${_APK_BASENAME}\"/g" src/main/AndroidManifest.xml
sed -i "s/tw.DDNet/${_REPLACE_PACKAGE_NAME_STR}/g" proguard-rules.pro sed -i "s/org.ddnet.client/${_APK_PACKAGE_NAME}/g" src/main/AndroidManifest.xml
mv src/main/java/org/ddnet/client src/main/java/"${_APK_PACKAGE_FOLDER}"
sed -i "s/org.ddnet.client/${_APK_PACKAGE_NAME}/g" src/main/java/"${_APK_PACKAGE_FOLDER}"/NativeMain.java
sed -i "s/org.ddnet.client/${_APK_PACKAGE_NAME}/g" proguard-rules.pro
# disable hid manager for now # disable hid manager for now
sed -i "s/mHIDDeviceManager = HIDDeviceManager.acquire(this);/mHIDDeviceManager=null;/g" src/main/java/org/libsdl/app/SDLActivity.java sed -i "s/mHIDDeviceManager = HIDDeviceManager.acquire(this);/mHIDDeviceManager=null;/g" src/main/java/org/libsdl/app/SDLActivity.java
if [[ "${3}" == "Debug" ]]; then if [[ "${_APK_BUILD_TYPE}" == "Debug" ]]; then
sed -i "s/android.enableR8.fullMode=true/android.enableR8.fullMode=false/g" gradle.properties sed -i "s/android.enableR8.fullMode=true/android.enableR8.fullMode=false/g" gradle.properties
fi fi
if [[ -z ${GE_NO_APK_BUILD} || "${GE_NO_APK_BUILD}" != "1" ]]; then if [[ -z ${GE_NO_APK_BUILD} || "${GE_NO_APK_BUILD}" != "1" ]]; then
_RELEASE_TYPE_NAME=debug _RELEASE_TYPE_NAME=debug
_RELEASE_TYPE_APK_NAME= _RELEASE_TYPE_APK_NAME=
if [[ "${3}" == "Debug" ]]; then if [[ "${_APK_BUILD_TYPE}" == "Debug" ]]; then
_RELEASE_TYPE_NAME=debug _RELEASE_TYPE_NAME=debug
fi fi
if [[ "${3}" == "Release" ]]; then if [[ "${_APK_BUILD_TYPE}" == "Release" ]]; then
_RELEASE_TYPE_NAME=release _RELEASE_TYPE_NAME=release
_RELEASE_TYPE_APK_NAME= _RELEASE_TYPE_APK_NAME=
fi fi
@ -70,7 +69,7 @@ if [[ -z ${GE_NO_APK_BUILD} || "${GE_NO_APK_BUILD}" != "1" ]]; then
APP_BASE_NAME=Gradle APP_BASE_NAME=Gradle
CLASSPATH=gradle-wrapper.jar CLASSPATH=gradle-wrapper.jar
java "-Dorg.gradle.appname=${APP_BASE_NAME}" -classpath "${CLASSPATH}" org.gradle.wrapper.GradleWrapperMain --warning-mode all java "-Dorg.gradle.appname=${APP_BASE_NAME}" -classpath "${CLASSPATH}" org.gradle.wrapper.GradleWrapperMain --warning-mode all
if [[ "${3}" == "Debug" ]]; then if [[ "${_APK_BUILD_TYPE}" == "Debug" ]]; then
java "-Dorg.gradle.appname=${APP_BASE_NAME}" -classpath "${CLASSPATH}" org.gradle.wrapper.GradleWrapperMain --warning-mode all builddebug java "-Dorg.gradle.appname=${APP_BASE_NAME}" -classpath "${CLASSPATH}" org.gradle.wrapper.GradleWrapperMain --warning-mode all builddebug
java "-Dorg.gradle.appname=${APP_BASE_NAME}" -classpath "${CLASSPATH}" org.gradle.wrapper.GradleWrapperMain --warning-mode all assembleDebug java "-Dorg.gradle.appname=${APP_BASE_NAME}" -classpath "${CLASSPATH}" org.gradle.wrapper.GradleWrapperMain --warning-mode all assembleDebug
else else
@ -80,7 +79,7 @@ if [[ -z ${GE_NO_APK_BUILD} || "${GE_NO_APK_BUILD}" != "1" ]]; then
cp build/outputs/apk/"$_RELEASE_TYPE_NAME"/"$_APK_BASENAME"-"$_RELEASE_TYPE_NAME""$_RELEASE_TYPE_APK_NAME".apk "$_APK_BASENAME".apk cp build/outputs/apk/"$_RELEASE_TYPE_NAME"/"$_APK_BASENAME"-"$_RELEASE_TYPE_NAME""$_RELEASE_TYPE_APK_NAME".apk "$_APK_BASENAME".apk
if [[ "${3}" == "Release" ]]; then if [[ "${_APK_BUILD_TYPE}" == "Release" ]]; then
java "-Dorg.gradle.appname=${APP_BASE_NAME}" -classpath "${CLASSPATH}" org.gradle.wrapper.GradleWrapperMain --warning-mode all bundleRelease java "-Dorg.gradle.appname=${APP_BASE_NAME}" -classpath "${CLASSPATH}" org.gradle.wrapper.GradleWrapperMain --warning-mode all bundleRelease
cp build/outputs/bundle/"$_RELEASE_TYPE_NAME"/"$_APK_BASENAME"-"$_RELEASE_TYPE_NAME""$_RELEASE_TYPE_APK_NAME".aab "$_APK_BASENAME".aab cp build/outputs/bundle/"$_RELEASE_TYPE_NAME"/"$_APK_BASENAME"-"$_RELEASE_TYPE_NAME""$_RELEASE_TYPE_APK_NAME".aab "$_APK_BASENAME".aab

View file

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View file

@ -1,4 +1,5 @@
package tw.DDNet; package org.ddnet.client;
import android.app.NativeActivity; import android.app.NativeActivity;
import org.libsdl.app.SDLActivity; import org.libsdl.app.SDLActivity;
import android.os.Bundle; import android.os.Bundle;

View file

@ -1,10 +0,0 @@
## This file is automatically generated by Android Studio.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file should *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
sdk.dir="TW_HOME_DIR/Android/Sdk"

View file

@ -16,7 +16,7 @@
# debugging stack traces. # debugging stack traces.
#-keepattributes SourceFile,LineNumberTable #-keepattributes SourceFile,LineNumberTable
-keepclassmembers, allowoptimization public class tw.DDNet.NativeMain { -keepclassmembers, allowoptimization public class org.ddnet.client.NativeMain {
*; *;
} }

View file

@ -1,10 +1,11 @@
#!/bin/bash #!/bin/bash
ANDROID_HOME=~/Android/Sdk ANDROID_HOME=~/Android/Sdk
ANDROID_NDK="$(find "$ANDROID_HOME/ndk" -maxdepth 1 | sort -n | tail -1)" ANDROID_NDK_HOME="$(find "$ANDROID_HOME/ndk" -maxdepth 1 | sort -n | tail -1)"
echo "$ANDROID_NDK" export ANDROID_NDK_HOME
export MAKEFLAGS=-j32 MAKEFLAGS=-j$(nproc)
export MAKEFLAGS
if [[ "${2}" == "webasm" ]]; then if [[ "${2}" == "webasm" ]]; then
COMPILEFLAGS="-pthread -O3 -g -s USE_PTHREADS=1" COMPILEFLAGS="-pthread -O3 -g -s USE_PTHREADS=1"
@ -20,10 +21,15 @@ function compile_source() {
-H. \ -H. \
-G "Unix Makefiles" \ -G "Unix Makefiles" \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DANDROID_NATIVE_API_LEVEL="android-$1" \ -DANDROID_PLATFORM="android-$1" \
-DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" \ -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake" \
-DANDROID_NDK="$ANDROID_NDK_HOME" \
-DANDROID_ABI="${3}" \ -DANDROID_ABI="${3}" \
-DANDROID_ARM_NEON=TRUE \ -DANDROID_ARM_NEON=TRUE \
-DCMAKE_ANDROID_NDK="$ANDROID_NDK_HOME" \
-DCMAKE_SYSTEM_NAME=Android \
-DCMAKE_SYSTEM_VERSION="$1" \
-DCMAKE_ANDROID_ARCH_ABI="${3}" \
-B"$2" \ -B"$2" \
-DBUILD_SHARED_LIBS=OFF \ -DBUILD_SHARED_LIBS=OFF \
-DHIDAPI_SKIP_LIBUSB=TRUE \ -DHIDAPI_SKIP_LIBUSB=TRUE \

View file

@ -53,9 +53,15 @@ fi
mkdir -p "$1" mkdir -p "$1"
cd "$1" || exit 1 cd "$1" || exit 1
_ANDROID_ABI_LEVEL=34
function build_cmake_lib() { function build_cmake_lib() {
if [ ! -d "${1}" ]; then if [ ! -d "${1}" ]; then
if [ -z ${3+x} ]; then
git clone "${2}" "${1}" git clone "${2}" "${1}"
else
git clone --single-branch --branch "${3}" "${2}" "${1}"
fi
fi fi
( (
cd "${1}" || exit 1 cd "${1}" || exit 1
@ -64,8 +70,6 @@ function build_cmake_lib() {
) )
} }
_ANDROID_ABI_LEVEL=24
mkdir -p compile_libs mkdir -p compile_libs
cd compile_libs || exit 1 cd compile_libs || exit 1
@ -90,7 +94,7 @@ build_cmake_lib zlib https://github.com/madler/zlib
build_cmake_lib png https://github.com/glennrp/libpng build_cmake_lib png https://github.com/glennrp/libpng
build_cmake_lib curl https://github.com/curl/curl build_cmake_lib curl https://github.com/curl/curl
build_cmake_lib freetype2 https://gitlab.freedesktop.org/freetype/freetype build_cmake_lib freetype2 https://gitlab.freedesktop.org/freetype/freetype
build_cmake_lib sdl https://github.com/libsdl-org/SDL build_cmake_lib sdl https://github.com/libsdl-org/SDL SDL2
build_cmake_lib ogg https://github.com/xiph/ogg build_cmake_lib ogg https://github.com/xiph/ogg
build_cmake_lib opus https://github.com/xiph/opus build_cmake_lib opus https://github.com/xiph/opus

View file

@ -54,23 +54,23 @@ void InitAndroid()
dbg_msg("integrity", "copying integrity.txt with size: %ld", length); dbg_msg("integrity", "copying integrity.txt with size: %ld", length);
IOHANDLE pIO = io_open("integrity.txt", IOFLAG_WRITE); IOHANDLE IntegrityFileWrite = io_open("integrity.txt", IOFLAG_WRITE);
io_write(pIO, pAl, length); io_write(IntegrityFileWrite, pAl, length);
io_close(pIO); io_close(IntegrityFileWrite);
free(pAl); free(pAl);
} }
IOHANDLE pIO = io_open("integrity.txt", IOFLAG_READ); IOHANDLE IntegrityFileRead = io_open("integrity.txt", IOFLAG_READ);
CLineReader LineReader; CLineReader IntegrityFileLineReader;
LineReader.Init(pIO); IntegrityFileLineReader.Init(IntegrityFileRead);
const char *pReadLine = NULL; const char *pReadLine = NULL;
std::vector<std::string> vLines; std::vector<std::string> vLines;
while((pReadLine = LineReader.Get())) while((pReadLine = IntegrityFileLineReader.Get()))
{ {
vLines.push_back(pReadLine); vLines.push_back(pReadLine);
} }
io_close(pIO); io_close(IntegrityFileRead);
// first line is the whole hash // first line is the whole hash
std::string AllAsOne; std::string AllAsOne;
@ -82,17 +82,18 @@ void InitAndroid()
SHA256_DIGEST ShaAll; SHA256_DIGEST ShaAll;
bool GotSHA = false; bool GotSHA = false;
{ {
IOHANDLE pIOR = io_open("integrity_save.txt", IOFLAG_READ); IOHANDLE IntegritySaveFileRead = io_open("integrity_save.txt", IOFLAG_READ);
if(pIOR != NULL) if(IntegritySaveFileRead != NULL)
{ {
CLineReader LineReader; CLineReader IntegritySaveLineReader;
LineReader.Init(pIOR); IntegritySaveLineReader.Init(IntegritySaveFileRead);
const char *pLine = LineReader.Get(); const char *pLine = IntegritySaveLineReader.Get();
if(pLine != NULL) if(pLine != NULL)
{ {
sha256_from_str(&ShaAll, pLine); sha256_from_str(&ShaAll, pLine);
GotSHA = true; GotSHA = true;
} }
io_close(IntegritySaveFileRead);
} }
} }
@ -138,20 +139,20 @@ void InitAndroid()
SDL_RWclose(pF); SDL_RWclose(pF);
IOHANDLE pIO = io_open(FileName.c_str(), IOFLAG_WRITE); IOHANDLE AssetFileWrite = io_open(FileName.c_str(), IOFLAG_WRITE);
io_write(pIO, pAl, length); io_write(AssetFileWrite, pAl, length);
io_close(pIO); io_close(AssetFileWrite);
free(pAl); free(pAl);
} }
IOHANDLE pIOR = io_open("integrity_save.txt", IOFLAG_WRITE); IOHANDLE IntegritySaveFileWrite = io_open("integrity_save.txt", IOFLAG_WRITE);
if(pIOR != NULL) if(IntegritySaveFileWrite != NULL)
{ {
char aFileSHA[SHA256_MAXSTRSIZE]; char aFileSHA[SHA256_MAXSTRSIZE];
sha256_str(ShaAllFile, aFileSHA, sizeof(aFileSHA)); sha256_str(ShaAllFile, aFileSHA, sizeof(aFileSHA));
io_write(pIOR, aFileSHA, str_length(aFileSHA)); io_write(IntegritySaveFileWrite, aFileSHA, str_length(aFileSHA));
io_close(pIOR); io_close(IntegritySaveFileWrite);
} }
} }
} }

View file

@ -4279,16 +4279,6 @@ int main(int argc, const char **argv)
#endif #endif
CCmdlineFix CmdlineFix(&argc, &argv); CCmdlineFix CmdlineFix(&argc, &argv);
bool Silent = false;
for(int i = 1; i < argc; i++)
{
if(str_comp("-s", argv[i]) == 0 || str_comp("--silent", argv[i]) == 0)
{
Silent = true;
}
}
#if defined(CONF_PLATFORM_ANDROID) #if defined(CONF_PLATFORM_ANDROID)
InitAndroid(); InitAndroid();
#endif #endif
@ -4302,6 +4292,14 @@ int main(int argc, const char **argv)
#if defined(CONF_PLATFORM_ANDROID) #if defined(CONF_PLATFORM_ANDROID)
pStdoutLogger = std::shared_ptr<ILogger>(log_logger_android()); pStdoutLogger = std::shared_ptr<ILogger>(log_logger_android());
#else #else
bool Silent = false;
for(int i = 1; i < argc; i++)
{
if(str_comp("-s", argv[i]) == 0 || str_comp("--silent", argv[i]) == 0)
{
Silent = true;
}
}
if(!Silent) if(!Silent)
{ {
pStdoutLogger = std::shared_ptr<ILogger>(log_logger_stdout()); pStdoutLogger = std::shared_ptr<ILogger>(log_logger_stdout());