使用 Conan 時最常看到的錯誤就是 Missing prebuilt package。

咦,ConanCenter 不是都有預編譯好的套件嗎?那為什麼我跑 conan install 指令,還是常常看到一大片紅紅的 Missing prebuilt package ?
說好的「下載就能用」呢?
答案就是: ConanCenter 有預編譯套件可供下載,但不一定有「為你量身訂做」的那一份。
我們前面提過,C++二進位檔案之間的相容性錯綜複雜,到底 Visual Studio 2026 編譯出來的檔案,Visual Studio 2019 能不能用呢? GCC 10 跟 GCC 13 的相容性呢? Debug 版跟 Release 版的二進位檔案呢?預編譯套件用了 C++20 標準,可是下游消費端只能跑 C++17,這樣可以直接下載嗎?
上面那一串,我可以跟你說,有的可以,有的不行。實在太多條件跟狀況了,而 Conan 盡可能的把這些不相容的地方考慮進來,所以在真實的專案情境下(例如:我這個專案就是要用 MSVC2026 + /MT + C++26),幾乎無可避免的會恰好碰到一個小地方沒對上,最終就無法下載伺服器上的預編譯二進位檔。
所以從外面看「這家店明明有賣這道菜呀」,但是實際走進店裡,卻發現店家不接受「不加香菜大辣」特製餐點。
D14 我們講過 Package ID 這個東西:Conan 把套件的 settings、options 和依賴丟進去算 hash,算出來的就是 package ID,每個 package ID 對應一個 binary。
所以下面這些,只要改一項,就是另一個新的 package ID:
os: Windows 或者 Linuxarch: x86_64 或者 armv8compiler: msvc / apple-clang / gcccompiler.version: 194 vs 193 (MSVC)、17 vs 21 (Xcode)compiler.runtime: MSVC 的 /MD(dynamic)vs /MT(static)compiler.cppstd: C++語言標準 14、17、20…build_type: Release vs Debugoptions: shared=True/False、header_only只要有一個東西沒對上,抱歉,預編譯二進位檔可能就是跟你無緣,無法套用。

另一個可能造成 binary 突然消失的隱形原因:Recipe 改版(recipe revision)。
還有一個比較少人注意的間接依賴。
比如你的程式引入了 cURL 這個套件,然後 cURL 套件需要 zlib,zlib 就是間接依賴。
今天狀況如下, cURL 雖然沒變,但是上游套件改版了,zlib 1.3.0 → 1.3.1 升版,請問 cURL 套件的預編譯二進位檔還可以用嗎?
這個就有趣了,實際上要看 zlib 到底是怎麼編譯跟連結的。如果 zlib 只是小改版修 BUG,而且公開函數的界面、記憶體布局都沒變,那「有機會」不需要重編。
到底需不需要重編,Conan 有相當細微的設定。官方稱之為 embed / non-embed 模式,有興趣者可用這個關鍵字下去鑽研細節。
一般使用者只要知道「間接依賴升版,也可能害你的套件 package ID 變動而 Missing」就夠了。
ConanCenter 上到底有什麼可以下載,可以直接問伺服器:

conan list "fmt/12.2.0:*" -r conancenter
我把 fmt 12.2.0 的結果整理成表格:
| 平台 | 編譯器 | C++ 標準 | build_type | shared |
|---|---|---|---|---|
| Windows x86_64 | msvc 194 | 14 | Release | True / False |
| Windows armv8 | msvc 194 | 14 | Release | True / False |
| macOS x86_64 | apple-clang 17 | gnu17 | Release | True / False |
| macOS armv8 | apple-clang 17 | gnu17 | Release | True / False |
| Linux x86_64 | gcc 13 | gnu17 | Release | True / False |
再加上一個 Header Only 的版本,總共只有 11 個預編譯的版本。
你有沒有發現一個有趣的狀況:怎麼全部都是 Release 版本的二進位檔?意思是,如果你用 Debug 編譯專案,那麼就抓不到官方伺服器上的預編譯二進位檔案了。
事實上,ConanCenter 根本不可能把全世界每種編譯器版本、每種 CRT、每種 options 組合都編一份。它只能挑主流平台加上幾個固定的編譯器組合。
用 conan list ... -r conancenter 這個指令查詢套件,非常好用。
不過,找不到「一模一樣」的 package ID,Conan 也不會馬上放棄。
Conan 有一套 binary compatibility 相容機制。
比方說,Conan 有一條內建規則:同一個編譯器、同一個編譯器版本下,不同 compiler.cppstd 編出來的二進位檔視為相容。
比如說,我的專案是 C++17,官方伺服器上的 fmt/12.2.0 用的是 C++14。那麼我呼叫 conan install 的時候,Conan 判斷 C++14 的那份二進位檔案相容,可以直接拿來用。

用 C++14 編的 fmt 給 C++17 專案連結,應該是沒問題啦。
Windows 上它還會試圖去找 MSVC 的前一版
compiler.version=193,這是 Conan 對 msvc 的額外相容規則。因為微軟官方保證了 VS 2015 (190) 到 VS 2022 (194) 二進位向後相容,用 193 編出來的 library 給 194 連結是安全的,所以 Conan 敢大膽通融。反觀 Apple Clang 並沒有做出保證,Conan 就不敢跨版本相容。
但是除了少數例外,其實大部分編譯器設定還是會造成不相容。
有一個超好用的指令:就是 conan graph explain。
只要把 conan install 裡面的字替換成 graph explain,他就會告訴你「最接近的那份 binary」,然後直接告訴你差異在哪裡。
比如我們用以下指令故意下達 static runtime 的要求。
conan graph explain . -s compiler.runtime=static
輸出
======== Closest binaries ========
fmt/12.2.0
fmt/12.2.0#b445244e6d0151a425e229248cd2bed8:159b372171ff86fd7630aefcf978b21a606abf85
remote: conancenter
settings: Windows, x86_64, Release, msvc, 14, dynamic, Release, 194
options: header_only=False, shared=False, with_os_api=True, with_unicode=True
diff
settings
expected: compiler.runtime=static
existing: compiler.runtime=dynamic
explanation: This binary was built with different settings.
Conan 直接告訴你:你想要 static runtime,伺服器上只有 dynamic runtime。
以後看到 Missing prebuilt package,第一件事就是先打 graph explain,不用猜。
找到問題之後,你有三條路可以選。
如果那個設定不是你非用不可的(例如只是 profile 裡不小心把 compiler.runtime 設成 static),改回官方有的設定,就可以直接下載現成的二進位檔啦。
真的需要那個設定,就讓 Conan 自己編譯就好了:
conan install . -s compiler.runtime=static --build=missing
只要在安裝的時候,下達 --build=missing 的指令,Conan 就會在本機上編譯缺漏的套件。
我的電腦上只用了 11 秒就編譯完成 fmt。編譯好的二進位留在本機快取,同一台電腦以後不用再編譯一次。
--build 有好幾種寫法:
--build:找不到 binary 就報錯--build=never:明確禁止任何本機編譯--build=missing:找不到(含相容 binary 也找不到)的才現場編--build=missing:fmt/*:只允許 fmt 本機編譯,其他套件找不到照樣報錯--build=fmt/*:fmt 一律從原始碼重編,不管伺服器上面有沒有--build="*":全部重編注意 pattern 要寫 fmt/*,不是只寫 fmt。平常開發 --build=missing 最省事。
如果團隊專案就是指定用了一個官方沒有的編譯器設定,團隊裡的十個開發者,難道十個人都要編一次?CI 上每一台機器也要編一次嗎?
不用啦。只要有一個人編譯好之後,上傳到團隊自己的 remote 伺服器:
conan remote add mycompany https://<your-remote-url>
conan upload "fmt/12.2.0:*" -r mycompany -c
之後同事安裝套件時,Conan 會到自架伺服器上面去找。只要算出來是同一個 package ID,就會從伺服器直接下載二進位檔,不必再編譯。

當然,這個解法需要自己架設 Conan server(例如 Artifactory),這也是大多數企業處理內部函式庫的方法。remote 怎麼加、怎麼上傳,請看 D19。