目录
基于上篇文章,我们可以通过条件结构 if-else-endif来控制cmake编译的行为。本文的例子用来实现:
- 将 Message.h 和 Message.cpp 构建成一个静态库,然后将生成库链接到 helloworld 可执行文件中。
- 将 Message.h、Message.cpp 和 helloworld.cpp 构建成一个可执行文件,但不生成任何一个库。
一、条件控制编译
1.CMakeLists.txt源文件
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(ifelseStudy LANGUAGES CXX)
#定义新变量 USE_LIBRARY ,这是一个逻辑变量,值为 OFF
set(USE_LIBRARY OFF)
#打印值
message(STATUS "Compile sources into a library?${USE_LIBRARY}")
#CMake内部 BUILD_SHARED_LIBS 全局变量,设置为 OFF,即生成静态库
set(BUILD_SHARED_LIBS OFF)
#引入一个局部变量_sources,包括 Message.h 和 Message.cpp
list(APPEND
_sources
Message.cpp
Message.h)
if(USE_LIBRARY)
add_library(mylib ${_sources})
add_executable(helloworldexe helloworld.cpp)
target_link_libraries(helloworldexe mylib)
else(USE_LIBRARY)#可简写成else()
add_executable(helloworldexe helloworld.cpp ${_sources})
endif(USE_LIBRARY)#可简写成endif()
2.CMake语言说明
(1)set
set(USE_LIBRARY OFF)
定义新变量 USE_LIBRARY,这是一个逻辑变量,其值为OFF。
逻辑真或假可以用多种方式表示:
- 如果将逻辑变量设置为以下任意一种: 1 、 ON 、 YES 、 true 、 Y 或非零数,则逻辑变量为 true 。
- 如果将逻辑变量设置为以下任意一种: 0 、 OFF 、 NO 、 false 、 N 、 IGNORE、 NOTFOUND 、空字符串,或者以 -NOTFOUND 为后缀,则逻辑变量为 false。
set(BUILD_SHARED_LIBS OFF)
BUILD_SHARED_LIB 是一个CMake全局变量,用于控制cmake是否可以生成动态库,默认情况下BUILD_SHARED_LIB变量为ON。
当add_library函数的第二个参数省略、并且没有设置BUILD_SHARED_LIB(即ON),则cmake会生成动态库。
(2)message
message(STATUS "Compile sources into a library?${USE_LIBRARY}")
message([<mode>] "message text" ...)
在日志中记录指定的消息文本,可以通过可选参数mode来设置日志类型,比如STATUS表示用户感兴趣的日志。
(3)list
CMake中,列表是用分号分隔的字符串组。列表可以由 list 或 set 命令创建。例如, set(var a b c d e) 和 list(APPEND a b c d e) 都创建了列表 a;b;c;d;e
list(APPEND _sources Message.cpp Message.h)
创建一个局部变量_sources,包括 Message.h 和 Message.cpp。
(4)if-else-endif
else(USE_LIBRARY)… endif(USE_LIBIRAY) 可以简写成else() 和 endif() 中的 () ,其历史原因是,因为其能够指出指令的作用范围。
3.构建编译
(1)当USE_LIBRARY为OFF时
(2)当USE_LIBRARY为ON时
二、条件控制编译
上方的代码有个缺陷,就是我们切换生成器行为时需要手动更改CMakeLists.txt中的USE_LIBRARY。option() 命令以选项的形式显示逻辑开关,用于外部设置,可以使用option( )切换构建系统的生成行为。
1.CMakeLists.txt
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(ifelseStudy LANGUAGES CXX)
option(USE_LIBRARY "Compile sources into a library" OFF)
message(STATUS "Compile sources into a library?${USE_LIBRARY}")
include (CMakeDependentOption)
cmake_dependent_option(
MAKE_STATIC_LIBRARY "Compile sources into a static library" OFF
"USE_LIBRARY" ON)
cmake_dependent_option(
MAKE_SHARED_LIBRARY "Compile sources into a shared library" ON
"USE_LIBRARY" ON)
message(STATUS "MAKE_STATIC_LIBRARY:" ${MAKE_STATIC_LIBRARY})
message(STATUS "MAKE_SHARED_LIBRARY:" ${MAKE_SHARED_LIBRARY})
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
list(APPEND
_sources
Message.cpp
Message.h)
if(USE_LIBRARY)
if(MAKE_STATIC_LIBRARY)#静态库
add_library(mylib STATIC ${_sources})
add_executable(helloworldexe helloworld.cpp)
target_link_libraries(helloworldexe mylib)
endif()
if(MAKE_SHARED_LIBRARY)#动态库
add_library(mylib SHARED ${_sources})
add_executable(helloworldexe helloworld.cpp)
target_link_libraries(helloworldexe mylib)
endif()
else()
add_executable(helloworldexe helloworld.cpp ${_sources})
endif()
2.CMake语言说明
(1)option
option(USE_LIBRARY "Compile sources into a library" OFF)
创建一个选项替换上方的 set(USE_LIBRARY OFF) 命令。该选项将修改 USE_LIBRARY 的值,并设置其默认值为 OFF 。
option 可接受三个参数: option(<option_variable> "help string" [initial value])
- <option_variable>表示该选项的变量的名称。
- "help string" 用于描述选项,在CMake的终端或图形用户界面中可见。
- [initial value] 选项的默认值,可以是 ON 或 OFF 。
(2)cmake_dependent_option
有时选项之间会有依赖的情况。比如在USE_LIBRARY 设置为ON时,我们提供生成静态库或动态库的选项。CMake提供 cmake_dependent_option() 命令用来定义依赖于其他选项的选项。
cmake_dependent_option有五个参数:
cmake_dependent_option(<option> "<help_text>" <value> <depends> <force>)
1 2 3 4 5option(1)的值由depends(4)来决定:当depends(4)为ON时,option(1)的值为value(3);当depends(4)为OFF时,option(1)的值为force(5)。
cmake_dependent_option(
MAKE_STATIC_LIBRARY "Compile sources into a static library" OFF
"USE_LIBRARY" ON)
cmake_dependent_option(
MAKE_SHARED_LIBRARY "Compile sources into a shared library" ON
"USE_LIBRARY" ON)
当USE_LIBRARY为ON时,MAKE_STATIC_LIBRARY为OFF, MAKE_SHARED_LIBRARY 为ON。
当USE_LIBRARY为OFF时,MAKE_STATIC_LIBRARY为ON, MAKE_SHARED_LIBRARY 为ON。(这时,我们编译出来的仍然是只有一个exe,没关系,我们可以通过-D来设置使其编译固定的库)
3.构建编译
-D 开关用于为CMake设置任何类型的变量:逻辑变量、路径等。
(1)直接无参构建编译
USE_LIBRARY为OFF。
(2) 设置USE_LIBRARY为ON
由CMakeLists.txt可知,当USE_LIBRARY为ON时,我们编译动态库。
(3)编译静态库
cmake -D USE_LIBRARY=ON -D MAKE_STATIC_LIBRARY=ON -D MAKE_SHARED_LIBRARY=OFF ..