CMake高级用法

摘要:
第二种是在CMakeLists文件中使用set命令,如set添加include目录:include_directoriesinclude_directories添加include目录到当前CMakeLists。C++11如果用到了C++11特性,需要让CMake支持该特性add_defin
0. 写在最前面

本文将总结自己日常用到的CMake命令以及功能。如有错误,欢迎在评论中指正。

如果觉得写得还不错,就请收藏一下啦~~~也可以找一下我写的其他文章来看一下。关注一下我的专栏什么的。

你的Star是作者坚持下去的最大动力哦~~~

在这里可以查到关于命令的官方文档

使用宏定义:macro

macro(add_example name)
   add_executable(${name} ${name}.cpp)
   target_link_libraries(${name} dlib::dlib )
endmacro()

add_example(dnn_metric_learning_ex)

添加外部的CMake:add_subdirectory

有时候自己的CMakeLists需要依赖其他的包,需要先编译这个包;或者一个工程分成几个部分,然后在最外面用一个CMakeLists来统一编译,那就需要包含其他的CMakeLists文件来实现。
使用到:
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

  • source_dir:首先需要指出另外这个CMakeLists的目录,可以使用相对路径(相对当前路径)和绝对路径。
  • binary_dir:接着指明编译生成二进制的目录,可以使用相对路径(相对当前路径)和绝对路径。目标目录是可选项,如不指定,目标文件会被放到source_dir
  • EXCLUDE_FROM_ALLsource_dir生成的目标会被排除在原目录的ALL target之外,也会排除在其IDE工程文件之外。比如source_dir是一些examples,原目录其实是不需要它们的,只是希望他们能编译,就可以添加这个命令。

这个命令的位置需要注意,不能太后面,编译dlib时放在比较后面出现了问题。

例子:

add_subdirectory(../dlib dlib_build)

注意:当运行到该命令时,会立即跳到source_dir执行CMake,等到该CMakeLists执行完毕再跳回原来的CMakeLists执行add_subdirectory后面的命令。

输出消息:message

message("No GUI support, so we won't build the ${name} example.")
#name是一个变量

if判断

if (DLIB_NO_GUI_SUPPORT)
   message("No GUI support, so we won't build the ${name} example.")
else()
   add_example(${name})
endif()

设置变量:set

  • 设置一般变量
set(CPACK_PACKAGE_NAME "dlib")
set(CPACK_PACKAGE_VERSION_MAJOR "19")
set(CPACK_PACKAGE_VERSION_MINOR "16")
set(CPACK_PACKAGE_VERSION_PATCH "0")
set(VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH})
  • 设置内部变量
    CMAKE_C_COMPILER:指定C编译器
    CMAKE_CXX_COMPILER
    CMAKE_C_FLAGS:编译C文件时的选项,如-g;也可以通过add_definitions添加编译选项
    EXECUTABLE_OUTPUT_PATH:可执行文件的存放路径
    LIBRARY_OUTPUT_PATH:库文件路径
    CMAKE_BUILD_TYPE:build 类型(Debug, Release, …),CMAKE_BUILD_TYPE=Debug
    BUILD_SHARED_LIBS:Switch between shared and static libraries
    设置内部变量有两种方式,一种是直接在cmake命令后面加-D+命令+=+值,如cmake .. -DBUILD_SHARED_LIBS=OFF。第二种是在CMakeLists文件中使用set命令,如set(BUILD_SHARED_LIBS OFF)

添加include目录:include_directories

include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])
添加include目录到当前CMakeLists(包括build和target)。默认是目录的递归,相对目录是相对当前路径的。

查找包:find_package

find_package(<package> [version] [EXACT] [QUIET] [MODULE] [REQUIRED] [[COMPONENTS] [components...]] [OPTIONAL_COMPONENTS components...] [NO_POLICY_SCOPE])
查找并加载外部工程,这个命令后,一个<package>_FOUND的变量会表明是否找到。
QUIET选项忽视找不到的消息;REQUIRED选项表明该外部包是必须的,找不到会立刻停止;
例子(这里的判断是没必要的,只是为了说明,因为找不到就会退出):

find_package(OpenCV REQUIRED)
if (OpenCV_FOUND)
  include_directories(${OpenCV_INCLUDE_DIRS})
else()
  message("OpenCV not found, so we won't build the project.")
endif()

链接库目录:link_directories

https://haoqchen.site/2018/04/26/CMakeLists-setting-relative-path/

生成自己的静态、动态链接库

add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] source1 [source2 ...])

增加一个叫name的链接库,可以选择是STATICSHARED或者是MODULE类型的。

  • STATIC:静态链接库,当生成可执行程序时进行链接。在Linux下为.a文件
  • SHARED:动态链接库,可执行程序运行时动态加载并链接。在Linux下为.so文件
  • MODULE:模块,可执行程序运行时动态加载,但不链接到可执行程序中。
    BUILD_SHARED_LIBS变量决定了默认值,如果为on则为动态的,否则为静态的

可以通过设置CMAKE_LIBRARY_OUTPUT_DIRECTORY变量指定输出的路径
例子:

SET(LIBHELLO_SRC hello.c)
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})       #添加动态库
#ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC})      #添加静态库
#ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})  

需要注意的是源文件前没有逗号。

C++11

如果用到了C++11特性,需要让CMake支持该特性
add_definitions(-std=c++11)

移动资源文件、配置文件

有些资源文件或者配置文件需要从源文件目录移动到生成文件目录,这个时候可以使用file命令,file命令可以进行文件写入、读取、生成、下载、上传、重命名等操作,这里先说一下文件复制的:

file(<COPY|INSTALL> <files>... DESTINATION <dir> [FILE_PERMISSIONS <permissions>...] [DIRECTORY_PERMISSIONS <permissions>...] [NO_SOURCE_PERMISSIONS] [USE_SOURCE_PERMISSIONS] [FILES_MATCHING] [[PATTERN <pattern> | REGEX <regex>] [EXCLUDE] [PERMISSIONS <permissions>...]] [...])

COPY一个<files>(文件、目录或者链接)到一个目标位置DESTINATION<dir>。如果使用相对路径,<files>将会是相对当前源文件目录,而<dir>将会是相对当前build目录。复制默认使用USE_SOURCE_PERMISSIONS选项,即保留源文件权限,包括可执行性等,可以通过显式声明NO_SOURCE_PERMISSIONS来去除。
实例:

file(COPY ./dlib/data/ DESTINATION ./dlib_models)

这样子就可以将源文件目录下的一些模型(data文件夹内所有)复制到生成二进制文件的dlib_models目录了。

常用宏变量

  • PROJECT_BINARY_DIR:由project命令生成,指向build目录的绝对路径
  • PROJECT_SOURCE_DIR:由project命令生成,指向CMakeLists目录绝对路径。
    这两个配合file命令可以设置链接库相对路径。
    例子:
file(COPY ./voice/libs/X64/ DESTINATION ./)
target_link_libraries(awaken_asr ${PROJECT_BINARY_DIR}/libmsc.so libasound.so)
参考

https://www.cnblogs.com/narjaja/p/9533169.html


喜欢我的文章的话Star一下呗Star

版权声明:本文为白夜行的狼原创文章,未经允许不得以任何形式转载

免责声明:文章转载自《CMake高级用法》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Go语言参数校验(go-playground / validator)——基本使用股票涨跌和买卖预测计算公式下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

jsp、freemarker、velocity对比

在java领域。表现层技术主要有三种:jsp、freemarker、velocity。 jsp是大家最熟悉的技术长处:1、功能强大,能够写java代码2、支持jsp标签(jsp tag)3、支持表达式语言(el)4、官方标准。用户群广。丰富的第三方jsp标签库5、性能良好。jsp编译成class文件运行。有非常好的性能表现缺点:jsp没有明显缺点,非要挑点...

ClassLoader读取classpath目录下的文件

项目中的需求是根据配置文件创建一个页面,配置文件中配置一些图例或者搜索框。读取classpath目录下文件的方式有很多,且记录自己在项目中用到的一种方式。 ClassLoader主要是对类的请求提供服务,当jvm需要某个类时,它根据名称向ClassLoader请求获得这个类,然后ClassLoader返回给jvm这个类的class对象。ClassLoad...

将cmake文件转化为vs方便代码阅读与分析

下面通过“chengxuyuancc”同学的图来说明。通过cmake将winafl cmake编译方式转化为vs2015,方便源码阅读与分析。 1.到官网下载cmake软件。启动图形版 2.选择源码目录(也就是cmakelists.txt所在目录),选择生成的项目(.sln)目录。 3.配置生成vs2015项目。点击配置。出现错误,提示DynamoRIO_...

Jmeter接口测试01

Jmeter 简介   Apache JMeter 是 Apache 组织的开放源代码项目,是一个纯 Java 桌面应用,用于压力测试和性能测试。它最初 被设计用于 Web 应用测试但后来扩展到其它测试领域。   Jmeter 功能   • 能够对 HTTP 和 FTP 服务器进行压力和性能测试, 也可以对任何数据库进行同样的测试(通过 JDBC)。  ...

ThinkPHP模板(一)

如何关闭ThinkPHP的模板缓存 ThinkPHP的模板缓存是无奈关闭的,因为内置的模板引擎是一个编译型的模板引擎,必须经过编译后生成一个可执行的缓存文件才能被执行。但是可以设置缓存的有效期,例如设置 ‘TMPL_CACHE_TIME’ =>3, // 模板缓存有效期 -1 永久 单位为秒 这样,每隔3秒系统会自动重新编译模板文件。默认的配置是-1...

AI学习---基于TensorFlow的案例[实现线性回归的训练]

线性回归原理复习         1)构建模型               |_> y = w1x1 + w2x2 + …… + wnxn + b        2)构造损失函数               |_> 均方误差        3)优化损失               |_> 梯度下降 实现线性回归的训练         准...