Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. How does qmake make use of NDK/SDK and -spec settings
Forum Update on Monday, May 27th 2025

How does qmake make use of NDK/SDK and -spec settings

Scheduled Pinned Locked Moved Solved Mobile and Embedded
3 Posts 1 Posters 912 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    TenG
    wrote on last edited by
    #1

    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, and INSTALL_FAILED_NO_MATCHING_ABIS res=-113 on a real tablet.

    I have noticed that regardless of what I set ANDROID_SDK and ANDROID_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?

    T 1 Reply Last reply
    0
    • T TenG

      @TenG

      I found this article:

      https://android.googlesource.com/platform/bionic/+/refs/heads/oreo-r2-release/android-changes-for-ndk-developers.md#missing-section-headers-enforced-for-api-level-24

      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 or qmake stripping the section headers from the libraries.

      T Offline
      T Offline
      TenG
      wrote on last edited by
      #3

      @TenG Solved.

      Added --no-strip flag to the androiddeployqt 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.

      1 Reply Last reply
      0
      • T TenG

        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, and INSTALL_FAILED_NO_MATCHING_ABIS res=-113 on a real tablet.

        I have noticed that regardless of what I set ANDROID_SDK and ANDROID_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?

        T Offline
        T Offline
        TenG
        wrote on last edited by
        #2

        @TenG

        I found this article:

        https://android.googlesource.com/platform/bionic/+/refs/heads/oreo-r2-release/android-changes-for-ndk-developers.md#missing-section-headers-enforced-for-api-level-24

        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 or qmake stripping the section headers from the libraries.

        T 1 Reply Last reply
        0
        • T TenG

          @TenG

          I found this article:

          https://android.googlesource.com/platform/bionic/+/refs/heads/oreo-r2-release/android-changes-for-ndk-developers.md#missing-section-headers-enforced-for-api-level-24

          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 or qmake stripping the section headers from the libraries.

          T Offline
          T Offline
          TenG
          wrote on last edited by
          #3

          @TenG Solved.

          Added --no-strip flag to the androiddeployqt 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.

          1 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved