cmake 03 一个可用的 cmake 工程应当是什么样的

news2024/12/24 11:27:43

cmake 学习笔记
代码地址:
https://gitcode.net/u014254963/cmake-study/-/tree/master/hello_cmake_project
https://gitcode.net/u014254963/cmake-study/-/tree/master/hello_cmake_project_vs

本文目标

  1. 多目录构建
  2. 引用自己写的动态库
  3. 关于单元测试的一些实践
  4. 使用 python 脚本控制构建的生命周期的目标描述

注意

  1. 本文不涉及任何静态库的操作
  2. 本文不涉及任何第三方库的 find_package 操作
  3. 本文不涉及任何 install 操作

简单的多目录

linux 与 vs 不需要测试

目录结构

F:\2023\code\cmake\hello_cmake_project>tree /f
卷 dox 的文件夹 PATH 列表
卷序列号为 34D2-6BE8
F:.
│  CMakeLists.txt
│
├─.vscode
│      launch.json
│      tasks.json
│
├─include
│      person.h
│
└─src
        CMakeLists.txt
        main.cpp
        person.cpp


F:\2023\code\cmake\hello_cmake_project>

c++

person.h

#ifndef  _PERSON_H_
#define  _PERSON_H_

#include <string>

class Person
{
public:
    Person();
    ~Person();
    std::string SayHello();
};

#endif // _PERSON_H_

person.cpp

#include "person.h"

Person::Person()
{

}
Person::~Person()
{

}
std::string Person::SayHello()
{
    return "hello world";
}

main.cpp

#include <iostream>

#include "person.h"

int main()
{
    Person *p = new Person();
    std::cout << p->SayHello() << std::endl;
    delete p;
    std::cout << "hello world" << std::endl;
    return 0;
}

CMakeLists.txt

CMakeLists.txt

# 该项目所需 cmake 的最小版本, 如果 cmake 版本小于设置的版本,  cmake 将停止处理并报错
cmake_minimum_required(VERSION 3.0)

# 设置项目名称和语言
project(hello_cmake_project CXX)
set(CMAKE_BUILD_TYPE DEBUG)

# 指定 c++ 11
set (CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)


MESSAGE(STATUS "源码目录: " ${PROJECT_SOURCE_DIR})
MESSAGE(STATUS "构建目录: " ${PROJECT_BINARY_DIR})

add_subdirectory(src)

src/CMakeLists.txt

# 头文件目录
include_directories(${PROJECT_SOURCE_DIR}/include)

# 源文件列表
aux_source_directory(. SRCS)

# 可执行文件目录
# set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

# 使用指定的源文件向项目添加可执行文件
add_executable(${PROJECT_NAME} ${SRCS})

使用过程

F:\2023\code\cmake\hello_cmake_project>cmake -S . -G "Unix Makefiles" -B build && cmake --build build --config debug
-- The CXX compiler identification is GNU 10.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: D:/program/tdmgcc/bin/g++.exe - skipped
-- Detecting CXX compile features       
-- Detecting CXX compile features - done
-- 源码目录: F:/2023/code/cmake/hello_cmake_project      
-- 构建目录: F:/2023/code/cmake/hello_cmake_project/build
-- Configuring done
-- Generating done
-- Build files have been written to: F:/2023/code/cmake/hello_cmake_project/build
[ 33%] Building CXX object src/CMakeFiles/hello_cmake_project.dir/main.cpp.obj
[ 66%] Building CXX object src/CMakeFiles/hello_cmake_project.dir/person.cpp.obj
[100%] Linking CXX executable hello_cmake_project.exe
[100%] Built target hello_cmake_project

F:\2023\code\cmake\hello_cmake_project>.\build\src\hello_cmake_project.exe
hello world
hello world

F:\2023\code\cmake\hello_cmake_project>

在这里插入图片描述

多目录生成动态库并使用

linux 和 vs 均需测试

源码

目录结构

F:\2023\code\cmake\hello_cmake_project>tree /f
卷 dox 的文件夹 PATH 列表
卷序列号为 34D2-6BE8
F:.
│  CMakeLists.txt
│
├─.vscode
│      launch.json
│      tasks.json
│
├─include
│  └─human
│          person.h
│
└─src
    │  CMakeLists.txt
    │
    ├─human
    │      CMakeLists.txt
    │      person.cpp
    │
    └─main
            CMakeLists.txt
            main.cpp


F:\2023\code\cmake\hello_cmake_project>

c++

只需要修改一下 person.h 引入的路径即可

#include "human/person.h"

CMakeLists.txt

CMakeLists.txt

# 该项目所需 cmake 的最小版本, 如果 cmake 版本小于设置的版本,  cmake 将停止处理并报错
cmake_minimum_required(VERSION 3.0)

# 设置项目名称和语言
project(hello_cmake_project CXX)
set(CMAKE_BUILD_TYPE DEBUG)

# 指定 c++ 11
set (CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# human 库名称
set(lib_human human)

add_subdirectory(src)

src/CMakeLists.txt

add_subdirectory(main)
add_subdirectory(human)

src/human/CMakeLists.txt

# 头文件目录
include_directories(${PROJECT_SOURCE_DIR}/include)

# 源文件列表
aux_source_directory(. HUMAN_SRCS)

# 设置生成目录
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/dist)

# 生成动态库, 默认生成的是静态库
add_library(${lib_human} SHARED ${HUMAN_SRCS})

# 指定动态库版本
# VERSION 动态库版本
# SOVERSION API版本
set_target_properties(${lib_human} PROPERTIES VERSION 1.0 SOVERSION 1)

src/main/CMakeLists.txt

# 头文件目录
include_directories(${PROJECT_SOURCE_DIR}/include)

# 源文件列表
aux_source_directory(. MAIN_SRCS)

# 可执行文件目录
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/dist)

# 使用指定的源文件向项目添加可执行文件
add_executable(${PROJECT_NAME} ${MAIN_SRCS})

# 声明链接时需要参与的依赖库名称
target_link_libraries(${PROJECT_NAME} ${lib_human})

命令行验证

注意: 缺失 dll 的提示需要在 cmd 下才能验证出来, 当然直接双击 exe 也可以验证

F:\2023\code\cmake\hello_cmake_project>cmake -S . -G "Unix Makefiles" -B build && cmake --build build --config debug
-- The CXX compiler identification is GNU 10.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: D:/program/tdmgcc/bin/g++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: F:/2023/code/cmake/hello_cmake_project/build
[ 25%] Building CXX object src/human/CMakeFiles/human.dir/person.cpp.obj
[ 50%] Linking CXX shared library F:/2023/code/cmake/hello_cmake_project/dist/libhuman.dll
[ 50%] Built target human
[ 75%] Building CXX object src/main/CMakeFiles/hello_cmake_project.dir/main.cpp.obj
[100%] Linking CXX executable F:/2023/code/cmake/hello_cmake_project/dist/hello_cmake_project.exe
[100%] Built target hello_cmake_project

F:\2023\code\cmake\hello_cmake_project>cd dist

F:\2023\code\cmake\hello_cmake_project\dist>dir
 驱动器 F 中的卷是 dox
 卷的序列号是 34D2-6BE8

 F:\2023\code\cmake\hello_cmake_project\dist 的目录

2023/01/21  18:09    <DIR>          .
2023/01/21  18:09    <DIR>          ..
2023/01/21  18:09         2,931,195 hello_cmake_project.exe
2023/01/21  18:09           752,047 libhuman.dll
2023/01/21  18:09             3,976 libhuman.dll.a
               3 个文件      3,687,218 字节
               2 个目录 92,873,236,480 可用字节

F:\2023\code\cmake\hello_cmake_project\dist>hello_cmake_project.exe
hello world
hello world

F:\2023\code\cmake\hello_cmake_project\dist>move libhuman.dll libhuman.dll.bak
移动了         1 个文件。

F:\2023\code\cmake\hello_cmake_project\dist>hello_cmake_project.exe

F:\2023\code\cmake\hello_cmake_project\dist>

在这里插入图片描述

如何在 vscode 中使用

由于默认的 exe 和 dll 生成的目录比较深, 所以重新设置了生成路径

# src/human/CMakeLists.txt
# 设置生成目录
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/dist)

# src/main/CMakeLists.txt
# 可执行文件目录
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/dist)

相应的 launch.json 也要修改

"program": "${workspaceFolder}/dist/hello_cmake_project.exe"

linux 验证

这一部分没有什么特殊的

ubuntu@ubuntu-cpp:~/code/cmake/hello_cmake_project$ ll
total 20
drwxrwxr-x 4 ubuntu ubuntu 4096 Jan 21 19:27 ./
drwxrwxr-x 4 ubuntu ubuntu 4096 Jan 21 19:27 ../
-rw-rw-r-- 1 ubuntu ubuntu  402 Jan 21 19:27 CMakeLists.txt
drwxrwxr-x 3 ubuntu ubuntu 4096 Jan 21 19:27 include/
drwxrwxr-x 4 ubuntu ubuntu 4096 Jan 21 19:27 src/
ubuntu@ubuntu-cpp:~/code/cmake/hello_cmake_project$ cmake -S . -B build && cmake --build build --config debug
-- The CXX compiler identification is GNU 11.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/ubuntu/code/cmake/hello_cmake_project/build
[ 25%] Building CXX object src/human/CMakeFiles/human.dir/person.cpp.o
[ 50%] Linking CXX shared library /home/ubuntu/code/cmake/hello_cmake_project/dist/libhuman.so
[ 50%] Built target human
[ 75%] Building CXX object src/main/CMakeFiles/hello_cmake_project.dir/main.cpp.o
[100%] Linking CXX executable /home/ubuntu/code/cmake/hello_cmake_project/dist/hello_cmake_project
[100%] Built target hello_cmake_project
ubuntu@ubuntu-cpp:~/code/cmake/hello_cmake_project$ ls -l dist
total 124
-rwxrwxr-x 1 ubuntu ubuntu 63384 Jan 21 19:27 hello_cmake_project
lrwxrwxrwx 1 ubuntu ubuntu    13 Jan 21 19:27 libhuman.so -> libhuman.so.1
lrwxrwxrwx 1 ubuntu ubuntu    15 Jan 21 19:27 libhuman.so.1 -> libhuman.so.1.0
-rwxrwxr-x 1 ubuntu ubuntu 60968 Jan 21 19:27 libhuman.so.1.0
ubuntu@ubuntu-cpp:~/code/cmake/hello_cmake_project$ ./dist/hello_cmake_project
hello world
hello world
ubuntu@ubuntu-cpp:~/code/cmake/hello_cmake_project$

如何在 vs 2019 中使用

这一部分稍显繁琐

  1. vs 的 debug 和 release 生成路径不一样
  2. 需要复制 dll 到 exe 所在目录

注意: CMakeLists.txt 脚本与源码均有变动

目录结构

F:\2023\code\cmake\hello_cmake_project_vs>tree /f
Folder PATH listing for volume dox
Volume serial number is 34D2-6BE8
F:.
│   CMakeLists.txt
│
├───include
│   └───human
│           framework.h
│           pch.h
│           person.h
│
└───src
    │   CMakeLists.txt
    │
    ├───human
    │       CMakeLists.txt
    │       dllmain.cpp
    │       pch.cpp
    │       person.cpp
    │
    └───main
            CMakeLists.txt
            main.cpp


F:\2023\code\cmake\hello_cmake_project_vs>

c++

include/human/framework.h

#pragma once

#define WIN32_LEAN_AND_MEAN             // 从 Windows 头文件中排除极少使用的内容
// Windows 头文件
#include <windows.h>

include/human/pch.h

// pch.h: 这是预编译标头文件。
// 下方列出的文件仅编译一次,提高了将来生成的生成性能。
// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。
// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。

#ifndef PCH_H
#define PCH_H

// 添加要在此处预编译的标头
#include "framework.h"

#endif //PCH_H

include/human/person.h

#ifndef  _PERSON_H_
#define  _PERSON_H_

#define DllExport __declspec(dllexport)

#include <string>

class DllExport Person
{
public:
    Person();
    ~Person();
    std::string SayHello();
};

#endif // _PERSON_H_

src/human/dllmain.cpp

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "human/pch.h"

BOOL APIENTRY DllMain(HMODULE hModule,
	DWORD  ul_reason_for_call,
	LPVOID lpReserved
)
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

src/human/pch.cpp

#include "human/pch.h"

src/human/person.cpp

#include "human/pch.h"
#include "human/person.h"

Person::Person()
{

}
Person::~Person()
{

}
std::string Person::SayHello()
{
    return "hello world";
}

src/main/main.cpp

#include <iostream>

#include "human/person.h"

int main()
{
    Person *p = new Person();
    std::cout << p->SayHello() << std::endl;
    delete p;
    std::cout << "hello world" << std::endl;
    return 0;
}

CMakeLists.txt

CMakeLists.txt

# 该项目所需 cmake 的最小版本, 如果 cmake 版本小于设置的版本,  cmake 将停止处理并报错
cmake_minimum_required(VERSION 3.0)

# 设置项目名称和语言
project(hello_cmake_project CXX)
set(CMAKE_BUILD_TYPE DEBUG)

# 指定 c++ 11
set (CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# 设置编译类型为 Debug
# set(CMAKE_BUILD_TYPE "Debug")
# set(CMAKE_BUILD_TYPE "Release")

# -------------------------------------------------------------------------------------------


#[[
    将 CMAKE_BUILD_TYPE 保存到 project_debug , 避免重复判断
    设置 debug 库后缀
]]
if(CMAKE_BUILD_TYPE)
    string(TOLOWER ${CMAKE_BUILD_TYPE} BUILD_TYPE)
    if(${BUILD_TYPE} STREQUAL "debug")
        set(project_debug 1)
        set(CMAKE_BUILD_TYPE "Debug")
        set(CMAKE_DEBUG_POSTFIX d)
    elseif(${BUILD_TYPE} STREQUAL "release")
        set(project_debug 0)
        set(CMAKE_BUILD_TYPE "Release")
    else()
        set(project_debug 1)
        set(CMAKE_BUILD_TYPE "Debug")
        set(CMAKE_DEBUG_POSTFIX d)
    endif()
else()
    set(project_debug 1)
    set(CMAKE_BUILD_TYPE "Debug")
    set(CMAKE_DEBUG_POSTFIX d)
endif()

# -------------------------------------------------------------------------------------------

#[[
    设置构建目录
]]
if(project_debug)
    set(build_dir out/build/x64-Debug)
else()
    set(build_dir out/build/x64-Release)
endif()

# -------------------------------------------------------------------------------------------

#[[
    全局引入的头文件
]]

# 当前项目目录
include_directories(${PROJECT_SOURCE_DIR}/include)

# -------------------------------------------------------------------------------------------

#[[
    全局变量
]]

# 每个目标源文件所在目录(相对于根目录)
set(main_dir src/main)
set(human_dir src/human)

######### 主程序 变量
# 主程序可执行文件路径
set(main_binary_dir ${CMAKE_INSTALL_PREFIX}/${main_dir})
string(REPLACE install build main_binary_dir ${main_binary_dir})

######### human 库 变量
# human 库路径
set(human_library_dir ${CMAKE_INSTALL_PREFIX}/${human_dir})
string(REPLACE install build human_library_dir ${human_library_dir})
# human 库名称, 不带后缀
set(human_lib_name human)
# human 库名称, 带后缀
set(human_lib_file_name ${human_lib_name}${CMAKE_DEBUG_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX})

# -------------------------------------------------------------------------------------------

#[[
    输出信息
]]
message(STATUS "CMAKE_BUILD_TYPE : ${CMAKE_BUILD_TYPE}")
message(STATUS "main_binary_dir ${main_binary_dir}")
message(STATUS "human_library_dir ${human_library_dir}")
message(STATUS "human_lib_name ${human_lib_name}")
message(STATUS "human_lib_file_name ${human_lib_file_name}")
if(project_debug)
    message(STATUS "current project compile type is debug")
else()
    message(STATUS "current project compile type is release")
endif()


add_subdirectory(src)

src/CMakeListst.txt

add_subdirectory(main)
add_subdirectory(human)

src/human/CMakeListst.txt

# 头文件目录
include_directories(${PROJECT_SOURCE_DIR}/include)

# 源文件列表
aux_source_directory(. HUMAN_SRCS)

# 设置生成目录
# set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/dist)

# 生成动态库, 默认生成的是静态库
add_library(${human_lib_name} SHARED ${HUMAN_SRCS})

# 指定动态库版本
# VERSION 动态库版本
# SOVERSION API版本
set_target_properties(${human_lib_name} PROPERTIES VERSION 1.0 SOVERSION 1)

# 指定 msvc 编译模式
if(project_debug)
    target_link_options(${human_lib_name} PRIVATE /DEBUG)
else()
    target_link_options(${human_lib_name} PRIVATE /RELEASE)
endif()

# 构建后复制到主程序 exe 所在路径
if(project_debug)
    add_custom_command(TARGET ${human_lib_name} POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy ${human_library_dir}/${human_lib_file_name} ${main_binary_dir}/${human_lib_file_name}
    )
else()
    add_custom_command(TARGET ${human_lib_name} POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy ${human_library_dir}/${human_lib_file_name} ${main_binary_dir}/${human_lib_file_name}
    )
endif()

src/man/CMakeListst.txt

# 头文件目录
include_directories(${PROJECT_SOURCE_DIR}/include)

# 源文件列表
aux_source_directory(. MAIN_SRCS)

# 可执行文件目录
# set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/dist)

# 使用指定的源文件向项目添加可执行文件
add_executable(${PROJECT_NAME} ${MAIN_SRCS})

# 声明链接时需要参与的依赖库名称
target_link_libraries(${PROJECT_NAME} ${human_lib_name})

# 指定 msvc 编译模式
if(project_debug)
    target_link_options(${PROJECT_NAME} PRIVATE /DEBUG)
else()
    target_link_options(${PROJECT_NAME} PRIVATE /RELEASE)
endif()

cmake 生成

debug 生成如下

1> 已为默认配置“x64-Debug”启动 CMake 生成。
1> 命令行: "C:\WINDOWS\system32\cmd.exe" /c "%SYSTEMROOT%\System32\chcp.com 65001 >NUL && "D:\PROGRAM\MICROSOFT\VS2019\IDE\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CMAKE\CMake\bin\cmake.exe"  -G "Ninja"  -DCMAKE_BUILD_TYPE:STRING="Debug" -DCMAKE_INSTALL_PREFIX:PATH="F:\2023\code\cmake\hello_cmake_project_vs\out\install\x64-Debug" -DCMAKE_CXX_COMPILER:FILEPATH="D:/program/microsoft/vs2019/ide/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe"  -DCMAKE_MAKE_PROGRAM="D:\PROGRAM\MICROSOFT\VS2019\IDE\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CMAKE\Ninja\ninja.exe" "F:\2023\code\cmake\hello_cmake_project_vs" 2>&1"
1> 工作目录: F:\2023\code\cmake\hello_cmake_project_vs\out\build\x64-Debug
1> [CMake] -- The CXX compiler identification is MSVC 19.29.30133.0
1> [CMake] -- Detecting CXX compiler ABI info
1> [CMake] -- Detecting CXX compiler ABI info - done
1> [CMake] -- Check for working CXX compiler: D:/program/microsoft/vs2019/ide/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe - skipped
1> [CMake] -- Detecting CXX compile features
1> [CMake] -- Detecting CXX compile features - done
1> [CMake] -- CMAKE_BUILD_TYPE : Debug
1> [CMake] -- main_binary_dir F:/2023/code/cmake/hello_cmake_project_vs/out/build/x64-Debug/src/main
1> [CMake] -- human_library_dir F:/2023/code/cmake/hello_cmake_project_vs/out/build/x64-Debug/src/human
1> [CMake] -- human_lib_name human
1> [CMake] -- human_lib_file_name humand.dll
1> [CMake] -- current project compile type is debug
1> [CMake] -- Configuring done
1> [CMake] -- Generating done
1> [CMake] -- Build files have been written to: F:/2023/code/cmake/hello_cmake_project_vs/out/build/x64-Debug
1> 已提取 CMake 变量。
1> 已提取源文件和标头。
1> 已提取代码模型。
1> 已提取工具链配置。
1> 已提取包含路径。
1> CMake 生成完毕。

release 生成如下

1> 已为配置“x64-Release”启动 CMake 生成。
1> 命令行: "C:\WINDOWS\system32\cmd.exe" /c "%SYSTEMROOT%\System32\chcp.com 65001 >NUL && "D:\PROGRAM\MICROSOFT\VS2019\IDE\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CMAKE\CMake\bin\cmake.exe"  -G "Ninja"  -DCMAKE_BUILD_TYPE:STRING="RelWithDebInfo" -DCMAKE_INSTALL_PREFIX:PATH="F:\2023\code\cmake\hello_cmake_project_vs\out\install\x64-Release" -DCMAKE_CXX_COMPILER:FILEPATH="D:/program/microsoft/vs2019/ide/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe"  -DCMAKE_MAKE_PROGRAM="D:\PROGRAM\MICROSOFT\VS2019\IDE\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CMAKE\Ninja\ninja.exe" "F:\2023\code\cmake\hello_cmake_project_vs" 2>&1"
1> 工作目录: F:\2023\code\cmake\hello_cmake_project_vs\out\build\x64-Release
1> [CMake] -- The CXX compiler identification is MSVC 19.29.30133.0
1> [CMake] -- Detecting CXX compiler ABI info
1> [CMake] -- Detecting CXX compiler ABI info - done
1> [CMake] -- Check for working CXX compiler: D:/program/microsoft/vs2019/ide/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe - skipped
1> [CMake] -- Detecting CXX compile features
1> [CMake] -- Detecting CXX compile features - done
1> [CMake] -- CMAKE_BUILD_TYPE : Release
1> [CMake] -- main_binary_dir F:/2023/code/cmake/hello_cmake_project_vs/out/build/x64-Release/src/main
1> [CMake] -- human_library_dir F:/2023/code/cmake/hello_cmake_project_vs/out/build/x64-Release/src/human
1> [CMake] -- human_lib_name human
1> [CMake] -- human_lib_file_name human.dll
1> [CMake] -- current project compile type is release
1> [CMake] -- Configuring done
1> [CMake] -- Generating done
1> [CMake] -- Build files have been written to: F:/2023/code/cmake/hello_cmake_project_vs/out/build/x64-Release
1> 已提取 CMake 变量。
1> 已提取源文件和标头。
1> 已提取代码模型。
1> 已提取工具链配置。
1> 已提取包含路径。
1> CMake 生成完毕。

要点

  1. 从 vs 的 cmake 输出可看出, vs 设置了 -DCMAKE_CXX_COMPILER:FILEPATH=".../cl.exe" , -DCMAKE_MAKE_PROGRAM="...\ninja.exe". 关于 ninja 的文档可在https://ninja-build.org/找到. 简单来说, ninja 是个 Makefile/make的替代品, 与 linux 对比的话, 就是把 gcc 换成了 cl.exe , 把 make 换成了 ninja
  2. 与之前的使用方式相同, 构建 release 版本, 需要手动设置 set(CMAKE_BUILD_TYPE "Release")

关于单元测试

参考

浅谈c++单元测试
C++单元测试工具——doctest
doctest

cmake 整合 doctest 示例

修改的是 vscode 的版本

目录结构

F:\2023\code\cmake\hello_cmake_project>tree /f
卷 dox 的文件夹 PATH 列表
卷序列号为 34D2-6BE8
F:.
│  build.txt
│  CMakeLists.txt
│
├─.vscode
│      launch.json
│      tasks.json
│
├─include
│  └─human
│          person.h
│
├─src
│  │  CMakeLists.txt
│  │
│  ├─human
│  │      CMakeLists.txt
│  │      person.cpp
│  │
│  └─main
│          CMakeLists.txt
│          main.cpp
│
├─test
│      CMakeLists.txt
│      hellocmaketest.cpp
│
└─third
    └─doctest
            doctest.h


F:\2023\code\cmake\hello_cmake_project>

顶层 CMakeLists.txt

# 该项目所需 cmake 的最小版本, 如果 cmake 版本小于设置的版本,  cmake 将停止处理并报错
cmake_minimum_required(VERSION 3.0)

# 设置项目名称和语言
project(hello_cmake_project CXX)
set(CMAKE_BUILD_TYPE DEBUG)

# 指定 c++ 14
set (CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# human 库名称
set(lib_human human)

add_subdirectory(src)

# 下面的就是测试相关的

# 传递项目根目录
set(proj_dir ${PROJECT_SOURCE_DIR})
# 添加测试项目所在目录
add_subdirectory(test)
# 必须添加这两行, 而且必须在顶层 CMakeLists.txt 添加
enable_testing()
add_test(NAME hello_cmake_test COMMAND hello_cmake_test)

test 项目

CMakeLists.txt

# 该项目所需 cmake 的最小版本, 如果 cmake 版本小于设置的版本,  cmake 将停止处理并报错
cmake_minimum_required(VERSION 3.0)

# 设置项目名称和语言
project(hello_cmake_test CXX)
set(CMAKE_BUILD_TYPE DEBUG)

# 指定 c++ 14
set (CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)

include_directories(${proj_dir}/include)
include_directories(${proj_dir}/third)

aux_source_directory(. TEST_SRCS)

set(EXECUTABLE_OUTPUT_PATH ${proj_dir}/dist)

add_executable(${PROJECT_NAME} ${TEST_SRCS})

target_link_libraries(${PROJECT_NAME} ${lib_human})

hellocmaketest.cpp

#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest/doctest.h"
#include "human/person.h"

int add(int x , int y )
{
    return x + y;
}

TEST_CASE("test add")
{
    CHECK(3 == add(1,2));
}

TEST_CASE("test person")
{
    Person *p = new Person();
    std::string s = "hello world";
    CHECK(0 == p->SayHello().compare(s));
}

使用过程

F:\2023\code\cmake\hello_cmake_project>cmake -S . -G "Unix Makefiles" -B build && cmake --build build --config debug
-- The CXX compiler identification is GNU 10.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: D:/program/tdmgcc/bin/g++.exe - skipped
-- Detecting CXX compile features       
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: F:/2023/code/cmake/hello_cmake_project/build
[ 12%] Building CXX object src/human/CMakeFiles/human.dir/person.cpp.obj
[ 25%] Linking CXX shared library F:/2023/code/cmake/hello_cmake_project/dist/libhuman.dll
[ 25%] Built target human
[ 37%] Building CXX object src/main/CMakeFiles/hello_cmake_project.dir/main.cpp.obj
[ 50%] Linking CXX executable F:/2023/code/cmake/hello_cmake_project/dist/hello_cmake_project.exe
[ 50%] Built target hello_cmake_project
[ 62%] Building CXX object src/human/CMakeFiles/human_static.dir/person.cpp.obj
[ 75%] Linking CXX static library F:/2023/code/cmake/hello_cmake_project/dist/libhuman.a
[ 75%] Built target human_static
[ 87%] Building CXX object test/CMakeFiles/hello_cmake_test.dir/hellocmaketest.cpp.obj
[100%] Linking CXX executable F:/2023/code/cmake/hello_cmake_project/dist/hello_cmake_test.exe
[100%] Built target hello_cmake_test

F:\2023\code\cmake\hello_cmake_project>.\dist\hello_cmake_project.exe 
hello world
hello world

F:\2023\code\cmake\hello_cmake_project>.\dist\hello_cmake_test.exe    
[doctest] doctest version is "2.4.9"
[doctest] run with "--help" for options
===============================================================================
[doctest] test cases: 2 | 2 passed | 0 failed | 0 skipped
[doctest] assertions: 2 | 2 passed | 0 failed |
[doctest] Status: SUCCESS!

F:\2023\code\cmake\hello_cmake_project>

使用 python 控制 cmake 构建的生命周期

使用的时候应当是什么样的

使用方式应该是这样:

F:\2023\code\cmake\hello_cmake_project> cm help
build					编译
run						运行
test					测试
doxygen					生成 doxygen 文档

F:\2023\code\cmake\hello_cmake_project> cm build
项目编译中...
项目编译完毕

F:\2023\code\cmake\hello_cmake_project> cm run
启动项目...

hello world
hello world

项目运行结束

F:\2023\code\cmake\hello_cmake_project> cm test
开始测试

[doctest] doctest version is "2.4.9"
[doctest] run with "--help" for options
===============================================================================
[doctest] test cases: 2 | 2 passed | 0 failed | 0 skipped
[doctest] assertions: 2 | 2 passed | 0 failed |
[doctest] Status: SUCCESS!

测试结束

F:\2023\code\cmake\hello_cmake_project> cm doxygen
生成 doxygen 文档

应当有什么功能

除了上述的几个命令行参数之外, 还应该有

  1. 类似git 的 hook 一样, 可以在构建前后或测试前后做一些自定义的动作
  2. 类似 npm init 一样初始化一个项目
  3. 自定义命令别名
  4. 提供 python 源码而不是二进制

有哪些功能没有做

构建之前的检查
通常来说, 构建工具都有检查功能, 比如校验构建脚本是否正确, 但是目前没啥必要

依赖管理
比如和 vcpkg 或者 Conan 的整合. 这部分做起来难度太高

和 ide 的集成
比如写个 vscode 或者 vs 的插件, 鼠标点一点就能直接构建, 测试, 生成文档, 发布等等. 这个难度也不小.
参考: VSCode 插件开发教程

下一篇:
cmake 04 使用 python 管理 cmake 工程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/175349.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Pandas-DataFrame基础知识点总结

1、DataFrame的创建 DataFrame是一种表格型数据结构&#xff0c;它含有一组有序的列&#xff0c;每列可以是不同的值。DataFrame既有行索引&#xff0c;也有列索引&#xff0c;它可以看作是由Series组成的字典&#xff0c;不过这些Series公用一个索引。 DataFrame的创建有多种…

JavaEE-多线程初阶4

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;JavaEE &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录多线程案例阻塞队列阻塞队列是什么生产者消费者模型标准库中的阻塞队列阻塞队列实现定时器定时器是什么标准库中的定时器实现定…

(第107篇)C规范编辑笔记(十三)

往期文章&#xff1a; C规范编辑笔记(一) C规范编辑笔记(二) C规范编辑笔记(三) C规范编辑笔记(四) C规范编辑笔记(五) C规范编辑笔记(六) C规范编辑笔记(七) C规范编辑笔记(八) C规范编辑笔记(九) C规则编辑笔记(十) C规范编辑笔记(十一) C规范编辑笔记(十二) 正文&#xff…

行人属性识别研究综述(二)

文章目录6 PAR&#xff08;行人属性识别&#xff09;算法综述6.1全局基于图像的模型6.1.1 ACN (iccvw-2015)6.1.2 DeepSAR and DeepMAR (ACPR-2015) [6]6.1.3 MTCNN (TMM-2015) [7]6.2 基于部件的模型6.2.1 Poselets (ICCV-2011)6.2.2 rad (iccv-2013)6.2.3 PANDA (cvp -2014) …

Java-IO知识详解(一)

分类分类&#xff08;传输&#xff0c;操作&#xff09;IO理解分类 - 从传输方式上字节流字符流字节流和字符流的区别IO理解分类 - 从数据操作上文件(file)数组([])管道操作基本数据类型缓冲操作打印对象序列化反序列化转换装饰者模式分类&#xff08;传输&#xff0c;操作&…

迈百瑞冲刺创业板上市:关联收入占比较高,房健民为加拿大籍

撰稿|汤汤 来源|贝多财经 近日&#xff0c;烟台迈百瑞国际生物医药股份有限公司&#xff08;下称”迈百瑞“&#xff09;在深圳证券交易所提交更新后的招股书&#xff08;申报稿&#xff09;。据贝多财经了解&#xff0c;迈百瑞于2022年9月在递交IPO申请材料&#xff0c;准备…

指定不同版本的pcl

18.04里面安装了两个版本的pcl&#xff0c;一个是安装ros的时候安装的pcl1.8&#xff0c;另一个是安装的源码pcl1.12版本。一直相安无事&#xff0c;今天在我编译lego-loam的时候&#xff0c;突然就冲突了。卡了我两个小时&#xff0c;到处找原因&#xff0c;网上基本上没有相似…

RSD高分卫星数据处理能力提升——日正射处理数千景高分数据集

李国春 通常认为&#xff0c;能够单日处理几百景高分辨率对地观测卫星数据的系统就已经是非常优秀的卫星数据处理系统了。RSD此次优化将其处理能力提升超过了一个数量级&#xff0c;达到了单日正射处理数千景高分辨率卫星数据集的水平。 不仅如此&#xff0c;RSD达到如此高的…

SpringBoot+Vue项目(学生信息管理系统)搭建运行

项目地址&#xff1a;学生信息管理系统 前端部分&#xff08;Vue&#xff09; 首先以管理员身份运行终端 不然运行命令时有些会报错 1.首先下载node.js 2.打开并安装node.js 3.安装完成&#xff0c;打开控制台&#xff0c;输入node -v查看是否安装完成&#xff0c;如果显示…

MongoDB学习笔记【part2】数据库、文档、集合与常用命令

一、MongoDB 概念 Mongo 与 SQL 的术语区别如下&#xff1a; SQL术语/概念MongoDB术语/概念解释/说明databasedatabase数据库tablecollection数据表 – 集合rowdocument记录 – 文档columnfield字段 – 域indexindex索引table joins表连接&#xff0c;MongoDB不支持primary k…

分享121个PHP源码,总有一款适合您

PHP源码 分享121个PHP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 121个PHP源码下载链接&#xff1a;https://pan.baidu.com/s/1--fhiwI0gwB1a2ouivPw7g?pwdd61x 提取码&#x…

监控指标解读和JVM 分析调优

1、中间件指标  当前正在运行的线程数不能超过设定的最大值。一般情况下系统性能较好的情况下&#xff0c;线 程数最小值设置 50 和最大值设置 200 比较合适。  当前运行的 JDBC 连接数不能超过设定的最大值。一般情况下系统性能较好的情况下&#xff0c; JDBC 最小值设置 …

Transformers学习笔记4

Tokenizernlp任务的输入都是raw text&#xff0c;model的输入需要是inputs id&#xff0c;所以tokenzier将句子转换成inputs id&#xff0c;怎么转换呢&#xff0c;有3种方式&#xff1a;word-basedsplit the text&#xff1a;按照空格来区分按照标点来区分我们会得到一个非常大…

Element-UI的dialog对话组件内的tinymce弹窗被遮挡的解决办法及其它相关注意事项

问题一&#xff1a;tinymce的弹窗被遮挡 问题截图 解决办法 修改层级 注意要写在 <style></style> 中&#xff0c;我当时没注意&#xff0c;写在了 <style scoped></style> 中&#xff0c;死活没反应。 <style> /* 在el-dialog中tinymce z-ind…

C进阶_指针和数组试题解析

农历新年即将到来&#xff0c;我在这里给大家拜年了&#xff01;祝大家新的一年心想事成&#xff0c;皆得所愿。新的一年&#xff0c;新的征程&#xff0c;愿各位继续怀揣梦想和远方&#xff0c;奔赴每一场山海。我们一起砥砺前行&#xff0c;“卯定乾坤”&#xff01; 老老少…

Spring Boot操作数据库学习之整合JDBC

文章目录一 Spring Data简介二 Spring Boot集成JDBC2.1 项目创建步骤2.2 测试的SQL脚本2.3 编写yaml配置文件连接数据库2.4 IDEA连接数据库步骤【非必要的步骤】2.5 测试2.6 运行结果2.7 对运行结果的探究2.8 遇到的错误2.8.1 问题1&#xff1a;jdk编译版本2.8.2 解决方法2.8.3…

低成本搭建一台 Unraid 家庭存储服务器:中篇

虎年最后一篇文章&#xff0c;接着上一篇内容&#xff0c;聊聊如何提升硬件的易用性问题。 写在前面 如果你的诉求非常简单、明确&#xff0c;不需要界面&#xff0c;上一篇内容中的 Ubuntu Server 应该已经能够完成你的诉求了。 但是&#xff0c;如果你和我一样&#xff0c…

【Java数据结构与算法】day4-稀疏数组和队列(环形队列)

✅作者简介&#xff1a;热爱Java后端开发的一名学习者&#xff0c;大家可以跟我一起讨论各种问题喔。 &#x1f34e;个人主页&#xff1a;Hhzzy99 &#x1f34a;个人信条&#xff1a;坚持就是胜利&#xff01; &#x1f49e;当前专栏&#xff1a;Java数据结构与算法 &#x1f9…

第五届字节跳动青训营 前端进阶学习笔记(七)HTTP协议入门

文章目录前言HTTP协议概述1.输入网址到页面加载完成中间发生了什么2.HTTP协议3.HTTP协议的发展历程4.HTTP报文结构&#xff08;1&#xff09;HTTP请求报文&#xff08;2&#xff09;HTTP响应报文5.请求方法&#xff08;1&#xff09;安全的方法&#xff08;2&#xff09;幂等6.…

表单标签的学习

表单标签的学习 textarea textarea标签来表示多行文本框&#xff0c;又叫做文本域。与其它 标签不同&#xff0c; textarea标签是单闭合标签&#xff0c;它包含起始标签和结束标签&#xff0c;文本内容需要写在两个标签中间。 input input type“text” 表示文本框 &#xff…