C++ Dependencies With CMake
CMake is a great tool to manage your dependencies smoothly in C++ projects, but some open source repositories don’t provide installation info for CMake projects. This guide aims to show you how to include repositories in your projects using CMake. In particular, ZXing (famous QR code library) and OpenCV (famous computer vision library).
*Note: maybe it is a good idea to install OpenCV before ZXing, since ZXing enables an extra module if it finds OpenCV in the system.
Example 1: Include ZXing
- Go to your c++ project directory, for example mine looks like this:
cuda/
├─ matrix/
| ├─ Matrix.h
| ├─ Matrix.cpp
| ├─ CMakeLists.txt
├─ main.cpp
├─ CMakeLists.txt
cd cuda
- Clone the ZXing repo (inside your project, for better order):
git clone git@github.com:nu-book/zxing-cpp.git
- Make a folder for it inside
/usr/lib/:
sudo mkdir /usr/lib/zxing-cpp/
- Build the package in the folder we made (you must be located still in the root directory of the project, so that folder
./zxing-cppis visible):
sudo cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local -G "Unix Makefiles" -S zxing-cpp/ -B /usr/lib/zxing-cpp/
With these command we are setting:
-
-D CMAKE_INSTALL_PREFIX=/usr/local: Specifies the installation prefix where the ZXing library will be installed. In this case, you’ve set it to the system-wide location/usr/local, which is a common location for installing libraries and headers that are meant to be available system-wide. -
-S zxing-cpp/: Sets the source directory where CMake should look for the project’s CMakeLists.txt file. The source code for the ZXing library is located in thezxing-cpp/directory. In this case, CMake now understands that the source code is insidecuda/zxing-cpp. -
-B /usr/lib/zxing-cpp/: Sets the build directory where CMake generates build files, such as Makefiles, build scripts, and other intermediate files. In this case, you’ve set it to/usr/lib/zxing-cpp/.- If you go to
/usr/lib/zxing-cpp/and see what’s in there:
CMakeFiles cmake_install.cmake libZXing.so libZXing.so.2.1.0 libZXing.so.3 Makefile ZXingConfig.cmake ZXingConfigVersion.cmake zxing.pc ZXVersion.h- Here, CMake generates all the build-related files and folders required for building the ZXing library. The build process compiles the source code and creates the library files and CMake configuration files.
- If you go to
- Go to the folder:
cd /usr/lib/zxing-cpp/
- Install the package:
sudo make install
-
After running
sudo make install, the ZXing library files and CMake configuration files are installed in system-wide locations such as/usr/local/includeand/usr/local/lib/cmake.- If we go to
/usr/local/include/ZXing, you will find all header files that are available to#includein your cpp files:
BarcodeFormat.h BitMatrix.h ByteArray.h Content.h Error.h GTIN.h Matrix.h Point.h Range.h Result.h TextUtfEncoding.h ZXConfig.h ...- If we go to
/usr/local/lib/cmake/ZXing, you will find the CMake config files as well, that the linefind_package(ZXing REQUIRED)is looking for:
ZXingConfig.cmake ZXingConfigVersion.cmake ZXingTargets.cmake ZXingTargets-release.cmake- If we go to
/usr/lib/zxing-cpp/core/CMakeFiles/Export/lib/cmake/ZXing, we will find also CMake related files:
ZXingTargets.cmake ZXingTargets-release.cmake - If we go to
- Add to your project’s CMakeLists.txt at
./CMakeLists.txt:
find_package(ZXing REQUIRED PATHS /usr/lib/zxing-cpp/core)
cmake_policy(SET CMP0048 NEW)
cmake_minimum_required(VERSION 3.15)
project( main )
find_package(ZXing REQUIRED PATHS /usr/lib/zxing-cpp/core) # added, but it can be just find_package(ZXing REQUIRED) also
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_subdirectory(qrcode)
add_executable( main main.cpp )
target_link_libraries( main ${OpenCV_LIBS} ZXing::ZXing qrcode) # added
target_include_directories(main PRIVATE /usr/local/include) # addes
-
find_packagecommand searches for package configuration files in a list of well-known locations, including directories specified by theCMAKE_PREFIX_PATHvariable. TheCMAKE_PREFIX_PATHvariable is used to provide additional hints about where to find CMake packages. -
You installed the ZXing library using the CMAKE_INSTALL_PREFIX option, which set the installation prefix to
/usr/local. CMake automatically looks in the system-wide installation directories, including/usr/local/lib/cmake/ZXing, to find the package configuration files (e.g., ZXingConfig.cmake). -
The use of
find_package(ZXing REQUIRED)should ideally be sufficient to locate the ZXing library and its package configuration files, assuming that the installation was performed correctly. -
The alternative
find_package(ZXing REQUIRED PATHS /usr/lib/zxing-cpp/core)is a specific hint to CMake to look in a particular directory (in this case,/usr/lib/zxing-cpp/core) for the package configuration files. While this approach can work, it’s generally not the standard way to usefind_package, and it might be less portable across different systems.
- If you check the header files inside
/usr/local/lib/cmake/ZXing(step 6), you can now include in you cpp code the library:
#include <ZXing/BarcodeFormat.h>
int main(){
}
- It’s in the format
<ZXing/...>because of the installation path/usr/local/include/ZXing/.
Sources: https://stackoverflow.com/questions/66059595/building-zxing-zebra-crossing-library-on-linux
Example 2: Include OpenCV Full
- Install the needed modules:
cd ~
sudo apt install -y g++ cmake make git libgtk2.0-dev pkg-config
- Clone opencv classic (still in ~):
git clone https://github.com/opencv/opencv.git
mkdir -p build
- Clone extra opencv modules:
git clone https://github.com/opencv/opencv_contrib
- Build both:
cmake -DOPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules ~/opencv
make -j4
- Install them system-wide:
sudo make install
-
This command will copy header files to
/usr/local/include/opencv2:ccalib.hpp dpm.hpp fuzzy.hpp img_hash.hpp ... -
CMake configuration files for OpenCV and its extra modules are stored in
/usr/local/lib/cmake/opencv. These files are used by CMake when configuring projects that depend on OpenCV.libopencv_dpm.so libopencv_imgproc.so libopencv_rapid.so libopencv_tracking.so ...
- Now, in your project’s
./CMakeLists.txt, add these:
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
...
target_link_libraries( main ${OpenCV_LIBS} ...)
-
When you execute
find_package(OpenCV REQUIRED)in your CMake project, CMake searches for the OpenCV CMake configuration files in standard locations, including system-wide installation paths like/usr/local/lib/cmake/opencv.OpenCVConfig.cmake OpenCVConfig-version.cmake OpenCVModules.cmake OpenCVModules-release.cmake -
Therefore, as long as your desired lib has its CMakeConfig files inside a directory in
/usr/local/lib/cmake, yourfind_package()should work.
Conclusion
-
When installing a c++ dependency using CMake, make sure to:
-
clone the repo
-
build the source
-
install the built (compiled) source: this step will make some CMake files in
/usr/local/, in somecmakesub folder. -
add the lines
find_package()in the project’s./CMakeLists.txtso that the package is found. -
#includethe lib’s header files now, find them at/usr/local/include/your-lib-name.
-