CMake Compilation Tools and Project Building

Click on the aboveBeginner’s Guide to Vision” to selectStar or “Pin

Important content delivered promptly

Article Overview

This article starts with the compilation process of C/C++ code, clarifying the relationship between Make and Makefile, CMake and CMakeLists, and finally provides examples from the syntax rules of CMakeLists to help everyone become familiar with how to write a simple compilation script.

1

The Compilation Process of C/C++

The compilation process is essentially the translation of one language (usually a high-level language) into another language (usually a low-level language). The main workflow of compiling C/C++ programs is: source code → preprocessor → compiler → assembler → linker → executable program

(1) Preprocessing

In C/C++, before the compiler compiles the source program, the program text must first undergo preprocessing. The preprocessor provides a set of pre-compile processing directives and preprocessing operators, which formally begin with #, and do not actually belong to statements in C/C++, and cannot be translated by the compiler. They need to be preprocessed before actual compilation, ultimately outputting a “.i” file.

(2) Compilation

Compilation is the process of converting C/C++ code into assembly code. The compiler needs to perform lexical analysis and syntax analysis, and after confirming that all instructions conform to the syntax rules without syntax errors, it converts the code into assembly language, generating assembly code.

(3) Assembly

Assembly is the process of translating the assembly code output from the previous step into target machine instructions, generating a target file that contains machine language equivalent to the source program.

(4) Linking

Linking is the process of linking the target files generated by the assembler, system library target files, and library files together to generate an executable program that can run on a specific platform.

CMake Compilation Tools and Project Building

2

What is the relationship between Make and Makefile?

When there are many source files, it is generally not suitable to compile the code directly using gcc; at this point, an automated compilation tool is needed.

Make (GNU Make) is an automated software tool used to compile source code files into executable binary files, thus completing automated compilation. The Make tool requires a Makefile to provide compilation rules during the compilation process. The Makefile defines a series of compilation rules, including the order of compilation, which files need to be recompiled, and other operations.

Using the Make tool can automatically complete the compilation work; if a few source files are modified, only those few source files will be recompiled. If a header file is modified, all source files that include that header file will be recompiled. This automatic compilation greatly improves development efficiency and avoids unnecessary recompilation.

3

What are CMake and CMakeLists?

CMake is a more abstract cross-platform project management tool that can output various Makefile files or project files. For example, it can generate a Visual Studio project on Windows and a Makefile on Linux. In other words, CMake can generate project files for various compilers according to the same abstract rules, thus ignoring platform differences and abstracting into a consistent environment.

The rules followed by the execution of CMake commands are written in the CMakeLists.txt file.

CMake Compilation Tools and Project Building

For a large project, writing a Makefile can be quite complex. With the CMake tool, one can read all source files and automatically generate a Makefile. The basic process of using CMake to write a cross-platform project is as follows:

  1. Write source files

  2. Write CMakeLists.txt

  3. Generate Makefile using CMake based on CMakeLists.txt

  4. Use Make to call gcc to generate the executable file based on the Makefile

CMake Compilation Tools and Project Building

4

How to write CMakeLists

The writing of CMakeLists.txt mainly includes the following steps:

  1. cmake_minimum_required(VERSION 2.8.0): specifies the minimum version required by CMake;

  2. project(Project): specifies the project name;

  3. include_directories(): includes the header file directories;

  4. aux_source_directory(src dir_srcs): includes the source file directories;

  5. set(TEST_MATH): sets environment variables, all source files used for compilation must be placed here;

  6. add_executable(${PROJECT_NAME} ${TEST_MATH}): adds the executable file to be compiled;

  7. target_link_libraries(${PROJECT_NAME} m): adds the libraries required by the executable file;

CMake syntax has preset some commonly used variables:

  • CMAKE_MAJOR_VERSION: CMake major version;

  • CMAKE_MINOR_VERSION: CMake minor version;

  • CMAKE_C_FLAGS: sets C compilation options;

  • CMAKE_CXX_FLAGS: sets C++ compilation options;

  • PROJECT_SOURCE_DIR: root directory of the project;

  • PROJECT_BINARY_DIR: directory where the cmake command is run;

  • CMAKE_CURRENT_SOURCE_DIR: path of the current CMakeLists.txt;

  • CMAKE_CURRENT_BINARY_DIR: directory for compiling target files;

  • EXECUTABLE_OUTPUT_PATH: redefines the storage location of the target binary executable file

  • LIBRARY_OUTPUT_PATH: redefines the storage location of the target link library files

Example code is as follows (CMake syntax is case insensitive)

cmake_minimum_required(VERSION 2.8.12)
option(ARM "Activate the ARM cross-compile" OFF)
if(ARM)
    message(STATUS "ARM Cross-Compile")
    set(CMAKE_SYSTEM_NAME Linux)
    set(CMAKE_C_COMPILER /usr/local/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gcc)
    set(CMAKE_CXX_COMPILER /usr/local/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-g++)
    set(CMAKE_BUILD_TYPE "Release")
else()
    message(STATUS "Default Compile")
endif()
project("Demo")

In the above code, the cmake_minimum_required specifies the minimum version of CMake, and the if-else statement performs conditional judgment, as CMake can compile across platforms, the above code selects the ARM cross-compiler or the default compiler under Windows through macros.

The project() mentioned above specifies the current project name. The message() function is similar to printf for outputting information. The set() function is used to explicitly define variables, such as defining the CMAKE_C_COMPILER variable to store the path of the ARM platform C compiler, and the CMAKE_BUILD_TYPE variable to specify that the compiled program is the Release version.

add_compile_options(-D_DEBUG)
add_compile_options(-D_INTERNALDEBUG)
add_compile_options(-std=c++11)
add_compile_options(-O0)
add_compile_options(-g)
add_compile_options(-Wall)

add_compile_options is mainly used to set compilation options, for example, in the example code, -std=c++11 specifies that the C++ code should be compiled with C++11 support; -g allows all useful warnings provided by gcc to be emitted to the generated binary file; -O0 adjusts the level of compilation optimization, setting it to the highest requires -O3, and the lowest is -O0, which means no optimization;

# Find requirements
find_package(PCL REQUIRED)
if(NOT PCL_FOUND)
    message("Not found PCL")
endif()
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})

When using third-party libraries in a project, it is necessary to know where to find header files; where to find library files; and what the names of the linked libraries are. The find_package() command will search for Find.cmake in the module path, which records the relevant information of the library. For example, in the instance code, once the configuration path of the third-party library is found, one can include its header files through include_directories; link its library files through link_directories; and control the source code switches of the library using add_definitions to ensure that changes to the third-party library code do not damage its source code while adding one’s own functionalities.

file(GLOB_RECURSE SRC_LIST    ${CMAKE_CURRENT_SOURCE_DIR}/modules/src/*.cpp)
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/modules/common     SRC_COMMON_LIST)
add_library(perception STATIC        ${SRC_LIST}${SRC_COMMON_LIST})

file() stores the contents of files according to custom search rules into a variable, where the parameter GLOB will produce a list of all files matching the globbing expression and save it into the variableSRC_LIST. Alternatively, the parameter GLOB_RECURSE traverses all files matching the directory and subdirectory files and saves them into the variable SRC_LIST.

aux_source_directory() serves a similar function tofile(), finding all source files under a specified directory and storing the results in a specified variable name. For example, the above code saves the files under the common path into the variable SRC_COMMON_LIST.

add_library is used to package the source files saved in the variable into a library. You can choose between a static library or a dynamic library using parameters. For example:

add_library(perception STATIC ${SRC_LIST})

add_library(perception SHARED ${SRC_LIST})

link_directories(${CMAKE_CURRENT_SOURCE_DIR}/modules/lib/)
add_executable(main ${SRC_FILES})
target_link_libraries(main     libdetect.a    libsegment.a    libtracker.a)

Finally, the process of generating the executable file and linking the library files occurs, where add_executable uses the specified source files to generate the target executable file.

The target executable files can be classified into three types:

  • Regular executable target files

  • Imported executable target files

  • Alias executable target files

Among them, the commands link_libraries and target_link_libraries look quite similar but serve different functions:

link_libraries specifies the paths of the library files to be linked. Self-generated library files can be specified using this command so that the project can find them.

target_link_libraries links the target files with library files, allowing you to specify dynamic/static libraries. If only the library name is provided, the system will search for xxx.so or xxx.a files based on the linked library directory; or specify the full path.

Good news!
The Beginner’s Guide to Vision Knowledge Planet
is now open to the public👇👇👇





Download 1: OpenCV-Contrib Extension Module Chinese Version Tutorial
Reply: Extension Module Chinese Tutorial in the backend of the “Beginner’s Guide to Vision” public account to download the first OpenCV extension module tutorial in Chinese on the internet, covering installation of extension modules, SFM algorithms, stereo vision, object tracking, biological vision, super-resolution processing, and more than twenty chapters of content.

Download 2: Python Vision Practical Project 52 Lectures
Reply: Python Vision Practical Project in the backend of the “Beginner’s Guide to Vision” public account to download 31 visual practical projects including image segmentation, mask detection, lane line detection, vehicle counting, adding eyeliner, license plate recognition, character recognition, emotion detection, text content extraction, and face recognition, to help quickly learn computer vision.

Download 3: OpenCV Practical Project 20 Lectures
Reply: OpenCV Practical Project 20 Lectures in the backend of the “Beginner’s Guide to Vision” public account to download 20 practical projects based on OpenCV, achieving advanced learning of OpenCV.

Communication Group

Welcome to join the reader group of the public account to exchange with peers. Currently, there are WeChat groups for SLAM, 3D vision, sensors, autonomous driving, computational photography, detection, segmentation, recognition, medical imaging, GAN, algorithm competitions, etc. (will gradually be subdivided in the future). Please scan the WeChat ID below to join the group, with the note: “Nickname + School/Company + Research Direction”, for example: “Zhang San + Shanghai Jiao Tong University + Visual SLAM”. Please follow the format for notes; otherwise, you will not be approved. After successful addition, you will be invited to related WeChat groups based on your research direction. Please do not send advertisements in the group; otherwise, you will be asked to leave, thank you for your understanding~


Leave a Comment