build: Add apk_package target for building Android APK

This commit is contained in:
Hennadii Stepanov 2025-04-13 18:00:13 +01:00
parent 33d817dd24
commit b136afd990
No known key found for this signature in database
GPG key ID: 410108112E7EA81F
11 changed files with 169 additions and 0 deletions

View file

@ -241,6 +241,8 @@ $(host_prefix)/toolchain.cmake : toolchain.cmake.in $(host_prefix)/.stamp_$(fina
-e 's|@multiprocess@|$(MULTIPROCESS)|' \ -e 's|@multiprocess@|$(MULTIPROCESS)|' \
-e 's|@android_abi@|$(android_abi)|' \ -e 's|@android_abi@|$(android_abi)|' \
-e 's|@android_ndk@|$(ANDROID_NDK)|' \ -e 's|@android_ndk@|$(ANDROID_NDK)|' \
-e 's|@android_toolchain_bin_dir@|$(android_toolchain_bin_dir)|' \
-e 's|@android_libcxx_shared_dir@|$(android_libcxx_shared_dir)|' \
$< > $@ $< > $@
touch $@ touch $@

View file

@ -5,9 +5,11 @@ android_toolchain_bin_dir := $(ANDROID_NDK)/toolchains/llvm/prebuilt/$(build_os)
ifeq ($(HOST),armv7a-linux-android) ifeq ($(HOST),armv7a-linux-android)
android_CXX := $(android_toolchain_bin_dir)/$(HOST)eabi$(ANDROID_API_LEVEL)-clang++ android_CXX := $(android_toolchain_bin_dir)/$(HOST)eabi$(ANDROID_API_LEVEL)-clang++
android_CC := $(android_toolchain_bin_dir)/$(HOST)eabi$(ANDROID_API_LEVEL)-clang android_CC := $(android_toolchain_bin_dir)/$(HOST)eabi$(ANDROID_API_LEVEL)-clang
android_libcxx_shared_dir := arm-linux-androideabi
else else
android_CXX := $(android_toolchain_bin_dir)/$(HOST)$(ANDROID_API_LEVEL)-clang++ android_CXX := $(android_toolchain_bin_dir)/$(HOST)$(ANDROID_API_LEVEL)-clang++
android_CC := $(android_toolchain_bin_dir)/$(HOST)$(ANDROID_API_LEVEL)-clang android_CC := $(android_toolchain_bin_dir)/$(HOST)$(ANDROID_API_LEVEL)-clang
android_libcxx_shared_dir := $(host_arch)-linux-android
endif endif
android_CXXFLAGS := -std=$(CXX_STANDARD) android_CXXFLAGS := -std=$(CXX_STANDARD)

View file

@ -287,6 +287,9 @@ endef
define $(package)_stage_cmds define $(package)_stage_cmds
cmake --install . --prefix $($(package)_staging_prefix_dir) cmake --install . --prefix $($(package)_staging_prefix_dir)
endef endef
ifeq ($(host_os),android)
$(package)_stage_cmds += && cp -r $($(package)_extract_dir)/qtbase/src/android/jar/src $($(package)_staging_prefix_dir)/src/android/java
endif
define $(package)_postprocess_cmds define $(package)_postprocess_cmds
rm -rf doc/ rm -rf doc/

View file

@ -8,6 +8,18 @@ if("@host_system_name@" STREQUAL "Android")
set(ANDROID_ABI @android_abi@) set(ANDROID_ABI @android_abi@)
set(ANDROID_PLATFORM android-@host_system_version@) set(ANDROID_PLATFORM android-@host_system_version@)
include(@android_ndk@/build/cmake/android.toolchain.cmake) include(@android_ndk@/build/cmake/android.toolchain.cmake)
# Qt's Java sources for Android Application Package (APK).
cmake_path(SET ANDROID_APK_SRC "${CMAKE_CURRENT_LIST_DIR}/src/android/java")
# The libc++_shared.so shared library, provided by the Android SDK,
# is required to build an Android Application Package (APK).
cmake_path(SET ANDROID_SHARED_CXX_LIB NORMALIZE "@android_toolchain_bin_dir@/../sysroot/usr/lib/@android_libcxx_shared_dir@/libc++_shared.so")
# Qt recommends using the same Gradle version that it comes with.
# Therefore, we use the Gradle wrapper provided by Qt to build
# an Android Application Package (APK).
# See:
# - https://doc.qt.io/qt-6/deployment-android.html
# - https://doc.qt.io/qt-6/qtcore-attribution-android-gradle-wrapper.html
cmake_path(SET GRADLEW_EXECUTABLE "${CMAKE_CURRENT_LIST_DIR}/src/3rdparty/gradle/gradlew")
else() else()
# If CMAKE_SYSTEM_NAME is set within a toolchain file, CMake will also # If CMAKE_SYSTEM_NAME is set within a toolchain file, CMake will also
# set CMAKE_CROSSCOMPILING to TRUE, even if CMAKE_SYSTEM_NAME matches # set CMAKE_CROSSCOMPILING to TRUE, even if CMAKE_SYSTEM_NAME matches

View file

@ -362,3 +362,7 @@ else()
VERBATIM VERBATIM
) )
endif() endif()
if(ANDROID)
add_subdirectory(android)
endif()

View file

@ -0,0 +1,35 @@
<?xml version='1.0' encoding='utf-8'?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt.android.bindings.QtApplication" android:label="Bitcoin Core" android:icon="@drawable/bitcoin">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
android:name="org.bitcoincore.qt.BitcoinQtActivity"
android:screenOrientation="unspecified"
android:launchMode="singleTop"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<meta-data android:name="android.app.arguments" android:value="-testnet"/>
<meta-data android:name="android.app.lib_name" android:value="bitcoin-qt"/>
<meta-data android:name="android.app.repository" android:value="default"/>
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="1"/>
<meta-data android:name="android.app.use_local_qt_libs" android:value="1"/>
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
<meta-data android:name="android.app.system_libs_prefix" android:value="/system/lib/"/>
<meta-data android:name="android.app.background_running" android:value="true"/>
<meta-data android:name="android.app.auto_screen_scale_factor" android:value="true"/>
<meta-data android:name="android.app.extract_android_style" android:value="default"/>
<meta-data android:name="android.app.load_local_libs_resource_id" android:resource="@array/load_local_libs"/>
</activity>
</application>
</manifest>

View file

@ -0,0 +1,19 @@
# Copyright (c) 2025 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
PATTERN "CMakeLists.txt" EXCLUDE
)
file(COPY ${ANDROID_APK_SRC}/src/org DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/src)
file(COPY ${ANDROID_SHARED_CXX_LIB} DESTINATION libs/${CMAKE_ANDROID_ARCH_ABI})
cmake_path(RELATIVE_PATH GRADLEW_EXECUTABLE BASE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_custom_target(apk_package
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:bitcoin-qt> libs/${CMAKE_ANDROID_ARCH_ABI}/libbitcoin-qt_${CMAKE_ANDROID_ARCH_ABI}.so
COMMAND ${GRADLEW_EXECUTABLE} build
VERBATIM
)

View file

@ -0,0 +1,51 @@
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.0.2'
}
}
repositories {
google()
mavenCentral()
}
apply plugin: 'com.android.application'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
android {
compileSdkVersion androidCompileSdkVersion.toInteger()
buildToolsVersion androidBuildToolsVersion
namespace 'org.bitcoincore.qt'
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = [qtAndroidDir + '/src', 'src', 'java']
aidl.srcDirs = [qtAndroidDir + '/src', 'src', 'aidl']
res.srcDirs = [qtAndroidDir + '/res', 'res']
resources.srcDirs = ['src']
renderscript.srcDirs = ['src']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs']
}
}
lintOptions {
abortOnError false
}
defaultConfig {
minSdkVersion 26
targetSdk 33
}
}

View file

@ -0,0 +1,4 @@
androidBuildToolsVersion=33.0.3
androidCompileSdkVersion=33
qtAndroidDir=new File(".").absolutePath
org.gradle.jvmargs=-Xmx4608M

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="load_local_libs">
<item>
arm64-v8a;libbitcoin-qt_arm64-v8a.so
</item>
<item>
armeabi-v7a;libbitcoin-qt_armeabi-v7a.so
</item>
<item>
x86_64;libbitcoin-qt_x86_64.so
</item>
</array>
</resources>

View file

@ -0,0 +1,23 @@
package org.bitcoincore.qt;
import android.os.Bundle;
import android.system.ErrnoException;
import android.system.Os;
import org.qtproject.qt.android.bindings.QtActivity;
import java.io.File;
public class BitcoinQtActivity extends QtActivity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
final File bitcoinDir = new File(getFilesDir().getAbsolutePath() + "/.bitcoin");
if (!bitcoinDir.exists()) {
bitcoinDir.mkdir();
}
super.onCreate(savedInstanceState);
}
}