How to setup CMake to build anything for Android
-
Linux, NDK-10, QT-5.10.1, GCC. Qmake works fine, can compile to any CPU arch.
I was trying to build a sample project with CMake but it doesn't work out of the box. Seems like it's missing lots of things in default config/setup.
That's what I've done to try to make it work:- At first CMake itself didn't start at all. I followed QTCREATORBUG-16155: copied and renamed kit and added SYSROOT to CMake variables.
- Then commented out a line in QtCore cmake file as proposed in QTBUG-54666. Now CMake did actually generate build files.
- Then I've tried to compile a project aaaaand... Yes I didn't work :-). I decided to compare Qmake and CMake g++ command lines and found lots of differences. By adding g++ arguments from Qmake to CMake g++ command line one by one I've found those which made g++ compile. The Stl path! I've also added CMake vars which tell it to use gnustl_shared and C++11 but it was not sufficient. So, I've added
include_directories(SYSTEM /opt/android-ndk/sources/cxx-stl/gnu-libstdc++/4.9/include /opt/android-ndk/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/include)
to CMakeLists.txt. - Now the files are being compiled but they couldn't be linked:
... [1/4 61.2/sec] Automatic MOC and RCC for target SampleCmake Generating MOC predefs moc_predefs.h [2/2 36.2/sec] Linking CXX executable SampleCmake FAILED: SampleCmake : && /opt/android-ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ --sysroot=/opt/android-ndk/platforms/android-16/arch-arm -rdynamic CMakeFiles/SampleCmake.dir/main.cpp.o CMakeFiles/SampleCmake.dir/SampleCmake_autogen/mocs_compilation.cpp.o CMakeFiles/SampleCmake.dir/SampleCmake_autogen/EWIEGA46WW/qrc_qml.cpp.o -o SampleCmake -Wl,-rpath,/opt/qt-android/5.10/armeabi-v7a/lib /opt/qt-android/5.10/armeabi-v7a/lib/libQt5Quick.so -lstdc++ /opt/qt-android/5.10/armeabi-v7a/lib/libQt5Gui.so /opt/qt-android/5.10/armeabi-v7a/lib/libQt5Qml.so /opt/qt-android/5.10/armeabi-v7a/lib/libQt5Network.so /opt/qt-android/5.10/armeabi-v7a/lib/libQt5Core.so && : CMakeFiles/SampleCmake.dir/main.cpp.o:main.cpp:function main: error: undefined reference to '__cxa_end_cleanup' CMakeFiles/SampleCmake.dir/main.cpp.o(.ARM.extab.text._ZN7QStringD2Ev+0x0): error: undefined reference to '__gxx_personality_v0' CMakeFiles/SampleCmake.dir/main.cpp.o(.ARM.extab+0x0): error: undefined reference to '__gxx_personality_v0' CMakeFiles/SampleCmake.dir/main.cpp.o(.ARM.extab+0x10): error: undefined reference to '__gxx_personality_v0' CMakeFiles/SampleCmake.dir/main.cpp.o(.ARM.extab.text._ZN5QListIP7QObjectED2Ev+0x0): error: undefined reference to '__gxx_personality_v0' collect2: error: ld returned 1 exit status ...
I've found info that I should use -lstdc++ and found how to add it. I did it by adding
set(CMAKE_CXX_STANDARD_LIBRARIES -lstdc++)
to CMakeLists.txt. It added -lstdc++ to g++ link-time command line but did not help.P.S. Here are some more or less significant observations about difference between compile-time g++ command line in Qmake and CMake.
Qmake adds Qt libs with -I while CMake does same adding -isystem. Does that matter?
Also I've tried gnustl_static instead of gnustl_shared. That doesn't produce any different results.
There are also lots of missing arch-related compiler flags among compile-time g++ args produced by CMake. I've added some more variables to CMake config:CMAKE_ANDROID_ARCH_ABI:STRING=armeabi-v7a
andCMAKE_SYSTEM_NAME:STRING=Android
. This makes arch-related g++ flags list produced by CMake resemble the one produced by Qmake. But it doesn't help for linking either. -
Oh, I forgot to mention one important thing if anybody will stuck in the same place. If I don't make step 3 (don't propagate STL path) - the error
type_traits: No such file or directory
will raise up, just like in QBS-1200. But for that case it looks like asking Qbs to switch g++ to using gnustl_shared helped. In my case with CMake it's not sufficient - I have to tell g++ with the help of CMake where is STL actually situated which I've described in step 3.