导图社区 CMakelist编写整理
这是CMakelist编写整理的思维导图,主要内容为设计初衷的常见make工具、语法、一般流程、传参和特殊。
编辑于2021-08-11 16:11:55cmake
CMake Practice.pdf
设计初衷
常见的make工具
GNU Make
QT的qmake
微软的MS nmake
......
不同平台的makefile格式不同,通过cmake来兼容,只需要写一次CMakeLists.txt就OK了
语法
综合
命令不区分大小写
注释用#
命令会自动生成一些变量
变量:AAA,变量值:${AAA}
常用命令
PROJECT(hello_cmake)
设置项目名称
生成变量
PROJECT_NAME
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
限定了 CMake 的版本
ADD_SUBDIRECTORY(src)
指明本项目包含一个子目录 src
也是通过这个添加模块编译
SET(SOURCES src/Hello.cpp src/main.cpp)
创建变量SOURCES,包含了这几个文件
ADD_EXECUTABLE(main ${SOURCES })
编译SOURCES变量中的源文件编译成叫main的可执行文件
等价于ADD_EXECUTABLE(main src/Hello.cpp src/main.cpp)
ADD_LIBRARY(hello_library STATIC src/Hello.cpp)
创建名为libhello_library.a的静态库
TARGET_LINK_LIBRARIES(neutron ${APP_DEPEND_LIBS})
set(APP_DEPEND_LIBS json infra gcore vlog pthread utils http event encrypt sqllite storage aliyunOss curl apr-1 aprutil-1 expat mxml crypto ssl cJson)
添加链接库。指明可执行文件 main 需要连接....链接库
TARGET_INCLUDE_DIRECTORIES(hello_library PUBLIC ${PROJECT_SOURCE_DIR}/include)
添加了一个目录,这个目录是库所包含的头文件的目录,并设置库属性为PUBLIC。
MESSAGE(STATUS “Using bundled Findlibdb.cmake…”)
打印内容
默认变量
CMAKE_SOURCE_DIR
根源代码目录,工程顶层目录。暂认为就是PROJECT_SOURCE_DIR
CMAKE_CURRENT_SOURCE_DIR
当前处理的 CMakeLists.txt 所在的路径
PROJECT_SOURCE_DIR
工程顶层目录
CMAKE_BINARY_DIR
运行cmake的目录。外部构建时就是build目录
CMAKE_CURRENT_BINARY_DIR
The build directory you are currently in.当前所在build目录
PROJECT_BINARY_DIR
暂认为就是CMAKE_BINARY_DIR
........
可用message输出看看。
变量
Normal Variables
作用域属于整个 CMakeLists.txt 文件
set(MY_VAL "666")
MY_VAL = 666
通过add_subdirectory()/function()
相当于C++的参数传参,不是引用和指针
无PARENT_SCOPE参数
传参,局部变量修改,不影响别的文件变量值
set(MY_VAL "666")
有PARENT_SCOPE参数
相当于引用,修改会改变别的文件的变量值
set(MY_VAL "666" PARENT_SCOPE)
Cache Variables
set(MY_CACHE_VAL "666" CACHE STRING INTERNAL)
一般流程
【工程根目录】
1. 确定CMake最低版本
cmake_minimum_required (VERSION 2.8)
2. 确定项目名称
project(Demo3)
3. 指定C++版本
修改MakeFile:CFLAGS += -std=c++11
修改 CMakeLists.txt:set(CMAKE_CXX_STANDARD 11)
编译cmake时指定:cmake -DCMAKE_CXX_STANDARD=11
4. 设置路径
设置静态/动态库生成的路径
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/Lib/)
设置可执行文件生成路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/)
5. 设置编译器
【C】SET(CMAKE_C_COMPILER "/opt/sv510/bin/arm-linux-gnueabihf-gcc")
【C++】SET(CMAKE_CXX_COMPILER "/opt/sv510/bin/arm-linux-gnueabihf-g++")
6. 添加主模块
add_subdirectory(Src)
会进入Src执行它的CMakeLists.txt
【主模块】
1. 创建变量
所有源文件:APP_SOURCE_FILES
编译所有文件成可执行文件时使用
add_executable(neutron ${APP_SOURCE_FILES})
模块下
file(GLOB_RECURSE APP_DEVICE_SOURCE_FILES *.cpp)
set(APP_SOURCE_FILES ${APP_SOURCE_FILES} ${APP_DEVICE_SOURCE_FILES} PARENT_SCOPE)
所有目录路径:APP_INCLUDE_DIRS
.cpp中#inclue ".../...h"的相对路径是基于这个路径上的
set(APP_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/Include/ ${PROJECT_SOURCE_DIR}/Depend/)
所有链接库:APP_DEPEND_LIBS
用于编译结束后,给可执行文件链接所有链接库,json=libjson.so/a
target_link_libraries(neutron ${APP_DEPEND_LIBS})
set(APP_DEPEND_LIBS json crypto ssl cJson)
所有链接库路径:APP_LIBRARY_DIRS
set(APP_LIBRARY_DIRS ${PROJECT_SOURCE_DIR}/Lib/${PLATFORM}/json ${PROJECT_SOURCE_DIR}/Lib/${PLATFORM}/3thparty/openssl)
2. 修改__FILE__绝对路径
源码
function(REDEFINE_FILE_MACRO targetname) #获取当前目标的所有源文件 get_target_property(SOURCE_FILE "${targetname}" SOURCES) #遍历源文件 foreach(sourcefile ${SOURCE_FILE}) #获取当前源文件的编译参数 get_property(defs SOURCE "${sourcefile}" PROPERTY COMPILE_DEFINITIONS) #获取当前文件的绝对路径 get_filename_component(filepath "${sourcefile}" ABSOLUTE) #将绝对路径中的项目路径替换成空,得到源文件相对于项目路径的相对路径 string(REPLACE ${PROJECT_SOURCE_DIR}/ "" relpath ${filepath}) #将我们要加的编译参数(__FILE__定义)添加到原来的编译参数里面 list(APPEND defs "__FILE__=\"${relpath}\"") #重新设置源文件的编译参数 set_property( SOURCE "${sourcefile}" PROPERTY COMPILE_DEFINITIONS ${defs} ) endforeach() endfunction()
底层思路
宏__FILE__是gcc定义的,默认为gcc命令执行时的文件路径,所以是当前电脑的绝对路径,想变成代码工程的相对路径。
g++ tests/test.cc -D__FILE__="\"aaa/test.cc\"" -o test
3. 添加各个模块
4. 生效目录路径
include_directories(${APP_INCLUDE_DIRS})
5. 生效链接库路径
链接器将在这里查找库的目录
link_directories(${APP_LIBRARY_DIRS})
6. 编译可执行文件
add_executable(neutron ${APP_SOURCE_FILES})
7. 为程序重定向__FILE__
REDEFINE_FILE_MACRO(neutron)
8. 连接链接库
target_link_libraries(neutron ${APP_DEPEND_LIBS})
【子模块】
1. 添加源代码文件
file(GLOB_RECURSE APP_AUX_SOURCE_FILES *.cpp)
set(APP_SOURCE_FILES ${APP_SOURCE_FILES} ${APP_AUX_SOURCE_FILES} PARENT_SCOPE)
2. 添加目录路径
set(APP_INCLUDE_DIRS ${APP_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/Src/Alg/Record PARENT_SCOPE)
3. 添加链接库路径
set(APP_LIBRARY_DIRS ${APP_LIBRARY_DIRS} ${PROJECT_SOURCE_DIR}/Lib/${PLATFORM}/auxiliary/ ${PROJECT_SOURCE_DIR}/Lib/${PLATFORM}/3thparty/ev PARENT_SCOPE)
4. 添加模块库依赖
set(APP_DEPEND_LIBS ${APP_DEPEND_LIBS} deviceFind ev PARENT_SCOPE)
5. 添加模块识别?
add_definitions(-DLOG_LIB_MODULE="Aux")
总结
根目录:做工程级别设定
主模块和子模块,添加源代码文件名与路径、添加库文件路径
主模块:处理子模块与最终编译
传参
cmake -DAAA=111
if(${AAA} STREQUAL "111")
特殊
add_definitions(-Wno-builtin-macro-redefined)
-Wno-builtin-macro-redefined
如果某些内置宏被重新定义,请不要警告。这抑制了警告的重新定义__TIMESTAMP__,__TIME__,__DATE__,__FILE__,和__BASE_FILE__。