Getting started with cmake

Time:2021-8-25

In C + +, it is very important to choose what kind of compiler. Unlike other languages, C + + programs are ultimately composed of header files (. H) and library files (. DLL or. So) components.
When different applications (Libraries) assist in work, they also need to support files and library files, and the library files on different platforms are inconsistent. Therefore, in cross platform development, we prefer to use cmake to compile and link.

Therefore, cmake is not a package management tool. It can not solve the problem of package dependency, but only solve the cross platform problem.

compiler

Turning the source code into an executable application requires something called a compiler. If a formed third-party library is used in the application, or your own application is large and needs the cooperation of multiple modules. You also need to connect these simulations to form a usable application.

This is like when a standard spring boot project is built, it can build a library containing itself and other third-party libraries that can be run directlyxxx.jarAnd a library that contains only its own and can be used as a third-party libraryxxx.jar.originalFile.

The process of turning the source code into executable bytecode is called compilation. The process of connecting the library generated by the source code with other libraries and finally forming an executable application is called linking.

The tools that accomplish the above functions are called compilers.

In java development, we need to download different jdks for different operating systems. Part of the function of this JDK is the java compiler. In C + + development, a compiler named clang has been installed in MacOS by default, so we don’t need to install it separately.

The C + + compiler in each system needs to be different. For example, clang is installed by default in MacOS. In addition, the compiler also has GNU (GCC, G + +). Different compilers have their own characteristics. When developing applications, we will also add the characteristics of these compilers to our source code. Then the compiler compiles it into byte files according to the source code. Some features are only supported by specific compilers, which is why some applications can only work with specific compilers.

Dependency management

There are some famous in JavamavengradlePackage manager, which can automatically download dependencies for us, then call the specified JDK for compilation, and can complete the packaging of Java applications.

Unfortunately, there is no such powerful package management tool in C + + applications. But for a project with multiple modules and dependencies, the idea of implementation is still the same.

likenpmPackages managed underpackage.jsonThe required package and version number are declared in and then usednpm installTo install. C + + applications can beCMakeLists.txtTo declare the version number. Then use other methods to install.

Load dependency

As mentioned earlier, cmake is a cross platform compiler, and its corresponding configuration file isCMakeLists.txt, the dependency on other third-party packages is described in this file.

find_package()

CMakeLists.txtThere are two ways to declare dependencies. The first is to usefind_package
For example:find_package(JsonCpp REQUIRED)。 At this time, cmake will first find its internal package. If it is not found in the internal package, it will find the file in the current directoryFindJsonCpp.cmakeFile. If you find itFindJsonCpp.cmakeFile, the package will be loaded according to the settings of the file; If not found, because the value of the second parameter isREQUIRED, an exception is thrown.

So if some third-party packages provideFindXxxx.cmakeFile, you can use it easilyfind_package(name, REQUIRED)Function to load third-party packages.

Generally, if the third-party package is found successfully, the following variables will be defined:

#The value is true when the package is found
Xxxx_FOUND
#Location of the package header file
Xxxx_ INCLUDE_ Dirs or XXXX_ INCLUDES
#The location of the package library file
Xxxx_ Library or XXXX_ Libraries or XXXX_ LIBS
#You can use message (${XXXX)_ Libraries}) to print the value of the variable

pkg_check_modules()

The second way is with the help ofPkgConfig

find_package(PkgConfig REQUIRED)

When the system is not installedPkgConfigA not found will be mentionedPkgConfigIn this case, it needs to be installed in the systemPkgConfig

YesPkgConfigThen you can use the information it providespkg_check_modulesThe packet detection method is used to obtain the information of the third-party packet:

pkg_check_modules(JSONCPP jsoncpp)

amongJSONCPPIt can be used as an alias,jsoncppIs the module name.

At this time, when there isjsoncppSystem variableJSONCPP__FOUNDThe value of istrue, otherwisefalse。 If the current project must depend on a third-party package, you can joinREQUIREDFor example:pkg_check_modules(XXX xxx REQUIRED)When does not existxxxAn exception will occur.

load

Whether throughfind_package()Or throughpkg_check_modulesTo obtain the third-party dependent package, which is essentially: check whether a package exists. If it exists, return the information of the package. If it does not exist, return the system variable XXXX_ Found is set to false. In addition, it has no other effect.

That is, the above two methods do not load dependencies on their third parties. Therefore, it is necessary to use the command to find the information of a package (the location of the package’s library file and header file), which is also the reason for considering cross platform. In the case of cross platform, we can’t use such as in windowsc:\xxx\xxxOr xunix~/xxx/xxxAny form. Therefore, before loading a dependency, you need to dynamically obtain the package information through the above methods. If you are currently using Windows system, it can bec:\xxx\xxIf the form used isxunixSystem, it may be/usr/local/xxxForm of.

Loading a third-party library requires that the header file be used in the locationinclude_directoriesInclude and use the librarytarget_link_librariesLink in.

include_directories(project-name ${Xxxxx_INCLUDE_DIRS})
target_link_libraries(project-name ${Xxxxx_LIBRARIES})

Package manager

Microsoft providesvcpkgTo install the dependencies of C + + applications. The shell installation method is as follows:

#Clone warehouse
git clone https://github.com/Microsoft/vcpkg.git --depth=1
#Enter the warehouse
cd vcpkg
#Run the installation script
./bootstrap-vcpkg.sh
#It is set to global installation. When installing other packages in the future, it is global
./vcpkg integrate install

After the executive board is fully installed, you will get a prompt:

[email protected] vcpkg % ./vcpkg integrate install
Applied user-wide integration for this vcpkg root.

CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=/Users/panjie/github/Microsoft/vcpkg/scripts/buildsystems/vcpkg.cmake"

It says that if we use the cmake tool again, we need to append the above parameters after the cmake command. If we use the clion editor, we need to add it to cmake options:
Getting started with cmake
At this time, cmake in clion will automatically add the above parameters during execution. Since then, clion can work happily with cmake and vcpkg package manager.

Install specific packages

For example, we install a for JSON serializationjsoncpp, you canvcpkgExecute in:./vcpkg install jsoncpp

[email protected] vcpkg % ./vcpkg install jsoncpp       
Computing installation plan...
...
The package jsoncpp:x64-osx provides CMake targets:

    find_package(jsoncpp CONFIG REQUIRED)
    target_link_libraries(main PRIVATE jsoncpp_object jsoncpp_static)

Finally, follow the prompts to add the above code to your projectCMakeLists.txtThen you can happily use the third-party jsoncpp package in the project:

    add_executable(yz-main yz-main.cpp)
    find_package(jsoncpp CONFIG REQUIRED)
    target_link_libraries(yz-main PRIVATE jsoncpp_object jsoncpp_static)    

After that, it can be used freely in the current projectjsoncppTo complete the serialization and deserialization of JSON.

summary

Finally, make a comparison and summary between Java and C + + projects:

  1. Both are compiled languages and need to be compiled first.
  2. Java source files are compiled using JDK. Different operating systems need to install different JDK installation packages; C + + needs to be compiled with C + + compiler, and different operating systems need to download different compilers.
  3. The java compiler has multiple versions, such as Oracle’s own JDK or the third-party openjdk; C + + compilers also have multiple versions, such as clang and GNU. In the actual development process, you need to download, install and configure according to your own needs.
  4. Java has unified package management and installation toolsmavenorgradle; C + + has a unified package management toolvcpkg, there is a unified installation toolcmake
  5. vcpkgWant to be withcmakeHappy work, you need to configure some parameters. This parameter is different for different computers and needs to be installed as requiredvcpkgConfigure according to the situation.