QtCreator中如何使用Conan包管理工具
要點
- Conan本身是一個包管理工具, 類似Pyhon的pip, 本身用Python編寫
- QT 6.0 開始引入Conan插件, 從個人觀察來看, 似乎該插件僅僅引入了cmake腳本文件
- Conan本身不依賴QtCreator, 可以隨意使用, 其他編譯環(huán)境可以忽略掉本文章所有關(guān)于QT的內(nèi)容, 其他不變
一 準備環(huán)境, 安裝Conan
1.1 安裝Python 3 及 pip3
2 brew install python3
3 curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
4 sudo python get-pip.py
5
6 python3 -m pip install --upgrade pip
7 python3 -m pip conan
8
9 #對于QtCreator, 此步驟必須, 否則會找不到conan指令
10 ln -s /opt/homebrew/bin/conan /usr/local/bin
11
12 conan --version
13 > Conan version 1.41.0
以上為OSX 環(huán)境安裝步驟, 依賴brew, brew環(huán)境搭建見
鏈接
Windows 建議使用 官方
MSI安裝包
安裝, 并勾選 pip組件linux建議使用
apt-get
yum
pacman
之類的包管理工具安裝
二 設(shè)置Qt Creator
- Mac : 菜單
Qt Creator
-->關(guān)于插件
, 在filter中輸入conan, 勾選Conan
插件 - Win : 菜單
幫助
-->關(guān)于插件
, 在filter中輸入conan, 勾選Conan
插件
三 測試樣例
- 創(chuàng)建Qt工程, 此處選擇
Application (Qt Quick)
-->Qt Quick Application -Empty
, 構(gòu)建方式選CMake
- 在工程
根目錄
下創(chuàng)建 conanfile.txt, 錄入: -
1 [requires]
2 picojson/1.3.0
3
4 [generators]
5 cmake
- 在工程根目錄下執(zhí)行
mkdir build && cd build && conan install .. && cd -
- 在CMakeLists.txt 輸入:
1 # 手工修改 第一處
2 ## 引入conan install產(chǎn)生的 cmake腳本
3 include(${CMAKE_CURRENT_SOURCE_DIR}/build/conanbuildinfo.cmake)
4 ## 引入腳本中創(chuàng)建的編譯環(huán)境變量
5 include_directories(${CONAN_INCLUDE_DIRS_PICOJSON})
6 link_directories(${CONAN_LIB_DIRS_PICOJSON})
7
8 find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Quick LinguistTools REQUIRED)
9 find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Quick LinguistTools REQUIRED)
10
11 # 手工修改第二處
12 if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
13 qt_add_executable(RantionMidiCenter
14 MANUAL_FINALIZATION
15 ${PROJECT_SOURCES}
16 )
17 ## link conan引入的picojson靜態(tài)庫, 需要時使用
18 target_link_libraries(main ${CONAN_LIBS_PICOJSON})
19
20 qt_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
21 else()
22 if(ANDROID)
23 add_library(RantionMidiCenter SHARED
24 ${PROJECT_SOURCES}
25 )
26 else()
27 add_executable(RantionMidiCenter
28 ${PROJECT_SOURCES}
29 )
30 endif()
31
32 ## link conan引入的picojson靜態(tài)庫, 需要時使用
33 target_link_libraries(main ${CONAN_LIBS_PICOJSON})
34
35 qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
36 endif()
37
38
39 ## CONAN_LIBS_PICOJSON 中的 `CONAN_LIBS_xxxx` 可以替換成引入的其他庫名稱
- 在
main.cpp
頭部輸入:1 #ifndef PICOJSON_USE_INT64
2 #define PICOJSON_USE_INT64
3 #include <picojson.h>
4 #endif至此就可以隨意使用picojson.h中的功能了
上述范例引入了一個
header only
的工具庫 picojson.h, 僅用于演示功能, 實際上CONAN_LIB_DIRS_PICOJSON
與CONAN_LIBS_PICOJSON
變量在CmakeLists
文件中的引入動作并無必要
四 2. 自建軟件包
因為很多第三方開源項目沒有 Conan 官方的支持,使用這些項目的時候就需要自己來編寫 Receipe 來告訴 Conan 如何編譯、打包第三方庫了。
Conan打包過程
這里以bgfx為例來構(gòu)造一個 Conan 的二進制包,并提交到我們自建的私倉中。
因為bgfx官方構(gòu)建方式比較復(fù)雜,筆者選取了其 CMake 版本來執(zhí)行構(gòu)建。此外 Github 上已經(jīng)有用戶創(chuàng)建過對應(yīng)的構(gòu)建腳本了,因此這里可以直接參考別人的寫法來進行構(gòu)建。
使用 conan new Hello/0.1 -t
可以創(chuàng)建一個 HelloWorld 的空白 Receipe。可以看到呈現(xiàn)出這樣的目錄結(jié)構(gòu):
test_package
CMakeLists.txt
conanfile.py
example.cpp
其中conanfile.py
用來描述構(gòu)建軟件包的編譯打包過程,test_package
存儲一個測試用的樣例,用來檢查是否成功構(gòu)建了軟件包并且是否能正常使用。
以構(gòu)建bgfx
的腳本為例,修改conanfile.py
:
2 from distutils.dir_util import copy_tree
3
4 class BgfxConan(ConanFile):
5 name = "bgfx"
6 version = "20190604.018bbc4" # 這個地方我亂填的,請遵照SemVer的規(guī)范制定版本號
7 description = "Conan package for bgfx."
8 url = "https://github.com/9chu/bgfx-conan"
9 license = "BSD"
10 settings = "arch", "build_type", "compiler", "os" # 這些選項會被作為包的標識,區(qū)分不同的ABI
11 generators = "cmake"
12 options = {"shared": [True, False]}
13 default_options = "shared=False"
14
15 def source(self):
16 self.run("git clone https://github.com/JoshuaBrookover/bgfx.cmake")
17 copy_tree("bgfx.cmake", ".")
18 self.run("git reset --hard 018bbc4")
19 self.run("git submodule update --init --recursive")
20
21 def build(self):
22 cmake = CMake(self)
23 shared_options = "-DBUILD_SHARED_LIBS=ON" if self.options.shared else "-DBUILD_SHARED_LIBS=OFF"
24 fixed_options = "-DBGFX_BUILD_EXAMPLES=OFF"
25 tool_options = "-DBGFX_BUILD_TOOLS=OFF" if self.settings.os == "Emscripten" else ""
26 opengl_version = "-DBGFX_OPENGL_VERSION=33"
27 self.run("cmake %s %s %s %s %s" % (cmake.command_line, shared_options, fixed_options, tool_options, opengl_version))
28 self.run("cmake --build . %s -j8" % cmake.build_config)
29
30 def collect_headers(self, include_folder):
31 self.copy("*.h" , dst="include", src=include_folder)
32 self.copy("*.hpp", dst="include", src=include_folder)
33 self.copy("*.inl", dst="include", src=include_folder)
34
35 def package(self):
36 self.collect_headers("bgfx/include")
37 self.collect_headers("bimg/include")
38 self.collect_headers("bx/include" )
39 self.copy("*.a" , dst="lib", keep_path=False)
40 self.copy("*.so" , dst="lib", keep_path=False)
41 self.copy("*.lib", dst="lib", keep_path=False)
42 self.copy("*.dll", dst="bin", keep_path=False)
43
44 def package_info(self):
45 self.cpp_info.libs = ["bgfxd", "bimgd", "bxd"] if self.settings.build_type == "Debug" else ["bgfx", "bimg", "bx"]
46 self.cpp_info.libs.extend(["astc-codec", "astc", "edtaa3", "etc1", "etc2", "iqa", "squish", "nvtt", "pvrtc"])
47 if self.settings.os == "Macos":
48 self.cpp_info.exelinkflags = ["-framework Cocoa", "-framework QuartzCore", "-framework OpenGL", "-weak_framework Metal"]
49 if self.settings.os == "Linux":
50 self.cpp_info.libs.extend(["GL", "X11", "pthread", "dl"])
可以看到整個腳本分為若干個函數(shù)。其中:
source 函數(shù)
,用于源代碼拉取和準備,比如對源碼進行一些修改;build 函數(shù)
,調(diào)用 CMake 進行構(gòu)建;package 函數(shù)
,用于執(zhí)行打包操作;package_info
則用于輸出構(gòu)建相關(guān)的信息,比如需要鏈接包中的哪些庫文件。
默認的,Conan 以lib
、include
、bin
等文件夾標識頭文件庫文件目錄,也可以在package_info函數(shù)
中進行修改。此外,Conan 提供了一系列的驅(qū)動包裝函數(shù)來執(zhí)行各種第三方工具,以及定制版本號規(guī)則、設(shè)定依賴等等。具體可以通過查閱官方文檔來進一步了解,本文僅作拋磚引玉的目的。
在構(gòu)建完成后,Conan 會以 Settings
和 Options
的取值 Hash 后為軟件包指定一個 package_id
,因而不同的構(gòu)建選項會對應(yīng)到不同的 Id 上。最終拉取預(yù)編譯包時就會以這個 Id 作為基準。因此,如果構(gòu)建一個 Header-Only 的包,則可以去掉這些選項,這樣在各個平臺上都不需要額外構(gòu)建即可使用了。
編寫完 Receipe 后,就可以執(zhí)行 Conan 來進行構(gòu)建了。
conan install bgfx/20190604.018bbc4@9chu/stable --build=bgfx
構(gòu)建完成后會自動執(zhí)行test_package
的內(nèi)容進行測試。最后使用命令上傳到我們的私倉:
conan upload bgfx/20190604.018bbc4@9chu/stable --all -r=my_local_server
然后,我們就能在 Artifactory 中看到我們提交的包了。
配合 CMake 實戰(zhàn)
上傳完自己制作的包,接下來就可以將其作為依賴引入自己的項目之中了。
在這里,推薦使用 Conan 官方提供的 CMake 腳本將其引入項目中。
2 project(test CXX)
3
4 ######################################## conan package manager ########################################
5
6 # Download automatically, you can also just copy the conan.cmake file
7 if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
8 message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
9 file(DOWNLOAD "https://github.com/conan-io/cmake-conan/raw/v0.14/conan.cmake"
10 "${CMAKE_BINARY_DIR}/conan.cmake")
11 endif()
12
13 include(${CMAKE_BINARY_DIR}/conan.cmake)
14
15 ######################################## dependencies ########################################
16
17 conan_cmake_run(
18 REQUIRES
19 bgfx/20190604.018bbc4@9chu/stable
20 BASIC_SETUP CMAKE_TARGETS
21 BUILD missing)
22
23 ######################################## compiler flags ########################################
24
25 set(CMAKE_CXX_STANDARD 11)
26
27 if(MSVC)
28 add_definitions(-D_WIN32_WINNT=0x0600 -D_GNU_SOURCE -D_CRT_SECURE_NO_WARNINGS)
29 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /utf-8")
30 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /utf-8")
31 else()
32 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -Wextra -Wno-implicit-fallthrough")
33 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Wall -Wextra -Wno-implicit-fallthrough")
34 endif()
35
36 ######################################## targets ########################################
37
38 file(GLOB_RECURSE TEST_SRC ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
39
40 add_executable(test ${TEST_SRC})
41 target_include_directories(test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
42 target_link_libraries(test CONAN_PKG::bgfx)
通過 conan_cmake_run
來直接指定依賴,這樣就不需要寫 conanfile.txt
并且會在 CMake 構(gòu)建的時候自動把依賴安裝上,集成到 CMake 中,非常的方便。
此外,由于使用了CMAKE_TARGETS
模式,依賴的指定方法也變成了CONAN_PKG::bgfx
的方式,這里可以根據(jù)需要自行調(diào)整。
附錄1 Conan常用指令
# 在遠程倉庫搜索 picojson庫, 包名支持通配符, 官方倉庫為conancenter, conan-center已廢棄
conan search picojson -r all
conan search picojson -r conancenter
conan search boost* -r conancenter
# 在本地緩存搜索 picojson庫
conan search picojson
# 查看picojson/1.3.0包的詳細信息, picojson為包名, 1.3.0為版本號
conan inspect picojson/1.3.0
# 根據(jù) ..目錄的conanfile.txt文件, 下載依賴包
conan install ..
# 遠端管理
## 查閱所有遠程倉庫配置
conan remote list
## 添加源
conan remote add my-repo http://my-repo.com/xxx
# 或者使用insert來將其作為首個源
conan remote update my-repo http://my-repo.com/xxx --insert=0
# 刪除一個源
conan remote remove my-repo
附錄2 自建倉庫
Conan 官方提供了一個迷你的服務(wù)端來提供倉庫的功能,同時也推薦使用Artifactory Community Edition for C/C++來自建倉庫。當(dāng)然,如果是為了開源項目,可以直接在 Bintray 上申請一個開源項目賬號來上傳自制軟件包而無需自建倉庫(但是實在是太慢了)。
本文使用 Artifactory 來自建倉庫,因為功能相對完善。Artifactory 支持配置用戶和組以及對應(yīng)的權(quán)限,商業(yè)版本還支持高可用和分布式。
安裝
sudo docker pull docker.bintray.io/jfrog/artifactory-cpp-ce
sudo docker run -d --restart=always \
--name artifactory \
-v /data/artifactory:/var/opt/jfrog/artifactory \
-p 8081:8081 \
-e EXTRA_JAVA_OPTIONS='-Xms512m -Xmx2g -Xss256k -XX:+UseG1GC' \
docker.bintray.io/jfrog/artifactory-pro:latest
暴露在本機的8081端口上,同時掛載數(shù)據(jù)目錄到/data/artifactory目錄下
注意: Artifactory 默認會以
UserID 1030
運行服務(wù),一定要注意宿主機的數(shù)據(jù)目錄的權(quán)限是否滿足要求,如果啟動時出現(xiàn) Permission Denied 錯誤,請修改目錄權(quán)限:sudo chown 1030:1030 /data/artifactory sudo chmod 0755 /data/artifactory
你也可以使用
--user 1234:4321
的方式來指定 Docker 使用哪個用戶
/組
權(quán)限來執(zhí)行容器。
配置
首次訪問 http://localhost:8081 即可打開配置向?qū)АDJ的,配置好 Admin 賬戶的密碼,初始化默認的 Conan 倉庫配置即可。向?qū)崾灸銊?chuàng)建一個 HTTP Proxy,如果網(wǎng)絡(luò)夠好或者只作私倉使用則可以忽略該配置,否則,建議創(chuàng)建一個代理設(shè)置來加速訪問 Remote 倉庫。
Artifactory 提供了三種類型的 Conan 倉庫供不同目的使用:
- 本地倉庫(Local):即當(dāng)前 Artifactory 服務(wù)器上存儲軟件包的倉庫;
- 遠端倉庫(Remote):即第三方的軟件倉庫,在本服務(wù)器上作為 Proxy 和 Cache 運作;
- 虛擬倉庫(Virtual):作為一個索引中心,能將其他兩類倉庫整合到一個倉庫名下,方便使用。
初始化之后,Artifactory 會創(chuàng)建好一個本地倉庫,一個到 Conan Center 的遠程倉庫和包含上述兩個倉庫的虛擬倉庫。
需要注意的是,默認配置下 Artifactory 是允許匿名訪問的,必須在 Admin > Security Configuration 頁面中關(guān)閉匿名訪問才能真正作為私倉使用。
添加到 Conan
在倉庫管理頁面,點擊虛擬倉庫 Conan
,在右上角點擊 Set Me Up
按鈕即可顯示當(dāng)前倉庫如何在 Conan 中配置并作為一個源。
posted on 2021-10-19 16:09 Khan 閱讀(3163) 評論(0) 編輯 收藏 引用 所屬分類: GCC/G++ 、跨平臺開發(fā)