-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathinterview_vcpkg.txt
More file actions
187 lines (173 loc) · 10.7 KB
/
interview_vcpkg.txt
File metadata and controls
187 lines (173 loc) · 10.7 KB
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
Vcpkg 跨平台构建上可能会出现的问题,怎么排查解决:
1.构建命令冲突 - CMake选项覆盖
$ vcpkg install openssl
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
OPENSSL_ROOT_DIR
排查步骤:
查看 vcpkg 的构建命令: $ vcpkg install openssl --debug
检查端口文件中的 CMake 参数: $ cat ports/openssl/portfile.cmake
对比上游 CMakeLists.txt 的选项: $ grep -r "OPENSSL_ROOT_DIR" ports/openssl/
问题原因:上游 CMakeLists.txt 已经设置了 OPENSSL_ROOT_DIR,但 vcpkg 的端口文件中也设置了相同的变量,导致冲突。
解决方案:使用 vcpkg 的 CMake 工具链 -DCMAKE_INSTALL_PREFIX=${CURRENT_PACKAGES_DIR} 或者 使用条件设置,避免覆盖
2.上游误传编译命令 - 编译器标志重复
$ vcpkg install curl
clang: error: argument unused during compilation: '-fPIC' [-Werror,-Wunused-command-line-argument]
clang: error: argument unused during compilation: '-O2' [-Werror,-Wunused-command-line-argument]
排查步骤:
查看详细的构建日志: $ vcpkg install curl --debug 2>&1 | tee build.log
检查编译命令: $ grep "clang.*-fPIC" build.log
检查端口文件的编译选项: $ grep -A 10 -B 10 "vcpkg_configure_make" ports/curl/portfile.cmake
查看上游 configure.ac 或 Makefile.am: $ grep -r "CFLAGS.*-fPIC" ports/curl/src/
问题原因: 上游的 autoconf 脚本已经自动添加了 -fPIC 标志,但vcpkg的端口文件中也显式添加了相同的标志,导致编译器收到重复参数。
解决方案:只在需要时添加编译标志 OPTIONS_RELEASE "CFLAGS=-O2" 或者 检查上游是否已经处理了 PIC
3./wx 将所有的编译器警告提升为编译错误:
核心问题是它打破了编译流程的容忍度,任何一个新的警告都会导致整个构建失败。
出现问题的原因:
第三方库和遗留代码的集成困难: 它所依赖的 第三方库 和 vcpkg 都不是在 /wx 的模式下编译的,这会导致编译失败。
编译器版本升级: 不同版本的编译器可能会引入新的、更严格的警告,一次简单的编译器升级就可能导致项目无法编译。
MSVC 2019 升级到 2022 后,新增了一个警告 C5208(关于未命名的类)。
警告的模糊性: 有些警告可能只是编译器的“过度警惕”,代码逻辑本身是完全正确的。但 wx会强制你修改代码去“讨好”编译器。
可能掩盖真正重要的警告: 因为所有的警告和错误现在都是错误,反而无法辨别真正严重的错误。
阻碍快速迭代: 在开发新功能时,开发者可能会暂时留下一些位置来扩展开发。
通用排查工具和技巧:
启用详细日志: --debug --feature-flags=manifests
检查环境变量: env | grep -iE "(CXX|CC|CFLAGS|CXXFLAGS|LDFLAGS)"
查看工具链文件: cat scripts/buildsystems/vcpkg.cmake
检查依赖关系: vcpkg depend-info package-name
创建最小复现环境
核心工具链文件 scripts/buildsystems/vcpkg.cmake:
将 vcpkg 的包管理集成到 CMake 构建系统中
自动查找和链接 vcpkg 安装的库
处理依赖关系和编译选项
提供跨平台的一致性构建环境
包发现和链接:
1. 设置 vcpkg 安装目录 VCPKG_INSTALLED_DIR
2. 添加包搜索路径 CMAKE_PREFIX_PATH
3. 设置库搜索路径 CMAKE_LIBRARY_PATH
4. 设置头文件搜索路径 CMAKE_INCLUDE_PATH
工具链配置(跨平台工具链设置):
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
if(MSVC) # MSVC 编译器标志
add_compile_options(/MP) # 多处理器编译
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
...
自动依赖管理: vcpkg.cmake 自动处理传递依赖
跨平台一致性: vcpkg.cmake 确保在不同平台上行为一致
Windows (MSVC)
- 自动设置运行时库 (/MT vs /MD)
- 处理 Windows SDK 路径
- 设置字符集 (Unicode)
Linux/macOS (GCC/Clang)
- 自动设置 -fPIC
- 处理 rpath
- 设置 C++标准库
构建类型配置: 自动处理 Debug/Release 配置
Debug 构建:
- 链接 Debug 版本的库
- 启用调试符号
- 优化级别为 -O0
Release 构建:
- 链接 Release 版本的库
- 优化级别为 -O2/-O3
- 去除调试符号
构建命令:
cmake -B build -S . \
-DCMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake \
-DVCPKG_TARGET_TRIPLET=x64-windows
CMake 跨平台构建的底层原理:
整体架构流程: CMakeLists.txt -> CMake 配置阶段 -> 生成器(Generator) -> 平台特定适配层 -> 构建文件生成阶段 -> 原生构建系统文件
配置阶段:
读取你的 CMakeLists.txt 文件
检测你的电脑是什么系统(Windows/Linux/macOS)、有什么编译器、哪些工具可用
分析项目需要哪些库、哪些源文件、它们之间的依赖关系
设置编译参数、链接选项、输出路径等
生成阶段:
根据检测到的环境,生成该平台能理解的构建文件
在 Linux 上生成 Makefile
在 Windows 上生成 .sln 和 .vcxproj 文件
如果装了 Ninja 就生成 build.ninja
设置好各个模块之间的依赖关系,确保按正确顺序构建
为不同平台准备好合适的编译命令和参数
构建阶段:
这时 CMake 的工作已经完成,真正的“施工队”上场:
在 Linux 上: make 施工队拿着 Makefile 手册开始编译
在 Windows 上: MSBuild 施工队拿着 .sln 方案开始工作
用 Ninja 时: ninja 施工队快速并行编译
CMake 的厉害之处在于: 只需要写一次 CMakeLists.txt,CMake 会自动翻译成各平台适配的命令,并且能做到依赖管理智能化。
CMake 的本质: 翻译官、适配器(提供统一接口)、项目经理(管理文件依赖、构建顺序、编译参数)
> vcpkg Issue/PR 自动处理脚本(CPU密集型优先)
这个项目的核心是执行大量本地计算(编译、依赖分析),需要充分利用多核CPU,同时避免重复工作。
使用 【多进程 + redis】 实现:
Redis 在这里主要作为分布式锁和轻量级状态缓存。
分布式锁:
确保同一时间只有一个进程在处理同一个Issue/PR,防止冲突。
使用 SET issue:{number} owner NX EX 600获取锁,处理完后 DEL。
缓存处理结果:
缓存耗时的分析结果(如依赖关系图),避免重复计算。
使用 SETEX,TTL 设置为几小时或一天。
任务队列(可选):
如果需要按优先级处理,可以使用简单的List作为队列。
LPUSH添加任务,BRPOP阻塞获取任务。
速率限制:
遵守GitHub API的速率限制。
使用 INCR 和 EXPIRE 记录单位时间内的API调用次数。
并发模型选择:多进程(ProcessPoolExecutor)
由于是CPU密集型任务(编译、静态分析),使用多进程可以绕过GIL,真正利用多核。
为什么 vcpkg 本身和它的集成方式如此依赖 CMake?
1.CMake 是当今 C++ 项目最主流的构建系统。通过深度集成 CMake,vcpkg 可以覆盖最广泛的用户和项目。
2.find_package的革命性简化:
传统方式:手动查找,非常繁琐且容易出错
find_path(FMT_INCLUDE_DIR fmt/format.h)
find_library(FMT_LIBRARY fmt)
target_include_directories(my_target ${FMT_INCLUDE_DIR})
target_link_libraries(my_target ${FMT_LIBRARY})
使用vcpkg后一行命令搞定:
find_package(fmt CONFIG REQUIRED) # vcpkg 提供了 fmtConfig.cmake 文件
target_link_libraries(my_target PRIVATE fmt::fmt) # 自动包含头文件路径和链接库
3.vcpkg 通过一个 工具链文件 介入 CMake 的构建过程:
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake
将 vcpkg 的包安装目录添加到 CMake 的搜索路径中。
设置编译器标志、查找路径等,确保 vcpkg 安装的库能被正确找到。
处理依赖关系,如果项目 A 依赖库 B,vcpkg 会自动确保 B 对 CMake 可见。
4.跨平台一致性:vcpkg 支持 Windows、Linux、macOS。通过 CMake 的工具链,它可以在所有平台上提供一致的依赖查找和链接体验,无论底层是 VS、GCC 还是 Clang。
其他的 C++ 构建/依赖管理工具介绍:
Meson: 旨在更快、更人性化的构建系统(后端支持 Ninja, Visual Studio)。
Makefile/ Autotools: 元老级构建工具。 Makefile:定义目标和依赖规则。 Autotools(automake/autoconf):用于生成兼容不同 Unix 系统的配置脚本。
Conan: 去中心化的 C/C++ 包管理器,先安装预编译的二进制包到本地缓存,再被构建系统使用,支持任意构建系统(CMake, Makefile, Visual Studio...)。
Azure Pipeline + GitHub Actions:
GitHub PR 提交
↓
触发 Webhook - 向 Azure DevOps 发送事件通知
├─▶ Azure DevOps(多平台编译测试)
│ └─▶ Azure Repos - 代码同步,收到通知(GitHub 上有新 PR),代码会被自动镜像到内部的 Repos 项目中,无缝触发 Pipelines 中定义的复杂构建任务
│ └─▶ Azure Pipelines - 构建核心
│ └─▶ microsoft.vcpkg.ci - 定时触发,对主分支进行全面的集成测试,保障主干代码的健康度
│ └─▶ microsoft.vcpkg.pr
│ └─▶ 自动触发,进行编译、测试,确保代码质量后才允许合并
│ └─▶ 版本管理正确性
│ └─▶ 许可证字段完整性
│ └─▶ 废弃函数使用情况
│ └─▶ 回传状态,任务执行完毕后,Azure Pipelines 通过 GitHub 状态 API,将结果(成功/失败)回写到 GitHub 上对应的 PR 页面。
│ └─▶ Azure Artifacts - 成品仓库,可以直接被开发者或下游项目引用的最终产品的路径,或者错误日志
│
└─▶ GitHub Actions(快速检查) - Check For Common Mistakes
│ └─▶ vcpkg.json 格式规范
│ └─▶ 版本管理正确性
│ └─▶ 许可证字段完整性
│ └─▶ 废弃函数使用情况
│ └─▶ 代码格式和规范
│
└─▶ GitHub 策略服务 - Microsoft GitHub Policy Service
│ └─▶ 是否签署了微软的 CLA(贡献者许可协议)
│ └─▶ 确保贡献者授权微软使用其代码
↓
测试通过 → 等待 Reviewer 批准
↓
Merge to main
↓
触发部署流水线
├─▶ 更新文档站点(vcpkg.io)
├─▶ 更新包索引
├─▶ 构建二进制缓存(可选)
└─▶ 通知下游项目