如何使用Qt Creator创建一个不依赖于Android的单个本机共享库
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用Qt Creator创建一个不依赖于Android的单个本机共享库相关的知识,希望对你有一定的参考价值。
我使用Qt Creator创建了一个共享库,并添加了android SDK,Android NDK和Android Qt工具包。然后我成功编译了我的Android库。我甚至成功地在Android应用程序中测试了它。
由于我没有使用Qt库,我的库不依赖于庞大的Qt库。但出乎意料的是,这是我的依赖:
[matin@Lenovo-X1-Fedora ~]$ ndk-depends libMatinChess.so
WARNING: Could not find library: libgnustl_shared.so
libMatinChess.so
libz.so
libstdc++.so
libm.so
liblog.so
libgnustl_shared.so
libdl.so
libc.so
当我检查libgnustl_shared.so时,它的大小超过5 MB。因此,我必须在每个项目中将这个巨大的库放在我的小型库旁边。
另一个选择是静态链接它。我之前问过the question关于如何静态链接依赖关系,我发现可以通过在我的.pro文件中添加QMAKE_LFLAGS += -static
来实现:
这个标志完美无缺,并消除了stdc ++对Windows编译的依赖性。但在android中我得到以下错误:
error: cannot find -lgnustl_shared
error: cannot find -llog
error: cannot find -lz
error: cannot find -ldl
我搜索了我的android-ndk文件夹,我意识到没有liblog.a
,libz.a
和libdl.a
文件位于其中,但有一个libgnustl_static.a
文件。
我尝试使用LIBS += -Lpath/to/libdir -lgnustl_static
添加它,但结果是一样的。
在上一个问题中提到的CMake中有一个解决方案,可以选择在makefile中设置APP_STL := gnustl_static
。但在QMake中似乎没有相应的东西。
一个复杂的问题是当我使用CONFIG += static
时,它编译成功但我的库不再共享了。它变成了一个静态库。
如何静态链接gnustl以便我的库无需其他依赖项?
编辑
我读了编译输出,发现以下行:
/home/matin/Applications/android-ndk-r13b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ --sysroot = / home / matin / Applications / android -ndk-r13b / platforms / android-9 / arch-arm / -static -Wl, - no-undefined -Wl,-z,noexecstack -shared -Wl,-soname,libMatinChess.so -o libMatinChess.so matinchessdll。 o bishop.o piece.o board.o king.o memorymanager.o pawn.o queen.o blackpawn.o knight.o rook.o whitepawn.o squarelist.o game.o boardhistory.o -L / home / matin / Applications / android-ndk -r13b / sources / cxx-stl / gnu-libstdc ++ / 4.9 / libs / armeabi-v7a -L / home / matin / Applications / android-ndk-r13b / platforms / android-9 / arch-arm / / usr / lib -lgnustl_shared -llog -lz -lm -ldl -lc -lgcc
我无法使用LIB -= -lgnustl_shared
删除gnustl_shared
通过读取编译输出,我手动执行以下命令并创建了1 MB大小的库。它工作正常。
/home/matin/Applications/android-ndk-r13b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ --sysroot = / home / matin / Applications / android -ndk-r13b / platforms / android-9 / arch-arm / -Wl, - no-undefined -Wl,-z,noexecstack -shared -Wl,-soname,libMatinChess.so -o libMatinChess.so matinchessdll.o bishop .o piece.o board.o king.o memorymanager.o pawn.o queen.o blackpawn.o knight.o rook.o whitepawn.o squarelist.o game.o boardhistory.o -L / home / matin / Applications / android-ndk-r13b / sources / cxx-stl / gnu-libstdc ++ / 4.9 / libs / armeabi-v7a -L / home / matin / Applications / android-ndk-r13b / platforms / android-9 / arch-arm // usr / lib -lgnustl_static
但我仍然不知道如何在QMake中自动执行此命令
脚本android.pri
下面的脚本对我有帮助,我在项目中包含了一些QtCreator相关的bug:
## this file changes many values set by "Qt/mkspec/android-g++/qmake.conf"
## since the failed to work with newest Android SDK and/or NDK
##
## use below lines before including this file
##
#ANDROID_API = 21
#ANDROID_ARCH = armeabi-v7a
#do you after using this have still problems?
#there is an bug inside "QtCreator" (not inside "Gradle")
# that leads to .o and .so files get not found
#solved: not required to change "QMAKE_LIBDIR" just open "AndroidManifest.xml"
# and change "Minimum required SDK" to "not set" save then restore to last
# value and save agian to force "QtCreator" update
isEmpty(ANDROID_API): ANDROID_API = 21
isEmpty(ANDROID_ARCH): ANDROID_ARCH = armeabi-v7a #ANDROID_TARGET_ARCH=armeabi-v7a
#remove old values
CONFIG -= $$ANDROID_PLATFORM
QMAKE_CFLAGS -= --sysroot=$$ANDROID_PLATFORM_ROOT_PATH
QMAKE_CXXFLAGS -= --sysroot=$$ANDROID_PLATFORM_ROOT_PATH
QMAKE_LFLAGS -= --sysroot=$$ANDROID_PLATFORM_ROOT_PATH
#NDK Root directory
ANDROID_NDK_ROOT = $$(ANDROID_NDK_ROOT) #first try Environment variable
isEmpty(ANDROID_NDK_ROOT) | !exists($$ANDROID_NDK_ROOT) {
ANDROID_NDK_ROOT = D:/android/sdk/ndk-bundle }
NDK_ROOT = $$ANDROID_NDK_ROOT
#API Level
ANDROID_NDK_PLATFORM = android-$$ANDROID_API
ANDROID_PLATFORM = $$ANDROID_NDK_PLATFORM
CONFIG += $$ANDROID_PLATFORM
DEFINES += __ANDROID_API__=$$ANDROID_API
#Architecture
ANDROID_TARGET_ARCH = $$ANDROID_ARCH
equals(ANDROID_TARGET_ARCH, x86): ANDROID_ARCHITECTURE = x86
else: equals(ANDROID_TARGET_ARCH, x86_64): ANDROID_ARCHITECTURE = x86_64
else: equals(ANDROID_TARGET_ARCH, mips): ANDROID_ARCHITECTURE = mips
else: equals(ANDROID_TARGET_ARCH, mips64): ANDROID_ARCHITECTURE = mips64
else: equals(ANDROID_TARGET_ARCH, arm64-v8a): ANDROID_ARCHITECTURE = arm64
else: ANDROID_ARCHITECTURE = arm
#API Path
ANDROID_PLATFORM_ROOT_PATH = $$NDK_ROOT/platforms/$$ANDROID_PLATFORM/arch-$$ANDROID_ARCHITECTURE/
ANDROID_PLATFORM_PATH = $$ANDROID_PLATFORM_ROOT_PATH/usr
QMAKE_CFLAGS += --sysroot=$$ANDROID_PLATFORM_ROOT_PATH
QMAKE_CXXFLAGS += --sysroot=$$ANDROID_PLATFORM_ROOT_PATH
QMAKE_LFLAGS += --sysroot=$$ANDROID_PLATFORM_ROOT_PATH
# used to compile platform plugins for android-4 and android-5
QMAKE_ANDROID_PLATFORM_INCDIR = $$NDK_ROOT/sysroot/usr/include #headers bundled
QMAKE_ANDROID_PLATFORM_LIBDIR = $$ANDROID_PLATFORM_PATH/lib #same as before
ANDROID_SOURCES_CXX_STL_LIBDIR = $$NDK_ROOT/sources/cxx-stl/gnu-libstdc++/$$NDK_TOOLCHAIN_VERSION/libs/$$ANDROID_TARGET_ARCH
ANDROID_SOURCES_CXX_STL_INCDIR = $$NDK_ROOT/sources/cxx-stl/gnu-libstdc++/$$NDK_TOOLCHAIN_VERSION/include $$ANDROID_SOURCES_CXX_STL_LIBDIR/include
equals(ANDROID_TARGET_ARCH, x86_64)|equals(ANDROID_TARGET_ARCH, mips64): \
QMAKE_ANDROID_PLATFORM_LIBDIR = $${QMAKE_ANDROID_PLATFORM_LIBDIR}64
#additionl fix
QMAKE_CFLAGS += -Wno-attributes #ignore Android Macros
QMAKE_CFLAGS += \
-Wno-unused-parameter \
-Wno-unused-variable \
-Wno-unused-but-set-variable \
-Wno-unused-value \
-Wno-unused-function
INCLUDEPATH += $$ANDROID_NDK_ROOT/sysroot/usr/include
INCLUDEPATH += $$ANDROID_NDK_ROOT/sysroot/usr/include/arm-linux-androideabi
## you most times need set "ANDROID_PACKAGE_SOURCE_DIR" manualys
isEmpty(ANDROID_PACKAGE_SOURCE_DIR) {
DISTFILES += \
$$PWD/res/android/AndroidManifest.xml \
$$PWD/res/android/gradle/wrapper/gradle-wrapper.jar \
$$PWD/res/android/gradlew \
$$PWD/res/android/res/values/libs.xml \
$$PWD/res/android/build.gradle \
$$PWD/res/android/gradle/wrapper/gradle-wrapper.properties \
$$PWD/res/android/gradlew.bat
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/res/android
!build_pass:warning(no ANDROID_PACKAGE_SOURCE_DIR defaulted to $$ANDROID_PACKAGE_SOURCE_DIR)
}
#ANDROID_EXTRA_LIBS = $$PWD/libTest.so ## you may need
#ANDROID_DEPLOYMENT_SETTINGS_FILE = $$PWD/android-settings.json ## no need ever
#QML_IMPORT_PATH
#QML_DESIGNER_IMPORT_PATH
#QMAKE_PROJECT_NAME
#isEmpty(ANDROID_PACKAGE_SOURCE_DIR) {
# # note that $$PWD/android/assets directory is "QFile::ReadOnly" on android
# android: varDirInstall.path =/assets
# else: varDirInstall.path =$$OUT_PWD
#
# varDirInstall.files = $$files($$PWD/android/assets)
# win32: varDirInstall.files ~= s|\\\\|/|g
# varDirInstall.depends += FORCE
# INSTALLS += varDirInstall
#}
使用样本:
ANDROID_API = 21
ANDROID_ARCH = armeabi-v7a
include($$PWD/android.pri)
但我对TEMPLATE = app
的任何方式确实得到以下错误:
没有.pro文件设置的Android拱门。构建/部署项目时出错vpnAndroid(套件:Qt5_android_armeabi-v7a)执行步骤“部署到Android设备”时
这个特殊的QtCreator相关错误需要花费一些时间来修复:
- 关闭IDE并删除所有QtCreator设置文件(在windows
"C:\Users\Admin\UserName\Roaming\QtProject"
中) - 再次启动IDE并按此顺序配置Android路径,编译器,调试器和套件
- 关闭IDE以保存更改
- 备份前面提到的文件夹以节省时间,见下图:
与Android相关的QtCreator插件会在设置中存储失败,因此您需要备份,因为插件可能会再次执行此操作
以上是关于如何使用Qt Creator创建一个不依赖于Android的单个本机共享库的主要内容,如果未能解决你的问题,请参考以下文章
QT Creator中[main]和[mainwindow]的区别