1

我已按照本教程进行操作。它解释了制作依赖关系的 Makefile。我制作了以下 Makefile,它根据以下目录结构工作:

folder--|Makefile
    |src----|(all .c and .h files here)
    |obj----|(all objects file are made here)
    |bin----|(target is made here)

生成文件是:

TARGET  =   exec

CC      =   gcc
CFLAGS  =   -g -I.
LINKER  =   gcc -o
LFLAGS  =   -I. -lm -lpthread

BINDIR  =   bin
OBJDIR  =   obj
SRCDIR  =   src
INTERFACE = interface
STD =   -std=c99

PROGRAMSOURCES  :=  $(wildcard $(SRCDIR)/*.c)
PROGRAMINTERFACE:=  $(wildcard $(INTERFACE)/*.h)
OBJECTS     :=  $(PROGRAMSOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)

$(BINDIR)/$(TARGET) :   $(OBJECTS)
    $(LINKER) $@ $(LFLAGS) $(OBJECTS) $(STD)

#pull the dependencies to the .o files
-include $(OBJECTS:.o=.d)

#the -o $@ says to put the output of the compilation in the file named on the left side of the :.
#the $< is the first item in the dependencies list. Basically the name of the .c file which is to be compiled.
$(OBJECTS)      :   $(OBJDIR)/%.o :$(SRCDIR)/%.c
    $(CC) $(CFLAGS) -c $< -o $@ $(STD)
    $(CC) $(CFLAGS) -MM $< > $*.d
    @mv -f $*.d $*.d.tmp             #changes file name
    @sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d    #Unable to understand
    @sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
     sed -e 's/^ *//' -e 's/$$/:/' >> $*.d      #Unable to understand
    @rm -f $*.d.tmp

.PHONY  :   run
run     :
    ./$(BINDIR)/$(TARGET) ${TYPE} ${INP_FILE}

print:
    @echo $(OBJECTS)

我知道它正在尝试预处理临时文件以生成自动依赖项。我无法理解的是它是如何完成的。这是我想要解释的两行:

@sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d    #Unable to understand
@sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
 sed -e 's/^ *//' -e 's/$$/:/' >> $*.d      #Unable to understand

我以前从未使用sed过,所以我遇到了问题。

任何帮助表示赞赏。

4

1 回答 1

3

假设您是从 构建obj/foo.osrc/foo.c,因此该文件foo.d.tmp包含:

foo.o: src/foo.c src/foo.h src/bar.h

现在第一个sed声明:

@sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d

“读取foo.d.tmp,将所有内容取一个冒号并将其更改为 'foo.o',然后将结果写入foo.d.” 所以现在foo.d包含:

foo.o: src/foo.c src/foo.h src/bar.h

(在这种情况下没有变化。)现在下一个命令:

@sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $*.d

“阅读foo.d.tmp,删除所有(包括)冒号,\如果有一个则删除尾随。获取结果并将每个单词(即每个先决条件)放在自己的行中。然后对于每一行,删除前导空格,放入最后一个冒号,并将结果附加到foo.d." 所以现在foo.d包含:

foo.o: src/foo.c src/foo.h src/bar.h
src/foo.c:
src/foo.h:
src/bar.h:

这个想法是为每个先决条件创建一个空规则,这样如果代码发生了变化并且某个先决条件不再需要——也不再存在——但它仍然列在 oldfoo.d中,Make 不会因为出现而恐慌无法构建它。

于 2013-04-07T19:31:46.073 回答