Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android NDK CMake uses C++17

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!

like image 948
Scindix Avatar asked May 25 '18 09:05

Scindix


People also ask

What compiler does Android NDK use?

Code written in C/C++ can be compiled to ARM, or x86 native code (or their 64-bit variants) using the Android Native Development Kit (NDK). The NDK uses the Clang compiler to compile C/C++.

What is NDK and CMake?

The Android Native Development Kit (NDK): a set of tools that allows you to use C and C++ code with Android. CMake: an external build tool that works alongside Gradle to build your native library. You do not need this component if you only plan to use ndk-build.

What is Android NDK used for?

The Android NDK is a toolset that lets you implement parts of your app in native code, using languages such as C and C++. For certain types of apps, this can help you reuse code libraries written in those languages.

What C++ compiler does Android use?

libc++ LLVM's libc++ is the C++ standard library that has been used by the Android OS since Lollipop, and as of NDK r18 is the only STL available in the NDK.


1 Answers

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.

like image 76
Dan Albert Avatar answered Oct 04 '22 18:10

Dan Albert