Compare commits

...

7 commits

Author SHA1 Message Date
Hennadii Stepanov
9cc58038c0
Merge fec1a7029a into c5e44a0435 2025-04-29 11:52:27 +02:00
merge-script
c5e44a0435
Merge bitcoin/bitcoin#32369: test: Use the correct node for doubled keypath test
Some checks are pending
CI / macOS 14 native, arm64, fuzz (push) Waiting to run
CI / Windows native, VS 2022 (push) Waiting to run
CI / Windows native, fuzz, VS 2022 (push) Waiting to run
CI / Linux->Windows cross, no tests (push) Waiting to run
CI / Windows, test cross-built (push) Blocked by required conditions
CI / ASan + LSan + UBSan + integer, no depends, USDT (push) Waiting to run
CI / test each commit (push) Waiting to run
CI / macOS 14 native, arm64, no depends, sqlite only, gui (push) Waiting to run
32d55e28af test: Use the correct node for doubled keypath test (Ava Chow)

Pull request description:

  #29124 had a silent merge conflict with #32350 which resulted in it using the wrong node. Fix the test to use the correct v22 node.

ACKs for top commit:
  maflcko:
    lgtm ACK 32d55e28af
  rkrux:
    ACK 32d55e28af
  BrandonOdiwuor:
    Code Review ACK 32d55e28af

Tree-SHA512: 1e0231985beb382b16e1d608c874750423d0502388db0c8ad450b22d17f9d96f5e16a6b44948ebda5efc750f62b60d0de8dd20131f449427426a36caf374af92
2025-04-29 09:59:42 +01:00
Ava Chow
32d55e28af test: Use the correct node for doubled keypath test 2025-04-28 14:44:17 -07:00
Hennadii Stepanov
fec1a7029a
doc: Update documentation for Android builds 2025-04-13 18:00:15 +01:00
Hennadii Stepanov
b136afd990
build: Add apk_package target for building Android APK 2025-04-13 18:00:13 +01:00
Hennadii Stepanov
33d817dd24
qt: Revert back Android icons
This change is necessary for a subsequent commit and partially reverts
commit 5deb0b024e.
2025-04-13 17:06:05 +01:00
Hennadii Stepanov
206cb5ead4
build: Restore cross-compilation for Android
This change partially reverts 5deb0b024e
and includes additional related adjustments.
2025-04-13 17:05:03 +01:00
28 changed files with 537 additions and 46 deletions

View file

@ -702,7 +702,11 @@ message(" bench_bitcoin ....................... ${BUILD_BENCH}")
message(" fuzz binary ......................... ${BUILD_FUZZ_BINARY}")
message("")
if(CMAKE_CROSSCOMPILING)
set(cross_status "TRUE, for ${CMAKE_SYSTEM_NAME}, ${CMAKE_SYSTEM_PROCESSOR}")
if(ANDROID)
set(cross_status "TRUE, for ${CMAKE_SYSTEM_NAME}, ${CMAKE_ANDROID_ARCH_ABI}")
else()
set(cross_status "TRUE, for ${CMAKE_SYSTEM_NAME}, ${CMAKE_SYSTEM_PROCESSOR}")
endif()
else()
set(cross_status "FALSE")
endif()

View file

@ -97,6 +97,10 @@ host_os+=$(findstring netbsd,$(full_host_os))
host_os+=$(findstring openbsd,$(full_host_os))
host_os+=$(findstring mingw32,$(full_host_os))
ifeq (android,$(findstring android,$(full_host_os)))
host_os:=android
endif
host_os:=$(strip $(host_os))
ifeq ($(host_os),)
host_os=$(full_host_os)
@ -235,6 +239,10 @@ $(host_prefix)/toolchain.cmake : toolchain.cmake.in $(host_prefix)/.stamp_$(fina
-e 's|@bdb_packages@|$(bdb_packages_)|' \
-e 's|@usdt_packages@|$(usdt_packages_)|' \
-e 's|@multiprocess@|$(MULTIPROCESS)|' \
-e 's|@android_abi@|$(android_abi)|' \
-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 $@

View file

@ -34,8 +34,11 @@ Common `host-platform-triplet`s for cross compilation are:
- `riscv32-linux-gnu` for Linux RISC-V 32 bit
- `riscv64-linux-gnu` for Linux RISC-V 64 bit
- `s390x-linux-gnu` for Linux S390X
- `armv7a-linux-android` for Android ARM 32 bit
- `aarch64-linux-android` for Android ARM 64 bit
- `x86_64-linux-android` for Android x86 64 bit
The paths are automatically configured and no other options are needed.
The paths are automatically configured and no other options are needed unless targeting [Android](../doc/build-android.md).
### Install the required dependencies: Ubuntu & Debian

View file

@ -207,33 +207,45 @@ ifneq ($($(1)_ldflags),)
$(1)_autoconf += LDFLAGS="$$($(1)_ldflags)"
endif
$(1)_cmake = env CFLAGS="$$($(1)_cppflags) $$($(1)_cflags)" \
CXXFLAGS="$$($(1)_cppflags) $$($(1)_cxxflags)" \
LDFLAGS="$$($(1)_ldflags)"
ifeq ($(host_os),android)
# For Android, we use the toolchain file provided by the Android SDK.
# See: https://developer.android.com/ndk/guides/cmake
$(1)_cmake += cmake \
-DANDROID_ABI=$(android_abi) \
-DANDROID_PLATFORM=android-$(android_cmake_system_version) \
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=$(ANDROID_NDK)/build/cmake/android.toolchain.cmake
else
$(1)_cmake += CC="$$($(1)_cc)" \
CXX="$$($(1)_cxx)"
$(1)_cmake += cmake \
-DCMAKE_AR=`which $$($(1)_ar)` \
-DCMAKE_NM=`which $$($FILEPATH(1)_nm)` \
-DCMAKE_RANLIB=`which $$($(1)_ranlib)`
endif
$(1)_cmake += -G "Unix Makefiles" \
-DCMAKE_INSTALL_PREFIX:PATH="$$($($(1)_type)_prefix)" \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DCMAKE_VERBOSE_MAKEFILE:BOOL=$(V) \
$$($(1)_config_opts)
# We hardcode the library install path to "lib" to match the PKG_CONFIG_PATH
# setting in depends/toolchain.cmake.in, which also hardcodes "lib".
# Without this setting, CMake by default would use the OS library
# directory, which might be "lib64" or something else, not "lib", on multiarch systems.
$(1)_cmake=env CC="$$($(1)_cc)" \
CFLAGS="$$($(1)_cppflags) $$($(1)_cflags)" \
CXX="$$($(1)_cxx)" \
CXXFLAGS="$$($(1)_cppflags) $$($(1)_cxxflags)" \
LDFLAGS="$$($(1)_ldflags)" \
cmake -G "Unix Makefiles" \
-DCMAKE_INSTALL_PREFIX:PATH="$$($($(1)_type)_prefix)" \
-DCMAKE_AR=`which $$($(1)_ar)` \
-DCMAKE_NM=`which $$($(1)_nm)` \
-DCMAKE_RANLIB=`which $$($(1)_ranlib)` \
-DCMAKE_INSTALL_LIBDIR=lib/ \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DCMAKE_VERBOSE_MAKEFILE:BOOL=$(V) \
$$($(1)_config_opts)
$(1)_cmake += -DCMAKE_INSTALL_LIBDIR=lib/
ifeq ($($(1)_type),build)
$(1)_cmake += -DCMAKE_INSTALL_RPATH:PATH="$$($($(1)_type)_prefix)/lib"
else
ifneq ($(host),$(build))
ifneq ($(host_os),android)
$(1)_cmake += -DCMAKE_SYSTEM_NAME=$($(host_os)_cmake_system_name)
$(1)_cmake += -DCMAKE_C_COMPILER_TARGET=$(host)
$(1)_cmake += -DCMAKE_CXX_COMPILER_TARGET=$(host)
endif
endif
endif
endef
define int_add_cmds

31
depends/hosts/android.mk Normal file
View file

@ -0,0 +1,31 @@
ANDROID_API_LEVEL ?= 26
android_toolchain_bin_dir := $(ANDROID_NDK)/toolchains/llvm/prebuilt/$(build_os)-$(build_arch)/bin
ifeq ($(HOST),armv7a-linux-android)
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_libcxx_shared_dir := arm-linux-androideabi
else
android_CXX := $(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
android_CXXFLAGS := -std=$(CXX_STANDARD)
android_CFLAGS := -std=$(C_STANDARD)
android_AR := $(android_toolchain_bin_dir)/llvm-ar
android_RANLIB := $(android_toolchain_bin_dir)/llvm-ranlib
android_cmake_system_name := Android
android_cmake_system_version := $(ANDROID_API_LEVEL)
# https://developer.android.com/ndk/guides/abis
ifeq ($(host_arch),armv7a)
android_abi := armeabi-v7a
else ifeq ($(host_arch),aarch64)
android_abi := arm64-v8a
else ifeq ($(host_arch),x86_64)
android_abi := x86_64
endif

View file

@ -4,6 +4,7 @@ $(package)_download_path=https://github.com/libevent/libevent/releases/download/
$(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_sha256_hash=92e6de1be9ec176428fd2367677e61ceffc2ee1cb119035037a27d346b0403bb
$(package)_patches=cmake_fixups.patch
$(package)_patches += android_threads_fixup.patch
$(package)_patches += netbsd_fixup.patch
$(package)_build_subdir=build
@ -21,6 +22,7 @@ endef
define $(package)_preprocess_cmds
patch -p1 < $($(package)_patch_dir)/cmake_fixups.patch && \
patch -p1 < $($(package)_patch_dir)/android_threads_fixup.patch && \
patch -p1 < $($(package)_patch_dir)/netbsd_fixup.patch
endef

View file

@ -5,10 +5,12 @@ boost_packages = boost
libevent_packages = libevent
qrencode_linux_packages = qrencode
qrencode_android_packages = qrencode
qrencode_darwin_packages = qrencode
qrencode_mingw32_packages = qrencode
qt_linux_packages:=qt expat libxcb xcb_proto libXau xproto freetype fontconfig libxkbcommon libxcb_util libxcb_util_cursor libxcb_util_render libxcb_util_keysyms libxcb_util_image libxcb_util_wm
qt_android_packages=qt
qt_darwin_packages=qt
qt_mingw32_packages=qt
ifneq ($(host),$(build))

View file

@ -10,6 +10,8 @@ endif
$(package)_linux_dependencies=freetype fontconfig libxcb libxkbcommon libxcb_util libxcb_util_cursor libxcb_util_render libxcb_util_keysyms libxcb_util_image libxcb_util_wm
$(package)_patches_path := $(qt_details_patches_path)
$(package)_patches := dont_hardcode_pwd.patch
$(package)_patches += fix_android_duplicate_symbol.patch
$(package)_patches += fix_android_jni_static.patch
$(package)_patches += qtbase-moc-ignore-gcc-macro.patch
$(package)_patches += qtbase_avoid_native_float16.patch
$(package)_patches += qtbase_avoid_qmain.patch
@ -154,6 +156,16 @@ ifneq ($(LTO),)
$(package)_config_opts_mingw32 += -ltcg
endif
$(package)_config_opts_android = -android-sdk $(ANDROID_SDK)
$(package)_config_opts_android += -android-ndk $(ANDROID_NDK)
$(package)_config_opts_android += -android-ndk-platform android-$(ANDROID_API_LEVEL)
$(package)_config_opts_android += -android-abis $(android_abi)
$(package)_config_opts_android += -egl
$(package)_config_opts_android += -no-dbus
$(package)_config_opts_android += -no-fontconfig
$(package)_config_opts_android += -opengl es2
$(package)_config_opts_android += -qt-freetype
# CMake build options.
$(package)_config_env := CC="$$($(package)_cc)"
$(package)_config_env += CXX="$$($(package)_cxx)"
@ -257,6 +269,8 @@ endif
define $(package)_preprocess_cmds
patch -p1 -i $($(package)_patch_dir)/dont_hardcode_pwd.patch && \
patch -p1 -i $($(package)_patch_dir)/fix_android_duplicate_symbol.patch && \
patch -p1 -i $($(package)_patch_dir)/fix_android_jni_static.patch && \
patch -p1 -i $($(package)_patch_dir)/qtbase-moc-ignore-gcc-macro.patch && \
patch -p1 -i $($(package)_patch_dir)/qtbase_avoid_native_float16.patch && \
patch -p1 -i $($(package)_patch_dir)/qtbase_avoid_qmain.patch && \
@ -281,6 +295,9 @@ endef
define $(package)_stage_cmds
cmake --install . --prefix $($(package)_staging_prefix_dir)
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
rm -rf doc/

View file

@ -0,0 +1,21 @@
cmake: Fix Android build.
Android/Bionic C library needs no special flags to have threading support.
Found when trying to build with vcpkg.
See https://github.com/libevent/libevent/commit/8f47d8de281b877450474734594fdc0a60ee35d1.
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -858,6 +858,11 @@ endif()
if (NOT EVENT__DISABLE_THREAD_SUPPORT)
if (WIN32)
list(APPEND SRC_CORE evthread_win32.c)
+ elseif(ANDROID)
+ # pthreads is built in to bionic
+ set(EVENT__HAVE_PTHREADS 1)
+ CHECK_TYPE_SIZE(pthread_t EVENT__SIZEOF_PTHREAD_T)
+ list(APPEND SYMBOLS_TO_CHECK pthread_mutexattr_setprotocol)
else()
find_package(Threads REQUIRED)
if (NOT CMAKE_USE_PTHREADS_INIT)

View file

@ -0,0 +1,157 @@
Fix "duplicate symbol: JNI_OnLoad" linker error
Qt does not officially support static linking on Android. See:
- https://bugreports.qt.io/browse/QTBUG-36097
- https://bugreports.qt.io/browse/QTBUG-102326
Reverting upstream commit 175e3ac8fabc864ffcc23c7769eaf7f220bddf59
avoids the linker error.
Note: the revert is not clean and required minor adjustments.
--- a/qtbase/src/corelib/CMakeLists.txt
+++ b/qtbase/src/corelib/CMakeLists.txt
@@ -1016,6 +1016,7 @@ qt_internal_extend_target(Core CONDITION ANDROID
kernel/qjnienvironment.cpp kernel/qjnienvironment.h
kernel/qjniobject.cpp kernel/qjniobject.h
kernel/qjnihelpers.cpp kernel/qjnihelpers_p.h
+ kernel/qjnionload.cpp
platform/android/qandroidextras_p.h platform/android/qandroidextras.cpp
platform/android/qandroidnativeinterface.cpp
NO_UNITY_BUILD_SOURCES
--- a/qtbase/src/corelib/kernel/qjnihelpers.cpp
+++ b/qtbase/src/corelib/kernel/qjnihelpers.cpp
@@ -12,7 +12,6 @@
#include <QtCore/private/qcoreapplication_p.h>
#include <QtCore/private/qlocking_p.h>
-#include <android/log.h>
#include <deque>
#include <memory>
@@ -349,38 +348,3 @@ void QtAndroidPrivate::releaseAndroidDeadlockProtector()
}
QT_END_NAMESPACE
-
-JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
-{
- Q_UNUSED(reserved);
-
- static const char logTag[] = "QtCore";
- static bool initialized = false;
- if (initialized)
- return JNI_VERSION_1_6;
- initialized = true;
-
- typedef union {
- JNIEnv *nenv;
- void *venv;
- } _JNIEnv;
-
- __android_log_print(ANDROID_LOG_INFO, logTag, "Start");
-
- _JNIEnv uenv;
- uenv.venv = nullptr;
-
- if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_6) != JNI_OK) {
- __android_log_print(ANDROID_LOG_FATAL, logTag, "GetEnv failed");
- return JNI_ERR;
- }
-
- JNIEnv *env = uenv.nenv;
- const jint ret = QT_PREPEND_NAMESPACE(QtAndroidPrivate::initJNI(vm, env));
- if (ret != 0) {
- __android_log_print(ANDROID_LOG_FATAL, logTag, "initJNI failed");
- return ret;
- }
-
- return JNI_VERSION_1_6;
-}
--- /dev/null
+++ b/qtbase/src/corelib/kernel/qjnionload.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qjnihelpers_p.h"
+
+#include <jni.h>
+#include <android/log.h>
+
+static const char logTag[] = "QtCore";
+
+Q_CORE_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
+{
+ Q_UNUSED(reserved);
+
+ static bool initialized = false;
+ if (initialized)
+ return JNI_VERSION_1_6;
+ initialized = true;
+
+ typedef union {
+ JNIEnv *nenv;
+ void *venv;
+ } _JNIEnv;
+
+ __android_log_print(ANDROID_LOG_INFO, logTag, "Start");
+
+ _JNIEnv uenv;
+ uenv.venv = nullptr;
+
+ if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_6) != JNI_OK) {
+ __android_log_print(ANDROID_LOG_FATAL, logTag, "GetEnv failed");
+ return JNI_ERR;
+ }
+
+ JNIEnv *env = uenv.nenv;
+ const jint ret = QT_PREPEND_NAMESPACE(QtAndroidPrivate::initJNI(vm, env));
+ if (ret != 0) {
+ __android_log_print(ANDROID_LOG_FATAL, logTag, "initJNI failed");
+ return ret;
+ }
+
+ return JNI_VERSION_1_6;
+}

View file

@ -0,0 +1,16 @@
--- a/qtbase/src/plugins/platforms/android/androidjnimain.cpp
+++ b/qtbase/src/plugins/platforms/android/androidjnimain.cpp
@@ -895,6 +895,13 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
__android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed");
return -1;
}
+
+ const jint ret = QT_PREPEND_NAMESPACE(QtAndroidPrivate::initJNI(vm, QJniEnvironment::getJniEnv()));
+ if (ret != 0) {
+ __android_log_print(ANDROID_LOG_FATAL, "Qt", "initJNI failed");
+ return ret;
+ }
+
QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
// attach qt main thread data to this thread

View file

@ -2,21 +2,54 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://opensource.org/license/mit/.
# This file is expected to be highly volatile and may still change substantially.
if("@host_system_name@" STREQUAL "Android")
# For Android, we use the toolchain file provided by the Android SDK.
# See: https://developer.android.com/ndk/guides/cmake
set(ANDROID_ABI @android_abi@)
set(ANDROID_PLATFORM android-@host_system_version@)
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()
# If CMAKE_SYSTEM_NAME is set within a toolchain file, CMake will also
# set CMAKE_CROSSCOMPILING to TRUE, even if CMAKE_SYSTEM_NAME matches
# CMAKE_HOST_SYSTEM_NAME. To avoid potential misconfiguration of CMake,
# it is best not to touch CMAKE_SYSTEM_NAME unless cross-compiling is
# intended.
if(@depends_crosscompiling@)
set(CMAKE_SYSTEM_NAME @host_system_name@)
set(CMAKE_SYSTEM_VERSION @host_system_version@)
set(CMAKE_SYSTEM_PROCESSOR @host_arch@)
# If CMAKE_SYSTEM_NAME is set within a toolchain file, CMake will also
# set CMAKE_CROSSCOMPILING to TRUE, even if CMAKE_SYSTEM_NAME matches
# CMAKE_HOST_SYSTEM_NAME. To avoid potential misconfiguration of CMake,
# it is best not to touch CMAKE_SYSTEM_NAME unless cross-compiling is
# intended.
if(@depends_crosscompiling@)
set(CMAKE_SYSTEM_NAME @host_system_name@)
set(CMAKE_SYSTEM_VERSION @host_system_version@)
set(CMAKE_SYSTEM_PROCESSOR @host_arch@)
set(CMAKE_C_COMPILER_TARGET @host@)
set(CMAKE_CXX_COMPILER_TARGET @host@)
set(CMAKE_OBJCXX_COMPILER_TARGET @host@)
endif()
set(CMAKE_C_COMPILER_TARGET @host@)
set(CMAKE_CXX_COMPILER_TARGET @host@)
set(CMAKE_OBJCXX_COMPILER_TARGET @host@)
if(NOT DEFINED CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER @CC@)
endif()
if(NOT DEFINED CMAKE_CXX_COMPILER)
set(CMAKE_CXX_COMPILER @CXX@)
set(CMAKE_OBJCXX_COMPILER ${CMAKE_CXX_COMPILER})
endif()
set(CMAKE_AR "@AR@")
set(CMAKE_RANLIB "@RANLIB@")
set(CMAKE_STRIP "@STRIP@")
set(CMAKE_OBJCOPY "@OBJCOPY@")
set(CMAKE_OBJDUMP "@OBJDUMP@")
endif()
if(NOT DEFINED CMAKE_C_FLAGS_INIT)
@ -29,10 +62,6 @@ if(NOT DEFINED CMAKE_C_FLAGS_DEBUG_INIT)
set(CMAKE_C_FLAGS_DEBUG_INIT "@CFLAGS_DEBUG@")
endif()
if(NOT DEFINED CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER @CC@)
endif()
if(NOT DEFINED CMAKE_CXX_FLAGS_INIT)
set(CMAKE_CXX_FLAGS_INIT "@CXXFLAGS@")
set(CMAKE_OBJCXX_FLAGS_INIT "@CXXFLAGS@")
@ -46,11 +75,6 @@ if(NOT DEFINED CMAKE_CXX_FLAGS_DEBUG_INIT)
set(CMAKE_OBJCXX_FLAGS_DEBUG_INIT "@CXXFLAGS_DEBUG@")
endif()
if(NOT DEFINED CMAKE_CXX_COMPILER)
set(CMAKE_CXX_COMPILER @CXX@)
set(CMAKE_OBJCXX_COMPILER ${CMAKE_CXX_COMPILER})
endif()
# The DEPENDS_COMPILE_DEFINITIONS* variables are to be treated as lists.
set(DEPENDS_COMPILE_DEFINITIONS @CPPFLAGS@)
set(DEPENDS_COMPILE_DEFINITIONS_RELWITHDEBINFO @CPPFLAGS_RELEASE@)
@ -75,12 +99,6 @@ if(NOT DEFINED CMAKE_SHARED_LINKER_FLAGS_DEBUG_INIT)
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG_INIT "@LDFLAGS_DEBUG@")
endif()
set(CMAKE_AR "@AR@")
set(CMAKE_RANLIB "@RANLIB@")
set(CMAKE_STRIP "@STRIP@")
set(CMAKE_OBJCOPY "@OBJCOPY@")
set(CMAKE_OBJDUMP "@OBJDUMP@")
# Using our own built dependencies should not be
# affected by a potentially random environment.
set(CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH OFF)

View file

@ -45,6 +45,7 @@ The following are developer notes on how to build Bitcoin Core on your native pl
- [FreeBSD Build Notes](build-freebsd.md)
- [OpenBSD Build Notes](build-openbsd.md)
- [NetBSD Build Notes](build-netbsd.md)
- [Android Build Notes](build-android.md)
Development
---------------------

44
doc/build-android.md Normal file
View file

@ -0,0 +1,44 @@
# Android Build Guide
This guide describes how to build and package the `bitcoin-qt` GUI for Android on Linux and macOS.
## Dependencies
Before proceeding with an Android build one needs to get the [Android SDK](https://developer.android.com/studio) and use the "SDK Manager" tool to download the NDK and one or more "Platform packages" (these are Android versions and have a corresponding API level).
Qt 6.7.3 used in depends supports Android NDK version is [r26b (26.1.10909125)](https://github.com/android/ndk/wiki/Changelog-r26).
In order to build `ANDROID_API_LEVEL` (API level corresponding to the Android version targeted, e.g. Android 9.0 Pie is 28 and its "Platform package" needs to be available) needs to be set.
Qt 6.7.3 used in depends supports API levels from 26 to 34.
When building [depends](../depends/README.md), additional variables `ANDROID_SDK` and `ANDROID_NDK` need to be set.
This is an example command for a default build with no disabled dependencies:
gmake HOST=aarch64-linux-android ANDROID_SDK=/home/user/Android/Sdk ANDROID_NDK=/home/user/Android/Sdk/ndk/26.1.10909125 ANDROID_API_LEVEL=34
## Building and packaging
After the depends are built configure, build and create an Android Application Package (APK) as follows (based on the example above):
```bash
cmake -B build --toolchain depends/aarch64-linux-android/toolchain.cmake
cmake --build build --target apk_package # Use "-j N" for N parallel jobs.
```
The APKs will be available in the following directory:
```bash
$ tree build/src/qt/android/build/outputs/apk
build/src/qt/android/build/outputs/apk
├── debug
│ ├── android-debug.apk
│ └── output-metadata.json
└── release
├── android-release-unsigned.apk
└── output-metadata.json
3 directories, 4 files
```

View file

@ -15,13 +15,18 @@ get_target_property(qt_lib_type Qt6::Core TYPE)
function(import_plugins target)
if(qt_lib_type STREQUAL "STATIC_LIBRARY")
set(plugins Qt6::QMinimalIntegrationPlugin)
set(plugins "")
if(TARGET Qt6::QMinimalIntegrationPlugin)
list(APPEND plugins Qt6::QMinimalIntegrationPlugin)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
list(APPEND plugins Qt6::QXcbIntegrationPlugin)
elseif(WIN32)
list(APPEND plugins Qt6::QWindowsIntegrationPlugin Qt6::QModernWindowsStylePlugin)
elseif(APPLE)
list(APPEND plugins Qt6::QCocoaIntegrationPlugin Qt6::QMacStylePlugin)
elseif(ANDROID)
list(APPEND plugins Qt6::QAndroidIntegrationPlugin Qt6::QAndroidStylePlugin)
endif()
qt6_import_plugins(${target}
INCLUDE ${plugins}
@ -357,3 +362,7 @@ else()
VERBATIM
)
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

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);
}
}

View file

@ -87,7 +87,7 @@ class BackwardsCompatibilityTest(BitcoinTestFramework):
# 0.21.x and 22.x would both produce bad derivation paths when topping up an inactive hd chain
# Make sure that this is being automatically cleaned up by migration
node_master = self.nodes[1]
node_v22 = self.nodes[self.num_nodes - 5]
node_v22 = self.nodes[self.num_nodes - 3]
wallet_name = "bad_deriv_path"
node_v22.createwallet(wallet_name=wallet_name, descriptors=False)
bad_deriv_wallet = node_v22.get_wallet_rpc(wallet_name)