- 一、cmake模板
- 二、引數設定
- 三、命令解釋
- 3.1 find命令
- 3.2 file 執行與檔案和目錄相關的操作
- 3.3 自定義命令
- 3.4 配置檔案
- 四、自動化測試
- 五、安裝
- 5.1 Linux的rpath機制
- 5.2
CMAKE_INSTALL_RPATH
的使用案例 - 5.3
CMAKE_BUILD_RPATH
的使用案例
- 六、閉源包引用
- 七、vcpkg包管理
- 6.1 安裝
- 6.2 vcpkg.json
- 6.3 多包管理器共存
一、cmake模板
|--CMakeLists.txt
|--extern
|--src
|--|--subsrc1
|--|--|--CMakeLists.txt
|--|--subsrc2
|--|--|--CMakeLists.txt
|--|--main.cc
|--|--CMakeLists.txt
|--test
|--|--CMakeLists.txt
|--vcpkg.json
根目錄的CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(PROJECT_XXX VERSION 0.0.0 )
#C/C++標準
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 14)
#設定編譯器
set (CMAKE_C_COMPILER "/usr/bin/gcc")
set (CMAKE_CXX_COMPILER "/usr/bin/g++")
######### build 變數 #####
set(CMAKE_BUILD_TYPE Debug#[[Release | Debug| RelWithDebInfo |MinSizeRel]])
set(CMAKE_BUILD_PARALLEL_LEVEL 4)#編譯處理器數量
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)#clang
set(CMAKE_GENERATOR "Unix Makefiles")#“Ninja”、“Unix Makefiles”、“Visual Studio”
#add_compile_options()#等同CMAKE_CXXFLAGS_RELESE,前者可以對所有的編譯器設定,後者只能是C++編譯器
########## vcpkg #######
#set(CMAKE_TOOLCHAIN_FILE $ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake)
#set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH};${CMAKE_SOURCE_DIR}/vcpkg_installed/x64-linux/lib/pkgconfig")
#lib&&bin輸出目錄
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/build/bin)#可執行檔案
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/build/lib)#動態庫
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/build/lib/static)#靜態庫
###### sub directory #####
add_subdirectory(src)
#add_subdirectory(external)
########## TEST ##########
if(FALSE)
enable_testing()
add_subdirectory(test)
add_test(NAME test COMMAND ${PROJECT_NAME} -arg1 -arg2)
endif()
########## istanll #######
set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR}/install)
# 1.target 放到 DESTINATION 指定的目錄
#install(TARGETS ... RUNTIME DESTINATION bin)#exe
#install(TARGETS ... LIBRARY DESTINATION lib)#*.so
#install(TARGETS ... ARCHIVE DESTINATION lib/static)#*.lib
#install(TARGETS ... PUBLIC_HEADER DESTINATION include)#公共標頭檔案的安裝路徑
#install(TARGETS ... RESOURCE DESTINATION <dir>)#私有標頭檔案的安裝路徑
# 2.普通檔案 放置放到 DESTINATION 指定的目錄,eg:readme.md config.ini
#install(FILES ... DESTINATION etc)
# 3.目錄
#install(DIRECTORY ... DESTINATION ...)
# 4.指令碼 放置到 DESTINATION 指定的目錄,eg:install.sh
#install(PROGRAMS ... DESTINATION ...)
# 5.target集合
#install(TARGETS ... EXPORT export_name RUNTIME DESTINATION bin)#exe
#install(EXPORT export_name NAMESPACE namespace DESTINATION <dir>)
########## PACK ##########
if(FALSE)
# 安裝包名稱
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
# 版本號
set(CPACK_PACKAGE_VERSION "1.0.0")
# 描述資訊
set(CPACK_PACKAGE_DESCRIPTION "My awesome application")
# 許可證
set(CPACK_RPM_PACKAGE_LICENSE "Apache 2.0 + Common Clause 1.0")
# vendor
set(CPACK_PACKAGE_VENDOR "vesoft")
# 安裝包圖示
#set(CPACK_PACKAGE_ICON )
#配置軟體包型別和生成器ZIP、TGZ、RPM、NSIS
set(CPACK_GENERATOR ZIP)#二進位制包
#set(CPACK_SOURCE_GENERATOR ZIP)#原始碼包
#安裝系統依賴庫
include(InstallRequiredSystemLibraries)
#安裝安裝包時的依賴關係
#set(CPACK_DEBIAN_PACKAGE_DEPENDS "")#Debian自動安裝依賴
#set(CPACK_RPM_PACKAGE_REQUIRES "")
#新增指令碼和配置
#set(CPACK_PRE_INSTALL_SCRIPTS "${CMAKE_CURRENT_SOURCE_DIR}/pre_install_script.sh")#安裝前,目錄許可權
#set(CPACK_POST_INSTALL_SCRIPTS "${CMAKE_CURRENT_SOURCE_DIR}/post_install_script.sh")#安裝後,systemctl自啟動指令碼
# 設定支援指定安裝目錄的控制為 ON;設定安裝到的目錄路徑
#set(CPACK_SET_DESTDIR ON)
#set(CPACK_INSTALL_PREFIX )
include(CPack)
endif()
LIB
######### Target LIB #########
aux_source_directory(目錄 LIBS_SRC_LISTS)
set(LIBS_NAME )
add_library(${LIBS_NAME } "")#預設是STATIC
target_include_directories(${LIBS_NAME} PRIVATE )
target_sources(${LIBS_NAME} PRIVATE ${LIBS_SRC_LISTS})
#target_link_libraries(${LIBS_NAME} )
target_compile_options(${LIBS_NAME} PRIVATE -Wall
-O3 -std=c++11 )
target_compile_definitions(${LIBS_NAME} PRIVATE
CMAKE_BUILD_TYPE=Release
CMAKE_EXPORT_COMPILE_COMMANDS=ON)
EXE
######### Target EXE #########
aux_source_directory(目錄 EXE_SRC_LISTS)
add_executable(${PROJECT_NAME} )
#target_include_directories(${PROJECT_NAME} RIVATE )
target_sources(${PROJECT_NAME} PRIVATE ${EXE_SRC_LISTS})
#target_link_libraries(${PROJECT_NAME} )
target_compile_options(${PROJECT_NAME} RRIVATE -Wall
-O3 -std=c++11 )
target_compile_definitions(${PROJECT_NAME} PRIVATE
CMAKE_BUILD_TYPE=Release
CMAKE_EXPORT_COMPILE_COMMANDS=ON)
FIND
######### FIND FILE #######
#find_package(Eigen3 REQUIRED)
#find_path (<VAR> name1 [path1 path2 ...])
#find_file (<VAR> name1 [path1 path2 ...])
#find_library (<VAR> name1 [path1 path2 ...])
vcpkg
######### VCPKG #########
set(CMAKE_TOOLCHAIN_FILE $ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake)
#增加*.cmake的尋找路徑
#list(APPEND CMAKE_PREFIX_PATH ${CMAKE_SOURCE_DIR}/vcpkg_installed/x64-linux/share/gtest)
find_package(Boost REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES})
####### 清單pkgconfig模式 ###
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBRARY_NAME REQUIRED libname)#變數 libname.pc
target_include_directories(${TARGET_NAME} ${LIBRARY_NAME_INCLUDE_DIRS})#標頭檔案目錄
target_link_directories(${PROJECT_NAME} PRIVATE ${LIBRARY_NAME_INCLUDE_DIRS})#連結目錄
target_link_libraries(${TARGET_NAME} ${LIBRARY_NAME_LIBRARIES})#連結庫
閉源庫
######### 閉源庫 ##########
add_library(${LIBNAME} STATIC IMPORTED)
set_property(TARGET ${LIBNAME} PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/extern/{LIBNAME}/lib-vc2019/glfw3.lib)
target_include_directories( ${LIBNAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}/extern/${LIBNAME}/include)
test
二、引數設定
編譯選項
CMAKE_BUILD_TYPE Release | Debug| RelWithDebInfo |MinSizeRel
三、命令解釋
3.1 find命令
find_path:用於找到指定檔案或目錄路徑的命令(安裝ini檔案)
find_path(<VAR> name1 [path1 path2 ...])
eg:
find_path(STDIO_H_INCLUDE_DIR stdio.h
/usr/include
/usr/local/include)
其中,<VAR>
是用於儲存找到的路徑的變數名。name1
是要查詢的檔案或目錄的名稱。path1
,path2
等是可選的搜尋路徑。
find_path命令特別適用於需要在構建過程中動態查詢標頭檔案路徑的情況
find_file:用於查詢指定檔案的路徑
find_file(<VAR> name1 [path1 path2 ...])
eg:
find_file(EXAMPLE_FILE example.txt)
執行上述命令後,如果找到了example.txt檔案,路徑將儲存在EXAMPLE_FILE變數中,否則該變數將為空。
find_file(EXAMPLE_FILE example.txt
/usr/data
/home/user/data
)
這將在/usr/data和/home/user/data目錄下搜尋example.txt檔案
其中,<VAR>
是一個變數,用於儲存找到的檔案路徑。name1
是要查詢的檔案的名稱。path1
,path2
等是可選的搜尋路徑。
find_library:用於查詢指定庫檔案的路徑
find_library(<VAR> name1 [path1 path2 ...])
其中,<VAR>
是用於儲存找到的庫檔案路徑的變數名。name1
是要查詢的庫檔案的名稱(不包括字首lib
和副檔名)。
使用案例
cmake_minimum_required(VERSION 3.12)
project(MyProject)
# 查詢名為 mylibrary 的庫檔案
find_library(MYLIBRARY_LIB mylibrary)
# 如果找到了庫檔案
if(MYLIBRARY_LIB)
message("Found mylibrary at: ${MYLIBRARY_LIB}")
# 新增庫檔案的路徑到連結器
target_link_libraries(MyExecutable ${MYLIBRARY_LIB})
else()
message(FATAL_ERROR "mylibrary not found")
endif()
find_program:用於查詢指定可執行程式的路徑
find_program(<VAR> name1 [path1 path2 ...])
eg:
find_program(MYPROGRAM_EXECUTABLE myprogram
/usr/bin
/usr/local/bin
)
這將在/usr/bin
和/usr/local/bin
目錄下搜尋myprogram
可執行程式。
使用案例
cmake_minimum_required(VERSION 3.12)
project(MyProject)
# 查詢名為 myprogram 的可執行程式
find_program(MYPROGRAM_EXECUTABLE myprogram)
# 如果找到了可執行程式
if(MYPROGRAM_EXECUTABLE)
message("Found myprogram at: ${MYPROGRAM_EXECUTABLE}")
# 在構建過程中使用可執行程式
add_custom_target(run_myprogram COMMAND ${MYPROGRAM_EXECUTABLE})
else()
message(FATAL_ERROR "myprogram not found")
endif()
在這個案例中,假設我們的專案想要執行名為myprogram
的可執行程式。
透過find_program(MYPROGRAM_EXECUTABLE myprogram)
命令,CMake會嘗試在系統的預設可執行程式搜尋路徑中找到名為myprogram
的可執行程式。
如果成功找到了可執行程式,CMake會將路徑儲存在變數MYPROGRAM_EXECUTABLE
中,並透過add_custom_target
命令定義一個自定義目標,使得我們可以在構建過程中使用該可執行程式。
如果未找到可執行程式,則會輸出錯誤訊息並終止構建過程
find_package: CMake中用於查詢和載入第三方庫的命令
使用案例
cmake_minimum_required(VERSION 3.12)
project(MyProject)
# 查詢並載入 OpenCV
find_package(OpenCV 4 REQUIRED)
# 檢查是否找到庫
if(OpenCV_FOUND)
message("Found OpenCV version ${OpenCV_VERSION}")
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(MyApp main.cpp)
target_link_libraries(MyApp ${OpenCV_LIBS})
else()
message(FATAL_ERROR "OpenCV not found")
endif()
# 新增其他專案配置和構建指令...
變數
<PackageName>_FOUND
:
表示是否找到了指定的庫。它是一個布林值,如果找到了庫,則為TRUE
,否則為FALSE
。<PackageName>_VERSION
:
當找到庫時,它表示所找到的庫的版本號。該值可能是一個字串或一個列表。<PackageName>_INCLUDE_DIRS
:
包含著所找到的庫的標頭檔案路徑的變數。這允許您在專案中包含庫的標頭檔案。<PackageName>_LIBRARIES
:
儲存了所找到的庫的完整庫檔案路徑的變數。透過這個變數,您可以將所需的庫連結到專案的可執行檔案或庫中。這些變數的命名約定在不同的
Find
模組中可能會有所不同,因此請查閱庫的相關文件來獲取詳細的變數名稱和用途。
3.2 file 執行與檔案和目錄相關的操作
它可以用於建立、複製、刪除、重新命名、讀取檔案內容等操作。以下是一些 file()
命令的常見用法:
-
file(COPY ...)
:
將指定的檔案或目錄複製到指定的目標目錄下。該命令可以用於將檔案複製到構建目錄或安裝位置。file(COPY source_file DESTINATION destination_directory)
-
file(REMOVE ...)
:
刪除指定的檔案或目錄。file(REMOVE file_path)
-
file(RENAME ...)
:
將檔案或目錄重新命名。file(RENAME old_name new_name)
-
file(READ ...)
:
讀取檔案內容到變數中。file(READ file_path variable_name)
-
file(WRITE ...)
:
將字串內容寫入檔案中。file(WRITE file_path "content")
-
file(APPEND ...)
:
將字串內容追加到檔案末尾。file(APPEND file_path "content")
這只是 file()
命令的一些常見用法示例,實際上它還有很多其他用法,例如建立目錄、查詢檔案、獲取檔案屬性等。您可以在 CMake 官方文件中查詢 file()
命令的完整參考以獲取更詳細的資訊和用法示例。
3.3 自定義命令
在很多時候,需要在cmake
中建立一些目標,如clean
、copy
等等,這就需要透過add_custom_target
來指定。同時,add_custom_command
可以用來完成對add_custom_target
生成的target
的補充。
區別
在CMake中,"add_custom_command"和"add_custom_target"是兩個常用的命令,用於定義自定義編譯命令和自定義構建目標。它們之間的區別如下:
- add_custom_command:
- add_custom_command用於定義在構建時執行的自定義命令。它可以用來生成檔案、生成程式碼、執行指令碼等。add_custom_command通常被用作目標的依賴項。
- add_custom_command並不會建立真正的構建目標,它僅僅是一個構建過程中執行的命令。因此,預設情況下,add_custom_command不會導致重新構建整個專案。
- add_custom_target:
- add_custom_target用於定義一個構建目標,該目標不與實際的檔案或輸出相關聯,而是與一組其他規則相關聯。
- add_custom_target可以用來執行一系列自定義命令或構建步驟。它對於組織和管理構建過程非常有用。
- add_custom_target通常用作構建系統的入口點,透過依賴其他目標和規則來執行自定義構建任務。
總結來說,add_custom_command用於定義構建過程中的自定義命令,而add_custom_target用於定義自定義構建目標。兩者可以結合使用,以實現更復雜的構建邏輯。
add_custom_target:自定義構建目標
add_custom_target(Name [ALL] [command1 [args1...]]
[COMMAND command2 [args2...] ...]
…
)
# Name:定義的target的名字
# COMMAND:該target要執行的命令
add_custom_target(
target_name
[COMMAND command1 [ARGS] [args1...]]
[COMMAND command2 [ARGS] [args2...] ...]
[DEPENDS [depend1...]]
[WORKING_DIRECTORY dir]
[COMMENT comment]
[VERBATIM]
[USES_TERMINAL]
)
其中,常用的引數和選項包括:
target_name:自定義構建目標的名稱。
COMMAND:指定要執行的命令。
DEPENDS:指定自定義目標所依賴的其他目標或檔案。
WORKING_DIRECTORY:設定命令的工作目錄。
COMMENT:新增對命令或目標的註釋。
VERBATIM:保留命令中的跳脫字元,確保按原樣傳遞給底層的構建工具。
USES_TERMINAL:指示命令是否會使用終端。
透過使用 add_custom_target,可以在構建過程中定義各種自定義的構建目標,例如執行測試、生成文件、執行程式碼檢查等。這些目標可以依賴其他目標或檔案,並根據需要執行自定義的命令或操作
add_custom_target 命令不會生成實際的構建產物(如可執行檔案或庫),它只是定義了一個自定義的構建目標。您可以透過 add_dependencies 命令將這個自定義目標與其他目標關聯起來,以確保在構建過程中執行相關的自定義操作。
使用案例
add_custom_target(RunTests
COMMAND run_tests.sh
DEPENDS test_files
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Running tests..."
)
add_dependencies(RunTests MyApp)
在這個示例中,RunTests 是一個自定義目標,透過執行 run_tests.sh 指令碼來執行測試。它依賴於 test_files 目標(或檔案),並在 ${CMAKE_BINARY_DIR} 目錄下執行。透過 COMMENT 可以新增註釋,說明正在執行的操作。最後,透過 add_dependencies 將 RunTests 目標與 MyApp 目標關聯起來,以確保在構建 RunTests 目標時先構建 MyApp 目標。
使用教程
-
建立自定義目標:
首先,使用add_custom_target
命令建立一個自定義構建目標並指定它的名稱。add_custom_target(MyTarget)
在上述示例中,我們建立了一個名為
MyTarget
的自定義目標,這個目標還沒有定義任何操作。 -
新增命令:
使用COMMAND
選項來新增要執行的命令或操作。add_custom_target(MyTarget COMMAND echo "Hello, World!" )
在這個例子中,我們在
MyTarget
目標中新增了一個命令,即輸出 “Hello, World!”。您可以根據實際需求新增更多的命令或操作。 -
新增依賴項:
使用DEPENDS
選項來指定MyTarget
目標所依賴的其他目標或檔案。add_custom_target(MyTarget COMMAND echo "Hello, World!" DEPENDS other_target file.txt )
在上述示例中,我們將
MyTarget
目標設定為依賴於other_target
目標和file.txt
檔案。這意味著在構建MyTarget
之前,CMake 將確保先構建other_target
目標和檢查file.txt
檔案的更新。 -
設定工作目錄和註釋:
使用其他選項如WORKING_DIRECTORY
和COMMENT
來設定工作目錄和新增註釋。add_custom_target(MyTarget COMMAND echo "Hello, World!" DEPENDS other_target file.txt WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMENT "Running custom commands..." )
在上述示例中,我們設定了
MyTarget
的工作目錄為${CMAKE_BINARY_DIR}
,並新增了一個註釋以描述正在執行的操作。 -
新增到其他目標的依賴項:
使用add_dependencies
命令將自定義目標與其他目標關聯起來。add_executable(MyApp main.cpp) add_custom_target(MyTarget COMMAND echo "Hello, World!" DEPENDS other_target file.txt WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMENT "Running custom commands..." ) add_dependencies(MyApp MyTarget)
在這個例子中,我們將自定義目標
MyTarget
新增為可執行檔案MyApp
的依賴項。這意味著在構建MyApp
時,CMake 將確保先構建MyTarget
。
add_custom_command:自定義編譯命令
add_custom_command(OUTPUT output1 [output2 ...]
COMMAND command1 [ARGS] [args1...]
[COMMAND command2 [ARGS] [args2...] ...]
[MAIN_DEPENDENCY depend]
[DEPENDS [depends...]]
[BYPRODUCTS [files...]]
[IMPLICIT_DEPENDS <lang1> depend1
[<lang2> depend2] ...]
[WORKING_DIRECTORY dir]
[COMMENT comment]
[DEPFILE depfile]
[JOB_POOL job_pool]
[VERBATIM] [APPEND] [USES_TERMINAL]
[COMMAND_EXPAND_LISTS]
[DEPENDS_EXPLICIT_ONLY])
其中,常用的引數和選項包括:
TARGET
:指定目標(可執行檔案或庫),表示該自定義命令與構建目標相關聯。PRE_BUILD
、PRE_LINK
、POST_BUILD
:指定自定義命令在何時執行,分別表示前置構建、前置連結和後置構建。COMMAND
:指定要執行的命令。WORKING_DIRECTORY
:設定命令的工作目錄。COMMENT
:新增對命令的註釋。MAIN_DEPENDENCY
:指定自定義命令所依賴的主檔案。DEPENDS
:指定自定義命令所依賴的其他檔案。BYPRODUCTS
:指定由命令生成的副產品檔案。IMPLICIT_DEPENDS
:指定命令的隱式依賴關係,這些依賴關係可能是根據原始檔的語言推斷出來的。USES_TERMINAL
:指示命令是否會使用終端(僅在可執行檔案的情況下)。
透過使用 add_custom_command
,可以在構建過程中執行各種自定義的命令,如生成程式碼、複製檔案、執行指令碼等。這允許您在構建過程中執行與編譯和連結無關的任意操作。
請注意,add_custom_command
命令必須與 add_custom_target
或 add_executable
/ add_library
配合使用,以將其與構建目標關聯起來。
使用案例
add_custom_command
命令用於在構建過程中執行自定義的命令。下面是一個簡單的教程,介紹瞭如何使用 add_custom_command
:
-
新增生成檔案的自定義命令:
首先,使用add_custom_command
命令定義一個用於生成檔案的自定義命令。add_custom_command( OUTPUT generated_file.txt COMMAND generate_file.py DEPENDS generate_file.py )
在上述示例中,我們定義了一個自定義命令,它使用 Python 指令碼
generate_file.py
來生成一個名為generated_file.txt
的檔案。DEPENDS
引數指定生成檔案的依賴項,例如指令碼檔案本身。 -
將生成的檔案作為構建目標使用:
可以將生成的檔案作為構建目標的一部分使用,例如作為原始檔或目標檔案。add_executable(MyApp main.cpp generated_file.txt)
在上述示例中,我們將生成的檔案
generated_file.txt
作為一個原始檔之一與main.cpp
一起使用,構建一個名為MyApp
的可執行檔案。 -
宣告生成檔案的依賴關係:
使用add_dependencies
命令將自定義命令與其他目標關聯起來。add_custom_command( OUTPUT generated_file.txt COMMAND generate_file.py DEPENDS generate_file.py ) add_executable(MyApp main.cpp) add_dependencies(MyApp generated_file.txt)
在這個例子中,我們在自定義命令與目標之間建立了依賴關係。透過
add_dependencies
命令,MyApp
目標將在構建之前先構建generated_file.txt
。
使用 add_custom_command
,您可以執行各種自定義的命令或操作,並將其與構建目標進行關聯。這使得您可以在構建過程中執行額外的操作,例如生成程式碼、複製檔案、預處理資源等。根據自己的專案需求,您可以根據需要實現適合的自定義命令,並根據構建邏輯設定相關的依賴關係。
3.4 配置檔案
configure_file命令是CMake提供的一個常用命令,用於在構建過程中根據模板檔案生成配置檔案
四、自動化測試
當使用CTest來執行測試時,通常需要按照以下步驟進行配置和執行:
-
建立測試目錄:在專案中建立一個用於存放測試指令碼和測試資料的目錄。可以將該目錄命名為
tests
或者其他合適的名稱。 -
編寫測試指令碼:在測試目錄中建立一個或多個測試指令碼檔案,用於描述測試用例和測試步驟。測試指令碼可以使用CTest的命令和語法來定義測試行為、驗證結果等。以下是一個簡單的示例:
# tests/mytest.cmake # 定義一個測試用例 add_test(NAME MyTest COMMAND my_program input_data.txt output_data.txt) # 驗證測試結果 set_tests_properties(MyTest PROPERTIES PASS_REGULAR_EXPRESSION "Expected output")
-
建立CTest配置檔案:在專案的根目錄中建立一個名為
CTestTestfile.cmake
的配置檔案,用於配置測試設定、測試套件和測試驅動程式等細節。該檔案會被CTest自動載入。以下是一個簡單的示例:# CTestTestfile.cmake # 新增測試目錄 add_subdirectory(tests)
-
構建專案:使用CMake構建專案,此時確保CTest被啟用並已成功整合到專案中。
-
執行CTest:在專案構建完成後,在構建目錄中執行
ctest
命令來執行測試。可以使用ctest --verbose
來顯示詳細的測試輸出。$ ctest
或者使用圖形介面工具來執行CTest,例如執行
ccmake
或cmake-gui
命令來檢視和執行CTest。 -
檢視測試結果:CTest將測試結果輸出到終端或CTest的GUI前端。你將看到每個測試的狀態(透過、失敗、跳過等),以及相關的錯誤訊息和日誌檔案。
這只是一個簡單的CTest使用示例,你可以根據專案的特定需求和測試要求自定義和擴充套件CTest的功能。參閱CTest文件以獲取更多詳細資訊和更高階的CTest配置選項。
記住,在編寫測試指令碼時,應該儘可能涵蓋專案的各方面,並驗證預期的行為和結果。測試是質量保證過程的重要組成部分,能夠提供反饋以確保專案的正確性和可靠性。
五、安裝
5.1 Linux的rpath機制
在 CMake 中,可以透過使用 CMAKE_INSTALL_RPATH
或者 CMAKE_BUILD_RPATH
屬性來設定可執行檔案的 rpath。
CMAKE_INSTALL_RPATH
:用於指定在安裝過程中可執行檔案的 rpath。可執行檔案會被安裝到目標目錄,同時 rpath 會被設定為CMAKE_INSTALL_RPATH
指定的路徑。可以透過在 CMakeLists.txt 檔案中設定該屬性來達到目的。
set(CMAKE_INSTALL_RPATH <path>)
其中 <path>
是要設定的 rpath 的路徑。
CMAKE_BUILD_RPATH
:用於指定在構建過程中可執行檔案的 rpath。可執行檔案在構建過程中會被放置在構建目錄,同時 rpath 會被設定為CMAKE_BUILD_RPATH
指定的路徑。可以透過在 CMakeLists.txt 檔案中設定該屬性來達到目的。
set(CMAKE_BUILD_RPATH <path>)
同樣,<path>
是要設定的 rpath 的路徑。
注意:
<path>
可以是多個路徑的列表。可以使用;
分隔路徑。- 在設定
CMAKE_INSTALL_RPATH
和CMAKE_BUILD_RPATH
時,可以使用 CMake 的 generator expressions,以便根據不同的配置和平臺展開不同的路徑。 CMAKE_INSTALL_RPATH
和CMAKE_BUILD_RPATH
可以同時設定,並且它們的優先順序會根據具體的情況決定。
設定 CMAKE_INSTALL_RPATH
或 CMAKE_BUILD_RPATH
後,重新執行 CMake 構建過程,可執行檔案的 rpath 會被相應地設定。這樣,在執行時可執行檔案會使用 rpath 指定的路徑來查詢動態庫,從而確保動態庫能夠正確載入。
需要注意的是,rpath 機制在不同的作業系統上有所不同,具體的設定和行為可能會有所差異。確保根據目標平臺和作業系統的要求進行適當的配置和測試。
5.2 CMAKE_INSTALL_RPATH
的使用案例
以下是一個使用 CMAKE_INSTALL_RPATH
的簡單示例:
cmake_minimum_required(VERSION 3.12)
project(MyApp)
# 設定可執行檔案的原始檔
set(SOURCES main.cpp)
# 設定生成可執行檔案
add_executable(myapp ${SOURCES})
# 設定動態庫的搜尋路徑
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
# 安裝規則
install(TARGETS myapp
RUNTIME DESTINATION bin
DESTINATION "${CMAKE_INSTALL_PREFIX}"
# 設定 rpath 為 CMAKE_INSTALL_RPATH 變數的值
INSTALL_RPATH "${CMAKE_INSTALL_RPATH}"
)
在這個示例中,假設專案目錄結構如下:
.
├── CMakeLists.txt
├── main.cpp
└── lib
└── mylib.so
main.cpp
是可執行檔案的原始檔。lib
目錄下包含一個名為mylib.so
的動態庫檔案。
在 CMakeLists.txt 中,我們首先定義了可執行檔案的原始檔,並透過 add_executable()
命令新增了一個名為 myapp
的可執行目標。
接下來,我們透過 set()
命令設定了 CMAKE_INSTALL_RPATH
的值為 $ORIGIN/lib
。這裡使用了 $ORIGIN
變數,它表示可執行檔案所在的目錄。
最後,在安裝規則中,我們使用 install()
命令將可執行檔案安裝到指定的目錄,並透過 INSTALL_RPATH
屬性將 CMAKE_INSTALL_RPATH
的值傳遞給 rpath。
在構建並執行專案時,可執行檔案 myapp
將被安裝到目標目錄(例如安裝到 /usr/local/bin
),同時 rpath 將被設定為 /usr/local/bin/lib
。這樣在執行時,可執行檔案就能夠找到並載入位於 lib
目錄下的動態庫檔案。
請注意,實際的 rpath 設定可能因作業系統、CMake 版本和專案結構而有所不同,上述示例僅為了說明如何使用 CMAKE_INSTALL_RPATH
。根據具體的需求和情況,可能需要進行適當的調整。
5.3 CMAKE_BUILD_RPATH
的使用案例
以下是一個使用 CMAKE_BUILD_RPATH
的簡單示例:
cmake_minimum_required(VERSION 3.12)
project(MyApp)
# 設定可執行檔案的原始檔
set(SOURCES main.cpp)
# 設定生成可執行檔案
add_executable(myapp ${SOURCES})
# 設定動態庫的搜尋路徑
set(CMAKE_BUILD_RPATH "$ORIGIN/lib")
# 構建規則
set_target_properties(myapp PROPERTIES
# 設定 rpath 為 CMAKE_BUILD_RPATH 變數的值
BUILD_RPATH "${CMAKE_BUILD_RPATH}"
)
在這個示例中,假設專案目錄結構如下:
.
├── CMakeLists.txt
├── main.cpp
└── lib
└── mylib.so
main.cpp
是可執行檔案的原始檔。lib
目錄下包含一個名為mylib.so
的動態庫檔案。
在 CMakeLists.txt 中,我們首先定義了可執行檔案的原始檔,並透過 add_executable()
命令新增一個名為 myapp
的可執行目標。
接下來,我們透過 set()
命令設定了 CMAKE_BUILD_RPATH
的值為 $ORIGIN/lib
。這裡使用了 $ORIGIN
變數,它表示構建目錄。
最後,使用 set_target_properties()
命令,將 BUILD_RPATH
屬性設定為 CMAKE_BUILD_RPATH
的值。這樣,在構建過程中,可執行檔案 myapp
的 rpath 將被設定為構建目錄下的 lib
目錄。
在構建專案時,生成的可執行檔案 myapp
將具有指定的 rpath,以便在執行時正確載入位於構建目錄下的動態庫檔案。
請注意,實際的 rpath 設定可能因作業系統、CMake 版本和專案結構而有所不同,上述示例僅為了說明如何使用 CMAKE_BUILD_RPATH
。根據具體的需求和情況,可能需要進行適當的調整。
六、閉源包引用
#glfw
add_library(glfw STATIC IMPORTED)
set_property(TARGET glfw PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/extern/glfw/lib-vc2019/glfw3.lib)
target_include_directories(glfw INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/extern/glfw/include)
#引用
target_link_libraries(main glfw)
七、vcpkg包管理
6.1 安裝
官方連結
-
開啟終端。
-
克隆 Vcpkg 儲存庫:
git clone https://github.com/microsoft/vcpkg.git
-
進入 Vcpkg 目錄:
cd vcpkg
-
執行
bootstrap-vcpkg.sh
指令碼以初始化和構建 Vcpkg:./bootstrap-vcpkg.sh sudo ln -s $HOME/vcpkg/vcpkg /usr/bin cat "EXPORT VCPKG_ROOT=/home/chao/vcpkg" &>> ~/.bashrc
-
執行以下命令將 Vcpkg 安裝到系統目錄
/usr/local
:sudo ./vcpkg integrate install
輸入您的密碼以進行身份驗證。
-
現在,Vcpkg 已成功安裝到您的 Ubuntu 系統上。
-
使用 Vcpkg 安裝和管理庫。
-
在終端中,使用以下命令安裝所需的庫:
./vcpkg install <library-name>
將
<library-name>
替換為您要安裝的庫的名稱。 -
安裝完成後,您可以在程式碼中使用 Vcpkg 安裝的庫來進行開發和構建。
-
請注意,使用 Vcpkg 在 Ubuntu 上安裝庫可能需要滿足一些依賴項和構建工具的要求。在某些情況下,您可能需要在 Ubuntu 上預先安裝一些依賴項,以便成功安裝和使用特定的庫
6.2 vcpkg.json
-
在專案的根目錄下建立一個名為 vcpkg.json 的檔案。
-
開啟 vcpkg.json 並編輯檔案,按照 JSON 格式的語法來定義您的庫和其設定。下面是一個示例:
{ "name": "myproject", "version": "0.1", "dependencies": [ { "name": "library1", "version": "1.2" }, { "name": "library2", "version": "2.0" } ] }
上述示例中,“name” 指定專案名稱,“version” 指定專案版本,“dependencies” 下列出了專案所依賴的庫。
-
定義庫的依賴項。每個依賴項都需要指定名稱 (“name”) 和版本 (“version”)。此外,您還可以指定特定的庫功能(如果有)。
-
儲存 vcpkg.json 檔案。
-
在終端中,導航到專案的根目錄。
-
執行以下命令,使用 Vcpkg 安裝專案依賴項:
vcpkg install
Vcpkg 將根據 vcpkg.json 檔案中定義的庫和版本資訊,自動下載、安裝和構建所需的庫。
-
安裝完成後,您可以在專案中使用已安裝的庫進行開發和構建。
vcpkg.json 是一個方便的方法,可以在專案級別上配置 Vcpkg。透過使用該檔案,可以輕鬆地與其他人共享專案依賴項和配置,並確保每個人都能夠使用相同的庫版本。
6.3 多包管理器共存
if(USE_VCPKG)
find_package(<VCPKG_PACKAGE> REQUIRED)
include_directories(${<VCPKG_PACKAGE>_INCLUDE_DIRS})
target_link_libraries(MyProject ${<VCPKG_PACKAGE>_LIBRARIES})
else()
find_package(<APT_PACKAGE> REQUIRED)
include_directories(${<APT_PACKAGE>_INCLUDE_DIRS})
target_link_libraries(MyProject ${<APT_PACKAGE>_LIBRARIES})
endif()