If you’re a fan of OBS (Open Broadcaster Software), you may already be familiar with its vast library of plugins that enhance its functionality and provide added features. One such plugin that I recently developed is the URL API source plugin. This plugin allows you to fetch information from a URL and display it in your OBS stream. In this blog post, we will take a closer look at the source code for this plugin and understand how it works.
Category: cmake
Last time I’ve posted about cross compiling TF for the TK1. That however was a canned sample example from TF, based on the bazel build system.
Let’s say we want to make our own TF C++ app and just link vs. TF for inference on the TK1.
Now that’s a huge mess.
First we need to cross-compile TF with everything built in.
Then we need protobuf cross-compiled for the TK1.
Bundle everything together, cross(-compile) our fingers and pray.
The prayer doesn’t help. But let’s see what does…
So I just spent 1.5 hours figuring this out.
Compiling an example on Ubuntu 16.04 with OpenCV built from scratch with OpenNI2 support.
(OpenNI2 is from Orbbec, but that doesn’t make any difference: https://orbbec3d.com/develop/)
When using this straightforward CMake script for compilation – it doesn’t work:
cmake_minimum_required(VERSION 3.2) project(MyApp) find_package(OpenCV 3 REQUIRED) set(OPENNI2_LIBS "OpenNI2") link_directories("/home/user/Downloads/2-Linux/OpenNI-Linux-x64-2.3/Redist") add_executable(myapp main.cpp) target_link_libraries(myapp ${OpenCV_LIBS} ${OPENNI2_LIBS})
Complains of undefined references:
/usr/bin/c++ -g CMakeFiles/myapp.dir/main.cpp.o -o myapp -L/home/user/Downloads/2-Linux/OpenNI-Linux-x64-2.3/Redist -rdynamic -lOpenNI2 /usr/local/lib/libopencv_shape.so.3.2.0 /usr/local/lib/libopencv_stitching.so.3.2.0 /usr/local/lib/libopencv_superres.so.3.2.0 /usr/local/lib/libopencv_videostab.so.3.2.0 /usr/local/lib/libopencv_objdetect.so.3.2.0 /usr/local/lib/libopencv_calib3d.so.3.2.0 /usr/local/lib/libopencv_features2d.so.3.2.0 /usr/local/lib/libopencv_flann.so.3.2.0 /usr/local/lib/libopencv_highgui.so.3.2.0 /usr/local/lib/libopencv_ml.so.3.2.0 /usr/local/lib/libopencv_photo.so.3.2.0 /usr/local/lib/libopencv_video.so.3.2.0 /usr/local/lib/libopencv_videoio.so.3.2.0 /usr/local/lib/libopencv_imgcodecs.so.3.2.0 /usr/local/lib/libopencv_imgproc.so.3.2.0 /usr/local/lib/libopencv_core.so.3.2.0 -Wl,-rpath,/home/user/Downloads/2-Linux/OpenNI-Linux-x64-2.3/Redist:/usr/local/lib /usr/local/lib/libopencv_videoio.so.3.2.0: undefined reference to `oniStreamGetProperty' /usr/local/lib/libopencv_videoio.so.3.2.0: undefined reference to `oniRecorderDestroy' /usr/local/lib/libopencv_videoio.so.3.2.0: undefined reference to `oniDeviceIsCommandSupported' /usr/local/lib/libopencv_videoio.so.3.2.0: undefined reference to `oniDeviceSetProperty'
You’ll notice that -lOpenNI2
does indeed appear for correct linking.
The linker doesn’t complain that lib was not found – it just misses the references.
This lead me to understand it’s a linking order problem (after ~45 minutes of banging my head vs. the keyboard and swearing profusely).
Some more swearing and head banging got me to understand that CMake is messing around with the link order.
So even if try:
target_link_libraries(myapp ${OpenCV_LIBS} ${OPENNI2_LIBS} ${OpenCV_LIBS} ${OPENNI2_LIBS})
i.e. making the order effectively meaningless — it still doesn’t work!
More swearing and head banging, another ~40 minutes passed, and I figured out a solution.
The real solution is to slap someone in CMake in the face with a trout, but here’s a solution to my problem:
find_package(OpenCV 3 REQUIRED core highgui videoio) # ORDER MATTERS!!! videoio must be last! set(OpenCV_LIBS "${OpenCV_LIBS};OpenNI2") #add openni2 at the end (although cmake doesn't keep order anyway) target_link_libraries(myapp ${OpenCV_LIBS})
Now it compiles.
And look at the make VERBOSE=1
:
/usr/bin/c++ -g CMakeFiles/myapp.dir/main.cpp.o -o myapp -L/home/user/Downloads/2-Linux/OpenNI-Linux-x64-2.3/Redist -rdynamic /usr/local/lib/libopencv_highgui.so.3.2.0 /usr/local/lib/libopencv_videoio.so.3.2.0 -lOpenNI2 /usr/local/lib/libopencv_core.so.3.2.0 -Wl,-rpath,/home/user/Downloads/2-Linux/OpenNI-Linux-x64-2.3/Redist:/usr/local/lib -Wl,-rpath-link,/usr/local/lib
Can you see how highgui and videoio are before OpenNI2, and core is after?
Why? Whhhhhhy?
The key is to get OpenNI to be linked in order after videoio.
OMG CMake, OMG OpenCV, OMG you gaiz, W-T-F?
Update:
This method breaks down as soon as more OpenCV components are added. The order goes haywire again, and OpenNI2 comes before videoio, which breaks the link.
As of now the way I can compile it is like so:
set(LINK_LIBS /usr/local/lib/libopencv_core.so.3.2 /usr/local/lib/libopencv_highgui.so.3.2 /usr/local/lib/libopencv_videoio.so.3.2 /usr/local/lib/libopencv_imgproc.so.3.2 /usr/local/lib/libopencv_calib3d.so.3.2 OpenNI2)