文章目录
2022-06-02,今天开始研究cmake。不间断更新。
一、说明
0.官方文档网址:www.cmake.org
1.cmake的定义:高级编译配置工具
当多个人用不同的语言或者编译器开发一个项目,最终要输出一个可执行文件或者共享库(dll、so),这时候就出现了神器CMake! 所有的操作都是通过编译CMakeLists.txt来完成的。
学习CMake的目的,是为将来处理大型的C/C++/JAVA项目做准备。
2.安装
sudo apt-get install cmake
二、使用步骤
1.构建CMakeLists.txt
CMake 构建脚本是一个纯文本文件,您必须将其命名为 CMakeLists.txt
,并在其中包含 CMake 构建您的 C/C++ 库时需要使用的命令。如果您的原生源代码文件还没有 CMake 构建脚本,您需要自行创建一个,并在其中包含适当的 CMake 命令。
2.在包含CMakeLists.txt
的目录下使用cmake
cmake 放置CMakeList.txt路径
1)构建放在当前目录下(内部构建):cmake .
即在当前目录cmake,在当前目录build。
2)在当前目录下创建build文件夹存放构建文件(外部构建),build内输入cmake ..
。即在上级目录cmake,在该目录下build。
结果:生成4个东西:CMakeFiles文件夹、cmake_install.cmake、CMakeCache.txt、Makefile
只要产生Makefile文件,就说明cmake成功了
3.在包含Makefile
的目录下使用make
直接在build出4个东西的目录下(命令针对的是Makefile)输入make
make
4.生成可执行文件。 输入./文件名
运行
举例1:
1)先编写main.cpp
#include <iostream>
using namespace std;
int main(){
cout<<"hello,world"<<endl;
return 0;
}
2)编写CMakeLists.txt
PROJECT(HELLO) #工程名为HEELO
SET(SRC_LIST main.cpp) #变量SRC_LIST包含main.cpp
MESSAGE(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir " ${HELLO_SOURCE_DIR})
ADD_EXECUTABLE(hello ${SRC_LIST}) #生成可执行程序文件名为hello,源文件读取变量SRC_LIST中内容
3)cmake
cmake .
生成了4个东西:CMakeFiles文件夹、cmake_install.cmake、CMakeCache.txt、Makefile
4)make
make
生成了可执行文件hello
5)执行
./hello
显示"hello,world"
三、如何编写CMakeLists.txt,语法详解
PROJECT关键字 ※
可以用来指定工程的名字和支持的语言,默认支持所有语言
PROJECT(HELLO) 指定了工程的名字为HELLO,且支持所有语言(建议这样做)
PROJECT(HELLO CXX)指定了工程的名字为HELLO,仅支持C++语言
PROJECT(HELLO C CXX)指定了工程的名字为HELLO,仅支持C和C++语言
该指定隐式地定义了两个CMake变了
<projectname>_BINARY_DIR
<projectname>_SOURCE_DIR
本例中是HELLO_BINARY_DIR、HELLO_SOURCE_DIR
MESSAGE关键字就可以直接使用这两个变量。当前都指向当前的工作目录
SET关键字
SET用来显式的指定变量,可以为多个
SET(SRC_LIST main.cpp) 意为SRC_LIST变量包含了main.cpp
SET(SRC_LIST main.cpp test1.cpp test2.cpp) 意为SRC_LIST变量包含了main.cpp、test1.cpp、test2.cpp
MESSAGE关键字
向终端输出用户自定义的信息,主要包含三种:
- SEND_ERROR:产生错误,生成过程被跳过
- STATUS:输出前缀为- -的信息
- FATAL_ERROR:立即终止所有cmake过程
ADD_EXECUTABLE关键字 ※
生成可执行文件
ADD_EXECUTABLE(hello $(SRC_LIST)),生成的可执行文件名为hello,源文件读取变量SRC_LIST中的内容
也可直接写为 ADD_EXECUTABLE(hello main.cpp)
注意:工程名的HELLO和生成的可执行文件hello是没有任何关系的
所以,上例中的5行CMakeLists.txt可以简化为2行:
PROJECT(HELLO)
ADD_EXECUTABLE(hello main.cpp)
ADD_SUBDIRECTORY关键字
①有子目录时,要用ADD_SUBDIRECTORY关键字包含所有需要访问的子文件夹。除了工程目录外,每个被访问的子目录里也都需要有一个CMakeLists.txt说明
②将目标文件放入构建目录的bin子目录:ADD_SUBDIRECTOR(子目录名 bin)
:自动在子目录下新建一个名为bin的子目录,存放中间二进制文件、目标二进制文件、库文件。
注意:文件就是file。目录(文件夹)就是directory。
语法基本原则
1.变量取值 ${ }
2.分隔多个文件:空格或者分号
3.大小写:指令大小写不敏感,参数和变量对大小写敏感
四、内部构建与外部构建
内部构建:例1就是内部构建,产生的临时文件和源文件堆在一起,不方便清理。BINARY DIR和SOURCE DIR在同一个目录下。
外部构建:把生成的临时文件放在build目录下,方便清理(直接删除build整个文件夹)。BINARY DIR在build目录下,SOURCE DIR在CMakeLists.txt目录下(一般CMakeLists.txt是在build的上级目录,这样可以直接cmake …,然后make)。将build放在CMakeLists.txt同级目录下。推荐使用外部构建。
五、让Hello,World看起来更像一个工程
- 为工程添加一个
子目录src
,用来放置工程源代码 - 为工程添加一个
子目录doc
,用来放置工程的文档hello.txt - 为工程添加文本文件
使用文档README
,版权COPYRIGHT
- 在工程目录中添加一个
runhello.sh
脚本,用来调用hello二进制 - 为工程添加一个
子目录bin
,用来放置生成的目标文件
举例2:
1)在工程目录下,先编写main.cpp。创建src子目录,将main.cpp放入其中
#include <iostream>
using namespace std;
int main(){
cout<<"hello,world"<<endl;
return 0;
}
2)在工程目录下编写CMakeLists.txt,包含子目录版本
PROJECT(HELLO ) #工程名为HEELO
ADD_SUBDIRECTORY(src bin) #源文件包含子目录src,目标文件放在构建文件的bin目录下
3)在源文件目录src下编写子目录的CMakeLists.txt
ADD_EXECUTABLE(hello main.cpp)
4)在工程目录下构建子目录build,并在build中进行cmake。出现Makefile后再进行make
mkdir build
cd build
cmake .. #出现5个东西:bin CMakeCache.txt CMakeFiles cmake_install.cmake Makefile
make #bin目录中出现了可执行文件hello
只进行到mkdir build时,对工程目录进行tree。效果(目录结构)应该是这样的:
.
├── build
├── CMakeLists.txt
└── src
├── CMakeLists.txt
└── main.cpp
六、安装:INSTALL
(一) 安装文件
INSTALL(FILES 文件名 DESTINATION 目标地址)
举例3:
工程目录下的CMakeLists.txt添加一行:
INSTALL(FILES COPYRIGHT README DESTINATION share/doc/cmake) #会自动安装到/usr/local/share/doc/cmake下
DESTINATION后面:
1.写绝对路径
2.相对路径:
CMAKE_INSTALL_PREFIX 默认是在/usr/local/
若想要更改,可以手动设置
set(CMAKE_INSTALL_PREFIX "目标路径")
这时候再 DESTINATION ${CMAKE_INSTALL_PREFIX}
,就导出到目标路径上了。
(二)安装脚本
PROGRAMS:非目标文件的可执行程序安装(比如脚本之类)
INSTALL(PROGRAMS runhello.sh DESTINATION bin) #实际安装到/usr/bin
(三)安装目录
安装doc中的hello.txt
方法一:通过在doc目录中建立CMakeLists.txt,通过install下的file
方法二:直接在工程目录中写入
INSTALL(DIRECTORY doc/ DESTINATION share/doc/cmake)
(四)可执行文件安装
在src的CMakeLists.txt里输入
INSTALL(TARGETS hello DESTINATION bin)
(五)执行
cd build
cmake ..
make
make install
七、生成静态库和动态库
SET(变量 源文件名)
ADD_LIBRARY(库名 STATIC或SHARED ${变量})
(一)构建动态库(命令用SHARED) (构建静态库,命令用STATIC)
举例4:
SET(LIBHELLO_SRC hello.cpp)
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC}) #生成动态库libhello.so
1)构建目录树
.
├── build
├── CMakeLists.txt
└── src
├── CMakeLists.txt
├── hello.cpp
└── hello.h
2 directories, 4 files
2)编写CMakeLists.txt
①工程目录CMakeLists.txt内容为:
cmake_minimum_required(VERSION 3.13)
PROJECT(HELLO)
ADD_SUBDIRECTORY(src bin)
②lib目录CMakeLists.txt内容为:
SET(LIBHELLO_SRC hello.cpp)
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
3)lib下源文件内容
①hello.h内容
#ifndef HELLO_H
#define HELLO_H
void HelloFunc();
#endif
②hello.cpp内容
#include "hello.h"
#include <iostream>
using namespace std;
void HelloFunc(){
cout<<"Hello,world!"<<endl;
}
4)在build目录下进行cmake … 、make 。在build/bin下即出现了libhello.so
(二)同时构建静态库和动态库
SET_TARGET_PROPERTIES
3行命令。视频里补充
八、使用外部头文件和共享库
(一)添加头文件搜索路径:
INCLUDE_DIRECTORIES(路径)
(二)添加需要链接的共享库
TARGET_LINK_LIBRARIES(源文件名 库名)
TARGET_LINK_LIBRARIES(main libhello.so) #链接动态库
TARGET_LINK_LIBRARIES(main libhello.a) #链接静态库
本文参考:b站刘贝斯《从零开始介绍CMake》
转一篇参考:https://blog.csdn.net/wml00876/article/details/120965558