Hello, world
创建一个 CMakeLists.txt
,写入:
1 2 3 4 5 6 7 8 9 10 11 12
| cmake_minimum_required(VERSION 3.10)
project( hello VERSION 0.0.1 LANGUAGES C CXX )
add_executable( main main.cpp )
|
这里省略了 main.cpp
程序。
按照惯例,创建一个 build
文件夹,切换到该路径下,cmake ..
。基于 Visual Studio 的环境,会自动生成 .sln
工程。项目名称就是 project
中指定的 hello
。
拆分文件夹
现在把 main.cpp
放到一个新建的 src
目录中,并且新建一个 include
作为头文件的文件夹,并在 src
目录中新建一个 CMakeLists.txt
,写入:
1 2 3 4
| add_executable( main main.cpp )
|
最外层的(原先的)的 CMakeLists.txt
加入:
1 2
| include_directories(include) add_subdirectory(src)
|
GoogleTest
现在引入 GoogleTest 作为例子。目前 GoogleTest 1.15.2 要求 C++ 标准不低于 C++14,于是在项目层级的 CMakeLists.txt
中设定该条件(这里设定是 C++17):
1 2 3
| set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
给用户一个选项是否开启单元测试:
1 2
| option(ENABLE_UNIT_TESTS "Enable unit tests" ON) message(STATUS "Enable testing: ${ENABLE_UNIT_TESTS}")
|
对这个条件进行判断,再进行后续操作:
1 2 3
| if (ENABLE_UNIT_TESTS) endif()
|
导入 FetchContent
模块,并指定 GoogleTest 的地址,并导入:
1 2 3 4 5 6 7 8 9
| if (ENABLE_UNIT_TESTS) include(FetchContent) FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG v1.15.2 ) FetchContent_MakeAvailable(googletest) endif()
|
写一个最简单的测试库(注意对应的文件):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| #pragma once
#include <vector>
int sum_integers(const std::vector<int> integers);
#include "sum_integers.hpp"
int sum_integers(const std::vector<int> integers) { auto sum = 0; for (auto i : integers) { sum += i; } return sum; }
#include <iostream> #include <string> #include <vector>
#include "sum_integers.hpp"
int main(int argc, char *argv[]) { std::vector<int> integers; for (auto i = 1; i < argc; i++) { integers.push_back(std::stoi(argv[i])); }
auto sum = sum_integers(integers);
std::cout << sum << std::endl; return 0; }
|
将 src
中的 CMakeLists.txt
改成:
1 2 3 4 5 6 7
| add_library(sum_integers sum_integers.cpp) SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/build/bin)
add_executable(sum_up main.cpp)
target_link_libraries(sum_up sum_integers)
|
写一个测试
新建一个 tests
文件夹,用于编写存放单元测试。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include "sum_integers.hpp" #include "gtest/gtest.h" #include <vector>
TEST(example, sum_zero) { auto integers = {1, -1, 2, -2, 3, -3}; auto result = sum_integers(integers); ASSERT_EQ(result, 0); }
TEST(example, sum_five) { auto integers = {1, 2, 3, 4, 5}; auto result = sum_integers(integers); ASSERT_EQ(result, 15); }
|
为了更加清晰的划分,在 tests
目录中添加 CMakeLists.txt
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| if (ENABLE_UNIT_TESTS) include(FetchContent) FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG v1.15.2 ) FetchContent_MakeAvailable(googletest)
add_executable(cpp_test test.cpp)
target_link_libraries(cpp_test PRIVATE sum_integers gtest_main )
add_test(NAME cpp_test COMMAND cpp_test) endif()
|
顶层的 CMakeLists.txt
可以更宏观的描述整个项目:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| cmake_minimum_required(VERSION 3.15) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON)
project(HelloWorld) enable_testing()
option(ENABLE_UNIT_TESTS "Enable unit tests" ON) message(STATUS "Enable testing: ${ENABLE_UNIT_TESTS}")
include_directories(include) add_subdirectory(src)
if (ENABLE_UNIT_TESTS) add_subdirectory(tests) endif()
|
可以使用 ctest
运行并收集测试报告:
1 2 3 4 5 6 7 8
| > ctest -C Release Test project E:/vs/project-build/build Start 1: cpp_test 1/1 Test #1: cpp_test ......................... Passed 0.03 sec
100% tests passed, 0 tests failed out of 1
Total Test time (real) = 0.04 sec
|
常用的命令
add_library
定义一个库目标,可以是静态库、共享库或模块库。
1
| add_library(MyLibrary STATIC mylib.cpp)
|
target_link_libraries
为目标添加链接库。
1
| target_link_libraries(MyExecutable PRIVATE MyLibrary)
|
add_custom_command
添加定制命令,例如用于复制:
1 2 3 4 5 6
| add_custom_command(TARGET toyfun_grpc POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_FILE:toyfun_grpc>" "${TARGET_DIR}" COMMENT "Copying toyfun_grpc.dll to ${TARGET_DIR}" )
|
Vcpkg
Vcpkg 是由 Microsoft 和 C++ 社区维护的免费开源 C/C++ 包管理器,可在 Windows、macOS 和 Linux 上运行。它是核心的 C++ 工具,使用 C++ 和 CMake 脚本编写。它旨在解决管理 C/C++ 库的独特难题。
Conan
Conan 是一个开源的、跨平台的 C/C++ 包管理器,旨在简化和自动化 C/C++ 项目的依赖管理,并且可以在 Windows、macOS 和 Linux 上运行。Conan 提供了一个灵活且强大的工具集,帮助开发者管理库的构建、打包和分发。
参考资料
- cmake 官方文档
- CMake 与 gtest:自动下载 gtest 与搭建测试驱动环境
- vcpkg 概述
- vcpkg 官网
- Conan 官网