Continue with the last [CMake series] (a) introduction to continue.

This time, I will focus on CMake dependency management.

Dependency management

When we talk about dependency management of CMake, we usually talk about dependency management of C/C++ projects, but there is no official unified dependency management tool for this ancient language.

Ruby had gem, Node.js had NPM, Golang had Go Mod, Rust had Cargo.

You might mention that C++ introduced modules in C++20, but compiler support is still lacking, let alone support from well-known C++ projects. If you can do such as modern language after a command installed all dependencies can be directly used, the family sacrifice without forgetting to tell is weng.

So what kind of support does CMake give us? It can be said that projects that support CMake generally provide a file similar to xxx-config. CMake or xxxconfig. CMake, which provides lookup and import to the current project for use.

CMake find_package

Here’s what it looks like:

find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE] [REQUIRED] [[COMPONENTS] [components...]] [OPTIONAL_COMPONENTS components...]  [NO_POLICY_SCOPE])Copy the code

Therefore, if you need to introduce OpenCV dependencies, you need to write the following sentence before you compile your project files:

find_package(OpenCV 3.4.9 REQUIRED)
Copy the code

You need to look for OpenCV dependencies with version 3.4.9 (compatibility logic is controlled by the package itself. If it is not EXACT, it will automatically find compatible packages) and must be REQUIRED. Of course, if you don’t have to use this dependency, you can use the keyword QUIET.

And then where it needs to be used:

target_link_libraries(lib PUBLIC ${OpenCV_LIBS})
Copy the code

Notice the PUBLIC keyword here. This keyword means that if there are other libraries or executables that depend on lib, you don’t have to declare that you need opencV-related libraries again, CMake will add the dependencies automatically. Also, if you are using CMake version 3.5 or below, do this:

target_include_directories(lib PUBLIC ${OpenCV_INCLUDE_DIRS})
Copy the code

In addition, if you are looking for dependencies that require submodule dependencies, such as Boost, you would use COMPONENTS or OPTIONAL_COMPONENTS:

find_package(Boost 1.50 REQUIRED COMPONENTS filesystem)
target_link_libraries(lib PUBLIC Boost::filesystem)
Copy the code

Third Party dependency Management

Now the question is, if I can use find_package to manage packages so easily, how can I find packages?

Sudo apt install libopencv-dev if you need OpenCV sudo apt install libopencv-dev if you need OpenCV sudo apt install libopencv-dev On MacOS, brew Install OpencV is available.

If you are cross-compiling, or if the current version of the development library on your system does not meet the requirements, then you need to compile the source code.

At this point, the question arises, how does the source code fit into our development projects? Just copy it in, right? For those of you who have read my previous article on how to clone a large Git project, don’t make this mistake.

So how do you do that? Git SubModule is easy to use.

You can put the corresponding code base in a special folder, such as extern or third_party.

And then by a command like this: git submodule add https://github.com/opencv/opencv – b 3.4 extern/opencv to add.

For users, it requires git submodule update –init –recursive, or add –recursive when cloning.

Then, you need to add additional configuration steps to your cmakelists. TXT. If the project’s cmakelists. TXT is supported as a module, you can add it directly to a subdirectory: add_subdirectory(extern/opencv).

I tried this approach but ran into cross-compilation problems that I couldn’t solve for a while and abandoned it because some projects didn’t write cmakelists.txt as a standard and didn’t support it as a submodule of other projects, and not all projects supported CMake. Of course, you can fix this by writing a patch to your project, or by writing a special bash script.

If you don’t like the idea of using git subModules, you have three alternatives:

  1. ExternalProject: runs at compile time and cannot be used during configurationadd_subdirectory
  2. DownloadProject: Run at configuration time, yesadd_subdirectory;
  3. FetchContent (CMake 3.11+) : this is the official version of CMake 3.11+, which is simpler and only available in higher versions.

Currently, I use ExternalProject for team projects. Why? As a single step, it can pre-compile the libraries that each platform depends on, saving other team members unnecessary time.

I will be related to a third party rely on make it can command a compiler version, so every time can be on the server, using the high performance server CPU compile well, then the products directly to save storage space in public, finally others to use, can directly download the use, of course there will be signature verification was carried out on the product.

Moreover, even the download steps can be directly downloaded and used in the configuration stage through CMake, which greatly improves the development efficiency of the team.


Github Issues: github.com/xizhibei/bl… (Star and Watch strongly suggest 🙈); This article also can read in my blog: blog. Xizhibei. Me / 2020/03/15 /… .

In this paperAttribution – Non-commercial Use – Shared in the same way (BY-NC-SA)Grant permission.