手動管理 C/C++ 套件
想像你需要使用 LLVM 開發一個程式,如果在 macOS 上,最簡單的安裝方法是用 Homebrew,一行就搞定: brew install llvm
。但 Homebrew 上的版本不一定是最新的而且也無法同時安裝不同的版本 (例如 LLVM 5.0/6.0 共存) 或同版本但不同設置(例如 LLVM 6.0 的 debug/release 版本);而在 Linux 及 Windows 上也有各自不同的安裝問題。
安裝完畢後,麻煩才剛開始:通常第一步是設置編譯環境的 CPPFLAGS 及 LDFLAGS:
For compilers to find this software you may need to set:
LDFLAGS: -L/usr/local/opt/llvm/lib
CPPFLAGS: -I/usr/local/opt/llvm/include
根據不同的開發環境或編譯器,設置的方法也都不同。最後設置完後編譯及連結也不一定能成功,因為 LLVM 本身可能又依賴其他套件,還需要把它的 dependencies 一一安裝及設置。
Conan 介紹
Conan 企圖幫助 C/C++ 脫離這個窘境:沒有一個像樣的套件管理 (package management) 工具。
我建議先讀一下 Conan 的文檔來了解如何安裝 Conan 以及利用 Conan 來使用現成的程式庫。
如果你是使用 CMake,事情會簡單一些,因為 Conan 提供的 CMake 整合還算好用,使用範例可以參考這個基於 LLVM 的小程式: clike。
下載套件
除了預設的 conan-center
,Conan 官網建議也可以到 bincrafters
及 conan-community
裡尋找,可以用下列指令新增這兩個 remote:
$ conan remote add conan-community https://api.bintray.com/conan/conan-community/conan
$ conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan
之後就可以指定 remote 搜尋 package:
$ conan search ffmpeg -r=bincrafters
Existing package recipes:
ffmpeg/3.4@bincrafters/stable
目前 server 上面的套件數量不算多,有可能你會找不到你想要的,因此你不能期待很快地有人會幫你做出來,相反地你必須學會自己創建套件才能充分得到使用 Conan 的好處。
創建 package
自己創建一個套件其實也不難,基本的概念如下:
整個建置過程需要的目錄結構及流程會是由 Conan 來控制,但你需要提供一個 conanfile.py 描述每個步驟裡的需要執行的動作。Conan 會把打包的套件放在一個 local cache 裡讓其他的程式來使用。
以下示範如何下載 LLVM 6.0 的原始碼, 編譯,最後把它包裝成套件:
from conans import ConanFile, CMake
import glob
import os
class LlvmConan(ConanFile):
name = "LLVM"
version = "release_60"
license = "LLVM Release License"
url = "https://github.com/p47r1ck7541/llvm-60"
description = "%s %s" % (name, version)
settings = "os", "compiler", "build_type", "arch"
generators = "cmake"
def source(self):
self.run("git clone https://github.com/llvm-mirror/llvm -b %s --depth 1 src" % self.version)
def build(self):
cmake = CMake(self)
cmake.configure(source_folder="src")
cmake.install()
def package(self):
# nothing to do here now because we reuse 'cmake install' to package files
pass
def package_info(self):
self.cpp\_info.libs = \[os.path.basename(a) for a in glob.glob(os.path.join(self.package\_folder, "lib", "*.a"))\]
self.cpp_info.cppflags = \["-std=c++11", "-fno-rtti"\]
self.cpp_info.exelinkflags = \["-lcurses", "-lz"\]
幾個關鍵步驟:
source()
: 利用git clone
下載原始碼build()
: 負責編譯,這裏我們直接使用 Conan 提供的 CMake class 來控制 cmake 的執行,值得注意的是我們直接利用cmake.install()
來取代實際打包套件的工作。package()
: 如上解釋,不需做任何事。package_info()
: 提供套件的相關使用資訊。例如cppflags
及exelinkflags
是寫死的,但libs
則是運行 Python script 搜尋編譯結果找出來的。
完整範例可以參考這個 GitHub project: conan-llvm-60。
實際運作過程如下(中間請自行快轉):
總結
就簡化自己手動管理 C/C++ 套件的工作來看,我認為 Conan 提供的好處值得你花時間去學它,至於它是否能成為主流的 C/C++ 套件管理工具,那就等待時間來驗證了。