Add example of building TDLib for Android.
This commit is contained in:
parent
e7fa6741aa
commit
5479c640fe
44
example/android/AddIntDef.php
Normal file
44
example/android/AddIntDef.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
if ($argc !== 2) {
|
||||
exit();
|
||||
}
|
||||
$file = file_get_contents($argv[1]);
|
||||
|
||||
if (strpos($file, 'androidx.annotation.IntDef') !== false) {
|
||||
exit();
|
||||
}
|
||||
|
||||
$file = str_replace('import androidx.annotation.Nullable;', 'import androidx.annotation.IntDef;'.PHP_EOL.
|
||||
'import androidx.annotation.Nullable;'.PHP_EOL.
|
||||
PHP_EOL.
|
||||
'import java.lang.annotation.Retention;'.PHP_EOL.
|
||||
'import java.lang.annotation.RetentionPolicy;', $file);
|
||||
|
||||
preg_match_all('/public static class ([A-Za-z0-9]+) extends ([A-Za-z0-9]+)/', $file, $matches, PREG_SET_ORDER);
|
||||
$children = [];
|
||||
foreach ($matches as $val) {
|
||||
if ($val[2] === 'Object') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$children[$val[2]][] = PHP_EOL.' '.$val[1].'.CONSTRUCTOR';
|
||||
}
|
||||
|
||||
$file = preg_replace_callback('/public abstract static class ([A-Za-z0-9]+)(<R extends Object>)? extends Object [{]/',
|
||||
function ($val) use ($children) {
|
||||
return $val[0].PHP_EOL.' @Retention(RetentionPolicy.SOURCE)'.PHP_EOL.' @IntDef({'.implode(',', $children[$val[1]]).<<<'EOL'
|
||||
|
||||
})
|
||||
public @interface Constructors {}
|
||||
|
||||
/**
|
||||
* @return identifier uniquely determining type of the object.
|
||||
*/
|
||||
@Constructors
|
||||
@Override
|
||||
public abstract int getConstructor();
|
||||
EOL;
|
||||
},
|
||||
$file);
|
||||
|
||||
file_put_contents($argv[1], $file);
|
48
example/android/CMakeLists.txt
Normal file
48
example/android/CMakeLists.txt
Normal file
@ -0,0 +1,48 @@
|
||||
cmake_minimum_required(VERSION 3.4.1 FATAL_ERROR)
|
||||
|
||||
project(TdAndroid VERSION 1.0 LANGUAGES CXX)
|
||||
|
||||
option(TD_ENABLE_JNI "Enable JNI-compatible TDLib API" ON)
|
||||
|
||||
set(TD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../..)
|
||||
|
||||
if (CMAKE_CROSSCOMPILING)
|
||||
set(CMAKE_MODULE_PATH "${TD_DIR}/CMake")
|
||||
|
||||
include(TdSetUpCompiler)
|
||||
td_set_up_compiler()
|
||||
string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -flto=thin -Oz")
|
||||
|
||||
list(APPEND CMAKE_FIND_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/third-party/openssl/${ANDROID_ARCH_NAME}")
|
||||
add_subdirectory(${TD_DIR} td)
|
||||
|
||||
add_library(tdjni SHARED "${TD_DIR}/example/java/td_jni.cpp")
|
||||
|
||||
target_link_libraries(tdjni PRIVATE Td::TdStatic)
|
||||
target_compile_definitions(tdjni PRIVATE PACKAGE_NAME="org/drinkless/tdlib")
|
||||
|
||||
add_custom_command(TARGET tdjni POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E rename $<TARGET_FILE:tdjni> $<TARGET_FILE:tdjni>.debug
|
||||
COMMAND ${CMAKE_STRIP} --strip-debug --strip-unneeded $<TARGET_FILE:tdjni>.debug -o $<TARGET_FILE:tdjni>)
|
||||
else()
|
||||
add_subdirectory(${TD_DIR} td)
|
||||
|
||||
set(TD_API_JAVA_PACKAGE "org/drinkless/tdlib")
|
||||
set(TD_API_JAVA_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${TD_API_JAVA_PACKAGE}/TdApi.java")
|
||||
set(TD_API_TLO_PATH "${TD_DIR}/td/generate/auto/tlo/td_api.tlo")
|
||||
set(TD_API_TL_PATH "${TD_DIR}/td/generate/scheme/td_api.tl")
|
||||
set(JAVADOC_TL_DOCUMENTATION_GENERATOR_PATH "${TD_DIR}/td/generate/JavadocTlDocumentationGenerator.php")
|
||||
set(GENERATE_JAVA_CMD td_generate_java_api TdApi ${TD_API_TLO_PATH} ${CMAKE_CURRENT_SOURCE_DIR} ${TD_API_JAVA_PACKAGE})
|
||||
if (PHP_EXECUTABLE)
|
||||
set(GENERATE_JAVA_CMD ${GENERATE_JAVA_CMD} &&
|
||||
${PHP_EXECUTABLE} ${JAVADOC_TL_DOCUMENTATION_GENERATOR_PATH} ${TD_API_TL_PATH} ${TD_API_JAVA_PATH} androidx.annotation.Nullable @Nullable &&
|
||||
${PHP_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/AddIntDef.php ${TD_API_JAVA_PATH})
|
||||
endif()
|
||||
|
||||
file(MAKE_DIRECTORY ${TD_API_JAVA_PACKAGE})
|
||||
add_custom_target(tl_generate_java
|
||||
COMMAND ${GENERATE_JAVA_CMD}
|
||||
COMMENT "Generate Java TL source files"
|
||||
DEPENDS td_generate_java_api tl_generate_tlo ${TD_API_TLO_PATH} ${TD_API_TL_PATH}
|
||||
)
|
||||
endif()
|
18
example/android/README.md
Normal file
18
example/android/README.md
Normal file
@ -0,0 +1,18 @@
|
||||
# TDLib Android example
|
||||
|
||||
This is an example of building `TDLib` for Android.
|
||||
You need a Bash shell on Linux, macOS, or Windows with some common tools, cmake, JDK, PHP, and gperf pre-installed.
|
||||
|
||||
## Building TDLib for Android
|
||||
|
||||
* Run the script `./check-environment.sh` to check that you have all required Unix tools and Java utilities. If the script exits with an error message, install the missing tool.
|
||||
* Run the script `./fetch-sdk.sh` to download Android SDK to a local directory.
|
||||
* Run the script `./build-openssl.sh` to download and build OpenSSL for Android.
|
||||
* Run the script `./build-tdlib.sh` to build TDLib for Android.
|
||||
* The built libraries are now located in the `tdlib/libs` directory, corresponding Java code is located in the `tdlib/java` directory, and standalone Java documentation can be found in the `tdlib/javadoc` directory. You can also use archives `tdlib/tdlib.zip` and `tdlib/tdlib-debug.zip`, which contain all aforementioned data.
|
||||
|
||||
If you already have installed Android SDK and NDK, you can skip the second step and specify existing Android SDK root path and Android NDK version as parameters to the subsequent scripts. Make sure that the SDK includes android-33 platform.
|
||||
|
||||
If you want to update TDLib to a newer version, you need to run only the script `./build-tdlib.sh`.
|
||||
|
||||
You can specify different OpenSSL version as a third parameter to the script `./build-openssl.sh`. By default OpenSSL 1.1.1 is used because of much smaller binary footprint then newer OpenSSL versions.
|
68
example/android/build-openssl.sh
Executable file
68
example/android/build-openssl.sh
Executable file
@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env bash
|
||||
cd $(dirname $0)
|
||||
|
||||
ANDROID_SDK_ROOT=${1:-SDK}
|
||||
ANDROID_NDK_VERSION=${2:-23.2.8568313}
|
||||
OPENSSL=${3:-OpenSSL_1_1_1q} # openssl-3.0.5
|
||||
|
||||
OPENSSL_INSTALL_DIR="third-party/openssl"
|
||||
if [ -d "$OPENSSL_INSTALL_DIR" ] ; then
|
||||
echo "Error: directory $OPENSSL_INSTALL_DIR already exists. Delete it manually to proceed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source ./check-environment.sh
|
||||
|
||||
ANDROID_SDK_ROOT="$(cd "$(dirname -- "$ANDROID_SDK_ROOT")" >/dev/null; pwd -P)/$(basename -- "$ANDROID_SDK_ROOT")"
|
||||
|
||||
if [[ "$OS_NAME" == "linux" ]] ; then
|
||||
HOST_ARCH="linux-x86_64"
|
||||
elif [[ "$OS_NAME" == "mac" ]] ; then
|
||||
HOST_ARCH="darwin-x86_64"
|
||||
elif [[ "$OS_NAME" == "win" ]] ; then
|
||||
HOST_ARCH="windows-x86_64"
|
||||
else
|
||||
echo "Error: unsupported OS_NAME."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f $OPENSSL.tar.gz ] ; then
|
||||
echo "Downloading OpenSSL sources..."
|
||||
$WGET https://github.com/openssl/openssl/archive/refs/tags/$OPENSSL.tar.gz || exit 1
|
||||
fi
|
||||
rm -rf ./openssl-$OPENSSL || exit 1
|
||||
tar xzf $OPENSSL.tar.gz || exit 1
|
||||
rm $OPENSSL.tar.gz || exit 1
|
||||
cd openssl-$OPENSSL
|
||||
|
||||
export ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/$ANDROID_NDK_VERSION # for OpenSSL 3.0
|
||||
export ANDROID_NDK_HOME=$ANDROID_NDK_ROOT # for OpenSSL 1.1.1
|
||||
PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/$HOST_ARCH/bin:$PATH
|
||||
|
||||
for ARCH in arm64 arm x86_64 x86 ; do
|
||||
if [[ $ARCH == "x86" ]]; then
|
||||
./Configure android-x86 no-shared -U__ANDROID_API__ -D__ANDROID_API__=16 || exit 1
|
||||
elif [[ $ARCH == "x86_64" ]]; then
|
||||
./Configure android-x86_64 no-shared -U__ANDROID_API__ -D__ANDROID_API__=21 || exit 1
|
||||
elif [[ $ARCH == "arm" ]]; then
|
||||
./Configure android-arm no-shared -U__ANDROID_API__ -D__ANDROID_API__=16 -D__ARM_MAX_ARCH__=8 || exit 1
|
||||
elif [[ $ARCH == "arm64" ]]; then
|
||||
./Configure android-arm64 no-shared -U__ANDROID_API__ -D__ANDROID_API__=21 || exit 1
|
||||
fi
|
||||
|
||||
sed -i.bak 's/-O3/-O3 -ffunction-sections -fdata-sections/g' Makefile || exit 1
|
||||
|
||||
make depend -s || exit 1
|
||||
make -j4 -s || exit 1
|
||||
|
||||
rm -rf ../$OPENSSL_INSTALL_DIR/$ARCH/* || exit 1
|
||||
mkdir -p ../$OPENSSL_INSTALL_DIR/$ARCH/lib/ || exit 1
|
||||
cp libcrypto.a libssl.a ../$OPENSSL_INSTALL_DIR/$ARCH/lib/ || exit 1
|
||||
cp -r include ../$OPENSSL_INSTALL_DIR/$ARCH/ || exit 1
|
||||
|
||||
make distclean || exit 1
|
||||
done
|
||||
|
||||
cd ..
|
||||
|
||||
rm -rf ./openssl-$OPENSSL || exit 1
|
57
example/android/build-tdlib.sh
Executable file
57
example/android/build-tdlib.sh
Executable file
@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env bash
|
||||
cd $(dirname $0)
|
||||
|
||||
ANDROID_SDK_ROOT=${1:-SDK}
|
||||
ANDROID_NDK_VERSION=${2:-23.2.8568313}
|
||||
|
||||
source ./check-environment.sh
|
||||
|
||||
echo "Downloading annotation Java package..."
|
||||
rm -rf annotation || exit 1
|
||||
mkdir -p annotation || exit 1
|
||||
cd annotation
|
||||
$WGET https://maven.google.com/androidx/annotation/annotation/1.4.0/annotation-1.4.0.pom || exit 1
|
||||
$WGET https://maven.google.com/androidx/annotation/annotation/1.4.0/annotation-1.4.0.jar || exit 1
|
||||
cd ..
|
||||
|
||||
echo "Generating TDLib source files..."
|
||||
mkdir -p build-native || exit 1
|
||||
cd build-native
|
||||
cmake .. || exit 1
|
||||
cmake --build . --target prepare_cross_compiling || exit 1
|
||||
cmake --build . --target tl_generate_java || exit 1
|
||||
cd ..
|
||||
php AddIntDef.php org/drinkless/tdlib/TdApi.java || exit 1
|
||||
|
||||
echo "Copying Java source files..."
|
||||
rm -rf tdlib || exit 1
|
||||
mkdir -p tdlib/java/org/drinkless/tdlib || exit 1
|
||||
cp -p {../../example,tdlib}/java/org/drinkless/tdlib/Client.java || exit 1
|
||||
mv {,tdlib/java/}org/drinkless/tdlib/TdApi.java || exit 1
|
||||
rm -rf org || exit 1
|
||||
|
||||
echo "Generating Javadoc documentation..."
|
||||
javadoc -d tdlib/javadoc -encoding UTF-8 -charset UTF-8 -bootclasspath $ANDROID_SDK_ROOT/platforms/android-33/android.jar -extdirs annotation -classpath tdlib/java org.drinkless.tdlib || exit 1
|
||||
rm -rf annotation || exit 1
|
||||
|
||||
ANDROID_SDK_ROOT="$(cd "$(dirname -- "$ANDROID_SDK_ROOT")" >/dev/null; pwd -P)/$(basename -- "$ANDROID_SDK_ROOT")"
|
||||
|
||||
echo "Building TDLib..."
|
||||
for ABI in arm64-v8a armeabi-v7a x86_64 x86 ; do
|
||||
mkdir -p build-$ABI || exit 1
|
||||
cd build-$ABI
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=${ANDROID_SDK_ROOT}/ndk/${ANDROID_NDK_VERSION}/build/cmake/android.toolchain.cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -GNinja -DANDROID_ABI=${ABI} -DANDROID_PLATFORM=android-16 .. || exit 1
|
||||
cmake --build . || exit 1
|
||||
cd ..
|
||||
|
||||
mkdir -p tdlib/libs/$ABI/ || exit 1
|
||||
cp -p build-$ABI/libtd*.so* tdlib/libs/$ABI/ || exit 1
|
||||
done
|
||||
|
||||
echo "Compressing..."
|
||||
jar -cMf tdlib-debug.zip tdlib || exit 1
|
||||
rm tdlib/libs/*/*.debug || exit 1
|
||||
jar -cMf tdlib.zip tdlib || exit 1
|
||||
mv tdlib.zip tdlib-debug.zip tdlib
|
||||
|
||||
echo "Done."
|
42
example/android/check-environment.sh
Executable file
42
example/android/check-environment.sh
Executable file
@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# The script checks that all needed tools are installed and sets OS_NAME and WGET variables
|
||||
|
||||
if [[ "$OSTYPE" == "linux"* ]] ; then
|
||||
OS_NAME="linux"
|
||||
elif [[ "$OSTYPE" == "darwin"* ]] ; then
|
||||
OS_NAME="mac"
|
||||
elif [[ "$OSTYPE" == "msys" ]] ; then
|
||||
OS_NAME="win"
|
||||
else
|
||||
echo "Error: this script supports only Bash shell on Linux, macOS, or Windows."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if which wget >/dev/null 2>&1 ; then
|
||||
WGET="wget -q"
|
||||
elif which curl >/dev/null 2>&1 ; then
|
||||
WGET="curl -sfLO"
|
||||
else
|
||||
echo "Error: this script requires either curl or wget tool installed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for TOOL_NAME in cmake gperf jar javadoc make perl php sed tar yes unzip ; do
|
||||
if ! which "$TOOL_NAME" >/dev/null 2>&1 ; then
|
||||
echo "Error: this script requires $TOOL_NAME tool installed."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $(which make) = *" "* ]] ; then
|
||||
echo "Error: OpenSSL expects that full path to make tool doesn't contain spaces. Move it to some other place."
|
||||
fi
|
||||
|
||||
if ! perl -MExtUtils::MakeMaker -MLocale::Maketext::Simple -MPod::Usage -e '' >/dev/null 2>&1 ; then
|
||||
echo "Error: Perl installation is broken."
|
||||
if [[ "$OSTYPE" == "msys" ]] ; then
|
||||
echo "For Git Bash you need to manually copy ExtUtils, Locale and Pod modules to /usr/share/perl5/core_perl from any compatible Perl installation."
|
||||
fi
|
||||
exit 1
|
||||
fi
|
31
example/android/fetch-sdk.sh
Executable file
31
example/android/fetch-sdk.sh
Executable file
@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
cd $(dirname $0)
|
||||
|
||||
ANDROID_SDK_ROOT=${1:-SDK}
|
||||
ANDROID_NDK_VERSION=${2:-23.2.8568313}
|
||||
|
||||
if [ -d "$ANDROID_SDK_ROOT" ] ; then
|
||||
echo "Error: directory $ANDROID_SDK_ROOT already exists. Delete it manually to proceed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source ./check-environment.sh
|
||||
|
||||
SDKMANAGER="./sdkmanager"
|
||||
if [[ "$OS_NAME" == "win" ]] ; then
|
||||
SDKMANAGER="./sdkmanager.bat"
|
||||
fi
|
||||
|
||||
echo "Downloading SDK Manager..."
|
||||
mkdir -p "$ANDROID_SDK_ROOT" || exit 1
|
||||
cd "$ANDROID_SDK_ROOT" || exit 1
|
||||
$WGET "https://dl.google.com/android/repository/commandlinetools-$OS_NAME-8512546_latest.zip" || exit 1
|
||||
mkdir -p cmdline-tools || exit 1
|
||||
unzip -qq "commandlinetools-$OS_NAME-8512546_latest.zip" -d cmdline-tools || exit 1
|
||||
rm "commandlinetools-$OS_NAME-8512546_latest.zip" || exit 1
|
||||
mv cmdline-tools/* cmdline-tools/latest/ || exit 1
|
||||
|
||||
echo "Installing required SDK tools..."
|
||||
cd cmdline-tools/latest/bin/ || exit 1
|
||||
yes | $SDKMANAGER --licenses >/dev/null || exit 1
|
||||
$SDKMANAGER --install "platform-tools" "ndk;$ANDROID_NDK_VERSION" "cmake;3.22.1" "build-tools;33.0.0" "platforms;android-33" > /dev/null || exit 1
|
Loading…
Reference in New Issue
Block a user