[cmake-developers] Building with Qt for the Raspberry Pi with CMake
Stephen Kelly
steveire at gmail.com
Wed Apr 10 19:41:24 EDT 2013
Hi,
This is mostly just feedback on some experience with cross-compiling.
As part of trying to figure out to what extent Qt 5 needs to be patched to
solve the kind of issue raised in
http://public.kitware.com/Bug/view.php?id=14041
and fixed in 6c613b433c45efb0bb013a6bd668cbb8ac740259, I've been toying with
building Qt 5 for the Raspberry Pi (raspbian image).
I configured Qt like this:
/home/stephen/dev/src/qtbase-stable/configure -prefix
/home/stephen/dev/prefix/rpi -release -device linux-rasp-pi-g++ -make libs -
device-option CROSS_COMPILE=/home/stephen/rpi/gcc-4.7-linaro-rpi-
gnueabihf/bin/arm-linux-gnueabihf- -sysroot /home/stephen/rpi/rasp-pi-
rootfs/ -opensource -confirm-license -no-pch
[From the prefix you'll notice I'm not trying to reproduce #14041 here yet]
I can use the resulting Qt 5 build by passing a prefix and toolchain:
cmake .. -DCMAKE_PREFIX_PATH=/home/stephen/rpi/rasp-pi-
rootfs/home/stephen/dev/prefix/rpi/ -
DCMAKE_TOOLCHAIN_FILE=../rpiToolchain.cmake
$ cat ../rpiToolchain.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_C_COMPILER /home/stephen/rpi/gcc-4.7-linaro-rpi-
gnueabihf/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
[Side note, a colleague is working on a patch to generate such a toolchain
file as part of the Qt build. The Qt mkspecs have all needed information.
Any comments on that?]
I can then build GammaRay for the Pi if I patch it like this:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ca7a377..ea0b8d6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -91,6 +91,32 @@ if(Qt5Core_FOUND)
include("cmake/ECMQt4To5Porting.cmake")
include_directories(${QT_INCLUDES}) # TODO: Port away from this.
+
+ find_library(QTGUI_EGL_LIB EGL
+ PATHS /home/stephen/rpi/rasp-pi-rootfs/opt/vc/lib NO_DEFAULT_PATH)
+ if (QTGUI_EGL_LIB)
+ set_property(TARGET Qt5::Gui APPEND PROPERTY
+ IMPORTED_LINK_DEPENDENT_LIBRARIES_DEBUG "${QTGUI_EGL_LIB}")
+ set_property(TARGET Qt5::Gui APPEND PROPERTY
+ IMPORTED_LINK_DEPENDENT_LIBRARIES_RELEASE "${QTGUI_EGL_LIB}")
+ endif()
+
+ set(CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES ".so.1")
+ find_library(QTCORE_Z_LIB_1 libz.so.1 PATHS
+ /home/stephen/rpi/rasp-pi-rootfs/lib/arm-linux-gnueabihf/
+ NO_DEFAULT_PATH)
+ find_library(QTCORE_Z_LIB z PATHS
+ /home/stephen/rpi/rasp-pi-rootfs/usr/lib/arm-linux-gnueabihf/
+ NO_DEFAULT_PATH)
+ if (QTCORE_Z_LIB_1 AND QTCORE_Z_LIB)
+ set_property(TARGET Qt5::Core APPEND PROPERTY
+ IMPORTED_LINK_DEPENDENT_LIBRARIES_DEBUG
+ "${QTCORE_Z_LIB}" "${QTCORE_Z_LIB_1}")
+ set_property(TARGET Qt5::Core APPEND PROPERTY
+ IMPORTED_LINK_DEPENDENT_LIBRARIES_RELEASE
+ "${QTCORE_Z_LIB}" "${QTCORE_Z_LIB_1}")
+ endif()
This is working toward a patch to generate the
IMPORTED_LINK_DEPENDENT_LIBRARIES_* in Qt itself.
In regular builds of Qt 5, the IMPORTED_LINK_DEPENDENT_LIBRARIES_* does not
need to be specified because libz and libEGL are usually in standard
locations, so they don't need to be in -rpath-link specified directories.
However, the Raspberry Pi has libz.so in some funny locations:
stephen at hal:~/rpi/rasp-pi-rootfs$ find -name "*libz*"
./lib/arm-linux-gnueabihf/libz.so.1
./lib/arm-linux-gnueabihf/libz.so.1.2.7
./usr/lib/arm-linux-gnueabihf/libz.so
./usr/lib/arm-linux-gnueabihf/libz.a
stephen at hal:~/rpi/rasp-pi-rootfs$ ll usr/lib/arm-linux-gnueabihf/libz.*
-rw-r--r-- 1 stephen stephen 104598 Jun 24 2012 usr/lib/arm-linux-
gnueabihf/libz.a
lrwxrwxrwx 1 stephen stephen 46 Apr 9 17:03 usr/lib/arm-linux-
gnueabihf/libz.so -> ../../../lib/arm-linux-gnueabihf/libz.so.1.2.7
stephen at hal:~/rpi/rasp-pi-rootfs$ ll lib/arm-linux-gnueabihf/libz.*
lrwxrwxrwx 1 stephen stephen 13 Jun 24 2012 lib/arm-linux-
gnueabihf/libz.so.1 -> libz.so.1.2.7
-rw-r--r-- 1 stephen stephen 87792 Jun 24 2012 lib/arm-linux-
gnueabihf/libz.so.1.2.7
So, the libz.so.1 and libz.so are in different directories.
stephen at hal:~/rpi/rasp-pi-rootfs/home/stephen/dev/prefix/rpi/lib$
~/rpi/gcc-4.7-linaro-rpi-gnueabihf/bin/arm-linux-gnueabihf-ldd --root
~/rpi/rasp-pi-rootfs/ libQt5Core.so.5.1.0
libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0
(0xdeadbeef)
libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xdeadbeef)
ld-linux-armhf.so.3 => /lib/ld-linux-armhf.so.3 (0xdeadbeef)
libz.so.1 => /lib/arm-linux-gnueabihf/libz.so.1 (0xdeadbeef)
libgcc_s.so.1 => /lib/arm-linux-gnueabihf/libgcc_s.so.1
(0xdeadbeef)
libdl.so.2 => /lib/arm-linux-gnueabihf/libdl.so.2 (0xdeadbeef)
librt.so.1 => /lib/arm-linux-gnueabihf/librt.so.1 (0xdeadbeef)
libstdc++.so.6 => /usr/lib/arm-linux-gnueabihf/libstdc++.so.6
(0xdeadbeef)
libm.so.6 => /lib/arm-linux-gnueabihf/libm.so.6 (0xdeadbeef)
The libQt5Core.so links to the libz.so.1 version. So, for some reason I seem
to need both usr/lib/arm-linux-gnueabihf/ and lib/arm-linux-gnueabihf to
appear in the -rpath-link. Therefore I'm adding both to the LINK_DEPENDENT
libraries. The qmake files already add -rpath-link entries for these paths:
https://qt.gitorious.org/qt/qtbase/blobs/HEAD/mkspecs/devices/linux-rasp-pi-g++/qmake.conf
https://qt.gitorious.org/qt/qtbase/blobs/HEAD/mkspecs/devices/common/linux_device_post.conf
On the RPi image, these paths are preconfigured:
rasp-pi-rootfs/etc/ld.so.conf.d$ cat 00-vmcs.conf
/opt/vc/lib
rasp-pi-rootfs/etc/ld.so.conf.d$ cat arm-linux-gnueabihf.conf
# Multiarch support
/lib/arm-linux-gnueabihf
/usr/lib/arm-linux-gnueabihf
I also need to
set(CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES ".so.1")
to tell CMake that libz.so.1 is a shared library, otherwise it gets ignored.
So, for feedback, it seems like it might make sense to automatically treat
".so.<number>" as shared libraries for systems which split the libs and
symlinks like this.
It seems that if binaries are linked to shared libs with the sonumber
appended, and libraries without it are in the LINK_DEPENDENT_LIBRARIES, that
only 'happens' to work because they are usually in the same directory.
Comments?
I also tried other variations of the cmake command before realizing I had to
join the sysroot path and the install_prefix myself for the
CMAKE_PREFIX_PATH. My first attempt was like this:
cmake .. -DCMAKE_PREFIX_PATH=/home/stephen/dev/prefix/rpi/ -
DCMAKE_FIND_ROOT_PATH=/home/stephen/rpi/rasp-pi-rootfs/ -
DCMAKE_TOOLCHAIN_FILE=../rpiToolchain.cmake
which did not work.
-- The C compiler identification is GNU 4.7.2
-- The CXX compiler identification is GNU 4.7.2
-- Check for working C compiler: /home/stephen/rpi/gcc-4.7-linaro-rpi-
gnueabihf/bin/arm-linux-gnueabihf-gcc
-- Check for working C compiler: /home/stephen/rpi/gcc-4.7-linaro-rpi-
gnueabihf/bin/arm-linux-gnueabihf-gcc -- broken
CMake Error at /usr/share/cmake-2.8/Modules/CMakeTestCCompiler.cmake:61
(message):
The C compiler
"/home/stephen/rpi/gcc-4.7-linaro-rpi-gnueabihf/bin/arm-linux-gnueabihf-
gcc"
is not able to compile a simple test program.
It fails with the following output:
Change Dir: /home/stephen/dev/src/kdab/gammaray/rpi/CMakeFiles/CMakeTmp
Run Build Command:/home/stephen/rpi/rasp-pi-rootfs/usr/bin/make
"cmTryCompileExec1792583416/fast"
/home/stephen/rpi/rasp-pi-rootfs/usr/bin/make: 1:
/home/stephen/rpi/rasp-pi-rootfs/usr/bin/make: Syntax error: word
unexpected (expecting ")")
CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
CMakeLists.txt:17 (project)
The problem is that it is finding make in the sysroot, but it does work if I
additionally pass:
-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER
to cmake. Even though CMAKE_FIND_ROOT_PATH_MODE_PROGRAM is set to NEVER in
my toolchain file, I suppose that is processed to late already to take
effect for the compiler sanity check.
Maybe CMake should imply -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER for the
make tool (and for other tools needed that early in the cmake run).
Comments?
Thanks,
Steve.
More information about the cmake-developers
mailing list