I try to compile my project with native c-libs and get next error
/Users/eugene/KREF14001/app/src/main/jni/libC/PulseFilter.c: In function 'shapeMonoGame':
/Users/eugene/KREF14001/app/src/main/jni/libC/PulseFilter.c:696:5: error: 'for' loop initial declarations are only allowed in C99 mode
/Users/eugene/KREF14001/app/src/main/jni/libC/PulseFilter.c:696:5: note: use option -std=c99 or -std=gnu99 to compile your code
From this report I find that I must to use option -std=c99 or -std=gnu99 to compile my code, but I don't know how to do it. Please, help me.
In the build.gradle file of your app, you can add cFlags "-std=c99" in the ndk block located within the defaultConfig block like this:
ndk {
moduleName "libblur"
abiFilter "armeabi-v7a"
stl "gnustl_static"
cFlags "-std=c99"
ldLibs "log"
}
The problem was in that the Gradle don't use your .mk files, but generate its own and use them. So it's useful to edit Android.mk and Application.mk. You can build your source code manually or edit ndk section of build.gradle.
Related
I am using Gradle 3.0.1 in Android studio (3) trying to compile FFMPEG and armeabi-v7a has two shared libraries one with neon and one without. Typically in the old days before gradle, ndkbuild would compile my project without any issues, now with gradle and new ndkbuild, a bunch of issues showed up. The below isn't exactly how my code is but you can checkout my code in https://github.com/matthewn4444/VPlayer_lib. I have 3 questions about building in gradle with ndk.
I prebuilt 2 versions of libffmpeg.so, one for armeabi-v7a in neon and other without. I have a module for application-neon and application in the Android.mk file. I am not sure if there is a way to have just 1 .so file but since FFMPEG is complex I didn't want to wrap neon calls just to create one shared library.
My first question is, is it possible to just have 1 shared library in ndk to import into java with neon and non-neon support that links to larger 3rd party libraries or is having 2 separate libraries easier?
If I try to compile other architectures like arm64-v8a I will get an error:
* What went wrong:
Execution failed for task ':VPlayer_library:externalNativeBuildDebug'.
> Unexpected native build target application-neon. Valid values are: <projects>
This is because in my Android.mk file I have a module for non-neon and one for neon mainly for armeabi-v7a. I get the error above because the neon module is only available for armeabi-v7a, arm 64 will not have one so that error pops up on compile. If i create a dummy neon build it will allow the project to compile but then it bundles that fake neon shared library into the apk. I was thinking of building it like this and then having all dummy shared libraries removed from arm64, x86 etc from the build section before merging the shared libraries into the apk.
My second question is, is there a way to bypass this error or have special targets for specific architectures when building (abiFilters) without all this hacking? Code is below.
Android.mk
... <the module for normal application project>
ifdef FEATURE_NEON
include $(CLEAR_VARS)
LOCAL_ALLOW_UNDEFINED_SYMBOLS=false
LOCAL_MODULE := application-neon
LOCAL_SRC_FILES := application.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/$(TARGET_ARCH_ABI)/include \
$(LOCAL_PATH)/application
LOCAL_SHARED_LIBRARY := application-neon
LOCAL_LDLIBS += -landroid
LOCAL_LDLIBS += -llog -ljnigraphics -lz -lm -g $(LOCAL_PATH)/ffmpeg-build/$(TARGET_ARCH_ABI)/libffmpeg-neon.so
include $(BUILD_SHARED_LIBRARY)
else
# This is the dummy app to get the project to compile.
include $(CLEAR_VARS)
LOCAL_MODULE := application-neon
LOCAL_ALLOW_UNDEFINED_SYMBOLS=false
include $(BUILD_SHARED_LIBRARY)
endif
-------------------------------------------------------
build.gradle
externalNativeBuild {
ndkBuild {
targets "application", "cpufeatures", "application-neon" // fails for 'arm64-v8a' without that dummy module
}
}
Next, when I change the abiFilters, it will include all the architectures that I built before besides the ones I selected. For example, if I built
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a'
}
then....
ndk {
abiFilters 'arm64-v8a'
}
and made an apk and then decided to only build arm64-v8a and built an apk, all the armeabi-v7a shared libraries are also in the apk. Android studio does not delete the other architectures compiled data from the build folder but bundles them into the apk as well. So for now I have a gradle task to remove them from build folder (the code is at the end).
My third question is if I did something wrong or if there is something easier I can do that does not require the gradle code below?
def deleteOtherArchFromFolder(config, path) {
new File(path).listFiles().each { folder ->
if (!config.ndk.abiFilters.contains(folder.name)) {
delete {
delete folder
}
}
}
}
task prebuildTask() {
doLast {
def config = android.defaultConfig
// delete the obj files in build directory
deleteOtherArchFromFolder(config, project.buildDir.absolutePath + '/intermediates/ndkBuild/debug/obj/local')
}
}
preBuild.dependsOn(prebuildTask)
Thanks in advance!
I am building my app in debug mode, and I notice some errors saying "parent failed to evaluate: no location, value may have been optimized out". Therefore, I try to add "-O0" in my module build.gradle like this:
externalNativeBuild {
cmake {
cppFlags "-O0 -frtti -fexceptions -std=c++11 -DANDROID_ARM_NEON=TRUE -mfloat-abi=softfp "
abiFilters "armeabi-v7a"
}
}
But still, the same error shows up after adding "-O0". May I ask how to disable compiler optimization properly? My android Studio version is 2.3.3, my sdk tool version is 26.0.2 and my ndk version is 15.1.4
If you want to disable optimization for release build, you can force Debug for C/C++ only:
android {
defaultConfig {
externalNativeBuild {
cmake {
arguments '-DCMAKE_BUILD_TYPE:STRING=Debug'
You can override the build flags by adding the following to your CMakeLists.txt:
# Debug flags
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0")
# Release flags
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast")
To verify this has worked check build output in:
app/.externalNativeBuild/cmake/<buildconfig>/<architecture>/build.ninja
Look for a line starting with FLAGS. This doesn't actually replace the existing compiler flags it just appends your flags and these take precedence.
The default flags are inherited from $ANDROID_NDK/build/cmake/android.toolchain.cmake so you could edit that file directly, however, if you update your NDK these changes will be overwritten.
I am trying to use https://github.com/nlohmann/json in my Android app with C++. The issue is that when I go to build I get the error "no member named 'to_string' in namespace 'std'". I have followed the instructions on the Github for Android, except I have used Gradle to specify the stl and flags:
ndk {
stl "c++_static"
}
externalNativeBuild {
cmake {
cppFlags "-fexceptions -frtti -std=c++11"
}
}
Does anyone have any suggestions on how to make this library work on Android and use Gradle to set the stl properly?
Turns out I needed this instead (I have not looked into why though because the docs say what I posted should work):
externalNativeBuild {
cmake {
cppFlags "-fexceptions -frtti -std=c++11"
arguments "-DANDROID_STL=c++_shared"
}
}
Android Studio 2.2 Preview 1 has a new external ndk build feature, but from app/build.gradle snippet shown in official blog post it's not clear at all how to set additional ndk build parameters which Application.mk file usually contains
I'm able to set Android.mk ndk build file via externalNativeBuild, but how could I set the required Application.mk variables?
My Application.mk contains:
NDK_TOOLCHAIN_VERSION := clang
APP_PLATFORM := android-16
APP_ABI := armeabi
APP_STL := c++_static
APP_CPPFLAGS += -std=c++11
Android Studio 2.2 Preview 3 with updated gradle plugin added support for additional arguments. You can set Application.mk and additional configuration like this:
defaultConfig {
ndkBuild {
arguments "NDK_APPLICATION_MK:=Application.mk"
cFlags "-DTEST_C_FLAG1" "-DTEST_C_FLAG2"
cppFlags "-DTEST_CPP_FLAG2" "-DTEST_CPP_FLAG2"
abiFilters "armeabi-v7a", "armeabi"
}
}
If possible I would recommend migrating to CMake build system, because of better C++ code editor and debugging integration in Android Studio. You will find more info on gradle plugin configuration here:
https://sites.google.com/a/android.com/tools/tech-docs/external-c-builds.
Edit:
From Android Studio 2.2 Preview 5 you must wrap cmake and ndkBuild groups under externalNativeBuild group:
defaultConfig {
externalNativeBuild {
ndkBuild {
targets "target1", "target2"
arguments "NDK_APPLICATION_MK:=Application.mk"
cFlags "-DTEST_C_FLAG1", "-DTEST_C_FLAG2"
cppFlags "-DTEST_CPP_FLAG2", "-DTEST_CPP_FLAG2"
abiFilters "armeabi-v7a", "armeabi"
}
}
}
Edit 2: It seems that wrapping ndkBuild under externalNativeBuild group does not work because of a bug in build tools.
add-native-code
android {
...
defaultConfig {...}
buildTypes {...}
// Encapsulates your external native build configurations.
externalNativeBuild {
// Encapsulates your CMake build configurations.
cmake {
// Provides a relative path to your CMake build script.
path "CMakeLists.txt"
}
}
}
Note: If you want to link Gradle to an existing ndk-build project, use the ndkBuild {} block instead of cmake {}, and provide a relative path to your Android.mk file. Gradle also includes the Application.mk file if it is located in the same directory as your Android.mk file.
I would like to include c++ header iostream into my NDK code. In order to do that, I have to include APP_STL := stlport_static (or similar) into Application.mk file as mentioned in Android ndk-build iostream: No such file or directory.
It all works well if I compile using command line ndk-build, however while compiling using Android Studio, I still get the same error as iostream not found. It looks like application.mk is ignored by Android Studio and I am not sure how to configure it in build.gradle.
Can anyone help me including APP_STL := stlport_static using android studio?
Thanks
It looks like at the moment there is no support for including Application.mk file in build.gradle, however adding stl "stlport_static" under ndk section of build.gradle works well (thanks Michael for quick reply).
Under defaultConfig section, add:
ndk {
moduleName "app"
stl "stlport_static"
}
Details can be found at: https://groups.google.com/forum/#!topic/adt-dev/pHnST37HrlM
For Gradle 2.5, it should look like this:
android.ndk {
moduleName = "app"
stl = "stlport_static"
}
For Gradle 4.4 :
Adding
path 'jni/Application.mk'
to the app level build.gradle solved my problem. It should be like this
externalNativeBuild {
ndkBuild {
path 'jni/Android.mk'
path 'jni/Application.mk'
}
}
Then Android Studio checks for your Application.mk file.
My folder structure is like this