Link fails when cross compiling OpenCV 3.3.1 for Raspberry Pi Zero even though libraries are present
I've been attempting to build OpenCV 3.3.1 for the Raspberry PI Zero (Raspbian stretch) on a Ubuntu 16.04 machine. I've been following the steps documented here https://github.com/HesselM/rpicross_n... with the major exception that instead of using the tools from https://github.com/raspberrypi/tools which have GCC 4.9.3 I used crosstool-ng to build a GCC 6.3.0 toolchain to match the GCC version shipped with Raspbian stretch. I've installed all the OpenCV prerequistites on a RaspberryPi Zero and then taken a copy of the filesystem to use as the system root for cross-compilation on the host.
CMake confliguration appears to work but the make build fails when linking libopencv_freetype.so
as the harfbuzz and freetype libraries are not found.
/opt/cross/x-tools/arm-unknown-linux-gnueabihf/bin/../lib/gcc/arm-unknown-linux-gnueabihf/6.3.0/../../../../arm-unknown-linux-gnueabihf/bin/ld: cannot find -lfreetype
/opt/cross/x-tools/arm-unknown-linux-gnueabihf/bin/../lib/gcc/arm-unknown-linux-gnueabihf/6.3.0/../../../../arm-unknown-linux-gnueabihf/bin/ld: cannot find -lharfbuzz
collect2: error: ld returned 1 exit status
modules/freetype/CMakeFiles/opencv_freetype.dir/build.make:97: recipe for target 'lib/libopencv_freetype.so.3.3.1' failed
These libraries are present in my RaspberryPI system in usr/lib/arm-linux-gnueabihf
-rw-r--r-- 1 dsnowdon dsnowdon 717178 Apr 27 2017 libfreetype.a
-rw-r--r-- 1 dsnowdon dsnowdon 909 Apr 27 2017 libfreetype.la
lrwxrwxrwx 1 dsnowdon dsnowdon 21 Apr 27 2017 libfreetype.so -> libfreetype.so.6.12.3
lrwxrwxrwx 1 dsnowdon dsnowdon 21 Apr 27 2017 libfreetype.so.6 -> libfreetype.so.6.12.3
-rw-r--r-- 1 dsnowdon dsnowdon 567844 Apr 27 2017 libfreetype.so.6.12.3
-rw-r--r-- 1 dsnowdon dsnowdon 739360 Jan 24 2017 libharfbuzz.a
lrwxrwxrwx 1 dsnowdon dsnowdon 24 Jan 24 2017 libharfbuzz.so -> libharfbuzz.so.0.10400.2
lrwxrwxrwx 1 dsnowdon dsnowdon 24 Jan 24 2017 libharfbuzz.so.0 -> libharfbuzz.so.0.10400.2
-rw-r--r-- 1 dsnowdon dsnowdon 551256 Jan 24 2017 libharfbuzz.so.0.10400.2
Building with make VERBOSE=1 shows that the failure occurs when this command is run:
/usr/bin/cmake -E cmake_link_script CMakeFiles/opencv_freetype.dir/link.txt --verbose=1
Which generates this:
/opt/cross/x-tools/arm-unknown-linux-gnueabihf/bin/arm-unknown-linux-gnueabihf-g++ -fPIC -isystem /opt/software/raspberrypi/rpi-cross/rootfs/usr/include/arm-linux-gnueabihf -isystem /opt/software/raspberrypi/rpi-cross/rootfs/usr/include -isystem /opt/software/raspberrypi/rpi-cross/rootfs/usr/local/include -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wuninitialized -Winit-self -Wno-narrowing -Wno-delete-non-virtual-dtor -Wno-comment -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -mfp16-format=ieee -fvisibility=hidden -fvisibility-inlines-hidden -O3 -DNDEBUG -DNDEBUG -shared -Wl,-soname,libopencv_freetype.so.3.3 -o ../../lib/libopencv_freetype.so.3.3.1 CMakeFiles/opencv_freetype.dir/src/freetype.cpp.o ../../lib/libopencv_imgproc.so.3.3.1 -ldl -lm -lpthread -lrt ../../3rdparty/lib/libtegra_hal.a -lfreetype -lharfbuzz ../../lib/libopencv_core.so.3.3.1
However if I manually add -L${RPI_ROOTFS}/usr/lib/arm-linux-gnueabihf
to give the following then the link works:
/opt/cross/x-tools/arm-unknown-linux-gnueabihf/bin/arm-unknown-linux-gnueabihf-g++ -L/opt/software/raspberrypi/rpi-cross/rootfs/usr/lib/arm-linux-gnueabihf ...
I'm not an expert in cross-compile, but did you try compiling it directly on a Raspberry Pi? It takes loooooonger, but it surely works - and saves you from all this hassle.
If you have a Rasp 2/3, you can plug the uSD card in it to compile it faster.
you could try to disable the freetype module:
@kbarni I have managed to compile OpenCV on the Raspberry PI 3. The trouble is that the Pi Zero has an older processor without some of the instructions supported by the Pi 3 and so I could not run the code on the Pi Zero. The Pi Zero does not have a lot of RAM and is single core.
This is strange. Normally all the PIs are compatible.They have different processors, but the same instruction set. As long as you use the same system and compiler, the library should work.
Move all the SD card to the Pi Zero. If you copy only the library, it might miss some dependencies.
You can also compile OpenCV on the Pi Zero. Count in a whole night, but it will eventually finish it. I compiled OpenCV on the original Pi, that has even less RAM and processing power.
It's true that the Zero has less RAM and a single core, so expect to scale your application accordingly (don't use large images and avoid processing that's computationally heavy).
@berak I tried building with freetype disabled and the build failed later on. Looks like it did not pick up one of the gstreamer includes so I think there is definitely something off with the lib and include paths than are being passed to the compiler.
@kbarni I'm running a build locally on the Pi Zero; so far it's run overnight and got to 53%
again, cross-compiling means, that you cannot use any of the libs present on your system. (because tose are x86 or x64, not arm)
you can only use, what you can cross-compile. so - no gstreamer, no ffmpeg, no gui, no harfbuzz, no external image libs, etc.
@kbarni OK, it took about 14 hours but it did eventually compile on the Pi Zero (I also bumped up the available swap to ensure it didn't hit any memory issues).
I'd still like to figure out why the cross compilation didn't work, but I can come back to that later. Thanks
Annoyingly I still got an illegal instruction when running on the PiZero using the locally compiled build. Looking at https://www.raspberrypi.org/forums/vi... it seems that I may need to explicitly disable neon instructions
@berak I'm well aware of that. I have harfbuzz, freetype, gstreamer and all the other prerequisites required to build OpenCV on the RaspberryPi filesystem image I'm using to cross compile with. I had thought I made that clear in my question.