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

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

Related

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

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

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 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')).

Choosing compiler options based on the operating system in boost-build

Currently I can build my program using boost build in different platforms by setting the toolset and parameters in the command line. For example :
Linux
b2
MacOS
b2 toolset=clang cxxflags="-stdlib=libc++" linkflags="-stdlib=libc++"
Is there a way to create a rule in the Jamroot file to decide which compiler to use based on the operating system? I am looking for something along these lines:
import os ;
if [ os.on-macos ] {
using clang : <cxxflags>"-stdlib=libc++" <linkflags>"-stdlib=libc++c ;"
}
in linux it automatically decides to use gcc but in the mac if I don't specify the clang toolset it will try (without success) to compile it with gcc.
Just for reference, here is my current jamroot (any suggestions also appreciated):
# Project requirements (note, if running on a Mac you have to build foghorn with clang with libc++)
project myproject
: requirements <cxxflags>-std=c++11 <linkflags>-std=c++11 ;
# Build binaries in src
lib boost_program_options ;
exe app
: src/main.cpp src/utils src/tools boost_program_options
;
How abou using a Jamroot? I have the following in mine. It selects between two GCC versions on Linux, depending on what's in an environmen variable, and chooses vacpp on AIX.
if [ os.name ] = LINUX
{
switch [ modules.peek : ODSHOME ]
{
case *gcc-4* : using gcc : 4.4 : g++-4.4 ;
case *gcc-3.3* : using gcc : 3.3 : g++-3.3 ;
case * : error Only gcc v4 and gcc v3.3 supported. ;
}
}
else if [ os.name ] = AIX
{
using vacpp ;
}
else
{
error Only Linux and AIX supported at present. ;
}
After a long time I have found out that there is really no way (apart from very hacky) to do this. The goal of Boost.Build is to let the toolset option for the user to define.
The user has several ways to specify the toolset:
in the command line with --toolset=gcc for example
in the user configuration by setting it in the user-config.jam for all projects compiled by the user
in the site configuration by setting it in the site-config.jam for all users
the user-config.jam can be in the user's $HOME or in the boost build path.
the site-config.jam should be in the /etc directory, but could also be in the two locations above.
In summary, setup your site-config or user-config for a pleasant experience, and write a nice README file for users trying to compile your program.
Hope this helps someone else.