【CMake】CMake使用说明

1.CMake语法

(53条消息) cmake使用教程(实操版)_知愚的博客-CSDN博客_cmake

1.1 指定cmake的最小版本

cmake_minimum_required(version 2.8)

1.2 定义工程名称

# 定义工程名称 
project(MyTest)

1.3 显示定义变量

set(var [value])

## 用法1,生成代码文件列表
set(SRC_LIST add.h add.cpp)			# 先直接设置SRC_LIST的值
set(SRC_LIST ${SRC_LIST} main.cpp)	# 然后再在SRC_LIST中追加main.cpp 

## 用法2,设置库生成目录或者可执行文件生成目录
set( LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib/linux) 
set( EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

1.4 设置编译类型

# 编译静态库
add_library(库名称 STATIC 代码文件名称) 

# 编译动态库
add_library(库名称 SHARED 代码文件名称) 

# 编译可执行程序
add_executable(可执行程序名 代码文件名称)

# 例如
# 编译静态库
add_library(add STATIC add.h add.cpp)
add_library(add STATIC ${ADD_SRC} ${ADD_HDR})

# 编译动态库
add_library(add  SHARED add.h add.cpp) 
add_library(add SHARED  ${ADD_SRC} ${ADD_HDR})

# 编译可执行程序
add_executable(main add.h add.cpp mai.cpp)
add_executable(main ${MAIN_SRC} ${MAIN_HDR})

1.5 库文件输出目录

将当前编译的静态库或者动态库输出到当前项目文件夹lib子目录

set(LIBRARY_OUTPUT_PATH  ${PROJECT_SOURCE_DIR}/lib)

1.6 指定可执行程序编译输出目录

将当前可执行程序输出到当前项目文件夹的bin子目录下

#设定可执行二进制文件的目录
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

1.7 设置链接库搜索目录

例如将链接库搜索目录设置为当前项目文件夹下lib/linux文件夹

link_directories( ${PROJECT_SOURCE_DIR}/lib/linux)

1.8 设置包含目录

例如将包含目录设置为当前项目文件夹下include文件夹

include_directories(${PROJECT_SOURCE_DIR}/include)

1.9 设置宏定义

# 预定义宏
add_definitions(-D宏名称)

# 例如
add_definitions(-DWINDOWS)
add_definitions(-DLINUX)

1.10 链接静态库

link_libraries(
    静态库1
    静态库2
    静态库3
    ...
)
# 注意:link_libraries中的静态库为全路径,常与1.7 link_directories 搭配使用。

# 例如
# 设置链接目录
link_directories(${PROJECT_SOURCE_DIR}/lib/linux)
# 链接该目录下对应的库文件
link_libraries(
        lib1.a
        lib2.a
)

1.11 链接动态库

target_link_libraries(所需生成的文件名称 所需链接的动态库名称)

# 例如
target_link_libraries(main dl)

1.12 静态库和动态库链接区别

  • link_libraries用在add_executable之前,target_link_libraries用在add_executable之后;
  • link_libraries用来链接静态库,target_link_libraries用来链接导入库,即按照header file + .lib + .dll方式隐式调用动态库的.lib库

1.13 file操作

1、将文件夹所有的类型的文件添加到文件列表

file(GLOB MAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
file(GLOB MAIN_HDR ${CMAKE_CURRENT_SOURCE_DIR}/*.h)

2、将文件夹下**(包含子目录)**符合类型的文件添加到文件列表

file(GLOB_RECURSE MAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
file(GLOB_RECURSE MAIN_HDR ${CMAKE_CURRENT_SOURCE_DIR}/*.h)

1.14 list操作

1、常见List操作

list(LENGTH <list> <output variable>) 
list(GET <list> <element index> [<element index> ...] <output variable>)
list(APPEND <list> [<element> ...])
list(FIND <list> <value> <output variable>)
list(INSERT <list> <element_index> <element> [<element> ...])
list(REMOVE_ITEM <list> <value> [<value> ...])
list(REMOVE_AT <list> <index> [<index> ...])
list(REMOVE_DUPLICATES <list>)
list(REVERSE <list>)
list(SORT <list>)

2、List移除指定项

例如从MAIN_SRC移除指定项

list(REMOVE_ITEM MAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/add.cpp)

3、将两个List链接起来

# 搜索当前目录
file(GLOB  MAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
file(GLOB  MAIN_HDR ${CMAKE_CURRENT_SOURCE_DIR}/*.h)

# 递归搜索当前目录下src子目录
file(GLOB_RECURSE MAIN_SRC_ELSE  ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
file(GLOB_RECURSE MAIN_HDR_ELSE  ${CMAKE_CURRENT_SOURCE_DIR}/src/*.h)

# 将MAIN_SRC_ELSE中的值添加到MAIN_SRC 
# 将MAIN_HDR_ELSE中的值添加到MAIN_HDR 
list(APPEND MAIN_SRC ${MAIN_SRC_ELSE})
list(APPEND MAIN_HDR ${MAIN_HDR_ELSE})

1.15 添加子文件夹

例如:执行完当前文件夹CMakeLists.txt之后执行src子目录下的CMakeLists.txt

add_subdirectory(src)

1.16 message输出消息机制

输出正常:

message(STATUS "Enter cmake ${CMAKE_CURRENT_LIST_DIR}")

输出警告

message(WARNING "Enter cmake ${CMAKE_CURRENT_LIST_DIR}")

输出错误:

message(FATAL_ERROR "Enter cmake ${CMAKE_CURRENT_LIST_DIR}")

1.17 安装

install指令用于定义安装规则,安装的内容包括二进制可执行文件、动态库、静态库以及文件、目录、脚本等。

1、目标文件安装

install(TARGETS util
  RUNTIME DESTINATION bin		# 安装可执行目标二进制
  LIBRARY DESTINATION lib		# 安装动态库
  ARCHIVE DESTINATION lib)		# 安装静态库
  • 如果目标util是可执行二进制目标,则安装到${CMAKE_INSTALL_PREFIX}/bin目录;
  • 如果目标util是静态库,则安装到安装到${CMAKE_INSTALL_PREFIX}/lib目录;
  • 如果目标util是动态库,则安装到安装到${CMAKE_INSTALL_PREFIX}/lib目录;

2、文件夹安装

install(DIRECTORY include/ DESTINATION include/util)
  • 将include/目录安装到include/util目录

1.18 设置编译选项

设置编译选项可以通过add_compile_options命令,也可以通过set命令修改CMAKE_CXX_FLAGS或CMAKE_C_FLAGS。

方式1

set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -march=native -O3 -frtti -fpermissive -fexceptions -pthread")

方式2

add_compile_options(-march=native -O3 -fexceptions -pthread -fPIC)

区别在于:

  • add_compile_options命令添加的编译选项是针对所有编译器的(包括c和c++编译器),
  • set命令设置CMAKE_C_FLAGS或CMAKE_CXX_FLAGS变量则是分别只针对c和c++编译器的。

1.19 预定义变量

1、基本变量

PROJECT_SOURCE_DIR		# 我们使用cmake命令后紧跟的目录,一般是工程的根目录;
PROJECT_BINARY_DIR		# 执行cmake命令的目录,通常是${PROJECT_SOURCE_DIR}/build;
CMAKE_INCLUDE_PATH		# 系统环境变量,非cmake变量;
CMAKE_LIBRARY_PATH		# 系统环境变量,非cmake变量;
CMAKE_CURRENT_SOURCE_DIR		# 当前处理的CMakeLists.txt所在的路径;
CMAKE_CURRENT_BINARY_DIR		# target编译目录(使用ADD_SURDIRECTORY(src bin)可以更改此变量的值,SET(EXECUTABLE_OUTPUT_PATH <新路径>)并不会对此变量有影响,只是改变了最终目标文件的存储路径);
CMAKE_CURRENT_LIST_FILE			# 输出调用这个变量的CMakeLists.txt的完整路径;
CMAKE_CURRENT_LIST_LINE			# 输出这个变量所在的行;
CMAKE_MODULE_PATH				# 定义自己的cmake模块所在的路径(这个变量用于定义自己的cmake模块所在的路径,如果你的工程比较复杂,有可能自己编写一些cmake模块,比如SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake),然后可以用INCLUDE命令来调用自己的模块);
EXECUTABLE_OUTPUT_PATH 			# 重新定义目标二进制可执行文件的存放位置;
LIBRARY_OUTPUT_PATH				# 重新定义目标链接库文件的存放位置;
PROJECT_NAME					# 返回通过PROJECT指令定义的项目名称;
CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS		# 用来控制IF ELSE语句的书写方式;

2、操作系统变量

CMAKE_MAJOR_VERSION			# cmake主版本号,如3.4.1中的3;
CMAKE_MINOR_VERSION			# cmake次版本号,如3.4.1中的4;
CMAKE_PATCH_VERSION			# cmake补丁等级,如3.4.1中的1;
CMAKE_SYSTEM				# 操作系统名称,包括版本名,如Linux   2.6.22;
CAMKE_SYSTEM_NAME			# 操作系统名称,不包括版本名,如Linux;
CMAKE_SYSTEM_VERSION		# 操作系统版本号,如2.6.22;
CMAKE_SYSTEM_PROCESSOR		# 电脑处理器名称,如i686;
UNIX						# 在所有的类UNIX平台为TRUE,包括OS X和cygwin,Linux/Unix操作系统;
WIN32						# 在所有的win32平台为TRUE,包括cygwin,Windows操作系统;
APPLE						# 苹果操作系统;

操作系统判断方式一:

if(WIN32)
    message(STATUS “This operating system is Windows.”)
elseif(UNIX)
    message(STATUS “This operating system is Linux.”)
elseif(APPLE)
    message(STATUS “This operating system is APPLE.”)
endif(WIN32)

操作系统判断方式二:

if (CMAKE_SYSTEM_NAME MATCHES "Linux")
    message(STATUS "current platform: Linux ")
elseif (CMAKE_SYSTEM_NAME MATCHES "Windows")
    message(STATUS "current platform: Windows")
elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
    message(STATUS "current platform: FreeBSD")
else ()
    message(STATUS "other platform: ${CMAKE_SYSTEM_NAME}")
endif (CMAKE_SYSTEM_NAME MATCHES "Linux")

3、开关选项

BUILD_SHARED_LIBS	# 控制默认的库编译方式。如果未进行设置,使用ADD_LIBRARY时又没有指定库类型,默认编译生成的库都是静态库;
CMAKE_C_FLAGS		# 设置C编译选项,也可以通过指令ADD_DEFINITIONS()添加;
CMAKE_CXX_FLAGS		# 设置C++编译选项,也可以通过指令ADD_DEFINITIONS()添加;
CMAKE_C_COMPILER	# 指定C编译器;
CMAKE_CXX_COMPILER	# 指定C++编译器;
CMAKE_BUILD_TYPE	# build 类型(Debug, Release, …) CMAKE_BUILD_TYPE=Debug

4、环境变量

设置环境变量:

set(env{name} value)	# 环境变量设置后可被调用

# 例如
message(STATUS "$env{name}")	# 打印环境变量的值

5、CMAKE_INCLUDE_CURRENT_DIR

自动添加CMAKE_CURRENT_BINARY_DIR和CMAKE_CURRENT_SOURCE_DIR到当前处理的CMakeLists.txt。相当于在每个CMakeLists.txt加入:

include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})

1.20 条件判断

1、逻辑判断和比较

if (expression)         # expression 不为空时为真,false的值包括(0,N,NO,OFF,FALSE,NOTFOUND);
if (not exp)            # 与上面相反;
if (var1 AND var2)      # 如果两个变量都为真时为真;
if (var1 OR var2)       # 如果两个变量有一个为真时为真;
if (COMMAND cmd)        # 如果 cmd 确实是命令并可调用为真;
if (EXISTS dir) if (EXISTS file)    # 如果目录或文件存在为真;
if (file1 IS_NEWER_THAN file2)      # 当file1比file2新,或file1、file2中有一个不存在时为真,文件名需使用全路径;
if (IS_DIRECTORY dir)               # 当dir 是目录时为真;
if (DEFINED var)            # 如果变量被定义为真;
if (var MATCHES regex)      # 给定的变量或者字符串能够匹配正则表达式 regex时为真,此处var可以用var名,也可以用 ${var};
if (string MATCHES regex)   # 给定的字符串能够匹配正则表达式regex时为真。

2、数字比较

if (variable LESS number)       # 如果variable小于number时为真;
if (string LESS number)         # 如果string小于number时为真;
if (variable GREATER number)    # 如果variable大于number时为真;
if (string GREATER number)      # 如果string大于number时为真;
if (variable EQUAL number)      # 如果variable等于number时为真;
if (string EQUAL number)        # 如果string等于number时为真。

3、字母表顺序比较

if (variable STRLESS string)
if (string STRLESS string)
if (variable STRGREATER string)
if (string STRGREATER string)
if (variable STREQUAL string)
if (string STREQUAL string)

1.21 循环

1、foreach

# start表示起始数,stop表示终止数,step表示步长
foreach(loop_var RANGE start stop [step])
    ...
endforeach(loop_var)

2、while

while(condition)
    ...
endwhile()

猜你喜欢

转载自blog.csdn.net/m0_61011506/article/details/129130647