Makefile 简介

Makefile是在Linux环境下 C/C++ 程序开发必须要掌握的一个工程管理文件。当你使用make命令去编译一个工程项目时,make工具会首先到这个项目的根目录下去寻找Makefile文件,然后才能根据这个文件去编译程序。那Makefile在编译过程中到底起了什么作用呢?这还得从程序的编译链接过程说起。

在Windows下编写程序,你只要会使用集成开发环境(IDE,Integrated Development Environment)就可以了,因为IDE集成了程序的编写、编译、链接、运行、项目管理等一条龙服务,一个编程小白,安装好IDE后,新建一个文件,编写好程序,点击菜单栏上的运行(Run)按钮,程序就可以跑起来了,程序员不需要关心程序在底层是如何编译和运行的。

而在Linux下编写程序,因为早期没有成熟的IDE,一般都是使用不同的命令进行编译:将源文件分别使用编译器、汇编器、链接器编译成可执行文件,然后手动运行。以一个最简单的helloworld程序为例:

// helloworld.c
#include <stdio.h>

int main(void)
{
    printf("hello zhaixue.cc!\n");
    return 0;
}

如果想要将上面的 helloworld.c 编译成可执行文件,一般需要预处理、编译、汇编、链接四个步骤,每个步骤会分别调用预处理器、编译器、汇编器、链接器来完成。

在Linux环境下,如果你安装了GCC编译器,你会看到在程序的安装目录下面会有各种二进制可执行文件:

  • cpp:预处理器
  • ccl:编译器
  • as:汇编器
  • ld:链接器
  • ar:静态库制作工具

程序在编译过程中会分别使用这些工具,完成程序编译的每个流程。为了简化程序编译流程,GCC编译器一般会提供一个gcc命令,当你使用gcc命令去编程程序时:

# gcc -o a.out helloworld.c

gcc会分别调用预处理器、编译器、汇编器和链接器来自动完成程序编译的整个过程,不需要用户一个命令一个命令分别输入了。

当然,gcc还提供了一些列参数,用来控制编译流程。如果你只想对 helloworld.c 进行预处理,不作编译。你可以使用-E参数来完成:

# gcc -E helloworld.c

如果你想helloworld.c只做汇编处理,可以使用下面的命令,就可以将源文件 helloworld.c 编译为汇编文件helloworld.S:

# gcc -S -o helloworld.S helloworld.c

如果你只想对源文件进行编译,不链接,可以使用-c参数,就可以将 helloworld.c 编译为对应的目标文件 helloworld.o:

# gcc -c -o helloworld.o helloworld.c

对于一些简单的程序,单文件程序,使用gcc编译非常方便。当一个项目很大,源文件很多时,此时再使用gcc编译,可能就变成了下面这个样子:

# gcc -o a.out helloworld.c module1.c module2.c module3.c ...

以Linux内核源码为例,有好几万个源文件(.c、.S和.h),如果还使用gcc编译的话,每编译一次,都要敲进去几万个源文件,太折腾了,此时自动化编译工具make就派上用场了:使用make编译程序,不需要每次都输入源文件,直接在命令行下敲击make命令,就可一键自动化完成编译。

make编译依赖Makefile文件。所以在使用make命令编译程序之前,你还需要编写一个Makefile文件:

a.out: helloworld.o
    gcc -o a.out helloworld.o
helloworld.o: helloworld.c
    gcc -c -o helloworld.o helloworld.c
clean:
    rm -f a.out helloworld.o

编写好Makefile文件后,把它和helloworld.c源文件放在同一个目录,进入这个目录,直接敲击make密令,就可以自动完成程序的编译了。

wit@pc:/home/makefile# ls
helloworld.c  Makefile
wit@pc:/home/makefile# make
gcc -o a.out helloworld.c 
wit@pc:/home/makefile# ls
a.out  helloworld.c  helloworld.o Makefile
wit@pc:/home/makefile# ./a.out 
hello world!

wit@pc:/home/makefile# make clean
rm -f a.out helloworld.o
wit@pc:/home/makefile# ls
helloworld.c  Makefile

makefile的文件名通常有三种格式:Makefile、makefile、GNUmakefile,make会在当前目录下自动寻找找三个文件名,如果没有找到的话,make就无法继续编译程序,产生一个错误并退出:

make: *** No targets specified and no makefile found.  Stop.
《Makefile工程实践》视频教程,一线开发工程师独家录制,网上首家讲解Makefile的实战课程。从零开始,教你一步一步编写一个工程项目的Makefile,支持使用第三方静态库、动态库,支持指定模块或目录编译生成静态库、动态库,赠送企业级的Makefile模板,学完即可拿来使用,投入项目开发实战,具备独立开展项目开发和管理的能力。详情请点击淘宝链接:Linux三剑客