iT邦幫忙

2026 iThome 鐵人賽

DAY 6
0
Software Development

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

D06:Makefile 搭配 Conan 套件管理器

  • 分享至 

  • xImage
  •  

昨天我們把 Conan 接上了 Xcode。今天是建置系統的最後一篇,輪到非常常見的 Makefile。

寫這篇範例時,我的實測環境:

  • Debian 13 + GCC 13
  • Conan 2.32.0

前兩天一篇是 Windows (Visual Studio)、一篇是 macOS (Xcode),當然今天就輪到 Linux 了,不過這份 Makefile 在 macOS 上也能用。

步驟一:建立專案

請依照以下的目錄結構,自己手動建起來:

hello-conan-make/
├── conanfile.txt
├── Makefile
└── src/
    └── main.cpp

全部就三個檔案。

步驟二:撰寫 conanfile.txt

開啟 conanfile.txt,填入以下內容。

[requires]
fmt/12.2.0
nlohmann_json/3.12.0

[generators]
MakeDeps

[requires] 區塊跟前兩篇一字不差,寫我們想導入的函式庫和版本號碼,一個函式庫一行。我們同樣使用業界廣為使用的 fmt + nlohmann JSON 函式庫作為範例。

[generators] 區塊填入 MakeDeps,告訴 Conan 這次我們要串接 Makefile。

注意:MakeDeps 在 Conan 2 官方文件上還標示為 experimental,以後可能會有改動。

步驟三:執行 Conan Install 安裝套件

開啟命令列,到專案的根目錄,執行以下指令:

conan install . --build=missing --output-folder build

--build=missing 是告訴 Conan 萬一沒辦法從伺服器上找到預編譯好的二進位檔,就抓原始碼下來現場編譯。

--output-folder build 指示 Conan 把產生的檔案放進 build/ 子目錄。

上面這行裝的是 Release 版套件 (Profile 裡預設的),如果你想要 Debug 版的套件,多跑一次conan install 指令加上 -s build_type=Debug 就可以了。

套件安裝完成之後, build/ 底下會多出七個檔案,我們只需關心一個檔案 conandeps.mk

CONAN_DEPS = fmt nlohmann_json

CONAN_INCLUDE_DIRS = $(CONAN_INCLUDE_DIR_FLAG)/home/matt/.conan2/p/b/fmt.../p/include ...
CONAN_LIB_DIRS = $(CONAN_LIB_DIR_FLAG)/home/matt/.conan2/p/b/fmt.../p/lib ...
CONAN_LIBS = $(CONAN_LIB_FLAG)fmt $(CONAN_LIB_FLAG)fmt-c
CONAN_SYSTEM_LIBS = $(CONAN_SYSTEM_LIB_FLAG)m

裡面定義了多個變數,如 CONAN_INCLUDE_DIRS, CONAN_LIB_DIRS 等等,供我們之後使用。

步驟四:撰寫 Makefile

到了重點步驟了,我們要撰寫 Mekfile 檔串接 Conan。以下就是 Makefile 的內容:

CONAN_INCLUDE_DIR_FLAG = -I
CONAN_LIB_DIR_FLAG = -L
CONAN_LIB_FLAG = -l
CONAN_DEFINE_FLAG = -D
CONAN_SYSTEM_LIB_FLAG = -l

include build/conandeps.mk

CXXFLAGS += -std=c++17
CPPFLAGS += $(CONAN_INCLUDE_DIRS) $(CONAN_DEFINES)
LDFLAGS  += $(CONAN_LIB_DIRS)
LDLIBS   += $(CONAN_LIBS) $(CONAN_SYSTEM_LIBS)

build/hello: src/main.cpp
	$(CXX) $(CPPFLAGS) $(CXXFLAGS) $< -o $@ $(LDFLAGS) $(LDLIBS)

.PHONY: clean
clean:
	rm -f build/hello

我們用 include build/conandeps.mk 把 Conan 設定好的那些變數導入,然後依次設定 CPPFLAGSLDFLAGSLDLIBS

然後這裡有個問題,為什麼 Makefile 檔案的開頭的五行,需要設定五個變數呢?

原因是因為啊, make 本身的機制並沒有綁死某個編譯器。比如設定 Include 目錄時,GCC 和 Clang 是用 -I ,而 MSVC 是寫 /I。Conan 無法預測 Makefile 最後會呼叫哪一個編譯器,只能把前綴留空給你填。

開頭那五行把 Conan 留的變數補上,之後就能直接用 $(CONAN_INCLUDE_DIRS) 這些彙總變數,直接一次導入 fmt & nlohmann JSON 的標頭檔目錄位置。

順帶一提,這五行寫在 include 前面或後面其實都可以,make 的變數是用到的時候才展開,放前面只是比較好讀。

另一個容易漏掉的地方就是 C++ 標準的版本。不同於前兩個建置系統,MakeDeps 不會把 profile 裡的 compiler.cppstd 設定值導入,所以 -std=c++17 要自己寫。

步驟五:編譯專案並執行!

main.cpp 原始碼(一如我們前兩天用的同樣程式碼):

#include <fmt/core.h>
#include <nlohmann/json.hpp>

int main() {
    nlohmann::json j = {
        {"name", "Conan"},
        {"language", "Python"},
        {"stars", 9000}
    };

    fmt::print("Hello, {}!\n", j["name"].get<std::string>());
    fmt::print("{}\n", j.dump(2));
    return 0;
}

使用以下命令編譯執行:

make
./build/hello

你就會看到跟前兩篇完全一樣的輸出囉!

Hello, Conan!
{
  "language": "Python",
  "name": "Conan",
  "stars": 9000
}

小結

generators 要串接的檔案
Visual Studio MSBuildDeps + MSBuildToolchain conandeps.propsconantoolchain.props
Xcode XcodeDeps + XcodeToolchain conan_config.xcconfig
Makefile MakeDeps conandeps.mk

走過這三天,其實就幾個重點:

  1. [requires] 這個區塊,就是條列函式庫的地方,不論哪個建構系統寫法都一樣。
  2. [generators] 替換不同的 generators 就能串接不同的建置系統
  3. 這三天都是「Conan 產生設定檔,建置系統去讀」,專案本身不需要知道 Conan 的存在

好啦,建置系統的串接部分,到這裡先告一段落。

明天就來看稍微進階的用法: conanfile.py


上一篇
D05: Xcode 搭配 Conan 套件管理器
系列文
C++ 套件管理器求生指南 Conan vs Vcpkg6
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言