Android NDK CMake使用C++17。

11

问题

我希望在我的Android NDK项目中使用分解声明。因此,需要使用-std=c++17参数调用clang。目前我的代码可以编译通过,但是Clang会打印以下警告:

warning: decomposition declarations are a C++17 extension [-Wc++17-extensions]

我知道的和我想要的

在构建日志中,我注意到-std=...被四次附加到构建标志中:

[...]/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 [...]

我知道第二个和第三个标志来自哪里(见下文)。我尝试将它们更改为-std=c++17-std=c++1z,但没有成功。
我猜后面的标志会覆盖前面的。所以我不太关心第一个标志。但我无法确定最后一个标志(-std=gnu++11)来自哪里,也不知道如何停用或修改它。此外,我猜它是gnu++11而不是c++11,激活了一些GNU扩展,导致我只收到警告而没有错误。
但我不能确定。尽管如此,我想要“真正”的C++17支持,而不仅仅是一些GNU扩展。另外,我想摆脱这些警告。
涉及构建过程的文件
我的gradle.build 这里的cppFlags开关是上面构建日志摘录中第二个标志的来源。我知道这里的某些版本已经过时。但我从NDK示例存储库中得到了这些,并且我是Android编程的新手。我还在弄清楚事情是如何工作的。因此,我暂时不关心那部分。
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'
}

我的CMakeLists.txt

第三个标志的来源。来自assets/CMakeRC.cmakecmrc_add_resource_library编译资源。我查看了代码,没有任何与std=*CMAKE_*_FLAGS相关的内容。如果你不相信我,请自己查看源代码

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)

我的项目中没有其他文件包含与构建标志有关的代码。所以我想这就是全部了。

主要问题

最后那个 -std= 标志可能来自哪里?如果上面的问题描述不足以推断解决方案,我可以采取哪些进一步的步骤来找出它的来源?也许我完全弄错了,clang++ 已经使用 C++17 编译了。但为什么我还会收到这些警告?我该如何摆脱它们?

更新

我在本地的 Android SDK 文件夹中搜索了 std=gnu++11 并尝试连续更改所有出现的情况,以找出在我的构建过程中使用的是哪一个。结果发现,在 cmake/3.6.4111459/share/cmake-3.6/Modules/Compiler/Clang-CXX.cmake 中,变量 CMAKE_CXX11_EXTENSION_COMPILE_OPTION 负责前面提到的编译器标志。我的当前解决方法是在我的 CMakeLists.txt 中将其设置为所需的标准:

set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=c++17")

这个方法可行,我成功消除了所有警告。然而,它似乎有些hacky,我仍然不知道是什么将该变量附加到构建命令中。因此,我不会将其发布为答案,因为我仍在寻找实际解决方案。但如果有人遇到同样的问题,并且只是寻找一个快速修复,那么这里就有一个!


你尝试检查 ${CMAKE_CXX_FLAGS} 了吗?现在你正在使用 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1z -Wall") 进行附加。尝试扩展前后的标志以查看它是如何添加的。https://dev59.com/pmox5IYBdhLWcg3wTija - James Poag
@JamesPoag 抱歉,我刚看到你的评论。 我检查了CMAKE_CXX_FLAGS并发现它包含构建日志中的前两个标志。我还尝试使用string(REPLACE ...)将它们替换为std = c ++ 17。虽然我成功地更改了第一个构建标志,但最后一个标志仍然保持不变。不幸的是,最后一个标志是确定所使用标准的标志。但是,似乎在执行我的CMakeLists.txt之后附加了它。 - Scindix
2个回答

4

NDK的工具链文件遵循-std设置,两个标志都会出现,但是按照应该让用户设置覆盖工具链的顺序。

听起来你的构建中某处有像target_compile_features(foobar PRIVATE cxx_range_for)或者set_property(TARGET foobar PROPERTY CXX_STANDARD 11)这样的东西。


0

将参数传递给cmake应该作为列表而不是简单字符串。我在我的一个项目中使用它来构建本地库:

    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"
          ...
    }

你的构建脚本使用简单字符串,而不是列表。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接