天天看点

【工作向】CMakeLists.txt写作

1. CMakeLists.txt导览

1.1 cmake介绍

  • cmake是GNU工具链中构建项目的重要一环,Linux常用,Windows下有cmake软件
  • cmake根据CMakeLists.txt生成一个编译规则(Makefile文件)
  • 编译器逐个文件进行编译,生成中间件,Makefile是将中间件统一编译的规则
  • 查看cmake版本:cmake --version

1.2 CMakeLists.txt介绍

  • 项目构建,每个需要管理的目录下均存在一个CMakeLists.txt
  • CMakeLists.txt大小写敏感
  • 在需要进行编译的文件夹内编写CMakeList.txt,.cpp/.c的文件夹内
  • 通常将下层目录编译成一个静态库文件,让上层目录直接读取和调用,而上层目录就直接生成一个可执行文件
  • 在最顶层创建build或cmake目录,然后编译

1.3 cmake构建方式

mkdir cmake && cd cmake
cmake ..			# 指定CMakeLists.txt所在目录,cmake实际是做了一个转换,将CMakeLists.txt转换成Makefile文件
make project_name	# 然后由make进行编译,输出project文件

./project_name		# 运行可执行文件
           

2. CMakeLists.txt基本结构

# 简单举例:

cmake_minimum_required(VERSION 3.9)		# cmake版本【可省略】

project(my_project)						# 项目名称

add_executable							# 添加源文件

target_include_directories				# 添加头文件

target_link_directories					# 库文件目录

target_link_libraries					# 链接库文件
           

3. 命令介绍

1. set

功能:给文件名/路径名/源文件/库文件等起别名
set(变量 文件名/路径名/库文件/源文件)
	set(THIRD_PARTY /data/libcommon.so)		// 显示定义变量, 用变量代替值
           

2. target_link_libraries

功能:

将目标文件与库文件进行链接,不然会出现光声明没定义的错误

# 对add_executable生成的文件进行链接操作
	# 库文件名称通常为libxxx.so,链接时只需要写xxx即可 */

	target_link_libraries(main THIRD_PARTY)		# THIRD_PARTY是多个库文件的别名
	target_link_libraries(main xxx.so)
	target_link_libraries(main xxx.a)
           

3. if else

功能:条件控制语句
### 方式1: ###
	if()
		# do something
	endif()
	
	### 方式2: ###
	if(condition1)
		# do something
	elseif(condition2)
		# do something
	else()
		# do something
	endif()
           
if (DEFINED cpu AND "${cpu}" STREQUAL "x86")
		set(THIRD_PARTY /x86/.../xx.so)
	else()
		set(THIRD_PARTY /arm/.../xx.so)
	endif()
	
	# DEFINED: 是否定义过
	# AND/OR/NOT:与或非
           

4. -D和-G选项

功能:

-D: 使用cmake -D 创建一个要用的编译类型的cmake缓存

-G:设置指定的生成器,generator,可以设置IDE

# CMakeLists.txt中使用:
	if (TARGET_CPU STREQUAL "x86")
		# do something
	else()
		# do something
	endif()
           

5. file

功能:

查找头文件/源文件

file参数较多,还有WRITE/READ/RENAME/REMOVE等参数

file(GLOB HEADER_FILES ${DIR}/*.h)			# 查找DIR目录下所有头文件并保存到HEADER_FILES变量里
	file(GLOB_RECURSE SRC_FILES ${DIR}/*.cpp)	# 查找DIR目录下所有源文件并保存到SRC_FILES变量里

	# GLOB和GLOB_RECURSE推荐使用RECURSE递归版本,避免源文件添加或删除引起识别错误
           

6. add_executable

功能:

添加不同项目要编译的可执行文件

将.cpp/.c/.cc等文件生成可执行文件

# add_executable(${PROJECT_NAME} xxx.cpp)

	project(test)
	add_executable(test ${SRC_FILES1} ${SRC_FILES2})
           

7. option

功能:

提供一个用户可以选择的选项:ON 或 OFF, 如果不提供初始值,默认为OFF

8. add_definitions

功能:

相当于添加编译宏,方便通过命令行而不是改代码进行参数控制

或用于添加编译选项

option(TORCH_DEBUG "option for torch debug" OFF)
	if(TORCH_DEBUG)
		add_definitions(-DTORCH_DEBUG)
	endif(TORCH_DEBUG)
           
/* 源文件中 */
	#ifdef TORCH_DEBUG
	...
	#else
	...
	#endif
           
  • 构建项目的时候就可以添加参数控制宏的开启和关闭
cmake -DTORCH_DEBUG=ON ..	# 打开
	cmake -DTORCH_DEBUG=OFF ..	# 关闭
           
# 添加编译选项
	add_definitions("-Wall -g")		# 显示所有类型log,用于gdb调试
           

9. target_include_directories

功能:

指定编译target所需要的头文件路径

# PUBLIC和INTERFACE具有依赖传递性,而PRIVATE没有
	
	PRIVATE: 指这里引用的头文件路径仅仅被这个目标使用,目标不会对外暴露引用的头文件路径
	
	PUBLIC:不仅被这个目标使用,目标还会对外暴露引用的头文件路径
	
	INTERFACE:引用头文件不被这个目标使用,但目标会对外暴露引用的头文件路径
           

10. target_link_directories

功能:

目标添加链接库的查找目录,只是提供目录,具体链接库文件通过 target_link_libraries 添加

用法和 target_include_directories 基本类似

# target_link_libraries 		# 链接单个库文件或库文件目录下的所有库文件
	# target_include_directories	# 包含头文件
	
	# 举例
	target_link_directories(test PRIVATE ${OFFLINE_LIB})
           

11. target_compile_definitions

功能:目标添加编译器编译选项

12. message

功能:打印消息
message([mode] "message to display" ...)
	
	mode: 模式,可不写;有STATUS/ERROR/DEBUG/TRACE等选项, STATUS表示一般的打印信息
	"..."	为要显示的内容
	...		表示可以连接多个输出

	message(${STRING})		# 打印STRING变量值
           

13. add_subdirectory

功能:

添加编译的子文件夹

当执行到 add_subdirectory 这一句时会先将子文件夹进行编译生成库文件等

在 add_subdirectory 之前set的各个变量,包括子文件中生成的库文件,在子文件夹中可以调用

子文件夹里添加CMakeList.txt就可进行编译

# 代码结构
	
	|--- example.cpp
	|--- CMakeLists.txt		# add_subdirectory(SubDir)
	|--- SubDir
		|-- subExample.xpp
		|-- subHeader.h
		|-- CMakeLists.yxy
	|--- ThirdParty
		|--- bin			# 可执行文件
		|--- include		# 头文件
		|--- lib			# 库文件
           

14. aux_source_directory

功能:获取路径下所有的源文件.cpp/.c/.cc文件,并赋值给变量中
# aux_source_directory(路径 变量)
	
	aux_source_directory(${PROJECT_SRC_DIR} SRC_FILES)
           

参考文章:

cmake: 推荐阅读

编译选项介绍

cmake基本用法

cmake备忘录

created by shuaixio, 2021.07.30