当前位置: 首页 > news >正文

CMake3: CMake的嵌套使用与自定义库

文章目录

  • 1. CMake嵌套使用
  • 2.自定义库(该库依赖第三方库实现)


1. CMake嵌套使用

如果项目很大,或者项目中有很多的源码目录,在通过CMake管理项目的时候如果只使用一个CMakeLists.txt,那么这个文件相对会比较复杂,有一种化繁为简的方式就是给每个源码目录都添加一个CMakeLists.txt文件(头文件目录不需要),这样每个文件都不会太复杂,而且更灵活,更容易维护。

当前文件的目录结构为:

.
├── bin
│   └── function_text
├── build
├── CMakeLists.txt
├── dataset
├── cmake_modules
├── include
│   ├── Frame.h
│   ├── ORBextractor.h
│   ├── ORBVocabulary.h
│   ├── system.h
│   ├── visual_odometry.h
│   └── visual_template.h
├── lib
│   └── libmyslam.so
├── src
│   ├── CMakeLists.txt
│   ├── Frame.cpp
│   ├── ORBextractor.cpp
│   ├── system.cpp
│   ├── visual_odometry.cpp
│   └── visual_template.cpp
├── test
│   ├── CMakeLists.txt
│   ├── function_text.cpp
│   └── main.cpp
└── ThirdParty└── DBoW2├── CMakeLists.txt├── DBoW2│   ├── BowVector.cpp│   ├── BowVector.h│   ├── FClass.h│   ├── FeatureVector.cpp│   ├── FeatureVector.h│   ├── FORB.cpp│   ├── FORB.h│   ├── ScoringObject.cpp│   ├── ScoringObject.h│   └── TemplatedVocabulary.h├── DUtils│   ├── Random.cpp│   ├── Random.h│   ├── Timestamp.cpp│   └── Timestamp.h├── lib│   └── libDBoW2.so├── LICENSE.txt└── README.txt

根目录包含的内容一般包含以下几个文件:

  • bin : 存储生成的可执行二进制文件,可在CMakeLists.txt中指定路径
  • build :存储查找链接库时生成的中间文件
  • include:放置函数的头文件
  • src : 放置函数的源文件
  • lib : 放由函数文件所生成的静态库(.a)和动态库(.so)可在CMakeLists.txt中指定路径
  • test : 存放主函数以及需要测试的文件(可撰写多个主函数,在CMakeLists.txt指定编译)
  • cmake_modules :里边的文件以.cmake结尾,存放着库文件的路径,供find_package查询(文件名Find×××.cmake)
  • dataset : 存放运行程序所需要的数据集
  • CMakeLists.txt : 撰写该文件指导整个项目的编译,可存在于不同的目录下(上述在根目录,src以及text文件内均存在CMakeLists.txt)
  • ThirdParty :存放一些修改过的第三方库

(1)编写顶层的CMakeLists.txt

Linux的目录是树状结构,所以嵌套的 CMake 也是一个树状结构,最顶层的 CMakeLists.txt 是根节点,其次都是子节点。

注意:CMakeLists.txt 文件变量作用域有如下关系

  • 根节点CMakeLists.txt中的变量全局有效
  • 父节点CMakeLists.txt中的变量可以在子节点中使用
  • 子节点CMakeLists.txt中的变量只能在当前节点中使用

顶层,即根目录下的CMakeLists.txt内容为:

cmake_minimum_required(VERSION 2.8)
project(myslam)#设置编译方式
set(CMAKE_BUILD_TYPE Debug)#设置C++标准
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall")
#设置可执行文件输出路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
#设置库文件输出路径
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)############### dependencies ######################
find_package(OpenCV REQUIRED)#包含头文件的路径
include_directories(
${PROJECT_SOURCE_DIR}
${OpenCV_INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}/ThirdParty
"/usr/include/eigen3"
)#给定自定义的库文件的路径
link_directories(${PROJECT_SOURCE_DIR}/TirdParty/DBoW2/lib)set(THIRD_PARTY_LIBS${OpenCV_LIBS}libDBoW2.so)
add_subdirectory(src)
add_subdirectory(test)

(2)编写src下的CMakeLists.txt,用于编译库文件

#获取当前文件夹下的所有源文件
aux_source_directory( ./ SRC_LIST)
#添加库文件
add_library(myslam SHARED   ${SRC_LIST})
#将生成的库文件与第三方库进行链接
target_link_libraries(myslam ${THIRD_PARTY_LIBS})
# 旧版本 CMake 中 target_link_libraries 默认是 PRIVATE 行为

(3)编写test下的CMakeLists.txt,用于编译主函数

add_executable(main_outcar main.cpp )
target_link_libraries(main_outcar myslam${THIRD_PARTY_LIBS})
#由前面注释知,(2)中的连接为 PRIVATE 行为,所以需要再连接一次add_executable(function_text function_text.cpp)
target_link_libraries(function_text myslam ${THIRD_PARTY_LIBS})
# 同上

2.自定义库(该库依赖第三方库实现)

将以上的文件修改,作为当前文件目录(不包含test文件夹):

.
├── build
├── CMakeLists.txt
├── include
│   ├── Frame.h
│   ├── ORBextractor.h
│   ├── ORBVocabulary.h
│   ├── system.h
│   ├── visual_odometry.h
│   └── visual_template.h
├── src
│   ├── CMakeLists.txt
│   ├── Frame.cpp
│   ├── ORBextractor.cpp
│   ├── system.cpp
│   ├── visual_odometry.cpp
│   └── visual_template.cpp
└── ThirdParty└── DBoW2├── CMakeLists.txt├── DBoW2│   ├── BowVector.cpp│   ├── BowVector.h│   ├── FClass.h│   ├── FeatureVector.cpp│   ├── FeatureVector.h│   ├── FORB.cpp│   ├── FORB.h│   ├── ScoringObject.cpp│   ├── ScoringObject.h│   └── TemplatedVocabulary.h├── DUtils│   ├── Random.cpp│   ├── Random.h│   ├── Timestamp.cpp│   └── Timestamp.h├── lib│   └── libDBoW2.so├── LICENSE.txt└── README.txt

(1)编写带安装命令的CMakeLists.txt

在根目录下编写CMakeLists.txt为:

cmake_minimum_required(VERSION 2.8)
project(myslam)
# 使用Debug或Release都可
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall")
set(CMAKE_CXX_FLAGS_RELEASE  "-std=c++11 -O3 -fopenmp -pthread")############### dependencies ######################
# OpenCV
find_package(OpenCV  REQUIRED)
include_directories(#opencv头文件路径${OpenCV_INCLUDE_DIRS}#自定义库的头文件路径${PROJECT_SOURCE_DIR}/include#第三方库的头文件路径(注:此处应与实际代码对应)#如:我的代码为#include "DBoW2/DBoW2/BowVector.h";因此上面加入的路径到ThirdParty就为止了${PROJECT_SOURCE_DIR}/ThirdParty#eigen库的头文件,该库全是头文件,无库文件,故后续无需链接"/usr/include/eigen3"
)#因为该库未安装到系统目录,也没有使用find_package指令进行查找,故在此处需要该库文件的路径
link_directories(${PROJECT_SOURCE_DIR}/TirdParty/DBoW2/lib)set(THIRD_PARTY_LIBS${OpenCV_LIBS}libDBoW2.so)#添加子文件夹,在子文件夹中编译库文件
add_subdirectory(src)

在src目录下编写CMakeLists.txt为:

# 将当前目录下的所有源文件添加到 SRC_LIST 变量中
aux_source_directory(./ SRC_LIST)# 创建名为 myslam 的共享库,使用 SRC_LIST 中的源文件进行编译
add_library(myslam SHARED ${SRC_LIST})# 将 myslam 库链接到 THIRD_PARTY_LIBS 中指定的第三方库
target_link_libraries(myslam ${THIRD_PARTY_LIBS})# 设置 myslam 库的版本为 PROJECT_NAME
set_target_properties(myslam PROPERTIES VERSION ${PROJECT_NAME})# 将 myslam 库安装到指定目录
install(TARGETS myslam#安装动态库使用这行指令 DESTINATION指定安装目录LIBRARY DESTINATION /usr/local/lib#安装静态库使用这行指令ARCHIVE DESTINATION /usr/local/lib
)# 将 include 目录下的所有头文件安装到指定目录
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include DESTINATION /usr/local/include/myslam# 匹配${PROJECT_SOURCE_DIR}/include 下的所有.h文件进行安装FILES_MATCHING PATTERN "*.h")# 还可加一些install命令,让其生成对应的Findmyslam.cmake或myslamConfig.cmake文件,这样就不用自己写配置文件了;具体指令目前尚未尝试

(2)生成带安装指令的库文件并安装的系统目录

在根目录build文件夹中,执行指令:

cmake ..
make#待成功编译后
sudo make install

生成的库文件名称为libmyslam.so

安装成功后显示:

在这里插入图片描述

注:第一行的libmyslam.so.myslam,最后一个myslam即为之前指定的版本号,用的是project_name

在相应的系统路径可查询为:

在这里插入图片描述

(3)新建一个工作空间,使用安装到系统的myslam库文件

新的工作空间为:

├── CMakeLists.txt
├── build
├── cmake_modules
│   └── Findmyslam.cmake
└── main.cpp

主函数main.cpp如下,该程序只使用了一个system.h的头文件:

#include <iostream>
#include <vector>
#include <string>
#include "system.h"void Loadimage(const string&  Datafilepath,vector<string>& file_names);
int main(int argc, char **argv)
{vector<string> file_names;Loadimage(string(argv[1]),file_names);  System SLAM;SLAM.TrackRGB(file_names);SLAM.SaveTrajectory(SLAM.GetExpTrajectory(),"./coordinate.csv");return 0;
}

新的工作空间下的CMakeLists.txt为:

cmake_minimum_required(VERSION 2.8)
project(Test_slam)# 设置 C++ 标准为 C++11
set(CMAKE_CXX_STANDARD 11)# 将自定义的模块路径添加到 CMake 模块路径中
set(CMAKE_MODULE_PATH  ${PROJECT_SOURCE_DIR}/cmake_modules ${CMAKE_MODULE_PATH})# 查找并加载名为 myslam 的 CMake 配置文件
find_package(myslam REQUIRED)# 将 myslam 的头文件路径添加到包含目录中
include_directories(${MYSLAM_INCLUDE_DIRS})# 添加可执行文件 main_outcar,使用 main.cpp 源文件
add_executable(main_outcar main.cpp )
# 将 myslam 库链接到 main_outcar 可执行文件中
target_link_libraries(main_outcar ${MYSLAM_LIBRARIES})

Findmyslam.cmake文件的编写如下:

注:这是固定格式的名称 Find库名.cmake;

# 检查是否已经找到 myslam 库
if(NOT MYSLAM_FOUND)
# 使用 find_path 查找指定的 .h 文件路径,并将结果存储到 MYSLAM_INCLUDE_DIRS 变量中# MYSLAM_INCLUDE_DIRS为变量,内存储的是路径find_path(MYSLAM_INCLUDE_DIRS#引入的头文件,此处不支持使用变量"system.h"#头文件的系统路径/usr/local/include/myslam/include)# 使用 find_library 查找指定的库文件,并将结果存储到 MYSLAM_LIBRARIES 变量中# MYSLAM_LIBRARIES为变量,内存储的是路径 + lib库名.sofind_library(MYSLAM_LIBRARIESmyslam/usr/local/lib)# 因为本库还依赖第三方库实现,需在此处引入连接find_package(OpenCV REQUIRED)# 添加需要的头文件include_directories(${OpenCV_INCLUDE_DIRS}"/usr/include/eigen3""/home/wheeltec-client/Desktop/Neuroslam/NeuroSlam_cpp/NeuroSLAM_MATLABtocpp-neuroslam_v2.0/TirdParty")# 添加链接目录,链接到指定的库文件目录link_directories(/home/wheeltec-client/Desktop/Neuroslam/NeuroSlam_cpp/NeuroSLAM_MATLABtocpp-neuroslam_v2.0/TirdParty/DBoW2/lib)# 设置 MYSLAM_LIBRARIES 变量,包含 myslam 库、libDBoW2.so、以及 OpenCV 的库文件set(MYSLAM_LIBRARIES${MYSLAM_LIBRARIES}libDBoW2.so${OpenCV_LIBS})# 设置库的找到标志为 TRUEset(MYSLAM_FOUND TRUE)
endif()

最后在build目录下编译:

cmake ..
make
http://www.dtcms.com/a/342115.html

相关文章:

  • Spring Event 企业级应用
  • 笔试——Day45
  • Prompt魔法:提示词工程与ChatGPT行业应用读书笔记:提示词设计全能指南
  • 第四章:大模型(LLM)】07.Prompt工程-(7)角色提示
  • Flink基础
  • 解锁工业级Prompt设计,打造高准确率AI应用
  • Web自动化测试:测试用例流程设计
  • Java设计模式-解释器模式
  • 策略模式 vs 适配器模式
  • 基于STM32设计的大棚育苗管理系统(4G+华为云IOT)_265
  • 移动应用抓包与调试实战 Charles工具在iOS和Android中的应用
  • 数据结构初阶:详解二叉树(三):链式二叉树
  • system\core\init\init.cpp----LoadBootScripts()解析init.rc(1)
  • STM32之串口详解
  • 学习Linux嵌入式(正点原子imx课程)开发到底是在学什么
  • Spring Cloud Netflix学习笔记06-Zuul
  • Kafka消息持久化机制全解析:存储原理与实战场景
  • Kafka集成Flume
  • 人工智能 -- 循环神经网络day1 -- 自然语言基础、NLP基础概率、NLP基本流程、NLP特征工程、NLP特征输入
  • 算法 之 拓 扑 排 序
  • LeetCode 回文链表
  • 桥梁设计模式
  • RabbitMQ事务消息原理是什么
  • RabbitMQ:延时消息(死信交换机、延迟消息插件)
  • 领域专用AI模型训练指南:医疗、法律、金融三大垂直领域微调效果对比
  • 28、工业网络资产漏洞扫描与风险评估 (模拟) - /安全与维护组件/industrial-network-scanner
  • 深度解析Atlassian 团队协作套件(Jira、Confluence、Loom、Rovo)如何赋能全球分布式团队协作
  • Whisk for Mac 网页编辑器 PHP开发
  • 牛客:链表的回文结构详解
  • NewsNow搭建喂饭级教程