我們知道 C++ 不像很多其他語言有包管理工具,比如 Python 有 pip,Java 有 maven,C# 有 nuget,JS 有 npm,Go 有 go mod,Rust 有 cargo,項目中需要自己手動引入第三方庫,手動維護帶來了很多麻煩。現在 C++ 也有了包管理工具,比如 VCpkg 和 conan,后者 conan 是跨平臺的,支持 Windows、Linux、MacOS 等平臺,并且支持多種編譯器,本文介紹一下如何在項目中引入 conan。
- nlohmann::json/3.11.3
- sqlite3/3.48.0
1. 包管理器 conan
1.1 最小化配置
1.1.1 安裝
Conan 基于 Python3 的工具,安裝好 python3(3.6以上) 后,用 python 的 pip?安裝 conan?很簡單:
pip install conan # windows/linux下
brew install conan # macos下
1.1.2 配置
conan 的配置文件有兩種,一種是?conanfile.txt
?文本文件相當于配置:
[requires]
nlohmann_json/3.11.3
sqlite3/3.48.0[generators]
CMakeDeps
CMakeToolchain
這個配置文件用來配置我們需要的第三方庫,比如指定版本的 nlohmann_json 和 sqlite3。然后?generators
?為我們指定的生成器。
另一種是?conanfile.py
?的 python 腳本文件,我們用這個腳本文件可以結合 python 代碼獲得更靈活的能力:
from conan import ConanFileclass MyProjectConan(ConanFile):name = "mytestproj"version = "0.1"settings = "compiler", "build_type", "arch"generators = "CMakeDeps", "CMakeToolchain"def requirements(self):self.requires("nlohmann_json/3.11.3")self.requires("sqlite3/3.48.0", options={"shared": True})
在項目根目錄下創建?conanfile.py
?文件,在其中的?requirements
?配置我們需要的第三方庫。
NOTE! 這兩種配置文件是互斥的,只能選擇一種。
如果只是比較輕量級使用,可以用?conanfile.txt
?配置文件,否則一般用?conanfile.py
?腳本文件,以獲得最大自由度,比如我們可以寫 python 代碼將生成的?.lib
、.dll
、.so
?和頭文件等拷貝到指定目錄下。
1.1.3 安裝第三方庫
項目根目錄下執行:
conan install .
之后 conan 會在文件根目錄生成?.cmake
、.sh
、.bat
?等等一堆文件,這些文件都是 conan 生成的,用來給項目引入第三方庫的腳本文件,如何引入我們在后面介紹。
上面的方式會在根目錄下生成一堆文件,一般我會在根目錄下放一個?thridparty
?目錄,將 conan 生成的文件都放在這個目錄下,這樣方便管理,然后一些本地的第三方庫或者驅動也用?mklink /d
?命令創建軟鏈接,指向對應文件夾,這樣方便管理。
這是最小化配置的 conan 配置,我們可以在?conanfile.txt
?或?conanfile.py
?中配置更多的選項,比如指定第三方庫的版本、指定第三方庫的構建類型、指定第三方庫的構建選項等等。
下面介紹一下在 VS 項目中如何引入 conan。
2. VS 項目中引入 conan
2.1 修改配置文件
為了指定 conan 將我們的第三方庫生成到指定目錄,并且在生成結束后,將生成的?.dll
?動態庫文件復制到可執行文件同級目錄,需要對?conanfile.py
?進行一些改動:
import os
from conan import ConanFile
from conan.tools.files import copyclass MyProjectConan(ConanFile):name = "cef_131_mytest"version = "0.1"settings = "os", "compiler", "build_type", "arch"generators = "MSBuildDeps", "MSBuildToolchain"def requirements(self):self.requires("nlohmann_json/3.11.3")self.requires("sqlite3/3.48.0", options={"shared": True})def layout(self):self.folders.generators = os.path.join("thirdparty", "conan")self.folders.build = os.path.join("thirdparty", "conan", "build")def deploy(self):print(f" -->deploying env: arch={self.settings.arch}, build_type={self.settings.build_type}")source_dir = os.path.join(self.dependencies["sqlite3"].package_folder, "bin")print(f" -->deploy source_dir: {source_dir}")# 動態生成目標路徑(如 x64/Debug 或 x64/Release)arch = "x64" if self.settings.arch == "x86_64" else "x86"target_dir = os.path.join(os.getcwd(), arch, str(self.settings.build_type))print(f" -->deploy target_dir: {target_dir}")# 復制 DLL 到項目輸出目錄dll_files = [f for f in os.listdir(source_dir) if f.endswith(".dll")]for dll_file in dll_files:print(f" --> Copying {dll_file}")copy(self, dll_file, src=source_dir, dst=target_dir)
由于是 VS 項目,所以配置文件的 generators 使用的是 MSBuild 構建工具鏈。
然后在項目根目錄下:
conan install . -s build_type=Debug --build=missing --deployer-package=*
如果是 Release 模式:
conan install . -s build_type=Release --build=missing --deployer-package=*
此時會在?thirdparty/conan
?目錄下生成?conandeps.props
?等 VS 屬性表,然后我們可以通過公共配置文件的方式引入生成的 VS 屬性表,關于 VS 公共配置文件的使用方式參考?<C++ 中 VS 項目引入公共配置文件>
2.2 引入 VS 項目
對于上面的 generators 為?"MSBuildToolchain", "MSBuildDeps"
,使用的是 Microsoft Visual Studio 的 MSBuild 編譯工具鏈,此時在?conan install
?命令會生成?props
?文件供 VS 引入,如果使用的 generators 是?"CMakeToolchain", "CMakeDeps"
,那么會生成 CMake 相關的一系列文件,可以從?CMakeLists.txt
?文件中引入 conan 管理的庫。
其中:
-Deps
:為三方庫的所有依賴項生成 CMake 配置文件;-Toolchain
:根據傳遞給 conan 的系統、編譯器、架構等信息,生成 CMake 構建三方庫所需的所有信息。還會生成 cmake-presets 文件,以供一些 IDE 集成。
現在我們要引入的配置文件是 conan 在 install 的時候生成的?conandeps.props
,在項目配置?.vcxproj
?中加入:
<Import Project="$(SolutionDir)\thirdparty\conan\conandeps.props" Condition="exists('$(SolutionDir)\thirdparty\conan\conandeps.props')" Label="conandeps" />
這個?conandeps.props
?文件會導入 conan 給每個引入的第三方庫生成的 props 配置文件:
第三方庫的 props 配置文件中會分別引入其 Debug 和 Rlease 版本的目錄配置和變量配置,其中指定了將第三方庫目錄和包含目錄存放的具體位置,在項目?.vcxproj
?中cli引入?conandeps.props
?之后重啟 VS,就可以從 conan 的緩存目錄里直接?#include
?相應庫的頭文件了。
網上的帖子大多深淺不一,甚至有些前后矛盾,在下的文章都是學習過程中的總結,如果發現錯誤,歡迎留言指出,如果本文幫助到了你,別忘了點贊支持一下,你的點贊是我更新的最大動力!~