Makefile小摘要

来点圡的。

makefile这种东西也熟能生巧的东西。网上的资料很多很全了,这篇就算自己整理的一些小tip, 如果已经很熟悉makefile的可以直接忽略。

网上和参考书的资料多是详细罗列各种语法规则,要么勿尽齐全,以致冗繁(这点和linux里面的man手册有点像,虽然手册写得大而全无可厚非,但是读起来总是很费时费力,效率不高),要么只捡要点,拾一漏万。本文直接用一个现成的MAKEFILE文件添加注释的方式进行说明,力求能覆盖makefile编写过程中的一些基本要点。

include Makefile.env
#makefile中include的用法和c语言中类似,只不过不用加””或<>,实际使用中可以用类似Makefile.env之类的文件来定义一些常用的可移植的宏定义来增加makefile的可重用性

SRC_PATH=./src
INC_PATH=./inc
PWD=./

#以上类似于C语言中的宏定义,只不过不用加#define,或者也可以视为变量定义,其实就是shell中的语法

INCLUDES =  -I $(CONFIG)/include \
-I $(TEST)test_log/ \
-I $(BUFFER)include \
LDFLAGS = -L $(CONFIG)/lib -lconfig \
-L $(TEST)/test_log/ -ltest_log \
-L $(BUFFER)lib/ -lullib\
CFLAGS = -Wall -W -pipe -Wno-unused-parameter -g -D__64BIT__ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_REENTRANT -D__VERSION_ID__="\"$(VERSION)\"" $(VERSION_SIGN) $(INCLUDES)

#此处还是变量定义,只不过比较长,$(CONFIG)中的CONFIG变量是在Makefile.env中定义的,以下皆同

CXXFLAGS = $(CFLAGS)SOURCES=$(wildcard $(SRC_PATH)/*.cpp)
#wildcard的意思是展开通配符,这里如果不使用wildcard,*.cpp中的”*”将不会被展开。

OBJS=$(patsubst %.cpp,%.o,$(SOURCES))
#patsubst的作用是按条件替换,在这里就是将$(SOURCES)中的所有的以.cpp结尾的字符(%是通配符)替换为以.o结尾

TARGET = makefile_test
all : $(TARGET)
#XXX : YYY的形式表示XXX的生成依赖于YYY的生成,另外XXX还可以在make命令中直接当成参数使用,例如打入make all。这里all是目标,同时由于是第一个声明的目标,因此如果直接打入make而不加参数的话,将等同于执行make all。

.PHONY : clean
#.PHONY的意思是之后的目标是“伪目标”,也就是说这个目标并不是一个文件,这样做一般的目的是为了使该目标命令肯定会被执行(主要是为了防止出现命令与文件重名的情况)比如当你的文件夹中存在clean文件,而当你执行make clean的时候make将检查到clean文件,而该文件又没有任何更新,make便不会执行,这与我们的要求不符。由于.PHONY指明了之后的目标不是实际的文件,因此在执行时make命令会跳过对内置规则的搜索,所以可以起到提高效率的作用。
makefile_test : makefile_test.o makefile_t.o
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(INCLUDES)
makefile_test.o : $(SRC_PATH)/makefile_test.cpp
$(CC) $(CFALGS) -c $(SRC_PATH)/makefile_test.cpp $(INCLUDES)
makefile_t.o: $(SRC_PATH)/makefile_t.cpp
$(CC) $(CFALGS) -c $(SRC_PATH)/makefile_t.cpp $(INCLUDES)
tags :                                 #make tags的时候将执行下面的语句
ctags -R *
clean:                                 #make clean的时候将执行下面的语句
rm -f $(OBJS) makefile_test

#在第二行的表示用什么方式生成上面的对象(或者更直观的,当要生成之前的makefile_test时则直接调用这里的语句)。至于这里的语句就是gcc之类编译器的语法,可以参考相关的man手册……
另外集中介绍一下makefile中自动变量的含义:
$@:当前目标的名字。
$?:列出当前目标所依赖的文件列表中比当前目标文件还要新的文件。
$<:当前依赖文件的名字。
$*:不包括后缀名的当前依赖文件的名字。
$^:所有的依赖目标的集合。以空格分隔,如果在依赖目标中有多个重复的,那么这个变量会去除重复的依赖目标,只保留一份。

另外makefile中还有内置规则,可以通过make -p命令打印出所有的内置规则,利用内置规则可以大大简化makefile文件的编写,当然其内容相当的长……-,-其中比较常用的内置规则如下:
OUTPUT_OPTION = -o $@
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
%.o: %.c

按照这条内置规则,在编写makefile时可以将用于制作目标文件的规则去掉,而只需指定依赖关系就可以了,事实上由于另一条规则的存在,当你的.o文件直接由同名.c文件生成时,连编译依赖都可以不指定了:-)

This entry was posted in linux and tagged . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *