Chinaunix首页 | 论坛 | 博客
  • 博客访问: 323185
  • 博文数量: 61
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 789
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-05 22:48
文章分类
文章存档

2012年(1)

2011年(2)

2010年(22)

2009年(36)

我的朋友

分类: LINUX

2010-05-11 21:51:23

在GNU/Linux环境下, 使用make编译程序是个不错的选择. 较之IDE, make更灵活, 更健壮, 尤其对平台适应力强.  实际上, make在上实际七十年代就出现了, 它的年纪可比你我大许多. 许多大型项目(最著名的恐怕就是linux内核)都使用make进行管理.

在众多的make版本中, GNU make是最突出的, 它已成了当前的"标准"make. 所有的GNU/Linux平台上都有提供, 一些BSD的变种, Mac OS X甚至cygwin也都使用GNU Make. 所以选择GNU make学习, 编写makefile是不二选择.

关于GNU Make, 可以看看. 它摘录自 o'reilly的《GNU Make项目管理》, 这本书china-pub上有得卖, 薄薄280面, 定价却要¥58, 在此鄙视一下东南大学出版社  

OK, 现在步入正题, 这里假设你使用C语言进行编程.


预备知识

首先我们必须具有一些预备知识: 你知道什么叫编译, 什么叫连接吗? 目标文件和可执行文件有什么区别? 一个C源程序是如何转化为可执行程序的? 以往的IDE往往对C初学者隐藏了这些基础概念. 要使用Make, 这些概念是要清楚的.

另外, 你需要对GNU/Linux上的编译器具有一定的了解——当然是gcc啦! 因为Makefile中的命令实际上是针对编译器的命令.

可以参考本人blog的这两篇文章:
GNU/Linux平台的C程序开发及程序运行环境
GCC笔记

几个要说明的词汇
目标(target): 在makefile指定要生成的目标,  它可以是可执行文件,  目标文件,  也可以只是一个标签.

先决条件(prerequisite): makefile中指定的针对要生成某个target所依赖的文件或标号.

命令(command): Make针对target利用makefile中指定的规则所调用的命令. 它可以是你在shell中能够指定的所有命令.

GNU Make的工作原理

Make 通过 makefile文件被告知它的工作: 要生成怎样的目标文件?  由哪些代码编译生成?所以学习GNU Make实际上就是学习Makefile的写法. 下面是一个简单的makefile:

hello: hello.c
    gcc hello.c -o hello

我们熟悉的hello程序,
$ make
gcc hello.c -Wall -o hello

这样我们的hello可执行程序就出来了!

make的规则:
target: prereq1 prereq2
    commands

target就是目标文件, 它可能是,o文件, 可执行文件或标签中的一种.

关于target,有这样的约定:
如果某target被包含在执行make的命令行参数中, 则更新该target; 如果make没带参数, 则将第一个target作为默认目标进行更新.

prerequisites是生成target所需要的文件.

command是make调用gcc执行的指令. 注意, command以Tab键打头, 不能是空格!

到了这里, 就可以理解Make的原理了:

make的基本思想: 对于一个target (由命令行所指定或默认第一个target), 如果它不存在, 或者它的prerequisites中有比它更新的, 那么执行command所指定的命令.
所谓"更新", 是指比别的文件更晚被修改, make通过timestamp来记录谁更新.


makefile文件名

  1. 默认情况下, make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件.

  2. 最好不要用“GNUmakefile”, 这个文件只被GNU make识别. 虽然有些Make只对全小写的“makefile”文件名敏感, 但大多数的make都支持“makefile”和“Makefile”这两种默认文件名.

  3. 可以使用别的文件名来书写makefile, 比如: "Make.Linux", “Make.Solaris”, “Make.AIX”等. 如果要指定特定的Makefile,你可以使用make的“-f”或者“--file”参数,如:make -f Make.Linux 或 make --file Make.AIX.

推荐以 Makefile 作为文件名!


命令行中调用Make命令


(1) $ make target-name
(2) $ make
(3) $ make non-exist-target
(4) $ make -n   or  $ make --just-print

(1) 如果在命令行中指定了target, 则make针对该target进行工作
(2) 如果未指定target, 则make对默认target进行操作.(Makefile中出现的第一个target)
(3) 如果指定的target不存在, 则make报错:

 make: *** No rule to make target `non-exist-target'.  Stop.

(4) 若加上 -n 或者 --just-print选项, make只是列出将要执行的命令, 并不执行它们. 这非常有用!


Makefile 的基本语法

Makefile 采用自上而下 (top-down)的组织, 最开始的target即"终极目标", 也是默认target. 观察make输出的命令可以发现, 它们的顺序与出现在Makefile中的命令刚好相反. 可以把Makefile中针对target的规则想象成C函数. 最开始的是main(), 然后依次调用相关的函数(即针对prereq调用相关的规则).

看看一个比较简单的Makefile规则:

target1 target2 target3 : prereq1 prereq2
    command1
    command2
    command3

  • 第一行列出了targets和prereqs, 注意目标与它们依赖的文件之间以" : "分隔. 目标或prereq之间以空格分隔.

  • 在冒号左边可以有1个或多个targets, 在冒号右边可以有0个或者多个prerequisites. 如果prerequisite的数目为0, 则只有当对应的target不存在时才执行命令.

  • 如果command不和目标, 先决条件在一行,那么它之前必须以Tab开头; 如果command与目标, 先决条件在一行, 那么它要以";"开头. Make将command传递给子shell去执行.

 注意: 不要忘了在命令以Tab开头, 也别在不是命令开头的地方输入Tab, 否则Make会将它之后的字符当作命令.
  • Make中的注释符为 "#". #之前可以有空格, 从#开始到行尾的所有字符都会被忽略. 注意: 如果你把#写在了命令中, 包括#在内的行都会传递给shell, 会有什么样的结果取决于你所用的shell.

  • 可以在Makefile中使用转义字符 \, 我们都知道, 在命令行中, 可以使用 \ 在下一行输入命令. 同样的, 在Makefile的所有行中, 都可以使用 \ 来分割太长的语句.

阅读(1378) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~