習慣 Linux GCC 命令行編譯流程,但在 Windows 需要用 MSVC 編譯 DLL。Visual Studio 安裝體積龐大,若只需命令行編譯器,可提取核心文件構建輕量級工具鏈,類似 MinGW 但使用官方 MSVC 編譯器,保證 ABI 兼容性。
D:\vctool\
├── bin\ # 編譯器 cl.exe、鏈接器 link.exe 等
├── include\ # 標準庫頭文件
├── lib\ # MSVC 庫文件
└── sdklib\ # Windows SDK 庫文件
| 目標目錄 | 來源路徑 (VS 2019/2022 典型路徑) |
|---|---|
| bin | VC\Tools\MSVC\14.xx.xxxxxx\bin\Hostx64\x64\ |
| include | VC\Tools\MSVC\14.xx.xxxxxx\include\ |
| lib | VC\Tools\MSVC\14.xx.xxxxxx\lib\x64\ |
| sdklib | Windows Kits\10\Lib\10.0.xxxxxx\um\x64\ |
注意:SDK 庫單獨放 sdklib 避免覆蓋 MSVC 庫,後續鏈接時需同時指定兩個路徑。
將 D:\vctool\bin 加入系統 PATH,或在編譯腳本中臨時設置。
// Test.c
#include <stdio.h>
__declspec(dllexport) int sum(int a, int b) {
return a + b;
}
__declspec(dllexport) void hello() {
puts("Hello from MSVC DLL!");
}
@echo off
setlocal
:: 工具鏈路徑
set VCTOOL=D:\vctool
set PATH=%VCTOOL%\bin;%PATH%
set INCLUDE=%VCTOOL%\include
set LIB=%VCTOOL%\lib;%VCTOOL%\sdklib
:: 編譯為目標文件
cl /c Test.c
if errorlevel 1 exit /b 1
:: 鏈接為 DLL
link /dll Test.obj /out:Test.dll
if errorlevel 1 exit /b 1
echo 成功生成: Test.dll, Test.lib, Test.exp
pause
| 錯誤信息 | 原因 | 解決 |
|---|---|---|
| 找不到 mspdb140.dll / mspdbcore.dll | PDB 服務 DLL 缺失 | 從 VS 安裝目錄複製到 bin 目錄 |
| LINK: fatal error LNK1104: 無法打開 kernel32.lib | SDK 庫路徑缺失 | 確認 sdklib 已複製且 LIB 包含該路徑 |
| cl: 命令行錯誤 D8003: 缺少源文件名 | 工作目錄錯誤 | cd 到源文件目錄再運行 build.bat |
| 未解析的外部符號 | 缺少庫或調用約定不匹配 | 檢查 __declspec(dllexport)、.def 文件、LIB 路徑 |
/c 僅編譯不鏈接,生成 .obj
/Zs 語法檢查不生成文件
/I 路徑 添加頭文件搜索路徑
/D 宏 定義預處理器宏
/MD 使用動態運行庫 MSVCRT.dll (發布推薦)
/MT 使用靜態運行庫 libcmt.lib
/O2 速度優化
/Ob2 內聯優化
/Wall 最高警告級別
/WX 警告視為錯誤
/EHsc C++ 異常處理模型
/TC 強制作為 C 源文件編譯
/TP 強制作為 C++ 源文件編譯
/Fo文件名 指定輸出 .obj 文件名
/dll 生成 DLL
/out:文件名 指定輸出文件名
/libpath:路徑 添加庫搜索路徑
/machine:x64 目標架構
/def:文件.def 模塊定義文件導出符號
/export:函數名 命令行指定導出
/entry:函數名 入口點 (DLL 默認 DllMain)
/subsystem:console 控制台子系統
/subsystem:windows GUI 子系統
/opt:ref 移除未引用數據/函數
/opt:icf 合併相同函數
; Test.def
LIBRARY Test
EXPORTS
sum
hello
link /dll Test.obj /def:Test.def /out:Test.dll
.def 文件優勢:不污染源碼、支持序數導出、重命名導出、數據導出。
# CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(TestDLL LANGUAGES C)
# 指定 MSVC 工具鏈 (可選,通常自動檢測)
# set(CMAKE_C_COMPILER "D:/vctool/bin/cl.exe")
add_library(Test SHARED Test.c)
set_target_properties(Test PROPERTIES
WINDOWS_EXPORT_ALL_SYMBOLS ON # 自動導出所有符號 (類 GCC)
)
CMake 會自動調用 cl/link,生成 Visual Studio 解決方案或直接構建,比手寫 bat 更可維護。
| 維度 | MinGW-w64 | MSVC 提取版 |
|---|---|---|
| ABI 兼容性 | GNU/MinGW | 原生 MSVC (Windows 系統組件標準) |
| C 標準支持 | C11/C17 較好 | C11/C17 部分,C18 改進中 |
| 調試器支持 | GDB | WinDbg / VS Debugger (最佳) |
| 運行庫依賴 | msvcrt.dll (系統) 或 ucrtbase.dll | vcruntime140.dll + ucrtbase.dll |
| 授權 | GPL/LGPL | Visual Studio 授權條款 |