草庐IT

CMakeLists.txt详解

上进的打工人 2023-11-21 原文

一:CMakeLists.txt文件是cmake用来生成Makefile文件需要的一个描述编译链接的规则文件

学习cmake需要提前了解gcc等编译命令,先来解释一条最简单的命令

        gcc ./source/*.c -o ./bin/test -I ./include -L ./lib/ -l动态库名

上述命令的解释为:用gcc工具编译当前目录下source文件夹中的所有的.c文件 生成目标为test的可执行文件且将其放在当前目录下的bin文件夹中,其所用到的头文件所在路径为当前目录下的include文件夹,动态库文件路径为当前目录下的lib文件夹,编译时需要用到的动态库为库名所对应的.so动态库

二:CMakeList.txt规则文件常用变量

(1)常用变量

        PROJECT_NAME:用函数project(demo)指定的项目名称,这里变量的值为demo

        PROJECT_SOURCE_DIR:工程的根目录

        PROJECT_BINARY_DIR:执行cmake命令的目录,如果mkdir build ,cd build, cmake ../,的话,该变量的值为build目录

        CMAKE_CURRENT_SOURCE_DIR:当前处理的CMakeLists.txt文件所在目录

        CMAKE_CURRENT_BINARY_DIR:cmake当前正在处理的二进制目录

        CMAKE_CURRENT_LIST_DIR:CMakeLists.txt的完整路径

        CMAKE_CURRENT_LIST_LINE:当前所在行

        CMAKE_C_FLAGS:设置C编译选项

        CMAKE_CXX_FLAGS:设置C++编译选项

        CMAKE_INSTALL_PREFIX:指定install指令安装文件的根目录

        EXECUTABLE_OUTPUT_PATH:生成目标可执行文件的输出位置

        LIBRARY_OUTPUT_PATH:库文件输出位置

    三:指令详解

             需要注意的是CMakeLists.txt文件中的指令不区分大小写 

(1)PROJECT(projectname [CXX] [C] [Java]):

该函数定义工程名字,并指定了工程的语言,支持语言的列表可以省略,默认情况下表示支持所有语言,并隐式定义了两个cmake的变量   

        PROJECT_BINARY_DIR:执行cmake的目录

        PROJECT_SOURCE_DIR:工程的根目录

(2).SET(<variable> <value>... [PARENT_SCOPE])

显式设置普通变量

        variable:只能有一个;
        value:可以有0个,1个或多个,当value值为空时,方法同unset,用于取消设置的值;
        PARENT_SCOPE(父作用域):作用域,除PARENT_SCOPE外还有function scope(方法作用域)和directory scope(目录作用域)。

     2.set(<variable> <value>... CACHE <type> <docstring> [FORCE]) #设置缓存条目

        variable:只能有一个
        value:可以有0个,1个或多个,当value值为空时,方法同unset,用于取消设置的值
        CACHE:关键字,说明是缓存变量设置
        type(类型):必须为以下中的一种:
                BOOL:有ON/OFF,两种取值
                FILEPATH:文件的全路径
                PATH:目录路径
                STRING:字符串
                INTERNAL:字符串
        docstring:总结性文字(字符串)
        [FORCE]:变量名相同,第二次调用set方法时,第一次的value将会被覆盖

     3.set(ENV{<variable>} [<value>]) #设置环境变量

        variable:只有一个

  value:一般来说,只有一个,为空时,将清除之前设置的变量值,多个时,取值最近的一个,之后的值将被忽略

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin):设置可执行文件的输出路径为build/bin

set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib):设置库文件的输出路径为build/lib

(3)include_directories(xxx)

                给工程添加头文件,例如使用opencv时需要包含/usr/local/include/opencv/cv.h这个头文件,则我们需要include_directories(/usr/local/include),在调用的函数里写 #include “opencv/cv.h”即可

        target_include_directories()

                为指定的目标添加搜索头文件

include_directories()和target_include_directories()区别

include_directories 会为当前CMakeLists.txt的所有目标,以及之后添加的所有子目录的目标添加头文件搜索路径。因此,慎用,会影响全局target

target_include_directories 只会为指定目标包含头文件搜索路径。如果想为不同目标设置不同的搜索路径,target_include_directories 更合适

例:target_include_directories(test xxx ${PROJECT_SOURCE_DIR}/include)

如果xxx为PRIVATE 则表示头文件只能由 test使用

如果xxx为INTERFACE 则表示头文件只能由 调用test的文件使用

如果xxx为PUBLIC 则test和任何调用test的文件都能使用头文件

(4)add_executable(可执行文件名 1.cpp 2.ppp …)

添加可执行文件,其中可执行文件需要用到1.cpp和2.cpp 工程会给1.cpp和2.cpp编译生成一个可执行文件

(5)add_library(生成的库名称 STATIC/SHARED 源文件.cpp)

将源文件生成 静态/动态 库文件 STSTIC 表示静态库最终会编入到可执行文件中,SHARED(常见参数)表示动态库(又称共享库)方式

(6)target_link_libraries (库/可执行文件 library1 library2 ...)

为库或者可执行文件添加需要链接的库

注:需要放在add_executable之后

(7)add_subdirectory(source_dir)

向当前工程添加存放其他源文件的子目录,用于多目录下都有CMakeLists.txt文件的情况

(8)aux_source_directory( 文件目录 变量名)

把文件目录下的所有源文件储存在变量中

例:aux_source_directory(${PROJECT_SOURCE_DIR}/ DIR_SRCS) 表示把工程目录的源文件添加到DIR_SRCS变量中

(9)message(模式 "output msg" )

打印输出信息,常见模式有FATAL_ERROR、WARNING、STATUS、DEBUG等

(10)find_package(<NAME> 版本号 EXACT/QUIET/REQUIRED)

version:指定查找库的版本号。 EXACT:要求该版本号必须精确匹配。 QUIET:禁掉没有找到时的警告信息。如果没找到则忽略这一问题,继续执行 REQUIRED选项表示如果包没有找到的话,CMake的过程会终止,并输出警告信息

当find_package找到一个库的时候,以下变量会自动初始化:

<NAME>_FOUND : 显示是否找到库的标记
<NAME>_INCLUDE_DIRS 或 <NAME>INCLUDES : 头文件路径
<NAME>_LIBRARIES 或 <NAME>_LIBS : 库文件 

注:如果CMake自动找不到路径,我们需要手动设置路径,如 先 set(OpenCV_INCLUDE_DIRS “home/hwh/Opencv3.1/build”) 设置路径 然后find_package(OpenCV 3.1 REQUIRED)

(11)file(GLOB 变量 "路径")

会在路径下查找目标文件并保存在变量中

(12)execute_process(COMMAND shell命令 WORKING_DIRECTORY shell命令的工作目录)

执行shell命令
(13)foreach(var ${list})

                xxx

          endforeach()

变量var从list中取值,并循环执行xxx命令

(14)install指令

install(TARGETS a.a b.so exe ARCHIVE a.a  DESTINATION lib/  LIBRARY b.so DESTINATION lib/ RUNTIME exe DESTINATION bin/)

TARGETS:通过ADD_EXECUTABLE ADD_LIBRARY定义的目标文件,ARCHIVE特指静态库,LIBRARY特指动态库,RUNTIME特指可执行目标二进制,DESTINATION定义了安装的路径

FILE:普通文件的安装

PROGRAMS :可执行脚本

DIRECTORY:目录安装

(15)add_definitions()

向编译器添加-D定义,如ADD_DEFINITIONS(-DENABLE_DEBUG -DABC),参数之间用空格隔开

如果代码中定义了#ifdef ENABLE_DEBUG #endif,这个代码块就会生效

如果要添加其他编译器开关,可以通过CMAKE_C_FLAGS变量和CMAKE_CXX_FLAGS变量设置

(16)ADD_DEPENDENCIES()

定义target依赖其他的target,确保在编译本target之前,其他的target以及被构建

(17)FILE()

文件操作指令

(18)include(file OPTIONAL)

用于载入CMakeLists.txt文件和.cmake文件,模块文件搜索路径与CMAKE_MODULE_PATH

变量指定的路径有关,OPTIONAL参数作用是即使文件不存在也不报错

(19)find_xxx(<VAR> name1 path1 path2)

查找相应的文件,VAR变量表示找到文件的全路径

(20)

function的定义格式如下:后面可作为命令供调用

function(<name> [<arg1> ...])

        <commands>

endfunction()

其中name是function的名字,参数为arg1, arg2等。

注意:变量的取值使用${},但在if控制语句中和直接使用变量名

                   Make VERBOSE=1可以看到makefile执行的详细步骤

                   CMAKE_INCLUDE_PATH 与CMAKE_LIBRARY_PATH是环境变量,两者都被用于find_path

有关CMakeLists.txt详解的更多相关文章

  1. 物联网MQTT协议详解 - 2

    一、什么是MQTT协议MessageQueuingTelemetryTransport:消息队列遥测传输协议。是一种基于客户端-服务端的发布/订阅模式。与HTTP一样,基于TCP/IP协议之上的通讯协议,提供有序、无损、双向连接,由IBM(蓝色巨人)发布。原理:(1)MQTT协议身份和消息格式有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。MQTT传输的消息分为:主题(Topic)和负载(payload)两部分Topic,可以理解为消息的类型,订阅者订阅(Su

  2. Tcl脚本入门笔记详解(一) - 2

    TCL脚本语言简介•TCL(ToolCommandLanguage)是一种解释执行的脚本语言(ScriptingLanguage),它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。•实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是

  3. 【详解】Docker安装Elasticsearch7.16.1集群 - 2

    开门见山|拉取镜像dockerpullelasticsearch:7.16.1|配置存放的目录#存放配置文件的文件夹mkdir-p/opt/docker/elasticsearch/node-1/config#存放数据的文件夹mkdir-p/opt/docker/elasticsearch/node-1/data#存放运行日志的文件夹mkdir-p/opt/docker/elasticsearch/node-1/log#存放IK分词插件的文件夹mkdir-p/opt/docker/elasticsearch/node-1/plugins若你使用了moba,直接右键新建即可如上图所示依次类推创建

  4. 【Elasticsearch基础】Elasticsearch索引、文档以及映射操作详解 - 2

    文章目录概念索引相关操作创建索引更新副本查看索引删除索引索引的打开与关闭收缩索引索引别名查询索引别名文档相关操作新建文档查询文档更新文档删除文档映射相关操作查询文档映射创建静态映射创建索引并添加映射概念es中有三个概念要清楚,分别为索引、映射和文档(不用死记硬背,大概有个印象就可以)索引可理解为MySQL数据库;映射可理解为MySQL的表结构;文档可理解为MySQL表中的每行数据静态映射和动态映射上面已经介绍了,映射可理解为MySQL的表结构,在MySQL中,向表中插入数据是需要先创建表结构的;但在es中不必这样,可以直接插入文档,es可以根据插入的文档(数据),动态的创建映射(表结构),这就

  5. 最强Http缓存策略之强缓存和协商缓存的详解与应用实例 - 2

    HTTP缓存是指浏览器或者代理服务器将已经请求过的资源保存到本地,以便下次请求时能够直接从缓存中获取资源,从而减少网络请求次数,提高网页的加载速度和用户体验。缓存分为强缓存和协商缓存两种模式。一.强缓存强缓存是指浏览器直接从本地缓存中获取资源,而不需要向web服务器发出网络请求。这是因为浏览器在第一次请求资源时,服务器会在响应头中添加相关缓存的响应头,以表明该资源的缓存策略。常见的强缓存响应头如下所述:Cache-ControlCache-Control响应头是用于控制强制缓存和协商缓存的缓存策略。该响应头中的指令如下:max-age:指定该资源在本地缓存的最长有效时间,以秒为单位。例如:Ca

  6. IDEA 2022 创建 Spring Boot 项目详解 - 2

    如何用IDEA2022创建并初始化一个SpringBoot项目?目录如何用IDEA2022创建并初始化一个SpringBoot项目?0. 环境说明1.  创建SpringBoot项目 2.编写初始化代码0. 环境说明IDEA2022.3.1JDK1.8SpringBoot1.  创建SpringBoot项目        打开IDEA,选择NewProject创建项目。        填写项目名称、项目构建方式、jdk版本,按需要修改项目文件路径等信息。        选择springboot版本以及需要的包,此处只选择了springweb。        此处需特别注意,若你使用的是jdk1

  7. ruby - 在 ruby​​ 中下载多个 FTP 文件,如 d*.txt - 2

    我需要连接到一个ftp站点并下载一堆名为D*.txt的文件(最多6个)。你能帮我用Ruby编写代码吗?下面的代码就ftp=Net::FTP::new("ftp_server_site")ftp.login("user","pwd")ftp.chdir("/RemoteDir")fileList=ftp.nlstftp.getbinaryfile(edi,edi)ftp.close谢谢 最佳答案 最简单的方法是遍历fileList中的文件列表。这是一个例子(未经测试):ftp=Net::FTP::new("ftp_server_sit

  8. 详解Unity中的粒子系统Particle System (二) - 2

    前言上一篇我们简要讲述了粒子系统是什么,如何添加,以及基本模块的介绍,以及对于曲线和颜色编辑器的讲解。从本篇开始,我们将按照模块结构讲解下去,本篇主要讲粒子系统的主模块,该模块主要是控制粒子的初始状态和全局属性的,以下是关于该模块的介绍,请大家指正。目录前言本系列提要一、粒子系统主模块1.阅读前注意事项2.参考图3.参数讲解DurationLoopingPrewarmStartDelayStartLifetimeStartSpeed3DStartSizeStartSize3DStartRotationStartRotationFlipRotationStartColorGravityModif

  9. VMware虚拟机与本地主机进行磁盘共享(详解) - 2

    VMware虚拟机与本地主机进行磁盘共享前提虚拟机版本为Windows10(专业版,不是可能有问题)本地主机为家庭版或学生版(此版本会有问题,但有替代方式)最好是专业版VMware操作1.关闭防火墙,全部关闭。2.打开电脑属性3.点击共享-》高级共享-》权限4.如果没有everyone,就添加权限选择完全控制,然后应用确定。5.打开cmd输入lusrmgr.msc(只有专业版可以打开)如果不是专业版,可以跳过这一步。点击用户-》administrator密码要复杂密码,否则不行。推荐admaiN@1234类型的密码。设置完密码,点击属性,将禁用解开。6.如果虚拟机的windows不是专业版,可

  10. arrays - 为什么 Dir.glob ("*.txt").sort 也需要 .each? - 2

    Dir.glob("*.txt"){|f|pf}打印文件名。Dir.glob("*.txt").sort{|f|pf}因ArgumentError失败。Dir.glob("*.txt").sort.each{|f|pf}按字母顺序打印文件名。为什么第二个失败了?更好的是,为什么第一个工作,有或没有.each?Dir.glob和Dir.glob.sort都是数组。Dir.glob.methods==Dir.glob.sort.methods。(受AlphabetizeresultsofDir.glob启发。不是Dir.globwithsortissue的副本,因为“第三个”已经回答了那个

随机推荐