clion--cmake内置常量---打算一锅端了

news/2025/3/15 0:56:15/
# cmakelists.txt文件讲解,以下语意不是都在同一个cmakelists.txt
message("${CMAKE_SOURCE_DIR} 是工程终极父级目录")
message("${CMAKE_BINARY_DIR} 是CMAKE_SOURCE_DIR下的一个cmake_build_<buildtype>目录")
message("${PROJECT_NAME} 是引用当前cmakelists.txt的project(<pro-name>) 的pro-name")
# 类似的PROJECT开头的都是以当前cmakelists为基准的目录
# 可以用cmake CMakeLists.txt指定cmake要解析cmakelists文件
message("${PROJECT_SOURCE_DIR}  ${PROJECT_BINARY_DIR} ${PROJECT_INCLUDE_DIR} 都默认指向pro-name")
# 那么就建议把变量自定义设置一下,比如说终极父级下有子项目test,在test下的cmakelists
set(PROJECT_SOURCE_DIR ${PROJECT_NAME}/src)#也就是test/src
#以后的构建文件编写有两种类型cmakelists + .cmake文件
#cmakelists主要负责构建过程,.cmake文件主要负责第三方库的寻找或安装,然后在cmakelists引入#自行生成库:含动态库和静态库
add_library(target_lib SHARE add.cpp)#不写SHARE默认静态

一些专业一点的解释(大佬博客)

project:用于定义项目名称、版本号和语言。

add_executable:用于添加可执行文件。第一个参数很重要,被称为target,可以作为target_xxx命令的接收对象。

add_library:用于添加库文件,可以创建静态库或动态库。第一个参数很重要,被称为target,可以作为target_xxx命令的接收对象。简单使用如下

add_library(test_lib a.cc b.cc) #默认生成静态库
add_library(test_lib SHARED a.cc b.cc) #默认生成静态库
add_definitions:用于添加宏定义,注意该命令没有执行顺序的问题,只要改项目中用了该命令定义宏,那么所有的源代码都会被定义这个宏 add_definitions(-DFOO -DBAR …) 。

add_subdirectory:用于添加子项目目录,如果有该条语句,就先会跑去执行子项目的cmake代码,这样会导致一些需要执行后立马生效的语句作用不到,比如include_directories和link_directories如果执行在这条语句后面,则他们添加的目录在子项目中无法生效。有些命令如target_include_directories和target_link_directories是根据目标target是否被链接使用来生效的,所以这些命令的作用范围与执行顺序无关,且恰好同一个cmake项目中产生的库文件是可以直接通过名称链接的,无论链接对象是在子目录还是父目录

target_link_libraries:用于将可执行文件或库文件链接到库文件或可执行文件。身为target_xxx的一员,很明显第二个参数也可以进行权限控制。

include_directories:用于指定头文件搜索路径,优点是简单直接,缺点是无法进行权限控制,一旦被执行后,后续的所有代码都能搜索到对应的文件路径。

target_include_directories:指定头文件搜索路径,并将搜索路径关联到一个target上,这里的target一般是指生成可执行程序命令里的target或者生成库文件的target,与上一个命令的不同点在于可以设置导出权限,比如现在我写了一个项目,这个项目引入了其他库,但是我不想让其他库的符号暴露出去(毕竟使用这个项目的人只关注这个项目的接口,不需要关注其他依赖的接口)可以通过PRIVATE将头文件搜索目录设置不导出的权限。

link_directories:与前面的include_directories命令类似,添加的是库的搜索路径。

target_link_directories:和前面的include版本一样的,只是改成了库路径。

if\elseif\endif ,在编程语言立马已经用烂了,现在主要是了解 if(condition) 中的条件到底如何判断的,以及内部都支持哪些操作,比如大于等于啥的,这方面直接看官方文档吧,非常好懂:https://cmake.org/cmake/help/latest/command/if.html

aux_source_directory:这个指令简单实用,第一个参数传递一个文件目录,它会扫描这里面所有的源文件放到第二个参数定义的变量名中。注意第一个参数只能是文件夹。

aux_source_directory(${PROJECT_SOURCE_DIR} SRC)
file:可以说是上面那个命令的增强版本,但如果熟悉这个命令的朋友肯定很快站出来反对,因为这个命令实在是太强大了,你如果翻一翻这个官方文档就会发现它具备几乎文件系统的所有功能,什么读写文件啊,什么从网上下载文件,本地上传文件之类的它都有,计算文件的相对路径,路径转化等等。但我们平时用到的最多的命令还是用来获取文件到变量里。比如file(GLOB FILES “文件路径表示1” “文件路径表示2” …) GLOB会产生一个由所有匹配globbing表达式的文件组成的列表,并将其保存到第二个参数定义的变量中。Globbing 表达式与正则表达式类似,但更简单,比如如果要实现前一个命令的功能可以这么写:

file(GLOB SRC “${PROJECT_SOURCE_DIR}/*.cc”)
如果GLOB 换成GLOB_RECURSE ,那么上述命令将递归的搜寻其子目录的所有符合条件的文件,而不仅仅是一个层级。

execute_process:用于执行外部的命令,如下的示例代码是执行git clone命令,执行命令的工作目录在 ${CMAKE_BINARY_DIR}/deps/

execute_process(COMMAND git clone https://github.com//.git
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/deps/)
message:打印出信息用于debug。

option:用于快速设置定义变量并赋值为对应的bool值,常被用于判断某些操作是否执行。

find_package:用于查找外界的package,其实就是查找外界对应的 Config.cmake 和 Find.cmake 文件,这些文件里有外界包对应的变量信息以及库和头文件的各种路径信息。我们需要注意一些有关 find_package 命令查找 Config.cmake 路径的变量:

CMAKE_PREFIX_PATH 变量是一个路径列表,CMake 会在这些路径中搜索包的 Config.cmake 文件。
_DIR 变量是指向包的 Config.cmake 文件的路径。如果你手动设置了这个变量,那么 find_package 命令就可以找到包的信息。
同时他的一些常用参数如下:

CONFIG :显式指定find_package去查找 Config.cmake 文件,一般只要你在变量里面指定了 Config.cmake的路径,那么该参数填不填都没差别。我建议最好还是带上该参数比较好。
REQUIRED :该参数表示如果没找到,那么直接产生cmake错误,退出cmake执行过程,如果没有REQUIRED,则即使没找到也不会终止编译。
PATHS :这个参数的效果和前面的变量类似,也是指定查找的路径。
COMPONENTS :用于指定查找的模块,模块分离在不同的文件中,需要使用哪个就指定哪个模块。典型的就是使用Qt时的cmake代码,比如 find_package(Qt5 COMPONENT Core Gui Widgets REQUIRED) 。
VERSION:可能有很多个不同版本的包,则需要通过该参数来指定,如:find_package(XXX VERSION 1.2.3)。
include:从文件或模块加载并运行 CMake 代码。我用这个命令实际上只是为了使用 FetchContent¶ 这个module的功能,该功能是从cmake3.11开始支持的,使用该module前需要通过include命令加载该模块,命令如下:

include(FetchContent)
FetchContent:这是一个模块功能,它用来从代码仓库中拉取代码,例如我要把最近写的日志库引入到当前的项目中使用(注意这中间不会有任何代理,所以拉取GitHub的仓库可能失败):

include(FetchContent)#引入功能模块

FetchContent_Declare(
my-logger #项目名称
GIT_REPOSITORY https://github.com/ACking-you/my-logger.git #仓库地址
GIT_TAG v1.6.2 #仓库的版本tag
GIT_SHALLOW TRUE #是否只拉取最新的记录
)
FetchContent_MakeAvailable(my-logger)

add_excutable(main ${SRC})
#链接到程序进行使用
target_link_libraries(main my-logger)
这样引入第三方库的好处显而易见,优点类似于包管理的效果了,但缺少了最关键的中心仓库来确保资源的有效和稳定。参考golang再做个proxy层级就好了。 同样可以拉取最新的googletest可以使用下列语句:

FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.12.1
GIT_SHALLOW TRUE
)

上面的大佬解释的命令大部分是能用在工程的了,已经足够了

最关心的是能不能链接到特定的库

  • 网络拉取 vcpkg conan
  • 本地链接 提升这方面的知识

http://www.ppmy.cn/news/57992.html

相关文章

检查替换后的词是否有效

题目描述 给你一个字符串 s &#xff0c;请你判断它是否 有效 。 字符串 s 有效 需要满足&#xff1a;假设开始有一个空字符串 t “” &#xff0c;你可以执行 任意次 下述操作将 t 转换为 s &#xff1a; 将字符串 “abc” 插入到 t 中的任意位置。形式上&#xff0c;t 变为…

西门子PLC沿脉冲类指令汇总

S7-1200CPU提供了四种沿脉冲指令供用户使用&#xff0c;分别为&#xff1a;扫描操作数信号边沿指令、在信号边沿置位操作数的指令、扫描RLO的信号边沿指令以及检测信号边沿指令。 信号从0--1的时刻称为上升沿&#xff0c;信号从1--0的时刻称为下降沿&#xff0c;不管是上升沿还…

使用 ESP32 设计智能手表 – 第 1 部分制作表盘

相关设计资料下载ESP32 智能手表带心率、指南针设计资料(包含Arduino源码+原理图+Gerber+3D文件).zip 人们可以使用智能手表轻松快速地访问消息、警报、健康信息和其他高级信息。虽然智能手表作为独立设备在形式上是革命性的,但当与人们携带的其他设备(例如智能手机或平板…

Bridge模式如何配置

Bridge模式案例&#xff08;一&#xff09; 基于Docker引擎启动Nginx WEB容器&#xff0c;默认以Bridge方式启动Docker容器&#xff0c;会动态DHCP给Docker容器分配IP、网关等信息&#xff0c;操作指令如下&#xff1a; 查看镜像列表 docker images#运行新的Nginx容器 dock…

工作流框架研究

工作流框架研究 主流开源框架介绍OsWorkFlowJBPMActivitiFlowableCamundaCamunda 和Flowable对比功能上对比性能上对比 总结 主流开源框架介绍 OsWorkFlow 对于比较简单的流程&#xff0c;OsWorkFlow会是一个比较好的选择&#xff0c;对于复杂的流程就不推荐了&#xff0c;Os…

2023年软件测试常见面试题100%问必背全套教程

随着数字化时代的到来&#xff0c;软件测试越来越受到重视。在未来的几年里&#xff0c;软件测试将继续成为信息技术领域中的热门职业之一。如果你是一名正在寻找或准备进入软件测试行业的人&#xff0c;那么这套常见面试题全套教程对你来说会非常有用。 这套教程旨在帮助你了…

GO Select 使用

Go select case 用法 case 1 func Test_Select_Case_1(t *testing.T) {chan1 := make(chan int)chan2 := make(chan int)go

EventBus(事件总线)的使用和源码的简单解析

Google Guava EventBus(事件总线)的使用和源码的简单解析 什么是EventBus&#xff1f; 事件总线&#xff08;EventBus&#xff09;是一种广泛用于软件架构中的设计模式&#xff0c;用于实现解耦和松散耦合的通信机制。它可以帮助组织和管理应用程序中不同组件之间的通信&…