一般在使用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(<NAME> REQUIRED)是找不到库的。因为其实根本就不知道libNAME是什么。比如我的libBAYES.so,我在CMakeLists.txt里应该叫它Bayes呢还是BAYES呢?比如

find_pakcage(BayesOpt REQUIRED)

就会报错,程序找不到BayesOpt是个什么玩意儿,那么接下来怎么做呢?

1、在CMakeLists.txt相同目录下创建一个叫cmake_modules的文件夹,在里面创建一个名为FindBAYES.cmake的文件。命名格式Find<name>.cmake,这也增加了规范性。

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>.cmake中的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这个语句都省略了,不过这样做的话以后别人使用你的程序来扩展会比较麻烦

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐