iT邦幫忙

2026 iThome 鐵人賽

DAY 11
0
Software Development

C++ 套件管理器求生指南 Conan vs Vcpkg系列 第 11 篇

D11:vcpkg 的 triplet 是什麼碗糕?

  • 分享至 

  • xImage
  •  

在昨天跟前天的範例中,Windows 使用者一定發現了編譯出來的執行檔旁邊有個 fmt.dll。

其實我看到這個 DLL 覺得有點煩。

我把執行檔給同事用,還要連同 DLL 一起給,不然程式就跑不起來?難道不能把函式庫全部打包起來,只產出一個執行檔就好了嗎?這些在 vcpkg 裡面要怎麼設定呢?

其實啊,問題的答案就在 triplet 裡面。

一、所以 triplet 到底是什麼?

triplet 這個詞有點難懂,中文意思是「三元組」或「三胞胎」。以前是 GNU 用來指定編譯器設定用的專有名詞,被 vcpkg 沿用下來。

只要打開 $VCPKG_ROOT/triplets/ 這個目錄,你就可以看到全部的 triplet。

挑一個打開來看看,發現它就是一個 .cmake 檔案,然後裡面設定了一些變數。

比如說 x64-windows.cmake 的內容如下:

set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE dynamic)
set(VCPKG_PROVIDED_FORTRAN ON)

你會發現,這就是一組套件編譯相關的設定,像是可以指定:

  • CPU 架構 (VCPKG_TARGET_ARCHITECTURE): x64, x86, arm64 等等
  • C 執行期函式庫(VCPKG_CRT_LINKAGE):dynamic or static
  • 編譯成動態庫還是靜態庫(VCPKG_LIBRARY_LINKAGE): dynamic or static

再看看 Linux 跟 macOS 的 triplet:

x64-linux.cmake

set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE static)

set(VCPKG_CMAKE_SYSTEM_NAME Linux)

arm64-osx.cmake

set(VCPKG_TARGET_ARCHITECTURE arm64)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE static)

set(VCPKG_CMAKE_SYSTEM_NAME Darwin)
set(VCPKG_OSX_ARCHITECTURES arm64)

看完三個檔案,你會發現 VCPKG_LIBRARY_LINKAGE 這個變數在三個平台上的值不一樣,在 Windows 上是 dynamic,另外兩個平台是 static。這就是 Windows 平台上會產生 fmt.dll 的根本原因。

二、vcpkg 怎麼挑選預設的 triplet?

在前面的章節中,我們完全沒指定 triplet,所以 vcpkg 到底是用哪個呢?

triplet 的命名規則其實很直觀,就是:[CPU 架構]-[作業系統]。

當不指定時,vcpkg 會根據你的建置工具自動推導這兩項資訊:

  1. 如果你用 CMake(Manifest 模式):

    • 先看目前的作業系統,再看編譯器要產出的目標架構。例如 Windows MSVC 產出 64 位元就是 x64;macOS 則是 Apple Silicon(arm64)。
    • 兩者拼在一起,就是 x64-windows 或 arm64-osx。
  2. 如果你用 Visual Studio(MSBuild 專案):

    • 這更簡單直接,它直接看 Visual Studio 上方工具列的 平台下拉選單(Platform):
      • 選 x64 → 自動使用 x64-windows
      • 選 Win32(x86) → 自動使用 x86-windows
      • 選 ARM64 → 自動使用 arm64-windows

這是自動挑選的邏輯,那可以手動指定 Triplet 嗎?當然可以!

三、手動指定 Triplet:換成靜態連結

文章一開始說,我們希望用靜態連結的方式來編譯第三方函式庫,只產出單一執行檔,避免複製 fmt.dll 的麻煩。

這件事的最佳 Triplet 是 x64-windows-static-md,裡面已經把VCPKG_LIBRARY_LINKAGE 值改為 static,這樣函式庫就會被編譯成靜態的 .lib 而非 .dll。

接著在 CMake 指令中傳入 -DVCPKG_TARGET_TRIPLET 來指定 Triplet:

cmake -S . -B build-static `
  -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" `
  -DVCPKG_TARGET_TRIPLET=x64-windows-static-md
cmake --build build-static --config Release

就這樣,編譯過後,打開輸出目錄,裡面只有一個乾乾淨淨的 exe,討人厭的 fmt.dll 已經消失了。因為 fmt 已經變成靜態函式庫,被直接連結融入 exe 檔案裡了。

四、內建的和社群維護的 Triplet

triplets/ 底下的檔案分兩種:

官方內建(built-in)的放在根目錄,官方 CI 每次都測。目前的內建 triplet 只有這幾個:

社群(community)維護的放在 triplets/community/。裡面有 iOS、MinGW、FreeBSD、WebAssembly 等等一百多個。附帶一提,Intel Mac x64-osx 也是社群維護的。

五、Visual Studio 換靜態連結

Visual Studio 要換 triplet 的話,一樣在專案屬性裡改。

專案屬性 → vcpkg:

要直接指定其他 triplet,就在 Triplet 那一欄裡面填入你要的名稱。

六、小結

  • triplet 是一個 CMake 檔,核心是三個變數:架構、CRT 連結、套件連結方式。
  • Windows 預設是動態連結(產出 DLL),Linux 與 macOS 預設是靜態連結。
  • Windows 想要函式庫靜態連結、CRT 維持動態,指定 x64-windows-static-md 最省事;連 CRT 都要靜態才用 x64-windows-static。
  • 官方內建的 triplet 只有十來個,其餘上百個(包含 Intel Mac 的 x64-osx)都在 community 社群維護區。

上一篇
D10:Visual Studio 搭配 vcpkg 套件管理器
下一篇
D12:vcpkg 的版本控制與 baseline 概念
系列文
C++ 套件管理器求生指南 Conan vs Vcpkg 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言