[Xiao Mu learns C++] C++ builds engineering projects based on CMake (Windows, Linux)

1 Introduction

Official website address:
https://cmake.org

CMake is a cross-platform installation (compilation) tool, which can describe the installation (compilation process) of all platforms with simple sentences. It can output various makefiles or project files, and can test the C++ features supported by the compiler, similar to automake under UNIX. It's just that the configuration file of CMake is named CMakeLists.txt.
insert image description here

2. Download cmake

(1) Official website download address one
https://cmake.org/download/
insert image description here

(2) Official website download address 2
https://cmake.org/files/
insert image description here
(3) GitHub download address:
https://github.com/Kitware/CMake/releases
insert image description here

Under the ubuntu system, only the following command is required:

# ubuntu
sudo apt install cmake

CMake provides a variety of versions, including but not limited to "RC version" (Release Candidate) and "stable version" (Latest Release). Switch to the directory where the system stores the source code, and then use the curl command to download the binary distribution compressed package of CMake through this link:

cd /usr/local/src

curl -LO https://github.com/Kitware/CMake/releases/download/v3.22.2/cmake-3.22.2-linux-x86_64.tar.gz

# or
yum install -y wget
wget -c https://github.com/Kitware/CMake/releases/download/v3.22.2/cmake-3.22.2-linux-x86_64.tar.gz
# wget -c https://cmake.org/files/v3.26/cmake-3.26.0-rc1-linux-x86_64.tar.gz

insert image description here

3. Install cmake

After the CMake binary distribution compressed package is downloaded, run the following two commands to decompress the compressed package, move the obtained folder to the local program directory of the system, and rename the folder to cmake (ie /usr/local/cmake ):

tar -xvf cmake-3.26.0-rc1-linux-x86_64.tar.gz
# tar zxvf cmake-3.22.2-linux-x86_64.tar.gz
mv cmake-3.26.0-rc1-linux-x86_64 /usr/local/cmake

insert image description here
insert image description here
View the path after installation:

ls /usr/local/cmake

insert image description here

If you are installing CMake for the first time according to the steps in this article, for the convenience of running CMake related commands later, please run the following two commands to add the CMake executable file directory to the system environment variable PATH:

echo 'export PATH="/usr/local/cmake/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

insert image description here
View ~/.bashrc:

vi ~/.bashrc
#在最后添加export PATH=/usr/local/cmake/bin:$PATH

insert image description here

Check the version of cmake:

cmake --verison

insert image description here

4. Test cmake

4.1 Single source file

main.c:

#include <stdio.h>

int main(void)
{
    
    
	printf("Hello World\n");
	return 0;
}

Then write CMakeLists.txt in the same directory as main.c:

cmake_minimum_required (VERSION 2.8)
project (demo)
add_executable(main main.c)

Excuting an order:

cmake .

insert image description here
insert image description here
Let's take a look at the files in the directory again. The Makefile was successfully generated, and there are some files automatically generated when cmake runs:
insert image description here
View Makefile:

vi Makefile

insert image description here
Enter the make command to compile:

make
ls
./main
#make clean

insert image description here

4.2 Multiple source files in the same directory

Install the tree command to view the hierarchical relationship of folders:

ubuntu:sudo apt-get install tree
centos:yum -y install tree

insert image description here

tree ./

insert image description here

Modify CMakeLists.txt:

cmake_minimum_required (VERSION 2.8)

project (demo)
add_executable(main main.c anotherTest.c)

Excuting an order:

cmake .
ls
make
./main

insert image description here
If there are multiple source files in the same directory. cmake provides a command to store all source files in a specified directory in a variable, this command is aux_source_directory(dir var). The first parameter dir is the specified directory, and the second parameter var is the variable used to store the list of source files.

Modify CMakeLists.txt:

cmake_minimum_required (VERSION 2.8)

project (demo)
aux_source_directory(. SRC_LIST)
add_executable(main ${SRC_LIST})

Use aux_source_directory to store the source file storage list in the current directory into the variable SRC_LIST, and then call SRC_LIST in add_executable (note the way of calling the variable).
aux_source_directory() also has disadvantages. It will add all the source files in the specified directory, and may add some files we don’t need. At this time, we can use the set command to create new variables to store the required source files, as follows:

cmake_minimum_required (VERSION 2.8)

project (demo)
set( SRC_LIST
	 ./main.c
	 ./anotherTest.c)
	 
add_executable(main ${SRC_LIST})

4.3 Multiple source files in different directories

insert image description here
Modify CMakeLists.txt:

cmake_minimum_required (VERSION 2.8)
project (demo)

include_directories (test1 test2)

aux_source_directory (test1 SRC_LIST)
aux_source_directory (test2 SRC_LIST1)

add_executable (main main.c ${SRC_LIST} ${SRC_LIST1})

insert image description here

4.4 Standard Organizational Structure

Generally, the source files are put in the src directory, the header files are put in the include file, the generated object files are put in the build directory, and the final output elf file is put in the bin directory, so that the whole structure is clearer.
insert image description here
Modify CMakeLists.txt:

cmake_minimum_required (VERSION 2.8)
project (demo)

add_subdirectory (src)

Here, the source files are stored in the src directory. When cmake is executed, it will enter the src directory to find the CMakeLists.txt in the src directory, so create a CMakeLists.txt in the src directory: add CMakeLists.txt
:

aux_source_directory (. SRC_LIST)
include_directories (../include)
add_executable (main ${SRC_LIST})
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

There is a new command set here, which is used to define variables. EXECUTABLE_OUT_PATH and PROJECT_SOURCE_DIR are predefined variables that come with CMake. Their meanings are as follows.

EXECUTABLE_OUTPUT_PATH: The storage location of the target binary executable file
PROJECT_SOURCE_DIR: The root directory of the project

insert image description here
Create a new build folder and enter:

mkdir build
cd build
cmake ..
make
ls
../bin/main

insert image description here
You can also use only one CMakeLists.txt, and change the content of the outermost CMakeLists.txt as follows:

cmake_minimum_required (VERSION 2.8)
project (demo)

set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
aux_source_directory (src SRC_LIST)
include_directories (include)
add_executable (main ${SRC_LIST})

4.5 Compilation of dynamic library and static library

Sometimes it is necessary to compile dynamic libraries and static libraries, and then wait for other programs to use them. The test project folder is as follows:

  • The Windows example is as follows:
    insert image description here
    The content of CMakeLists.txt is as follows:
cmake_minimum_required (VERSION 2.8)

project (myrand)

# find *.cpp *.c
set (SRC_LIST ${PROJECT_SOURCE_DIR}/src/getRandomAPI.cpp)

# find *.h
include_directories (${PROJECT_SOURCE_DIR}/include)

########################################
# create lib and dll
add_library (myrand_shared SHARED ${SRC_LIST})
add_library (myrand_static STATIC ${SRC_LIST})

set_target_properties (myrand_shared PROPERTIES OUTPUT_NAME "myrand")
set_target_properties (myrand_static PROPERTIES OUTPUT_NAME "myrand_s")

set (LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

########################################
# create exe
add_compile_options(-std=c++11 -Wall)
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
add_executable (myrand_test ${SRC_LIST})
命令解释如下:
(1)add_library: 生成动态库或静态库(第1个参数指定库的名字;第2个参数决定是动态还是静态,如果没有就默认静态;第3个参数指定生成库的源文件)
(2)set_target_properties: 设置最终生成的库的名称,还有其它功能,如设置库的版本号等等
(3)LIBRARY_OUTPUT_PATH: 库文件的默认输出路径,这里设置为工程目录下的lib目录

Run cmake in the build directory, and store the generated library files (.dll, .lib) in the lib folder, and put the exe in the bin folder. Execute the command as follows:

cd C:\Users\tomcat\Desktop\test_cmake
mkdir build
cd build
cmake ..

insert image description here
Open the build folder as follows:
insert image description here
Compile myrand.sln through the command line, as follows.

# release x64(默认)
cd C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE
.\devenv.com C:\Users\tomcat\Desktop\test_cmake\build\myrand.sln /Build

# or debug x64
.\devenv.com F:\00Projects\test.sln /Build "Debug|64"

# or debug win32
.\devenv.com F:\00Projects\test.sln /Build "Debug|Win32"

The running results are as follows:
insert image description here
the running result folder is as follows:
insert image description here
insert image description here
insert image description here

4.6 Linking the library

Add a main.cpp in the src directory and call the library file generated in the above section.

cmake_minimum_required (VERSION 2.8)
project (myrand_test)

set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
set (SRC_LIST ${PROJECT_SOURCE_DIR}/src/main.cpp)

# find *.h
include_directories (${PROJECT_SOURCE_DIR}/include)

find_library(TEST_LIB NAMES myrand HINTS ${PROJECT_SOURCE_DIR}/lib/debug)

add_executable (test ${SRC_LIST})
target_link_libraries (test ${TEST_LIB})

Excuting an order:

cmake ..

insert image description here
insert image description here

4.7 Add compilation options

Add some compilation options, such as -Wall, -std=c++11, etc., and you can use add_compile_options to operate.

cmake_minimum_required (VERSION 2.8)
project (test)

set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
add_compile_options(-std=c++11 -Wall) 
add_executable(test main.cpp)

4.8 Add control options

Sometimes only compile some specified source code, you can use the cmake option command:

1、本来要生成多个bin或库文件,现在只想生成部分指定的bin或库文件
2、对于同一个bin文件,只想编译其中部分代码(使用宏来控制)

The content of CMakeLists.txt is as follows:

cmake_minimum_required(VERSION 3.0)
project(test)

set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
set (SRC_LIST ${PROJECT_SOURCE_DIR}/src/main.cpp)
set (SRC_LIST2 ${PROJECT_SOURCE_DIR}/src/main2.cpp)

option(USE_TEST_1 "use test 1" OFF)
option(USE_TEST_2 "use test 2" OFF)
option(USE_TEST_3 "use test 3" OFF)

if (USE_TEST_1)
    add_definitions(-DTEST_1)
endif()

if (USE_TEST_2)
    add_definitions(-DTEST_2)
endif()

if (USE_TEST_3)
    add_definitions(-DTEST_3)
endif()

add_executable(main ${SRC_LIST})

if (USE_PROJECT2)
    add_executable(main2 ${SRC_LIST2})
else()
    message(STATUS "No project main2")    
endif()

main.cpp:

#include <windows.h>
#include <iostream>

int main()
{
    
    
#ifdef TEST_1
	printf("getRandom_1\n");
#endif

#ifdef TEST_2
	printf("getRandom_2\n");
#endif

#ifdef TEST_3
	printf("getRandom_3\n");
#endif

	system("pause");
	return 0;
}
cmake .. -DTEST_3=ON -DTEST_2=OFF -DUSE_PROJECT2=OFF
cmake .. -DTEST_3=ON && make

5. Build a minimal project

5.1 Create a new code file

Edit the code file: tutorial.cpp

  • tutorial.cpp
// tutorial.cpp

#include <cmath>
#include <cstdlib>
#include <iostream>
#include <string>

int main(int argc, char* argv[])
{
    
    
    if (argc < 2) {
    
    
        std::cout << "Usage: " << argv[0] << " number" << std::endl;
        return 1;
    }

    // convert input to double
    const double inputValue = atof(argv[1]);

    // calculate square root
    const double outputValue = sqrt(inputValue);
    std::cout << "(爱看书的小沐)The square root of " << inputValue
              << " is " << outputValue
              << std::endl;
    return 0;
}

5.2 Create a new CMakeLists.txt

Create a new file in the same folder: CMakeLists.txt.

  • CMakeLists.txt
cmake_minimum_required(VERSION 3.15)

# set the project name
project(Tutorial)

# add the executable
add_executable(Tutorial tutorial.cpp)

cmake_minimum_required: specifies the minimum version number of CMake,
project: specifies the project name,
add_executable: is used to generate an executable file, and needs to specify the name of the generated executable file and related source files.

Now start building, compiling and running the above code example.
insert image description here

5.3 Building the project

In the current project working folder, create a build directory build. Next, enter the build directory and run CMake to configure the project and generate the build system.

mkdir build
cd build
cmake ..
  • Command execution status:
    insert image description here
  • The generated files and folders are as follows:
    insert image description here

5.4 Compile the project

Then invoke that build system to actually compile/link the project:

cmake --build .

insert image description here

  • The generated files and folders are as follows:
    insert image description here

5.5 Running the project

.\debug\Tutorial.exe 3.14

The result of the operation is as follows:
insert image description here

5.6 Modify related files

Edit the code file: CMakeLists.txt

  • CMakeLists.txt
cmake_minimum_required(VERSION 3.15)

## set the project name
# project(Tutorial)
project(Tutorial VERSION 1.2.3)

string(TIMESTAMP COMPILE_TIME %Y%m%d-%H%M%S)
configure_file(TutorialConfig.h.in TutorialConfig.h)

# set(SRC_LIST a.cpp b.cpp c.cpp)
SET(SRC_LIST tutorial.cpp)
		   
## add the executable
# add_executable(Tutorial tutorial.cpp)
# add_executable(${PROJECT_NAME} tutorial.cpp)
# add_executable(${PROJECT_NAME} a.cpp b.cpp c.cpp)
add_executable(${
    
    PROJECT_NAME} ${
    
    SRC_LIST})

target_include_directories(${
    
    PROJECT_NAME} PUBLIC
                           ${
    
    PROJECT_BINARY_DIR} )

New file: TutorialConfig.h.in

  • TutorialConfig.h.in
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @PROJECT_VERSION_MINOR@
#define Tutorial_VERSION_PATCH @PROJECT_VERSION_PATCH@

#define TIMESTAMP @COMPILE_TIME@

Edit the code file: tutorial.cpp

  • tutorial.cpp
// tutorial.cpp

#include <cmath>
#include <cstdlib>
#include <iostream>
#include <string>
#include "TutorialConfig.h"

int main(int argc, char* argv[])
{
    
    
    if (argc < 2) {
    
    
    	std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
                << Tutorial_VERSION_MINOR << std::endl;
        std::cout << "Usage: " << argv[0] << " number" << std::endl;
        return 1;
    }

    // convert input to double
    const double inputValue = atof(argv[1]);

    // calculate square root
    const double outputValue = sqrt(inputValue);
    std::cout << "(爱看书的小沐)The square root of " << inputValue
              << " is " << outputValue
              << std::endl;
    return 0;
}

Execute the following command:

cmake --build .
.\debug\Tutorial.exe

insert image description here
Make file: TutorialConfig.h
TutorialConfig.h:

insert image description here

insert image description here

epilogue

如果您觉得该方法或代码有一点点用处,可以给作者点个赞,或打赏杯咖啡;╮( ̄▽ ̄)╭
如果您感觉方法或代码不咋地//(ㄒoㄒ)// ,就在评论处留言,作者继续改进;o_O???
如果您需要相关功能的代码定制化开发,可以留言私信作者;(✿◡‿◡)
感谢各位大佬童鞋们的支持!(´▽´)ノ (´▽´)! ! !

Guess you like

Origin blog.csdn.net/hhy321/article/details/129135059