CMake学习笔记

使用cmake进行项目构建已经很久了,但是一直是一知半解的状态,在此做一些整理,今后会根据实际使用和学习的进展来不断完善更新。

以下是一些收藏的高质量的cmake网页,常看常新:

cmake 之 CMakeLists.txt常用命令语法介绍
cmake 之 find_package 用法详解
cmake 之 官方教程 #全英教程,且示例有一定门槛

以下将按照不同的文件结构和编译需求,对CMakeLists.txt进行分类整理。

这是参考的一个博主的内容,且他将源码发布在GitHub上了,当时只顾着下载GitHub源码,忘记收藏网页,也忘记作者是哪位了。后面如果找到这个原作者一定会附上链接,也希望如果有幸被原作者看到,还请联系一下,谢谢!

1. 编译某一目录中的指定源文件,且没有调用第三方库,最终编译成一个可执行文件
文件树:
- CMakeLists.txt
- test.cpp`
CMakeLists.txt
project( Demo1 )
cmake_minimum_required( VERSION 2.8 )
set(CMAKE_CXX_STANDARD    11)
set(CMAKE_BUILD_TYPE "Release")  # Debug
add_executable( test test.cpp )

2. 编译同一目录中的多个源文件,且没有调用第三方库,最终编译成一个可执行文件
文件树:
- CMakeLists.txt
- test01.cpp
- test02.c
- test01.h
- test02.hpp
CMakeLists.txt
project( Demo2 )
cmake_minimum_required( VERSION 2.8 )
set(CMAKE_CXX_STANDARD    11)
set(CMAKE_BUILD_TYPE "Release")  # Debug

file( GLOB SRCS *.c *.cpp *.cc *.h *.hpp )# 把当前文件夹下的源码列表(文件后缀匹配的那些文件)存到变量 SRCS 中
add_executable( test01 ${SRCS} )# 将SRCS中保存的文件编译成可执行文件

3. cpp文件在一个文件夹(src/中),头文件在另一个文件夹内(include/中),且没有调用第三方库,最终编译成一个可执行文件
文件树:
- CMakeLists.txt
- include
  - count.h
- src
  - count.cpp
  - test03.cpp
CMakeLists.txt
project( Demo3 )
cmake_minimum_required( VERSION 2.8 )
set(CMAKE_CXX_STANDARD    11)
set(CMAKE_BUILD_TYPE "Release")  # 也可以是Debug

aux_source_directory(./src/ DIR_SRC) # 查找在src路径下的所有源文件,并将源文件名保存在DIR_SRC中。

include_directories(./include/) # 设定头文件路径

add_executable( test03 ${DIR_SRC} )

4. cpp文件在一个文件夹(src/中),头文件在另一个文件夹内(include/中),调用第三方库,最终编译成一个可执行文件
文件树:
- CMakeLists.txt
- include
  - test04.h
- src
  - test04.cpp
CMakeLists.txt
project( Demo4 )
cmake_minimum_required( VERSION 2.8 )
set(CMAKE_CXX_STANDARD    11)
set(CMAKE_BUILD_TYPE "Release")  # 也可以是Debug

aux_source_directory(./src/ DIR_SRC)
include_directories(./include/)

find_package(OpenCV REQUIRED)  # 查找并添加OpenCV的头文件目录
# message( STATUS "    version: ${OpenCV_VERSION}" )
# message( STATUS "    include path: ${OpenCV_INCLUDE_DIRS}" )
include_directories(${OpenCV_INCLUDE_DIRS})

add_executable( test04 ${DIR_SRC} )
target_link_libraries( test04 ${OpenCV_LIBS} )  # 可执行文件名 链接 OpenCV库

5. cpp文件在一个文件夹(src/中),头文件在另一个文件夹内(include/中),将自己的cpp文件(libsrc/中)生成静态库,将静态库链接到可执行文件,最终生成一个可执行文件
文件树
- CMakeLists.txt   #1
- include
  - add.h
  - mul.h
- libsrc
  - CMakeLists.txt  #2
  - add.cpp
  - mul.cpp
- src
  - CMakeLists.txt  #3
  - main.cpp
CMakeLists.txt #1
cmake_minimum_required (VERSION 3.5)
project (test5)

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)	# 设置可执行文件的输出目录
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)	# 设置库文件的输出目录

include_directories (${PROJECT_SOURCE_DIR}/include)		# 添加头文件目录,可以添加多个,或多次添加

# refer:https://www.jianshu.com/p/07acea4e86a3
add_subdirectory(${PROJECT_SOURCE_DIR}/libsrc)		# 先执行这个目录下的cmake生成静态库
add_subdirectory(${PROJECT_SOURCE_DIR}/src)			# 在生成库后,此时再链接库生成可执行文件
CMakeLists.txt #2
# 生成静态库,name属性必须全局唯一
add_library(add STATIC ${PROJECT_SOURCE_DIR}/libsrc/add.cpp)
add_library(mul STATIC ${PROJECT_SOURCE_DIR}/libsrc/mul.cpp)
CMakeLists.txt #3
aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC_LIST)
add_executable (test5 ${SRC_LIST})
# 将静态库链接到可执行文件
target_link_libraries(test5
		${PROJECT_SOURCE_DIR}/lib/libadd.a
		${PROJECT_SOURCE_DIR}/lib/libmul.a)

6. sub文件夹是一个项目,把sub文件夹编译成静态库,链接到可执行文件,最终生成一个可执行文件
文件树:
- sub
  - add.h
  - add.cpp
  - CMakeLists.txt  #1
- main.cpp
- CMakeLists.txt  #2
CMakeLists.txt #1
add_library(subadd add.cpp)  # 生成静态库libsubadd.a,subadd这个名字可以自定义
CMakeLists.txt #2
cmake_minimum_required(VERSION 3.10.2)
project(main)

# sub子模块
include_directories(sub)  # 添加头文件查找路径
add_subdirectory(sub)  # 会编译子模块生成静态库,默认保存位置:build/sub/libsubadd.a

add_executable(main main.cpp)
target_link_libraries(main subadd)  # 会链接静态库subadd

7. 编译多个子文件夹为静态库/动态库,并调用第三方库,生成一个可执行文件
文件树:
- source
  - add
	- add.h add3.h
	- add.cpp add3.cpp
  - mul
	- mul.h
	- mul.cpp
  - sub
	- sub.h
	- sub.cpp
- main.cpp
- CMakeLists.txt
CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(test8)

set(CMAKE_CXX_STANDARD 11)  # 指定为 C++ 版本
set(CMAKE_BUILD_TYPE Release)  # Debug模式可以调试,Release模式运行速度快

message("${PROJECT_SOURCE_DIR}=" ${PROJECT_SOURCE_DIR})

# 这里设置好路径后,进入子模块的cmake时不用再次设置
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)  # 设置可执行文件的输出目录
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)	   # 设置库文件的输出目录

# 编译add,生成静态库
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/source/add ADD_SRC_LIST)
add_library(add ${ADD_SRC_LIST})

# 编译sub,生成静态库
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/source/sub SUB_SRC_LIST)
add_library(sub ${SUB_SRC_LIST})

# 编译mul,生成动态库
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/source/mul MUL_SRC_LIST)
add_library(mul SHARED ${MUL_SRC_LIST})

# 添加头文件路径,用于编译可执行文件
include_directories(./source/add
                    ./source/sub
                    ./source/mul)

# 调用第三方库 OpenCV
find_package(OpenCV REQUIRED)  # 查找并添加OpenCV的头文件目录
# message( STATUS "    version: ${OpenCV_VERSION}" )
# message( STATUS "    include path: ${OpenCV_INCLUDE_DIRS}" )
include_directories(${OpenCV_INCLUDE_DIRS})

# 编译main,生成可执行文件
add_executable(main ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
target_link_libraries(main add sub mul ${OpenCV_LIBS})  # 链接所有库

总的来说,编写CMakeLists.txt文件主要点有:

  1. 将cpp文件编译成库,链接到可执行文件
  2. 查找第三方库文件,并链接到可执行文件
  3. 指定库文件的生成路径,可执行文件的生成路径
  4. 搜索第三方库的头文件路径以及库文件路径,并告诉cmake,方便将第三方库链接到可执行文件

当然,更加复杂的项目文件系统和编译要求也有,后面有遇到可以进一步补充,以上这些在一些简单的项目中已基本够用。

posted @ 2022-12-06 14:46  Du_huili  阅读(34)  评论(0编辑  收藏  举报