CMAKE not obeying flags from gradle for NDK building on Android - android

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?

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

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"
}
}

Related

ABIs [armeabi, mips] are not supported for platform android NDK

I am using JNI code in my project with abiFilters like below
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.intel.hellojni"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
}
}
ndk {
abiFilters "armeabi", "armeabi-v7a", "x86", "mips"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:+'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
it's working fine in one system but after moving a code to other system,it show below error for import,i have checked with new created project it shoes the same error
ABIs [armeabi, mips] are not supported for platform. Supported ABIs are [armeabi-v7a, arm64-v8a, x86, x86_64].
Build command failed.
Error while executing process F:\sdk\cmake\3.6.4111459\bin\cmake.exe with arguments {-HC:\Users\Intel\Downloads\TestJNI\app -BC:\Users\Intel\Downloads\TestJNI\app\.externalNativeBuild\cmake\debug\armeabi -DANDROID_ABI=armeabi -DANDROID_PLATFORM=android-15 -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=C:\Users\Intel\Downloads\TestJNI\app\build\intermediates\cmake\debug\obj\armeabi -DCMAKE_BUILD_TYPE=Debug -DANDROID_NDK=F:\sdk\ndk-bundle -DCMAKE_CXX_FLAGS= -DCMAKE_TOOLCHAIN_FILE=F:\sdk\ndk-bundle\build\cmake\android.toolchain.cmake -DCMAKE_MAKE_PROGRAM=F:\sdk\cmake\3.6.4111459\bin\ninja.exe -GAndroid Gradle - Ninja}
(include) CMakeLists.txt
Open File
CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage
-- Configuring incomplete, errors occurred!
if I remove armeabi and mips like below then it's working
ndk {
abiFilters "armeabi-v7a", "x86"
}
I have already installed CMake and NDK for android studio.
As the message says, those ABIs are no longer supported by the NDK. This is mentioned in the NDK r17 changelog:
Support for ARMv5 (armeabi), MIPS, and MIPS64 has been removed. Attempting to build any of these ABIs will result in an error.
As others have said, there are not a significant number of devices out there that benefit from targeting any of these ABIs.
remove 'armebi' from abiFilters in your build.gradle file.
armebi is no longer supported by the NDK. A correct list could be:
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
}
armeabi are no longer supported by NDK. Remove armeabi from build gradle or replace
with supported ABIs e.g 'x86'
The same issue using Android Studio 4.1.1 on Windows 10. Changing the version in build.gradle fixes e.g.
from
classpath "com.android.tools.build:gradle:4.1.1"
to
classpath "com.android.tools.build:gradle:4.0.0".

Could not find method cppFlags() arguments() for arguments

I am trying to use
std::function
But the compiler throws an error
Error:(50, 10) error: no type named 'function' in namespace 'std'
I have tried to modify the build.gradle file
externalNativeBuild {
ndkBuild {
path "src/main/jni/Android.mk"
}
cmake {
cppFlags "-std=c++11"
arguments "-DANDROID_STL=gnustl_static"
path 'src/main/jni/CMakeLists.txt'
}
}
But it doesn't accept arguments other than path and throws the following errors
Error:(28, 0) Could not find method arguments() for arguments [-DANDROID_STL=gnustl_static] on object of type com.android.build.gradle.internal.dsl.CmakeOptions.
Please help me to be able to use
std::function
UPDATE
Thanks to #Alex Cohn I was able to configure flags and arguments, and now my file looks like that
apply plugin: 'com.android.library'
android {
compileSdkVersion 25
buildToolsVersion '26.0.2'
defaultConfig {
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
arguments "-DANDROID_STL=gnustl_static"
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
/* ndkBuild {
path "src/main/jni/Android.mk"
}*/
cmake {
// cppFlags "-std=c++11"
//arguments "-DANDROID_STL=gnustl_static"
path 'src/main/jni/CMakeLists.txt'
}
}
}
dependencies {
compile 'com.android.support:support-annotations:25.0.1'
}
There are two entirely different blocks in build.gradle that are named externalNativeBuild (thanks, Google).
One is under android top-level block, and it specifies the path to native build script, cmake or ndkBuild (but not both).
The other can be used to specify, from gradle, some parameters for the native build. This block is usually a child of the defaultConfig block, but can also appear for flavors (see an example).
These externalNativeBuild blocks can also have cmake or ndkBuild children, but only the child that matches the path setting (see above) is relevant, the other is silently ignored.
The bottom line, split your block in two, and put each one in correct place in build.gradle hierarchy.

Gradle seems to overrwrite ndk build arguments while adding product flavors

I have an android project where the build.gradle looks like this:
android {
compileSdkVersion 25
buildToolsVersion "25.0.0"
defaultConfig {
applicationId "com.example.test"
minSdkVersion 24
targetSdkVersion 25
versionCode 1
versionName "1.0"
ndk {
// Specifies the ABI configurations of your native
// libraries Gradle should build and package with your APK.
abiFilters 'armeabi-v7a'
}
externalNativeBuild {
ndkBuild {
targets "test_app"
}
}
}
buildTypes {
release {
minifyEnabled false
useProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
general {
externalNativeBuild {
ndkBuild {
arguments "LOCAL_CFLAGS+=-std=c++11"
arguments "LOCAL_CFLAGS+=-DMODE_GENERAL"
}
}
}
full {
externalNativeBuild {
ndkBuild {
arguments "LOCAL_CFLAGS+=-std=c++11"
arguments "LOCAL_CFLAGS+=-DMODE_FULL"
}
}
}
}
externalNativeBuild {
ndkBuild {
path 'src/main/cpp/Android.mk'
}
}
}
My Android.mk in path 'src/main/cpp/Android.mk' already includes LOCAL_CFLAGS += -std=c++11 and it builds fine if I don't have any product flavors. However, if I do have the product flavors then I have to include arguments "LOCAL_CFLAGS+=-std=c++11" to make it build. I am wondering if there is any way to avoid this as I feel I should only need to include extra args which are not mentioned in the Android.mk.
The root cause of the problematic behavior is not gradle, but that you set LOCAL_CFLAGS (a make variable) on make's command line. The rules of gnu make which runs under the hood of ndk-build, state that this "locks" the variable, and whatever you set in makefile has no effect. Make introduces a special override directive, but it cannot be used in ndk-build for LOCAL_CFLAGS.
You are not supposed to override LOCAL_CFLAGS from outside a local module; you should use APP_CFLAGS in Application.mk or as ndk-build command line arguments.
It is not a good idea to set (whatever)_CFLAGS=-std=c++11 because these flags will be passed both to C++ and C compilers. This setting belongs to LOCAL_CPPFLAGS and her kin.
With gradle plugin, you can use cFlags and cppFlags, as shown in the official doc - better than general-purpose arguments, e.g.:
productFlavors {
full {
externalNativeBuild {
ndkBuild {
cFlags "-DMODE_FULL"
cppFlags "-fexceptions"
}
}
}
}

How to set NDK lib path in Gradle?

I'm working on a PDF viewer application using ebookdroid & MuPDF CPP files. I am having lots of problem with NDK integration in Gradle. I've gone through many answers but they have not fixed my problem.
Gradle is giving me the following error message:
Error:Execution failed for task ':app:compileDebugNdk'.
Error: Your project contains C++ files but it is not using a supported native build system.
Consider using CMake or ndk-build integration with the stable Android Gradle plugin:
https://developer.android.com/studio/projects/add-native-code.html
or use the experimental plugin:
http://tools.android.com/tech-docs/new-build-system/gradle-experimental.
Edit your build.gradle, add defaultConfig.externalNativeBuild.ndkBuild, externalNativeBuild.ndkBuild and sourceSet.main.jni.srcDir options. See the comments below.
android {
compileSdkVersion 22
buildToolsVersion "27.0.0"
defaultConfig {
minSdkVersion 18
targetSdkVersion 22
versionCode 1
versionName "1.0"
//add arguments passed to ndkBuild
externalNativeBuild {
ndkBuild {
arguments "NDK_TOOLCHAIN_VERSION=clang", "APP_SHORT_COMMANDS=true", "APP_ALLOW_MISSING_DEPS=true"
arguments "-j" + Runtime.runtime.availableProcessors()
cFlags "-fexceptions"
}
}
ndk {
abiFilters "armeabi-v7a"
}
}
//specify jni source file path
sourceSets.main {
java.srcDir "src"
res.srcDir "res"
jni.srcDir "jni"
}
buildTypes {
debug {
debuggable true
jniDebuggable true
}
}
//specify makefile / CMake file
externalNativeBuild {
ndkBuild {
path 'jni/Android.mk'
}
}
}

How to setup Android library module with productflavors and jni

I'm trying to include mupdf as an android library module with precompiled .so binaries into my project.
I have an application module which includes my library module like so.
dependencies {
compile project(':mupdf')
}
In my mupdf library module I have my compiled binaries like so.
mupdf
- jniLibs
- arm64-v8a
libmupdf.so
- armeabi
libmupdf.so
- armeabi-v7a
libmupdf.so
- x86
libmupdf.so
- x86_64
libmupdf.so
My build.gradle for the mupdf library project:
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
publishNonDefault true
productFlavors {
x86 {
ndk {
abiFilter "x86"
}
}
x64 {
ndk {
abiFilter "x86_64"
}
}
arm {
ndk {
abiFilter "armeabi"
}
}
arm_v7a {
ndk {
abiFilter "armeabi-v7a"
}
}
arm64_v8a {
ndk {
abiFilter "arm64-v8a"
}
}
fat
}
}
dependencies{
compile project(':core')
}
The problem is soon as I add the product flavors my app doesn't compile because it doesn't find any of the java files from the mupdf module.
If I delete the product flavors part from the gradle file it compiles. But it crashes at runtime because it can't resolve/load the libmupdf library.
You can do this without product flavors. Just remove them and call System.loadLibrary("mupdf") on startup/at some point before the library is used. This call will figure out which native lib to use for the current devices architecture.
Indeed I have to build a fat module for the .aar library and apply the productflavors in my app.gradle.
I was missing this in my library's build.gradle
sourceSets.main {
jni.srcDirs = [] // This prevents the auto generation of Android.mk
jniLibs.srcDir 'src/main/jni'
}
Without this no methods were able to be resolved.

Categories

Resources