3. 隐含规则
隐含规则 是 make 程序内置的规则,他会在 make 命令的第一阶段加载,并可以根据隐含规则来生成对应的目标文件。
默认的隐含规则会在没有 .o 目标文件时,会尝试使用 cc 编译器将同名的 .c 文件生成同名的 .o 文件。如果不存在同名的 .c 文件也会尝试使用 yacc 词法分析工具将同名的 .y 文件生成 同名的 .c 文件。如果也没有 .y 文件,则会尝试使用 g++ 编译器将同名的 .cc 或 .cpp 编译成对应的 .o 文件。这样的规则称为隐含规则。类似的隐含规则还有很多。
在上节课的示例中我们定义了显式规则如下:
main.o : main.c $(HEADERS)
gcc -o $@ -c $<
file1.o : file1.c $(HEADERS)
gcc -o $@ -c $<
file2.o : file2.c $(HEADERS)
gcc -o $@ -c $<
在执行 make 时,是使用 gcc 编译器 对 mail.c、file1.c、file2.c 编译生成对应的 .o 文件。编译命令如下:
gcc -o file1.o -c file1.c
gcc -o file2.o -c file2.c
gcc -o main.o -c main.c
我们删除 Makefile 中的上述显式规则,你会发现在执行 make 命令时依旧可以编译成功。
Makefile 文件内容如下:
.PHONY: all clean
SOURCES := file1.c file2.c main.c
HEADERS := file1.h file2.h
OBJECTS := file1.o file2.o main.o
TARGET := myapp
all: $(TARGET) # 编译最终目标
$(TARGET) : $(OBJECTS)
gcc -o $@ $^
clean: # 清除目标文件
rm $(OBJECTS)
运行 make 结果如下:
weimingze@mzstudio:~/myapp$ make
cc -c -o file1.o file1.c
cc -c -o file2.o file2.c
cc -c -o main.o main.c
gcc -o myapp file1.o file2.o main.o
weimingze@mzstudio:~/myapp$ ./myapp
库函数 myfunc1 被调用
库函数 myfunc2 被调用
上述程序中,实际是使用的是隐含规则 来生成 mail.o、file1.o 和 file2.o 这三个文件,他们使用的命令是 $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $^。
其中 CC、CPPFLAGS 和 CFLAGS 都是隐含规则的变量,Makefile 允许我们修改这些变量来更换编译器和编译选项。
隐含规则的变量
ARarASasCCccCXXg++COcoCPP$(CC) -EFCf77GETgetLEXlexPCpcYACCyaccMAKEINFOmakeinfoTEXtexTEXI2DVItexi2dviWEAVEweaveCWEAVEcweaveTANGLEtangleRMrm -fARFLAGSrvASFLAGSCFLAGSCXXFLAGSCOFLAGSCPPFLAGSFFLAGSGFLAGSLDFLAGSLFLAGSPFLAGSRFLAGSYFLAGS在上述示例中,我们将编译器改为 gcc ,将编译选项 添加一个 -g -Wall 参数,改写后代码如下:
改写后的 Makefile 文件如下:
.PHONY: all clean
SOURCES := file1.c file2.c main.c
HEADERS := file1.h file2.h
OBJECTS := file1.o file2.o main.o
TARGET := myapp
# 修改隐含规则的变量,更改编译命令
CC = gcc
CFLAGS = -g -Wall
all: $(TARGET) # 编译最终目标
$(TARGET) : $(OBJECTS)
gcc -o $@ $^
clean: # 清除目标文件
rm $(OBJECTS)
使用 make 编译结果如下:
weimingze@mzstudio:~/myapp$ make
gcc -g -Wall -c -o file1.o file1.c
gcc -g -Wall -c -o file2.o file2.c
gcc -g -Wall -c -o main.o main.c
gcc -o myapp file1.o file2.o main.o
从上述 make 命令的执行结果可以看出。我们通过修改 CC 等变量的值将 C 语言的编译器改成了 gcc,而不再使用默认的编译器 cc。
可用的隐含规则
.c文件生成同名.o文件。.cc、.C或.cpp文件生成同名.o文件。.s文件生成同名.o文件。.f文件生成同名.o文件。.o文件生成同名无后缀文件。.i文件生成同名.o文件。.y文件生成同名.c文件。.l文件生成同名.c文件。.o文件生成同名lib开头,.a结尾的静态库文件。.dvi文件生成同名.ps文件。
实验:
尝试使用 隐含规则编译多个 C++ 文件。将多个 C++ 文件编译成一个可执行文件。如果你没有 C++ 文件,你可以尝试将 file1.c、file2.c 和 mail.c 的文件后缀由 .c 改为 .cpp 然后尝试运行 make 编译。