一事秀、命令格式
??該命令用于查找?guī)欤▌?dòng)態(tài)庫(kù)或者靜態(tài)庫(kù))彤断,當(dāng)構(gòu)建依賴(lài)于第三方庫(kù)/系統(tǒng)庫(kù)野舶,可以使用該命令來(lái)查找并使用庫(kù)(Cmake中有另外一個(gè)命令find_package
,能獲取庫(kù)的更多信息宰衙,具體可以參考Cmake命令之find_package介紹)
-
簡(jiǎn)潔的格式
find_library (<VAR> name [path1 path2 ...])
-
通用的格式
find_library ( <VAR> name | NAMES name1 [name2 ...] [NAMES_PER_DIR] [HINTS [path | ENV var]... ] [PATHS [path | ENV var]... ] [PATH_SUFFIXES suffix1 [suffix2 ...]] [DOC "cache documentation string"] [NO_CACHE] [REQUIRED] [NO_DEFAULT_PATH] [NO_PACKAGE_ROOT_PATH] [NO_CMAKE_PATH] [NO_CMAKE_ENVIRONMENT_PATH] [NO_SYSTEM_ENVIRONMENT_PATH] [NO_CMAKE_SYSTEM_PATH] [CMAKE_FIND_ROOT_PATH_BOTH | ONLY_CMAKE_FIND_ROOT_PATH | NO_CMAKE_FIND_ROOT_PATH] )
??幾個(gè)基本參數(shù)的解析:
-
<var>
用于存儲(chǔ)該命令執(zhí)行的結(jié)果平道,也就是找到的庫(kù)的全路徑(包含庫(kù)名):
?1.<var>
可以是普通變量(需要指定NO_CACHE
選項(xiàng)),也可以是緩存條目(意味著會(huì)存放在CMakeCache.txt
中供炼,不刪除該文件或者用set
重新設(shè)置該變量一屋,其存儲(chǔ)的值不會(huì)再刷新);
?2. 當(dāng)庫(kù)能被找到劲蜻,<var>
會(huì)被存放正常的庫(kù)路徑陆淀,當(dāng)庫(kù)未被找到,<var>
中存放的值為"<var>-NOTFOUND"
先嬉。只要<var>
中的值不是"<var>-NOTFOUND"
轧苫,那么即使多次調(diào)用find_library
,<var>
也不會(huì)再刷新; -
name
用于指定待查找的庫(kù)名稱(chēng)疫蔓,庫(kù)名稱(chēng)可以使用全稱(chēng)含懊,例如libmymath.a
(優(yōu)先會(huì)當(dāng)成全名搜索);也可以不帶前綴(例如前綴lib
)和后綴(例如Linux
中的.so
衅胀、.a
岔乔,Mac
中的.dylib
等),直接使用mymath
滚躯; -
path
用于指定庫(kù)的查找的路徑雏门;
二、命令解析
??通過(guò)一個(gè)例子來(lái)看下基本的使用掸掏,假設(shè)我們目錄和文件樹(shù)如下茁影,:
CMakeLists.txt 頂層目錄的cmake
test.cpp 頂層目錄測(cè)試文件
mylib 庫(kù)文件所在目錄
--- CMakeLists.txt 子目錄cmake
--- mymath.h 頭文件
--- mymath.cpp 實(shí)現(xiàn)文件
--- libmymath.a 庫(kù)文件
??我們?cè)?code>mylib中生成最終的庫(kù)libmymath.a
,然后在頂層的CMakeLists.txt
中查找這個(gè)庫(kù)文件丧凤,幾個(gè)文件的具體內(nèi)容如下:
// 頂層CMakeLists.txt
cmake_minimum_required (VERSION 3.21)
project (fl)
find_library (libvar mymath ./mymath)
add_executable (test test.cpp)
target_link_libraries (test ${libvar})
// test.cpp
#include "./mylib/mymath.h"
int main(int argc, char **argv)
{
int sum = mymath::add(1, 2);
return 0;
}
// mylib/CMakeLists.txt
cmake_minimum_required (VERSION 3.21)
project (mymath)
add_library (mymath mymath.cpp)
// mylib/mymath.h
namespace mymath {
int add(int a, int b);
};
// mylib/mymath.cpp
#include "mymath.h"
#include <iostream>
namespace mymath {
int add(int a, int b)
{
std::cout << "Add " << a << " and " << b << " is " << a + b << std::endl;
return a + b;
}
};
??在./mylib/
下執(zhí)行cmake .
和make
以便生成庫(kù)libmymath.a
募闲,然后在./
目錄下執(zhí)行cmake .
和make
,得到可執(zhí)行文件test
愿待,運(yùn)行test
的結(jié)果為:
./test
Add 1 and 2 is 3
三浩螺、更多細(xì)節(jié)
3.1 庫(kù)的搜索路徑
??庫(kù)的搜索路徑分為兩大類(lèi):默認(rèn)搜索路徑
和附加搜索路徑
。
??默認(rèn)搜索路徑包含cmake
定義的以CMAKE
開(kāi)頭的一些變量(例如CMAKE_LIBRARY_ARCHITECTURE
仍侥、CMAKE_PREFIX_PATH
要出、CMAKE_LIBRARY_PATH
、CMAKE_FRAMEWORK_PATH
)农渊、標(biāo)準(zhǔn)的系統(tǒng)環(huán)境變量(例如系統(tǒng)環(huán)境變量LIB
和PATH
定義的路徑)厨幻、系統(tǒng)的默認(rèn)的庫(kù)安裝路徑(例如/usr
、/usr/lib
等);
??附加搜索路徑即find_library
命令中通過(guò)HINTS
或PATHS
指定的路徑况脆;
- 當(dāng)指定
NO_DEFAULT_PATH
選項(xiàng)時(shí)饭宾,默認(rèn)搜索路徑不會(huì)生效,只會(huì)用到附加搜索路徑格了。修改頂層的CMakeLists.txt
看铆,在find_library
中指定選項(xiàng)NO_DEFAULT_PATH
,可以看到即使指定了CMAKE_XXX_PATH
的值盛末,也會(huì)被忽略弹惦,下面的代碼執(zhí)行cmake .
(建議在執(zhí)行之前rm CMakeCache.txt
刪除)會(huì)提示錯(cuò)誤,而去除NO_DEFAULT_PATH
選項(xiàng)后能正常找到庫(kù)的路徑悄但。
// 頂層CMakeLists.txt
set (CMAKE_LIBRARY_PATH "./mylib")
find_library (libvar mymath ./mylib2 NO_DEFAULT_PATH)
// 執(zhí)行"cmake ."后的提示
CMake Error at CMakeLists.txt:23 (message):
required mymath library but not found!
- 當(dāng)未指定
NO_DEFAULT_PATH
選項(xiàng)時(shí)棠隐,搜索路徑按照優(yōu)先級(jí)從高到低
依次是:
?1) 通過(guò)命令行使用-D
指定的CMAKE_XXX_PATH
變量,也就是形如cmake . -DCMAKE_XXX_PATH=paths
的格式檐嚣。其中CMAKE_XXX_PATH
包含如下幾個(gè):
??CMAKE_PREFIX_PATH
:指定搜索目錄的前綴助泽,如果前綴有多個(gè),需要以分號(hào)分割的列表
方式提供嚎京,該變量默認(rèn)為空嗡贺,一旦該變量非空,那么會(huì)搜索該變量提供的目錄鞍帝,以及${CMAKE_PREFIX_PATH}/lib
;例如CMAKE_PREFIX_PATH=A;B
诫睬,那么find_library
會(huì)從A
、B
以及A/lib
帕涌、B/lib
中搜索庫(kù)是否存在摄凡;
??CMAKE_LIBRARY_ARCHITECTURE
:如果該變量被設(shè)置歪脏,那么會(huì)搜索目錄${CMAKE_PREFIX_PATH}/lib/${CMAKE_LIBRARY_ARCHITECTURE}
;
??CMAKE_LIBRARY_PATH
:指定find_library
的庫(kù)查找目錄贤旷,默認(rèn)值為空,多個(gè)值時(shí)需要以分號(hào)分割列表指定券膀;
??CMAKE_FRAMEWORK_PATH
*:指定macOS
的框架作為搜索路徑辟躏。
// 頂層CMakeLists.txt
make_minimum_required (VERSION 3.21)
project (fl)
find_library (libvar mymath)
if (${libvar} STREQUAL "libvar-NOTFOUND")
message (FATAL_ERROR "required mymath library but not found!")
else()
message (STATUS "mymath library found in ${libvar}")
endif()
> cmake . -DCMAKE_LIBRARY_PATH=./mylib
-- mymath library found in /XXX/mylib/libmymath.a
?2) 通過(guò)在環(huán)境變量中指定CMAKE_XXX_PATH
變量谷扣,例如在window
的環(huán)境變量中增加CMAKE_XXX_PATH
(以;
分割多個(gè)路徑)土全、Linux
中shell
配置文件中添加(以:
分割多個(gè)路徑)捎琐。用法和cmake -D
指定類(lèi)似,例如在我的機(jī)器中(macOS
),在.zshrc
(我的命令行配置文件)中增加export CMAKE_LIBRARY_PATH="/XXX/……/mylib"
裹匙,即可在將該目錄加入到搜索路徑中瑞凑。
?3) HINTS
選項(xiàng)指定的路徑。
?4) 系統(tǒng)環(huán)境變量指定的目錄概页,默認(rèn)是LIB
和PATH
指定的路徑籽御。例如在PATH
中指定庫(kù)搜索目錄;
// 頂層CMakeLists.txt
make_minimum_required (VERSION 3.21)
project (fl)
find_library (libvar mymath)
if (${libvar} STREQUAL "libvar-NOTFOUND")
message (FATAL_ERROR "required mymath library but not found!")
else()
message (STATUS "mymath library found in ${libvar}")
endif()
// 命令行中執(zhí)行
export PATH=$PATH:./mylib
cmake .
// 執(zhí)行結(jié)果
-- mymath library found in /XXX/mylib/libmymath.a
?也可以通過(guò)find_library
中的PATHS ENV 環(huán)境變量名稱(chēng)
(cmake
中使用環(huán)境變量名稱(chēng)的格式為$ENV{環(huán)境變量名稱(chēng)}
)來(lái)指定從哪個(gè)環(huán)境變量名稱(chēng)中獲取路徑,例如定義一個(gè)TESTPATH
環(huán)境變量并賦值為./mylib
技掏,并在find_library
命令中指定使用該環(huán)境變量:
// 頂層CMakeLists.txt
make_minimum_required (VERSION 3.21)
project (fl)
find_library (libvar mymath PATHS ENV TESTPATH)
if (${libvar} STREQUAL "libvar-NOTFOUND")
message (FATAL_ERROR "required mymath library but not found!")
else()
message (STATUS "mymath library found in ${libvar}")
endif()
// 命令行中執(zhí)行
export TESTPATH=./mylib
cmake .
// 執(zhí)行結(jié)果
-- mymath library found in /XXX/mylib/libmymath.a
?5)跟當(dāng)前系統(tǒng)相關(guān)的平臺(tái)文件路徑铃将,一般來(lái)說(shuō)指的是當(dāng)前系統(tǒng)安裝軟件的標(biāo)準(zhǔn)目錄,不同的操作系統(tǒng)對(duì)應(yīng)的路徑有所不同哑梳。camke
中find_library
與此相關(guān)的也有如下幾個(gè)劲阎,CMAKE_SYSTEM_XXX_PATH
變量,這些:
??CMAKE_SYSTEM_PREFIX_PATH
:指定安裝目錄的前綴鸠真,例如在Windows
下的/XXXX/Program Files
悯仙,Linux
下的/usr
或/usr/local
等。find_library
命令會(huì)搜索這些前綴目錄吠卷,也會(huì)以這些目錄加上lib
進(jìn)行搜索锡垄,例如搜索/usr/local/lib
;
??CMAKE_SYSTEM_LIBRARY_PATH
:默認(rèn)是當(dāng)前系統(tǒng)的標(biāo)準(zhǔn)目錄祭隔,不建議修改它货岭;例如在我的系統(tǒng),這個(gè)變量的值是/usr/lib/X11
序攘;
??CMAKE_SYSTEM_FRAMEWORK_PATH
:macOS
框架路徑茴她,默認(rèn)是當(dāng)前系統(tǒng)的標(biāo)準(zhǔn)目錄,不建議修改它程奠;例如在我的系統(tǒng)丈牢,這個(gè)變量的值包含了路徑/Library/Frameworks
;
?6)PATHS
選項(xiàng)指定的路徑瞄沙。
3.2 find_library
命令中的部分選項(xiàng)
-
PATH_SUFFIXES
:為每個(gè)搜索目錄添加變量PATH_SUFFIXES
指定的后綴目錄己沛,假設(shè)當(dāng)前搜索的目錄為/A;/C/D
,PATH_SUFFIXES
指定的后綴目錄為PS
(當(dāng)前可以指定多個(gè)距境,以分號(hào)分割開(kāi)即可)申尼,那么除了/A;/C/D
之外,/A/PS;/C/D/PS
也會(huì)被搜索垫桂。
// 頂層CMakeLists.txt
make_minimum_required (VERSION 3.21)
project (fl)
find_library (libvar mymath PATHS ./ PATH_SUFFIXES mylib) # 會(huì)從./以及./mylib中搜索指定的mymath庫(kù)是否存在
if (${libvar} STREQUAL "libvar-NOTFOUND")
message (FATAL_ERROR "required mymath library but not found!")
else()
message (STATUS "mymath library found in ${libvar}")
endif()
// 命令行中執(zhí)行
cmake .
// 執(zhí)行結(jié)果
-- mymath library found in /XXX/mylib/libmymath.a
-
NO_CACHE
:該選項(xiàng)將<var>
變量當(dāng)成一個(gè)普通變量而不是一個(gè)緩存條目师幕,需要cmake 3.21及以上
的版本支持。
默認(rèn)find_library
命令最終存儲(chǔ)結(jié)果的變量<var>
是一個(gè)緩存條目(可以理解為全局變量诬滩,且會(huì)寫(xiě)入CMakeCache.txt
文件霹粥,在不清除CMakeCache.txt
文件的情況下,每次執(zhí)行cmake
都會(huì)先從CMakeCache.txt
載入該變量的值)疼鸟,而且find_library
命令只要檢查到<var>
有值(<var>
不為空且<var>
不為<var>-NOTFOUND
)后控,是不會(huì)執(zhí)行實(shí)際查找?guī)斓膭?dòng)作。因此多次對(duì)同一個(gè)變量<var>
執(zhí)行find_library
命令空镜,在第一次<var>
被賦值后浩淘,后續(xù)的find_library
命令不會(huì)被執(zhí)行捌朴。結(jié)合緩存條目變量,那么只要找到一個(gè)<var>
张抄,后續(xù)每次執(zhí)行cmake
命令得到的<var>
都是首次找到的<var>
值(除非清除CMakeCache.txt
文件)
因此NO_CACHE
選項(xiàng)要謹(jǐn)慎使用砂蔽,它會(huì)使得每次cmake
命令都會(huì)重新調(diào)用find_library
查找,增加cmake
的開(kāi)銷(xiāo)署惯。
// 頂層CMakeLists.txt
make_minimum_required (VERSION 3.21)
project (fl)
find_library (libvar mymath PATHS ./mylib NO_CACHE)
find_library (libvar mymath PATHS ./lib NO_CACHE) # 即使./lib中也存在mymath庫(kù)察皇,由于在上一步的./mylib中已經(jīng)找到,因此本條命令不會(huì)執(zhí)行查找
if (${libvar} STREQUAL "libvar-NOTFOUND")
message (FATAL_ERROR "required mymath library but not found!")
else()
message (STATUS "mymath library found in ${libvar}")
endif()
// 命令行中執(zhí)行
cmake .
// 執(zhí)行結(jié)果
-- mymath library found in /XXX/mylib/libmymath.a
// 頂層CMakeLists.txt
make_minimum_required (VERSION 3.21)
project (fl)
find_library (libvar mymath PATHS ./mylib) # libvar是緩存條目泽台,會(huì)存入`CMakeCache.txt`什荣,后續(xù)即使把PATHS ./mylib改成PATHS ./mylib2(不存在庫(kù)mymath),也不會(huì)保存怀酷,因?yàn)閘ibvar變量已經(jīng)從緩存中載入
if (${libvar} STREQUAL "libvar-NOTFOUND")
message (FATAL_ERROR "required mymath library but not found!")
else()
message (STATUS "mymath library found in ${libvar}")
endif()
// 命令行中執(zhí)行
cmake .
// 執(zhí)行結(jié)果
-- mymath library found in /XXX/mylib/libmymath.a
// 可以在CMakeCache.txt中找到libvar稻爬,命令行中執(zhí)行cat命令查看一下
> cat CMakeCache.txt | grep "libvar"
libvar:FILEPATH=/XXX/mylib/libmymath.a
// 即使此時(shí)把頂層CMakeLists.txt中的PATHS修改為不包含mymath庫(kù)的路徑,執(zhí)行結(jié)果也能找到
find_library (libvar mymath PATHS ./mylib2)
// cmake .執(zhí)行結(jié)果
-- mymath library found in /XXX/mylib/libmymath.a
-
REQUIRED
:指定該選項(xiàng)后蜕依,當(dāng)找不到庫(kù)桅锄,會(huì)輸出一條錯(cuò)誤信息并終止cmake
處理過(guò)程;未指定REQUIRED
選項(xiàng)样眠,當(dāng)find_library
未找到庫(kù)時(shí)友瘤,后續(xù)find_library
有針對(duì)<var>
的調(diào)用會(huì)繼續(xù)查找。該選項(xiàng)需要cmake 3.18及以上
的版本支持檐束。
// 頂層CMakeLists.txt
make_minimum_required (VERSION 3.21)
project (fl)
find_library (libvar mymath PATHS ./mylib REQUIRED)
if (${libvar} STREQUAL "libvar-NOTFOUND")
message (FATAL_ERROR "required mymath library but not found!")
else()
message (STATUS "mymath library found in ${libvar}")
endif()
// 命令行中執(zhí)行
cmake .
// 執(zhí)行結(jié)果
CMake Error at CMakeLists.txt:4 (find_library):
Could not find libvar using the following names: mymath
-- Configuring incomplete, errors occurred!
// 頂層CMakeLists.txt
cmake_minimum_required (VERSION 3.21)
project (fl)
find_library (libvar mymath PATHS ./mylib2) # 沒(méi)有指定REQUIRED選項(xiàng)辫秧,即使當(dāng)時(shí)沒(méi)有找到,會(huì)繼續(xù)往下執(zhí)行
find_library (libvar mymath PATHS ./mylib)
if (${libvar} STREQUAL "libvar-NOTFOUND")
message (FATAL_ERROR "required mymath library but not found!")
else()
message (STATUS "mymath library found in ${libvar}")
endif()
// 命令行中執(zhí)行
cmake .
// 執(zhí)行結(jié)果
-- mymath library found in /XXX/mylib/libmymath.a
NO_XXX_PATH
:3.1節(jié)
介紹了關(guān)于搜索路徑的查找順序被丧,NO_XXX_PATH
選項(xiàng)用于跳過(guò)指定的搜索路徑盟戏。
NO_CMAKE_PATH
:指定該選項(xiàng)會(huì)忽略cmake -DCMAKE_XXX_PATH=paths
的路徑;
NO_CMAKE_ENVIRONMENT_PATH
:指定該選項(xiàng)會(huì)忽略環(huán)境變量指定的CMAKE_XXX_PATH
路徑甥桂;
NO_SYSTEM_ENVIRONMENT_PATH
:指定該選項(xiàng)會(huì)忽略系統(tǒng)標(biāo)準(zhǔn)環(huán)境變量指定的路徑柿究;
NO_CMAKE_SYSTEM_PATH
:指定該選項(xiàng)會(huì)忽略平臺(tái)路徑指定的CMAKE_SYSTEM_XXX_PATH
路徑;CMAKE_FIND_ROOT_PATH
:指定搜索的根路徑黄选。CMAKE_SYSROOT
:該選項(xiàng)的值會(huì)傳遞給編譯器的--sysroot
標(biāo)記(備注:--sysroot
用于指定編譯搜索庫(kù)和頭文件的根目的蝇摸,例如編譯器原本搜搜索/A/include
和/A/lib
,使用--sysroot=DIR
后办陷,編譯器搜索的庫(kù)和頭文件目錄變成/DIR/A/include
和/DIR/A/lib
)貌夕。FIND_LIBRARY_USE_LIB32_PATHS
、FIND_LIBRARY_USE_LIBX32_PATHS
懂诗、FIND_LIBRARY_USE_LIB64_PATHS
:這三個(gè)屬性指明了要在搜索路徑中匹配到lib/
后蜂嗽,會(huì)為這個(gè)目錄添加一個(gè)后綴苗膝,然后在添加后綴后的目錄中搜索庫(kù)殃恒。三個(gè)屬性添加后的值為lib32/
植旧、libx32/
、lib64/
离唐,這個(gè)是根據(jù)平臺(tái)(32位或64位自動(dòng)添加的)病附,例如在我的系統(tǒng)中,除了搜索lib/
外亥鬓,也會(huì)搜索lib64/
:
// 頂層CMakeLists.txt
cmake_minimum_required (VERSION 3.21)
project (fl)
find_library (libvar mymath PATHS ./lib) # 假設(shè)lib目錄不存在但是lib64目錄存在
if (${libvar} STREQUAL "libvar-NOTFOUND")
message (FATAL_ERROR "required mymath library but not found!")
else()
message (STATUS "mymath library found in ${libvar}")
endif()
// 命令行中執(zhí)行
cmake .
// 執(zhí)行結(jié)果
-- mymath library found in /XXX/lib64/libmymath.a
?