[cmake series] (3) practice of external project


Last time, we talked about the third-party dependency management and mentioned that our team is using itExternalProjectTo manage dependencies, let’s talk about the specific practice this time, and an open source dependency management tool vcpkg based on cmake.

Practice of external project

Let’s see what it looks like

ExternalProject_Add(<name> [<option>...])
ExternalProject_Add_Step(<name> <step> [<option>...])
ExternalProject_Add_StepTargets(<name> [NO_DEPENDS] <step1> [<step2>...])

Is it very simple, obviously not, because there are too many parameters in the document? Are you surprised?

In fact, most of the parameters can not be used, so I will select some commonly used parameters to talk about. From the step, it is mainly divided into the following steps:

  • Directory configuration

    • Prefix: Directory prefix. It is recommended to choose one that you like;
    • DOWNLOAD_ Dir: This is important. It is recommended to select a compilation directory of the same level. After deleting the compilation directory, it will be equivalent to a cache directory. The next compilation will save download time;
  • download

    • URL & URL_ Hash: package download and verification. It is recommended to use it even if there is git project, which can further reduce the download time (for GitHub, a domestic network clone)_ T);
    • GIT_ REPOSITORY & GIT_ Tag: git project clone, it is recommended to addGIT_SHALLOWTo reduce the size of clone project;
  • to update

    • PATCH_ Command is a source file that can be modified. For example, you can use it as a temporary bug modification scheme. After all, the project maintainer may not change it in time;
  • to configure

    • CONFIGURE_ Command: configuration parameter of non cmake project, which can execute configuration command, such as./configure --prefix=${CMAKE_INSTALL_PREFIX}In addition, it needs to be configuredBUILD_IN_SOURCE true
    • CMAKE_ Args: configuration parameters of cmake project, such as-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
  • compile

    • In most cases, it can be omitted
  • test

    • TEST_ Command: if you need to test the execution of the compiler, you can set it. In most cases, you can skip it and leave it blankTEST_COMMAND ""
  • install

    • INSTALL_ Command: in most cases, you can also skip the standard of executionmake installCommand. If it is not the installation command, it can be modified;
  • other

    • Depends: if there are other dependencies, you can configure this option. It will sort out the relationship between these dependencies, and then compile them in turn;

In the configuration, as you can see, I will set theprefixby${CMAKE_INSTALL_PREFIX}All third-party dependencies are installed in a configurable unified directory, which makes it easy to package together. In addition, this has another advantage. If there is a dependency, most cases can be solved automatically.

as forExternalProject_Add_StepI’ve omitted the other two. I don’t use them very much, but if you want to compile documents, you can still use them. andExternalProject_Get_PropertyFor what you willExternalProjectIt’s useful to use it as the main project compilation step, only considering that it’s not downloaded and compiled at configuration time. After all, it’s liketarget_link_libraiesThis kind of method requires that you already have a compiled product, so it is not very useful.

After you compile, you can package and upload all the compiled products to the public storage space, and then download them in the main directoryCMakeLists.txtIn this way, all your team members can save the compilation time of third-party code.

The specific code is regarded as the homework, and the prompt is as follows:

file(DOWNLOAD <url> <file> [...])
file(UPLOAD <file> <url> [...])

You may think that it’s a bit noisy and not afraid to do so. Next, let’s introduce a very convenient tool.


Microsoft has contributed a lot of products and tools to the open source industry this year. Vcpkg is one of them.

In short, it is a package management tool based on cmake. After the installation is completed, most of the dependencies can be installed with one command. More and more third-party packages begin to accept and provide vcpkg support. Although not all third-party packages have been included, and cross compilation also has some problems, I believe vcpkg is one of the candidates if there is a package management tool to unify C / C + +.

It’s easy to install:

git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg

If you need to install the package:

vcpkg install opencv

Then in your project, usefind_packageThen:

find_package(OpenCV REQUIRED)
target_link_libraries(target ${OpenCV_LIBS})

Finally, in the cmake configuration phase:

cmake .. -DCMAKE_TOOLCHAIN_FILE=path/to/vcpkg/scripts/buildsystems/vcpkg.cmake

It’s OK. For packages with system support such as opencv, it may not improve much efficiency, but for packages without much system support, such as Google test, nlohmann JSON, Prometheus CPP, you don’t need to bother to download and compile them by yourself any more.

Then, in order to run vcpkg at any time, you can add it to the system path:

export PATH="path/to/vcpkg/:$PATH"

Is it simple? However, it is not perfect at present. The reason why I don’t use it in the existing team projects is that the problem of cross compilation has not been solved. There are not many cross compilers supported by it at present. For example, in the face of cross compilation of Android and IOS, it has basically become a waste. I plan to use it in the future when it is perfect.

In addition, compared with the above scheme, the compilation time can not be saved.

Thank you for reading. This article was first published in GitHub issues: https://github.com/xizhibei/b… (star and watch strongly suggest); in addition, this article can also be read in my blog: https://blog.xizhibei.me/2020… .

This article uses by-nc-sa to license.