CMake —从入门到精通(1)
首先感谢阅读,作者是在工作中学习与积累,每一个笔记都是心得和积累,希望可以和大家一起交流学习。
简介
Makefile:需要熟悉Makefile语法,还需依赖和推导规则,比较麻烦。
cmake:只需要开发者提供头文件路径、库路径、编译参数等基本参数,就快速生成Makefile,语法简单,易上手,另外cmake工具能够满足跨平台的要求。
理论
CMake生成Makefile并编译
- 编写 cmake 配置文件 CMakeLists.txt
- 在CMakeLists.txt所在目录创建build文件夹,然后进入目录
- 执行cmake …/ 生成makefile
- 执行make和make install进行编译和安装
Example实战1 初识
-
随手写一个cpp程序
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main() { printf("Martin is very newbee !\n"); return 0; }
-
编译它,CMakeLists.txt如何编写呢
#指定使用该CMakeList.txt文件需要的cmake最低版本 cmake_minimum_required(VERSION 3.5) #指定项目信息 project(calculator) #设置安装目录 set(INSTALL_DIR ${CMAKE_SOURCE_DIR}/install) #指定生成目标 add_executable(calculator main.cpp) #安装到安装目录 INSTALL(TARGETS calculator DESTINATION ${INSTALL_DIR}/usr/bin)
其中,
CMAKE_SOURCE_DIR为cmake定义的变量,指定义了顶级CMakeLists.txt的文件夹。
-
执行下面脚本
进行(1)创建build目录;(2)生成Makefile;(3)编译连接;(4)安装的操作
mkdir build cd build cmake ../ make make install
Example实战2 进阶
-
对上面的例子进行扩展,增加加法运算的函数,add.cpp和add.h文件
├── add.cpp ├── add.cpp ├── add.h ├── add.h ├── CMakeLists.txt ====> ├── CMakeLists.txt └── main.cpp ├── main.cpp ├── sub.cpp └── sub.h
怎么添加要编译的文件呢???修改下CMakeList.txt
#指定生成目标,在这里增加文件 add_executable(calculator main.cpp add.cpp)
问题来了,难道一直添加文件就一直重复上述操作吗???明显聪明人不会这么做!
杀招来了:aux_source_directory命令 -
aux_source_directory命令
该命令会查找指定目录下的所有源文件,然后将结果存进指定的变量名
#指定使用该CMakeList.txt文件需要的cmake最低版本 cmake_minimum_required(VERSION 3.5) #指定项目信息 project(calculator) #设置安装目录 set(INSTALL_DIR ${CMAKE_SOURCE_DIR}/install) #查找当前目录下的所有源文件 #并将名称保存到ALL_SRCS变量 aux_source_directory(. ALL_SRCS) #指定生成目标 #add_executable(calculator main.cpp add.cpp sub.cpp) add_executable(calculator ${ALL_SRCS}) #安装到安装目录 INSTALL(TARGETS calculator DESTINATION ${INSTALL_DIR}/usr/bin)
其中,
aux_source_directory(. ALL_SRCS)将目录下所有源文件的名称,存入变量ALL_SRCS
Example实战3 变态难度 静态库&动态库
之前都是cpp文件,cmake对于这类比较low的文件还是比较轻松的,下面开始上强度
-
对上面的例子再进行扩展,增加乘法函数,编译成静态库;增加触发运算,编译成动态库;
最后再链接为一个完整的可执行程序
├── add.cpp ├── add.h ├── CMakeLists.txt ├── div │ ├── CMakeLists.txt │ ├── div.cpp │ └── div.h ├── main.cpp ├── mul │ ├── CMakeLists.txt │ ├── mul.cpp │ └── mul.h ├── sub.cpp └── sub.h
mul和div文件夹下都有CMakeList.txt子文件,顶层CMakeList.txt文件中包含子cmake
儿子1 mul
#查找当前目录下的所有源文件 #并将名称保存到MUL_SRCS变量 aux_source_directory(. MUL_SRCS) #生成静态链接库 add_library(mul STATIC ${MUL_SRCS}) #安装到安装目录 INSTALL(TARGETS mul DESTINATION ${INSTALL_DIR}/usr/lib)
add_library(mul STATIC ${MUL_SRCS})指定生成静态库
儿子2 div
#查找当前目录下的所有源文件 #并将名称保存到DIV_SRCS变量 aux_source_directory(. DIV_SRCS) #生成动态链接库 **add_library(div SHARED ${DIV_SRCS})** #安装到安装目录 INSTALL(TARGETS div DESTINATION ${INSTALL_DIR}/usr/lib)
add_library(div SHARED ${DIV_SRCS}) 指定生成动态库
老父亲
#指定使用该CMakeList.txt文件需要的cmake最低版本 cmake_minimum_required(VERSION 3.5) #指定项目信息 project(calculator) #设置安装目录 set(INSTALL_DIR ${CMAKE_SOURCE_DIR}/install) #添加子目录 **add_subdirectory(mul) add_subdirectory(div)** #包含头文件目录 **include_directories(${CMAKE_SOURCE_DIR}/mul) include_directories(${CMAKE_SOURCE_DIR}/div)** #查找当前目录下的所有源文件 #并将名称保存到ALL_SRCS变量 aux_source_directory(. ALL_SRCS) #指定生成目标 add_executable(calculator ${ALL_SRCS}) #添加链接库 **target_link_libraries(calculator mul) target_link_libraries(calculator div)** #安装到安装目录 INSTALL(TARGETS calculator DESTINATION ${INSTALL_DIR}/usr/bin)
add_subdirectory表示本项目包含一个子目录
include_directories表示将指定目录添加到编译器的头文件搜索路径之下
target_link_libraries表示可执行文件calculator需要连接一个名为 mul/div的链接库
Cmake例程:
cmake_minimum_required(VERSION 3.10)
project(Functional)
add_compile_options(-std=c99)
set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
#link_directories(${PROJECT_SOURCE_DIR} )
set(CC_FILES ${PROJECT_SOURCE_DIR}/../App/FuncSafety/src/FuncSafety_Api.c)
set(CC_FILES ${CC_FILES} ${PROJECT_SOURCE_DIR}/../Module/FS_Cmpt/src/FuncSafety_Cmpt_Manage.c)
set(CC_FILES ${CC_FILES} ${PROJECT_SOURCE_DIR}/../Module/FS_Cmpt/src/FuncSafety_Cmpt_MonAlr.c)
set(CC_FILES ${CC_FILES} ${PROJECT_SOURCE_DIR}/../Module/FS_Cmpt/src/FuncSafety_Cmpt_Process.c)
set(CC_FILES ${CC_FILES} ${PROJECT_SOURCE_DIR}/../Module/FS_DrvIntf/src/FuncSafety_DrvIntf.c)
set(CC_FILES ${CC_FILES} ${PROJECT_SOURCE_DIR}/../Module/FS_Mod/src/FuncSafety_Mod_Camera.c)
set(CC_FILES ${CC_FILES} ${PROJECT_SOURCE_DIR}/../Module/FS_Mod/src/FuncSafety_Mod_Display.c)
set(CC_FILES ${CC_FILES} ${PROJECT_SOURCE_DIR}/../Module/FS_Mod/src/FuncSafety_Mod_FPD_Link.c)
set(CC_FILES ${CC_FILES} ${PROJECT_SOURCE_DIR}/../Module/FS_Mod/src/FuncSafety_Mod_GMSL.c)
set(CC_FILES ${CC_FILES} ${PROJECT_SOURCE_DIR}/../Module/FS_Mod/src/FuncSafety_Mod_ISP.c)
set(CC_FILES ${CC_FILES} ${PROJECT_SOURCE_DIR}/../OS/src/Os_Interface.c)
add_library(${PROJECT_NAME} SHARED ${CC_FILES})
include_directories( ${PROJECT_SOURCE_DIR}/../Lib/inc
${PROJECT_SOURCE_DIR}/../App/FuncSafety/inc
${PROJECT_SOURCE_DIR}/../Module/FS_Cmpt/inc
${PROJECT_SOURCE_DIR}/../Module/FS_DrvIntf/inc
${PROJECT_SOURCE_DIR}/../Module/FS_Mod/inc
${PROJECT_SOURCE_DIR}/../OS/inc )
#target_link_libraries(${PROJECT_NAME} )
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR})