Cocos 2dx 4.x. Enable C++17 in Android Studio - c++

I am trying to learn Cocos 2dx game engine. I generated a simple project with this command:
cocos new -l cpp -p com.testgame1 -d path_to_dir testgame1
Next, I try to build an android project. Everything is successful. Then I wrote a lot of code that uses C++ standard 14, 17. Example (file main.cpp):
void cocos_android_app_init(JNIEnv* env) {
LOGD("cocos_android_app_init");
std::string vec;
std::transform(std::begin(vec), std::end(vec), std::begin(vec), [](auto& elem)
{
return elem;
}
);
appDelegate.reset(new AppDelegate());
}
Here I using auto in lambda function (standart C++ 14).
I enable support for the standard in the usual way for Android Studio in build.gradle:
defaultConfig {
applicationId "com.testgame1"
minSdkVersion PROP_MIN_SDK_VERSION
targetSdkVersion PROP_TARGET_SDK_VERSION
versionCode 1
versionName "1.0"
externalNativeBuild {
cmake {
targets 'MyGame'
cppFlags "-std=c++17 -frtti -fexceptions -fsigned-char"
arguments "-DCMAKE_FIND_ROOT_PATH=", "-DANDROID_STL=c++_static", "-DANDROID_TOOLCHAIN=clang", "-DANDROID_ARM_NEON=TRUE"
}
}
ndk {
abiFilters = []
abiFilters.addAll(PROP_APP_ABI.split(':').collect{it as String})
}
}
But it doesn't have any effect. On a clean project (no Cocos 2dx game engine) everything works flawlessly.
I am getting an error in Android Studio:
..\..\..\..\jni\hellocpp\main.cpp:42:72: error: 'auto' not allowed in lambda parameter
NDK: 21.4.7075529
How to fix it?

In your game project folder, open up CMakeLists.txt, and add the following after the include(CocosBuildSet) statement:
set(CMAKE_CXX_STANDARD 17)
If you want to apply C++17 to the cocos2d engine code as well, then adding this may work:
set_target_properties(cocos2d PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO
)
Source: cocos2dx forum

Related

Configure C++ standard in gradle c++ project?

I have a gradle project defined by the following build script (build.gradle):
plugins {
id 'cpp-application'
}
application {
targetMachines.add(machines.linux.x86_64)
targetMachines.add(machines.windows.x86_64)
}
This is my directory structure:
./src
./src/main
./src/main/cpp
./src/main/cpp/descriptor.cpp
./src/main/cpp/reader_writer.cpp
./src/main/cpp/constant_pool.cpp
./src/main/cpp/unjar.cpp
./src/main/cpp/attribute.cpp
./src/main/cpp/main.cpp
./src/main/cpp/java_serde.cpp
./src/main/headers
./src/main/headers/unjar.h
./src/main/headers/attribute.h
./src/main/headers/constant_pool.h
./src/main/headers/descriptor.h
./src/main/headers/java_serde.h
./src/main/headers/reader_writer.h
./build.gradle
Now I want to compile my project, where I am using C++17 features in some source files. I am oblivious as to how I can set the C++ standard version for my gradle build.
How do I tell gradle to compile my code with C++17?
Set the following inside your application configuration clause:
compilerArgs.add '-std=c++17'
If you are targeting multiple platforms, you can set compilerArgs conditionally:
compilerArgs.addAll toolChain.map { toolChain ->
if (toolChain in [ Gcc, Clang ]) {
return ['-std=++17']
} else if (toolChain in VisualCpp) {
return '/std=c++17'
}
return []
}
In your gradle script where you kick off cmake, add cppFlags:
cmake {
cppFlags = "std=c++17"
}
I hope it helps you:
cmake {
cppFlags = "std=c++17"}
} <- at 3rd line

How to change CMake path in Android Studio

I copied an existing Android Studio project from another user and I can't compile C++ files using CMake because it uses the other user's CMake path
I already tried to delete and re-create the CMakeLists.txt file and re-installed CMake using SDK Manager
Here's my gradle:
apply plugin: 'com.android.library'
android {
compileSdkVersion 25
defaultConfig {
. . .
externalNativeBuild {
cmake {
arguments '-DANDROID_TOOLCHAIN=clang'
}
}
}
buildTypes {
release {
. . .
}
}
lintOptions {
abortOnError false
}
externalNativeBuild {
cmake {
path file('CMakeLists.txt')
}
}
}
About 2 months ago, the project worked perfectly. Then I made some minor modifications and now I have this error.
It's just like there's a way to indicate which CMake use, but I don't know where to find it.
Here's a resume of what the console show me when I want to clean the project:
Caused by: net.rubygrapefruit.platform.NativeException: Could not start '/Users/Old_User/Library/Android/sdk/cmake/3.6.4111459/bin/cmake'
at net.rubygrapefruit.platform.internal.DefaultProcessLauncher.start(DefaultProcessLauncher.java:27)
at net.rubygrapefruit.platform.internal.WrapperProcessLauncher.start(WrapperProcessLauncher.java:36)
The rest of the error log is about the same message saying that it can find the cmake file
It appears that android build system is not able to find cmake utility. Please check if it is installed.

How to fix Android NDK app crash with UnsatisfiedLinkError when loading protobuf-lite.so on Android 6.0?

I have created an Android application with a custom C++ library that depends on Google's protobuf-lite library. It works fine on all the recent devices I have tried to run it on (under Android 7, 8 and 8.1). However, I found that on older devices running Android 6.0.1 or 6.0 (Asus Nexus 7 and some old Motorola phone), the application crashes on loading the libprotobuf-lite.so dependency.
Here is the stacktrace I get:
E/AndroidRuntime: FATAL EXCEPTION:
main Process: com.mycompany.core, PID: 11582 java.lang.UnsatisfiedLinkError:
dlopen failed: cannot locate symbol "__aeabi_memmove8" referenced by "/data/app/com.mycompany.core-2/lib/arm/libprotobuf-lite.so"...
at java.lang.Runtime.loadLibrary(Runtime.java:372)
at java.lang.System.loadLibrary(System.java:1076)
at com.mycompany.core.CameraTestActivity.<clinit>(CameraTestActivity.java:46)
at java.lang.Class.newInstance(Native Method)
at android.app.Instrumentation.newActivity(Instrumentation.java:1067)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2317)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)$
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
This is really weird because the missing symbol "__aeabi_memmove8" appears to be a low-level standard library feature and I do not really grasp why it would not be found on Android 6.
In addition, I am quite confident that the issue comes from protobuf-lite not linking correctly because previous versions of my app, which were not using protobuf, ran fine on these Android 6 devices.
Below are some details on my config.
Protobuf version: 3.6.1
Lib package cross-compiled from source using Cmake GUI, NDK r18 toolchain and MinGW
Devices' ABI: armeabi-v7a
Android SDK compile version: API 28
Application build toolchain : Gradle + CMake.
Android Studio 3.1.3
Here is my build.gradle file:
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.mycompany.core"
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
}
}
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
ndk{
abiFilters "arm64-v8a", "armeabi-v7a"
}
}
debug {
ndk{
abiFilters "arm64-v8a", "armeabi-v7a"
}
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation "android.arch.lifecycle:extensions:1.1.0"
implementation "android.arch.lifecycle:viewmodel:1.1.0"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
And here is my CMakeLists.txt file:
cmake_minimum_required(VERSION 3.4.1)
include_directories(src/main/cpp/protobuf/include)
file(GLOB SRCS
"src/main/cpp/core/*.cpp"
)
file(GLOB JNI_SRCS
"src/main/cpp/jni/*.cpp"
)
add_library(mycorelib SHARED ${SRCS} ${JNI_SRCS})
find_library(log-lib log)
add_library(libprotobuf-lite SHARED IMPORTED)
set_target_properties(libprotobuf-lite
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libprotobuf-lite.so)
target_link_libraries(mycorelib
android
jnigraphics
${log-lib}
libprotobuf-lite)
Has anyone run into this problem before? Any hint on how to fix this would be greatly appreciated.
This is https://android.googlesource.com/platform/ndk/+/master/docs/user/common_problems.md#cannot-locate-symbols.
Your protobuf library was built for a higher minSdkVersion than the rest of your app, and cannot run on the device you're using.
You need to change the version of the NDK that you are using. The article below suggests that moving to NDK 22 or newer will fix this.
unable to run on Android 6.0 after 7b77c0acedf708749b68304cc5f0ac469c9d7136

How to compile a Linux LTO-enabled library with Premake 5?

SO wisdom, I'm turning to you. I'm trying to build a 64-bit static lib using LTO with Makefiles and Premake 5 on Ubuntu 16.04 LTS.
Here's the premake script i'm using:
-- premake5.lua
workspace "TestApp"
location "TestApp" -- The directory of generated files - .sln, etc.
configurations { "Debug", "Shipping" }
platforms { "Linux_Static", "Linux_DLL" }
targetdir "TestApp/Build/%{cfg.platform}/%{cfg.buildcfg}"
objdir "TestApp/Build/"
language "C++"
architecture "x86_64"
system "linux"
filter "platforms:*Static"
kind "StaticLib"
filter "platforms:*DLL"
kind "SharedLib"
filter "kind:SharedLib"
defines { "TEST_USE_DLL", "TEST_DLL_EXPORT" }
-- Configuration filters
configuration "*"
flags { "ExtraWarnings", "C++14", "MultiProcessorCompile", "ShadowedVariables", "UndefinedIdentifiers" }
configuration { "Debug" }
symbols "On"
defines { "TEST_DEBUG" }
optimize "Debug"
configuration "Shipping"
defines { "TEST_SHIPPING" }
optimize "Full"
flags { "LinkTimeOptimization" }
-- step 1
--buildoptions "--plugin=$$(gcc --print-file-name=liblto_plugin.so)"
-- step 2
--toolset "clang"
-- step 3
--premake.tools.gcc.ar = "gcc-ar"
-- Projects
project "TestCore"
location "TestApp/Core"
files { "TestApp/Core/*.h", "TestApp/Core/*.cpp" }
includedirs { "TestApp/" }
project "UnitTests"
location "TestApp/Tests"
kind "ConsoleApp"
links { "TestCore" }
objdir "TestApp/Tests/Build/"
files { "TestApp/Tests/UnitTests/*.cpp", "TestApp/ThirdParty/Catch/*" }
includedirs { "TestApp/ThirdParty/Catch", "TestApp/" }
removedefines { "TEST_DLL_EXPORT" }
filter { "platforms:*DLL", "system:linux" }
runpathdirs { "Build/%{cfg.platform}/%{cfg.buildcfg}" }
"Shipping" is the faulty configuration. I also bundled the whole test project in a zip for you to try to reproduce the issue.
The errors I have when compiling the TestCore library are first plugin needed to handle lto object, then plugin /usr/lib/gcc/x86_64-linux-gnu/5/liblto_plugin.so is not licensed under a GPL-compatible license.
What can we do about it ? If you have any knowledge to make it work with GCC, please help.
what you would do to reproduce the GCC errors after extracting the zip:
cd testBreaking
premake5 gmake
cd TestApp
make config=shipping_linux_static TestCore (get the "plugin needed to handle lto object" error)
Uncomment line 37 of premake5.lua to get the "not licensed under a GPL-compatible license" error
Uncomment line 43 to use gcc-ar instead of ar, notice it doesn't work either
Using gcc option -fuse-linker-plugin doesn't help
Some more system info:
ubuntu 16.04 LTS
gcc 5.4, make 4.1, ar 2.26.1
premake 5.0.0-alpha11
I got it working with Clang. Using toolset clang for Shipping configuration (using LLVM 3.9), the library seems to compile fine. But I got another error:
error adding symbols: Archive has no index; run ranlib to add one
I managed to work around this issue by calling ranlib Build/Linux_Static/Shipping/libTestCore.a --plugin /usr/lib/llvm-3.9/lib/LLVMgold.so, then make again.
So it painfully works using Clang.
I read that I could create a specific premake toolset for this kind of thing, because it's recommended replacing all gnu utils with their gcc- counterparts (e.g. gcc-ar instead of ar), but having rapidly tinkered with premake.tools.gcc.ar = "gcc-ar" with no result, I'm not so sure it would help.

How to disable Android NDK build for some build variant

I am using Android Studio 2.2 and have setup Gradle to build c/c++ sources with NDK via CMake.
Now I would like to disable NDK build for buildType "debug". For buildType "release" I would like to keep it.
The goal is to make NDK sources compile on the build server (using "release") but disable it for developers (using "debug").
This is the build.gradle file currently in use:
android {
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
defaultConfig {
externalNativeBuild {
cmake {
arguments "-DANDROID_TOOLCHAIN=clang"
cppFlags "-std=c++14"
}
}
ndk {
abiFilters 'armeabi-v7a', 'x86'
}
}
buildTypes {
release {
externalNativeBuild {
cmake {
arguments "-DANDROID_TOOLCHAIN=clang"
cppFlags "-std=c++14"
}
}
ndk {
abiFilters 'armeabi-v7a'
}
}
}
}
How can I disable NDK build (externalNativeBuild) for defaultConfig or buildType "debug"?
Other developers won't have NDK installed (local.properties without ndk.dir=PATH_TO_NDK). Is this possible to configure?
Thanks in advance
Edit:
This externalNativeBuild must be configured with a 'com.android.library'-module, not a 'com.android.application'-module.
Here is how I solved it.
This way Gradle build works for developers with and without NDK installed (and on the build server), which was the goal.
/*
* As soon as Gradle is linked to the externalNativeBuild (cmake / ndkBuild) with a path to
* CMakeLists.txt / Android.mk, the ndk.dir from local.properties file or the ANDROID_NDK_HOME
* environment variable needs to be set, otherwise gradle fails.
* E.g.:
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
*/
// Only enable externalNativeBuild on machines with NDK installed -> valid ndkDir
def ndkDir = project.android.ndkDirectory;
if (ndkDir != null && !ndkDir.toString().isEmpty()) {
externalNativeBuild.cmake.path = "CMakeLists.txt"
}
Regarding #1, if I understand correctly you want to do (or skip) certain things according to the buildType. If so, you can look at one of the many discussions on this subject, such as this one: get current buildType.
Regarding #2, it is not very clear what you want. If you are seeking an alternative to setting the NDK path in local.properties, you can set it via ANDROID_NDK_HOME environment variable. If you want to prevent gradle from failing, check if the ndk.dir exists in the relevant places of your build.gradle script (using properties.getProperty('ndk.dir')).