代码之家  ›  专栏  ›  技术社区  ›  Yanick Rochon

多次编译同一源的Makefile

  •  3
  • Yanick Rochon  · 技术社区  · 14 年前

    ** **

    这是一个典型的 Makefile 模板:

    TARGET   = my_prog               # project name
    
    CC       = gcc -o
    CFLAGS   = -Wall
    SOURCES  := $(wildcard *.c)
    INCLUDES := $(wildcard *.h)
    OBJECTS  := $(SOURCES:.c=*.o)
    rm       = rm -f
    
    $(TARGET): $(OBJECTS)
        @$(CC) $(TARGET) $(CFLAGS) $(SOURCES)
        @echo "Compilation complete!"
    
    clean:
        @$(rm) $(TARGET) $(OBJECTS)
        @echo "Cleanup complete!"
    

    问题: 为什么是11号线( @S(CC) $(TARGET) ... make

    回答: 因为问题在默认规则中,第11行可以。

    ** 更新 **

    生成文件

    # project name
    TARGET   = my_prog
    
    CC       = gcc -c
    CFLAGS   = -Wall -I.
    LINKER   = gcc -o
    LFLAGS   = -Wall
    SOURCES  := $(wildcard *.c)
    INCLUDES := $(wildcard *.h)
    OBJECTS  := $(SOURCES:.c=*.o)
    rm       = rm -f
    
    $(TARGET): $(OBJECTS)
        $(LINKER) $(TARGET) $(LFLAGS) $(OBJECTS)
    
    $(OBJECTS): $(SOURCES) $(INCLUDES)
        $(CC) $(CFLAGS) $(SOURCES)
    
    clean:
        $(rm) $(TARGET) $(OBJECTS)
    

    为什么 $(CC) $(CFLAGS) $(SOURCES) 正在执行 时代,哪里 n个

    ** **

    这是解决这个问题的好方法吗?

    $(TARGET): obj
        $(LINKER) $(TARGET) $(LFLAGS) $(OBJECTS)
    
    obj: $(SOURCES) $(INCLUDES)
        $(CC) $(CFLAGS) $(SOURCES)
    
    2 回复  |  直到 14 年前
        1
  •  5
  •   Community Anvaka    7 年前

    指挥部 $(CC) $(CFLAGS) $(SOURCES) 执行n次,因为 规则 执行n次,因为有n个对象要生成,因为 $(TARGET) PHONY 先决条件,其规则执行命令。

    但没有理由这么做。您可以使命令更具选择性,以便它只生成一个实际目标对象。这样,Make就不会浪费时间一遍又一遍地重建同一个对象,如果更改了一个或两个源文件,Make将只重建相关对象,而不是所有对象:

    $(OBJECTS): %.o : %.c $(INCLUDES)
      $(CC) $(CFLAGS) $<
    

    这个规则是保守的——它假设每个对象都依赖于每个报头,所以它有时会不必要地重建内容。如果你知道真正的依赖关系,你可以手工做得更好,或者用更先进的技术自动做得更好。

    编辑:

    你的“更新2”是个不错的解决方案,但我建议你加上一行

    .PHONY: obj
    

    告诉Make不会有名为“obj”的文件。否则Make将运行 obj 每次都是规则,试图建立那个文件。

    这仍然有一个问题,如果你改变一个源文件,例如。 foo.c ,Make将重建 全部的

    这个 $< automatic variable foo.o ,它将评估为 食品 .

    编辑:

    Jack Kelly (诅咒他!)已经指出我对虚假目标的工作方式是错误的 规则将永远运行,而 TARGET 规则,无论源文件是否已更改。所以“更新2”方法是有效的,但很粗糙。

        2
  •  1
  •   JasonWoof    14 年前

    看起来您没有创建.o文件的规则,因此make使用默认规则。

    试着说:

    @echo "starting compilation"
    

    在第11行构建命令之前的行上

    您可以看到“开始编译”是在gcc行之后输出的。

    或许第10行应该是:

    $(TARGET): $(SOURCES)