Recently LEARNED OpencV, FFMPEG, these excellent libraries are written using C/C ++, these projects are composed of multiple projects, if there is no a good tool to manage the relationship between them, this for every developer, without the help of the original author is impossible to complete the construction. Hence the introduction of CMake, which we download with the cmakelists.txt file so that developers can build the source code using CMake tools.

So here are a few steps for general usage

Build a single source file

We need to build the source file main.c into an executable with only three lines of configuration. Here main.c is the power of the number given manually by the runtime. The code is as follows:

#include <stdio.h>
#include <stdlib.h>
/**
 * power - Calculate the power of number.
 * @param base: Base value.
 * @param exponent: Exponent value.
 *
 * @return base raised to the power exponent.
 */
double power(double base, int exponent)
{
    int result = base;
    int i;
    
    if (exponent == 0) {
        return 1;
    }
    
    for(i = 1; i < exponent; ++i){
        result = result * base;
    }
    return result;
}

int main(int argc, char *argv[])
{
    if (argc < 3){
        printf("Usage: %s base exponent \n", argv[0]);
        return 1;
    }
    double base = atof(argv[1]);
    int exponent = atoi(argv[2]);
    double result = power(base, exponent);
    printf("%g ^ %d is %g\n", base, exponent, result);
    return 0;
}
Copy the code

Next, make sure the source file is in the same directory as the cmakelists.txt document, as shown below.

Cmakelists.txt configuration file

# Support cmake with minimum version 2.6Cmake_minimum_required (VERSION 2.6)# Project name
project(Demo1)

# Specify source code to generate executable file Demo1
add_executable(Demo1 main.c)

Copy the code

With these few lines of configuration you can generate an executable file, Demo1, which you need to build using the following command

// Execute 1.cmake. 2. Make in cmakelists. TXTCopy the code

Multi-directory source file build

Most of the time, our code is made up of many directories. We need to add the cmakelists. TXT file to the subdirectory of the build to describe the source relationships. For example, we’ll extract the power function from main.c into a new directory, math, as shown below:

Math/CMakeLists. TXT contents

Find all source files and put them in SRC_DIR variable.
aux_source_directory(. SRC_DIR)

Create a link library from the source file
add_library(MathFunctions ${SRC_DIR})
Copy the code

Add the following lines to cmakelists. TXT in the home directory

Add the math header from the source file to the compiler header search directory.
include_directories ("${PROJECT_SOURCE_DIR}/math")

Add math directory to cmake build. Cmakelists.txt will be executed in the subdirectory
add_subdirectory(math)

# Specify source code to generate executable file Demo2
add_executable(Demo2 main.c)

Link MathFunctions to Demo1
target_link_libraries(Demo2 MathFunctions)
Copy the code

Finally, execute cmake. And make commands to generate the executable.

Custom build configurations

In some cases, we need to control the source code, such as in our code above, by raising a number to a power. We can also use library functions to do this. We can control it at build time. So let’s improve the cmakelists. TXT file in the home directory.

# import header file to configure source code. Variables configured from config.h. n are printed to config.h
This is using macros to define #define
configure_file(
    "${PROJECT_SOURCE_DIR}/config.h.in"
    "${PROJECT_BINARY_DIR}/config.h"
)

The MY_MATH_FLAG variable can be set ON/OFF
option(MY_MATH_FLAG 
    "Whether to use custom functions for square root calculation"
    OFF
)

if (MY_MATH_FLAG)
    Add the math header from the source file to the compiler header search directory.
    include_directories ("${PROJECT_SOURCE_DIR}/math")
    Add math directory to cmake build. Cmakelists.txt will be executed in the subdirectory
    add_subdirectory(math)
    set(EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif(MY_MATH_FLAG)


# Specify source code to generate executable file Demo3
We can also use aux_source_directory(.src_dir) instead, which has the advantage of not writing multiple source files
add_executable(Demo3 main.c)

Link MathFunctions to Demo3
target_link_libraries(Demo3 ${EXTRA_LIBS})

Copy the code

We can compile this using the ccmake command, which specifies the ON/OFF status of the MY_MATH_FLAG variable. It will then ultimately determine what is generated in config.h if OFF is generated

/ *#undef MY_MATH_FLAG */

Copy the code

Generated for ON

 #define MY_MATH_FLAG

Copy the code

With config.h, we can do conditional compilation in source code

#include <stdio.h>
#include <stdlib.h>
#include "config.h"// MY_MATH_FLAG conditional compilation#ifdef MY_MATH_FLAG
    #include "CalcPower.h"
#else
    #include <math.h>
#endif

int main(int argc, char *argv[])
{
    if (argc < 3){
        printf("Usage: %s base exponent \n", argv[0]);
        return 1;
    }
    double base = atof(argv[1]);
    int exponent = atoi(argv[2]);

    #ifdef MY_MATH_FLAG
        double result = power(base, exponent);
        printf("Square calculation using custom function: %g ^ %d is %g\n", base, exponent, result);
    #else
        double result = pow(base, exponent);
        printf("Square calculation using system function: %g ^ %d is %g\n", base, exponent, result);
    #endif
        printf("%g ^ %d is %g\n", base, exponent, result);
    
    return 0;
}

Copy the code

Add test

In some cases, we need to test after the build is completed. We can use make install to do this by modifying the cmakelists. TXT file in the home directory

# import header files to configure the source code
configure_file(
    "${PROJECT_SOURCE_DIR}/config.h.in"
    "${PROJECT_BINARY_DIR}/config.h"
)

The MY_MATH_FLAG variable can be set ON/OFF
option(MY_MATH_FLAG 
    "Whether to use custom functions for square root calculation"
    ON
)

if (MY_MATH_FLAG)
    Add the math header from the source file to the compiler header search directory.
    include_directories ("${PROJECT_SOURCE_DIR}/math")
    Add math directory to cmake build. Cmakelists.txt will be executed in the subdirectory
    add_subdirectory(math)
    set(EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif(MY_MATH_FLAG)


# Specify source code to generate executable file Demo1
We can also use aux_source_directory(.src_dir) instead, which has the advantage of not writing multiple source files
add_executable(Demo4 main.c)

Link MathFunctions to Demo1
target_link_libraries(Demo4 ${EXTRA_LIBS})

Specify the Demo4 installation path
install (TARGETS Demo4 DESTINATION bin)
install (FILES "${PROJECT_BINARY_DIR}/config.h"        
         DESTINATION include)


# add test
enable_testing()
The [[#
add_test (test_run5_2 Demo4 5 2)
set_tests_properties (test_run5_2 PROPERTIES PASS_REGULAR_EXPRESSION "is 25")

add_test (test_run2_2 Demo4 2 2)
set_tests_properties (test_run2_2 PROPERTIES PASS_REGULAR_EXPRESSION "is 4")

add_test (test_run3_2 Demo4 3 2)
set_tests_properties (test_run3_2 PROPERTIES PASS_REGULAR_EXPRESSION "is 9")

add_test (test_run10_2 Demo4 10 2)
set_tests_properties (test_run10_2 PROPERTIES PASS_REGULAR_EXPRESSION "is 100")]]Use macro definitions to simplify writing test configurations
macro(do_test arg1 arg2 result)
    add_test(test_run${arg1}_${arg2} Demo4 ${arg1} ${arg2})
    set_tests_properties(test_run${arg1}_${arg2} PROPERTIES PASS_REGULAR_EXPRESSION ${result}
    )    
endmacro(do_test arg1 arg2 result)

do_test(5 2 "is 25")
do_test(2 2 "is 4")
do_test(3 2 "is 9")
do_test(10 2 "is 100")

Copy the code

I’ll write it down here and I’ll add it later. If you need a code, you can click here, and the code is differentiated by tag. You can switch to the corresponding point to view.