问题
I have created a shared library using Qt Creator and I have added the Android SDK, Android NDK and Android Qt kit. Then I compiled my library for Android successfully. I even tested it in an Android application successfully.
As I am not using the Qt libraries, my library does not depend on huge Qt libraries. But unexpectedly, here is my dependencies:
[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
And when I checked the libgnustl_shared.so it has more than 5 MBs size. So I have to place this huge library next to my tiny library in every project.
Another option is to link it statically. I previously asked the question about how is it possible to link a dependency statically and I figured out that it is possible by adding the QMAKE_LFLAGS += -static
in my .pro file:
This flags works perfect and removes the dependency of stdc++ on Windows compilation. But in android I get the following errors:
error: cannot find -lgnustl_shared
error: cannot find -llog
error: cannot find -lz
error: cannot find -ldl
I searched my android-ndk folder and I realized that there is no liblog.a
, libz.a
and libdl.a
files located in it but there is a libgnustl_static.a
file.
I tried to add it using LIBS += -Lpath/to/libdir -lgnustl_static
but the result was the same.
There is a solution in CMake that was mentioned in the previous question as a comment that there is the option to set APP_STL := gnustl_static
in the makefile. But there seems to be no equivalent in QMake.
And a complicated issue is that when I use CONFIG += static
, it compiles successfully but my library is not shared anymore. it becomes a static library.
How can I link gnustl statically so that my library works with no other dependencies?
Edit
I read the compile output and found the following line:
/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
And I was not able to remove gnustl_shared using LIB -= -lgnustl_shared
回答1:
By reading the compile output, I executed the following command manually and created my library with 1 MB size. And it works correctly.
/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
But still I don't know how to automate this command in QMake
回答2:
Below script android.pri
did help for me which I include in my projects to get rid of some QtCreator related bugs:
## 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
#}
usage sample:
ANDROID_API = 21
ANDROID_ARCH = armeabi-v7a
include($$PWD/android.pri)
but I do get below error some times any way for TEMPLATE = app
:
No Android arch set by the .pro file. Error while building/deploying project vpnAndroid (kit: Qt5_android_armeabi-v7a) When executing step "Deploy to Android device"
This special QtCreator related bug costs time to fix:
- Close IDE and delete all the QtCreator setting files (in windows
"C:\Users\Admin\UserName\Roaming\QtProject"
) - Start IDE again and reconfigure Android Paths, Compilers, Debugers and Kits in this order
- Close IDE to save changes
- Backup the folder mentioned before to save time see below:
the QtCreator plugins related to Android do store there failure in settings and so you need to backup since the plugins may do that again
来源:https://stackoverflow.com/questions/40917341/how-to-create-a-single-native-shared-library-with-no-dependency-for-android-usin