How do I integrate C++11 into Android?
It appears the main answer here includes experimental support for C++11, and C++11 is not experimental anymore.
If you're using command line NDK support (I use IDEA community edition 13 for the Java stuff), then this is what I had to put in my jni/Application.mk to get C++11 support with API 19 (on OSX ML):
NDK_TOOLCHAIN_VERSION := 4.8
# APP_STL := stlport_shared --> does not seem to contain C++11 features
APP_STL := gnustl_shared
# Enable c++11 extentions in source code
APP_CPPFLAGS += -std=c++11
Derived from here and here.
First of all, you will need to ensure that your toolchain is "Cross GCC". Whilst it was the default on my Linux, it was not on my MacOSX Lion.
In order to do this, go to Project Properties > C/C++ Build > Tool Chain Editor. "Current toolchain" should be set to "Cross GCC". You might need to uncheck the box "Display compatible toolchains only".
Then, add an option to LOCAL_CFLAGS in Android.mk:
LOCAL_CFLAGS := -std=gnu++11
We now need to inform Eclipse about where to find the corresponding new symbols (e.g. "std::unordered_map"). Go to Right Click on "jni" > Properties > C/C++ General -> Paths and Symbols -> Symbols -> GNU C++, and add the following symbol (by clicking "Add..."):
Name: __GXX_EXPERIMENTAL_CXX0X__
Value:
(i.e. let "Value" empty)
You can also set this in your build.gradle file if you are using the gradle-experimental-plugin:
android.ndk {
moduleName = "hello-android-jni"
stl = "stlport_shared"
cppFlags.add("-std=c++11")
}
With the latest gradle-experimental-plugin 0.8.0-alpha4 add to your app/build.gradle:
model {
android {
ndk {
moduleName "native"
CFlags.add("-std=c11") // Enable C11 support
ldLibs.add("log")
}
}
}
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 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
I am trying to use C++11 threading facilities with Android NDK, but not sure how to make it use the latest compilers.
I have Clang 3.2 and can build iOS apps. I wonder if there is a way to do it with Android NDK?
If not, then how should I build with gcc 4.8?
(I'm addressing the NDK version r9b)
To enable C++11 support for all source code of the application (and so any modules included) make the following change in the Application.mk:
# use this to select gcc instead of clang
NDK_TOOLCHAIN_VERSION := 4.8
# OR use this to select the latest clang version:
NDK_TOOLCHAIN_VERSION := clang
# then enable c++11 extentions in source code
APP_CPPFLAGS += -std=c++11
# or use APP_CPPFLAGS := -std=gnu++11
Otherwise, if you wish to have C++11 support only in your module, add this lines into your Android.mk instead of use APP_CPPFLAGS
LOCAL_CPPFLAGS += -std=c++11
Read more here:
http://adec.altervista.org/blog/ndk_c11_support/
NDK revision 10 has the Clang 3.6 toolchain. Use it:
NDK_TOOLCHAIN_VERSION := clang3.6
or use the latest available Clang toolchain
NDK_TOOLCHAIN_VERSION := clang
NDK revision 8e has the Clang 3.2 compiler bundled in it. Use it and you're good to go.
First, to decide which toolchain to use, edit your "application.mk" (do not confuse with android.mk) and insert for gcc 4.8:
NDK_TOOLCHAIN_VERSION := 4.8
or if you want clang:
NDK_TOOLCHAIN_VERSION := clang
But this has nothing to do with threads. This will only define which toolchain to use.
Now about threads, here is a simple example for android NDK:
#include <pthread.h> // <--- IMPORTANT
// This will be used to pass some data to the new thread, modify as required
struct thread_data_arguments
{
int value_a
bool value_b;
};
//---------------------------------
// This function will be executed in the new thread, do not forget to put * at the start of the function name declaration
void *functionRunningInSeparateThread(void *arguments)
{
struct thread_data_arguments *some_thread_arguments = (struct thread_data_arguments*)arguments;
if (some_thread_arguments->value_b == true)
{
printf("VALUE= %i", some_thread_arguments->value_a);
}
// Signal the end of the thread execution
pthread_exit(0);
}
//---------------------------------
// This is the actual function creating and starting the new thread
void startThread()
{
// Lets pass some data to the new thread, you can pass anything even large data,
// for that you only need to modify thread_data_arguments as required
struct thread_data_arguments *some_thread_arguments;
some_thread_arguments = (thread_data_arguments*)malloc(sizeof(*some_thread_arguments));
some_thread_arguments->value_a = 12345;
some_thread_arguments->value_b = true;
// Create and start the new thread
pthread_create(&native_thread, NULL, functionRunningInSeparateThread, (void*)some_thread_arguments)
}
For ndk builds, open Application.mk and add following info. in it (if using r8e):
NDK_TOOLCHAIN_VERSION=4.7
Note: Please use 4.8 in case you are using NDK revision 9.
Note that Android gcc support is now deprecated. You should now be using clang. Please read the version 11 release notes. You can specify:
NDK_TOOLCHAIN_VERSION=clang
To use the latest version based on your installed NDK. Also---as of this writing---the latest NDK (v12) is only accessable via Android Studio, and not through either the Downloads page or Standalone SDK Manager.
Does any android ndk compiler, based on gcc 4.7, support to_string, stof, and other string conversion functions?
In the NDK I am using I found the function in ext/vstring.h. But the function is wrapped in
#if (defined(__GXX_EXPERIMENTAL_CXX0X__) && defined(_GLIBCXX_USE_C99))
I am enabling -std=c++11 flag.
How do I enable GXX_EXPERIMENTAL_CXX0X?
I've enabled it by just adding it as a symbol in Project properties->C/C++ General->Symbols->GNU C++
I also added this in Android.mk:
LOCAL_CPPFLAGS := -std=gnu++0x
I've downloaded a custom toolchain (linaro) to build ARM based Android apps. How do I tell the NDK to use it? Can I define or set something in Android.mk and Application.mk that would allow me to do that? Is there another way?
The NDK makefile system is quite extensible and you can indeed define a different toolchain. You'll need some understanding of how Make works.
Toolchains are discovered and initialized in build/core/init.mk line 261 (in NDKr6, the line # may change in future versions). The initialization code looks for files named config.mk under $(NDK_ROOT)/toolchains/*. So you'll need to add your toolchain in a subdirectory under the NDK toolchains directory, and add a config.mk and setup.mk to that subdirectory. Look at toolchains/x86-4.4.3 and toolchains/arm-linux-androideabi-4.4.3 for examples. You should be able to cut and paste the ARM toolchain config.mk and setup.mk if your toolchain has a standard layout.
Once you've defined a toolchain in the toolchain directory, you can switch to it by setting the NDK_TOOLCHAIN variable inside your Application.mk file.
As the other answer mentions, toolchains are discovered by ndk-build makefile system in $(NDK_ROOT)/toolchains/ and you can mirror ideas you see there. But there are a few extra concepts for supporting non-Android target platforms that are interesting although they may be soon outdated as ndk-build starts to explicitly support other platforms, such as mingw targeting win32 (or other gcc compilers targeting plain 'ol linux).
In config.mk:
TOOLCHAIN_ABIS := (list of ABIs that the toolchain supports)
This is an important definition, because you can use this name in your Application.mk to build using the toolchain for a particular ABI. One of the benefits of corrupting the usage of this definition, is that ndk-build can simultaneously build for multiple ABIs. It always assumes that the platform is Android, but if you want to target win32 using a mingw based toolchain, you can define an "ABI" as x86-win32, and then use this ABI in your Application.mk to select it as an additional target via APP_ABI:= x86-win32 Then in your Android.mk files you can use the TARGET_ARCH_ABI definition to select win32 specific sources and include paths, for example:
ifeq ($(TARGET_ARCH_ABI),x86-win32)
LOCAL_SRC_FILES += my_win32_file.c
LOCAL_CFLAGS += -DSOME_WIN32_SPECIFIC
endif
The final piece is that in setup.mk for your toolchain, it may be insufficient to look at other toolchains as examples, because what setup.mk for a particular toolchain really does is override build settings in default-build-commands.mk, so what you want to do is inspect that file, and redefine things in it that you don't like.
Following the previous example, mingw does not support the noexec flag in the binaries, and you can get rid of this feature by adding the following lines in your setup.mk:
# These flags are used to enforce the NX (no execute) security feature in the
# generated machine code. This adds a special section to the generated shared
# libraries that instruct the Linux kernel to disable code execution from
# the stack and the heap.
TARGET_NO_EXECUTE_CFLAGS := # our platform doesn't support this flag!
TARGET_NO_EXECUTE_LDFLAGS := # our platform doesn't support this flag!
# These flags disable the above security feature
TARGET_DISABLE_NO_EXECUTE_CFLAGS := # our platform doesn't support this flag!
TARGET_DISABLE_NO_EXECUTE_LDFLAGS := # our platform doesn't support this flag!
This is just one example of the many features in default-build-commands.mk that may need to be overridden, and of course it's important to provide TOOLCHAIN_NAME so that the toolchain can be selected via NDK_TOOLCHAIN variable inside your Application.mk file in addition to the ABI methodology I mention above.
well,you can simply add "NDK_TOOLCHAIN_VERSION = 4.9" in your Application.mk