引言
本篇文章讲述如何简单的使用cmake工具构建一个项目,帮助入门的c++新手学会如何使用cmake.
我们在Clion新创建一个项目时,会发现,除了main.cpp文件之外,还存在一个build-debug目录和一个CMakelists.txt文件,如图:
CMakelists.txt
CMakelists.txt这个文件描述的是这个项目待编译的源文件,编译选项,库依赖等信息,类似于java项目中的maven.简单来说呢,Cmakelists.txt就是一个描述你这个项目总结构的一个文件.它默认的结构是这样的:
cmake_minimum_required:
是指能接受的cmake工具的最低版本
project:
是指该项目的项目名
set:
指的是当前使用的C++版本,如图,目前使用C++17
add_executable:
指该项目的项目名,和所有待编译的源文件.
cmake-build-debug目录:
在Clion中默认是这个样子的:
那么当我们点击Clion右上角的运行按钮时,不仅终端出会输出hello,world的运行结果,在cmake-build-debug这个文件夹中也会多出一部分内容,多出的这部分内容是构建的中间文件.
构建过程
当我们在Clion中点击运行按钮的时候,Clion会帮助我们自动构建项目,但是实际的构建过程是怎样的呢?
1.首先,CMakelists.txt里记录的是这个项目的一个总结构,库依赖等信息
,我们可以使用cmake命令进行构建
cmake Path
cmake命令会根据Cmakelists.txt里面的内容,在对应的路径下生成一个makefile文件.
Makefile 文件是一个包含构建规则的文本文件,它定义了如何将源代码文件转换为可执行文件或库文件。Makefile 文件中包含了目标(target)、依赖项(dependencies)和命令(commands)。目标表示要生成的文件,依赖项表示目标所依赖的文件,而命令则是执行构建过程的具体命令。
2.通过执行 make 命令,Make 工具会读取当前目录下的 Makefile 文件,并根据其中的规则和命令来执行构建过程。Make 工具会分析文件的依赖关系,检查目标文件和依赖文件的时间戳,以确定是否需要重新编译某个文件。然后,它会按照规则中定义的命令来执行编译、汇编和链接等操作,从而生成最终的可执行文件或库文件。
make path
必须有makefile文件才能执行make命令,然后就会生成一个可执行文件,这个可执行文件,就是一个简单项目的运行结果.
Makefile 文件是非常灵活和可定制的,你可以根据项目的需要定义自己的规则和命令。通过 Make 工具和 Makefile 文件,你可以更加方便地管理和构建 C++ 项目,并确保代码在不同平台上的可移植性。
所以说构建一个项目的大致过程就是
Cmakelists.txt ------>makefile--------> project(可执行文件)
cmake make
我们都知道,一个纯文本的CPP文件,要变成可执行文件,是要经历四个过程的,分别是:
预处理阶段,编译阶段,汇编阶段,链接阶段
那么其实这些过程就是在make命令执行makefile文件中的命令这个阶段中执行的
但是为什么Clion中,在build目录下没生成makefile文件呢,而是生成了一堆构建的中间文件?
这是因为Clion简化了构建过程,所以没有生成可读的makefile文件,但是它的实际构架过程也是这个过程.
简单的构建例子
如果我们不使用Clion,而是直接用命令行运行一个简单项目应该怎么办?
1.创建一个项目文件夹
mkdir my_project
cd my_project
2.创建一个main.cpp
vim main.cpp
随便写点Hello,world之类的
3.创建CMakelists.txt文件
vim CMakelists.txt
写入:
cmake_minimum_required(VERSION 3.24)
project(my_project)
set(CMAKE_CXX_STANDARD 17)
add_executable(my_project main.cpp)
4.创建一个build目录
mkdir build
cd build
5.执行cmake命令,会生成一个makefile
cmake ..
6.执行make命令,会生成一个可执行文件
make
7.执行可执行文件,输出结果
./可执行文件的名字
当然这只是一个最简单的例子
下面我们用Clion,利用CMakelists.txt写一个稍微复杂一丢丢的项目
接下来我将举一个简单例子,来讲一下CMakelists.txt的一些其他用法.
微项目
项目结构:
我们创建一个include的目录,用来存储头文件,因为我们在写C++项目时,需要有一个习惯,就是在.h文件中定义类和函数,但是并不写函数体,而是在.cpp文件中来完成函数体的部分.
Student.h:
#ifndef UNTITLED8_STUDENT_H
#define UNTITLED8_STUDENT_H
#include<string>
class Student
{
int age;
std::string name;
public:
Student(std::string name)
{
this->name=name;
}
std::string get_name();
};
#endif //UNTITLED8_STUDENT_H
Student.cpp
#include "Student.h"
std::string Student::get_name() {
return this->name;
}
当写到这里的时候就会出现点问题,当我们在写入
#include "Student.h"的时候会发现,这部分代码会标红,这是因为使用
Student.h跟Student.cpp不在同一个文件夹之下,我们可以使用
#include"../include/Student.h"
来引入这个头文件,但是这样太麻烦了,我们还是希望使用
#include"Student.h"这样简单的写法,所以我们可以在CMakelists.txt文件中写点东西:
加上这行之后,我们就可以直接使用 #include "Student.h"来引入了,include是头文件所在的目录名.
main.cpp
#include <iostream>
#include"Student.h"
int main() {
Student *stu =new Student("sunjin,hello");
std::cout<<stu->get_name()<<std::endl;
return 0;
}
但是现在又有一个问题,我们需要在CMakelists.txt下,把Student.cpp也添加上去,否则Student.cpp是不会被编译的
我们可以用
aux_source_directory给 ./src下面所有的文件起一个别名,然后把这个别名
加入到 add_executable中,这样src目录下面(一级)的所有文件就都能被编译了,但是这样并不能编译子目录下的文件,需要再用别名.
cmake_minimum_required(VERSION 3.24)
project(untitled8)
set(CMAKE_CXX_STANDARD 17)
include_directories(include)
aux_source_directory(./src DIR)
add_executable(untitled8 ${DIR})
做好这些之后,我们可以点击运行键,然后就可以运行了,也可以自己建一个build目录,手动cmake和make.
up我不是匠人