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 founderror when running the app on the x86 virtual machine, andINSTALL_FAILED_NO_MATCHING_ABIS res=-113on a real tablet.I have noticed that regardless of what I set
ANDROID_SDKandANDROID_NDKvariables 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-27In the SDK platforms I have:
root$ ls /shared/DevTools/Android/SDK-r25.2.5/platforms/ android-19 android-21 android-25 android-28The 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_PATHFrom 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=x86I 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: 0Resolution: 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: 40The 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 segmentSo the question is how to prevent 5.12.3 version
androiddeployqtorqmakestripping the section headers from the libraries.@TenG Solved.
Added
--no-stripflag to theandroiddeployqtcommand.Also amended the
build.gradletemplates under:/opt/Qt5.12.3/5.12.3/android_*/src/android/templates/build.gradleand added the following in the
androidsection: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 founderror when running the app on the x86 virtual machine, andINSTALL_FAILED_NO_MATCHING_ABIS res=-113on a real tablet.I have noticed that regardless of what I set
ANDROID_SDKandANDROID_NDKvariables 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-27In the SDK platforms I have:
root$ ls /shared/DevTools/Android/SDK-r25.2.5/platforms/ android-19 android-21 android-25 android-28The 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_PATHFrom 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=x86I 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: 0Resolution: 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: 40The 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 segmentSo the question is how to prevent 5.12.3 version
androiddeployqtorqmakestripping 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: 0Resolution: 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: 40The 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 segmentSo the question is how to prevent 5.12.3 version
androiddeployqtorqmakestripping the section headers from the libraries.@TenG Solved.
Added
--no-stripflag to theandroiddeployqtcommand.Also amended the
build.gradletemplates under:/opt/Qt5.12.3/5.12.3/android_*/src/android/templates/build.gradleand added the following in the
androidsection:packagingOptions{ doNotStrip "*/arm*/*.so" doNotStrip "*/x86/*.so" }After this the app ran on Android.