Cmake
-
工具链
- 预处理器(宏替换)->编译器->汇编器(二进制文件.obj&&.0)->链接器->变成.exe
-
单源文件可以直接命令生成.exe
- 解决1:源文件多时要编写makefile,但编写makefile文件很麻烦
- 解决2:使用cmake,跨平台,可以直接生成makefile
-
命令行直接编译源文件
g++ *.cpp -o app
- 会生成一个
app.exe
./app
-
编写
CMakelist.txt
-
# ====================================================================================== # 指定cmake的最低版本 cmake_minimum_required(VERSION 3.0.0) # 指定工程名 project(CALC) # 生成可执行文件名app: add_executable(可执行程序名 源文件名称) 后面的源文件用空格or; # add_executable(app add.c div.c main.c mult.c sub.c) # ====================================================================================== # 设置变量值: set(变量名, 变量值) 后面的变量值用空格隔开 set(SRC_LIST add.c div.c main.c mult.c sub.c) # 取变量值 add_executable(app ${SRC_LIST}) # 设置c++版本为c++11 set(CMAKE_CXX_STANDARD 11) # 设置app.exe的输出路径 set(HOME /home/fyq/...) set(EXECUTABLE_OUTPUT_PATH ${HOME}/bin) # ====================================================================================== # 搜索文件 # aux_source_directory(${PROJECT_SOURSE_DIR} SRC_LIST) # file(GLOB/GLOB_RECURSE SRC ${CMAKE_CURRENT_SOURSE_DIR}/*.cpp) # ======================================================================================
-
执行
cmake
命令,cmake
后面跟的目录是CMakelist.txt
所在的目录,会生成一系列文件,一般是在build
文件夹中执行,生成Makefile
文件后执行make
命令即可生成可执行文件 -
set
命令- 设置变量值
set(SRC_LIST add.c div.c main.c mult.c sub.c)
:设置SRC_LIST
的值为add.c ...
add_executable(app ${SRC_LIST})
:取变量值用${}
- 设置指定的
c++
版本:c++11
、c++14
、c++17
默认是c++98
- 方法一:
g++ *.cpp -std=c++11 -o app
- 方法二:在
CMakelist.txt
文件中指定 ,加入set(CMAKE_CXX_STANDARD 11)
- 方法一:
- 设置可执行文件的输出路径 建议使用绝对路径
set(HOME /home/fyq/...)
set(EXECUTABLE_OUTPUT PATH ${HOME}/bin)
- 设置变量值
-
set
命令需要找到所有的文件,仍然很麻烦,因此有搜索文件命令- 方法一:
aux_source_directory
${PROJECT_SOURSE_DIR}:CMakelist.txt所在目录路径aux_source_directory(${PROJECT_SOURSE_DIR} SRC_LIST)
:找到源文件目录下的所有文件,并赋值给SRC_LIST
add_executable(app ${SRC_LIST})
- 方法二:
file命令
${CMAKE_CURRENT_SOURSE_DIR}:CMakelist.txt所在目录路径file(GLOB/GLOB_RECURSE SRC ${CMAKE_CURRENT_SOURSE_DIR}/*.cpp)
:递归搜索某目录文件搜索所有.cpp
文件,将值赋给SRC
变量
- 方法一:
-
指定头文件所在路径
include_directories(${CMAKE_CURRENT_SOURSE_DIR}/include)
:head.h
在/include
目录下
-
动态库和静态库
- 注意:静态库会被加到生成文件中,因此应该在生成可执行文件即
add_exectable()
命令前运行,但是动态库不会被加,因此需要在生成可执行文件后执行,一般就是放在文件最末尾 - 都由
lib_xxx.xxx
组成,第二个是xxx
是后缀- 若是动态库 有可执行权限:
windows
:lib_xxx.dll
linux
:lib_xxx.so
- 若是静态库 无可执行权限
windows
:lib_xxx.lib
linux
:lib_xxx.a
- 若是动态库 有可执行权限:
- 制作静态库:例如制作一个计算器,只需要
add.c div.c ...
不需要main.c
add_library(库名称 STATIC 源文件1 源文件2...)
:add_library(calc STATIC ${SRC})
- 制作动态库
add_library(库名称 SHARED 源文件1 源文件2...)
:``add_library(calc SHARED ${SRC})`
- 指定输出库的路径 设置宏${LIBRARY_OUTPUT_PATH}
set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_SOURSE_DIR}/lib)
- 注意:静态库会被加到生成文件中,因此应该在生成可执行文件即
-
有了静态库和动态库之后,之前的
div.c add.c...
就不需要了,只需要使用库文件就行- 链接静态库库文件
link_libraries(静态库名字1 名字2...)
:link_libraries(calc)
- 对于自定义的库文件,还需要指定路径
link_directories(path)
:link_directories(${CMAKE_CURRENT_SOURSE_DIR}/lib)
- 链接动态库文件 注意:链接动态库需要写在生成可执行文件之后(add_executable(…))
target_link_libraries(动态库名称)
:target_link_libraries(app calc)
app是可执行文件,表示app要链接动态库,后面的calc是被链接的动态库名称
- 链接静态库库文件
-
日志
message(重要程度 消息)
:message(STATUS "message status")
默认重要STATUS
:非重要WARNING
:警告,继续执行SEND_ERROR
:继续执行,但是跳过所有生成步骤FATAL_ERROR
:cmake错误,终止所有
-
变量操作
- 字符串拼接:
list(APPEND 变量名 [子字符串])
:list(APPEND ${SRC} ${TEMP})
将TEMP
的值追加到SRC
中set(变量名 字符串1 字符串2 ..)
:set(tmp ${tmp1} ${tmp2})
将tmp1
和tmp2
的内容拼接,放到tmp
中
- 字符串删除:
list(REMOVE_ITEM 变量名 [子字符串])
:list(REMOVE_ITEM ${SRC} main.cpp)
list
其他功能list
底层存储了很多的字符串,每个字符串通过;
相隔- 获取长度:
list(LENGTH 列表名字 输出变量)
- 获取索引处值:
list(GET 列表名字 索引位置)
- 索引位置
-1
表示最后一个元素
- 索引位置
- 将列表中的元素连接成新字符串:
list(JOIN 列表名字 指定连接字符串 输出变量)
- 列表中是否存在指定元素:
list(FINO 列表名字 搜索元素 输出变量)
- 存在则返回索引,否则返回-1
- 插入元素在指定位置:
list(INSERT 列表名字 索引 插入元素1 插入元素2...)
- 移除最后元素:
list(POP_BACK 列表名字 存储弹出元素的变量:可省略)
- 将指定索引删除:
list(REMOVE_AT 列表名字 索引)
- 删除重复元素:
list(REMOVE_DUPLICATED 列表名字)
- 列表反转:
list(REVERSE 列表名字)
- 列表排序:
list(SORT 列表名字 COMPARE:... CASE:... ORDER:...)
COMPARE
:指定排序方法STRING
:字母顺序,默认FILE_BASENAME
:若是一系列路径名,会使用basename
排序NATURAL
:使用自然数顺序排序
CASE
:是否大小写敏感SENSITIVE
:大小写敏感,默认INSENSITIVE
:大小写不敏感
ORDER
:指定排序顺序ASCENDING
:升序排列,默认DESCENDING
:降序排序
- 获取长度:
- 字符串拼接:
-
自定义宏 用来控制日志是否输出
add_definitions(-D宏名称)
:add_definitions(-DDEBUG)
定义了一个DEBUG宏
-
Cmake
嵌套-
子节点可以使用父节点的变量值
-
$ tree . ├── build ├── calc │ ├── add.cpp │ ├── CMakeLists.txt │ ├── div.cpp │ ├── mult.cpp │ └── sub.cpp ├── CMakeLists.txt ├── include │ ├── calc.h │ └── sort.h ├── sort │ ├── CMakeLists.txt │ ├── insert.cpp │ └── select.cpp ├── test1 │ ├── calc.cpp │ └── CMakeLists.txt └── test2 ├── CMakeLists.txt └── sort.cpp
-
假如目录结构如上图所示,其中
include
是头文件目录calc
对应加减乘除sort
对应两种排序test1
和test2
是计算器和排序的测试程序
-
为了让
test1
和test2
能使用计算器和排序,因此需要将calc
和sort
里的内容生成库文件,若源文件多,则生成动态库,否则生成静态库,因为生成静态库会将库文件放在输出的文件夹中 -
添加子目录
add_subdirectory(子目录名)
:add_subdirectory(calc)
-
示例
-
根目录
CMakelist.txt
:-
# 最小版本 cmake_minimum_required(VERSION 3.0) # 可执行文件名 peoject(test) # 静态库输出路径 set(LIBPATH ${CMAKE_CURRENT_SOURSE_DIR}/lib) # 头文件目录路径 set(HEADPATH ${CMAKE_CURRENT_SOURSE_DIR}/lib) # 生成库文件名称 set(CALCLIB calc) set(SORTLIB sort) # 可执行文件程序名 set(APPNAME1 app1) set(APPNAME2 app2) # 给当前目录添加子节点 add_subdirectory(calc) add_subdirectory(sort) add_subdirectory(test1) add_subdirectory(test2)
-
-
calc
目录CMakelist.txt
sort
目录下的同理-
# 最小版本 cmake_minimum_required(VERSION 3.0) # 可执行文件名 peoject(calc) # 搜索源文件 在./下搜索所有文件,放到SRC中 aux_sourse_directory(./ SRC) # 添加头文件 因为calc用到了calc.h include_directories(${HEADPATH}) # 子节点可以使用父节点的变量 # 设置库文件输出位置 LIBRARY_OUTPUT_PATH是系统定义的宏 set(LIBRARY_OUTPUT_PATH ${LIBPATH}) # 生成静态库文件 add_library(${CALCLIB} STATIC ${SRC})
-
-
test1
目录CMakelist.txt
test2
目录同理-
# 最小版本 cmake_minimum_required(VERSION 3.0) # 可执行文件名 peoject(test1) # 搜索文件 aux_sourse_directory(./ SRC) # 添加头文件 include_directories(${HEADPATH}) # 指定静态库文件地址 link_directories(${LIBPATH}) # 链接静态库 link_libraries(CALCLIB) # 设置可执行文件生成路径 EXECUTABLE_OUTPUT_PATH是系统定义的宏 set(EXECUTABLE_OUTPUT_PATH ${EXECPATH}) # 生成可执行文件 add_executable(${APPNAME1} ${SRC})
-
-
-
-
在静态库中链接静态库
- 一样使用
link_directories
和link_libraries
- 一样使用
-
find_package()
:查找依赖包
-