Makefile学习笔记(2)@linux

作者: 云中布衣   分类:  学习笔记    热度: (380℃)   时间: 2017-6-15 16:58   标签: #《Linux程序设计》的那些事    

第二回 再探make命令与makefile文件

上一小节,通过一个程序员日常遇到的问题引出了make命令和makefile文件,这一小节着重介绍下makefile文件中的注释、宏、多目标,make命令的内置规则、后缀和模式规则、函数库管理。

1.makefile文件中的注释

makefile文件中的注释以#开头,一直延续到这一行的结束。例如 #This is a code annotation!

2.makefile文件中的宏

用过语句MACRONAME=value在makefile文件中可以定义宏,引用宏的方法是$(MACRONAME)或者${MACRONAME}。如果想把一个宏设为空在value可以不用写,(=)号后面直接留空。在makefile文件中宏的用途主要有以下两点:

(1)常被用于设置编译器的选项

(2)通过宏定义可以很方便的修改编译器,例如gcc、cc、c89、c99,使用宏可以很好的解决系统依赖问题。

宏通常是在makefile文件中定义的,但是你也可以在调用make命令时在命令行上,给出宏的定义。例如 make CC=gcc。命令行上的宏定义将覆盖在makefile文件中的宏定义。

注:当在makefile文件之外使用宏定义时,要注意宏定义必须以单个参数的形式传递,所以应该避免在宏定义中使用空格或给宏定义加上引号,例如 make="CC = c89"

事实上,make命令内置了一些特殊的宏定义,下面是一些常用的内置宏。

$?
当前目标所依赖的文件列表中比当前目标文件还要新的文件
$@
当前目标的名字
$<
当前依赖文件的名字
$*
不包括后缀名的当前依赖文件的名字
-
告诉命令忽略所有错误
@
告诉make在执行某条命令前不要将该命令显示在标准输出上

3.多目标(all,clean,intall

通常制作不止一个目标文件或者将多组命令集中到一个位置来执行是很有用的,你可以通过扩展makefile文件来达到这个目的,下面介绍三个目标来简单的展现多目标的makefile文件。

(1)目标all是一个特殊的目标,许多程序员都会在低级的makefile文件中第一个目标定义为all;

(2)目标clean用rm命令来删除不需要的目标文件。(rm命令以减号-开头,可以让make命令忽略rm命令的执行结果)

(3)目标install用来将编译成功的应用程序安装到另一个目录下。

4.make命令的内置规则

正如上篇文章中的实验makefile文件,我们对每个操作步骤的执行都做了精确的说明,事实上,make命令本身带有大量的内置规则,它们极大的简化了makefile文件的内容。下面我们做一个简单的小测试,创建一个foo.c文件,一个简单的“Hello,Word”程序:

/*foo.c*/
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char const *argv[]){
	printf("Hello Word!\n");
	exit(EXIT_SUCCESS);
}
在不指定makefile文件时,我们尝试用make命令来编译它:
$ make foo
cc foo.c -o foo
从Shell输出可以看到make命令默认使用的是cc编译器来编译foo.c文件,我们称其为内置规则(也称推导规则),由于它们都会使用宏定义,因此我们完全可以通过给宏重新赋值来改变其默认行为。
$ rm foo
$ make CC=gcc CFLAGS="-Wall -g" foo
gcc -Wall -g foo.c -o foo

其中参数解释如下: -Wall 参数 给出几乎所有的编译器警告   -g 参数 指示编译器在编译时产生调试信息

此外可以通过make -p命令打印出所有内置规则,由于内置规则太多,在此不能一一列举,下面是一部分内置规则。

# 默认
OUTPUT_OPTION = -o $@
# 默认
COMPILE.cpp = $(COMPILE.cc)
# makefile (from 'makefile', line 1)
MAKEFILE_LIST :=  makefile
# 自动
@F = $(notdir $@)
# 环境
IM_CONFIG_PHASE = 1
# 环境
UNZIP = -O CP93

5.后缀和模式规则

make命令知道应该用哪个规则来创建带有另一个不同后缀名的文件。最常见的一条规则就是从一个.c为后缀名的文件,创建出了一个以.o为后缀名的文件。该规则使用编译器进行编译,但是不对源文件进行链接。

我们可以通过下面方法创建新规则:

.<old_suffix> .<new_suffix>:

下面是makefile文件的一个片段,它用一个新的通用规则来将.cpp文件编译为.o文件:

.SUFFIXES: .cpp
.cpp .o:
    $(CC) --xc++ $(CFLAGS) -I$(INCLUDE) -c $<
#现在最新的make版本包含一个新的语法来实现同样的效果
#模式规则可以使用%通配符语法来匹配文件名,而不是依赖文件的后缀名
%.o: %.cpp
    $(CC) --xc++ $(CFLAGS) -I$(INCLUDE) -c $<
6.用make管理函数库

对于大型的项目,一种比较方便的方法就是用函数库来管理多个编译产品,函数库实际上就是文件,它们通常以.a(archive的首字母)为后缀名,在该文件中包含了一组目标文件。

参考资料:《Beginning Linux Programming》 4th Edition Neil Mattew & Richard Stones

(完)

56.8K

发表评论:

© 云中布衣 2015 | Driven by EMLOG  | SiteMap | RunTime: 9.45ms&RSS  | MORE  |   | TOP

文章数量【252】 评论数量【206】 稳定运行【1150天】

Visitor IP Address【54.80.96.153】

Email:ieeflsyu#outlook.com