Makefile在头文件更改期间重建

时间:2018-01-24 11:49:37

标签: c linux gcc makefile

我正在尝试为项目编写Makefile。有了这个,只要任何C文件发生变化,我就能够构建项目。但是,当头文件发生更改时,它不会构建。

所以,我正在尝试使用Makefile来实现更简单的目录结构,如果它有效,我打算在主项目中做同样的事情。

目录结构是,

src -> code1 -> file1.c
src -> code2 -> file2.c
src -> code1inc -> file1.h
src -> code2inc -> file2.h

所有文件应该构建并提供单个二进制文件FinalBin

当file1.h发生变化时,它必须只构建file1.c。 如何通过Makefile强制执行此操作?

这是我目前的Makefile。

CC = gcc

CFLAGS = $(INCLUDES)

TARGET = FinalBin

SOURCES := $(wildcard *.c)

PATH_CODE1 = src/code1
PATH_CODE2 = src/code2

CODE1_SOURCES := $(wildcard $(PATH_CODE1)/*.c)
CODE1_OBJECTS := $(patsubst %.c,%.o,$(CODE1_SOURCES))

CODE2_SOURCES := $(wildcard $(PATH_CODE2)/*.c)
CODE2_OBJECTS := $(patsubst %.c,%.o,$(CODE2_SOURCES))

PATH_CODE1INC = src/code1inc
PATH_CODE2INC = src/code2inc

INCLUDES = -I$(PATH_CODE1INC) \
                -I$(PATH_CODE2INC)

CODE1_HEADERS := $(wildcard $(PATH_CODE1INC)/*.h)
CODE2_HEADERS := $(wildcard $(PATH_CODE2INC)/*.h)

all: $(TARGET)

obj1 = $(CODE1_OBJECTS) $(CODE1_HEADERS)
obj2 = $(CODE2_OBJECTS) $(CODE2_HEADERS)

$(TARGET) : $(obj1) $(obj2)
        $(CC) $^ -o $@

clean:
        rm $(TARGET) $(CODE1_OBJECTS) $(CODE2_OBJECTS)

请指导我。

2 个答案:

答案 0 :(得分:2)

你所做的事似乎不寻常。

典型的方法是拥有一个源文件列表,可以手动编写或自动评估,例如:通过从一个或多个目录中捕获所有c文件。这就是你已经做过的事:CODE1_SOURCES := $(wildcard $(PATH_CODE1)/*.c)

但是应该自动生成每个文件的依赖项。例如,gcc提供了' -M'或者' -MM'重建所谓的依赖文件的选项,通常命名为' .d'或者' .dep'

可以在此处找到完整流程的好文档:

http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#basic

对于简单的情况,这是从上述文件中得到的一个例子:

SRCS = foo.c bar.c ...

%.o : %.c
    @$(MAKEDEPEND); \
      cp $*.Td $*.d; \
      sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
          -e '/^$$/ d' -e 's/$$/ :/' < $*.Td >> $*.d; \
      rm -f $*.Td
    $(COMPILE.c) -o $@ $<

include $(wildcard $(SRCS:.c=.d))

如果使用gcc MAKEDEPEND可以是:

MAKEDEPEND = gcc -M $(CPPFLAGS) -o $*.Td $<

一个简短的解释:

通常,您可以使用以下命令定义%。。文件生成%.o文件的规则:

%.o : %.c

作为该规则的第一步,如果必须编译源,则始终构建depfile,通常如果%.o文件不存在或者依赖项比%.o文件更新,则:

gcc -M $(CFLAGS) -o $*.Td $<

摘录中给出的最后一行确实包含了所有这些自动生成的依赖文件,只需将它们包含在Makefile本身中:

include $(wildcard $(SRCS:.c=.d))

答案 1 :(得分:1)

不需要规则中的sed语句。 Gcc支持-MF选项来控制依赖项输出文件。

CC = gcc
SRCS = foo.c bar.c ...
OBJS = $(SRCS:%.c=%.o)
DEPS = $(wildcard $(OBJS:%=%.d))

%.o : %.c
    $(CC) -MD -MP -MF "$@.d" -o $@ -c $<

include $(DEPS)