How to configure CMake scripts to generate a project that uses NDK's Clang toolchain and specific STL distribution

Hi,

OS is Windows 10 Professional (64-bit), version 1803, build 17134.48.
IDE is Visual Studio 2017 Community, version 15.7.3.
CMake is 3.11.3 (64-bit).
I’m running latest CodeWorks for Android 1R7.

Here’s a simple CMakeLists.txt file:

cmake_minimum_required(VERSION 3.9)
project(CMakeAndroidTest)
add_executable(cmake-android-test main.cpp)

And here’s a minimalistic main.cpp file:

int main()
{
return 0;
}

If I run CMake from the command-line using the above build environment, I’m getting VS projects/solution files tailored for gcc 4.9, targeting Android 9 API, using gnustl_static STL, without support for RTTI nor exceptions:

C:\Users\ema\Documents\Visual Studio 2017\Projects\CMakeAndroidTest\build>cmake … -G “Visual Studio 15 2017” -DCMAKE_SYSTEM_NAME=Android
– The C compiler identification is GNU 4.9.0
– The CXX compiler identification is GNU 4.9.0
– Check for working C compiler: C:/NVPACK/android-ndk-r15c/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-gcc.exe
– Check for working C compiler: C:/NVPACK/android-ndk-r15c/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-gcc.exe – works
– Detecting C compiler ABI info
– Detecting C compiler ABI info - done
– Detecting C compile features
– Detecting C compile features - done
– Check for working CXX compiler: C:/NVPACK/android-ndk-r15c/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++.exe
– Check for working CXX compiler: C:/NVPACK/android-ndk-r15c/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++.exe – works
– Detecting CXX compiler ABI info
– Detecting CXX compiler ABI info - done
– Detecting CXX compile features
– Detecting CXX compile features - done
– Configuring done
– Generating done
– Build files have been written to: C:/Users/ema/Documents/Visual Studio 2017/Projects/CMakeAndroidTest/build

OK, fine.

Now, I’m trying to customize the toolchain, Android API, STL library or RTTI/exceptions support by defining the following variables in CMakeLists.txt:

set(ANDROID_TOOLCHAIN clang)
set(ANDROID_PLATFORM android-24)
set(ANDROID_STL libc++)
set(ANDROID_CPP_FEATURES “rtti exceptions”)
set(ANDROID_ARM_NEON TRUE)

Absolutely no effect (yes, I clean up CMake cache between each CMake run). I’m getting no error, but it’s as if the variables aren’t taken into account.

So, rather than trying to refine the toolchain myself, I thought that using the default android.toolchain.cmake file provided by Android NDK r15c included with CodeWorks for Android 1R7 would do the trick for me. Nope, I’m simply unable to create VS projects/solution files:

C:\Users\ema\Documents\Visual Studio 2017\Projects\CMakeAndroidTest\build>cmake … -DCMAKE_TOOLCHAIN_FILE=C:\NVPACK\android-ndk-r15c\build\cmake\android.toolchain.cmake
– Building for: Visual Studio 15 2017
– Check for working C compiler: C:/NVPACK/android-ndk-r15c/toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe
– Check for working C compiler: C:/NVPACK/android-ndk-r15c/toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe – broken
CMake Error at C:/Program Files/CMake/share/cmake-3.11/Modules/CMakeTestCCompiler.cmake:52 (message):
The C compiler

"C:/NVPACK/android-ndk-r15c/toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe"

is not able to compile a simple test program.

It fails with the following output:

Change Dir: C:/Users/ema/Documents/Visual Studio 2017/Projects/CMakeAndroidTest/build/CMakeFiles/CMakeTmp

Run Build Command:"C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/MSBuild/15.0/Bin/MSBuild.exe" "cmTC_097ff.vcxproj" "/p:Configuration=Debug" "/p:VisualStudioVersion=15.0"
Microsoft (R) Build Engine version 15.7.179.6572 pour .NET Framework
Copyright (C) Microsoft Corporation. Tous droits réservés.

La génération a démarré 14/06/2018 15:35:38.
Projet "C:\Users\ema\Documents\Visual Studio 2017\Projects\CMakeAndroidTest\build\CMakeFiles\CMakeTmp\cmTC_097ff.vcxproj" sur le noud 1 (cibles par défaut).
PrepareForBuild:
  Création du répertoire "cmTC_097ff.dir\Debug\".
  Création du répertoire "C:\Users\ema\Documents\Visual Studio 2017\Projects\CMakeAndroidTest\build\CMakeFiles\CMakeTmp\Debug\".
  Création du répertoire "cmTC_097ff.dir\Debug\cmTC_097ff.tlog\".
InitializeBuildStatus:
  Création de "cmTC_097ff.dir\Debug\cmTC_097ff.tlog\unsuccessfulbuild", car "AlwaysCreate" a été spécifié.
ClCompile:
  C:\NVPACK\android-ndk-r15c\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\bin\arm-linux-androideabi-g++.exe
  testCCompiler.c
arm-linux-androideabi-g++.exe : error : unrecognized command line option '-fno-integrated-as' [C:\Users\ema\Documents\Visual Studio 2017\Projects\CMakeAndroidTest\build\CMakeFiles\CMakeTmp\cmTC_097ff.vcxproj]
arm-linux-androideabi-g++.exe : error : unrecognized command line option '-fno-limit-debug-info' [C:\Users\ema\Documents\Visual Studio 2017\Projects\CMakeAndroidTest\build\CMakeFiles\CMakeTmp\cmTC_097ff.vcxproj]
Génération du projet "C:\Users\ema\Documents\Visual Studio 2017\Projects\CMakeAndroidTest\build\CMakeFiles\CMakeTmp\cmTC_097ff.vcxproj" terminée (cibles par défaut) -- ÉCHEC.

ÉCHEC de la build.

"C:\Users\ema\Documents\Visual Studio 2017\Projects\CMakeAndroidTest\build\CMakeFiles\CMakeTmp\cmTC_097ff.vcxproj" (cible par défaut) (1) ->
(ClCompile cible) ->
  arm-linux-androideabi-g++.exe : error : unrecognized command line option '-fno-integrated-as' [C:\Users\ema\Documents\Visual Studio 2017\Projects\CMakeAndroidTest\build\CMakeFiles\CMakeTmp\cmTC_097ff.vcxproj]
  arm-linux-androideabi-g++.exe : error : unrecognized command line option '-fno-limit-debug-info' [C:\Users\ema\Documents\Visual Studio 2017\Projects\CMakeAndroidTest\build\CMakeFiles\CMakeTmp\cmTC_097ff.vcxproj]

    0 Avertissement(s)
    2 Erreur(s)

Temps écoulé 00:00:00.68

CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
CMakeLists.txt:2 (project)

– Configuring incomplete, errors occurred!
See also “C:/Users/ema/Documents/Visual Studio 2017/Projects/CMakeAndroidTest/build/CMakeFiles/CMakeOutput.log”.
See also “C:/Users/ema/Documents/Visual Studio 2017/Projects/CMakeAndroidTest/build/CMakeFiles/CMakeError.log”.

Can you see? Process starts up correctly using CLang as C++ compiler and then, all of a sudden, switch/revert to arm-linux-androideabi-g++ during compiler checks. What’s going on?

So, in short, what’s the right way to customize toolchain with CodeWorks for Android? I know how to switch to CLang from within VS once the projects/solution files have been generated [1] but this is not what I want to do; I want my VS projects/solution files generated from scratch to use CLang, using the chosen STL library, etc. As previously explained, defining the appropriate (I think) variables in CMakeLists.txt has no effect. Passing thel as CMake arguments from within the command-line doesn’t work either. Flags that I’ve tried without a success for e.g. switching to CLang:

-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang
-DCMAKE_ANDROID_TOOLCHAIN=clang
-DCMAKE_ANDROID_TOOLCHAIN_NAME=clang

(All tried out with/without CMAKE_ prefix; no luck).

BTW, the variables documented in android.toolchain.cmake are different than the ones in CMake | Android NDK page [2]. Which ones to use?

Thanks for reading.

 Émeric

[1] https://devtalk.nvidia.com/default/topic/987665/nsight-tegra-visual-studio-edition/clang-on-android/
[2] https://developer.android.com/ndk/guides/cmake

Hello Émeric, and thank you for using our software!

BTW, the variables documented in android.toolchain.cmake are different than the ones in CMake | Android NDK page [2]. Which ones to use?

The variables described in https://developer.android.com/ndk/guides/cmake are related to the CMake generator/integration module that generates Gradle build scripts with Android NDK support.

CMake version 3.6.x is recommended for generation of Visual C++ projects (.vcxproj files) in the format that’s compatible with Nsight Tegra VSE.
The project properties can be customized using CMake variables as described in the documentation:
https://cmake.org/cmake/help/v3.6/manual/cmake-toolchains.7.html?highlight=nsight#cross-compiling-using-nvidia-nsight-tegra

P.S.
Please note that CodeWorks is a software package containing various utilities, developer tools, application and SDK’s and it is not equivalent to NT VSE - the Android development offering that extends Visual Studio and MSBuild and is included in CodeWorks as a component.
https://developer.nvidia.com/nvidia-nsight-tegra

It’s possible to generate a project referencing Clang 5.0 toolchain from NDK r15c using cmake-3.11.4-win64-x64.
Here’s how:
You need the following 2 files:

  1. CMakeLists.txt that defines the generated project files
  2. The toolchain file, that instructs CMake to use Clang instead of GCC in its compiler feature discovery tests and the rest of a project generation process.
    The file can have an arbitrary name, like NsightTegraToolchain.cmake, and it should contain the following lines:
# CMake toolchain file for building Nsight Tegra project files
set(CMAKE_GENERATOR_TOOLSET clang-5.0)
set(CMAKE_SYSTEM_NAME Android)

Here’s an example CMake invocation command line used for generation of VS 2015 projects in NT VSE format:

cmake.exe  -G"Visual Studio 14 2015" -DCMAKE_TOOLCHAIN_FILE=NsightTegraToolchain.cmake

Attached is the example project that illustrates the approach.

VSNsightTegra.7z (6.97 KB)

Thank you Mikhail.

I didn’t pay attention to that, it’s now obvious.

As a side note, use of libc++ as STL library over default gnustl isn’t documented in ANDROID_STL_TYPE (https://cmake.org/cmake/help/latest/prop_tgt/ANDROID_STL_TYPE.html#prop_tgt:ANDROID_STL_TYPE): use llvm-libc++_static or llvm-libc++_shared string property to select it. llvm-libc++ seems to works fine too and I bet that it’ll select the shared flavor over the static one, if available.

Thanks, it works flawlessly. Besides clang- string property, it seems that clang-default is a valid choice too. I’m however unable to select armv7-a-hard as ANDROID_ARCH:

C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\VC\VCTargets\Platforms\Tegra-Android\Nvidia.AndroidBuild.targets(63,5): error : Hard FP is supported only for the NDK revisions from r9c to r11c. Please make sure that the path to NDK location is correctly specified either in Tools -> Options -> Nsight Tegra -> Android NDK location or in the project properties -> Android Directories -> Android NDK Location.

Android NDK location is however correctly set to C:\NVPACK\android-ndk-r15c that comes bundled with CodeWorks 1R7. No problem if ANDROID_ARCH is armv7-a (default choice, I think).

About RTTI and exceptions support, is there a more “integrated way” than https://devtalk.nvidia.com/default/topic/1003353/nsight-tegra-visual-studio-edition/cmake-support-and-rtti-exceptions/ to enable them? I mean, this solution works but -frtti -fexceptions are simply appended to the default -fno-rtti -fno-exceptions flags, thus resulting in an awkward compiler command-line that can lead to confusing parsing, starting with Visual Studio itself! Indeed, IDE is still reporting No for Enable C++ Exceptions and Enable Run-Time Type Information in a project’s C/C++ Code Generation and Language properties, whereas -frtti -fexceptions flags are definitely passed to the command-line and RTTI/exceptions support enabled during compilation.

Please mind the following points:

The support for armv7-a-hard ABI was removed in NDK r12:
https://github.com/android-ndk/ndk/blob/master/docs/HardFloatAbi.md
https://github.com/android-ndk/ndk/wiki/Changelog-r12#ndk

All STL types except libc++ are deprecated since NDK r16, they’re going to be removed in r18:
https://github.com/android-ndk/ndk/wiki/Changelog-r16#announcements

The product will remain compatible with older NDK versions.

Speaking of RTTI and exceptions, we have no other solution as of yet.
The convenient way is to write a patch to extend the CMake’s Nsight Tegra project generator, as CMake sources are open-sourced and the project maintainers are open to contributions.
Hope that helps!

Thanks for pointing this out. BTW, I totally misread the error message: the error was obviously “expected” with NDK r15c.

Hence the importance to explain how to enable use of libc++ in the documentation ;-)

Definitely. Many thanks!