前言:
- CMake是一个跨平台的安装编译工具,可以用简单的语句来描述所有平台的安装(编译过程)
- CMake可以说已经成为大部分C++开源项目标配
6.1 Cross-platfoem development
让我们假设您有一个跨平台的项目,在不同的平台/ ide上共享c++代码。假设你在Windows上使用visual studio,在OSX上使用Xcode,在Linux上使用Makefile:
What you will do if you want to add new bar.cpp source file? You have to add it to every tool you use:
为了保持环境一致,您必须多次进行类似的更新。最重要的是您必须手动完成(在这种情况下,图中用红色标记的箭头)。当然,这种方法容易出错且不灵活。
CMake 通过在开发过程中增加额外的步骤来解决这个设计缺陷。您可以在 CMakeLists.txt 文件中描述您的项目,并使用 CMake 生成您当前感兴趣的工具,使用跨平台 CMake 代码:
Same action - adding new bar.cpp file, will be done in one step now:
Note that the bottom part of the diagram was not changed. I.e. you still can keep using your favorite tools like Visual Studio/msbuild, Xcode/xcodebuild and Makefile/make!
6.2 语法特性
- 基本语法格式:指令(参数1 参数2…)
- 参数使用括弧括起
- 参数之间使用空格或分号分开
- 指令时大小写无关的,参数和变量是大小写相关的
set(HELLO hello.cpp) add_executable(hello main.cpp hello.cpp) ADD_EXECUTABLE(hello main.cpp ${HELLO})
- 变量使用${}的方式取值,但是在IF控制语句中是直接使用变量名
if(HELLO)而不是 if($(HELLO))
6.3 重要的指令和CMake常用变量
6.3.1 重要指令
- cmake_minimum_required -指定CMake的最小版本要求
- 语法:cmake_minimum_required(VERSION versionNumber [FATAL_ERROR])
#CMake 最小版本要求位2.8.3
cmake_minimum_required(VERSION 2.8.3) - project定义工程名称,并指定工程支持的语言
- 语法:project(projectname [CXX][C] [Java]). 中括号里的代表[可选项]
#指定工程名为HELLOWORLD
project(HELLOWORLD) - set -显式的定义变量
- 语法:set(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
#定义SRC变量,其值为sayhello.cpp hello.cpp
s#### et(SRC sayhello.cpp hello.cpp)
- include_directories -向工程添加多个特定的头文件搜索路径—>相当于指定g++编译器的**-I**参数
- 语法:include_directories([AFTER|BEFORE] [SYSTEM] dir1 dir2…)
#将/usr/include/myincludefolder和./include 添加到头文件搜索路径
include_directories(/usr/include/myincludefolder ./include)绝对路径 相对路径
- link_directories-向工程添加多个特定的库文件搜索路径—>相当于指定g++编译器的**-L**参数
- 语法:link_directories(dir1 dir2 …)
#将/usr/lib/mylibfolder和./lib 添加到头文件搜索路径
link_directories(/usr/lib/mylibfolder ./lib)
- add_library-生成库文件
- 语法:add_library(libname [SHARED|STATIC|MODULE] [EXCLUDE_FORM_ALL] source1 source2 … sourceN)
#通过变量SRC生成libhello.so文件共享库
add_library(hello SHARED ${SRC})
- add_compile_options-添加编译参数
- 语法:add_compile_options( …)
#添加编译参数 -Wall -std=c++11
add_compile_options(-Wall -std=c++11 -o2)
- add_executable-生成可执行文件
- 语法: add_executable(exename source1 source2 … sourceN)
#编译main.cpp生成可执行文件main
add_executable(main main.cpp)
- target_link_libraries-为target添加需要链接的共享库–>相当于指定g++编译器**-l参数**
- 语法:target_link_libraries(target library1
library2 …)
- 语法:target_link_libraries(target library1
#将hello动态库文件链接到可执行文件mian
target_link_libraries(main hello)
- add_subdirectory-向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制存放的位置
- 语法:add_subdirectory(source_dir [binary_dir] [EXCLUDE_FRO M_ALL])
#添加src子目录,src中需有一个CMakeLists.txt
add_subdirectory(src)
- aux_source_directory-发现一个目录下所有的源代码文件并将列表存储在一个变量中,这个指令临时被使用来自动构建源文件列表
- 语法:aux_source_directory(dir VARIABLE)
#定义SRC变量,其值为当前目录下随哦有的源代码文件
aux_source_director y(. SRC)#编译SRC变量所代表的源代码文件,生成main可执行文件
add_executable(main ${SRC})
6.3.2 CMake常用变量
- CMAKE_C_FLAGS gcc编译选项
- CMAKE_CXX_FLAGS g++编译选项
#在CMAKE_CXX_FLAGS 编译选项后追加-std=c++11
set( CMAKE_CXX_FLAGS “${CMAKE_CXX_FLAGS } -std=c++11”
- CMAKE_BUILD_TYPE编译类型(Debug,Release)
#设定编译类型为debug,调试时需要选择debug
set(CMAKE_BUILD_TYPE Debug)#设定编译类型为release,发布时需要选择release
set(CMAKE_BUILD_TYPE Release)
- CMAKE_BINARY_DIR
- PROJECT_BINARY_DIR
- _BINARY_DIR
1、这三个变量指代的内容是一致的
2、如果是in source build,指的就是工程顶层目录;
3、如果是out-of-source编译,指的就是工程编译发生的目录;
4、PROJECT_BINARY_DIR跟其他指令稍有区别,不过现在,你可以理解为他们是一致的。
- CMAKE_SOURCE_DIR
PROJECT_SOURCE_DIR
_SOURCE_DIR
1、这三个变量指代的内容是一致的,不论采用何种编译方式,都是工程顶层目录;
2、也就是在 in source build时,他跟CMAKE_BINARY_DIR等变量一致;
3、PROJECT_SOURCE_DIR跟其他指令稍有区别,现在可以线理解为一致的。
- CMAKE_C_COMPILER:指定C编译器
- CMAKE_CXX_COMPILER:指定C++编译器
- EXECUTABLE_OUTPUT_PATH:可执行文件输出的存放路径
- LIBRARY_OUTPUT_PATH:库文件输出的存放路径
6.4 CMake编译工程
CMake目录结构:项目主目录存在一个CMakeLists.txt文件
两种方式设置编译规则:
1、包含源文件的子文件夹包含CMakeLists.txt文件,主目录的CMakeLists.txt通过add_subdirectory添加子目录即可;
2、包含源文件的子文件夹包含CMakeLists.txt文件,子目录编译规则体现在主目录的CMake.txt中;
6.4.1编译流程
在Linux平台下使用CMake构建C/C++工程的流程如下:
- 1、手动编写CmakeLists.txt
- 2、执行命令cmake PATH生成Makefile(PATH是顶层CMakeLists.txt所在的目录)。
- 3、执行命令make进行编译。
#important tips
. #表示当前目录 ./ #表示当前目录 … #表示上级目录 …/ #表示上级目录
6.4.2 两种构建方式
- 内部构建(in-source build):不推荐使用
内部构建会在同级目录下产生一大堆中间文件,这些中间文件并不是最终需要的,和工程源文件放在一起会显得杂乱无章。
##内部构建
cmake .
#在当前目录下,编译本目录的CMakeLists.txt,生成Makefile和其他文件#执行make命令,生成target
make
- 外部构建(out-of-source build):推荐使用
将编译文件输出文件与源文件放到不同目录中
##外部构建
mkdir build
#1、在当前目录下,创建build文件夹#2、进入带build文件夹
cd build#3、编译上级目录的CMakeLists.txt,生成Makefile和其他文件
cmake …#4、执行make命令,生成target
make
6.5【实战】CMake代码时间
针对第五讲写的两个小项目来写对应的CMakeLists.txt
6.5.1最小CMake工程
6.5.2多目录工程-直接编译#set the mimimum version of CMake that can be used
camke_mimimum_required(VERSION 3.0)#set the project name
project(HELLO)#add an executable
add_executable(hello_cmake main.cpp)
#set the mimimum version of CMake that can be used
cmake_minimum_required(VERSION 3.0)#set the project name
project(SWAP)#head file path
include_directories(include)#add an executable
add_executable(main_cmake main.cpp src/swap.cpp)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)