makefile 可以自动推导生成.o规则

来源:互联网 发布:mac如何全选照片 编辑:程序博客网 时间:2024/05/18 22:45


CC      = gcc
 CPP     = g++
 RM      = rm -rf

## debug flag
 DBG_ENABLE   = 0

## source file path
 SRC_PATH   := .

## target exec file name
 TARGET     := exe

## get all source files
 SRCS         += $(wildcard $(SRC_PATH)/*.cpp)

## all .o based on all .c
 OBJS        := $(SRCS:.cpp=.o)


 ## need libs, add at here
 LIBS :=

## used headers  file path
 INCLUDE_PATH := ./

## used include librarys file path
 LIBRARY_PATH := /lib

## debug for debug info, when use gdb to debug
 ifeq (1, ${DBG_ENABLE})
     CFLAGS += -D_DEBUG -O0 -g -DDEBUG=1
 endif

## get all include path
 CFLAGS  += $(foreach dir, $(INCLUDE_PATH), -I$(dir))

## get all library path
 LDFLAGS += $(foreach lib, $(LIBRARY_PATH), -L$(lib))

## get all librarys
 LDFLAGS += $(foreach lib, $(LIBS), -l$(lib))

 
build:$(OBJS)
# $(CPP) -c $(CFLAGS) $(SRCS)
 $(CPP) $(CFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS)


#可自动推导.o文件生成规则 
 
sinclude $(SRCS:.cpp=.d)

%d: %cpp
 @echo "create depend"
 $(CPP) -MM $(CFLAGS) $< > $@.$$$$; \
 sed 's,\($*\)\.o[ :]*,\1.o $@ ,g' < $@.$$$$ > $@; \
 $(RM) $@.$$$$
   
#$(OBJS):$(SRCS)
# $(CPP) -c $(CFLAGS) $(SRCS)
 
clean:
 $(RM) $(OBJS) $(TARGET)


    sinclude $(SOURCES:.c=.d)
    %d: %c
          @echo "create depend"
          $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
          sed 's,\($*\)\.o[ :]*,\1.o $@ ,g' < $@.$$$$ > $@; \
          $(RM) $@.$$$$


 sinclude $(SOURCES:.c=.d) 这一行是非常关键的,它在当前Makefile里去include另外的Makefile. 这里“另外”的Makefile是将SOURCES变量里所有.c替换成.d。 在我的例子里就是dList.d memory.d test.d debug.d. 意思就是执行到这里
    的时候先去依次执行dList.d memory.d test.d debug.d. 这里的.d文件就是包含了每个.c文件自动生成的对头文件的依赖关系。这个依赖关系将由下面的%d:%c来完成。
   
    %d: %c
    此规则的含义是:所有的.d文件依赖于同名的.c文件。
第一行;使用c编译器自自动生成依赖文件($<)的头文件的依赖关系,并输出成为一个临时文件,“$$$$”表示当前进程号。如果$(CC)为GNU的c编译工具,产生的依赖关系的规则中,依赖头文件包括了所有的使用的系统头文件和用户定义的头文件。如果需要生成的依赖描述文件不包含系统头文件,可使用“-MM”代替“-M”。
第二行;使用sed处理第二行已产生的那个临时文件并生成此规则的目标文件。经过这一行后test.d里内容如下:test.o: test.c aaron.h dList.h debug.h 其他.d里以此类推。
第三行;删除临时文件。

    到这里基本的意义弄明白了,但是让我不解的是%d: %c这个依赖的规则怎么能被执行到的?按照我的理解Makefile在执行时首先检查终极目标main是否存在,如果不存在则建立(根据main的依赖规则),如果存在在需要查看
    main的依赖文件是否存在并且是最新的,这我的例子里就是要看test.o dList.o memory.o debug.o是否存在且最新。这样追下去是否没有%d: %c什么事啊, .d文件也应该不存在或者说是空的。尽管我们include了.d文件,但是没有依赖规则去执行它啊。后来仔细阅读了
    Makefile文件的重建才明白了。
    Makefile如果由其它文件重建(这里我的Makefile include了所有.d文件,.d也可以看成是一个Makefile),Makefile在读入所有其他makefile文件(.d)之后,首先将所读取的每个makefile(.d)作为一个目标,寻找更新它们的规则。同样
    如果此目标不存在则根据依赖规则重新创建。在例子里其实.d文件开始并不存在,所以当Makefile在include这些.d文件时首先看.d存在不,不存在就要去寻找.d的依赖文件和规则。这里就找到了%d: %c从而创建出真正的.d文件。其实这里的关键点就是对于
    include了理解,它是把include的文件首先当成一个目标,然后要去寻找其依赖文件和规则的,而不是我事先想象的简单的把其他文件的内容包含过来。
    到此,问题解决,基本达到预期。





0 0
原创粉丝点击