本節內容,轉載文章:https://www.zhihu.com/column/c_200294809 ;參考程序:https://github.com/BrightXiaoHan/CMakeTutorial
實驗環境:MacOS
find_package引入外部庫
爲了方便我們在項目中引入外部依賴包,cmake官方爲我們預定義了許多尋找依賴包的Module,他們存儲在path_to_your_cmake/share/cmake-
find_package用於引入外部庫,通過查找依賴庫的文件路徑,有兩種模式:
(1)Module模式
在Module模式中,cmake需要找到一個叫做Find
(2)Config模式
如果Module模式搜索失敗,沒有找到對應的Find
通過模式Module引入外部庫
引入外部庫:curl庫
curl是Linux下一個非常著名的下載庫,通過這個庫,可以很簡單的實現文件的下載等操作。支持http, https, ftp, gopher, telnet, dict, file, 和ldap 協議。libcurl同樣支持HTTPS證書授權,HTTP POST, HTTP PUT, FTP 上傳, HTTP基本表單上傳,代理,cookies,和用戶認證。
官方定義好的
我們看到官方已經定義好了FindCURL.cmake。所以我們在CMakeLists.txt中可以直接用find_pakcage進行引用,可以看作安裝CMake時自帶的!
(1)引用
find_package(CURL)
add_executable(curltest curltest.cc)
if(CURL_FOUND)
target_include_directories(curltest PRIVATE ${CURL_INCLUDE_DIR})
target_link_libraries(curltest ${CURL_LIBRARY})
else(CURL_FOUND)
message(FATAL_ERROR "CURL library not found")
endif(CURL_FOUND)
對於系統預定義的 Find
每一個模塊都會定義以下幾個變量 -
<LibaryName>_FOUND
<LibaryName>_INCLUDE_DIR or <LibaryName>_INCLUDES <LibaryName>_LIBRARY or <LibaryName>_LIBRARIES
你可以通過
通過模式Config引入非官方的庫
假設此時我們需要引入glog庫來進行日誌的記錄,我們在Module目錄下並沒有找到 FindGlog.cmake。所以我們需要自行安裝glog庫,再進行引用。
glog庫:Google glog是一個基於程序級記錄日誌信息的C++庫,編程使用方式與c++的stream操作類似,例如:LOG(INFO) << “one” << “two” << “three”;
其中“LOG”宏爲日誌輸出關鍵字,”INFO”爲嚴重性程度
(1)安裝
# clone該項目
git clone https://github.com/google/glog.git
# 切換到需要的版本
cd glog
git checkout v0.40
# 根據官網的指南進行安裝
cmake -H. -Bbuild -G "Unix Makefiles"
cmake --build build
cmake --build build --target install
在我們安裝之後,它在/usr/local/lib/cmake/glog/目錄下生成了glog-config.cmake文件,而/usr/local/lib/cmake/
(2)引用
find_package(glog)
add_executable(glogtest glogtest.cc)
if(GLOG_FOUND)
# 由於glog在連接時將頭文件直接鏈接到了庫裏面,所以這裏不用顯示調用target_include_directories
target_link_libraries(glogtest glog::glog)
else(GLOG_FOUND)
message(FATAL_ERROR ”glog library not found”)
endif(GLOG_FOUND)
引入自定義庫
編寫了一個新的函數庫,我們希望別的項目可以通過find_package對它進行引用
在當前目錄下新建一個ModuleMode的文件夾,在裏面我們編寫一個計算兩個整數之和的一個簡單的函數庫。庫函數以手工編寫Makefile的方式進行安裝,庫文件安裝在/usr/lib目錄下,頭文件放在/usr/include目錄下。
(1)Makefile文件
# 1、準備工作,編譯方式、目標文件名、依賴庫路徑的定義。
CC = g++
CFLAGS := -Wall -O3 -std=c++11
OBJS = libadd.o #.o文件與.cpp文件同名
LIB = libadd.so # 目標文件名
INCLUDE = ./ # 頭文件目錄
HEADER = libadd.h
all : $(LIB)
# 2. 生成.o文件
$(OBJS) : libadd.cc
$(CC) $(CFLAGS) -I ./ -fpic -c $< -o $@
# 3. 生成動態庫文件
$(LIB) : $(OBJS)
rm -f $@
g++ $(OBJS) -shared -o $@
rm -f $(OBJS)
# 4. 刪除中間過程生成的文件
clean:
rm -f $(OBJS) $(TARGET) $(LIB)
# 5.安裝文件
install:
mkdir -p /usr/lib/add
cp $(LIB) /usr/lib/add
cp $(HEADER) /usr/include
(2)編譯安裝
make
sudo make install
(3)接下來我們回到我們的Cmake項目中來,在cmake文件夾下新建一個FindAdd.cmake的文件。我們的目標是找到庫的頭文件所在目錄和共享庫文件的所在位置。
# 在指定目錄下尋找頭文件和動態庫文件的位置,可以指定多個目標路徑
find_path(ADD_INCLUDE_DIR libadd.h /usr/include/ /usr/local/include ${CMAKE_SOURCE_DIR}/ModuleMode)
find_library(ADD_LIBRARY NAMES add PATHS /usr/lib/add /usr/local/lib/add ${CMAKE_SOURCE_DIR}/ModuleMode)
if (ADD_INCLUDE_DIR AND ADD_LIBRARY)
set(ADD_FOUND TRUE)
endif (ADD_INCLUDE_DIR AND ADD_LIBRARY)
這時我們便可以像引用curl一樣引入我們自定義的庫了。
(4)在CMakeLists.txt中添加
# 將項目目錄下的cmake文件夾加入到CMAKE_MODULE_PATH中,讓find_pakcage能夠找到我們自定義的函數庫
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}")
add_executable(addtest addtest.cc)
find_package(ADD)
if(ADD_FOUND)
target_include_directories(addtest PRIVATE ${ADD_INCLUDE_DIR})
target_link_libraries(addtest ${ADD_LIBRARY})
else(ADD_FOUND)
message(FATAL_ERROR "ADD library not found")
endif(ADD_FOUND)