Android NDK CMake uses C++17 - android

The Problem
I'd like to use decomposition declarations in my Android NDK project. Therefore clang needs to be called with -std=c++17. Currently my code compiles without errors, but Clang prints the following warning:
warning: decomposition declarations are a C++17 extension [-Wc++17-extensions]
What I know and what I want
In the build log I spotted that -std=... is appended to the build flags four times:
[...]/bin/clang++ [...] -Wformat -Werror=format-security -std=c++11 -std=c++1z\
-fexceptions -std=c++1z -Wall -O0 -fno-limit-debug-info -fPIC\
-std=gnu++11 -MD -MT [...]
I know where the second and the third flag comes from (see below). I tried to change them to -std=c++17 and -std=c++1z but with no success.
I guess that later flags override earlier ones. So I don't really care about the first one. But I can't figure out where the last one (-std=gnu++11) comes from and how I could deactivate or modify it. Also I guess the fact that it's gnu++11 instead of c++11 activates some GNU extension that leads to the situation that I'm only getting warnings and no errors.
But I can't tell for sure. Nevertheless I want "real" C++17 support and not just some GNU extensions. Also I want to get rid of the warnings.
Files involved in the building process
My gradle.build
The switch cppFlags in here is the origin of the second flag from the above excerpt from the build log. I know that some of the versions here are outdated. But I got that from the NDK sample repository and I'm new to Android programming. I'm still figuring out how things work. And so I don't care about that part yet.
apply plugin: 'com.android.application'
android {
compileSdkVersion = 25
defaultConfig {
applicationId = 'com.example.stackoverflow'
minSdkVersion 14
targetSdkVersion 25
externalNativeBuild {
cmake {
arguments '-DANDROID_STL=c++_static'
cppFlags "-std=c++1z -fexceptions"
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path 'src/main/CMakeLists.txt'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:25.4.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.1'
}
My CMakeLists.txt
Origin of the third flag. cmrc_add_resource_library from assets/CMakeRC.cmake compiles resources. I searched the code and there is nothing related to std=* or CMAKE_*_FLAGS. If you don't believe me have a look at the source yourself.
cmake_minimum_required(VERSION 3.4.1)
include(assets/CMakeRC.cmake)
# Build native_app_glue as a static library
set(${CMAKE_C_FLAGS}, "${CMAKE_C_FLAGS}")
add_library(native_app_glue STATIC
${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
# Now build app's shared library
cmrc_add_resource_library(shaderFiles assets/shader/standard.fs assets/shader/standard.vs)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1z -Wall")
# Export ANativeActivity_onCreate(),
set(CMAKE_SHARED_LINKER_FLAGS
"${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")
add_library(myappname SHARED
cpp/main.cpp
#cpp files...
target_include_directories(myappname PRIVATE
${ANDROID_NDK}/sources/android/native_app_glue)
# Add library dependencies
target_link_libraries(myappname
shaderFiles
android
native_app_glue
EGL
GLESv2
log)
None of the other files in my project contains code that remotely has to do with build flags. So I guess that's all.
Main Question
Where could that last -std= flag originate from? If the above problem description is not enough to deduce a solution, what further steps could I take in finding out the origin? And maybe I got it all wrong and clang++ already compiles with C++17. But why am I getting these warnings then? And how do I get rid of them?
Update
I searched my local Android SDK folder for std=gnu++11 and tried changing all occurrences consecutively to find out which one is the one used in my build process. It turns out that in cmake/3.6.4111459/share/cmake-3.6/Modules/Compiler/Clang-CXX.cmake the variable CMAKE_CXX11_EXTENSION_COMPILE_OPTION is responsible to the aforementioned compiler flag. My current workaround is setting it to the desired standard in my CMakeLists.txt:
set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=c++17")
This works. I got rid of all the warnings. However it seems a bit hacky and I still don't have a clue what actually appends this variable to the build command. So I'm not posting this as an answer as I'm still searching for an actual solution. But if anyone has the same problem and is just searching for a quick fix, well, here you go!

The NDK's toolchain file obeys -std settings as it should. Both flags will appear, but they do so in the order that has the user's setting override the toolchains.
It sounds like you have something like target_compile_features(foobar PRIVATE cxx_range_for) or set_property(TARGET foobar PROPERTY CXX_STANDARD 11) somewhere in your build.

Passing arguments to cmake should be done as a list, not as a simple string. I use this in one of my projects to build a native lib:
cmake {
// Passes optional arguments to CMake. Make sure it is a list, not just a string :-) .
arguments "-DANDROID_NATIVE_API_LEVEL=21", "-DANDROID_STL=c++_shared", "-DANDROID=true"
cppFlags "-fexceptions", "-frtti"
...
}
Your build script uses simple strings, not lists.

Related

libcrashpad_handler.so: library "libc++_shared.so" not found: needed by main executable

I followed the manual written by Bugsplat to build Crashpad for Android.
The build was successful and I got all necessary libraries. However I noticed that the prebuilt library libcrashpad_handler.so in Bugsplat's sample weighs about 26Mb. And mine is only 700Kb.
Moreover I got errors from linker when trying to catch signals from system.
/lib/arm64/libcrashpad_handler.so": library "libc++_shared.so" not found: needed by main executable
Is the instructions are not up-to-date on Bugsplat? Maybe there should be some extra_cflags passed to gn gen --args ?
Btw, I tried to include c++shared into apk with:
externalNativeBuild {
cmake {
arguments "-DANDROID_STL=c++_shared"
}
}
But i got no success to load it.
Really appreciate your assistance in building libcrashpad_handler.so.

Error: no matching constructor for initialization of 'std::shared_ptr<uint8_t []>'

I am trying to use std::shared_ptr <uint8_t []> in my NDK application, but compiler throws below error.
error: no matching constructor for initialization of 'std::shared_ptr<uint8_t []>'
std::shared_ptr<uint8_t[]> x_data(new uint8_t[bytes_to_send]);
My NDK version is r19c and the CMake looks like below
cmake {
version "3.10.2"
cppFlags "-std=c++17 -stdlib=libc++ -frtti -fexceptions"
...
}
According to the libc++ Feature Test Macro Support page, the __cpp_lib_shared_ptr_arrays feature is currently unimplemented.
It may have something to do with this task not having been started according to this page.
An alternative in the meantime might be to explicitly specify an array deleter:
std::shared_ptr<uint8_t> x_data(new uint8_t[bytes_to_send], std::default_delete<uint8_t[]>());
(as seen in the documentation here)

Limit CPU cores for ndkBuild with Cmake and Ninja

Before, when I was using ndkBuld for building native code on Android I was able to pass an argument to make to define a number of CPU cores to be used. If I wanted to utilize 4 cores I could add something like this
externalNativeBuild {
ndkBuild {
arguments "-j4", "APP_SHORT_COMMANDS=true"
abiFilters "armeabi-v7a"
}
}
Can somebody give an advice how can I do something similar with Cmake and Ninja? Is there some equivalent parameter for cmake configuration?
externalNativeBuild {
cmake {
arguments "-DANDROID_STL=c++_static"
abiFilters getAbis()
}
}
Thanks.
controlling ninja parallelism
Ninja also support the same parameter:
$ ninja --help
usage: ninja [options] [targets...]
[...]
options:
[...]
-j N run N jobs in parallel [default=10, derived from CPUs available]
[...]
controlling ninja parallelism differentiating compile and link jobs
Now, if you want more granularity. For example, if you would like to limit the number of simultaneous link jobs, or compile jobs, or both.
Starting with CMake 3.11, it is now possible to limit the number of compile and/or link jobs.
You could then configure your project with these options:
-DCMAKE_JOB_POOL_COMPILE:STRING=compile
-DCMAKE_JOB_POOL_LINK:STRING=link
'-DCMAKE_JOB_POOLS:STRING=compile=5;link=2'
Now, if your project end up spawning other child processed that are themselves building projects using ninja, you would have to:
use the fork of ninja that include Job Server support like it is done in make. Binaries are also available in the associated GitHub releases. See https://github.com/kitware/ninja#readme
make sure sub-project are also configured with the same -DCMAKE_JOB_ options
in the context of externalNativeBuild
This means you could try something like this:
externalNativeBuild {
cmake {
arguments "-DANDROID_STL=c++_static -DCMAKE_JOB_POOL_COMPILE:STRING=compile -DCMAKE_JOB_POOL_LINK:STRING=link '-DCMAKE_JOB_POOLS:STRING=compile=5;link=2'"
abiFilters getAbis()
}
}
I was able to fix this by adding:
if (PARALLEL_COMPILE_JOBS)
set(CMAKE_JOB_POOL_COMPILE compile_job_pool${CMAKE_CURRENT_SOURCE_DIR})
string (REGEX REPLACE "[^a-zA-Z0-9]+" "_" CMAKE_JOB_POOL_COMPILE ${CMAKE_JOB_POOL_COMPILE})
set_property(GLOBAL APPEND PROPERTY JOB_POOLS ${CMAKE_JOB_POOL_COMPILE}=${PARALLEL_COMPILE_JOBS})
endif ()
if (PARALLEL_COMPILE_JOBS)
message(STATUS "${CMAKE_CURRENT_SOURCE_DIR}: Limiting compiler jobs to ${PARALLEL_COMPILE_JOBS}")
endif ()
to my base CMakeLists.txt, and then in my build.gradle I added to cmake arguments: "-DPARALLEL_COMPILE_JOBS=8" to specify max 8 parallel clang++ compile processes. This works on current Android Studio cmake (3.10) and ninja (1.8.2) versions
I created a workaround: wrap the ninja executable used by Android Studio with a script that calls ninja with all given parameter plus "-j1" at the end.
Locate the ninja executable used by Android Studio. Something like, for example, somefolder/Android/Sdk/cmake/3.10.2.4988404/bin/ninja
Rename it to something else, like ninja_orig
Create a shell script (and add execution permission to it) to replace the original ninja executable at somefolder/Android/Sdk/cmake/3.10.2.4988404/bin/ninja with the following content:
#!/bin/sh
somefolder/Android/Sdk/cmake/3.10.2.4988404/bin/ninja_orig $# -j1
Ok it seems it is a bug / missing feature in NDK. I've talked to some "NDK Googlers" and they were not able to help me either. Hopefully it will be supported in later versions of NDK / AS.
Here are the issues you can track the progress:
https://github.com/android-ndk/ndk/issues/983
and
https://issuetracker.google.com/issues/137878831

How to enable std::experimental::optional on Android

I'd like to use optionals in my Android app's C++ code, but I'm having trouble figuring out how to configure the STL to support either std::experimental::optional or std::optional. I get a build failure, "cannot find -lc++experimental," if I just add "-lc++experimental" to the cppFlags. This is what the externalNativeBuild portion of my Gradle file looks like presently.
externalNativeBuild {
cmake {
arguments "-DANDROID_STL=c++_shared"
cppFlags "-std=c++11", "-frtti", "-fexceptions"
}
}
How can I enable the use of std::optional or std::experimental::optional?
EDIT: I was able to download boost and use boost::optional instead, which was easy enough since it's a header-only library. Still, it would be nice to know how to to use one of the STLs that ships with the NDK, if that's possible. When I open up $ANDROID_NDK_HOME/sources/cxx-stl/llvm-libc++/include/experimental/optional, I see what looks like an implementation of std::experimental::optional, but it's surrounded by a lot of preprocessor statements that I imagine are disabling it.
std::optional is part of the C++17 STL. If your compiler supports it add -std=c++17otherwise I believe the correct flag is -std=c++1z.
See this discussion for more details.

ndk-build stays at NDEBUG=1 despite Gradle debuggable: true in Android Studio

I'm having a ton of difficulty trying to get Gradle to compile a debug version of my JNI code through NDK build. I've set the debug build to be debuggable in the build.gradle file like so:
buildTypes {
debug {
debuggable true
jniDebuggable true
}
}
I can confirm that the switches are taking effect if I check out Build/Edit Build types. However, once I check the ndkBuild_build_command.txt file inside of the .externalNdkBuild directory, I notice the following entries:
NDEBUG=1
APP_PLATFORM=android-9
I can confirm that my JNI code does not seem to be debuggable. Even though the breakpoints trigger, variables all show "variable not available" in LLVM.
Any ideas as to why NDEBUG is turned on even in a debug build? As a sidenote, I also have no idea where the android-9 platform is entering in... I'm not setting that myself anywhere that I could find.
If you use Android Studio 2.2 with externalNativeBuild, you can set APP_OPTIM=debug in your Application.mk or NDK_DEBUG=1 through parameters override, e.g.
externalNativeBuild {
ndkBuild {
arguments "NDK_DEBUG:=1"
}
}

Categories

Resources