CMake 基础概述
-
源代码是怎么变成可执行程序的
通过编译器处理(一系列工具链),分为四部分:预处理器,编译(gcc或g++),汇编,链接(连接器)最后得到一个二进制文件,写
makefile
(跨平台性不好),在使用make
进行批处理,当然还有一种处理方式是CMake
,创建一个脚本文件CMakeLists.txt
,再执行CMake
指令 -
CMake
项目准备工作单个注释:
# 此为单个注释 #[[ 这个为注释块 ]] # 这个是使用的 cmake 最低版本,当然也可以指定不写的 cmake_minimum_required(VERSION 3.0) # 当然,可以指定多个参数 [项目名称] [项目版本] [项目描述] [web 主页地址] [支持的语言] project([] [] [] [] []) # 定义工程生成一个可执行程序 # [可执行程序] [源文件名称],可以使用空格和分号进行分隔 add_executable([] [])
使用
cmake ..
命令执行CMakweLists.txt
,使用make
执行makefile
-
我们不可能把所有的
cpp
文件都写进去set
的使用,set
相当于定义一个变量set(app ${SRC}) # 指定程序输出路径 set(EXECUTABLE_OUTPUT_PATH /home/hoe/hoe-cpp/cmakeStudy/source/build) # 指定 C++ 使用标准 set(CMAKE_CXX_STANTARD 11)
如果需要输出库的路径,则把第一个参数改为
LIBRARY_OUTPUT_PATH
,其他的不用变化在外部设置宏
cmake .. -DCMAKE_CXX_STANDARD = 11
-
上面的代码并没有解决本质的问题
使用
aux_source_directory()
,会把搜索的所有文件放在第二个参数里面,第一个参数为搜索的路径常用宏:
PROJECT_SOURCE_DIR
,CMAKE_CURRENT_SOURCE_DIR
aux_source_directory(${PROJECT_SOURCE_DIR} SRC)
使用
file
命令,第一个参数指定搜索方式,如:GLOB/GLOB_RECURSE
,此方式为递归搜索,第二个参数用来存放搜索出来的值,第三个参数用来搜索文件路径和文件类型CMAKE_CURRENT_SOURCE_DIR
,file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
-
指定头文件
当我们创建的项目分为头文件和
cpp
文件的时候,那么会寻找不到当前的头文件,使用include_directories
可以追寻到头文件,如:include_directories(headPath)
-
制作一个库
add_library([制作库的名字] [指定库的类型:静态库static,动态库:shared] [源文件1] [源文件2] ...)
注意:动态库是有执行权限的,静态库没有执行权限;发布给使用者需要
.a(静态库)
和头文件指定库的路径:
LIBRARY_OUTPUT_PATH
->适用于动态库和静态库,EXCUTABLE_OUTPUT_PATH
->适用于动态库,适用方法还是set
-
指定库位置
link_libraries([静态库] [静态库])
通过这个命令可以链接一个或多个,一般为掐头去尾,如
libxxx.a
,去掉头和去掉尾后是xxx
如果是系统提供的,那么只需要提供名字就行,如果是自定义的,需要指定路径,如下:
link_directories([库路径] [库路径])
当然指定路径也可以指定多个路径,相当于添加环境变量
注意:如果使用的静态库,那么静态库会打包到可执行文件里面去,如果是动态库,并不会打包到可执行文件里面,如果出现
undefine_...
字样,那么需要检查link_directories
是否有写正确容易出现的错误:
1). 库函数于头文件函数不在一个文件夹内(由于库文件引用的头文件造成)
-
链接动态库
target_link_libraries([目标] [库] [库])
目标可能是一个动态库,也可以是静态库,也可能是一个源文件,也可能是可执行文件,但是要注意,使用此关键字需要写在已经生成的文件下或者写在已经存在/生成的可执行文件下
默认权限是
public
,且一般写在最后,要保证目标已经存在问题:使用动态库会不会造成混乱?多个进程使用同一个动态库。
每一个进程有一个虚拟地址空间,有一个区域叫做动态加载区,当被加载进来过后,会被映射到对应的虚拟地址空间中,一般是在虚拟地址空间进行操作,而 CPU 里面有一个 MMU,MMU 会把虚拟地址中的数据映射到物理地址上去,每一个进程都对应有一块不同的地址动态库里面的操作函数只有一套,通过这个函数计算出的结果是在不同的物理地址上进程存储,所以说最终的数据是不会错乱的
-
消息输出
message([重要级别] [消息])
如果什么都不写,那么说明很重要
STATUS
: 非重要消息WARNING
:CMake
警告,会继续执行AUTHOR_WARNING
:CMake
警告,会继续执行SEND_ERROR
:CMake
错误,继续执行,但是会跳过生成的步骤FATAL_ERROR
:CMake
错误,终止所有处理过程 -
字符串的拼接和追加
-
使用 set,把第二个开始的值拼接到第一个上,但是第一个值会被覆盖
set(str1 str2 str3)
-
使用 list, 是一个列表(是一个变量,里面是字符串), 追加的子字符串,底层上是通过分号进行拼接
list(APPEND <list> [element] ...)
-
删除字符串,删除指定的文件,其中 SRC 为原字符串,第三个参数为要删除的字符串
list(REMOVE_ITEM SRC ${PROJECT_SOURCE_DIR}/src/main.cpp)
-
其他参数,如[LENGTH]为长度(会写入第三个参数中),[GET]获取对应的元素
list(GET <list> <element index> [<element index> ...])
-
将列表里面的元素连接成一个字符串,第三个参数是连接符,最后一个参数是新生成的字符串
list(JOIN <list> <value> <output variable>)
-
查找列表中的某一个元素,如果没有找到,那么最后一个值是 -1
list(FIND <list> <value> <output variable>)
-
向列表中插入元素
list(INSERT <list> <element_index> <element> [<element> ...])
-
将元素插入到列表的前面
list(PREPEND <list> [<element> ...])
-
将列表的最后一个元素删除, 为弹出的值
list(POP_BACK <list> [<out-var> ...])
-
将列表中第一个元素移除
list(POP_FRONT <list> [<out-var> ...])
-
将指定索引的元素从列表中移除(注意:不能超出索引的指定范围)
list(REMOVE_AT <list> <index> [<value> ...])
-
移除列表中的重复元素
list(REMOVE_DUPLICATES <list>)
-
列表的翻转(倒序)
list(REVERS <list>)
-
列表排序
list(SORT <list> [COMPARE <compare>] [CASE <case>] [ORDER <order>])
COMPARE: 指定排序方法,如下几种可选 STRING: 按照字母顺序进行排序,默认排序方法 FILE_BASENAME: 如果是一系列路径名,会使用 basename 进行排序 NATURE: 使用自然数顺序排序 CASE:指明是否大小写敏感 SENSITIVE:按照大小写敏感的方式进行排序,为默认值 INSENSITIVE:按照大小写不敏感方式进行排序 ORDER:指明排序的顺序 ASCENDING:按照升序排列,为默认值 DESCENDING:按照降序排列
-
-
宏定义
add_definitions(-D[宏名字])
-
嵌套
CMake
在父文件里面的变量可以被子文件中使用,但是反向不行
# 第一个参数一般指向了子节点的 CMakeLists.txt 文件 add_subdirectory([source_dir [binary_dir] [EXCLUDE_FROM_ALL])
source_dir
: 指定子目录里面的CMakeLists.txt
文件中的源文件和代码文件位置binary_dir
: 制定了输出文件的路径,一般不需要指定,忽略即可EXCLUDE_FROM_ALL
: 在子路径下的目标默认不会被包含到父路径的ALL
目标中,并且也会被排除在IDE
工程文件之外,用户必须显示构建在子目录下的目标
库生成思路:如果源文件比较多,生成动态库,如果源文件比较少,那么生成静态库,当然,在链接库的时候还是要注意库文件生成的
位置
,还有使用库文件的头文件以及使用cmake
中引用的路径
其他
Linux 指令的使用:
# 此命令为拷贝整个文件夹
cp file1 file2 -r
# 使用 gcc 定义一个宏
gcc test.c DEBUG -G app
库文件生成
在 Windows
平台上 MinGW
环境下,生成的动态库是 .dll
结尾的格式,.a
结尾的为静态库,但是如果使用微软环境下(MSVC
环境),生成格式的静态库为 .lib
结尾的格式,其中间还会生成 .pdb
格式文件
注意
- 在
windows
平台下链接动态库的时候,需要手动放到可执行文件目录下,也可以把当前库放在环境变量中