三、后缀规则
前面我们已经看到,有些内部规则会根据文件的后缀(相当于Windows系统中的文件扩展名)来采取相应的处理。换句话说,这样当make见到带有一种后缀的文件时,就知道使用哪些规则来建立一个带有另外一种后缀的文件,最常见的是用以.c结尾的文件来建立以.o结尾的文件,即把源文件编译成目标程序,但是不连接。
现在举例说明后缀规则的应用。有时候,我们需要在不同的平台下编译源文件,例如Windows和Linux。假设我们的源代码是C++编写的,那么Windows下其后缀则为.cpp。不过Linux使用的make版本没有编译.cpp文件的内部规则,倒是有一个用于.cc的规则,因为在UNIX操作系统中c++文件扩展名通常为.cc。
这时候,要么为每个源文件单独指定一条规则,要么为make建立一条新规则,告诉它如何用.cpp为扩展名的源文件来生成目标文件。如果项目中的源文件较多的话,后缀规则就可以派上用场了。要添加一条新后缀规则,首先在makefile文件中加入一行来告诉make新后缀是什么;然后就可以添加使用这个新后缀的规则了。这时,make要用到一条专用的语法:
.<旧后缀名>.<新后缀名>: |
它的作用是定义一条通用规则,用来将带有旧后缀名的文件变成带有新后缀名的文件,文件名保持不变,如要将.cpp文件编译成.o文件,可以使用一个新的通用规则:
.SUFFIXES: .cpp .cpp.o: $(CC) -xc++ $(CFLAGS) -I$(INCLUDE) -c $< |
上面的“.cpp .o:”告诉make 这些规则用于把后缀为.cpp的文件转换成后缀为.o的文件。其中的标志“-xc ++”的作用是告诉gcc这次要编译的源文件是c++源文件。这里,我们使用一个宏$<来通指需要编译的文件的名称,不管这些文件名具体是什么。我们只需知道,所有以.cpp为后缀的文件将被编译成以.o为后缀的文件,例如以是app.cpp的文件将变成app.o。
注意,我们只跟make说明如何把.cpp文件变成.o文件就行了,至于如何从目标程序文件变成二进制可执行文件,因为make早已知晓,所以就不用我们费心了。所以,当我们调用make程序时,它会使用新规则把类似app.cpp这样的程序变成app.o,然后使用内部规则将app.o文件连接成一个可执行文件app。
现在,make已经知道如何处理扩展名为.cpp的c++源文件,除此之外,我们还可以通过后缀规则将文件从一种类型转换为另一种类型。不过,较新版本的make包含一个语法可以达到同样的效果。例如,模式规则使用%作为匹配文件名的通配符,而不单独依赖于文件扩展名。以下模式规则相当于上面处理.cpp的规则,具体如下所示:
%.cpp: %o $(CC) -xc++ $(CFLAGS) -I$(INCLUDE) -c $< |