3

I have an Android NDK project which I am trying to build through Gradle+CMake.

build.gradle:

apply plugin: 'com.android.library'

allprojects {
    repositories {
        jcenter()
        google()
    }
}

android {
    compileSdkVersion 27
    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        externalNativeBuild {
            cmake {
                cppFlags "-std=c++11"
                arguments "-DANDROID_ABI=armeabi-v7a",
                          "-DANDROID_PLATFORM=android-16",
                          "-DANDROID_STL=gnustl_static",
                          "-DANDROID_CPP_FEATURES=rtti exceptions",
                          "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=libs"
            }
        }
    }

    buildTypes {
        release {
            ndk {
                abiFilters "armeabi-v7a"
            }
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            ndk {
                abiFilters "armeabi-v7a"
            }
        }
    }
    externalNativeBuild {
        cmake {
            path 'CMakeLists.txt'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
}

CMAKE Command Output:

Executable : /Users/ssk/Library/Android/sdk/cmake/3.6.3155560/bin/cmake
arguments : 
-H/Users/ssk/MyProject
-B/Users/ssk/MyProject/.externalNativeBuild/cmake/debug/armeabi-v7a
-DANDROID_ABI=armeabi-v7a
-DANDROID_PLATFORM=android-16
------> -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/Users/ssk/MyProject/build/intermediates/cmake/debug/obj/armeabi-v7a
-DCMAKE_BUILD_TYPE=Debug
-DANDROID_NDK=/Users/ssk/Library/Android/sdk/ndk-bundle
-DCMAKE_CXX_FLAGS=-std=c++11
-DCMAKE_TOOLCHAIN_FILE=/Users/ssk/Library/Android/sdk/ndk-bundle/build/cmake/android.toolchain.cmake
-DCMAKE_MAKE_PROGRAM=/Users/ssk/Library/Android/sdk/cmake/3.6.3155560/bin/ninja
-GAndroid Gradle - Ninja
-DANDROID_STL=gnustl_static
-DANDROID_ABI=armeabi-v7a
-DANDROID_PLATFORM=android-16
-DANDROID_CPP_FEATURES=rtti exceptions
------> -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=libs
jvmArgs : 

I am trying to configure the output directory using DCMAKE_LIBRARY_OUTPUT_DIRECTORY, but it's not obeying.

Gradle prefixes a default one before my option as highlighted (------> in cmake command output).

Question:

How should I configure the output directory?

shizhen
  • 12,251
  • 9
  • 52
  • 88
ssk
  • 9,045
  • 26
  • 96
  • 169

2 Answers2

5

Below snippet will configure your output directory:

For static lib output directory, try below:

# copy out the static lib binary 
set_target_properties(${STATIC_LIBRARY_NAME}
                      PROPERTIES
                      ARCHIVE_OUTPUT_DIRECTORY "libs/${ANDROID_ABI}")

For shared lib output directory, try below:

# copy out the shared lib binary 
set_target_properties(${SHARED_LIBRARY_NAME}
                      PROPERTIES
                      LIBRARY_OUTPUT_DIRECTORY "libs/${ANDROID_ABI}")

Explanation:

ANDROID_ABI is a variable defining the Android ABI, e.g. armeabi-v7a

Reference about the CMake variables definition:

Android NDK path variable for "strip" command in CMake build tool chain

shizhen
  • 12,251
  • 9
  • 52
  • 88
3

Probably you need to set the buildStagingDirectory option. In the next link you will find how to manage paths for CMake in gradle:

CMakeOptions

And as a side note unrelated to the question. In your gradle script seems you are still using gnustl_static which is no longer supported and will be removed in the next NDK versions. You should switch to either c++_static or c++_shared. Take into account that gcc has been deprecated and you should use clang. Next an example:

externalNativeBuild {
            cmake {
                arguments "-DANDROID_PLATFORM=android-16", "-DANDROID_STL=c++_static", "-DANDROID_TOOLCHAIN=clang"
                abiFilters "armeabi-v7a", "arm64-v8a", "x86"
            }
        }
PerracoLabs
  • 16,449
  • 15
  • 74
  • 127
  • 1
    Just to point out It’s not good to use -DANDROID_PLATFORM, minSdkVersion should be the proper way managing platform versions, see more details here https://stackoverflow.com/a/54473346/8034839 – shizhen Feb 05 '19 at 01:34
  • "Instead of changing this flag directly, you should set the `minSdkVersion` property in the `defaultConfig` or `productFlavors` blocks of your `module-level build.gradle` file. This makes sure your library is used only by apps installed on devices running an adequate version of Android. " This is how the [**official document says**](https://developer.android.com/ndk/guides/cmake#variables). – shizhen Feb 05 '19 at 02:58
  • "1. If there exists a platform version for the ABI equal to minSdkVersion, CMake uses that version. 2. Otherwise, if there exists platform versions lower than minSdkVersion for the ABI, CMake uses the highest of those platform versions. This is a reasonable choice because a missing platform version typically means that there were no changes to the native platform APIs since the previous available version. 3. Otherwise, CMake uses the next available platform version higher than minSdkVersion." – shizhen Feb 05 '19 at 02:59