cmake-3

本節內容,轉載文章:https://www.zhihu.com/column/c_200294809 ;參考程序:https://github.com/BrightXiaoHan/CMakeTutorial
實驗環境:MacOS

find_package引入外部庫

爲了方便我們在項目中引入外部依賴包,cmake官方爲我們預定義了許多尋找依賴包的Module,他們存儲在path_to_your_cmake/share/cmake-/Modules目錄下。每個以Find.cmake命名的文件都可以幫我們找到一個包。我們也可以在官方文檔中【https://cmake.org/cmake/help/latest/module/FindCURL.html】查看到哪些庫官方已經爲我們定義好了。

find_package用於引入外部庫,通過查找依賴庫的文件路徑,有兩種模式:
(1)Module模式
在Module模式中,cmake需要找到一個叫做Find.cmake的文件。這個文件負責找到庫所在的路徑,爲我們的項目引入頭文件路徑和庫文件路徑。cmake搜索這個文件的路徑有兩個,一個是cmake安裝目錄下的share/cmake-/Modules目錄,另一個使我們指定的CMAKE_MODULE_PATH的所在目錄

(2)Config模式
如果Module模式搜索失敗,沒有找到對應的Find.cmake文件,則轉入Config模式進行搜索。它主要通過Config.cmake 或者-config.cmake這兩個文件來引入我們需要的庫。以我們下面安裝的glog庫爲例,在我們安裝之後,它在/usr/local/lib/cmake/glog/目錄下生成了glog-config.cmake文件,而/usr/local/lib/cmake//正是find_package函數的搜索路徑之一。

通過模式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.cmake 模塊,使用方法一般如上例所示。
每一個模塊都會定義以下幾個變量 -

<LibaryName>_FOUND
<LibaryName>_INCLUDE_DIR or <LibaryName>_INCLUDES <LibaryName>_LIBRARY or <LibaryName>_LIBRARIES

你可以通過_FOUND 來判斷模塊是否被找到,如果沒有找到,按照工程的需要關閉 某些特性、給出提醒或者中止編譯,上面的例子就是報出致命錯誤並終止構建。 如果_FOUND 爲真,則將_INCLUDE_DIR 加入 INCLUDE_DIRECTORIES。

通過模式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//正是find_package函數的搜索路徑之一。
(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 [email protected]

# 3. 生成動態庫文件
$(LIB) : $(OBJS)
	rm -f [email protected]
	g++ $(OBJS) -shared -o [email protected] 
	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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章