linux makefile入门简介

       皓哥写了一系列的makefile文章后, 就被大家奉为经典。 我自然无法与皓哥相比, 所以仅仅写一下自己对makefile的理解, 自娱自乐, 权当是个人笔记吧。

 

       Windows下的开发, 用IDE, 有所谓的工程的概念, 写好代码,编译、连接运行, 然后看结果就行了。 在这个过程中, IDE直接为我们写好了makefile, 我们啥都不用担心。但在Linux中, 这些makefile文件必须自己去写。 请别说:“我在linux下写了很多代码, 但我不熟悉makefile”

       先说一下基本概念吧: makefile是一个文件, make是一个命令(本质也是一个文件, 类似于ls, rm等基本的linux命令)。 makefile是名词, make是动词, make是用来执行makefile的。

 

       如果你是个linux新手, 那不懂makefile也不要紧, 看完本文后, 肯定会入门makefile.  下面, 我们慢慢来说。 先看几个文件:

       input.h:

 

void input(int *pn);

 

       process.h:

 

int process(int n);

 

       output.h:

 

void output(int result);

 

       intput.c:

 

#include "input.h"

void input(int *pn)
{
	*pn = 6;
}

 

       process.c:

 

#include "process.h"

int process(int n)
{
	return n * n;
}

 

       output.c:

 

#include <stdio.h>
#include "output.h"

void output(int result)
{
	printf("%d\n", result);
}

 

       main.c:

 

#include <stdio.h>
#include "input.h"
#include "process.h"
#include "output.h"

int main()
{
	int n = 0;
	int result = 0;

	input(&n);
	result = process(n);
	output(result);

	return 0;
}

 

       相信大家都能看得懂这么基础的代码。好, 现在我们来编译上面的程序:

[taoge@localhost learnMakeFile]$ gcc main.c input.c process.c output.c
[taoge@localhost learnMakeFile]$ ls
a.out  input.c  input.h  main.c  output.c  output.h  process.c  process.h
[taoge@localhost learnMakeFile]$ ./a.out 
36
[taoge@localhost learnMakeFile]$ 


       结果好, 并不一定真的好。假设main.c有变动, 那么要重新编译吧, 根据上述编译过程可知, 所有的.c文件都需要重新编译。 在实际开发中, 有好多好多.c文件, 全部编译一次, 有时要几个小时, 你自己算一下。  所以, 有必要对上述流程进行优化, 思路是产生中间的目标文件, 如下:

 

[taoge@localhost learnMakeFile]$ rm a.out 
[taoge@localhost learnMakeFile]$ gcc -c main.c
[taoge@localhost learnMakeFile]$ gcc -c input.c
[taoge@localhost learnMakeFile]$ gcc -c process.c
[taoge@localhost learnMakeFile]$ gcc -c output.c
[taoge@localhost learnMakeFile]$ ls
input.c  input.o  main.o    output.h  process.c  process.o
input.h  main.c   output.c  output.o  process.h
[taoge@localhost learnMakeFile]$ gcc main.o input.o process.o output.o
[taoge@localhost learnMakeFile]$ ls
a.out    input.h  main.c  output.c  output.o   process.h
input.c  input.o  main.o  output.h  process.c  process.o
[taoge@localhost learnMakeFile]$ ./a.out 
36
[taoge@localhost learnMakeFile]$ 

      结果好, 并不一定真的好。 假若改动了main.c文件, 我们的确不用编译其他.c文件了, 但还是要编译main.c生成新的main.o啊, 重新编译生成最后的a.out.  而且, 如果修改了某个头文件, 程序员要自己去查找哪些.c文件有依赖, 郁闷得不行。 

 

      那能不能搞个一键编译, 让编译彻底傻瓜化呢? 可以的, 这就是我们要介绍的makefile, 通过makefile我们可以做到:a. 操作简单傻瓜化, 执行make命令即可. b. 编译过的不再编译. c. 无需自己去找变化依赖关系。

 

      我们先建立一个文件, 文件名为makefile, 其内容为(注意, 缩进的时候必须用tab, 不能用空格代替):

a.out : main.o input.o process.o output.o
	gcc -o a.out main.o input.o process.o output.o

main.o : main.c input.h process.h output.h
	gcc -c main.c

input.o : input.c input.h
	gcc -c input.c

process.o : process.c process.h
	gcc -c process.c

output.o : output.c output.h
	gcc -c output.c

clean :
	rm *.o a.out

       好, 我们看看结果:

[taoge@localhost learnMakeFile]$ ls
input.c  input.h  main.c  makefile  output.c  output.h  process.c  process.h
[taoge@localhost learnMakeFile]$ make
gcc -c main.c
gcc -c input.c
gcc -c process.c
gcc -c output.c
gcc -o a.out main.o input.o process.o output.o
[taoge@localhost learnMakeFile]$ ./a.out 
36
[taoge@localhost learnMakeFile]$ make
make: `a.out' is up to date.
[taoge@localhost learnMakeFile]$ make clean
rm *.o a.out
[taoge@localhost learnMakeFile]$ make
gcc -c main.c
gcc -c input.c
gcc -c process.c
gcc -c output.c
gcc -o a.out main.o input.o process.o output.o
[taoge@localhost learnMakeFile]$ 

       我们来看看, 最开始, learnMakeFile这个目录下比较干净, 也就是.c, .h和makefile文件。 执行make命令后, 就执行了对应的编译。 然后, 我们再次make一下, 可以看到, 提示a.out已经是最新的的了, 也就是说, 没有任何修改。 此时, 我们执行make clean来rm中间生成的目标文件和最后的可执行文件, 再次make, 结果发现又重新编译了一次。 

 

       好的, 假设我们这个时候在input.h文件中增加一个空格(改变了input.h文件), 得到的结果如下:

[taoge@localhost learnMakeFile]$ vim input.h
[taoge@localhost learnMakeFile]$ make
gcc -c main.c
gcc -c input.c
gcc -o a.out main.o input.o process.o output.o
[taoge@localhost learnMakeFile]$ ./a.out 
36
[taoge@localhost learnMakeFile]$ make
make: `a.out' is up to date.
[taoge@localhost learnMakeFile]$ 

       可以看到, 在input.h中增加空格后, 依赖于它的main.c和input.c都自动重新编译, 且a.out也会更新。 

 

 

       由此可见: makefile实现了:

       a. 一键傻瓜式编译.  

       b. 只编译有修改的(此处的修改是广义的, 比如虽然main.c和input.c没有手动修改, 但其依赖的input.h文件改动了, 所以main.c和input.c实际上也修改了)

       c. 依赖关系自动识别(由makefile负责, 而不是敲make命令的人负责).

 

       我们还有个疑问, makefile文件中中那些东西都是什么意思啊?  其实, 很简单, 无非就是指定依赖关系, 并且给出对应的编译命令。 其实很简单, 一看就懂。我们知道, shell脚本可以理解为批量的shell命令, 而makefile其实也可以大致理解为批量的编译命令。

       我们再次审视一下makefile文件中的内容, 发现main.o input.o process.o output.o是重复的, 那该怎么办呢? 抽象, 对, 抽象就是专门干这事的, 该makefile文件内容为:

 

x = main.o input.o process.o output.o

a.out : $x
	gcc -o a.out $x

main.o : main.c input.h process.h output.h
	gcc -c main.c

input.o : input.c input.h
	gcc -c input.c

process.o : process.c process.h
	gcc -c process.c

output.o : output.c output.h
	gcc -c output.c

clean :
	rm *.o a.out

       编译结果如下:

 

 

[taoge@localhost learnMakeFile]$ make
gcc -c main.c
gcc -c input.c
gcc -c process.c
gcc -c output.c
gcc -o a.out main.o input.o process.o output.o
[taoge@localhost learnMakeFile]$ ./a.out 
36
[taoge@localhost learnMakeFile]$ make
make: `a.out' is up to date.
[taoge@localhost learnMakeFile]$

        可见, makefile中也可以有变量。 我们再次来审视一下上面的makefile文件, 总感觉有什么冗余的部分, 是的, 那些gcc命令顶多是多余的, 根据依赖关系, 强大的make命令肯定有办法自动推到gcc命令, 我们改为如下:

 

 

x = main.o input.o process.o output.o

main : $x

main.o : main.c input.h process.h output.h

input.o : input.c input.h

process.o : process.c process.h

output.o : output.c output.h

clean :
	rm *.o main

       注意, 此时不能再用a.out了, 结果如下:

 

 

[taoge@localhost learnMakeFile]$ make
cc    -c -o main.o main.c
cc    -c -o input.o input.c
cc    -c -o process.o process.c
cc    -c -o output.o output.c
cc   main.o input.o process.o output.o   -o main
[taoge@localhost learnMakeFile]$ ./main
36
[taoge@localhost learnMakeFile]$ make
make: `main' is up to date.
[taoge@localhost learnMakeFile]$ 

       可见, make确实可以正确推导。 OK, makefile的基本介绍就先告一段落。

 

 

       本文只是makefile的入门简介, 就像一个美少女, 你只是看到了脸蛋而已, 但仅仅脸蛋, 就足够有魅力的。 后续我们会继续深入介绍makefile, 不多说, 你懂的。

 

 


 

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值