Cmake工具的简单使用

引言
本篇文章讲述如何简单的使用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.


make命令执行多线程编译

先创建一个makefile文件:

CC=gcc
CFLAGS=-Wall -Wextra -pthread
LDFLAGS=-pthread

# 定义目标文件和依赖关系
TARGET=myprogram
OBJS=main.o thread1.o thread2.o

# 默认目标
all: $(TARGET)

# 生成可执行文件
$(TARGET): $(OBJS)
	$(CC) $(LDFLAGS) $^ -o $@

# 生成目标文件
%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

# 清理生成的文件
clean:
	rm -f $(TARGET) $(OBJS)

然后用make命令构建

make

该命令将根据Makefile文件中的规则编译和链接源代码,并生成可执行文件myprogram。

请注意,上述Makefile文件中的CFLAGS和LDFLAGS变量都包含了-pthread选项。这是启用多线程编程所必需的,它将在编译和链接过程中包含线程库。

另外,Makefile中的.c文件的编译规则指定了-pthread选项,以确保在编译每个源文件时都启用了多线程支持。

通过这种方式,你可以使用make指令来编译和链接多线程程序,并在编译过程中使用多线程选项。这样可以充分利用系统的多核处理器和线程并发性能。


makefile文件

CC=gcc
CFLAGS=-Wall -Wextra -pthread
LDFLAGS=-pthread

# 定义目标文件和依赖关系
TARGET=myprogram
OBJS=main.o thread1.o thread2.o

CC是用于指定编译器的变量。在示例中,它设置为gcc,表示使用GCC编译器。
CFLAGS是编译选项的变量。-Wall和-Wextra是启用所有警告的选项,-pthread是启用多线程支持的选项。
LDFLAGS是链接选项的变量。-pthread是启用多线程支持的选项。
TARGET是最终生成的可执行文件的名称,这里设置为myprogram。

OBJS是所有目标文件(.o文件)的列表,即需要编译和链接的源代码文件。

# 默认目标
all: $(TARGET)

all是默认的目标,即在执行make命令时,如果未指定目标,默认会构建$(TARGET)。

# 生成可执行文件
$(TARGET): $(OBJS)
	$(CC) $(LDFLAGS) $^ -o $@

这个规则指定了如何生成可执行文件。它说明了 ( T A R G E T ) 依赖于 (TARGET)依赖于 (TARGET)依赖于(OBJS)中列出的目标文件。 表 示所有的依赖文件, ^表示所有的依赖文件, 示所有的依赖文件,@表示目标文件。这一行的命令将使用GCC编译器和链接选项$(LDFLAGS)来编译和链接目标文件,生成最终的可执行文件。

# 生成目标文件
%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

这个规则指定了如何生成目标文件(.o文件)。它说明了每个目标文件(如main.o、thread1.o、thread2.o)依赖于相应的C源代码文件(如main.c、thread1.c、thread2.c)。 < 表示第一个依赖文件(即 C 源代码文件), <表示第一个依赖文件(即C源代码文件), <表示第一个依赖文件(即C源代码文件),@表示目标文件。这一行的命令将使用GCC编译器和编译选项$(CFLAGS)将C源代码文件编译为目标文件。

# 清理生成的文件
clean:
	rm -f $(TARGET) $(OBJS)

这个规则定义了一个clean目标,用于删除生成的可执行文件和目标文件。执行make clean命令将删除 ( T A R G E T ) 和 (TARGET)和 (TARGET)(OBJS)中列出的文件。

通过编写这样一个Makefile文件,你可以使用make命令来自动化

make的常用命令

在这里插入图片描述

up我不是匠人

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值