Windows 平台¶
使用 CCGO 为 Windows 构建 C++ 库的完整指南。
概述¶
CCGO 提供全面的 Windows 支持:
- 多工具链:MSVC(Visual Studio)和 MinGW(GCC)
- 多架构:x86、x64、ARM64
- 输出格式:静态库(.lib)、动态库(.dll)
- 构建方式:本地构建(Visual Studio/MinGW)或 Docker(跨平台)
- IDE 支持:Visual Studio 项目生成
- 子系统:控制台和窗口子系统
- 运行时库:静态和动态 CRT 链接
前置条件¶
方式一:本地构建(需要 Windows)¶
使用 MSVC: - Windows 10+(64位) - Visual Studio 2019+ 及 C++ 工作负载 - CMake 3.20+
安装方法:
# 从 visualstudio.microsoft.com 安装 Visual Studio
# 选择"使用 C++ 的桌面开发"工作负载
# 安装 CMake
# 从 cmake.org 下载或使用 chocolatey
choco install cmake
# 验证安装
cmake --version
cl.exe
使用 MinGW: - Windows 10+(64位) - MinGW-w64 或 MSYS2 - CMake 3.20+
安装方法:
# 从 msys2.org 安装 MSYS2
# 然后安装 MinGW-w64
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake
# 添加到 PATH
# C:\msys64\mingw64\bin
# 验证
gcc --version
g++ --version
方式二:Docker 构建(任何操作系统)¶
在 Linux 或 macOS 上使用 Docker 和 MinGW 构建 Windows 库。
必需: - 已安装并运行 Docker Desktop - 5GB+ 磁盘空间用于 Docker 镜像
优势: - 在任何操作系统上构建 - 无需 Windows 许可证 - 一致的构建环境 - MinGW-w64 交叉编译
限制: - 仅 MinGW(无 MSVC) - 无法运行/测试 Windows 应用 - 初始下载较大(约 1.2GB 镜像)
详见 Docker 构建部分。
快速开始¶
基本构建¶
# 使用默认工具链为 x64 构建
ccgo build windows
# 使用 Docker 构建(MinGW 交叉编译)
ccgo build windows --docker
# 指定工具链
ccgo build windows --toolchain msvc # MSVC(仅 Windows)
ccgo build windows --toolchain mingw # MinGW
ccgo build windows --toolchain auto # 两个工具链(默认)
# 指定架构
ccgo build windows --arch x86 # 32位
ccgo build windows --arch x64 # 64位(默认)
ccgo build windows --arch arm64 # ARM64
# 构建类型
ccgo build windows --build-type debug # Debug 构建
ccgo build windows --build-type release # Release 构建(默认)
# 链接类型
ccgo build windows --build-as static # 仅静态库
ccgo build windows --build-as shared # 仅 DLL
ccgo build windows --build-as both # 两种类型(默认)
生成 Visual Studio 项目¶
# 生成 Visual Studio 解决方案
ccgo build windows --ide-project
# 在 Visual Studio 中打开
start cmake_build/windows/msvc/MyLib.sln
输出结构¶
默认输出 (target/windows/)¶
target/windows/
├── MyLib_Windows_SDK-1.0.0.zip # 主包
│ ├── lib/
│ │ ├── static/
│ │ │ ├── msvc/
│ │ │ │ └── mylib.lib # MSVC 静态库
│ │ │ └── mingw/
│ │ │ └── libmylib.a # MinGW 静态库
│ │ └── shared/
│ │ ├── msvc/
│ │ │ ├── mylib.dll # MSVC DLL
│ │ │ └── mylib.lib # 导入库
│ │ └── mingw/
│ │ ├── libmylib.dll # MinGW DLL
│ │ └── libmylib.dll.a # 导入库
│ ├── bin/ # DLLs(用于运行时)
│ │ ├── msvc/
│ │ │ └── mylib.dll
│ │ └── mingw/
│ │ └── libmylib.dll
│ ├── include/
│ │ └── mylib/ # 头文件
│ │ ├── mylib.h
│ │ └── version.h
│ └── build_info.json # 构建元数据
│
└── MyLib_Windows_SDK-1.0.0-SYMBOLS.zip # 调试符号
└── symbols/
├── msvc/
│ └── mylib.pdb # MSVC 调试符号
└── mingw/
└── libmylib.dll.debug # MinGW 调试符号
库类型¶
静态库:
- MSVC:.lib 文件
- MinGW:.a 文件
- 编译时链接
- 可执行文件更大
- 无运行时依赖
动态库(DLL):
- MSVC:.dll + .lib(导入库)
- MinGW:.dll + .dll.a(导入库)
- 运行时加载
- 可执行文件更小
- 需要 DLL 在运行时存在
构建元数据¶
build_info.json 包含:
{
"project": {
"name": "MyLib",
"version": "1.0.0",
"description": "My Windows library"
},
"build": {
"platform": "windows",
"architectures": ["x64"],
"toolchains": ["msvc", "mingw"],
"build_type": "release",
"link_types": ["static", "shared"],
"timestamp": "2024-01-15T10:30:00Z",
"ccgo_version": "0.1.0",
"msvc_version": "19.38",
"mingw_version": "13.2.0"
},
"outputs": {
"libraries": {
"msvc": {
"static": "lib/static/msvc/mylib.lib",
"shared": "lib/shared/msvc/mylib.dll"
},
"mingw": {
"static": "lib/static/mingw/libmylib.a",
"shared": "lib/shared/mingw/libmylib.dll"
}
},
"headers": "include/mylib/",
"symbols": {
"msvc": "symbols/msvc/mylib.pdb",
"mingw": "symbols/mingw/libmylib.dll.debug"
}
}
}
MSVC vs MinGW¶
MSVC(Microsoft Visual C++)¶
优点: - 微软官方编译器 - 最佳 Windows 集成 - 使用 Visual Studio 的出色调试 - 更好的 Windows 优化 - 与 Windows SDK 兼容
缺点: - 仅 Windows - 需要 Visual Studio 安装 - 工具链更大
何时使用: - Windows 特定开发 - 需要 Visual Studio 集成 - 最大化 Windows 性能 - 使用 Windows SDK API
MinGW(Minimalist GNU for Windows)¶
优点: - 基于 GCC(跨平台兼容) - 可以从 Linux/macOS 交叉编译 - 工具链更小 - 开源 - 与 Unix 工具兼容
缺点: - 某些 Windows API 未完全支持 - 可能比 MSVC 慢 - 较少 Windows 特定优化
何时使用: - 跨平台开发 - 在非 Windows 系统上构建 - 需要 GCC 兼容性 - 不需要高级 Windows API
在 C++ 中使用库¶
链接静态库¶
CMakeLists.txt(MSVC):
# 查找库
find_library(MYLIB_LIBRARY
NAMES mylib
PATHS "path/to/lib/static/msvc"
)
# 链接到目标
target_link_libraries(myapp PRIVATE ${MYLIB_LIBRARY})
target_include_directories(myapp PRIVATE "path/to/include")
CMakeLists.txt(MinGW):
find_library(MYLIB_LIBRARY
NAMES mylib libmylib.a
PATHS "path/to/lib/static/mingw"
)
target_link_libraries(myapp PRIVATE ${MYLIB_LIBRARY})
target_include_directories(myapp PRIVATE "path/to/include")
链接动态库¶
CMakeLists.txt:
# 链接导入库
target_link_libraries(myapp PRIVATE "path/to/lib/shared/msvc/mylib.lib")
# 复制 DLL 到输出目录
add_custom_command(TARGET myapp POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"path/to/bin/msvc/mylib.dll"
$<TARGET_FILE_DIR:myapp>
)
在代码中使用:
Docker 构建¶
在任何操作系统上使用 Docker 和 MinGW 构建 Windows 库:
前置条件¶
# 安装 Docker Desktop
# 下载地址:https://www.docker.com/products/docker-desktop/
# 验证 Docker 正在运行
docker ps
使用 Docker 构建¶
# 首次构建下载预构建镜像(约 1.2GB)
ccgo build windows --docker
# 后续构建很快
ccgo build windows --docker --arch x64
# 所有标准选项都可用(仅 MinGW)
ccgo build windows --docker --build-as static
工作原理¶
- CCGO 使用 Docker Hub 的预构建
ccgo-builder-windows镜像 - 项目目录挂载到容器中
- 使用 MinGW-w64 交叉编译器构建
- 输出写入主机文件系统
限制¶
- 仅 MinGW:无法在 Docker 中使用 MSVC 构建
- 无法运行:Docker 中没有 Windows 运行时
- 无法测试:无法执行 Windows 二进制文件
平台配置¶
CCGO.toml 设置¶
[package]
name = "mylib"
version = "1.0.0"
[library]
type = "both" # static、shared 或 both
[build]
cpp_standard = "17" # C++ 标准
[windows]
subsystem = "console" # console 或 windows
runtime_library = "MD" # MT、MD、MTd、MDd(仅 MSVC)
windows_sdk_version = "10.0" # Windows SDK 版本
CMake 变量¶
为 Windows 构建时:
${PLATFORM} # "windows"
${ARCHITECTURE} # "x86"、"x64" 或 "arm64"
${BUILD_TYPE} # "Debug" 或 "Release"
${LINK_TYPE} # "static"、"shared" 或 "both"
${TOOLCHAIN} # "msvc" 或 "mingw"
${WINDOWS_SUBSYSTEM} # "console" 或 "windows"
${MSVC_RUNTIME_LIBRARY} # "MD"、"MT" 等(仅 MSVC)
条件编译¶
// 平台检测
#ifdef _WIN32
// Windows 特定代码
#include <windows.h>
#ifdef _WIN64
// 64位 Windows
#else
// 32位 Windows
#endif
#endif
// 编译器检测
#ifdef _MSC_VER
// MSVC 特定代码
#pragma warning(disable: 4996)
#elif defined(__MINGW32__) || defined(__MINGW64__)
// MinGW 特定代码
#endif
// DLL 导出/导入
#ifdef MYLIB_EXPORTS
#define MYLIB_API __declspec(dllexport)
#else
#define MYLIB_API __declspec(dllimport)
#endif
// 用法
class MYLIB_API MyClass {
public:
void do_work();
};
最佳实践¶
1. 支持两个工具链¶
使用 MSVC 和 MinGW 构建:
2. 使用正确的 DLL 导出¶
始终使用 __declspec(dllexport/dllimport):
// mylib_export.h
#ifdef _WIN32
#ifdef MYLIB_EXPORTS
#define MYLIB_API __declspec(dllexport)
#else
#define MYLIB_API __declspec(dllimport)
#endif
#else
#define MYLIB_API
#endif
3. 处理运行时库¶
选择正确的 CRT 链接:
4. 在分发中包含 DLL¶
始终将 DLL 与二进制文件一起包含:
5. 在目标 Windows 上测试¶
始终在实际 Windows 系统上测试: - 不同的 Windows 版本(10、11) - 不同的架构(x86、x64) - 有和没有 Visual Studio 安装的情况
故障排除¶
未找到 MSVC¶
解决方案:
# 安装带 C++ 工作负载的 Visual Studio
# 或安装生成工具
# 验证
where cl.exe
# 如果需要,添加到 PATH
$env:PATH += ";C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\bin\Hostx64\x64"
未找到 MinGW¶
解决方案:
# 安装 MSYS2/MinGW
# 添加到 PATH
export PATH="/c/msys64/mingw64/bin:$PATH"
# 验证
gcc --version
g++ --version
未找到 DLL¶
解决方案:
- 将 DLL 复制到可执行文件目录
-
将 DLL 目录添加到 PATH:
-
使用延迟加载(MSVC):
未找到符号¶
解决方案:
-
检查 DLL 导出:
-
验证 __declspec(dllexport):
-
使用 .def 文件导出:
性能提示¶
1. 使用链接时优化¶
2. 启用优化¶
3. 独立部署的静态 CRT¶
用于无需 Visual C++ 可再发行组件的部署:
迁移指南¶
从 Visual Studio 项目¶
之前:
之后:
-
创建 CCGO 项目:
-
复制源文件到
src/ -
配置 CCGO.toml:
-
构建:
从 CMake¶
CMakeLists.txt:
CCGO.toml:
然后:ccgo build windows