Conan:C/C++ 的套件管理工具

開發 C++ 程式時,套件管理會是個困擾開發者的問題,C++ 不像 Python 有 pip;node.js 有 npm;lua 有 rock;C# 有 Nuget。它就只是沒有。沒有套件管理,當不同開發環境的使用者要開發程式時,不僅需要手動將相關的檔案塞進 repository 中,還會遇到相容性的問題,例如小明使用 paho-c 1.3.0 開發,開發到一半時,另一位開發者小華引用了小明放在 repo 中 include 資料夾下的 header file,卻使用了自己的 1.3.1 shared library,這使得兩個人的版本不相容,要花很多時間除錯。

此外,當需要更新 repo 中的第三方套件版本時,需要手動將檔案放到 include 跟 libs 的資料夾,你引用多少套套件,你就要塞多少檔案進去;而跨平台的問題也是,Win32 可能要一份,Win64 要一份,Release 跟 Debug 的 Libs 各要一份,Linux 跟 Mac 再各要一份,最後 x86、arm、mips 再各要一份,自行排列組合一下就知道這個更新的痛苦了。為什麼我知道呢?因為我就是那個被困擾的人。

好在許多開發者都有同樣的問題,於是 Conan 出來了,這是一個 C++ 套件管理工具,用 Python 寫成,目的在於協助開發者解決上述的困擾。本文會簡單介紹 Conan 的用法,希望大家看完後都能如獲新生。

Install conan

首先來安裝 conan 這套工具,由於 conan 是用 python 寫的,也有在 pip 的 remote repo 中,因此只要用 pip 即可安裝

ken@DESKTOP-2R08VK6:~/git/conan/build$ pip3 install conan
Collecting conan
    Downloading [https://files.pythonhosted.org/packages/2e/b7/560406ecd9d20e308498ce378dc8c1e0bc932f44d5377bc0ca62ec8dd75b/conan-1.21.1.tar.gz](https://files.pythonhosted.org/packages/2e/b7/560406ecd9d20e308498ce378dc8c1e0bc932f44d5377bc0ca62ec8dd75b/conan-1.21.1.tar.gz) (552kB)
    100% |████████████████████████████████| 552kB 761kB/s 
Collecting Jinja2<3,>=2.3 (from conan)
...

安裝完記得重新讀取 .profile,引入 conan 指令

source ~/.profile

Prepare Environment

來看一下專案環境,假設我們參照前篇,用 cmake 來進行編譯,工作目錄會長

project/
├── build/
├── src/
|   ├── CMakeLists.txt
|   └── hello.cpp
├── CMakeLists.txt
├── conanfile.txt
└── README

其中 src 放原始碼,hello.cpp 內容為經典的 hello, world

#include "Poco/Thread.h"
#include "Poco/Runnable.h"
#include <iostream>

class HelloRunnable: public Poco::Runnable
{
    virtual void run()
    {
        std::cout << "Hello, world!" << std::endl;
    }
};

int main()
{
    HelloRunnable runnable;
    Poco::Thread thread;
    thread.start(runnable);
    thread.join();
    return 0;
}

這邊使用 Poco 的 Lib 來創建 thread,並呼叫一個印出 Hello, world 的 Runnable。之所以用 Poco 是因為 conan 官方也用 Poco 當範例,而且方便進行跨平台。Lib 本身不是重點,重點是有使用了一個第三方套件。

關於 CMakeLists.txt 的使用請參照前篇,不再多述,兩個 CMakeLists.txt 分別是

# .CmakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
PROJECT(HELLOLIB)
ADD_SUBDIRECTORY(src)

以及

# .src/CmakeLists.txt

ADD_EXECUTABLE(hello hello.cpp)

Edit conanfile

conan 使用 conanfile.txt 來管理套件,conanfile 的格式有點像 TOML,但我找不到官方說法,對使用者來說也許不用想太多,只要知道是某種配置文件就行,它的內容是

[requires]
Poco/1.9.4@pocoproject/stable

[generators]
cmake

這段內容表示依賴套件是 Poco,版本 1.9.4,來源 pocoproject/stable,產生cmake 模組。

接著進到 build 目錄,使用 conan

ken@DESKTOP-2R08VK6:~/git/conan/build$ conan install ..
Configuration:
[settings]
arch=x86_64
arch_build=x86_64
build_type=Release
compiler=gcc
compiler.libcxx=libstdc++
compiler.version=7
os=Linux
os_build=Linux
[options]
[build_requires]
[env]

conanfile.txt: Installing package
Requirements
    OpenSSL/1.0.2o@conan/stable from 'conan-center' - Cache
    Poco/1.9.4@pocoproject/stable from 'conan-center' - Cache
    zlib/1.2.11@conan/stable from 'conan-center' - Cache
Packages
    OpenSSL/1.0.2o@conan/stable:b781af3f476d0aa5070a0a35b544db7a3c193cc8 - Cache
    Poco/1.9.4@pocoproject/stable:57e3039664a87aab5ccabd995efae6da01c1ff17 - Cache
    zlib/1.2.11@conan/stable:d50a0d523d98c15bb147b18fa7d203887c38be8b - Cache

zlib/1.2.11@conan/stable: Already installed!
OpenSSL/1.0.2o@conan/stable: Already installed!
Poco/1.9.4@pocoproject/stable: Already installed!
conanfile.txt: Generator cmake created conanbuildinfo.cmake
conanfile.txt: Generator txt created conanbuildinfo.txt
conanfile.txt: Generated conaninfo.txt
conanfile.txt: Generated graphinfo

然後工作目錄就變成

project/
├── build/
|   ├── ...
|   ├── conanbuildinfo.cmake
|   └── ...
├── src/
|   ├── CMakeLists.txt
|   └── hello.cpp
├── CMakeLists.txt
├── conanfile.txt
└── README

跟之前對照,多出了 cmake 模組 conanbuildinfo.cmake

Modify CMakeLists

之所以要有 cmake 模組,就是為了讓 cmake 引用,因此要回頭改 CMakeLists.txt,將 conan 相關的指令加進去

# .CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
PROJECT(HELLOLIB)

INCLUDE(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
CONAN_BASIC_SETUP()

INCLUDE_DIRECTORIES(${CONAN_INCLUDE_DIRS})
MESSAGE(STATUS ${CONAN_INCLUDE_DIRS})
ADD_SUBDIRECTORY(src)

其中 INCLUDE 是引用 conan 產生的 cmake 模組;CONAN_BASIC_SETUP 會設定 conan 需要的變數;INCLUDE_DIRECTORIES 是引用 conan 相關的 header file,免去手動搬運 header file 的麻煩。MESSAGE 可加可不加,這邊是用來印出 conan header file 的所在目錄,讓開發者心底踏實一點。

而另一個 CMakeLists.txt 則改成

# .src/CMakeLists.txt

ADD_EXECUTABLE(hello hello.cpp)
TARGET_LINK_LIBRARIES(hello ${CONAN_LIBS})

非常單純,就是鏈結 conan 相關的 lib。

Build

關鍵的時候到了,用 cmake 配置並編譯

ken@DESKTOP-2R08VK6:~/git/conan/build$ cmake ..
-- The C compiler identification is GNU 7.4.0
...
-- /home/ken/.conan/data/Poco/1.9.4/pocoproject/stable/package/57e3039664a87aab5ccabd995efae6da01c1ff17/include/home/ken/.conan/data/OpenSSL/1.0.2o/conan/stable/package/b781af3f476d0aa5070a0a35b544db7a3c193cc8/include/home/ken/.conan/data/zlib/1.2.11/conan/stable/package/d50a0d523d98c15bb147b18fa7d203887c38be8b/include
...

可以看到 conan 抓下來的檔案會放在 user 家目錄的 .conan。

ken@DESKTOP-2R08VK6:~/git/conan/build$ cmake --build .
Scanning dependencies of target hello
[ 50%] Building CXX object src/CMakeFiles/hello.dir/hello.cpp.o
[100%] Linking CXX executable ../bin/hello
[100%] Built target hello

編譯完成,來執行看看

ken@DESKTOP-2R08VK6:~/git/conan/build$ ./bin/hello 
Hello, world!

結束!conan 自動抓完 header file 跟 library,開發者不要再煩惱套件跟庫管理了,專心來享受寫程式的快樂吧。

小結

看到 conan 能自動管理套件,真的不是個「爽」字能形容,套句強者我同事的話:「我不常寫 C++,因為它的套件管理太可怕了」。有使用開源程式碼開發的人,應該非常能了解這種感受。

在使用 conan 開發途中,難免踩到一些坑,直接上 GitHub 發問後,沒想到 conan 的 Contributor 在短短幾小時內就快速回覆,還 involve 相關專案的 Contributor 一起來確認,現在開源社群的活躍度已經這麼厲害了嗎?

要說 conan 的問題,可能是普及度還不夠,有時需要的 library 不一定會有,但我覺得這沒有關係,只要會 python,就可以捲起袖子,把自己要用的 library 打包後回饋,讓其他人也能快速利用同樣的資源。畢竟人生苦短,不要重複造輪子,我們可以面朝大海。

Reference

Read more

Weekly Issue 第 24 期:網路的精神高地

前陣子去了雪梨一趟,跟布里斯本或台北都形成有趣的對比,旅行中也不斷在想,一座城市如何發展出自己的文化?這有點像是網路平台如何形成聚落,而又如何消亡。 很喜歡本期談知乎的一篇文章,理想主義的光輝是最吸引人的,我常在想,有沒有辦法將那座「看不見的城市」帶到真實世界中。 🗞️ 熱門新聞 A ChatGPT prompt equals about 5.1 seconds of Netflix 看到 Simon Willison 提到,如果 Sam Altman 的資訊是對的,每個 LLM 提問相當於 5.1s 的 Netflix 影片耗能。 計算的需求讓輝達跟台積電挖到金礦,那電力需求又會讓誰挖到金礦呢? ✨ 科技觀點 我们失去的不只是知乎,而是中文互联网的精神高地 「那时的知乎,更像“思想沙龙”,而非“内容平台”。」 昨天跟朋友聊天,

By Ken Chen

Weekly Issue 第 23 期:Mastodon CEO 離職感言

電子報本質是種自媒體,儘管我發文前都會確認,還因為能力所限,偶爾還是有沒做好的地方。每次遇到時我都會想,不知道其他自媒體是如何查證的呢? 現代的訊息越來越快,不只是自媒體,很多專業媒體也不見得有完備的查證能力,我猜當內容氾濫,「真實」會變得越來越有價值,最終變成一門生意。 🗞️ 熱門新聞 Explore the independent web Ghost 最新一期的電子報談到他們如何處理「內容發現」的問題。 簡單來說,他們有個內容發現工具 Ghost Explore,如果創作者願意提交自己的網站數據,他們能依照這些網站數據來推薦。再來,他們還會參考 ahrefs 的資料,判斷該網域是否具有高品質。 這比 Substack 發展社群工具,更貼近我對產品的想像。現代內容網站基本都需要演算法,這已經不是要不要,是怎麼設計的問題。 My next chapter with Mastodon Mastodon 的 CEO 即將卸任,他發了篇談談這段時間的心路歷程。

By Ken Chen

Weekly Issue 第 22 期:Google 發布 Nano Banana Pro

最近大新聞要算 Cloudflare 出問題,以及 Google 發布新的 AI 模型。新的 Nano Banana Pro 不管在一致性還是文字呈現,都出乎意料地好。如果 Google 真的能在這場 AI 大戰中笑到最後,這一定會成為商業競爭的經典案例。 🗞️ 熱門新聞 How we’re bringing AI image verification to the Gemini app Google 幾天前發布的 AI 模型太強了,各種錦上添花的稱讚就不說了,在 Simon Willison 的 Blog 看到,Google 設計出防偽機制,避免假圖到處跑。 機制有兩種,一種是在生成的內容中,插入人眼不可辨識的 SynthID,

By Ken Chen

Weekly Issue 第 21 期:JetBrains 發表 2025 Go 生態系調查

最近在讀 Tony Fadell 的 "Build",作者曾經參與過 iPhone 的開發,各種經驗談讓人嘆為觀止,例如這段:「如果故事有某個部分銜接不上,那麼產品本身也會有某個地方行不通…這便是為什麼最後 iPhone 的表面是玻璃,而不是塑膠,以及為什麼 iPhone 沒有硬體鍵盤。」 好在哪呢?好在如果能掌握這個觀念,就能知道如何「閱讀」產品,看見一個產品,就像閱讀一則故事一樣,知道它的抑揚頓挫,知道它想表現的東西。我相信每個經歷過產品開發的人,看這本書都會很有感覺。   🗞️ 熱門新聞 The Go Ecosystem in 2025: Key Trends in Frameworks, Tools, and Developer Practices JetBrains 前陣子公布 Go 生態系的調查結果。

By Ken Chen