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文件主要点有:
- 将cpp文件编译成库,链接到可执行文件
- 查找第三方库文件,并链接到可执行文件
- 指定库文件的生成路径,可执行文件的生成路径
- 搜索第三方库的头文件路径以及库文件路径,并告诉cmake,方便将第三方库链接到可执行文件
当然,更加复杂的项目文件系统和编译要求也有,后面有遇到可以进一步补充,以上这些在一些简单的项目中已基本够用。