Android: Integrate vcpkg with Gradle build

This ensures that vcpkg downloads and builds all dependencies for
Android. We add it as a CMAKE_TOOLCHAIN_FILE that then chainloads the
Android NDK's toolchain file, as per the vcpkg documentation.
This commit is contained in:
Alex Studer 2024-07-03 15:17:16 -04:00 committed by Andrew Kaster
parent ab82fc8993
commit 1d0de0b450
Notes: sideshowbarker 2024-07-16 22:54:10 +09:00
5 changed files with 132 additions and 7 deletions

View file

@ -1,5 +1,12 @@
cmake_minimum_required(VERSION 3.25)
if (VCPKG_TARGET_ANDROID)
# If we are building for Android, we must load vcpkg_android.cmake before the project() declaration.
# This ensures that the CMAKE_TOOLCHAIN_FILE is set correctly.
# (we cannot set CMAKE_TOOLCHAIN_FILE from Gradle, unfortunately, so this is the only place we can do it.)
include("Ladybird/Android/vcpkg_android.cmake")
endif()
project(ladybird
VERSION 0.1.0
LANGUAGES C CXX

View file

@ -4,24 +4,39 @@ set -eo pipefail
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
SERENITY_ROOT="$(realpath "${DIR}"/../..)"
LADYBIRD_SOURCE_DIR="$(realpath "${DIR}"/../..)"
# shellcheck source=/dev/null
. "${SERENITY_ROOT}/Meta/shell_include.sh"
. "${LADYBIRD_SOURCE_DIR}/Meta/shell_include.sh"
# shellcheck source=/dev/null
. "${SERENITY_ROOT}/Meta/find_compiler.sh"
. "${LADYBIRD_SOURCE_DIR}/Meta/find_compiler.sh"
pick_host_compiler
BUILD_DIR=${BUILD_DIR:-"${SERENITY_ROOT}/Build"}
BUILD_DIR=${BUILD_DIR:-"${LADYBIRD_SOURCE_DIR}/Build"}
CACHE_DIR=${CACHE_DIR:-"${BUILD_DIR}/caches"}
cmake -S "$SERENITY_ROOT/Meta/Lagom" -B "$BUILD_DIR/lagom-tools" \
# HACK: This export of XDG_CACHE_HOME is required to make vcpkg happy.
# This is because vcpkg tries to find a cache directory by:
# 1) checking $XDG_CACHE_HOME
# 2) appending "/.cache" to $HOME
# The problem is, in the Android build environment, neither of those environment variables are set.
# This causes vcpkg to fail; so, we set a dummy $XDG_CACHE_HOME, ensuring that vcpkg is happy.
# (Note that vcpkg appends "/vcpkg" to the cache directory we give it.)
# (And this also works on macOS, despite the fact that $XDG_CACHE_HOME is a Linux-ism.)
export XDG_CACHE_HOME="$CACHE_DIR"
cmake -S "${LADYBIRD_SOURCE_DIR}/Meta/Lagom" -B "$BUILD_DIR/lagom-tools" \
-GNinja -Dpackage=LagomTools \
-DCMAKE_INSTALL_PREFIX="$BUILD_DIR/lagom-tools-install" \
-DCMAKE_C_COMPILER="$CC" \
-DCMAKE_CXX_COMPILER="$CXX" \
-DSERENITY_CACHE_DIR="$CACHE_DIR"
-DSERENITY_CACHE_DIR="$CACHE_DIR" \
-DCMAKE_TOOLCHAIN_FILE="$LADYBIRD_SOURCE_DIR/Toolchain/Tarballs/vcpkg/scripts/buildsystems/vcpkg.cmake" \
-DVCPKG_INSTALL_OPTIONS="--no-print-usage" \
-DVCPKG_OVERLAY_TRIPLETS="$LADYBIRD_SOURCE_DIR/Meta/CMake/vcpkg/release-triplets" \
-DVCPKG_ROOT="$LADYBIRD_SOURCE_DIR/Toolchain/Tarballs/vcpkg" \
-DVCPKG_MANIFEST_DIR="$LADYBIRD_SOURCE_DIR"
ninja -C "$BUILD_DIR/lagom-tools" install

View file

@ -7,6 +7,7 @@ plugins {
var buildDir = layout.buildDirectory.get()
var cacheDir = System.getenv("SERENITY_CACHE_DIR") ?: "$buildDir/caches"
var sourceDir = layout.projectDirectory.dir("../../").toString()
task<Exec>("buildLagomTools") {
commandLine = listOf("./BuildLagomTools.sh")
@ -36,7 +37,9 @@ android {
cppFlags += "-std=c++23"
arguments += listOf(
"-DLagomTools_DIR=$buildDir/lagom-tools-install/share/LagomTools",
"-DSERENITY_CACHE_DIR=$cacheDir"
"-DSERENITY_CACHE_DIR=$cacheDir",
"-DVCPKG_ROOT=$sourceDir/Toolchain/Tarballs/vcpkg",
"-DVCPKG_TARGET_ANDROID=ON"
)
}
}

View file

@ -0,0 +1,96 @@
# This file is based on the vcpkg Android example from here https://github.com/microsoft/vcpkg-docs/blob/06b496c3f24dbe651fb593a26bee50537eeaf4e5/vcpkg/examples/vcpkg_android_example_cmake_script/cmake/vcpkg_android.cmake
# It was modified to use CMake variables instead of environment variables, because it's not possible to set environment variables in the Android Gradle plugin.
#
# vcpkg_android.cmake
#
# Helper script when using vcpkg with cmake. It should be triggered via the variable VCPKG_TARGET_ANDROID
#
# For example:
# if (VCPKG_TARGET_ANDROID)
# include("cmake/vcpkg_android.cmake")
# endif()
#
# This script will:
# 1 & 2. check the presence of needed env variables: ANDROID_NDK and VCPKG_ROOT
# 3. set VCPKG_TARGET_TRIPLET according to ANDROID_ABI
# 4. Combine vcpkg and Android toolchains by setting CMAKE_TOOLCHAIN_FILE
# and VCPKG_CHAINLOAD_TOOLCHAIN_FILE
# Note: VCPKG_TARGET_ANDROID is not an official vcpkg variable.
# it is introduced for the need of this script
if (VCPKG_TARGET_ANDROID)
#
# 1. Check the presence of variable ANDROID_NDK
#
if (NOT DEFINED ANDROID_NDK)
message(FATAL_ERROR "Please set CMake variable ANDROID_NDK")
endif()
#
# 2. Check the presence of environment variable VCPKG_ROOT
#
if (NOT DEFINED VCPKG_ROOT)
message(FATAL_ERROR "Please set a CMake variable VCPKG_ROOT")
endif()
#
# 3. Set VCPKG_TARGET_TRIPLET according to ANDROID_ABI
#
# There are four different Android ABI, each of which maps to
# a vcpkg triplet. The following table outlines the mapping from vcpkg architectures to android architectures
#
# |VCPKG_TARGET_TRIPLET | ANDROID_ABI |
# |---------------------------|----------------------|
# |arm64-android | arm64-v8a |
# |arm-android | armeabi-v7a |
# |x64-android | x86_64 |
# |x86-android | x86 |
#
# The variable must be stored in the cache in order to successfully the two toolchains.
#
if (ANDROID_ABI MATCHES "arm64-v8a")
set(VCPKG_TARGET_TRIPLET "arm64-android" CACHE STRING "" FORCE)
elseif(ANDROID_ABI MATCHES "armeabi-v7a")
set(VCPKG_TARGET_TRIPLET "arm-android" CACHE STRING "" FORCE)
elseif(ANDROID_ABI MATCHES "x86_64")
set(VCPKG_TARGET_TRIPLET "x64-android" CACHE STRING "" FORCE)
elseif(ANDROID_ABI MATCHES "x86")
set(VCPKG_TARGET_TRIPLET "x86-android" CACHE STRING "" FORCE)
else()
message(FATAL_ERROR "
Please specify ANDROID_ABI
For example
cmake ... -DANDROID_ABI=armeabi-v7a
Possible ABIs are: arm64-v8a, armeabi-v7a, x64-android, x86-android
")
endif()
message("vcpkg_android.cmake: VCPKG_TARGET_TRIPLET was set to ${VCPKG_TARGET_TRIPLET}")
#
# 4. Combine vcpkg and Android toolchains
#
# vcpkg and android both provide dedicated toolchains:
#
# vcpkg_toolchain_file=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake
# android_toolchain_file=$ANDROID_NDK/build/cmake/android.toolchain.cmake
#
# When using vcpkg, the vcpkg toolchain shall be specified first.
# However, vcpkg provides a way to preload and additional toolchain,
# with the VCPKG_CHAINLOAD_TOOLCHAIN_FILE option.
set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE ${ANDROID_NDK}/build/cmake/android.toolchain.cmake)
set(CMAKE_TOOLCHAIN_FILE ${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake)
message("vcpkg_android.cmake: CMAKE_TOOLCHAIN_FILE was set to ${CMAKE_TOOLCHAIN_FILE}")
message("vcpkg_android.cmake: VCPKG_CHAINLOAD_TOOLCHAIN_FILE was set to ${VCPKG_CHAINLOAD_TOOLCHAIN_FILE}")
# vcpkg depends on the environment variables ANDROID_NDK_HOME and VCPKG_ROOT being set.
# However, we cannot set those through the Android Gradle plugin (we can only set CMake variables).
# Therefore, we forward our CMake variables to environment variables.
# FIXME: would be nice if vcpkg's android toolchain did not require this...
set(ENV{ANDROID_NDK_HOME} ${ANDROID_NDK})
set(ENV{VCPKG_ROOT} ${VCPKG_ROOT})
endif(VCPKG_TARGET_ANDROID)

View file

@ -27,6 +27,10 @@
"vulkan"
]
},
{
"name": "skia",
"platform": "android"
},
"sqlite3",
"woff2"
],