【问题标题】:GNU make dependency issueGNU make 依赖问题
【发布时间】:2012-04-24 14:10:23
【问题描述】:

为了简单起见,假设我有以下文件夹:

  • ./src/ 有很多 .c 文件
  • ./obj/ 带有许多 .obj 文件
  • ./output/ 我要构建的二进制文件

我的makefile如下:

all: init mybin

# init commands
init:
    mkdir obj
    mkdir output

mybin:  project1 project2 project3
    $(CC) src/misc.c ... etc
    $(LK) obj/first.obj obj/second.obj obj/third.obj obj/four.obj obj/five.obj obj/six.obj obj/seven.obj obj/eight.obj obj/nine.obj -o output/myapp.bin

project1: obj/first.obj obj/second.obj obj/third.obj

obj/first.obj: src/first.c
    $(CC) first.c ... etc

obj/second.obj: src/second.c
    $(CC) obj/second.c ... etc

obj/third.obj: src/third.c
    $(CC) obj/third.c ... etc


project2:   obj/four.obj obj/five.obj obj/six.obj

obj/four.obj: src/four.c
    $(CC) four.c ... etc

obj/five.obj: src/five.c
    $(CC) obj/five.c ... etc

obj/six.obj: src/six.c
    $(CC) obj/six.c ... etc


project3:   obj/seven.obj obj/eight.obj obj/nine.obj

obj/seven.obj: src/seven.c
    $(CC) seven.c ... etc

obj/eight.obj: src/eight.c
    $(CC) obj/eight.c ... etc

obj/nine.obj: src/nine.c
    $(CC) obj/nine.c ... etc

我第一次运行make all,所有编译的东西都找到了。然后我做了:

$ touch src/four.c
$ make all
$

但是make 没有编译任何东西就退出了。我猜它没有检测到其中一个 .c 文件已更改,但是我看不出我的依赖项有什么问题。

我所期望的:
touching src/four.c 应该标记为 obj/four.obj 已过时,project2 也应标记为已过时,因此也将 mybin 标记为已过时。这个链应该会触发src/four.cobj/four.obj 的新编译,然后是整个项目的新链接。

【问题讨论】:

  • 运行 make -d all 看看有什么过时的
  • 它尝试了很多没有意义的“隐含先决条件”。我正在尝试构建一个名为 FW.mot 的文件,make 试图找到不存在的 FW.mot.cFW.mot.ccFW.mot.F !!!
  • 好吧,grep 相关文件,如果它说 FW.mot 是最新的,然后检查所有依赖项,如果应该触发重建的那个不存在,那么你没有列出它在 Makefile 中

标签: gnu-make


【解决方案1】:

您是否指定了编译的输出文件(可能是-o 选项)?默认情况下(对于大多数工具链),编译 .c 文件会生成 .o 文件,而不是 .obj 文件。

更新。

要在某些先决条件更改时获取 Make 更新目标,您必须提供 确切 依赖关系 文件之间 就 Make 使用时间戳来确定文件是否已更改。

也就是说,allinit 可以保留为所谓的.PHONY targets,但最好将其余目标设为文件。

OUT_DIR := ./output
SRC_DIR := ./src
OBJ_DIR := ./obj

MYBIN := $(OUT_DIR)/myapp.bin

OBJS := $(addprefix $(OBJ_DIR)/, \
    first.obj \
    second.obj \
    third.obj \
    four.obj \
    five.obj \
    six.obj \
    seven.obj \
    eight.obj \
    nine.obj)

.PHONY : all mkdir-output mkdir-obj
all : $(MYBIN)

mkdir-output :
    @mkdir -p $(OUT_DIR)

mkdir-obj :
    @mkdir -p $(OBJ_DIR)

$(MYBIN) : $(OBJS) | mkdir-output
    $(LK) $^ -o $@

$(OBJS) : | mkdir-out
$(OBJS) : $(OBJ_DIR)/%.obj : $(SRC_DIR)/%.c
    $(CC) $< -object=$@ $(CC_OPT)

最后一条规则是 GNU Make 的static pattern rule。管道符号| 之后的mkdir-xxx 先决条件是order-only

【讨论】:

  • 是的,我做到了。这是针对特定硬件的专有 C 编译器。命令行是:$(CC) ./src/whatever.c -object=./obj/whatever.obj $(CC_OPT)。每个$(CC) 命令都会在正确的文件夹中成功创建其.obj 文件。问题是make 没有将依赖于touched .c 文件的.obj 文件标记为已过期。
  • 谢谢。我没有很好地利用.PHONY 目标。我添加了一些 @touch dummy_project1 来帮助 make 了解构建依赖项。我也清理了一下,现在它工作正常。非常感谢。
猜你喜欢
  • 2010-10-09
  • 2015-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-22
  • 1970-01-01
相关资源
最近更新 更多