Android Gradle build using cmake overrides '-std=c++17' flag

Android Gradle build using cmake overrides '-std=c++17' flag
0

I’m using the new v4 and everything compiles and runs great on iOS.

However, I’m having an issue compiling in Android Studio. I’m attempting to pass -std=c++17 in build.gradle externalNativeBuild.cmake.cppFlags to the clang compiler but it is always overridden by a subsequent flag ‘-std=gnu++11’, causing it to ignore my flag.

I’m not sure if this flag is being added by the cocos build system or is something to do with cmake itself.

Here are the commands passed to clang++:

…/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android21 --gcc-toolchain=…/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64 --sysroot=…/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -DANDROID -DCOCOS2D_DEBUG=1 -DLWS_WITH_LIBUV -DMyGame_EXPORTS -DUSE_FILE32API -I…/…/…/…/…/…/Classes -I…/…/…/…/…/…/cocos2d/cocos/audio/include -I…/…/…/…/…/…/cocos2d -I…/…/…/…/…/…/cocos2d/cocos -I…/…/…/…/…/…/cocos2d/extensions -I…/…/…/…/…/…/cocos2d/cocos/platform -I…/…/…/…/…/…/cocos2d/cocos/editor-support -I…/…/…/…/…/…/cocos2d/cocos/base -I…/…/…/…/…/…/cocos2d/cocos/platform/android -isystem …/…/…/…/…/…/cocos2d/external/Box2D/include -isystem …/…/…/…/…/…/cocos2d/external/chipmunk/include -isystem …/…/…/…/…/…/cocos2d/external/freetype2/include/android/freetype2 -I…/…/…/…/…/…/cocos2d/external/recast/… -isystem …/…/…/…/…/…/cocos2d/external/jpeg/include/android -isystem …/…/…/…/…/…/cocos2d/external/uv/include -isystem …/…/…/…/…/…/cocos2d/external/webp/include/android -isystem …/…/…/…/…/…/cocos2d/external/bullet/include -isystem …/…/…/…/…/…/cocos2d/external/bullet/include/bullet -isystem …/…/…/…/…/…/cocos2d/external/openssl/include/android -isystem …/…/…/…/…/…/cocos2d/external/tiff/include/android -isystem …/…/…/…/…/…/cocos2d/external/websockets/include/android -I…/…/…/…/…/…/cocos2d/external/tinyxml2/. -I…/…/…/…/…/…/cocos2d/external/xxhash/. -I…/…/…/…/…/…/cocos2d/external/xxtea/. -I…/…/…/…/…/…/cocos2d/external/clipper/. -I…/…/…/…/…/…/cocos2d/external/edtaa3func/. -I…/…/…/…/…/…/cocos2d/external/ConvertUTF/. -I…/…/…/…/…/…/cocos2d/external/poly2tri/… -I…/…/…/…/…/…/cocos2d/external/md5/… -isystem …/…/…/…/…/…/cocos2d/external/curl/include/android -isystem …/…/…/…/…/…/cocos2d/external/png/include/android -I/Users/timwebster/Library/Android/sdk/ndk-bundle/sources/android/cpufeatures -I…/…/…/…/…/…/cocos2d/external/android-specific/pvmp3dec/include -I…/…/…/…/…/…/cocos2d/external/android-specific/pvmp3dec/src -I…/…/…/…/…/…/cocos2d/external/android-specific/tremolo/. -isystem …/…/…/…/…/…/cocos2d/external/zlib/include -I…/…/…/…/…/…/cocos2d/external/unzip/. -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -fno-addrsig -Wa,–noexecstack -Wformat -Werror=format-security -std=c++17 -frtti -fexceptions -fsigned-char -O0 -fno-limit-debug-info -fPIC -std=gnu++11 -MD -MT CMakeFiles/MyGame.dir/Classes/AppDelegate.cpp.o -MF CMakeFiles/MyGame.dir/Classes/AppDelegate.cpp.o.d -o CMakeFiles/MyGame.dir/Classes/AppDelegate.cpp.o -c …/…/…/…/…/…/Classes/AppDelegate.cpp

Notice at the end my c++17 flag is there, but then so is gnu++11. And sure enough, c++17 features are not available. Does anyone know where that final gnu++11 flag is coming from and how to remove it? I’ve searched far and wide on the interwebs and so far nothing has been able to remove that flag!

Would appreciate any help.

@R101 I think is pretty familiar with this. @mars3142 I believe as well.

You can find the setting set(CMAKE_CXX_STANDARD 11) in cmake/Modules/CocosConfigDefine.cmake. So you can change it to 17 here. But i don’t know why it is gnu++11 instead of c++11 here.

I might be wrong, but does build.gradle have this: cppFlags "-std=c++11"

Bingo. BUILD SUCCESSFUL. Thanks so much for your help.

In future, could this be PROP_ var in gradle.properties?

Now all platforms uses cmake, so set it in cmake. I don’t know if or not can override it in build.gradle.

This is what I’m using in my projects (in gamename/CMakeLists.txt):

# Make sure this and any other setting is done AFTER the "include(CocosBuildSet)", 
# since it sets the same items and overrides our settings
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

Doing it this way enables you to override defines in cmake/Modules/CocosConfigDefine.cmake without having to edit that file.

Yep, you can override in project CMkaeLists.txt, good idea.

That’s weird, I’ve followed your instructions (added those 3 lines to end of CMakeLists.txt) but I’m not getting c++17 - back to build errors for specific syntax. Only way that works is to actually edit the line in cmake/Modules/CocosConfigDefine.cmake.

Edit: to clarify, adding to my own CMakeLists.txt is still passing the -std=gnu++11 flag to clang++ in the log. Changing in CocosConfigDefine.cmake sends the -std=gnu++1z instead. Weird.

Edit 2: To be clearer, @zhangxm’s solution is working for me, but @R101’s is not.

Edit 3: If I remove:-

#set(CMAKE_CXX_STANDARD 11)
#set(CMAKE_CXX_STANDARD_REQUIRED ON)

from CocosConfigDefine.cmake and add:-

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

to CMakeLists.txt, everything compiles and I get c++17. This suggests to me that CocosConfigDefine is overriding CMakeLists despite adding it after:-

include(CocosBuildSet)

@timtupman Did you delete the \proj.android\app\.externalNativeBuild\cmake\* folders before trying out each of the tests you did above (or just the CMakeCache.txt files in each debug/release folder).

This is because the first run of CMake won’t be the same as later runs of it, and some settings won’t be updated.

Also, out of curiosity, with Cocos2d cmake files unchanged, and adding the block of text from my previous post, what do you have in the following file:

proj.android\app\.externalNativeBuild\cmake\debug\arm64-v8a\cmake_build_output.txt

My one has this listed (irrelevant lines removed for brevity):

using toolchain file:X:\Android\android-sdk\ndk\20.0.5594570\build\cmake\android.toolchain.cmake
CMAKE_GENERATOR: Ninja
CMAKE_BUILD_TYPE: Debug
CXX_STANDARD: 17
CMake version: 3.10.2
CMAKE_CXX_COMPILER 'X:/Android/android-sdk/ndk/20.0.5594570/toolchains/llvm/prebuilt/windows-x86_64/bin/clang++.exe' 'Clang' '8.0'
CMAKE_CXX_FLAGS                '-g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -fno-addrsig -Wa,--noexecstack -Wformat -Werror=format-security  -frtti -fexceptions -fsigned-char -Wno-c++0x-compat'
CMAKE_CXX_FLAGS_DEBUG          '-O0 -fno-limit-debug-info '
Cocos2d Version 3.17.2
Configuring done

I’m not sure if adding the commands I pasted at the end of the CMakeLists.txt affects anything, but I never actually stated that it should be at the end, but rather just after the include(CocosBuildSet). So, for example:

include(CocosBuildSet)
add_subdirectory(${COCOS2DX_ROOT_PATH}/cocos ${ENGINE_BINARY_PATH}/cocos/core)

# Make sure this and any other setting is done AFTER the "include(CocosBuildSet)", since it
# sets the same items, and overrides our settings
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

One other thing, in your project.android/app/build.gradle, you can set it to use CMake 3.10.2, which will allow you to set the C++ standard version for each target explicitly as showed here:

            else if (PROP_BUILD_TYPE == 'cmake') {
                cmake {
                    targets 'MyGame'
                    arguments "-DCMAKE_FIND_ROOT_PATH=", "-DANDROID_STL=c++_static", "-DANDROID_TOOLCHAIN=clang", "-DANDROID_ARM_NEON=TRUE"
                    cppFlags "-frtti -fexceptions -fsigned-char"
                    version "3.10.2"
                }
            }

CMake v3.8 and newer allow target-specific settings like this:

target_compile_features(myTarget PUBLIC cxx_std_17)

and I think this may work too, but I’m not sure:

set_target_properties(myTarget PROPERTIES
    CXX_STANDARD 17
    CXX_STANDARD_REQUIRED YES
    CXX_EXTENSIONS NO
)

I think that is happening because CMAKE_CXX_EXTENSIONS is enabled (set to ON), so you must set it to OFF in order to fix it:

set(CMAKE_CXX_EXTENSIONS OFF)

More info here.

If that setting isn’t working, then it means that you need to delete the CMake cache files (as stated in my previous post), and if that still doesn’t work, try using a newer version of CMake.

I see! Things are becoming a little clearer. This being enabled was the reason for the “gnu++” flags being passed as opposed to their c++ counterparts.

I think I have realised why I must specify:-

set(CMAKE_CXX_STANDARD 17)

In both my CMakeLists and in CocosConfigDefine - it’s because I have editted a cocos2d in a way that requires c++17. That all seems to be solved and sorted now.

One final mystery is that I cannot seem to set the cmake version in the way that you described. I’ve been successful in setting it by adding:-

cmake.dir=…/Library/Android/sdk/cmake/3.10.2.4988404

to local.properties, however.

If I try just adding:-

version “3.10.2”

to build.gradle.externalNativeBuild.cmake, the Gradle log says the following:-

debug|native No CMake version was specified in build.gradle. Choosing a suitable version.
debug|native Trying to locate CMake in local SDK repository.
debug|native CMake ‘3.10.2’ found in SDK did not match requested version ‘3.6.0’.
debug|native - CMake found in SDK at ‘…/Library/Android/sdk/cmake/3.6.4111459’ had version ‘3.6.0’

I’m not sure where 3.6.0 is being requested, but the strangest thing is that is does not seem to recognise me asking for 3.10.2 in build.gradle. Any idea why? (I’ve tried clearing the cmake cache files by the way, and does not resolve it)

Since you’ve modified cocos2d with c++17 features, have you tried this in the game-side CMakeLists.txt?

set_target_properties(cocos2d PROPERTIES
    CXX_STANDARD 17
    CXX_STANDARD_REQUIRED YES
    CXX_EXTENSIONS NO
)

I’m actually curious if that overrides the global CMAKE_CXX_*** settings, so I’ll try it myself too at some point.

I’m so sorry, I completely forgot about that error, and that I fixed it the exact same way, by setting the cmake.dir manually in local.properties. The Android CMake page doesn’t even mention this specific issue, and they only state that we need to add version "3.10.2", and while it did work for me, it broke only recently after a Gradle update. Perhaps their documentation hasn’t kept up with the Gradle releases, I’m really not sure.

That seems to have worked. I reverted the CocosConfigDefine file and everything seems to have compiled to the c++17 standard!

No worries, I’ll stick with the cmake.dir= for now.

Great! I just verified that too on a Win32 build using Visual Studio. At least it helps in moving to each newer release of cocos2d-x without having to modify the makefiles every time.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.