【C++ 基础】CmakeLists常用语法以及实操

CMakeLists语法

1.1 设置版本要求

CMAKE_MINIMUM_REQUIRED(VERSION 3.8.0)

1.2 设置工程名

SET(TARGET "工程名")

1.3 声明变量

SET(TARGET_OUTPUT_NAME "libZLMediaKit");

1.3.1 常用的预定义变量

CMAKE_MAJOR_VERSION:cmake 主版本号
CMAKE_MINOR_VERSION:cmake 次版本号
CMAKE_C_FLAGS:设置 C 编译选项
CMAKE_CXX_FLAGS:设置 C++ 编译选项
PROJECT_SOURCE_DIR:工程的根目录
PROJECT_BINARY_DIR:运行 cmake 命令的目录
CMAKE_CURRENT_SOURCE_DIR:当前CMakeLists.txt 所在路径
CMAKE_CURRENT_BINARY_DIR:目标文件编译目录
EXECUTABLE_OUTPUT_PATH:重新定义目标二进制可执行文件的存放位置
LIBRARY_OUTPUT_PATH:重新定义目标链接库文件的存放位置
UNIX:如果为真,表示为UNIX-like的系统,包括AppleOSX和CygWin
WIN32:如果为真,表示为 Windows 系统,包括 CygWin
APPLE:如果为真,表示为 Apple 系统
CMAKE_SIZEOF_VOID_P:表示void*的大小(例如为4或者8),可以使用其来判断当前构建为32位还是64位
CMAKE_CURRENT_LIST_DIR:表示正在处理的CMakeLists.txt文件所在目录的绝对路径
CMAKE_ARCHIVE_OUTPUT_DIRECTORY:用于设置ARCHIVE目标的输出路径
CMAKE_LIBRARY_OUTPUT_DIRECTORY:用于设置LIBRARY目标的输出路径
CMAKE_RUNTIME_OUTPUT_DIRECTORY:用于设置RUNTIME目标的输出路径

1.4 引用变量

${TARGET_OUTPUT_NAME}

1.5 输出变量

message("${TARGET_OUTPUT_NAME}");

1.6引入到include

可以使用#include 包含头文件

INCLUDE_DIRECTORIES(头文件所在文件夹路径)
SET (FILE_INCLUDE_PATH "D:\\workspace\\Codec")
INCLUDE_DIRECTORIES(${FILE_INCLUDE_PATH})

1.7 把文件夹下所有子目录在工程中显示

如果文件夹下没有任何文件,那么在工程中就不会显示

# 设置工程名——A
SET (TARGET "myProject")
# 设置需要在工程中显示的文件夹名——B
SET (FILE_INCLUDE_PATH "D:\\workspace\\Codec")
# 获取文件夹B下的全部子目录
file(GLOB subdirectories RELATIVE ${FILE_INCLUDE_PATH} ${FILE_INCLUDE_PATH}/*)
# 遍历获取到的子目录名
foreach(subdirectory ${subdirectories})
	# 设置每个子目录名的路径
	SET(ITEM_PATH "${FILE_INCLUDE_PATH}/${subdirectory}")
	# 获取每个子目录路径下的所有.h、.cpp、.c文件,并命名为ITEM
	file(GLOB ITEM "${ITEM_PATH}/*.h" "${ITEM_PATH}/*.cpp" "${ITEM_PATH}/*.c")
	# 将ITEM命名为${subdirectory},也就是子目录名,并在工程中显示
	source_group(${subdirectory} FILES ${ITEM})
	# 将ITEM中的文件加入名为ALL_SOURCES的list中
	list(APPEND ALL_SOURCES ${ITEM})
endforeach()

# 将ALL_SOURCES中的文件放入工程的lib中,并可共享
ADD_LIBRARY(${TARGET} SHARED ${ALL_SOURCES})

1.8 如果文件夹下的子目录中还有子目录需要在工程中显示

# 设置工程名——A
SET (TARGET "myProject")
# 设置需要在工程中显示的文件夹名——B
SET (FILE_INCLUDE_PATH "D:\\workspace\\Codec")
# 获取文件夹B下的全部子目录
file(GLOB subdirectories RELATIVE ${FILE_INCLUDE_PATH} ${FILE_INCLUDE_PATH}/*)
# 遍历获取到的子目录名
foreach(subdirectory ${subdirectories})
	# 设置每个子目录名的路径
	SET(ITEM_PATH "${FILE_INCLUDE_PATH}/${subdirectory}")
	# 获取每个子目录路径下的所有.h、.cpp、.c文件,并命名为ITEM
	file(GLOB ITEM "${ITEM_PATH}/*.h" "${ITEM_PATH}/*.cpp" "${ITEM_PATH}/*.c")
	# 将ITEM命名为${subdirectory},也就是子目录名,并在工程中显示
	source_group(${subdirectory} FILES ${ITEM})
	# 将ITEM中的文件加入名为ALL_SOURCES的list中
	list(APPEND ALL_SOURCES ${ITEM})
endforeach()

SET (SUBFILE_INCLUDE_PATH "D:\\workspace\\Codec\\Encode")
file(GLOB directories RELATIVE ${SUBFILE_INCLUDE_PATH} ${SUBFILE_INCLUDE_PATH}/*)
# 遍历获取到的子目录名
foreach(directory ${directories})
	# 设置每个子目录名的路径
	SET(ITEM_PATH "${SUBFILE_INCLUDE_PATH}/${directory}")
	# 获取每个子目录路径下的所有.h、.cpp、.c文件,并命名为ITEM
	file(GLOB ITEM "${ITEM_PATH}/*.h" "${ITEM_PATH}/*.cpp" "${ITEM_PATH}/*.c")
	
	# 主要区别在这里,其他的没变化
	# 将ITEM命名为${SUBFILE_INCLUDE_PATH}/${directory},也就是父文件名\子目录名,并在工程中显示
	source_group(${SUBFILE_INCLUDE_PATH}/${directory} FILES ${ITEM})
	
	
	# 将ITEM中的文件加入名为ALL_SOURCES的list中
	list(APPEND ALL_SOURCES ${ITEM})
endforeach()

# 将ALL_SOURCES中的文件放入工程的lib中,生成动态库
ADD_LIBRARY(${TARGET} SHARED ${ALL_SOURCES})
# 生成静态库
ADD_LIBRARY(${TARGET} STATIC ${ALL_SOURCES})

1.9在project下创建子项目

如果顶层CMakeLists.txt,定义了project。

# 创建工程,设置工程名为myProject,使用的语言是c c++。
project(myProject LANGUAGES C CXX)

二、CMakeLists编写的技巧

初学者的理解:

  • 顶层cmake需要设置project
  • 如果没有需要引用的外部库,就直接
    • add_library(不需要执行的子项目)或者
    • add_executable(需要执行的子项目)或者
    • 只需要以文件夹的形式显示,file收集需要显示的文件,source_group为其分组(设置显示的名字),最后add_library所有文件,才能在VS项目中显示
  • 如果需要引入外部库,使用include_directories

其他一些常用的:

  • file,获取指定文件下的指定类型文件

  • aux_source_directory,获取指定文件夹下的所有源文件

  • include_directories,获取指定路径下的所有头文件,使用时其形式为include “*.h”,如果还有子文件夹会遍历子文件夹,并把子文件名作为include时的路径元素,比如include “subdir/*.h”。

  • 设置VS中文件夹路径

    见3.4

三、实操

3.1 project

CMAKE_MINIMUM_REQUIRED(VERSION 3.1.3...3.8.0)
project(myProject)
set(CMAKE_CXX_STANDARD 11)

file(GLOB source_list ${CMAKE_CURRENT_SOURCE_DIR}/src/mediaServer/source/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/mediaServer/source/*.h)
source_group("src" FILES ${source_list})
add_library(${PROJECT_NAME} SHARED ${source_list})

在这里插入图片描述

这里又需要注意的地方,就是这个project下面必须要又内容,才能被可视。如果上述cmakelists代码,只有如下:

CMAKE_MINIMUM_REQUIRED(VERSION 3.1.3...3.8.0)
project(myproject)
set(CMAKE_CXX_STANDARD 11)

那么就没有myproject项目的显示,如下:

在这里插入图片描述

3.2 只想文件夹下的各个文件在VS中显示

只想这些文件在文件夹下显示,而不是在子项目中显示

#找到执行路径下所有cpp和h文件,并存放在source_list中
file(GLOB source_list ${CMAKE_CURRENT_SOURCE_DIR}/src/mediaServer/source/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/mediaServer/source/*.h)
add_library(${PROJECT_NAME} SHARED ${source_list})

如果这样写,会将指定路径下的所有指定类型的文件,全部在myproject的Source Files和Header Files中显示,系统会自动将头文件和源文件分开。

如下

在这里插入图片描述

如果需要将,指定文件夹下的所有文件存放在一个文件夹下在VS中显示,需要使用source_group,如下

CMAKE_MINIMUM_REQUIRED(VERSION 3.1.3...3.8.0)
project(myproject)
set(CMAKE_CXX_STANDARD 11)

set(mediaserver_source_root ${CMAKE_CURRENT_SOURCE_DIR}/src/mediaServer/source)

file(GLOB source_list ${mediaserver_source_root}/*.cpp ${mediaserver_source_root}/*.h)
source_group("src" FILES ${source_list})

add_library(${PROJECT_NAME} SHARED ${source_list})

在这里插入图片描述

3.3 加入库,通过include使用

使用add_library加入project后,就可以直接使用,示例代码入3.2所示

在这里插入图片描述

3.4 set FOLDER

在VS中设置文件夹路径

#需要先将能使用文件夹打开
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
#再设置文件夹路径
set(FOLDER_PATH "TEST")
#最后将需要放在该文件夹下的子项目或文件夹,链接上
set_target_properties(${TARGET} PROPERTIES FOLDER ${FOLDER_PATH})

其中将使用文件夹功能打开,建议在顶层cmakelists文件中设置,设置后,全局都默认是打开的。

具体示例代码:

# 设置target名字
SET(TARGET PUSHER)
# 开启使用文件夹
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# 设置pusher的源文件路径
set(PUSHER_SOURCE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/src)
# 获取源文件下所有的cpp文件
aux_source_directory(${PUSHER_SOURCE_ROOT} pusher_source_list 
# 加入到库,会创建子项目
add_library(PUSHER ${pusher_source_list})
# 设置文件夹名字
set(FOLDER_PATH "TEST")
# 将子项目放入该文件夹下
set_target_properties(${TARGET} PROPERTIES FOLDER ${FOLDER_PATH})

结果如下:

在这里插入图片描述

3.5 使用其他库的头文件

如下

在这里插入图片描述

有两个项目,myproject和PUSHER,现在这两个项目,只能使用其自己项目的头文件。如果PUSHER的name.cpp需要使用myproject的Client.h或者Server.h,是会报错的,如下

在这里插入图片描述

如果需要PUSHER使用(include)myproject的头文件,那么需要使用include_directories。

具体代码如下

SET(TARGET PUSHER)
set(PUSHER_SOURCE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/src)
message("PUSHER_SOURCE_ROOT: ${PUSHER_SOURCE_ROOT}")
aux_source_directory(${PUSHER_SOURCE_ROOT} pusher_source_list )
message("pusher_source_list : ${pusher_source_list}")
foreach(item ${pusher_source_list})
	message("pusher_source_list :${item}")
endforeach()
add_executable(PUSHER ${pusher_source_list})
set(FOLDER_PATH "TEST")
message("FOLDER_PATH : ${FOLDER_PATH}")
message("TARGET_NAME : ${TARGET}")
set_target_properties(${TARGET} PROPERTIES FOLDER ${FOLDER_PATH})

# 主要是
# 设置需要include的库路径
set(3rdpart_root ${PROJECT_SOURCE_DIR}/src/mediaServer/source)
message("3rdpart_root : ${3rdpart_root}")
# 加入库
include_directories("${3rdpart_root}")

这样之后,就能够使用myprojecct的头文件了。结果如下:

在这里插入图片描述

如果某个路径下,有多个文件夹,每个文件夹下都有需要include的头文件,那么直接include_directories其上层路径,如下

set(3rdpart_root ${PROJECT_SOURCE_DIR}/src/mediaServer)
message("3rdpart_root : ${3rdpart_root}")
include_directories("${3rdpart_root}")

注意和上面的区别,只是mediaServer后面没有跟具体include哪个文件夹下的头文件,测试效果如下:

在这里插入图片描述
在这里插入图片描述

  • 22
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豆得儿不是猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值