一个简单的Makefile例子

一.欢迎来到我的酒馆

      在本章节介绍make工具。

目录

    • 一.欢迎来到我的酒馆
    • 二.什么是make
    • 三.make与Makefile
    • 四.如何写Makefile

二.什么是make

        你可能会遇到一些名词:GNU,Linux,make。它们是什么,又有什么样的联系?
        在1970年,最早的UNIX系统被开发出来。在UNIX刚开发出来的时候,为了促进UNIX系统的发展,AT&T公司将UNIX源码许可证授权给一些学术机构,许多机构在UNIX源码的基础上开发,开发出了很多类UNIX系统,UNIX系统在这一时期得到非常快速的发展。但是后来,AT&T公司将UNIX商业化并且闭源了,不在将UNIX源码的许可证授权给一些学术机构。
        为了避免版权纠纷,一个叫Richard M. Stallman的大叔发起了GNU计划,在类UNIX系统上从新开发出一个开源的操作系统。GNU是一个名字递归的缩写(GNU’s Not Unix!)。GNU是一个计划,它的目标是创建一套完全自由的操作系统。Rechard M.Stallman大叔为GNU计划开发著名的GCC和Emacs编辑器,并起草了GNU通用公共许可协议(GNU General Public License,GNU GPL),创造了copyleft的授权方式。所有的GNU程序遵循 "copyleft"原则,既可以拷贝、修改、出售,但源代码必须对每个用户公开,所有用户都可以获得修改后的源码。Rechard M. Stallman设立了自由软件基金会(Free Sofeware Fundation Inc. ,简称FSF)。
        有了GNU计划,大家开始着手开发,开发出了很多项目,比如著名的GCC,GLIBC,还有Rechard M. Sstallman大叔开发的Emacs编辑器,基本上实现了GNU计划,但GNU计划还缺少一个操作系统内核。GNU项目从1990年开始开发GNU HURD,这个GNU HURD项目一直不能完成。这时候,一个叫Linus的同学在Minix的启发下开发了Linux,Linux只是一个系统内核,刚好这正是GNU计划的一部分,于是两者一拍即合,一起发布了GNU Linux。Linux系统启动之后,运行的是gcc,bash,emacs等软件。
        make也是GNU计划的一个项目。GNU make是一个项目构建工具,由Rechard M. Stallman大叔和Roland McGrath开发。

三.make与Makefile

        在准备使用make工具之前,你需要写一个文件名为Makefile,顾名思义,Makefile文件就是一个项目的配置文件信息,由make程序执行。在一个程序中,可执行文件一般需要从object文件(.o文件)更新。一旦你写好了Makefile文件,你就可以在shell里使用make:

make

make工具使用Makefile里面的数据为基础,并且决定哪些文件需要被更新,每个文件的执行过程都记录在Makefile文件里面。Makefile文件告诉make程序如何编译和连接一个程序。

四.如何写Makefile

        4.1一个简单的makefile包含了一个规则,如下面描述的那样:

target : prerequisites 
	recipe 1
	recipe 2
	recipe 3
	......
  • target。目标。通常是一个程序生成的文件名,target一般是可执行文件或object文件(.o文件)。target同样可以是一个执行名称,例如:clean.
  • prerequisite 。依赖条件。它是一个文件,用作输入来创建一个target。一个target通常依赖多个文件。
  • recipe。配方。一个配方可以理解成一个shell命令,在写每个个配方之前,必须敲一个tab键。

接下来,我们开始写一个Makefile。这里我准备通过用一个项目介绍Makefile,cJSON是c语言编写的JSON解码器,代码非常简洁,只有750行代码。先将cJSON项目下载下来,点击这里下载cJSON源码,
解压文件:

tar -zxvf cJSONSourceFiles.tar.gz 

解压完成后,cJSON项目源程序如下:

一个简单的Makefile例子_第1张图片有用的文件:

  • cJSON.c:写好的函数
  • cJSON.h :头文件
  • test.c:测试文件

4.2接下来开始为这个项目创建Makefile文件,使用vim将下面内容粘贴到一个文件中,并命名为Makefile,如下:

all: test

test: test.c cJSON.o
	cc -W -Wall -o test test.c cJSON.o -lm 
	
cJSON.o: cJSON.c cJSON.h
	cc -W -Wall -c -o cJSON.o cJSON.c
	
clean:
	rm -rf *.o test 

来看一下这个Makefile文件是怎么写的,测试文件test.c用于生成一个可执行文件,它会用到cJSON.h里面的函数,而cJSON.h的函数实现写在cJSON.c中,所以,生成可执行文件的时候需要链接cJSON.o文件,cJSON.c文件编译之后就是一个.o文件了。
下面是对编译参数的介绍:

-W:关闭所有警告信息。
-Wall:打开警告信息。
-o:输出目标文件
-lm:链接库math。
-c:编译目标文件,但不链接。

4.3在当前文件打开命令行,输入命令:make就可以构建整个cJSON项目了。下面来看一些Makefile的执行流程:

一个简单的Makefile例子_第2张图片

①:target为all,all需要依赖条件test,test文件存在且最新吗 ? 报make: Nothing to be done for ‘all’ :执行②;
②:target为test,test需要依赖条件cJSON.o,cJSON.o文件存在且最新吗 ?执行⑧⑨ :执行④;
④:target为cJSON.o,cJSON.o需要先决条件cJSON.c和cJSON.h,cJSON.c和cJSON.h文件存在吗 ?执行⑦ : 报错make: *** No rule to make target `cJSON.c’,
⑦:是一条熟悉的gcc命令,写gcc命令之前需要敲一个tab键,执行完⑦后回到②的步骤,此时步骤②的依赖条件都满足了,执行下面的gcc命令⑨,编译test.c文件并且链接cJSON.o文件,生成可执行文件test。
⑩:target为clean,clean没有需要的先决条件,所以默认不会执行,除非指定参数才会执行。

make的执行流程不知道我讲清除没有,有点印象的话,我们赶紧生成一个程序,跑一下cJSON项目。在Makefile的同级目录下打开命令行,输入命令:

make 

如果你按照上面的流程写,不出意外的话,将会得到下面的输出:

gcc -W -Wall -c -o cJSON.o cJSON.c
gcc -W -Wall -o test test.c cJSON.o -lm 
......

上面的两条gcc命令看到之后,是不是觉得很熟悉!这和我们在shell里写的编译命令是一样的!
如果要删除编译的文件,可以执行命令:(这和上面讲到的make执行流程第⑩是一样的指定一个参数执行,就会执行⑪)

make clean

4.4 编译好了可执行文件,下面就可以运行了:

./test

输出:

{
	"name":	"Jack (\"Bee\") Nimble",
	"format":	{
		"type":	"rect",
		"width":	1920,
		"height":	1080,
		"interlace":	false,
		"frame rate":	24
	}
}
["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
[[0, -1, 0], [1, 0, 0], [0, 0, 1]]
{
	"Image":	{
		"Width":	800,
		"Height":	600,
		"Title":	"View from 15th Floor",
		"Thumbnail":	{
			"Url":	"http:/*www.example.com/image/481989943",
			"Height":	125,
			"Width":	"100"
		},
		"IDs":	[116, 943, 234, 38793]
	}
}
[{
		"precision":	"zip",
		"Latitude":	37.766800,
		"Longitude":	-122.395900,
		"Address":	"",
		"City":	"SAN FRANCISCO",
		"State":	"CA",
		"Zip":	"94107",
		"Country":	"US"
	}, {
		"precision":	"zip",
		"Latitude":	37.371991,
		"Longitude":	-122.026020,
		"Address":	"",
		"City":	"SUNNYVALE",
		"State":	"CA",
		"Zip":	"94085",
		"Country":	"US"
	}]
{
	"name":	"Jack (\"Bee\") Nimble",
	"format":	{
		"type":	"rect",
		"width":	1920,
		"height":	1080,
		"interlace":	false,
		"frame rate":	24
	}
}
["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
[[0, -1, 0], [1, 0, 0], [0, 0, 1]]
{
	"Image":	{
		"Width":	800,
		"Height":	600,
		"Title":	"View from 15th Floor",
		"Thumbnail":	{
			"Url":	"http:/*www.example.com/image/481989943",
			"Height":	125,
			"Width":	"100"
		},
		"IDs":	[116, 943, 234, 38793]
	}
}
[{
		"precision":	"zip",
		"Latitude":	37.766800,
		"Longitude":	-122.395900,
		"Address":	"",
		"City":	"SAN FRANCISCO",
		"State":	"CA",
		"Zip":	"94107",
		"Country":	"US"
	}, {
		"precision":	"zip",
		"Latitude":	37.371991,
		"Longitude":	-122.026000,
		"Address":	"",
		"City":	"SUNNYVALE",
		"State":	"CA",
		"Zip":	"94085",
		"Country":	"US"
	}]

你可能感兴趣的:(编辑器)