怎么把makefile文件和c++源文件转成vs工程_Makefile 基础知识

一、为什么需要 Makefile?

我们平常写一些小代码,都是直接在终端上执行 gcc 命令来完成源文件的编译。感觉挺方便的,这是因为我们工程中的源文件只有那么一两个,在终端直接执行编译命令,确实快捷方便。

但是现在很多项目工程中的源文件都是不计其数,其按类型、功能、模块分别存放在若干个目录中。如果我们仍然在终端输入这些命令来编译,那显然不切实际,开发效率极低。

所以我们需要一个工具来管理这些编译过程,这就是 “make”。

make 是一个应用程序,它根据 Makefile 来做事。Makefile 可以简单的认为是一个工程文件的编译规则,描述了整个工程的编译和链接等规则。其中包含了:要编译哪些文件?怎么编译这些文件?怎么把它们链接成一个可执行程序。总之Makefile 定义了一系列的规则来实现这些管理。它使得我们的项目工程的编译变得自动化,不需要每次都手动输入一堆源文件和参数。 二、Makefile 的引入

Makefile的引入是为了简化我们的编译流程,提高我们的开发进度。下面我们用一个例子来说明 Makefile 是如何简化我们的编译流程。

我们创建一个工程,内容包含 main.c,sub.c,sub.h,add.c,add.h 五个文件。sub.c 负责计算两个数减法运算;add.c 负责计算两个数加法运算;然后编译出可执行文件。其源文件内容如下图所示:

be1b49d3fd5b9ccb4c7f44e230829777.png

我们使用 gcc 编译器对上面工程进行编译及生成可执行程序,编译的命令如下所示:
[root@localhost test]# gcc main.c sub.c add.c -o output [root@localhost test]# lsadd.c  add.h  main.c  output  sub.c  sub.h[root@localhost test]# ./output 200[root@localhost test]#
上面的命令是通过 gcc 编译器对 main.c、sub.c、add.c 这三个源文件进行编译,及生成可执行程序 output, 并执行可执行文件产生结果。 这个例子看起来比较简单,一条命令即可完成三个源程序的编译并产生结果。但是设想一下,如果我们的工程有上千个源文件,即使你只修改了其中一个文件,你执行这样的命令时,它会把所有的源文件都编译一次。这样消耗的时间是不是非常恐怖呢。 所以我们希望实现的功能是: 哪个文件被修改了,只编译这个被修改的文件即可,其它没有修改的文件就不需要再次重新编译了。我们可以使用下列命令,先单独编译文件,最后再链接,如下所示:
[root@localhost test]# lsadd.c  add.h  main.c  sub.c  sub.h[root@localhost test]# gcc -c main.c[root@localhost test]# gcc -c add.c[root@localhost test]# gcc -c sub.c[root@localhost test]# lsadd.c  add.h  add.o  main.c  main.o  sub.c  sub.h  sub.o[root@localhost test]# gcc main.o sub.o add.o -o output[root@localhost test]# ./output 200[root@localhost test]#
这里我们将最开始的一条命令变成了四条,分别编译出每个源文件的目标文件,最后再将所有的目标文件链接成可执行文件。当其中一个源文件的内容发生了变化,我们只需要单独编译它,然后跟其它目标文件重新链接成可执行文件,不再需要重新编译其它文件。 假如我们修改了 add.c 文件,只需要重新编译生成 add.c 的目标文件,然后再将所有的.o 文件链接成可执行文件,如下:
[root@localhost test]# gcc -c add.c[root@localhost test]# gcc main.o sub.o add.o -o output[root@localhost test]#
这样的方式虽然可以节省时间,但仍然存在下面几个问题: 
  • 如果源文件很多,那么我们需要花费大量的时间去敲命令执行;

  • 如果源文件很多,然后修改了很多文件,后面又忘记修改了哪些文件;

  • 如果头文件的内容修改,替换,更换目录,所有依赖于这个头文件的源文件全部需要重新编译。

这时候引入Makefile 就可以解决这些问题啦。我们先看一个 Makefile,如下所示:

Makefile:
output: main.o add.o sub.o    gcc -o output main.o add.o sub.omain.o: main.c    gcc -c main.cadd.o: add.c    gcc -c add.csub.o: sub.c    gcc -c sub.cclean:    rm *.o output

Makefile 编写好后只需要执行 make 命令,它就可以自动帮助我们编译工程。注意,make 命令必须要在 Makefile 的当前目录执行,如下:

[root@localhost test]# tree .|-- Makefile|-- add.c|-- add.h|-- main.c|-- sub.c`-- sub.h0 directories, 6 files[root@localhost test]# makegcc -c main.cgcc -c add.cgcc -c sub.cgcc -o output main.o add.o sub.o[root@localhost test]# tree .|-- Makefile|-- add.c|-- add.h|-- add.o|-- main.c|-- main.o|-- output|-- sub.c|-- sub.h`-- sub.o0 directories, 10 files[root@localhost test]#
通过 make 命令就可以根据 Makefile 的规则生成相对应的目标文件.o 和可执行文件。如果我们再次使用 make 命令编译,它会提示你的目标文件已经是最新的了,不需要再做什么事情,如下:
[root@localhost test]# makemake: `output' is up to date.[root@localhost test]#

我们可以修改一下 add.c,然后再执行 make,如下:

[root@localhost test]# makemake: `output' is up to date.[root@localhost test]# touch add.c[root@localhost test]# makegcc -c add.cgcc -o output main.o add.o sub.o[root@localhost test]# makemake: `output' is up to date.[root@localhost test]#
会发现,它重新编译了 add.c,并且重新生成了可执行程序。 通过上述例子发现,Makefile 很容易地将我们上面的三个问题都解决了,无需手工输入复杂的命令,只编译修改过的文件。在一个很庞大的工程中,只有第一次编译时间比较长,第二次编译时会大大缩短时间,很大程度上提高编译的效率。

三、Makefile 的规则

  • 命名规则:

    编写Makefile的时候可以使用的文件的名称"GNUmakefile" 、"makefile" 、"Makefile" ;make 执行时会去寻找 Makefile 文件,寻找文件的顺序也是这样的。惯例是使用首字母大写的 “Makefile”。也可以使用其他名字,比如 makefile.linux,但你需要用“-f” 参数指定,示例如下:

$ make -f makefile.linux
  • 基本语法规则:

    它的语法规则主要由两个部分组成,分别是依赖的关系和执行的命令,其结构如下所示:

 目标(target):依赖(prerequisites) [Tab键]命令(command)
相关说明如下:
  • target:规则的目标,可以是 Object File(一般称它为中间文件),也可以是可执行文件,还可以是一个标签;

  • prerequisites:是我们的依赖文件,要生成 target 所需要的文件或者是目标。可以是多个,也可以没有;

  • command:make 需要执行的命令(任意的 shell 命令)。可以有多条命令,每一条命令占一行。

注意:我们的目标和依赖文件之间要使用冒号分隔开,命令的开始一定要使用Tab键。

我们平时要编译一个文件,可以直接使用gcc命令来,如下:

[root@localhost test]# gcc main.c -o main

如果需要换成 Makefile,那么它的书写格式如下:

main: main.c    gcc main.c -o main
第 1 行表示 main 这个可执行程序依赖于main.c;

第 2 行表示重建main目标文件需要执行的操作是“gcc main.c -o main”。

注意: Makefile文件里的命令前面必须要使用Tab键,不能使用空格。
  • 目标生成规则:

目标生成:
  1. 检查规则中的依赖文件是否存在;
  2. 若依赖文件不存在,则寻找是否有规则用来生成该依赖文件。

目标生成流程,如下:

d00874f992d970011ba892526fed9916.png

目标更新:
  1. 检查目标的所有依赖,任何一个依赖有更新,就要重新生成目标;

  2. 目标文件比依赖文件更新时间晚,则需要更新。

目标更新流程,如下:

96a12c24e20bbec95d6735f377c723e5.png

还是以前面的Makefile为例:

output: main.o add.o sub.o    gcc -o output main.o add.o sub.omain.o: main.c    gcc -c main.cadd.o: add.c    gcc -c add.csub.o: sub.c    gcc -c sub.cclean:    rm *.o output

使用make命令执行编译过程:

[root@localhost test]# makegcc -c main.cgcc -c add.cgcc -c sub.cgcc -o output main.o add.o sub.o[root@localhost test]#

默认情况下,make 执行的是 Makefile 中的第一规则(Makefile 中出现的第一个依赖关系),此规则的第一目标称之为“最终目标”或者是“终极目标”。

make 命令会检测寻找目标的依赖是否存在,不存在,则会寻找可以生成依赖的命令。如下:

  1. output 依赖于“main.o  add.o  sub.o”,这三个依赖文件一开始是都不存在的,那就要分别去生成它们。怎么生成? 继续寻找规则,发现 main.o 依赖于 main.c,于是使用“gcc -c main.c”来生成;其它两个文件类似处理。

  2. 现在output 的依赖文件都有了,但是output 文件还没有,所以使用“gcc -o output main.o add.o sub.o”来生成 output 文件。

这里当我们只修改某一个文件时,比如只修改 add.c 文件,然后再重新 make,如下:
[root@localhost test]# makemake: `output' is up to date.[root@localhost test]# touch add.c[root@localhost test]# makegcc -c add.cgcc -o output ma
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值