Cmake学习详细笔记(8) ——自定义编译选项

案例四:自定义编译选项
1). 源文件结构
.
├── CmakeLists.txt
├── config.h.in
├── main.cpp
└── students
├── CmakeLists.txt
├── student_pub.cpp
└── student_pub.h
2) .编写 CMakeLists.txt

#cmake mini ~ver
cmake_minimum_required(VERSION 2.8)
#project info
project(Studdent3)

message(STATUS "PROJECT_SOURCE_DIR " ${PROJECT_SOURCE_DIR})
message(STATUS "PROJECT_BINARY_DIR " ${PROJECT_BINARY_DIR})

set (STUDENT_VERSION_MAJOR "2.0.3" CACHE STRING [FORCE])
set (STUDENT_VERSION_MINOR "1.2.1")

message(STATUS "STUDENT_VERSION_MAJOR " ${STUDENT_VERSION_MAJOR})
message(STATUS "STUDENT_VERSION_MINOR " ${STUDENT_VERSION_MINOR})

set(LIB_ENABLE 1)

if(LIB_ENABLE)
    message(STATUS "define LIB_ENABLE 1")
else()
    message(STATUS "define LIB_ENABLE 0")
endif()

if(CODE_MODE_DEBUG MATCHES ON)
    message("*********Debug build***********")
endif()

# 加入一个配置头文件,用于处理 CMake 对源码的设置
configure_file(
"${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_BINARY_DIR}/config.h"
)
# 默认的该宏打开还是关闭 可以在ccmake . gui界面中进行配置  初始化的操作
option(USE_MYSTUDENT "Use provided StudentFuncsLib implementation" ON)
option(CODE_MODE_DEBUG "Use CODE_MODE_DEBUG" OFF)

if(CODE_MODE_DEBUG)
    message(STATUS "define CODE_MODE_DEBUG on")
else()
    message(STATUS "define CODE_MODE_DEBUG off")
endif()

if(USE_MYSTUDENT)
    message(STATUS "define USE_MYSTUDENT on")
else()
    message(STATUS "define USE_MYSTUDENT off")
endif()
#头文件引入
include_directories("${PROJECT_SOURCE_DIR}/students/")

# 是否加入 StudentFuncsLib 库
if(USE_MYSTUDENT)
add_subdirectory(students)
set(EXTRA_LIBS ${EXTRA_LIBS} StudentFuncsLib)
endif(USE_MYSTUDENT)

#将当前路径下的源文件保存到变量DIR_SRCS中
aux_source_directory(. DIR_SRCS)  

#添加student 目录
#add_subdirectory(students)

#先生成目标文件Student
add_executable(Studdent ${DIR_SRCS})
#添加链接库
target_link_libraries(Studdent ${EXTRA_LIBS})

3), 编写config.h.in文件

/**
 * This is the configure demo  
 *    - CMAKEDEFINE_VAR1 = @CMAKEDEFINE_VAR1@
 *    - CMAKEDEFINE_VAR2 = @CMAKEDEFINE_VAR2@
 *    - DEFINE_VAR1      = @DEFINE_VAR1@
 *    - DEFINE_VAR2      = @DEFINE_VAR2@
 */

/**
 *  cmakedefine 会根据变量的值是否为真(类似 if)来变换为 #define VAR ... 或  #undef VAR 
 */
#cmakedefine CMAKEDEFINE_VAR1 @CMAKEDEFINE_VAR1@
#cmakedefine LIB_ENABLE @LIB_ENABLE
/**
 * define 会直接根据规则来替换
 */
#define DEFINE_VAR1 @DEFINE_VAR1@
#define DEFINE_VAR2 ${DEFINE_VAR2}
#cmakedefine USE_MYSTUDENT
//#cmakedefine  CODE_MODE_DEBUG

4).cmake接口

message(STATUS "PROJECT_SOURCE_DIR " ${PROJECT_SOURCE_DIR})
message(STATUS "PROJECT_BINARY_DIR " ${PROJECT_BINARY_DIR})

解释:
message :为用户显示一条消息。
message([] “message to display” …)
mode的选项可以是:
(none) = Important information
STATUS = Incidental information
WARNING = CMake Warning, continue processing
AUTHOR_WARNING = CMake Warning (dev), continue processing
SEND_ERROR = CMake Error, continue processing,
but skip generation
FATAL_ERROR = CMake Error, stop processing and generation
DEPRECATION = CMake Deprecation Error or Warning if variable
CMAKE_ERROR_DEPRECATED or CMAKE_WARN_DEPRECATED
is enabled, respectively, else no message.
(无) = 重要消息;
STATUS = 非重要消息;
WARNING = CMake 警告, 会继续执行;
AUTHOR_WARNING = CMake 警告 (dev), 会继续执行;
SEND_ERROR = CMake 错误, 继续执行,但是会跳过生成的步骤;
FATAL_ERROR = CMake 错误, 终止所有处理过程;
CMake命令行工具在stdout上显示状态消息,在stderr上显示所有其他消息类型。CMake GUI显示其日志区域中的所有消息。交互式对话框(ccmake和CMakeSetup)每次在状态行上显示一条状态消息,并在交互式弹出框中显示其他消息。CMake警告和错误消息文本使用简单的标记语言显示。非缩进文本的格式是用换行符分隔的行包装的段落。缩进文本被认为是预格式化的。
configure_file(
P R O J E C T S O U R C E D I R / c o n f i g . h . i n " " {PROJECT_SOURCE_DIR}/config.h.in" " PROJECTSOURCEDIR/config.h.in""{PROJECT_BINARY_DIR}/config.h”
)
解释:
拷贝一个文件到另一个文件,格式为:
configure_file(
[COPYONLY] [ESCAPE_QUOTES] [@ONLY]
[NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
将一个文件复制到file ,并替换文件内容中引用的变量值。
如果是一个相对路径,则相对于当前source 求值。
必须是一个文件,而不是一个目录。
如果是一个相对路径,则相对于当前binary 目录求值。
如果命名一个现有目录,则输入文件将放置在该目录中,并使用其原始名称。
如果文件被修改,构建系统将重新运行CMake来重新配置文件并再次生成构建系统。
此命令将输入文件中引用为 V A R 或 @ V A R @ 的 任 何 变 量 替 换 为 C M a k e ( C m a k e L i s t s 中 设 置 的 值 ) 确 定 的 值 。 如 果 一 个 变 量 没 有 定 义 , 它 将 被 替 换 为 n o t h i n g 。 浅 显 一 点 : c o n f i g u r e f i l e , 复 制 一 份 输 入 文 件 到 输 出 文 件 , 替 换 输 入 文 件 中 被 @ V A R @ 或 者 {VAR}或@VAR@的任何变量替换为CMake(CmakeLists 中设置的值)确定的值。如果一个变量没有定义,它将被替换为nothing。 浅显一点: configure_file,复制一份输入文件到输出文件,替换输入文件中被@VAR@或者 VAR@VAR@CMakeCmakeListsnothingconfigurefile@VAR@{VAR}引用的变量值。也就是说,让普通文件,也能使用CMake中的变量。例如:
在CMakeLists.txt中定义了如下的变量:
set(USE_MYSTUDENT 1)
输入文件中为:
#cmakedefine LIB_ENABLE @LIB_ENABLE@
那么,在输出文件中就会被转化为:
#define LIB_ENABLE 1

或:

在CMakeLists.txt中定义了如下的变量:
option(CODE_MODE_DEBUG “Use CODE_MODE_DEBUG” ON)
输入文件中为:
#cmakedefine CODE_MODE_DEBUG
那么,在输出文件中就会被转化为:
#define CODE_MODE_DEBUG 1

Config.h.in文件中配置如下:

#cmakedefine USE_MYSTUDENT
#cmakedefine LIB_ENABLE @LIB_ENABLE@
#cmakedefine  CODE_MODE_DEBUG

configure_file的其他选项:
COPYONLY:只拷贝文件,不进行任何的变量替换。这个选项在指定了NEWLINE_STYLE选项时不能使用(无效)。
ESCAPE_QUOTES:躲过任何的反斜杠(C风格)转义。
@ONLY:限制变量替换,让其只替换被@VAR@引用的变量(那么 V A R 格 式 的 变 量 将 不 会 被 替 换 ) 。 这 在 配 置 {VAR}格式的变量将不会被替换)。这在配置 VAR){VAR}语法的脚本时是非常有用的。
NEWLINE_STYLE style:指定输出文件中的新行格式。UNIX和LF的新行是\n,DOS和WIN32和CRLF的新行格式是\r\n。这个选项在指定了COPYONLY选项时不能使用(无效)。
通常情况下,输入文件以.h.in为后缀,输出文件以.h为后缀。

如果指定了COPYONLY,则不会发生变量展开。
如果指定了ESCAPE_QUOTES,那么任何替换的引号都将是c风格的转义。该文件将配置为CMake变量的当前值。
如果指定了@ONLY,则只会替换形式@VAR@的变量,而忽略 V A R 。 这 对 于 配 置 使 用 {VAR}。这对于配置使用 VAR使{VAR}的脚本非常有用。

根据if()命令在CMake中是否将VAR设置为任何不被认为是错误常量的值,“#cmakedefine VAR…”形式的输入文件行将被替换为“#define VAR…”或/* #undef VAR */。
(“…”的内容,如有,按上文处理。)
类似地,“#cmakedefine01 VAR”形式的输入文件行将被“#define VAR 1”或“#define VAR 0”替换。

option(USE_MYSTUDENT “Use provided StudentFuncsLib implementation” ON)
解释:
提供用户可以选择的选项。为用户提供一个 ON或OFF选项。如果没有提供初始值,则使用OFF。
默认的该宏打开还是关闭,可以在ccmake . gui界面中进行配置,这里是初始化的操作,当没有定义时默认的值就是在这里配置,每次清除build文件重新cmake时,就会使用该默认值,可以在cmake时进行带参数编译,这样可以将值传进去。
可以使用ccmake … 进行GUI 界面的设置,先按enter设置,再按g更改保存文件构建系统。
执行后对照config.h 和config.h.in 两个文件进行对比。
include_directories("${PROJECT_SOURCE_DIR}/students")
引入头文件路径,这样在编译的时候就可以找到头文件了。而且在项目源文件中就不用像:
#include"./students/student_pub.h"
这样声明了,可以直接声明为:
#include"student_pub.h"
但是这样做容易让别人不清楚头文件路径,所以如果头文件不多的话尽量少用,尽量使用绝对路径在头文件中包含,像上面一样使用。
set(EXTRA_LIBS KaTeX parse error: Expected 'EOF', got '#' at position 137: …) config.h.in中 #̲cmakedefine STU…{STUDENT_VERSION_MINOR}"
则生成的config.h中:
#define STUDENT_VERSION_MAJOR 0.3
#define STUDENT_VERSION_MINOR “1.2.1”
就可以在main函数使用该宏了
官网参考; https://cmake.org/cmake/help/latest/command/set.html?highlight=set

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值