什么时候用?
当一个团队使用不同的语言或者编译器开发一个项目,最重要输出一个可执行文件或者共享库(dll,so等),这个时候就需要使用CMake了。所有的操作都是通过编译CMakeLists.txt来完成的。CMake的目的,是为了编译大型的C/C++/JAVA项目。
CMake一个HelloWorld
HelloWorld.cpp:
#include<iostream>
using namespace std;
int main(){
cout << "Hello world" << endl;
}
可以写如下CMakeList.txt:
# 指定工程的名字和支持的语言
# 会隐式地定义两个CMake变量
# <projectname>_BINARY_DIR
# <projectname>_SOURCE_DIR
# 所以后面message中使用的变量前缀必须和project指定的工程名相同
# 如果改了工程名字,后面的两个变量也会改变
# 所以有PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR来代替这两个变量
project(HELLO)
# 赋值
set(SRC_LIST HelloWorld.cpp)
# 向终端输出用户自定义的信息
# 主要包含三种信息:
# SEND_ERROR,产生错误,生成过程被跳过
# SATUS,输出前缀为‘-’的信息
# FATAL_ERROR,立即终止所有的cmake过程
message(STATUS "this is binary dir" ${HELLO_BINARY_DIR})
message(STATUS "this is source dir" ${HELLO_SOURCE_DIR})
# 从变量SRC_LIST中生成可执行文件hello
add_executable(hello ${SRC_LIST})
# 工程名和可执行文件名没有关联
使用:
// 表示就在当前目录cmake
// 会生成一写和CMake相关的文件以及一个Makefile
cmake .
// 用生成的Makefile进行make编译
make
一些CMake的语法
- 取值:${var},但是在IF控制语句中,可以直接使用变量名
- 指令:参数使用圆括号括起来,参数之间可以用空格或者分号分开
- 指令大小写不区分,变量区分大小写
内部构建、外部构建
内部构建:产生较多的临时文件
外部构建:把生成的临时文件放到build目录下,不会对源文件有任何影响
外部构建方法:
# 创建build文件夹,并进入
mkdir build
cd build
# .. 表示CMakeList.txt在上一层,这样生成的临时文件都在build中
cmake ..
工程构建
如何让这个HelloWorld看起来像一个工程呢?
- 添加src目录,用来放置工程源代码
- 添加doc目录,用于存放工程相关文档
- 将构建后的二进制文件放在bin中
- 添加版权©️COPYRIGHT,说明README
- 添加shell脚本,用来运行工程
所以,可以这么构建CMakeList.txt:
project(HELLO)
set(SRC_LIST src/HelloWorld.cpp)
message(STATUS "this is binary dir" ${HELLO_BINARY_DIR})
message(STATUS "this is source dir" ${HELLO_SOURCE_DIR})
add_executable(hello ${SRC_LIST})
# 指定生成的二进制放到bin中
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
# 生成的库文件放到lib目录中
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
构建静态库和动态库
静态库和动态库的区别:
- 静态库的拓展名一般为“.a”或“.lib”;动态库的拓展名一般为“.so”或“.dll”
- 静态库在编译时会直接整合到目标程序中,编译陈成功的可执行文件可独立运行
- 动态库在编译时不会放到链接的目标程序中,即可执行文件不可单独运行
那么在CMakeList.txt中可以这么生成库文件:
# 这个hello时你想要生成的库文件的名字,系统会自动在它前面加一个lib,变成libhello
# SHARED表示生成动态库(共享库)
# STATIC表示生成静态库
# lib/hello.cpp表示想要把哪个文件变成库文件
add_library(hello SHARED lib/hello.cpp)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
库连接
前面构建的动态库,静态库,可以用于后续的文件中。完成这些操作,需要在CMakeList.txt中声明:
# 要生成test这个可执行文件,要先生成sylar这个库,建立依赖,连接起来,这样才能生成
add_dependencies(test sylar)
target_link_libraries(test sylar)