之前我們學到了如何編寫一個可執行程序和Library,在繼續學習之前,需要解釋下target
,在cmake中我們可以給executable
和library
設置一個target名字,這樣可以方便我們在后續對target進行更加詳細的屬性設置。
本節我們將學習如何在項目中引用lib,相關的api有:
makefile
復制代碼
link_libraries(<item>... ...) # item鏈接到所有目標中 target_link_libraries(<target> ... <item>... ...) # 將item鏈接到指定的target中
其中item參數支持的情況比較多,提前介紹幾種情況:
- lib name:提供庫的名字,讓cmake去查找對應的庫文件絕對路徑
- lib fullpath:直接一步到位給出庫文件的絕對路徑
- target name: 根據target的屬性,讓cmake查找對應庫文件的絕對路徑
target_xxx
的命令顆粒度更細,是比較高版本的命令。
app調用有源代碼的lib
這種情況是有lib的源代碼,我們將lib以源代碼的方式鏈接到項目內
項目結構為:
- main.cpp
- lib.cpp
- CMakeLists.txt
makefile
復制代碼
# app cmake_minimum_required(VERSION 3.0.0) set(app "demo") project(${app} VERSION 0.1.0) add_executable(${app} main.cpp) # lib set(lib "my-lib") project(${lib}) add_library(${lib} ./lib.cpp) # 將lib鏈接到app target_link_libraries(${app} ${lib})
需要注意的target_link_libraries
- 第一個
target
參數來自add_executable
的第一個參數 - 后續
item
參數來自add_library
的第一個參數
app調用第三方lib、dll
這種情況是我們使用第三方的lib,只有頭文件和庫文件(
.a、.dll、*.so
)
方式1:imported-libraries
bash
復制代碼
# 設置target名字為dll,并且是一個外部導入的lib # GLOBAL選項可以將target的作用域變為全局,默認是只在目錄內可見 add_library(dll SHARED IMPORTED GLOBAL) # 設置target dll的詳細屬性,dll/lib 不區分debug/release的情況 set_target_properties(dll PROPERTIES # 指向lib,windows必須設置此項 IMPORTED_IMPLIB ${CMAKE_CURRENT_LIST_DIR}/dll.lib # 指向dll、so等 IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/dll.dll ) # 設置debug/release set_target_properties(dll PROPERTIES IMPORTED_IMPLIB_DEBUG ${CMAKE_CURRENT_LIST_DIR}/dll_debug.lib IMPORTED_IMPLIB_RELEASE ${CMAKE_CURRENT_LIST_DIR}/dll_release.lib IMPORTED_LOCATION_DEBUG ${CMAKE_CURRENT_LIST_DIR}/dll_debug.dll IMPORTED_LOCATION_RELEASE ${CMAKE_CURRENT_LIST_DIR}/dll_release.dll ) target_link_libraries(app dll)
這里我們使用的是set_target_properties
,可以同時給多個target設置多個不同的屬性:
scss
復制代碼
set_target_properties( target1 target2 ... PROPERTIES prop1 value1 prop2 value2 ... )
方式2:將指定的庫文件直接鏈接到target的不同配置
bash
復制代碼
target_link_libraries(${target} debug ${debug_fullpath}) target_link_libraries(${target} optimized ${release_fullpath})
這兩種方式都可以,原因是target_link_libraries的item
參數既可以是target name
,也可以是lib fullpath
。
在xcode中,對應的工程配置為:
-
當為
target name
時,出現在command的args中 -
當為
lib fullpath
時,在xcode中的位置在Linking/Others Linker Flags:
無論使用哪種方式,注意dll、lib必須是存在的,底層查找lib時,不會自動補充lib前綴。
include頭文件目錄問題
以上僅僅是告訴編譯器lib文件的位置在哪里,我們需要添加頭文件目錄,編譯器才能識別到lib api
方式1:直接添加頭文件目錄,缺點是要手動把使用到的lib include path一個一個加進去,比較麻煩
bash
復制代碼
# 注意:要放在add_executable、add_library前邊才有效 include_directories("a/b/c/")
方式2:給lib target中添加,只要項目依賴了這個target,就會自動將目錄添加到項目中
makefile
復制代碼
# 注意:要放在add_library后邊才有效 target_include_directories(lib INTERFACE # 權限控制,類比:public/private/protected ${CMAKE_CURRENT_SOURCE_DIR}/ )
方式3:和方式2沒啥區別,寫法不同而已
makefile
復制代碼
set_property(TARGET lib PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR} )
推薦使用第2種方式。
lib包含目錄問題
這種情況對應的是我們target_link_libraries
的item參數是lib name
,為了讓CMake可以通過lib name
找到對應的lib文件 ,所以我們才需要設置庫包含目錄,如果item參數是lib path
、target name
,則不需要設置庫包含目錄。
相關的命令有link_directories
和target_link_directories
,區別參考上文。
作者:xu__yanfeng
鏈接:https://juejin.cn/post/7157618014311940126
來源:稀土掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。