11

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!

Community
  • 1
  • 1
Scindix
  • 1,254
  • 2
  • 15
  • 32
  • Did you try to examine the `${CMAKE_CXX_FLAGS}`? Right now you are appending with `set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1z -Wall")`. Try to expand the flags before and after to see how it's being added. https://stackoverflow.com/questions/9298278/cmake-print-out-all-accessible-variables-in-a-script – James Poag May 26 '18 at 13:53
  • @JamesPoag Sorry, I've seen your comment just right now. I inspected CMAKE_CXX_FLAGS and it contains the first two flags from the build log. I also tried to replace them with `std=c++17` using `string(REPLACE ...)`. And although I successfully changed the first build flag the last one remains as is. Unfortunately the last flag is the one that determines the standard that is used. However it seems to be appended after my `CMakeLists.txt` gets executed. – Scindix Jun 28 '18 at 14:56

2 Answers2

4

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dan Albert
  • 10,079
  • 2
  • 36
  • 79
0

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.