build: Restore cross-compilation for Android

This change partially reverts 5deb0b024e
and includes additional related adjustments.
This commit is contained in:
Hennadii Stepanov 2025-04-13 17:05:03 +01:00
parent 817edfb21e
commit 206cb5ead4
No known key found for this signature in database
GPG key ID: 410108112E7EA81F
12 changed files with 318 additions and 44 deletions

View file

@ -695,7 +695,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,8 @@ $(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)|' \
$< > $@
touch $@

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

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

@ -0,0 +1,29 @@
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
else
android_CXX := $(android_toolchain_bin_dir)/$(HOST)$(ANDROID_API_LEVEL)-clang++
android_CC := $(android_toolchain_bin_dir)/$(HOST)$(ANDROID_API_LEVEL)-clang
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)"
@ -249,6 +261,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 && \

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,42 @@
# 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)
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 +50,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 +63,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 +87,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

@ -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}