blog icon indicating copy to clipboard operation
blog copied to clipboard

C/C++ 工程化

Open WangShuXian6 opened this issue 1 year ago • 12 comments

C/C++ 工程化

C++的工程化指的是如何组织、构建和维护大型的C++项目。它涉及到代码组织、构建系统、自动化测试、版本控制等多个方面。以下是一些建议和步骤,帮助你进行C++的工程化管理:

  1. 代码组织

    • 目录结构:为源文件(.cpp)、头文件(.h/.hpp)设定统一的目录,如src/include/。还可以按功能模块进一步划分子目录。
    • 模块化:将功能相似的代码放在同一个模块或命名空间中,减少不必要的耦合。
  2. 版本控制

    • 使用Git、SVN等版本控制工具来管理项目代码。
    • 为项目设定明确的版本和分支策略。
  3. 构建系统

    • 使用像CMake、Makefile、Bazel等工具来定义和管理构建流程。
    • 设定目标输出,如动态库、静态库、可执行文件等。
    • 确保跨平台兼容性,如Linux、Windows、Mac等。
  4. 依赖管理

    • 使用如vcpkg、conan等包管理工具来管理第三方库和依赖。
    • 尽量确保依赖的版本稳定,避免版本冲突。
  5. 自动化测试

    • 使用单元测试框架,如Google Test、Catch2等,编写单元测试。
    • 使用CI/CD工具,如Jenkins、Travis CI、GitHub Actions等,进行持续集成和自动化测试。
    • 考虑代码覆盖率,并使用工具如gcov、lcov等进行覆盖率分析。
  6. 代码质量检查

    • 使用代码格式化工具,如clang-format,确保代码风格统一。
    • 使用静态代码分析工具,如clang-tidy、cppcheck,检查代码质量和潜在问题。
  7. 文档

    • 使用Doxygen、Sphinx等工具生成代码文档。
    • 编写项目的README、设计文档、API说明等。
  8. 日志与调试

    • 使用日志库,如spdlog、log4cpp,记录关键的运行信息。
    • 使用调试和性能分析工具,如gdb、valgrind、perf等。
  9. 代码审查

    • 使用像Gerrit、Phabricator或GitHub的Pull Request等工具和流程进行代码审查。
  10. 发布与部署

  • 设定版本号规则,如语义化版本。
  • 使用Docker、安装脚本等方式,简化部署和分发过程。

总的来说,C++的工程化管理是一个综合性的过程,需要不断地迭代和完善,确保项目的高效、稳定和可维护。

WangShuXian6 avatar Sep 24 '23 09:09 WangShuXian6

C 工程化软件包

编辑器:VSCode

Linux 上需要的软件包[Ubuntu]

sudo apt-get update
sudo apt-get upgrade

# Mandatory
sudo apt-get install gcc g++ gdb
sudo apt-get install make cmake
sudo apt-get install git
sudo apt-get install doxygen
sudo apt-get install python3 python3-pip

# Optional
sudo apt-get install lcov gcovr
sudo apt-get install ccache
sudo apt-get install cppcheck
sudo apt-get install llvm clang-format clang-tidy
sudo apt-get install curl zip unzip tar

mac 上需要的软件包

Compiler Setup:

XCode: https://www.ics.uci.edu/~pattis/common/handouts/macclion/clang.html

lldb --version
clang --version
clang++ --version

Brew:

https://brew.sh/index_de

Brew:

brew install git
brew install make
brew install cmake
brew install doxygen
brew install lcov
brew install gcovr
brew install ccache

Windows

通过WSL子系统安装Linux版本包 https://github.com/WangShuXian6/blog/issues/125#issuecomment-1732532787 或安装Windows版本包 https://github.com/WangShuXian6/blog/issues/168#issue-1875128134

CMake

CMake https://github.com/WangShuXian6/blog/issues/171#issuecomment-1732571978 make https://www.gnu.org/software/make/ windows 版本 make https://www.gnu.org/software/make/ 配置make环境变量 右键我的电脑->属性->高级系统设置->高级->环境变量->系统变量->path 然后在path中新建环境变量,目录定位到make for windows安装目录即可 C:\Program Files (x86)\GnuWin32\bin image 重启终端和编辑器 make -v

doxygen

doxygen >https://www.doxygen.nl/download.html

右键我的电脑->属性->高级系统设置->高级->环境变量->系统变量->path 然后在path中新建环境变量 C:\Program Files\doxygen\bin

doxygen -v

Graphviz

https://graphviz.org/ Graphviz 是开源的图形可视化软件 https://graphviz.org/download/ ubuntu

sudo apt install graphviz

配置graphviz环境变量 右键我的电脑->属性->高级系统设置->高级->环境变量->系统变量->path 然后在path中新建环境变量,目录定位到graphviz for windows安装目录即可 C:\Program Files\Graphviz\bin image 测试

dot -v

删除重建命令

linux

rm -rf build
mkdir build

windows cmd

rmdir /s /q build
mkdir build

PowerShell

Remove-Item -Recurse -Force build
New-Item -Type Directory -Name build

Conan

https://conan.io/ 需要python3.5以上

conan -v
# 创建默认配置文件
conan profile detect

vcpkg

https://github.com/microsoft/vcpkg https://vcpkg.io/en/ https://github.com/microsoft/vcpkg/blob/master/README_zh_CN.md

安装 建议在项目的\external目录下安装vcpkg 因为vcpk路径需要硬编码到项目中,如果在系统全局安装,需要频繁更改该路径

cd external
git clone https://github.com/microsoft/vcpkg
.\vcpkg\bootstrap-vcpkg.bat
cd vcpkg
# 查看本次vcpkg的git log
git log

新建 \vcpkg.json 将git log值赋予\vcpkg.jsonbuiltin-baseline

\CMakeLists.txt

include(${CMAKE_SOURCE_DIR}/external/vcpkg/scripts/buildsystems/vcpkg.cmake)
find_package(nlohmann_json REQUIRED)

编译构建

WangShuXian6 avatar Sep 24 '23 09:09 WangShuXian6

代码组织

Clang-Format

Cmake-Format

WangShuXian6 avatar Sep 24 '23 13:09 WangShuXian6

版本控制

WangShuXian6 avatar Sep 24 '23 13:09 WangShuXian6

构建系统

CMake

https://cmake.org/download/ https://github.com/Modern-CMake-CN/Modern-CMake-zh_CN Modern CMake 简体中文版

WangShuXian6 avatar Sep 24 '23 13:09 WangShuXian6

依赖管理

git sub

Fetch Content

CPM

Conan

vcpkg

WangShuXian6 avatar Sep 24 '23 13:09 WangShuXian6

自动化测试

WangShuXian6 avatar Sep 24 '23 13:09 WangShuXian6

代码质量检查

WangShuXian6 avatar Sep 24 '23 13:09 WangShuXian6

文档

可视化

详解 使用 Graphviz 分析项目的依赖关系 导出依赖图

编写\Makefile

dependency:
	cd build && cmake .. --graphviz=graph.dot && dot -Tpng graph.dot -o graphImage.png

创建目录 build [否则报错] 生成依赖图 [项目根目录下执行]

make dependency

依赖图位置为 \build\graphImage.png image

这个 cmake 命令和后续的命令组合是用来生成和可视化一个 CMake 项目的依赖关系的。

具体解释如下:

  1. cd build: 这个命令是将当前工作目录切换到 build 目录。通常在 CMake 项目中,我们使用一个单独的目录(例如 build)来生成构建文件,以保持源代码目录的整洁。

  2. cmake ..: 这个命令是调用 cmake 并指向父目录(..),也就是项目的源代码目录,来生成构建文件。

  3. --graphviz=graph.dot: 这是一个 cmake 的选项,用于生成一个 Graphviz 格式的文件(在这里命名为 graph.dot),该文件描述了项目的依赖关系。这是一个非常有用的功能,特别是当项目很大或有复杂的依赖关系时。

  4. dot -Tpng graph.dot -o graphImage.png: 这个命令使用 Graphviz 的 dot 工具来将前面生成的 graph.dot 文件转换成 PNG 图像格式,并保存为 graphImage.png。这样,你可以直观地查看和理解项目的依赖关系。

总的来说,这个命令组合的目的是为了生成和可视化 CMake 项目的依赖关系图。这对于理解大型项目的结构和依赖关系非常有帮助。

--graphviz=graph.dot 是一个专门的 CMake 命令行选项,用于生成项目的依赖关系图。这个选项让 CMake 产生一个 Graphviz 格式的文件,该文件描述了整个项目中的目标(如库或可执行文件)之间的依赖关系。

详细解释如下:

  • --graphviz: 这是指示 CMake 生成 Graphviz 文件的命令行选项。

  • graph.dot: 这是生成的 Graphviz 文件的名称。在这个例子中,文件名被设置为 graph.dot,但你也可以选择其他名称。

这个功能特别有用,因为它可以帮助开发者可视化地了解项目中各个目标之间的依赖关系,特别是在大型项目中,这样的依赖关系图可以更直观地展示复杂的依赖结构。

当你运行带有 --graphviz=graph.dot 选项的 cmake 命令后,CMake 会在当前工作目录下生成一个名为 graph.dot 的文件。这个文件是纯文本格式,使用 Graphviz 的 DOT 语言描述了项目的依赖关系。为了将这个 .dot 文件转换为图形,你可以使用 Graphviz 的 dot 工具,如你之前提到的那样,将其转换为 PNG、SVG 等格式。

--graphviz 是 CMake 自带的一个命令行选项。使用这个选项,CMake 可以生成一个 Graphviz 格式的 .dot 文件,描述项目中的目标(例如库和可执行文件)之间的依赖关系。这个功能允许开发者在复杂的项目中快速和直观地了解各个组件之间的依赖结构。

WangShuXian6 avatar Sep 24 '23 13:09 WangShuXian6

日志与调试

WangShuXian6 avatar Sep 24 '23 13:09 WangShuXian6

代码审查

Clang-Tidy

WangShuXian6 avatar Sep 24 '23 13:09 WangShuXian6

发布与部署

WangShuXian6 avatar Sep 24 '23 13:09 WangShuXian6

CMake 构建工程化

CMake 构建 单文件

查看CMake版本 cmake --version 配置 VSCode 编译器 例如 g++ ,CMake 不包含编译器 新建 main.cpp

#include <iostream>

int main()
{
    std::cout << "hello world\n";

    return 0;
}

新建文件夹 build 新建 CMakeLists.txt

# CMake 最低版本
cmake_minimum_required(VERSION 3.22) 

#
project(
    CppProjectTemplate # 项目名
    VERSION 1.0.0 # 项目版本
    LANGUAGES C CXX # 项目包含 C,C++文件
)

add_executable(
    Executable # 生成的可执行文件名
    main.cpp # 要编译的文件
)

将构建文件写入 build 目录

cd build/
cmake ..

在 build 目录下 构建可执行文件

cmake --build .

生成可执行文件 build\Debug\Executable.exe

执行

.\Debug\Executable

返回 hello world


CMake 构建 多文件 包含库

新建文件夹 build

my_lib.h

//  确保头文件在一个编译单元中只被包含一次
#pragma once

void print_hello_world();

my_lib.cpp

#include <iostream>
#include "my_lib.h"

void print_hello_world()
{
    std::cout << "hello world\n";
}

主文件 main.cpp

#include <iostream>
#include "my_lib.h"

void print_hello_world()
{
    std::cout << "hello world\n";
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.16)

project(CppProjectTemplate VERSION 1.0.0 LANGUAGES C CXX)

# 构建库文件
add_library(Library #库名字
STATIC
my_lib.cpp #库文件
)

# 构建可执行文件
add_executable(Executable main.cpp)

# 将库文件 Library 链接到可执行文件 Executable
target_link_libraries(
    Executable PUBLIC Library
)

写入构建文件

cd build/
cmake ..

构建库和可执行文件,并链接两者

cmake --build .

这将生成库文件和可执行文件 build\Debug\Library.lib build\Debug\Executable.exe

单独构建库文件

cmake --build . --target Library

单独构建可执行文件[这将自动构建可执行文件所依赖的库]

cmake --build . --target Executable

构建多个项目

\CMakeLists.txt

add_library(Library STATIC my_lib.cpp)
target_include_directories(Library PUBLIC "./")

\src\CMakeLists.txt

add_subdirectory(my_lib)

\src\my_lib\CMakeLists.txt

add_library(Library STATIC my_lib.cpp)
# 包含当前目录文件
target_include_directories(Library PUBLIC "./")

src\my_lib\my_lib.h

#pragma once

void print_hello_world();

\src\my_lib\my_lib.cpp

#include <iostream>

#include "my_lib.h"

void print_hello_world()
{
    std::cout << "Hello World!\n";
}

\app\CMakeLists.txt

add_executable(Executable main.cpp)
# 链接库
target_link_libraries(Executable PUBLIC Library)

\app\main.cpp

#include <iostream>

#include "my_lib.h"

int main()
{
    print_hello_world();

    return 0;
}

\build

正常编译即可

cd build/
cmake ..
cmake --build .

执行

app\Debug\Executable.exe 

CMake 变量,选项开关

可以在根目录下的最外一层\CMakeLists.txt中添加变量和选项,内层CMakeLists.txt都可以引用变量 \CMakeLists.txt

cmake_minimum_required(VERSION 3.16)

project(CppProjectTemplate VERSION 1.0.0 LANGUAGES C CXX)

# C++版本为17
set(CMAKE_CXX_STANDARD          17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 关闭自定义扩展
set(CMAKE_CXX_EXTENSIONS        OFF)

# 变量 设置变量 LIBRARY_NAME 值为 Library,自动识别为 字符串格式 “Library”
set(LIBRARY_NAME Library)
set(EXECUTABLE_NAME Executable)

# 选项 COMPILE_EXECUTABLE 选项为 关闭 ,中间为描述
option(COMPILE_EXECUTABLE "Whether to compile the executable" OFF)

# add_subdirectory 要遵从依赖顺序 被依赖项目需要在前面
add_subdirectory(src)
# 如果开启,则构建可执行文件 可使用 else()
if (COMPILE_EXECUTABLE)
    add_subdirectory(app)
endif()

编译时传递变量 COMPILE_EXECUTABLE=ON 变量需加上前缀D

cd build/
cmake .. -DCOMPILE_EXECUTABLE=ON

添加一个编译前脚本Makefile文件来清空build文件夹 \Makefile

prepare:
	rm -rf build
	mkdir build

执行该脚本[windows下暂不可用]

make prepare

优化 CMakeLists

CMake 历史悠久,老版本的教程不再适应现代语言的工程化 绝大部分教程不应使用[例如通过脚本扫描所有文件以编译]

集合 源文件cpp和头文件h

set(LIBRARY_SOURCES
    "my_lib.cc"
    "my_lib2.cc")
set(LIBRARY_HEADERS
    "my_lib.h"
    "my_lib2.h")

add_library(${LIBRARY_NAME} STATIC
    ${LIBRARY_SOURCES}
    ${LIBRARY_HEADERS})
target_include_directories(${LIBRARY_NAME} PUBLIC
    "./"
    "${CMAKE_BINARY_DIR}/configured_files/include")

set(EXE_SOURCES
    "main.cc")

add_executable(${EXECUTABLE_NAME} ${EXE_SOURCES})
target_link_libraries(${EXECUTABLE_NAME} PUBLIC ${LIBRARY_NAME})


仅构建指定目标

在具由多个项目和目标的项目中,只编译指定目标,例如特定库 库名 Library 已定义

cmake --build . --target Library

使用 Graphviz 分析项目的依赖关系 导出依赖图

编写\Makefile

dependency:
	cd build && cmake .. --graphviz=graph.dot && dot -Tpng graph.dot -o graphImage.png

创建目录 build [否则报错] 生成依赖图 [项目根目录下执行]

make dependency

依赖图位置为 \build\graphImage.png image


Fetch Content 第三方库

第三方库需要支持cmake,即包含 CMakeLists.txt文件 FetchContent 是 CMake 提供的一个模块,允许在构建过程中从各种来源下载、构建和可选地安装内容。它尤其对于依赖管理和项目集成非常有用。

定义并下载第三方库 \CMakeLists.txt

include(FetchContent)

# 定义第三方库
FetchContent_Declare(
    # 库名
    nlohmann_json
    # 网址
    GIT_REPOSITORY https://github.com/nlohmann/json
    # 版本
    GIT_TAG v3.11.2
    # 关闭循环深克隆
    GIT_SHALLOW TRUE)

# 下载到本地
FetchContent_MakeAvailable(nlohmann_json)

FetchContent 模块会将内容(例如,从Git仓库下载的项目)放置在构建树的一个特定子目录中。默认情况下,这个目录是在你的构建目录(通常是当前的CMake构建目录)下的 _deps 子目录

在app中使用第三方库 \app\CMakeLists.txt

set(EXE_SOURCES
    "main.cpp")

add_executable(${EXECUTABLE_NAME} ${EXE_SOURCES})
target_link_libraries(${EXECUTABLE_NAME} PUBLIC
    ${LIBRARY_NAME}
    nlohmann_json)

\app\main.cpp

#include <iostream>

#include <nlohmann/json.hpp>

#include "config.hpp"
#include "my_lib.h"

int main()
{
    std::cout << project_name << '\n';
    std::cout << project_version << '\n';

    std::cout << "JSON:" << NLOHMANN_JSON_VERSION_MAJOR << "."
              << NLOHMANN_JSON_VERSION_MINOR << "."
              << NLOHMANN_JSON_VERSION_PATCH << "\n";

    print_hello_world();

    return 0;
}

库中使用第三方 \src\my_lib\CMakeLists.txt

set(LIBRARY_SOURCES
    "my_lib.cc")
set(LIBRARY_HEADERS
    "my_lib.h")
set(LIBRARY_INCLUDES
    "./"
    "${CMAKE_BINARY_DIR}/configured_files/include")

add_library(${LIBRARY_NAME} STATIC
    ${LIBRARY_SOURCES}
    ${LIBRARY_HEADERS})
target_include_directories(${LIBRARY_NAME} PUBLIC
    ${LIBRARY_INCLUDES})
target_link_libraries(${LIBRARY_NAME} PUBLIC
    nlohmann_json::nlohmann_json
    fmt::fmt
    spdlog::spdlog
    cxxopts::cxxopts)

\src\my_lib\my_lib.cpp

#include <iostream>

#include <nlohmann/json.hpp>

#include "my_lib.h"

void print_hello_world()
{
    std::cout << "Hello World!\n";

    std::cout << "JSON Lib Version:" << NLOHMANN_JSON_VERSION_MAJOR << "."
              << NLOHMANN_JSON_VERSION_MINOR << "."
              << NLOHMANN_JSON_VERSION_PATCH << "\n";
}


使用 doxygen 生成文档

新建文档目录 docs \docs\Doxyfile 定义文档信息


# Configuration for Doxygen for use with CMake

# Only options that deviate from the default are included

# To create a new Doxyfile containing all available options, call `doxygen -g`

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

# Project related configuration options

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

DOXYFILE_ENCODING       = UTF-8
PROJECT_NAME            = "C++ Project Template"
PROJECT_NUMBER          = 1.0
PROJECT_BRIEF           =
PROJECT_LOGO            =
OUTPUT_DIRECTORY        = ./
OUTPUT_LANGUAGE         = English
MARKDOWN_SUPPORT        = YES

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

# Build related configuration options

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

EXTRACT_ALL             = YES
RECURSIVE               = YES
GENERATE_HTML           = YES
GENERATE_LATEX          = NO

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

# Configuration options related to the input files

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

INPUT                  =    ../src \
INPUT                       ../include \
INPUT                       ../app
INPUT_ENCODING         = UTF-8
FILE_PATTERNS          = *.c \
                         *.cc \
                         *.cpp \
                         *.c++ \
                         *.h \
                         *.hpp \
                         *.h++ \
                         *.md \
                         *.dox \
                         *.doc \
                         *.txt

新建 cmake 目录存放自定义函数 \cmake\Docs.cmake

find_package(Doxygen)

# CMAKE_SOURCE_DIR 代表项目根目录

if (DOXYGEN_FOUND)
    add_custom_target(
        docs
        ${DOXYGEN_EXECUTABLE}
        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs
    )
endif()

添加注释 app\main.cpp

#include <iostream>

/**
 * @brief Prints out hello world .
 *
 */
int main()
{
    std::cout << "Hello World!\n";
    return 0;
}

编译 构建

cd build/
cmake ..
cmake --build .

生成文档

cd docs
doxygen

在 VSCode 底部栏快捷运行 image 点击生成【首次需要配置编译环境 可选择 gcc 等】 点击 all,输入 docs 命令


使用 CPM 管理第三方库

https://github.com/cpm-cmake/CPM.cmake

下载 https://github.com/cpm-cmake/CPM.cmake/releases 中的 CPM.cmake 文件 放入项目 cmake 目录下 \CMakeLists.txt 中添加

include(CPM)
cpmaddpackage("gh:nlohmann/json#v3.11.2")

此处等同 https://github.com/nlohmann/json 库的版本 v3.11.2

在app中使用第三方库 \app\CMakeLists.txt

set(EXE_SOURCES
    "main.cpp")

add_executable(${EXECUTABLE_NAME} ${EXE_SOURCES})
target_link_libraries(${EXECUTABLE_NAME} PUBLIC
    ${LIBRARY_NAME}
    nlohmann_json)

使用 Conan 管理库

项目根目录下新建 \conanfile.py

from conan import ConanFile
from conan.tools.cmake import CMakeToolchain


class CompressorRecipe(ConanFile):
    settings = "os", "compiler", "build_type", "arch"
    generators = "CMakeDeps"

    def requirements(self):
       // 依赖添加处
        self.requires("nlohmann_json/3.11.2")

    def generate(self):
        tc = CMakeToolchain(self)
        tc.user_presets_path = False
        tc.generate()

\CMakeLists.txt

# CMAKE_BINARY_DIR 表示编译目录 此处即 build
include(${CMAKE_BINARY_DIR}/conan_toolchain.cmake)
find_package(nlohmann_json REQUIRED)

\Makefile 如果Conan没有预编译文件,则在本地编译 --build missing

# 调试版本
conan_d:
	rm -rf build
	mkdir build
	cd build && conan install .. -s build_type=Debug -s compiler.cppstd=17 --output-folder=. --build missing

# 发布版本
conan_r:
	rm -rf build
	mkdir build
	cd build && conan install .. -s build_type=Release -s compiler.cppstd=17 --output-folder=. --build missing

先下载依赖 make 命令,在项目根目录执行

make conan_d

编译 构建

cd build/
cmake ..
cmake --build .

使用 vcpkg 管理库

https://github.com/microsoft/vcpkg https://vcpkg.io/en/ https://github.com/microsoft/vcpkg/blob/master/README_zh_CN.md

安装 建议在项目的\external目录下安装vcpkg 因为vcpk路径需要硬编码到项目中,如果在系统全局安装,需要频繁更改该路径

cd external
git clone https://github.com/microsoft/vcpkg
.\vcpkg\bootstrap-vcpkg.bat
cd vcpkg
# 查看本次vcpkg的git log
git log
08a6cdd73b8dd750778fa3d84cf2cf844e24530f

新建 \vcpkg.json

{
    "name": "cpptemplateproject",
    "version-string": "1.0.0",
    "dependencies": [
        {
            "name": "cxxopts",
            "version>=": "3.1.1"
        }
    ],
    "overrides": [
        {
            "name": "catch2",
            "version": "2.13.9"
        },
        {
            "name": "catch2",
            "version>=": "2.13.9"
        }
    ],
    "builtin-baseline": "08a6cdd73b8dd750778fa3d84cf2cf844e24530f"
}

将最新的 git log值赋予\vcpkg.jsonbuiltin-baseline dependencies只会下载最新库 overrides才可以指定精确版本

\CMakeLists.txt

include(${CMAKE_SOURCE_DIR}/external/vcpkg/scripts/buildsystems/vcpkg.cmake)
find_package(nlohmann_json REQUIRED)

编译构建

cd build/
cmake ..
cmake --build .

cmake ..编译时,将会将vcpkg包下载到external\vcpkg\packages\cxxopts_x64-windows等目录中供后续构建 cmake ..编译后,编辑器将可以正确解析新的库

示例

vcpkg.json

{
    "name": "cpptemplateproject",
    "version-string": "1.0.0",
    "dependencies": [
        {
            "name": "cxxopts",
            "version>=": "3.1.1"
        }
    ],
    "overrides": [

    ],
    "builtin-baseline": "40619a55c3e76dc4005c8d1b7395071471bb8b96"
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.16)

project(CppProjectTemplate VERSION 1.0.0 LANGUAGES C CXX)

set(CMAKE_CXX_STANDARD          17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS        ON)

set(EXECUTABLE_NAME Executable)

# 硬编码 vdpkg 路径
include(${CMAKE_SOURCE_DIR}/external/vcpkg/scripts/buildsystems/vcpkg.cmake)
# 手动找寻包
find_package(cxxopts REQUIRED)

# CMake 载入并执行当前项目目录下的 cmake 子目录中的 Docs.cmake 文件

add_subdirectory(app)

external\vcpkg build

app\CMakeLists.txt

set(EXE_SOURCES
    "main.cpp")

add_executable(${EXECUTABLE_NAME} ${EXE_SOURCES})

# 链接包
target_link_libraries(
    ${EXECUTABLE_NAME}
        cxxopts::cxxopts)

app\main.cpp

#include <iostream>
#include <cxxopts.hpp>
/**
 * @brief Prints out hello world .
 *
 */
int main()
{
    std::cout << "Hello World!\n";

    std::cout << "CXXOPTS:" << CXXOPTS__VERSION_MAJOR << "."
              << CXXOPTS__VERSION_MINOR << "." << CXXOPTS__VERSION_PATCH
              << "\n";
    return 0;
}

cd build/
cmake ..
cmake --build .
app\Debug\Executable.exe

显示

Hello World!
CXXOPTS:3.1.1

WangShuXian6 avatar Sep 24 '23 14:09 WangShuXian6