Skip to content

Commit c84a401

Browse files
committed
Update Android libraries and scripts, support Android 15 and 16
Library changes --------------- For Android (and Emscripten), replace libcrypto and libssl provided by OpenSSL with those provided by BoringSSL, as the former does not support using Android's system certificate store. This previously required embedding a certificate store separately in the APK, limiting the lifetime of the app until the certificate expires. With BoringSSL we can set `CURLOPT_CAPATH` for curl handles to use the Android system certificate store directly. Upgrade/downgrade libraries to fixed versions used on other platforms for parity, or latest release versions when more desirable or necessary for Android: - libpng: unspecified --> v1.6.43 - curl: curl-8_8_0 (unchanged) - freetype: unspecified --> VER-2-13-2 - SDL: unspecified --> release-2.32.10 - ogg: unspecified --> v1.3.5 - opus: unspecified --> v1.5.2 - opusfile: unspecified --> v0.12 - sqlite3: amalgamation-3360000 --> amalgamation-3460000 Remove unused precompiled zlib library, which is not necessary for Android because the bundled `src/engine/external/zlib` can be compiled. It is only necessary for the Emscripten build because `src/engine/external/zlib` does not compile, but Emscripten libraries are not currently included in the ddnet-libs repository. Change the version of zlib used for the Emscripten build to v1.3.1.2 to fix build failures. Remove unused `libSDL2main.a` library, which is not necessary for Android. Support for Android 15 and 16 ----------------------------- Bump versions of Android NDK, build tools, command line tools and Gradle to support [16 KiB pages sizes](https://developer.android.com/guide/practices/page-sizes), which is required to support Android 15 (API 35). Compile libraries with the correct flags for Android API 24 - 36 support. Fix various Android-specific CFLAGS not being set correctly when building some libraries. See the Android CMake toolchain files and https://android.googlesource.com/platform/ndk/+/master/docs/BuildSystemMaintainers.md for documentation of the flags being used. The only deviation from the default flags is that we build the libraries and the client without debug information (in Release mode), as the automatic stripping of debug information during the Gradle build does not work. This reduces the final APK size in Release mode by around 1/3 or 60 MiB. Bump target/compile API level to 36 to support Android 16. Set `android:enableOnBackInvokedCallback="false"` in the manifest to disable the [predictive back gesture](https://developer.android.com/guide/navigation/custom-back/predictive-back-gesture) and keep the legacy behavior of the back button. Fix Gradle deprecation warnings with latest Gradle version, by using `=` for property assignment in `build.gradle`. Towards reproducible builds --------------------------- Pin specific release version or commits for all libraries instead of building the default branch. Make the library build reproducible by removing the embedded absolute build paths of the libraries using the `-ffile-prefix-map` flag. Also separately remove the absolute paths of the Android NDK and the Emscripten SDK which were being embedded in libraries and in the Android and Emscripten client, respectively. Remove embedded paths of the build folder in addition to the source folder, as some compilers (Android) also seem to embed it separately for generated source files. Order entries in Android asset integrity index file lexicographically instead of using non-deterministic file enumeration order. Explicitly set `ANDROID_HOME` in the CI, as it was already defined and preinstalled Android tools were used instead. Use fixed Rust default version for Android build in CI. Overall, this should make the Android build almost reproducible if the specified versions of Android NDK and the JDK are used. Still not reproducible is the Vulkan shader compilation/optimization and something minor about the client binary compilation. Streamline library building process ----------------------------------- - Add log messages. - Add error message when building for Android if the Android NDK could not be found. Avoid different warning when building for Emscripten and not having the Android NDK installed. - Specify the correct libpng include and library paths when building libfreetype to enable PNG support in the latter. - Disable protocol support in libcurl for all protocols except those enabled on other platforms: HTTPS, HTTP, FTPS, FTP, FILE. - Use ninja for building CMake-based libraries to reduce building time. - Specify exact build targets when building CMake-based libraries to avoid building unused extra tools. - Avoid building zlib for Android, as it can be build from `src/engine/external/zlib` and only needs to be build separately for Emscripten. - Avoid rebuilding the sqlite3 and opusfile libraries if they are unchanged by generating minimal Makefiles. - Avoid copying build script files to the build folders of individual libraries, instead invoke the scripts within the build folders with absolute paths. - Avoid copying libopus and libogg files when building libopusfile, instead reference the files in the existing build folders. Improve documentation --------------------- - Add missing instruction to install libtool to the README. Without libtool the initial project configuration of libopusfile fails, although it seems to work on the second attempt anyway. - Add instructions for updating the Android SDK and Gradle versions to the README. - Add instructions to delete old Android/Emscripten-specific libraries files before copying new files to ddnet-libs, to avoid old files being left behind. - Explain how to perform a clean build of the libraries. Various refactoring ------------------- - Add `set -e` to all scripts to enable strict error handling and always exit on errors. Remove `|| exit 1` that are made unnecessary by this. - Add shellcheck source directives to comments so that shellcheck can correctly check the sourced shell scripts, instead of disabling the check. The paths in the source directives are relative to project root, the folder where shellcheck is executed. - Consolidate common flags and functions for Android and Emscripten building in the `_build_common.sh` file. - Consistently use `ON` for CMake settings instead of `1` or `TRUE`. - Use local variables when possible.
1 parent 3f623af commit c84a401

25 files changed

+833
-592
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Build Android libraries
2+
3+
# TODO: remove all except workflow_dispatch
4+
on:
5+
push:
6+
branches-ignore:
7+
- gh-readonly-queue/**
8+
- master
9+
pull_request:
10+
merge_group:
11+
workflow_dispatch:
12+
13+
jobs:
14+
build-libraries-android:
15+
runs-on: ubuntu-latest
16+
env:
17+
CARGO_HTTP_MULTIPLEXING: false
18+
steps:
19+
- name: Checkout repository
20+
uses: actions/checkout@v4
21+
with:
22+
submodules: recursive
23+
24+
- name: Prepare Linux
25+
run: |
26+
sudo apt-get update -y
27+
sudo apt-get install cmake glslang-tools libtool ninja-build p7zip-full
28+
scripts/android/download_android_sdk.sh /home/runner
29+
yes | latest/bin/sdkmanager --licenses
30+
31+
- name: Build Android libraries
32+
run: |
33+
scripts/compile_libs/gen_libs.sh build-android-libs android
34+
35+
- name: Check reproduciblity
36+
run: |
37+
find build-android-libs/ddnet-libs -type f -print0 | while IFS= read -r -d $'\0' new_file; do
38+
rel_path=${new_file#build-android-libs/ddnet-libs/}
39+
existing_file="ddnet-libs/$rel_path"
40+
if [ -f "$existing_file" ]; then
41+
diff -q "$new_file" "$existing_file" || true
42+
fi
43+
done
44+
45+
- name: Upload Artifacts
46+
uses: actions/upload-artifact@v4
47+
with:
48+
name: ddnet-libs-android
49+
path: build-android-libs/ddnet-libs

.github/workflows/build.yml

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -256,35 +256,14 @@ jobs:
256256
- name: Prepare Linux
257257
run: |
258258
sudo apt-get update -y
259-
sudo apt-get install cmake ninja-build openjdk-21-jdk p7zip-full curl glslang-tools openssl
259+
sudo apt-get install cmake ninja-build openjdk-21-jdk p7zip-full glslang-tools openssl
260+
rustup default 1.92.0
260261
cargo install cargo-ndk
261262
rustup target add armv7-linux-androideabi
262263
rustup target add i686-linux-android
263264
rustup target add aarch64-linux-android
264265
rustup target add x86_64-linux-android
265-
mkdir ~/Android
266-
cd ~/Android
267-
mkdir Sdk
268-
cd Sdk
269-
mkdir ndk
270-
cd ndk
271-
wget --quiet https://dl.google.com/android/repository/android-ndk-r26d-linux.zip
272-
unzip android-ndk-r26d-linux.zip
273-
rm android-ndk-r26d-linux.zip
274-
cd ~/Android/Sdk
275-
mkdir build-tools
276-
cd build-tools
277-
wget --quiet https://dl.google.com/android/repository/build-tools_r30.0.3-linux.zip
278-
unzip build-tools_r30.0.3-linux.zip
279-
rm build-tools_r30.0.3-linux.zip
280-
mv android-11 30.0.3
281-
cd ~/Android/Sdk
282-
mkdir cmdline-tools
283-
cd cmdline-tools
284-
wget --quiet https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip
285-
unzip commandlinetools-linux-11076708_latest.zip
286-
rm commandlinetools-linux-11076708_latest.zip
287-
mv cmdline-tools latest
266+
scripts/android/download_android_sdk.sh /home/runner
288267
yes | latest/bin/sdkmanager --licenses
289268
290269
- name: Cache Rust dependencies
@@ -302,10 +281,16 @@ jobs:
302281
run: |
303282
export TW_KEY_PW="$(openssl rand -base64 32)"
304283
keytool -genkey -v -keystore "$TW_KEY_NAME" -keyalg RSA -keysize 2048 -validity 10000 -alias "$TW_KEY_ALIAS" -storepass "$TW_KEY_PW" -dname "CN=DDNet CI, OU=DDNet, O=DDNet"
305-
mkdir build-android
284+
export ANDROID_HOME="/home/runner/Android/Sdk"
285+
unset ANDROID_SDK_ROOT
306286
scripts/android/cmake_android.sh all DDNet org.ddnet.client Release build-android
307287
mkdir artifacts
308288
mv build-android/DDNet.apk artifacts
289+
# TODO: remove testing
290+
mkdir artifacts/testing
291+
cp build-android/build_arch/arm64/checksummed_extra.txt artifacts/testing/checksummed_extra.txt
292+
cp build-android/build_arch/arm64/checksummed_files.txt artifacts/testing/checksummed_files.txt
293+
cp -R build-android/build_arch/arm64/src artifacts/testing
309294
310295
- name: Upload Artifacts
311296
uses: actions/upload-artifact@v4

CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ if(NOT MSVC AND NOT HAIKU)
307307

308308
if(NOT CMAKE_BUILD_TYPE STREQUAL Debug AND NOT DEV)
309309
add_cxx_compiler_flag_if_supported(OUR_FLAGS -ffile-prefix-map=${CMAKE_SOURCE_DIR}=/${CMAKE_PROJECT_NAME})
310+
add_cxx_compiler_flag_if_supported(OUR_FLAGS -ffile-prefix-map=${PROJECT_BINARY_DIR}=/${CMAKE_PROJECT_NAME})
310311
endif()
311312

312313
if(TARGET_OS STREQUAL "mac")
@@ -689,8 +690,8 @@ endif()
689690
if(CLIENT AND NOT(SDL2_FOUND))
690691
message(SEND_ERROR "You must install SDL2 to compile the ${CMAKE_PROJECT_NAME} client")
691692
endif()
692-
if(TARGET_OS STREQUAL "android" AND NOT(CRYPTO_FOUND))
693-
message(SEND_ERROR "You must install OpenSSL to compile ${CMAKE_PROJECT_NAME}")
693+
if((TARGET_OS STREQUAL "android" OR TARGET_OS STREQUAL "emscripten") AND NOT(CRYPTO_FOUND))
694+
message(SEND_ERROR "You must install BoringSSL to compile ${CMAKE_PROJECT_NAME} for Android/Emscripten")
694695
endif()
695696
if(NOT(GTEST_FOUND))
696697
if(DOWNLOAD_GTEST)

README.md

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -272,22 +272,30 @@ Install Emscripten cross-compilers on a modern linux distro. Follow the [instruc
272272
If you need to compile the ddnet-libs for WebAssembly, simply call
273273

274274
```sh
275-
# <directory to build in> should be a directory outside of the project's source directory
276-
scripts/compile_libs/gen_libs.sh "<directory to build in>" webasm
275+
scripts/compile_libs/gen_libs.sh build-webasm-libs webasm
277276
```
278277

279278
from the project's source directory. It will automatically create a directory called `ddnet-libs` in your build directory.
280-
You can then manually merge this directory with the one in the ddnet source directory.
279+
You can then merge this directory with the one in the ddnet source directory:
280+
281+
```sh
282+
find ddnet-libs -type d -name 'webasm' -exec rm -r {} + -prune
283+
cp -r build-webasm-libs/ddnet-libs/. ddnet-libs/
284+
```
281285
282286
Run `rustup target add wasm32-unknown-emscripten` to install the WASM target for compiling Rust.
283287
284-
Then run `emcmake cmake .. -G "Unix Makefiles" -DVIDEORECORDER=OFF -DVULKAN=OFF -DSERVER=OFF -DTOOLS=OFF -DPREFER_BUNDLED_LIBS=ON` in your build directory to configure followed by `cmake --build . -j8` to build. For testing it is highly recommended to build in debug mode by also passing the argument `-DCMAKE_BUILD_TYPE=Debug` when invoking `emcmake cmake`, as this speeds up the build process and adds debug information as well as additional checks. Note that using the Ninja build system with Emscripten is not currently possible due to [CMake issue 16395](https://gitlab.kitware.com/cmake/cmake/-/issues/16395).
288+
Create a new directory to build the client in.
289+
Then run `emcmake cmake .. -G "Unix Makefiles" -DVIDEORECORDER=OFF -DVULKAN=OFF -DSERVER=OFF -DTOOLS=OFF -DPREFER_BUNDLED_LIBS=ON` in your build directory to configure followed by `cmake --build . -j8` to build.
290+
For testing it is highly recommended to build in debug mode by also passing the argument `-DCMAKE_BUILD_TYPE=Debug` when invoking `emcmake cmake`, as this speeds up the build process and adds debug information as well as additional checks.
291+
Note that using the Ninja build system with Emscripten is not currently possible due to [CMake issue 16395](https://gitlab.kitware.com/cmake/cmake/-/issues/16395).
285292
286-
To test the compiled code locally, just use `emrun --browser firefox DDNet.html`
293+
To test the compiled code locally, just use `emrun --browser firefox DDNet.html`.
287294
288-
To host the compiled .html file copy all `.data`, `.html`, `.js`, `.wasm` files to the web server. See `other/emscripten/minimal.html` for a minimal HTML example. You can also run `other/emscripten/server.py` to host a minimal server for testing using Python without needing to install Emscripten.
295+
To host the compiled .html file copy all `.data`, `.html`, `.js`, `.wasm` files to the web server.
296+
See `other/emscripten/minimal.html` for a minimal HTML example. You can also run `other/emscripten/server.py` to host a minimal server for testing using Python without needing to install Emscripten.
289297
290-
Then enable cross origin policies. Example for apache2 on debian based distros:
298+
Enable cross-origin policies when using a proper web server. Example for apache2 on Debian-based distros:
291299
292300
```sh
293301
sudo a2enmod header

cmake/FindCrypto.cmake

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,37 +8,30 @@ if(NOT PREFER_BUNDLED_LIBS)
88
endif()
99
endif()
1010

11-
if(PREFER_BUNDLED_LIBS AND (TARGET_OS STREQUAL "android" OR CMAKE_SYSTEM_NAME STREQUAL "Emscripten"))
12-
set_extra_dirs_lib(CRYPTO openssl)
13-
find_library(CRYPTO_LIBRARY1
11+
if(PREFER_BUNDLED_LIBS AND (TARGET_OS STREQUAL "android" OR TARGET_OS STREQUAL "emscripten"))
12+
set_extra_dirs_lib(CRYPTO boringssl)
13+
find_library(CRYPTO_LIBRARY
1414
NAMES crypto
1515
HINTS ${HINTS_CRYPTO_LIBDIR} ${PC_CRYPTO_LIBDIR} ${PC_CRYPTO_LIBRARY_DIRS}
1616
PATHS ${PATHS_CRYPTO_LIBDIR}
1717
${CROSSCOMPILING_NO_CMAKE_SYSTEM_PATH}
1818
)
19-
find_library(CRYPTO_LIBRARY2
19+
find_library(SSL_LIBRARY
2020
NAMES ssl
2121
HINTS ${HINTS_CRYPTO_LIBDIR} ${PC_CRYPTO_LIBDIR} ${PC_CRYPTO_LIBRARY_DIRS}
2222
PATHS ${PATHS_CRYPTO_LIBDIR}
2323
${CROSSCOMPILING_NO_CMAKE_SYSTEM_PATH}
2424
)
25-
set(CRYPTO_LIBRARY ${CRYPTO_LIBRARY1} ${CRYPTO_LIBRARY2})
25+
set(CRYPTO_LIBRARY ${CRYPTO_LIBRARY} ${SSL_LIBRARY})
2626

2727
set(CMAKE_FIND_FRAMEWORK FIRST)
28-
set_extra_dirs_include(CRYPTO openssl "${CRYPTO_LIBRARY}")
29-
find_path(CRYPTO_INCLUDEDIR1 openssl/opensslconf.h
28+
set_extra_dirs_include(CRYPTO boringssl "${CRYPTO_LIBRARY}")
29+
find_path(CRYPTO_INCLUDEDIR openssl/ssl.h openssl/base.h openssl/hkdf.h openssl/opensslconf.h
3030
PATH_SUFFIXES CRYPTO
3131
HINTS ${HINTS_CRYPTO_INCLUDEDIR} ${PC_CRYPTO_INCLUDEDIR} ${PC_CRYPTO_INCLUDE_DIRS}
3232
PATHS ${PATHS_CRYPTO_INCLUDEDIR}
3333
${CROSSCOMPILING_NO_CMAKE_SYSTEM_PATH}
3434
)
35-
find_path(CRYPTO_INCLUDEDIR2 openssl/configuration.h
36-
PATH_SUFFIXES CRYPTO
37-
HINTS ${HINTS_CRYPTO_INCLUDEDIR} ${PC_CRYPTO_INCLUDEDIR} ${PC_CRYPTO_INCLUDE_DIRS}
38-
PATHS ${PATHS_CRYPTO_INCLUDEDIR}
39-
${CROSSCOMPILING_NO_CMAKE_SYSTEM_PATH}
40-
)
41-
set(CRYPTO_INCLUDEDIR ${CRYPTO_INCLUDEDIR1} ${CRYPTO_INCLUDEDIR2})
4235
endif()
4336

4437
include(FindPackageHandleStandardArgs)
@@ -47,6 +40,7 @@ find_package_handle_standard_args(Crypto DEFAULT_MSG CRYPTO_LIBRARY CRYPTO_INCLU
4740
mark_as_advanced(CRYPTO_LIBRARY CRYPTO_INCLUDEDIR)
4841

4942
if(CRYPTO_FOUND)
43+
is_bundled(CRYPTO_BUNDLED "${CRYPTO_LIBRARY}")
5044
set(CRYPTO_LIBRARIES ${CRYPTO_LIBRARY})
5145
set(CRYPTO_INCLUDE_DIRS ${CRYPTO_INCLUDEDIR})
5246
endif()

cmake/FindZLIB.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ if(NOT PREFER_BUNDLED_LIBS)
88
endif()
99
endif()
1010

11-
if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
11+
if(TARGET_OS STREQUAL "emscripten")
1212
set_extra_dirs_lib(ZLIB zlib)
1313
find_library(ZLIB_LIBRARY
1414
NAMES z

cmake/toolchains/Emscripten.toolchain

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
if(NOT DEFINED ENV{EMSDK})
2+
message(FATAL_ERROR "EMSDK environment variable must specify path of Emscripten SDK")
3+
endif()
4+
15
set(WASM_CXX_FLAGS "")
26
set(WASM_LINKER_FLAGS "")
37

@@ -54,6 +58,8 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
5458
else()
5559
# Will drastically reduce code size but also increases compile and link time significantly.
5660
set(WASM_CXX_FLAGS "${WASM_CXX_FLAGS} -O3")
61+
# Remove absolute paths of Emscripten SDK from binary.
62+
set(WASM_CXX_FLAGS "${WASM_CXX_FLAGS} -ffile-prefix-map=$ENV{EMSDK}=EMSDK")
5763
set(WASM_LINKER_FLAGS "${WASM_LINKER_FLAGS} -flto")
5864
endif()
5965

ddnet-libs

Submodule ddnet-libs updated 620 files

0 commit comments

Comments
 (0)