linux知识点——CMakeLists.txt中调用自己编写的so库

参考:https://blog.csdn.net/qq_41253960/article/details/121256498

1 问题

在使用ceres库时,CMakeLists.txt中出现:

...

# 添加cmake模块以使用ceres库
list( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules )

# 寻找Ceres库并添加它的头文件
find_package( Ceres REQUIRED )
include_directories( ${CERES_INCLUDE_DIRS} )

...

不太理解 list在这里的作用

2 解决

2.1 .cmake文件方法

之前接触的例子都是源文件和头文件都写在同一个文件下,或者是调用安装到/usr/local/include和/usr/local/lib中的库和头文件(如果ceres安装时没有执行sudo make install也不会安装到该目录下,也需要用现在讨论的list方法调用),之前没有调用过自己生成的so动态库文件。可以发现,我们使用过很多库他们都有一个文件夹叫cmake或者cmake_modules之类的。这类文件夹一般包含很多.cmake文件,这类文件把本来该写在CMakeLists.txt里的内容分散开来,用来找特定的库之类的。就好像我们写一个大型程序需要把很多功能分成特定的函数一样。

对于安装到本地的库(头文件所在目录/usr/local/include,库的位置位于/usr/local/lib.),一些大型的开源库,例如OpenCV,在输入:

find_package(OpenCV REQUIRED)

他就可以自己就能找到库,因为它们已经自带.cmake文件了,可以获取到头文件目录和库目录,并且把可执行文件链接到库

include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(test test.cpp)
target_link_libraries(test ${OpenCV_LIBS})

可是一些不知名的库,或者自己编译的库,你直接使用find_package(<NAME> REQUIRED)是找不到库的。因为其实根本就不知道libNAME.so在哪里。例如,我自己生成的libPOSE.so

find_pakcage(POSE REQUIRED)

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

2、在FindPOSE.cmake中写入下面内容。

find_path(POSE_INCLUDE_DIRS NAMES pose.h PATHS /usr/local/include
											  /usr/include
											  ../pose
												...)
#会在几个候选的PATHS中找到头文件并把正确的目录赋给POSE_INCLUDE_DIRS
# .cmake所在目录是CMmakeLists.txt所在目录,如../pose是在CMakeLists.txt的上级目录
find_library(POSE_LIBRARIES NAMES poselib PATHS /usr/local/include
												/usr/include
 											    ../pose/build
												...)
#会在几个候选的PATHS中找到库文件并把完整的文件路径赋给BAYES_LIBRARIES

第一行命令要求寻找一个叫(NAMES) pose.h的头文件。并在CMakeLists.txt中命名为POSE_INCLUDE_DIRS.(后续cmakelists.txt中include_directories(${POSE_INCLUDE_DIRS})调用),POSE_INCLUDE_DIRS中的POSE名称尽量与FindPOSE.cmake中的POSE一致。

第二行命令要求寻找一个叫(NAMES) libposelib.so的库文件。并在CMakeLists.txt中命名为POSE_LIBRARIES . 可以看到我们只是指定了poselib,并不是指定找libposelib.so(指定也行)。这是程序默认的。任何库的名字都是lib开头。你只需要指定lib后的那串字符就可以了

3、在你的CMakeLists.txt中,加入下面的这句话(list)决定我们在哪儿去找.cmake文件。

set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules)

或者

list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules/")

然后再find_package(POSE REQUIRED) 这个POSE与FindPOSE.cmake中的POSE一致。

cmake_minimum_required(VERSION 2.8)
project(demo)
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules/")
find_package(POSE REQUIRED)  # POSE --> FindPOSE.cmake
include_directories(${POSE_INCLUDE_DIRS})
add_executable(demo main.cpp)
target_link_libraries(demo ${POSE_LIBRARIES})
2.2 暴力链接库方法

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

3 例子

主要从调用so库举例,在例子中说明list的用法。

–pose
– --pose.cpp
– --pose.h
– --CMakeLists.txt
– --build
–main
– --main.cpp
– --cmake_modules
– – --FindPOSE.cmake
– --CMakeLists.txt
– --build

3.1 生成libposelib.so

pose/pose.cpp:

#include"pose.h"  //千万不要漏了
int pose(int a, int b)
{
   return (a+b);
}

pose/pose.h:

int pose(int a, int b);

pose/CMakeLists.txt:

cmake_minimum_required( VERSION 2.8)
add_library(poselib SHARED pose.cpp)

在build下面生成libposelib.so,前面的lib会自动加上

3.2 调用so库

main/cmake_modules/FindPOSE.cmake:

#Try to find BAYES library
find_path(POSE_INCLUDE_DIRS NAMES pose.h PATHS /usr/local/include
											  /usr/include
											  /home/w/SLlife/3.cmake/pose
											  ../pose
											  ...)
#会在几个候选的PATHS中找到头文件并把正确的目录赋给BAYES_INCLUDE_DIR

find_library(POSE_LIBRARIES NAMES poselib PATHS /usr/local/include
												/usr/include
 											    ../pose/build
												...)
#会在几个候选的PATHS中找到库文件并把完整的文件路径赋给BAYES_LIBRARIES

问题,这里不写绝对路径,应该怎么写-----换成相对路径,.cmake所在目录是CMmakeLists.txt所在目录,如../pose是在CMakeLists.txt的上级目录

注意:一个是find_path,另一个是find_library
main/CMakeLists.txt:

cmake_minimum_required(VERSION 2.8)
project(demo)
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules/")
find_package(POSE REQUIRED)  # POSE --> FindPOSE.cmake
include_directories(${POSE_INCLUDE_DIRS})
add_executable(demo main.cpp)
target_link_libraries(demo ${POSE_LIBRARIES})

main/main.cpp:

#include<iostream>
#include"pose.h"

using namespace std;

int main()
{
	int a=8, b=9;
	int c = pose(a, b);
	cout<<"c: "<<c<<endl;
	return 0;
}
3.3 find_package原理

module模式和config模式,如果module模式下指定的路径没有找到对应的.cmake文件,则会去寻找/usr/local/lib/cmake/XXX/目录下的XXXConfig.cmake文件。
参考:https://blog.csdn.net/fb_941219/article/details/88526157

  • 7
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
CMake 生成动态(.so)的步骤如下: 1. 在 CMakeLists.txt 文件,使用 `add_library()` 函数来创建一个目标。 ```cmake add_library(mylib SHARED mylib.cpp) ``` 其,`mylib` 是的名称,`SHARED` 表示生成动态。 2. 如果需要引用其他,需要使用 `target_link_libraries()` 函数将这些链接到当前。 ```cmake target_link_libraries(mylib lib1 lib2) ``` 其,`lib1` 和 `lib2` 是需要链接的名称。 3. 如果需要使用头文件,需要使用 `target_include_directories()` 函数将头文件目录添加到头文件搜索路径。 ```cmake target_include_directories(mylib PUBLIC include) ``` 其,`include` 是头文件所在的目录。 4. 如果需要设置的输出路径,可以使用 `set_target_properties()` 函数。 ```cmake set_target_properties(mylib PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib) ``` 其,`LIBRARY_OUTPUT_DIRECTORY` 表示的输出路径,`${CMAKE_CURRENT_SOURCE_DIR}/lib` 表示当前 CMakeLists.txt 所在的目录下的 `lib` 子目录。 最终的 CMakeLists.txt 文件示例: ```cmake cmake_minimum_required(VERSION 3.10) project(mylib) # 创建目标 add_library(mylib SHARED mylib.cpp) # 链接其他 target_link_libraries(mylib PRIVATE lib1 lib2) # 添加头文件搜索路径 target_include_directories(mylib PUBLIC include) # 设置输出路径 set_target_properties(mylib PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib) ``` 在运行 `cmake` 和 `make` 命令后,就可以在上述设置的输出路径找到生成的动态了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值