How does qmake make use of NDK/SDK and -spec settings
-
I have been really, really struggle to solve an issue with buidling a APK that will run. I keep getting
/lib/x86/libc++_shared.so" .dynamic section header was not found
error when running the app on the x86 virtual machine, andINSTALL_FAILED_NO_MATCHING_ABIS res=-113
on a real tablet.I have noticed that regardless of what I set
ANDROID_SDK
andANDROID_NDK
variables to I seem to get the same output for the qmake template:{ "description": "This file is generated by qmake to be read by androiddeployqt and should not be modified by hand.", "qt": "/opt/Qt5.12.3/5.12.3/android_x86", "sdk": "/shared/DevTools/Android/SDK-r25.2.5", "sdkBuildToolsRevision": "28.0.2", "ndk": "/opt/android-ndk/android-ndk-r19c", "toolchain-prefix": "llvm", "tool-prefix": "llvm", "toolchain-version": "4.9", "ndk-host": "linux-x86_64", "target-architecture": "x86", "android-package-source-directory": "/shared/WorkSpace/MyApp_dev/MyApp/MyApp/android", "android-extra-libs": "/shared/WorkSpace/HMyAppLibsAndroid/libvlc/lib/x86/libvlc.so", "qml-import-paths": "/shared/WorkSpace/MyApp_dev/MyApp/MyApp/controls/resourceHandling/RemoteResourceManagers/classFlowWebView.qml,/shared/WorkSpace/MyApp_dev/MyApp/MyApp/controls/resourceHandling/RemoteResourceManagers/smartWebView.qml", "qml-root-path": "/shared/WorkSpace/MyApp_dev/MyApp/MyApp", "stdcpp-path": "/opt/android-ndk/android-ndk-r19c/sources/cxx-stl/llvm-libc++/libs/x86/libc++_shared.so", "useLLVM": true, "application-binary": "/shared/WorkSpace/MyApp_dev/MyApp/MyApp/build/bin/libMyApp.so" }
I think the issue is here:
"stdcpp-path": "/opt/android-ndk/android-ndk-r19c/sources/cxx-stl/llvm-libc++/libs/x86/libc++_shared.so",
But I do not know what controls this getting resolved.
In my NDK/platforms I have:
root$ ls /opt/android-ndk/android-ndk-r19c/platforms/ android-16 android-18 android-21 android-23 android-26 android-28 android-17 android-19 android-22 android-24 android-27
In the SDK platforms I have:
root$ ls /shared/DevTools/Android/SDK-r25.2.5/platforms/ android-19 android-21 android-25 android-28
The qmake comnmand line is:
/opt/qt/5.12.3/5.12.3/android_x86/bin/qmake MyApp.pro -r -spec android-clang "CONFIG+=release" DEFINES+= LIB_PATH=$MyApp_DEPENDENCIES_PATH
From what I can see, the SDK and NDK are specified via a plethora of environment variables:
export ANDROID_HOME=/shared/DevTools/Android/SDK-r25.2.5 export ANDROID_NDK_HOST=linux-x86_64 export ANDROID_NDK_PLATFORM=android-21 export ANDROID_NDK_TOOLCHAIN_PREFIX=x86 export ANDROID_NDK_TOOLCHAIN_VERSION=4.9 export ANDROID_TARGET_PLATFORM=android-21 export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 export ANDROID_NDK_TOOLCHAIN_VERSION=4.9 export ANDROID_NDK_TOOLCHAIN_PREFIX=x86 export ANDROID_NDK_TOOLS_PREFIX=x86 export ANDROID_TARGET_ARCH=x86
I have been experiemneting with ANDROID_NDK_PLATFORM and ANDROID_TARGET_PLATFORM, but I'm getting to that desperate scatter gun stage now.
The build.gradle that results is:
buildscript { repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.2.0' } } repositories { google() jcenter() } apply plugin: 'com.android.application' dependencies { implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) } android { /******************************************************* * The following variables: * - androidBuildToolsVersion, * - androidCompileSdkVersion * - qt5AndroidDir - holds the path to qt android files * needed to build any Qt application * on Android. * * are defined in gradle.properties file. This file is * updated by QtCreator and androiddeployqt tools. * Changing them manually might break the compilation! *******************************************************/ compileSdkVersion androidCompileSdkVersion.toInteger() buildToolsVersion androidBuildToolsVersion sourceSets { main { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java'] aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl'] res.srcDirs = [qt5AndroidDir + '/res', 'res'] resources.srcDirs = ['src'] renderscript.srcDirs = ['src'] assets.srcDirs = ['assets'] jniLibs.srcDirs = ['libs'] } } lintOptions { abortOnError false } }
I have tried reading the documentation but I could do with some help to understand how this all works.
How does it all actually work?
What am I missing? Are the various platform settings for the NDK and Target controlled via the environment variables?
-
I found this article:
Which states:
Missing Section Headers (Enforced for API level >= 24)
Each ELF file has additional information contained in the section headers. These headers must be present now, because the dynamic linker uses them for sanity checking. Some developers strip them in an attempt to obfuscate the binary and prevent reverse engineering. (This doesn't really help because it is possible to reconstruct the stripped information using widely-available tools.)$ readelf --header libBroken.so | grep 'section headers' Start of section headers: 0 (bytes into file) Size of section headers: 0 (bytes) Number of section headers: 0
Resolution: remove the extra steps from your build that strip section headers.
Sure enough when I tried this on the libcstd++_shared.so in the APK zip and compared it the original file from the NDK location I found the APK version had no section header:
root$ readelf --header /opt/android-ndk/android-ndk-r19c/sources/cxx-stl/llvm-libc++/libs/x86/libc++_shared.so | grep 'section h' Start of section headers: 5917840 (bytes into file) Size of section headers: 40 (bytes) Number of section headers: 40
The APK:
root$ readelf --header /shared/WorkSpace/Releases/MyApp-4_0_2_900-x86/lib/x86/libc+* | grep 'section h' readelf: Error: Start of section headers: 995788 (bytes into file) Size of section headers: 40 (bytes) Number of section headers: 26 no .dynamic section in the dynamic segment
So the question is how to prevent 5.12.3 version
androiddeployqt
orqmake
stripping the section headers from the libraries.@TenG Solved.
Added
--no-strip
flag to theandroiddeployqt
command.Also amended the
build.gradle
templates under:/opt/Qt5.12.3/5.12.3/android_*/src/android/templates/build.gradle
and added the following in the
android
section:packagingOptions{ doNotStrip "*/arm*/*.so" doNotStrip "*/x86/*.so" }
After this the app ran on Android.
-
I have been really, really struggle to solve an issue with buidling a APK that will run. I keep getting
/lib/x86/libc++_shared.so" .dynamic section header was not found
error when running the app on the x86 virtual machine, andINSTALL_FAILED_NO_MATCHING_ABIS res=-113
on a real tablet.I have noticed that regardless of what I set
ANDROID_SDK
andANDROID_NDK
variables to I seem to get the same output for the qmake template:{ "description": "This file is generated by qmake to be read by androiddeployqt and should not be modified by hand.", "qt": "/opt/Qt5.12.3/5.12.3/android_x86", "sdk": "/shared/DevTools/Android/SDK-r25.2.5", "sdkBuildToolsRevision": "28.0.2", "ndk": "/opt/android-ndk/android-ndk-r19c", "toolchain-prefix": "llvm", "tool-prefix": "llvm", "toolchain-version": "4.9", "ndk-host": "linux-x86_64", "target-architecture": "x86", "android-package-source-directory": "/shared/WorkSpace/MyApp_dev/MyApp/MyApp/android", "android-extra-libs": "/shared/WorkSpace/HMyAppLibsAndroid/libvlc/lib/x86/libvlc.so", "qml-import-paths": "/shared/WorkSpace/MyApp_dev/MyApp/MyApp/controls/resourceHandling/RemoteResourceManagers/classFlowWebView.qml,/shared/WorkSpace/MyApp_dev/MyApp/MyApp/controls/resourceHandling/RemoteResourceManagers/smartWebView.qml", "qml-root-path": "/shared/WorkSpace/MyApp_dev/MyApp/MyApp", "stdcpp-path": "/opt/android-ndk/android-ndk-r19c/sources/cxx-stl/llvm-libc++/libs/x86/libc++_shared.so", "useLLVM": true, "application-binary": "/shared/WorkSpace/MyApp_dev/MyApp/MyApp/build/bin/libMyApp.so" }
I think the issue is here:
"stdcpp-path": "/opt/android-ndk/android-ndk-r19c/sources/cxx-stl/llvm-libc++/libs/x86/libc++_shared.so",
But I do not know what controls this getting resolved.
In my NDK/platforms I have:
root$ ls /opt/android-ndk/android-ndk-r19c/platforms/ android-16 android-18 android-21 android-23 android-26 android-28 android-17 android-19 android-22 android-24 android-27
In the SDK platforms I have:
root$ ls /shared/DevTools/Android/SDK-r25.2.5/platforms/ android-19 android-21 android-25 android-28
The qmake comnmand line is:
/opt/qt/5.12.3/5.12.3/android_x86/bin/qmake MyApp.pro -r -spec android-clang "CONFIG+=release" DEFINES+= LIB_PATH=$MyApp_DEPENDENCIES_PATH
From what I can see, the SDK and NDK are specified via a plethora of environment variables:
export ANDROID_HOME=/shared/DevTools/Android/SDK-r25.2.5 export ANDROID_NDK_HOST=linux-x86_64 export ANDROID_NDK_PLATFORM=android-21 export ANDROID_NDK_TOOLCHAIN_PREFIX=x86 export ANDROID_NDK_TOOLCHAIN_VERSION=4.9 export ANDROID_TARGET_PLATFORM=android-21 export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 export ANDROID_NDK_TOOLCHAIN_VERSION=4.9 export ANDROID_NDK_TOOLCHAIN_PREFIX=x86 export ANDROID_NDK_TOOLS_PREFIX=x86 export ANDROID_TARGET_ARCH=x86
I have been experiemneting with ANDROID_NDK_PLATFORM and ANDROID_TARGET_PLATFORM, but I'm getting to that desperate scatter gun stage now.
The build.gradle that results is:
buildscript { repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.2.0' } } repositories { google() jcenter() } apply plugin: 'com.android.application' dependencies { implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) } android { /******************************************************* * The following variables: * - androidBuildToolsVersion, * - androidCompileSdkVersion * - qt5AndroidDir - holds the path to qt android files * needed to build any Qt application * on Android. * * are defined in gradle.properties file. This file is * updated by QtCreator and androiddeployqt tools. * Changing them manually might break the compilation! *******************************************************/ compileSdkVersion androidCompileSdkVersion.toInteger() buildToolsVersion androidBuildToolsVersion sourceSets { main { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java'] aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl'] res.srcDirs = [qt5AndroidDir + '/res', 'res'] resources.srcDirs = ['src'] renderscript.srcDirs = ['src'] assets.srcDirs = ['assets'] jniLibs.srcDirs = ['libs'] } } lintOptions { abortOnError false } }
I have tried reading the documentation but I could do with some help to understand how this all works.
How does it all actually work?
What am I missing? Are the various platform settings for the NDK and Target controlled via the environment variables?
I found this article:
Which states:
Missing Section Headers (Enforced for API level >= 24)
Each ELF file has additional information contained in the section headers. These headers must be present now, because the dynamic linker uses them for sanity checking. Some developers strip them in an attempt to obfuscate the binary and prevent reverse engineering. (This doesn't really help because it is possible to reconstruct the stripped information using widely-available tools.)$ readelf --header libBroken.so | grep 'section headers' Start of section headers: 0 (bytes into file) Size of section headers: 0 (bytes) Number of section headers: 0
Resolution: remove the extra steps from your build that strip section headers.
Sure enough when I tried this on the libcstd++_shared.so in the APK zip and compared it the original file from the NDK location I found the APK version had no section header:
root$ readelf --header /opt/android-ndk/android-ndk-r19c/sources/cxx-stl/llvm-libc++/libs/x86/libc++_shared.so | grep 'section h' Start of section headers: 5917840 (bytes into file) Size of section headers: 40 (bytes) Number of section headers: 40
The APK:
root$ readelf --header /shared/WorkSpace/Releases/MyApp-4_0_2_900-x86/lib/x86/libc+* | grep 'section h' readelf: Error: Start of section headers: 995788 (bytes into file) Size of section headers: 40 (bytes) Number of section headers: 26 no .dynamic section in the dynamic segment
So the question is how to prevent 5.12.3 version
androiddeployqt
orqmake
stripping the section headers from the libraries. -
I found this article:
Which states:
Missing Section Headers (Enforced for API level >= 24)
Each ELF file has additional information contained in the section headers. These headers must be present now, because the dynamic linker uses them for sanity checking. Some developers strip them in an attempt to obfuscate the binary and prevent reverse engineering. (This doesn't really help because it is possible to reconstruct the stripped information using widely-available tools.)$ readelf --header libBroken.so | grep 'section headers' Start of section headers: 0 (bytes into file) Size of section headers: 0 (bytes) Number of section headers: 0
Resolution: remove the extra steps from your build that strip section headers.
Sure enough when I tried this on the libcstd++_shared.so in the APK zip and compared it the original file from the NDK location I found the APK version had no section header:
root$ readelf --header /opt/android-ndk/android-ndk-r19c/sources/cxx-stl/llvm-libc++/libs/x86/libc++_shared.so | grep 'section h' Start of section headers: 5917840 (bytes into file) Size of section headers: 40 (bytes) Number of section headers: 40
The APK:
root$ readelf --header /shared/WorkSpace/Releases/MyApp-4_0_2_900-x86/lib/x86/libc+* | grep 'section h' readelf: Error: Start of section headers: 995788 (bytes into file) Size of section headers: 40 (bytes) Number of section headers: 26 no .dynamic section in the dynamic segment
So the question is how to prevent 5.12.3 version
androiddeployqt
orqmake
stripping the section headers from the libraries.@TenG Solved.
Added
--no-strip
flag to theandroiddeployqt
command.Also amended the
build.gradle
templates under:/opt/Qt5.12.3/5.12.3/android_*/src/android/templates/build.gradle
and added the following in the
android
section:packagingOptions{ doNotStrip "*/arm*/*.so" doNotStrip "*/x86/*.so" }
After this the app ran on Android.