一般在使用CMakelists进行编译的时候所有源文件都写在一个文件中了。但是我们使用过很多库发现他们都有一个文件夹叫cmake
或者cmake_modules
之类的。这类文件夹一般包含很多.cmake
文件,这类文件把本来该写在CMakeLists.txt
里的内容分散开来,用来找特定的库之类的。就好像我们写一个大型程序需要把很多功能分成特定的函数一样。
首先我有一个CMakeLists.txt
文件,里面的可执行程序需要链接到一个叫libBAYES.so
的动态共享库,头文件所在目录/usr/local/include
,库的位置位于/usr/local/lib
.
我们使用一些大型开源库的时候,他好像自己就能找到,因为它们已经自带.cmake
文件了,比如OpenCV
,我们只需要在CMakeLists.txt
里添加
find_package(OpenCV REQUIRED)
并把某可执行文件链接到${OpenCV_LIBS}
就可以了
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(test test.cpp)
target_link_libraries(test ${OpenCV_LIBS})
可是一些不知名的库,或者自己编译的库,你直接使用find_package(
是找不到库的。因为其实根本就不知道libNAME
是什么。比如我的libBAYES.so
,我在CMakeLists.txt
里应该叫它Bayes
呢还是BAYES
呢?比如
find_pakcage(BayesOpt REQUIRED)
就会报错,程序找不到BayesOpt是个什么玩意儿,那么接下来怎么做呢?
1、在CMakeLists.txt
相同目录下创建一个叫cmake_modules
的文件夹,在里面创建一个名为FindBAYES.cmake
的文件。命名格式Find
,这也增加了规范性。
2、在FindBAYES.cmake
中写入下面内容。
#Try to find BAYES library
find_path(BAYES_INCLUDE_DIR NAMES BAYES.h PATHS /usr/local/include
/usr/include
~/MyProject/include
...)
#会在几个候选的PATHS中找到头文件并把正确的目录赋给BAYES_INCLUDE_DIR
find_library(BAYES_LIBRARIES NAMES BAYES PATHS /usr/local/lib
/usr/lib
~/MyProject/iib
...)
#会在几个候选的PATHS中找到库文件并把完整的文件路径赋给BAYES_LIBRARIES
第一行命令要求寻找一个叫(NAMES)
BAYES.h
的头文件。并在CMakeLists.txt
中命名为BAYES_INCLUDE_DIR
.
第二行命令要求寻找一个叫(NAMES)
libBAYES.so
的库文件。并在CMakeLists.txt
中命名为BAYES_LIBRARIES
. 可以看到我们只是指定了BAYES
,并不是指定找libBAYES.so
(指定也行)。这是程序默认的。任何库的名字都是lib
开头。你只需要指定lib
后的那串字符就可以了。
3、在你的CMakeLists.txt
中,就可以加入我们cmake_modules
的位置
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules)
或
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules/")
如:
cmake_minimum_required(VERSION 2.8)
project(test)
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules/")
find_package(BAYES REQUIRED)
include_directories(${BAYES_INCLUDE_DIR})
add_executable(test test.cpp)
target_link_libraries(test ${BAYES_LIBRARIES})
list
那一行告诉cmake
在哪儿去找我们的.cmake
文件。之后输入我们要找的package
名称。这里正如前面所说的,我们需要把BAYES
这个名字和Find
中的name
对应起来。最后在可执行文件添加库链接的时候,那个库的名字和FindBAYES.cmake
中的find_library
中定义的名字一样。
保存CMakeLists.txt
之后就能正常编译了。
暴力链接库
如果你实在不想写.cmake
文件,但是又要链接到一个你不知道find_package(XXX REQUIRED)
中name是何物的库,你可以用一种很暴力的方法。
比如你知道你要链接的库的位置就是在/usr/local/lib/libABC.so
,你可以在target_link_libraries
中直接添加这个路径
target_link_libraries(${PROJECT_NAME} /usr/local/lib/libABC.so)
这种方法也是可以的!不仅不用写cmake
,而且连find_package
这个语句都省略了,不过这样做的话以后别人使用你的程序来扩展会比较麻烦