gcc main.c # 生成a.out
直接执行: ./a.out
gcc main.c -o main # 生成main
直接执行: ./main
不同平台(GNU make、QT的qmake、微软的MS nmake、pamke、makeapp等)makefile格式不一样,cmake无关平台。
# 写cmake文件:CMakeLists.txt
# 1、单目录单文件,main.cpp
CMAKE_MINIMUM_REQUIRED(VERSION 3.10)
project( demo1 )
add_executable( demo1 main.cpp )
# 2、单目录多文件,多了myfunc.cpp和myfunc.hpp
-方法 1
CMAKE_MINIMUM_REQUIRED(VERSION 3.10)
project( demo2 )
add_executable( demo2 main.cpp myfunc.cpp )
# 发现一个目录下所有的源代码文件并将列表存储在一个变量中
# 把当前目录下的所有源码文件名赋给变量DIR_HELLO_SRCS
AUX_SOURCE_DIRECTORY(dir VAR)
- 方法2
CMAKE_MINIMUM_REQUIRED(VERSION 3.10)
project( demo2 )
AUX_SOURCE_DIRECTORY(./ DIR_SRCS)
add_executable( demo1 ${DIR_SRCS} )
# 3、多目录多文件
tree显示当前目录结构
- CMakeLists.txt
- demo.cpp
- mylib
- CMakeLists.txt
- mymath.cpp
- mymath.hpp
- CMakeLists.txt
./mylib/CMakeLists.txt
AUX_SOURCE_DIRECTORY(./ DIR_LIB_SRCS)
add_library( Mylib ${DIR_LIB_SRCS} )
./CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.10)
project( demo3 )
add_subdirectory(./mylib) # 增加静态库
AUX_SOURCE_DIRECTORY(./ DIR_SRCS)
add_executable( demo3 ${DIR_SRCS} )
target_link_libraries(demo3 Mylib) # 链接静态库
# 4、多目录多文件标志工程
目录树
- CMakeLists.txt
- build # 最后在build文件夹编译。cmake ..
- src
- CMakeLists.txt
- demo.cpp
- mylib
- CMakeLists.txt
- mymath.cpp
- mymath.hpp
./src/CMakeLists.txt
include_directories(${PROJECT_SOURCE_DIR}/mylib)
# project_binary_dir 为cmake所在目录,build
set(executable_output_path ${project_binary_dir}/bin) # 设置生成文件的输出目录
AUX_SOURCE_DIRECTORY(./ DIR_SRCS)
add_executable( demo4 ${DIR_SRCS} )
target_link_libraries(demo4 Mylib)
./mylib/CMakeLists.txt
AUX_SOURCE_DIRECTORY(. DIR_LIB_SRCS)
set(library_output_path ${project_binary_dir}/lib) # 设置库文件的输出目录
add_library( Mylib ${DIR_LIB_SRCS} )
./CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.10)
project( demo4 )
add_subdirectory(./mylib) # 增加子目录
add_subdirectory(./src)
# 5、自定义编译选项
目录树
- CMakeLists.txt
- build # 最后在build文件夹编译。cmake ..
- config
- config.hpp.in
- src
- CMakeLists.txt
- demo.cpp
- mylib
- CMakeLists.txt
- mymath.cpp
- mymath.hpp
./config/config.hpp.in
#cmakedefine USE_MYMATH # 定义一个宏,是否使用mylib或者标准库的math
./src/CMakeLists.txt
# project_binary_dir 为cmake所在目录,build
set(executable_output_path ${project_binary_dir}/bin) # 设置生成文件的输出目录
configure_file(
"${PROJECT_SOURCE_DIR}/config/config.hpp.in" # 输入
"${PROJECT_SOURCE_DIR}/config/config.hpp" # 输出
)
option(USE_MYMATH ON) # 决定变量的值
if(USE_MYMATH)
include_directories(${PROJECT_SOURCE_DIR}/mylib)
endif(USE_MYMATH)
AUX_SOURCE_DIRECTORY(./ DIR_SRCS)
add_executable( demo5 ${DIR_SRCS} )
target_link_libraries(demo5 Mylib)
./mylib/CMakeLists.txt
AUX_SOURCE_DIRECTORY(. DIR_LIB_SRCS)
set(library_output_path ${project_binary_dir}/lib) # 设置库文件的输出目录
add_library( Mylib ${DIR_LIB_SRCS} )
./CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.10)
project( demo4 )
add_subdirectory(./mylib) # 增加子目录
add_subdirectory(./src)
./src/demp.cpp
#ifdef
#include "../mylib/mymath.hpp"
#else
#include <math.h>
#endif
ccmake 查看
# 6、VS下调试
./CMakeLists.txt
增加:
add_definitions(-std=C++11)
set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -00 -Wall -g -ggdb")
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -03 -Wall")
camke,make后。Run -> Start Debugging -> 选择环境 C++(GDB/LLDB) -> 进入 launch.json 文件
将 "configurations" 的 "program" 设置路径: ${workspaceFolder}/build/bin/demo6
# 工程内的库,CMAKE_CURRENT_SOURCE_DIR是CMakeLists.txt的目录
set( 变量名字
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/lib.cpp
)
# 工程外的库,CMAKE_SOURCE_DIR是工程根目录
include_directories(
${CMAKE_SOURCE_DIR}/目录名/目录名
)
# 查找目录,在target_link_libraries中库名要加"",查找的文件为"lib库名.a"
link_directories(
${CMAKE_SOURCE_DIR}/目录名/目录名
)
# 增加可执行文件
预处理——编译——汇编——链接
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LkASEiod-1613654054907)(https://i.loli.net/2021/02/18/uCn3xSGhbzNLAM9.png)]
每一级目录都有 CMakeLists.txt 文件。
简单样例
project( helloworld )
# 工程内的库,CMAKE_CURRENT_SOURCE_DIR是CMakeLists.txt的目录
set( 变量名字
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/lib.cpp
)
# 工程外的库,CMAKE_SOURCE_DIR是工程根目录
include_directories(
${CMAKE_SOURCE_DIR}/目录名/目录名
)
# 查找目录,在target_link_libraries中库名要加"",查找的文件为"lib库名.a"
link_directories(
${CMAKE_SOURCE_DIR}/目录名/目录名
)
# 增加可执行文件
add_executable( helloworld
$(变量名字)
)
# 动态库、静态链接库
target_link_libraries(
helloworld
库名 # 值得是子目录里面camke的project
# 动态库
库名 dynamic
)
创建库
# 静态库
project( base64 )
set( src
${CMAKE_CURRENT_SOURCE_DIR}/base64.cpp
${CMAKE_CURRENT_SOURCE_DIR}/base64.h
)
add_library( base64 STATIC
${src}
)
# 动态库
project( base64_dynamic )
ADD_DEFINITIONS( -DBASE64_SHARED )
set( src
${CMAKE_CURRENT_SOURCE_DIR}/base64.cpp
${CMAKE_CURRENT_SOURCE_DIR}/base64.h
)
add_library( base64_dynamic SHARED
${src}
)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8Zocleiw-1613654054909)(E:\personal\C++\pics\Cmake\image-20210102221305159.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hcWpNmmT-1613654054911)(E:\personal\C++\pics\Cmake\image-20210102221415947.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NbYxpN74-1613654054913)(E:\personal\C++\pics\Cmake\image-20210102221431682.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OMXuz54E-1613654054914)(E:\personal\C++\pics\Cmake\image-20210102221519268.png)]
主体框架
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U9rSkhOd-1613654054916)(E:\personal\C++\pics\Cmake\image-20210102221603883.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZusFp4Mi-1613654054916)(E:\personal\C++\pics\Cmake\image-20210102221844282.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hVZXlWeR-1613654054916)(E:\personal\C++\pics\Cmake\image-20210102221904211.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zQCsH0z7-1613654054917)(E:\personal\C++\pics\Cmake\image-20210102221928104.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7xz67MA3-1613654054917)(E:\personal\C++\pics\Cmake\image-20210102222006470.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EAfgvuiW-1613654054918)(E:\personal\C++\pics\Cmake\image-20210102223035771.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i7juKbCY-1613654054918)(E:\personal\C++\pics\Cmake\image-20210102223308206.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5w8DM11S-1613654054919)(E:\personal\C++\pics\Cmake\image-20210102223509143.png)]
静态库:链接其他文件时用
动态链接库:运行时加载
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rFFPJzqd-1613654054919)(E:\personal\C++\pics\Cmake\image-20210102223620013.png)]
cmake
CMake
中的变量
-
变量和含义
常用变量 含义 PROJECT_NAME
工程名变量 PROJECT_SOURCE_DIR
顶层的项目目录 PROJECT_BINARY_DIR
使用 cmake
的路径CMAKE_ROOT
CMAKE
安装的根目录CMAKE_BUILD_TYPE
编译类型: empty
,Debug
,Release
…CMAKE_SOURCE_DIR
顶层的 CMakeLists.txt
所在路径CMAKE_BINARY_DIR
顶层的 CMakeLists.txt
的build
所在目录CMAKE_<LANG>_COMPILER
设定某个语言 LANG
的编译器,比如g++
CMAKE_INSTALL_PREFIX
指令 install
的路径CMAKE_CURRENT_SOURCE_DIR
当前 CMakeLists.txt
所在路径CMAKE_CURRENT_BINARY_DIR
当前 CMakeLists.txt
的build
所在目录EXECUTABLE_OUTPUT_PATH
可执行文件输出路径 LIBRARY_OUTPUT_PATH
库输出路径 -
个别变量解释
源码目录结构```bash jmudou ├── build.sh ├── CMakeLists.txt └── muduo └── base ├── Atomic.h ├── CMakeLists.txt ├── copyable.h ├── tests │ ├── Atomic_unittest.cc │ ├── CMakeLists.txt │ └── Timestamp_unittest.cc ├── Timestamp.cc ├── Timestamp.h └── Types.h ``` 三个`CMakeLists.txt`输出 ```cmake jmuduo/CMakeLists.txt: PROJECT_SOURCE_DIR= 11/jmuduo PROJECT_BINARY_DIR= 11/build/debug CMAKE_SOURCE_DIR= 11/jmuduo # 指定顶层的CMakeLists.txt的,因此所有的都相同 CMAKE_BINARY_DIR= 11/build/debug # 上面四项都是与整个项目相关,因此都是一致的。 CMAKE_CURRENT_SOURCE_DIR= 11/jmuduo # 指定当前层的CMakeLists.txt的,因此与层相关 CMAKE_CURRENT_BINARY_DIR= 11/build/debug muduo/base/test/CMakeLists.txt: PROJECT_SOURCE_DIR= 11/jmuduo PROJECT_BINARY_DIR= 11/build/debug CMAKE_SOURCE_DIR= 11/jmuduo CMAKE_BINARY_DIR= 11/build/debug CMAKE_CURRENT_SOURCE_DIR= 11/jmuduo/muduo/base/tests CMAKE_CURRENT_BINARY_DIR= 11/build/debug/muduo/base/tests muduo/base/CMakeLists.txt: PROJECT_SOURCE_DIR= 11/jmuduo PROJECT_BINARY_DIR= 11/build/debug CMAKE_SOURCE_DIR= 11/jmuduo CMAKE_BINARY_DIR= 11/build/debug CMAKE_CURRENT_SOURCE_DIR= 11/jmuduo/muduo/base CMAKE_CURRENT_BINARY_DIR= 11/build/debug/muduo/base ```
函数
所有的函数列表中,<>
表示的参数必须要有,[]
表示的参数为可选。
-
set
可以设置三个类型的变量值:正常变量,cache variable
、环境变量。Normal Variable
:set(<variable> <value>... [PARENT_SCOPE])
cache
:set(<variable> <value>... CACHE <type> <docstring> [FORCE])
env
:set(ENV{<variable>} [<value>])
-
***
OPTION
***:提供用户可以选择的选项-
格式:
option(<variable> "description" [initial value])
-
比如:
option( USE_MYPATH "user path" ON )
-
-
aux_source_directory
- 语法:
aux_source_directory(<dir> <variable>)
- 查找目录
dir
下的所有源文件(即.c, .cpp, .cc等文件),并将名称保存到variable
变量
- 语法:
-
add_subdirectory
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
- 添加一个将被编译的子目录。指明
CMakeLists.txt
所在目录下包含了一个子目录source_dir
。这样source_dir
下的源文件和CMakeLists.txt
等也会被处理。
-
target_link_libraries
target_link_libraries(exec libs)
- 表示可执行程序
exec
需要链接到一个名为libs
的链接库。
-
add_library
add_library (name dir)
- 用在目录
dir
下的源文件生成一个名为name
的静态链接库:libname.a
-
configure_file
-
加入一个配置头文件,用于处理 CMake 对源码的设置
configure_file ( "${PROJECT_SOURCE_DIR}/config.h.in" # config.h.in文件目录 "${PROJECT_BINARY_DIR}/config.h" # config.h 生成的头文件目录 )
在配置文件
config.h
中,配置相关项,比如options
中的USE_MYPATH
:#cmakedefine USE_MYMATH
-
-
include
include(file [optional])
:读取CMake
的相关文件。include(moudle [optional])
the file with name .cmake is searched in theCMAKE_MODULE_PATH
。
-
include_directories
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])
添加指定目录到编译器搜索路径。
-
install
使用:cmake
之后,sudo make install
就可以执行相应的库和头文件的安装。-
TARGET
格式install(TARGETS targets... [[ARCHIVE|LIBRARY|RUNTIME] [DESTINATION <dir>] [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] [OPTIONAL] ] [...])
-
targets
的类型
可以安装的库有[ARCHIVE|LIBRARY|RUNTIME]
三种:
1) 可执行程序视为runtime
2) 静态库视为archieve
3)Module Library
视为library
4) 共享库和平台有关 -
参数
-
DESTINATION
:
指定一个文件将要被安装的目录。如果给的是一个全路径,那么就直接使用;如果是相对路径,默认是相对CMAKE_INSTALL_PREFIX
,其值默认是/usr/local/
。
1) 头文件:inclide
2) 可执行文件:bin
3) 库:lib
-
PERMISSIONS
: 指定安装文件的权限:
1) user :OWNER_READ, OWNER_WRITE, OWNER_EXECUTE
2) group:GROUP_READ, GROUP_WRITE, GROUP_EXECUTE
3) other:WORLD_READ, WORLD_WRITE, WORLD_EXECUTE
4) uid :SETUID, and SETGID
。 -
CONFIGURATIONS
:为安装规则建立一个配置文件列表。
-
-
-
install
-
FILES
格式INSTALL(FILES files... DESTINATION <dir> [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] [RENAME <name>] [OPTIONAL])
files
:即文件名
-
-
测试
-
***
enanle_testing()
***:启动测试 -
***
add_test(testname Exename arg1 arg2 ...)
***:- 需要先运行测试程序
enanle_testing()
,这个指令才有效。 Exename
是可执行程序名,参数arg1, arg2
。
- 需要先运行测试程序
-
set_tests_properties(...)
- 括号内格式:
(Exename [Exename2...] PROPERTIES prop1 value1 prop2 value2)
,其中PROPERTIES
是固定的单词不能改 - 为
Exename
设置属性,如果没有这个属性,就报错,有如下属性:
1)WILL_FAIL
:如果设置为true
,那么会反转测试结果的pass/fail
标志。
2)PASS_REGULAR_EXPRESSION
: 匹配正则表达式,只少有一个匹配,则pass
2)FAIL_REGULAR_EXPRESSION
: 匹配正则表达式,则fail
- 括号内格式:
-
宏测试
macro(<name> [arg1 [arg2 [arg3 ...]]]) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... endmacro(<name>)
就类似于写一个函数,用宏实现,调用:
name(arg1,arg2,...)
。
-
-
设置项目的版本号
-
在顶层的
CMakeLists.txt
中:# 加入版本号是 1.0 set (Project_VERSION_MAJOR 1) # 主版本号 set (Project_VERSION_MINOR 0) # 副版本号
-
在配置文件
config.h.in
中设置:#define Project_VERSION_MAJOR @Project_VERSION_MAJOR@ #define Project_VERSION_MINOR @Project_VERSION_MINOR@
-
main
函数中就可以直接使用这两个宏,代表版本号:printf("Version %d.%d\n", Project_VERSION_MAJOR, Project_VERSION_MINOR);
-
-
生成安装包
需要利用CPack
工具,也是CMake
提供的工具。+ 先在顶层`CMakeLists.txt`中末尾添加: ```cmake # 构建一个 CPack 安装包 include(InstallRequiredSystemLibraries) set (CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt") set (CPACK_PACKAGE_VERSION_MAJOR "${Project_VERSION_MAJOR}") set (CPACK_PACKAGE_VERSION_MINOR "${Project_VERSION_MINOR}") include (CPack) ``` + 导入`InstallRequiredSystemLibraries`模块,以便之后导入`CPack`模块 + 设置一些`CPack`相关变量,包括版权信息和版本信息,其中版本信息用了上一节定义的版本号 + 导入`CPack`模块 + 生成二进制安装包:`cpack -C CPackConfig.cmake` + or 生成源码安装包 + 格式:`cpack -C CPackSourceConfig.cmake` 在执行该命令的目录下得到: ```bash # Demo8是项目名 $ ls -l | grep Demo8 -rwxrwxrwx 1 szz szz 8631 Dec 12 22:03 Demo8-1.0.1-Linux.sh -rw-rw-r-- 1 szz szz 3709 Dec 12 22:03 Demo8-1.0.1-Linux.tar.gz -rw-rw-r-- 1 szz szz 4982 Dec 12 22:03 Demo8-1.0.1-Linux.tar.Z ```` + 安装:`sh Demo8-1.0.1-Linux.sh`。 默认的安装路径: ```c By default the Demo8 will be installed in: "~/Study/SystemProgram/CMakeExe/Demo8/build/Demo8-1.0.1-Linux" Do you want to include the subdirectory Demo8-1.0.1-Linux? Saying no will install in: "~/Study/SystemProgram/CMakeExe/Demo8/build" [Yn]: ``` + 运行。安装后,就运行该程序 ```bash $ ./Demo8-1.0.1-Linux/bin/Demo 2 5 Now we use our own Math library. 2 ^ 5 is 32 ``` + Demo8-1.0.1-Linux下的目录结果 ```bash Demo8-1.0.1-Linux ├── bin │ └── Demo # 可执行程序 ├── include # 头文件 │ ├── config.h │ └── MathFunctions.h └── lib # 静态库 └── libMathFunctions.a ```
-
target_compile_definitions
-
格式
target_compile_definitions(<target> <INTERFACE|PUBLIC|PRIVATE> [items1...] [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
-
作用:编译时定义的宏
-
-
string
-
REPLACE
string(REPLACE <match_string> <replace_string> <output_variable> <input> [<input>...])
将所有
input
中出现的match_String
替换为replace_string
,并且将结果存在output_variable
。
-
-
message
message([<mode>] "message to display" ...)
-
显示信息给用户
mode
取决于信息的类型:-
STATUS
:以简洁的方式显示用户感兴趣的信息。message(STATUS "CXX_FLAGS = " ${CMAKE_CXX_FLAGS} " " ${CMAKE_CXX_FLAGS_${BUILD_TYPE}} )
可以理解为
printf
,把后面的几个信息以空格相间,然后打印出来。显示结果为(和上面对应分成三段):CXX_FLAGS = -g -D_FILE_OFFSET_BITS=64 -Wall -Wextra -Werror -Wconversion -Wno-unused-parameter -Wold-style-cast -Woverloaded-virtual -Wpointer-arith -Wshadow -Wwrite-strings -march=native -rdynamic -O0
-
-
-
find_package
find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE] [REQUIRED] [[COMPONENTS] [components...]] [OPTIONAL_COMPONENTS components...] [NO_POLICY_SCOPE])
主要是寻找和加载外部项目。如果
PackageName
找到了,PackageName-found
会显出,当没有找到时,默认显示
PackageName-not found
。通过模式的选择,可以处理在没有找到包时的解决方案。QUIET
:不显示有用信息,REQUIRED
:报错
-
find_path
find_path (<VAR> name0|NAMES name1 [path1 path2 ...])
用以寻找包含着
name1
文件的目录,如果找到了结果存储在VAR
,没有找到结果结果是VAR-not found
。成功时,变量被清除find_path
再次搜索,没有成功,fin_path
再次以相同的变量被调用时搜索。 -
find_library
同上find_path
find_library (<VAR> name0|NAMES name1 [path1 path2 ...])
- OPTIONS
NAMES
为library
指定一个或多个可能的名字。
- OPTIONS