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 第 6 期:Duolingo CEO 看 AI 與遊戲化

現在是 AI 時代,大家都在想怎麼讓自己的產品跟 AI 掛勾,但具體要怎麼做呢?背後的思考有哪些?Duolingo 給出他們自己的觀點。 例如,現在的產品是否只是 AI 套皮,你接收使用者的問題,套上自己的提詞後,拿去給 OpenAI,要它回答你?在現在百家爭鳴的情況下,選擇哪個模型會有差嗎?AI 能帶來新用戶與新營收嗎?等等。 另外本週也選了一篇少數派的文章,談 AI 對 RSS 的影響,對 RSS 未來方向有興趣的人不妨看看。 🗞️ 熱門新聞 Duolingo CEO Luis von Ahn wants you addicted to learning Duolingo CEO 專訪,相當紮實,推薦閱讀。 「對我們來說,

By Ken Chen

Weekly Issue 第 5 期:OpenAI 的企業文化

我一直都喜歡看科技公司的願景與文化,原因是,我想知道別人是如何看待自己的使命,又是用什麼方式打造它。願景通常在官網都會有,但想要知道文化,只能聽內部人講講了。 Palantir 前陣子因為它不同於矽谷的文化,而引起很多討論。受此影響,前 OpenAI 的員工在離職創辦公司後,也發文談論他所見到的 OpenAI。最讓我震撼的是,他們幾乎沒有資金困擾,想的都是如何打造出色的 AI 模型。 🗞️ 熱門新聞 Reflections on OpenAI 前員工談 OpenAI 的內部文化。 讀起來最大的感觸是,有些價值觀、觀點、實踐,只有在世界級的公司跟資源下,才有可能建立起來。讓每個團隊各自為政,看誰能端出最好的成果,這對新創(特別是沒拿創投)實在太奢侈了。 我相信這種經歷會變成是「可以帶著走的饗宴」,那種衝擊也是最寶貴的。 AI Open Source Productivity METR 前陣子發了一篇研究,說使用 AI

By Ken Chen

Weekly Issue 第 4 期:Canonical 的面試經驗

這星期看了比較多職涯相關的內容,最讓我驚訝的是 Canonical 的面試流程,當我分享這則新聞後,有更多朋友紛紛補充他們的面試經驗:需要經歷三個 Tier,每個 Tier 都有三關,而內容甚至還包括問人選「高中成績」與「大學生活」。 我很難想像一家做 Linux 發行版的公司,會如此草率對待人選,這讓我對他們家的產品有了很大的問號。 🗞️ 熱門新聞 My experience with Canonical's interview process 這是一篇 Canonical 的面試經歷(如果你不知道什麼是 Canonical,就是開發 Ubuntu 的公司)。 整個過程讓人非常驚訝,甚至還需要人選回答「高中成績」,而在面試中做筆記居然是扣分項。我看完後有股移除 Ubuntu 的衝動。真的太扯啦。 What happens when engineers work

By Ken Chen

Weekly Issue 第 3 期:Cloudflare 宣布內容獨立日

最近用了很多 Cloudflare 的產品,像是 Zero Trust、WARP,還有 Cloudflare Tunnel。每次的體驗都讓我嘖嘖稱奇,好像它們預判了我的需求一樣。這家公司始終追求著「更好的網路」這個目標,內容付費又是另一個例子。 🗞️ 熱門新聞 Content Independence Day: no AI crawl without compensation! 賽博佛陀 Cloudflare 又來普渡眾生了。這次是針對 AI 爬蟲收費。 「網路正在改變。它的商業模式也將改變。在這個過程中,我們有機會從過去 30 年網路的優點中學習,並為未來的網路創造更好的環境。 」 Cloudflare 真的很有意思,連思考的角度都很有趣。 內容當然是有價的,只是價格會怎麼支付呢?在現代的內容創作,這題變得非常複雜。 Folklore.org: Joining Apple Computer

By Ken Chen