CMake 实战

devtools/2024/11/14 7:20:03/

我现在项目的目录结构如下
project_root/
├── CMakeLists.txt
├── main.cpp 主函数
├── third_part/
│ ├── CMakeLists.txt # 总的 third_part CMakeLists.txt
│ ├── json/
│ │ ├── CMakeLists.txt # json 的 CMakeLists.txt
│ │ └── json.hpp
│ ├── spdlog/
│ │ ├── CMakeLists.txt # spdlog 的 CMakeLists.txt
│ │ ├── include/
│ │ │ └── spdlog/ # spdlog 的头文件
│ │ └── libspdlog.a # spdlog 静态库
│ ├── httplib/
│ │ ├── CMakeLists.txt # httplib 的 CMakeLists.txt
│ │ ├── httplib.cpp
│ │ └── httplib.h
│ └── inireader/
│ ├── CMakeLists.txt # INIReader 的 CMakeLists.txt
│ ├── ini.c
│ ├── ini.h
│ ├── INIReader.cpp
│ └── INIReader.h
├── basic/ # 业务基础代码
│ ├── CMakeLists.txt
│ ├── include/
│ ├── logic1.cpp
│ └── logicxxx.cpp

也即主函数,基础代码,第三方库。
第三方库有多种形式:
json :只有一个头文件
spdlog:有一个静态库和一个头文件目录
httplib:有一个头文件和源码文件
inireader:有两个头文件和两个源码文件

需要实现如下目标:

  1. 各个模块描述自己模块需要有哪些内容需要编译,哪些接口暴露出去。如果其他模块要使用本模块,只需用一行命令申明即可。编译时会自动链接这个模块,以及把模块的接口加入到头文件路径。
  2. third_part整个4个第三方库为一个库。其他模块只需要用一行命令导入third_part模块就能使用4个第三方库的功能。
    下面介绍各个目录下的CMakeLists.txt

CMakeLists

顶层

cmake_minimum_required(VERSION 3.10)  # cmake 版本最低为3.10
project(server)  # 设置工程名为serverset(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)  #把动态库放在build目录下的lib目录。
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)  #把静态库放在build目录下的lib目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)  #把可执行文件放在build目录下的bin目录# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)   # 设置C++标准
add_compile_definitions(SPDLOG_COMPILED_LIB)  # 添加编译器宏定义,即g++ -DSPDLOG_COMPILED_LIB,这个是spdlog要求的,这个库是日志库,哪里都用得到,所以在全局添加这个宏定义。# 读 子目录 third_part 和basic
add_subdirectory(third_part)  #引入子目录third_part的内容
add_subdirectory(basic) #引入子目录basic的内容add_executable(server main.cpp)  # 编译可执行文件,源文件只有一个erver.cpp,可执行文件名为server# 指定链接的库
target_link_libraries(server basic third_part mysqlcppconn)  # 指明 可执行文件依赖的模块,有本工程的basic模块和third_part模块,还有系统提供的mysqlcppconn模块。这个就是目标2

顶层配置了整个项目的信息,所以看起来多,但其实去掉注释也不多。引用别的模块很简单,就一个target_link_libraries加模块名,就完成引用了。

third_part

add_subdirectory(json)
add_subdirectory(httplib)
add_subdirectory(INIReader)
add_subdirectory(spdlog)add_library(third_part INTERFACE)
target_link_libraries(third_part INTERFACE json httplib INIReader spdlog)

显示指出需要引入哪些子文件夹的内容。
然后申明本模块的名称,以及本模块整合了哪些模块。别的模块只需要target_link_librairies third_part模块就可以使用这些第三方库,无需操心头文件在哪里,这个第三方库以什么方式提供。
这个就是目标2的实现。

httplib

add_library(httplib STATIC httplib.cc)
target_include_directories(httplib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

httplib是本模块的模块名,这里和目录名同名,和目录名同名不是强制的。

STATIC 表示本模块将以一个静态库的形式呈现。对应的还有SHARED。以动态库形式呈现。
以及INTERFACE,以只头文件(header-only)形式呈现。

PUBLIC:当前模块和使用该模块的模块都会使用的头文件
对应的还有:
INTERFACE:当前模块不会使用的头文件
PRIVATE:只有当前模块会使用的头文件

申明本模块的名称,本模块涉及的源文件。以及本模块的头文件。PUBLIC意味着直接或者间接引用本模块的模块,都能找到本模块的头文件。
这个就是目标1的实现。他告诉了cmake本模块如何编译链接。以及本模块哪些内容是需要暴露给其他模块的。

INIReader

add_library(INIReader STATIC ini.c INIReader.cpp)
target_include_directories(INIReader PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

同httplib

Spdlog

这个模块是一个静态库,所以有不同

add_library(spdlog STATIC IMPORTED GLOBAL) # 申明为global才能被全局发现
set_target_properties(spdlog PROPERTIESIMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/libspdlog.a)  #指明静态库的位置
set_target_properties(spdlog PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/include)  # 告诉外界这个静态库的头文件,让外界能够发现这个模块的头文件。

IMPORTED 告诉cmake这个库是从外部引入的,不需要生成任何规则来构建这个库。直接使用现成的。spdlog是那个被导入的库在本项目的别名。此后,在本项目中,都用这个别名指代那个外部导入的库。

GLOBAL 默认情况下,IMPORTED的库只能在当前目录以及子目录可见,GLOBAL可以拓展可见范围为全局。

json

add_library(json INTERFACE)
target_include_directories(json INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

只有头文件,则用INTERFACE
INTERFACE:当前模块不会使用的头文件
PRIVATE:只有当前模块会使用的头文件
PUBLIC:当前模块和使用该模块的模块都会使用的头文件

basic

file(GLOB SOURCES "*.cpp")
add_library(basic STATIC ${SOURCES})
target_include_directories(basic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(basic third_part)

basic下的所有.cpp文件都是需要编译的,第一条指令可以把当前目录下所有的.cpp文件列出来放到SOURCES变量中。
GLOB用于以列出符合指定模式的文件。
GLOB_RECURSE类似,但是他会列出子目录的。


http://www.ppmy.cn/devtools/133448.html

相关文章

vue的样式知识点

一、样式的定义 1、基本定义&#xff1a;Vue样式通常使用<style>标签在单文件组件中定义。这些样式可以应用于模板中的HTML元素。 2、全局样式&#xff1a;在Vue项目的根组件中引入全局样式文件&#xff0c;全局样式文件中的样式会应用到整个项目中的所有组件。 3、局…

智象未来(HiDream.ai):从科技创新启程,绘制智能未来新篇章

在人工智能领域飞速演进的当下&#xff0c;智象未来&#xff08;HiDream.ai&#xff09;作为全球领先的多模态生成式人工智能技术供应商&#xff0c;正以其独树一帜的视觉多模态大模型及创新应用&#xff0c;推动行业趋势的前进。智象未来&#xff08;HiDream.ai&#xff09;自…

【Linux】进程信号全攻略(一)

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; 信号的概念 二&#xff1a;&#x1f525; 信号产生的方式 &#x1f98b; 使用键盘&#x1f98b; 系统调用函数&#x1f98b; 软件条件&#x1f98b; 进程异…

渗透利器-kali工具 (第三章-4) sqlmap之sql注入原理利用

从sql注入到sqlmap的使用 一&#xff1a;认识sql注入漏洞 1.什么是sql注入&#xff1a; 攻击者通过构造不同的sql语句来实现对数据库的操作。 2.两个关键条件&#xff1a; 1.参数用户可以控制。 2.程序原本要执行的代码&#xff0c;拼接了用户输入的数据&#xff0c;然后去执行…

npm i 的时候报错: npm ERR! Error: EPERM: operation not permitted, rename

文章目录 噩梦解决办法总结 噩梦 最近改漏洞&#xff0c;这个项目删掉了 node_modules文件夹 重新安装依赖&#xff0c;结果安装一半的时候就一直报这个错。 然后查了很多方法&#xff0c;基本都是下面这些&#xff1a; 权限不够&#xff0c;以管理员运行cmd重新安装。清除 n…

网络安全:构建坚固的数字堡垒

网络安全&#xff1a;构建坚固的数字堡垒 在当今数字化时代&#xff0c;网络安全已经成为企业和个人不可忽视的重要议题。随着互联网的普及和信息技术的快速发展&#xff0c;网络攻击、数据泄露和隐私侵犯等问题日益严重&#xff0c;给企业和个人带来了巨大的风险和损失。本文…

可选链语法在javascript和typescript中的使用详解

可选链&#xff08;Optional Chaining&#xff09;在 JavaScript 和 TypeScript 中的使用非常相似。以下是一个详细的使用案例&#xff0c;包括解释和示例代码。 使用案例 假设我们有一个用户对象&#xff0c;包含用户的个人信息和地址信息。我们希望安全地访问用户的地址信息…

【网络安全 | 漏洞挖掘】隐藏的 DOS 技术

未经许可,不得转载。 文章目录 缺少对图片渲染参数的校验(高度和宽度)服务器根据GET参数获取数据识别从外部资源获取数据的服务缺少对图片渲染参数的校验(高度和宽度) 有时,你可能会上传个人头像或某个产品的图片。在这种情况下,检查渲染页面的行为非常重要,因为该页面…