CMake路徑搜索

目錄:
cmake中定義搜索路徑
修改環(huán)境變量增加搜索路徑
FIND 系列指令,通過FIND尋找路徑并進(jìn)行添加
大型開源庫路徑添加方式
find_package采用兩種模式搜索庫

路徑搜索,這里介紹頭文件的路徑搜索和庫文件的路徑搜索。

cmake中定義搜索路徑

cmake中定義頭文件的搜索路徑:INCLUDE_DIRECTORIES 命令添加搜索路徑
庫文件的搜索路徑是:LINK_DIRECTORIES 命令添加庫搜索路徑

link_libraries:(添加需要鏈接的庫文件路徑,注意這里是全路徑),該用法已經(jīng)被廢棄。
為最終目標(biāo)鏈接庫使用: TARGET_LINK_LIBRARIES 鏈接庫(動態(tài)庫和靜態(tài)庫)
需要鏈接的庫,會根據(jù)系統(tǒng)動態(tài)庫的搜索路徑依次進(jìn)行搜索。這里可以直接寫庫的名稱(程序定義路徑,環(huán)境變量定義的路徑,系統(tǒng)默認(rèn)搜索路徑)

target_link_libraries 要在 add_executable 之后,link_libraries 要在 add_executable 之前

修改環(huán)境變量增加搜索路徑

CMAKE_INCLUDE_PATH 和CMAKE_LIBRARY_PATH

特殊的環(huán)境變量CMAKE_INCLUDE_PATHCMAKE_LIBRARY_PATH務(wù)必注意,這兩個是環(huán)境變量而不是 cmake 變量。
使用方法是要在 bash 中用 export 或者在 csh 中使用 set 命令設(shè)置或者 CMAKE_INCLUDE_PATH=/home/include cmake ..等方式。如果頭文件沒有存放在常規(guī)路徑(/usr/include, /usr/local/include等), 則可以通過這些變量就行彌補(bǔ)。
為了將程序更智能一點(diǎn),我們可以使用 CMAKE_INCLUDE_PATH 來進(jìn)行,使用 bash 的方法 如下:
export CMAKE_INCLUDE_PATH=/usr/include/hello

eg:
設(shè)置export CMAKE_INCLUDE_PATH=/usr/include/hello
頭文件中將 INCLUDE_DIRECTORIES(/usr/include/hello)替換為: 
FIND_PATH(myHeader hello.h)
IF(myHeader)
INCLUDE_DIRECTORIES(${myHeader})
ENDIF(myHeader)

這里簡單說明一下,F(xiàn)IND_PATH 用來在指定路徑中搜索文件名,比如:
FIND_PATH(myHeader NAMES hello.h PATHS /usr/include /usr/include/hello)
這里我們沒有指定路徑,但是,cmake 仍然可以幫我們找到 hello.h 存放的路徑,就是因?yàn)槲覀冊O(shè)置了環(huán)境變量 CMAKE_INCLUDE_PATH。
如果你不使用 FIND_PATHCMAKE_INCLUDE_PATH 變量的設(shè)置是沒有作用的,你不能指望它會直接為編譯器命令添加參數(shù)-I<CMAKE_INCLUDE_PATH>。
以此為例,CMAKE_LIBRARY_PATH 可以用在 FIND_LIBRARY 中。
同樣,因?yàn)檫@些變量直接為 FIND_ 指令所使用,所以所有使用 FIND_ 指令的 cmake 模塊都會受益。

FIND 系列指令,通過FIND尋找路徑并進(jìn)行添加

FIND_系列指令主要包含一下指令:

FIND_FILE(<VAR> name1 path1 path2 ...)

VAR 變量代表找到的文件全路徑,包含文件名

FIND_LIBRARY(<VAR> name1 path1 path2 ...)

VAR 變量表示找到的庫全路徑,包含庫文件名
FIND_LIBRARY 示例:

FIND_LIBRARY(libX X11 /usr/lib) 
IF(NOT libX)
MESSAGE(FATAL_ERROR “l(fā)ibX not found”) 
ENDIF(NOT libX)
FIND_PATH(<VAR> name1 path1 path2 ...)

VAR 變量代表包含這個文件的路徑。

FIND_PROGRAM(<VAR> name1 path1 path2 ...)

VAR 變量代表包含這個程序的全路徑。

FIND_PACKAGE
FIND_PACKAGE(<name> [major.minor]
        [QUIET] [NO_MODULE] 
        [[REQUIRED|COMPONENTS] [componets...]] )

FIND_PACKAGE 其實(shí)是系統(tǒng)與定義的cmake模塊。對于系統(tǒng)預(yù)定義的 Find<name>.cmake 模塊,使用方法一般如上例所示: 每一個模塊都會定義以下幾個變量

  • <name>_FOUND
  • <name>_INCLUDE_DIR or <name>_INCLUDES
  • <name>_LIBRARY or <name>_LIBRARIES

你可以通過<name>_FOUND 來判斷模塊是否被找到,如果沒有找到,按照工程的需要關(guān)閉 某些特性、給出提醒或者中止編譯,上面的例子就是報出致命錯誤并終止構(gòu)建。
如果<name>_FOUND 為真,則將<name>_INCLUDE_DIR 加入 INCLUDE_DIRECTORIES, 將<name>_LIBRARY 加入 TARGET_LINK_LIBRARIES 中。
舉個例子:

FIND_PACKAGE(CURL)
IF(CURL_FOUND)
   INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIR})
   TARGET_LINK_LIBRARIES(curltest ${CURL_LIBRARY})
ELSE(CURL_FOUND)
     MESSAGE(FATAL_ERROR ”CURL library not found”)
ENDIF(CURL_FOUND)

FIND_PACKAGE 其實(shí)內(nèi)部主要還是通過FIND_PATH,F(xiàn)IND_LIBRARY等基礎(chǔ)命令實(shí)現(xiàn)的。

大型開源庫路徑添加方式

如果是簡單的引入,可以直接通過指令I(lǐng)NCLUDE_DIRECTORIES,LINK_DIRECTORIES或者CMAKE_INCLUDE_PATH和CMAKE_LIBRARY_PATH進(jìn)行設(shè)置。但是該方式存在缺點(diǎn)

  • 需要把路徑固定,不宜遷移,修改麻煩
  • 如果存在大量的路徑的話,需要一次添加所有的路徑比較復(fù)雜

因此可以通過FIND 進(jìn)行查找路徑,通過FIND_PACKAGE 獲得所有的頭文件和庫文件路徑。
比如對于OpenCV,這樣的方式將會十分方便。這里介紹幾種常用的方式:

  1. 方式一:FIND_PACKAGE
    通過FIND_PACKAGE的方式。
#添加OPENCV庫
#指定OpenCV版本,代碼如下
#find_package(OpenCV 3.3 REQUIRED)
#如果不需要指定OpenCV版本,代碼如下
find_package(OpenCV REQUIRED)

#添加OpenCV頭文件
include_directories(${OpenCV_INCLUDE_DIRS})

# 添加一個可執(zhí)行程序
# 語法:add_executable( 程序名 源代碼文件 )
add_executable( main main.cpp )

# 將庫文件鏈接到可執(zhí)行程序上
target_link_libraries( main ${OpenCV_LIBS})

要求opencv安裝在系統(tǒng)默認(rèn)目錄下。

  1. 方式二:cmake 關(guān)PKG-CONFIG的指令方式
    其實(shí)和方式二一樣,但是實(shí)現(xiàn)的方式上有出入。通過opencv自帶的pkg-config 提供的opencv.pc文件。
# 編譯該工程CMAKE最低版本
CMAKE_MINIMUM_REQUIRED(VERSION 3.2 FATAL_ERROR)
# 工程名字
PROJECT(MAIN)

#通過pkg-config管理的三方庫
# 非root下需要自己加入PKG_CONFIG_PATH,不然報錯!!!
SET(ENV{PKG_CONFIG_PATH} /home/topeet/programfile/opencv2/lib/pkgconfig)
#PkgConfig名字是固定的,代表準(zhǔn)備加入pkg-config模塊,即查找/usr/bin/pkg-config
FIND_PACKAGE(PkgConfig REQUIRED) 
#通過執(zhí)行pkg-config程序,并指定我需要的模塊是opencv,注意opencv名字固定,是源于安裝OpenCV生成的opencv.pc,PKG_OPENCV是前綴(觀察下面),
PKG_SEARCH_MODULE(PKG_OPENCV REQUIRED opencv)   

# 添加三方opencv的頭文件路徑-- -I/home/topeet/programfile/opencv2/include/opencv -I/home/topeet/programfile/opencv2/include
INCLUDE_DIRECTORIES(${PKG_OPENCV_INCLUDE_DIRS})

# 指定生成目標(biāo)
ADD_EXECUTABLE(main main.cpp)
# 為指定的bin文件添加三方鏈接庫
TARGET_LINK_LIBRARIES(main detect ${PKG_OPENCV_LDFLAGS})

find_package采用兩種模式搜索庫

Module模式:搜索CMAKE_MODULE_PATH指定路徑下的FindXXX.cmake文件,執(zhí)行該文件從而找到XXX庫。其中,具體查找?guī)觳⒔oXXX_INCLUDE_DIRS和XXX_LIBRARIES兩個變量賦值的操作由FindXXX.cmake模塊完成。

Module 搜素路徑:

  • CMAKE_MODULE_PATH指定的路徑
  • <CMAKE_ROOT>/share/cmake-x.y/Mdodules (注意:x.y表示版本號。我的是3.10)。其中CMAKE_ROOT是你在安裝Cmake的時候的系統(tǒng)路徑,因?yàn)槲也]有指定安裝路徑,所以是系統(tǒng)默認(rèn)的路徑,在我的系統(tǒng)中(ubuntu16.04)系統(tǒng)的默認(rèn)路徑是/usr/loacl,如果你在安裝的過程中使用了
    cmake -DCMAKE_INSTALL_PREFIX=自己dir路徑 ,那么此時CMAKE_ROOT就代表那個你寫入的路徑 。($CMAKE_ROOT的具體值可以通過CMake中message命令輸出)。這稱為模塊模式。

Config模式:搜索XXX_DIR指定路徑下的XXXConfig.cmake文件,執(zhí)行該文件從而找到XXX庫。其中具體查找?guī)觳⒔oXXX_INCLUDE_DIRS和XXX_LIBRARIES兩個變量賦值的操作由XXXConfig.cmake模塊完成。

Config 搜索路徑:

  • 搜索xxx_DIR 指定的路徑。如果在CMakeLists.txt中沒有設(shè)置這個cmake變量。也就是說沒有下面的指令: set(xxx_DIR "xxxConfig.cmkae文件所在的路徑")那么Cmake就不會搜索xxx_DIR指定的路徑
  • Cmake 會在/usr/local/lib/cmake/xxx/ /usr/local/share/xxx 中的xxxConfig.cmake文件。這個路徑不同的操作系統(tǒng)存在差異。

兩種模式看起來似乎差不多,不過cmake默認(rèn)采取Module模式,如果Module模式未找到庫,才會采取Config模式。若果在Module的搜索路徑中沒有找到對應(yīng)的cmake file,則使用config模式。總之,Config模式是一個備選策略。通常,庫安裝時會拷貝一份XXXConfig.cmake到系統(tǒng)目錄中,因此在沒有顯式指定搜索路徑時也可以順利找到。

在我遇到的問題中,由于Caffe安裝時沒有安裝到系統(tǒng)目錄,因此無法自動找到CaffeConfig.cmake,我在CMakeLists.txt最前面添加了一句話之后就可以了。

set(Caffe_DIR /home/wjg/projects/caffe/build)#添加CaffeConfig.cmake的搜索路徑find_package(Caffe REQUIRED)
if(NOT Caffe_FOUND)
  message(FATAL_ERROR"Caffe Not Found!")
endif(NOT Caffe_FOUND)
include_directories(${Caffe_INCLUDE_DIRS})
add_executable(useSSD ssd_detect.cpp)
target_link_libraries(useSSD${Caffe_LIBRARIES})
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 向您的項(xiàng)目添加 C 和 C++ 代碼 本文內(nèi)容 下載 NDK 和構(gòu)建工具 創(chuàng)建支持 C/C++ 的新項(xiàng)目 構(gòu)建和運(yùn)...
    會飛的大象_閱讀 3,918評論 0 3
  • 注:首發(fā)地址 1. 前言 當(dāng)在做 Android NDK 開發(fā)時,如果不熟悉用 CMake 來構(gòu)建,讀不懂 CMa...
    cfanr閱讀 24,794評論 1 53
  • 最近在負(fù)責(zé)一個大型工程的CMake編譯系統(tǒng)管理,整理一些工作過程中積累下來的知識片段和技巧。CMake是一個跨平臺...
    啊呀喲嘿閱讀 9,259評論 0 2
  • 為了將C/C++代碼轉(zhuǎn)換為可以在硬件上運(yùn)行的程序,需要經(jīng)過編譯和鏈接。編譯是將高級語言所寫的源程序翻譯成等價的機(jī)器...
    WalkeR_ZG閱讀 9,960評論 0 15
  • CMake學(xué)習(xí) 本篇分享一下有關(guān)CMake的一些學(xué)習(xí)心得以及相關(guān)使用。 本文目錄如下: [1、CMake介紹] [...
    AlphaGL閱讀 12,439評論 11 79

友情鏈接更多精彩內(nèi)容