【问题标题】:Makefile to rebuild during header file changesMakefile 在头文件更改期间重建
【发布时间】:2018-07-03 11:01:09
【问题描述】:

我正在尝试为项目编写 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)

请指导我。

【问题讨论】:

  • 让$(CODE1_OBJECTS) 依赖 $(CODE1_HEADERS)?如果可以是多个目标文件和头文件,则必须明确列出依赖关系。
  • 最好使用-MD -MF 到gcc 的键来生成头文件依赖文件,然后将它们包含到您的makefile 中。我已经在我的非递归制作模板中做到了这一点,你可以看看并可能使用我的模板:github.com/igagis/prorab/blob/master/wiki/…

标签: c linux gcc makefile


【解决方案1】:

你的所作所为对我来说似乎很不寻常。

典型的方法是有一个可以手动编写或自动评估的源文件列表,例如通过从一个或多个目录中捕获所有 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 文件的规则:

%.o : %.c

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

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

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

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

【讨论】:

  • $(CPPFLAGS) 应该是 $(CFLAGS),因为它编译的是 C 代码而不是 C++ 代码
  • @ChrisTurner:解决了这个问题!谢谢
【解决方案2】:

不需要规则中的 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)

【讨论】:

  • 感谢您提供更简单的解决方案!
猜你喜欢
  • 2019-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多