Linker Makefile-make can';链接时找不到依赖项

Linker Makefile-make can';链接时找不到依赖项,linker,makefile,Linker,Makefile,这里是一个简单的makefile,我是为了编译一个小程序而做的 INCLUDE = include OBJ = obj SRC = src BIN = bin COMPILER = gcc -g -I $(INCLUDE) VPATH = obj main : io.o alea.o tri.o main.o @echo "--------------LINKING----------------" ls obj $(COMPILER) $

这里是一个简单的makefile,我是为了编译一个小程序而做的

INCLUDE = include
OBJ = obj
SRC = src
BIN = bin
COMPILER = gcc -g -I $(INCLUDE)

VPATH = obj


main :  io.o alea.o tri.o main.o
        @echo "--------------LINKING----------------"
        ls obj
        $(COMPILER) $^ -o $(BIN)/$@

%.o : $(SRC)/%.c
        @echo "----" $@ "----"
        $(COMPILER) -c $< -o $(OBJ)/$@

clean:
        @echo "----Cleaning----"
        rm -v $(OBJ)/*
        rm -v $(BIN)/*
如您所见,
make
没有找到文件
.o
的正确路径。我使用
ls
来显示文件夹obj中的所有文件都已存在并准备好链接,但在执行主规则时,
make
意外地找不到它们(即使我设置了
VPATH=obj

但是当我第二次尝试时(当文件已经编译并且只需要链接时),一切都很顺利:

--------------LINKING----------------
ls obj
alea.o  io.o  main.o  tri.o
gcc -g -I include  obj/io.o obj/alea.o obj/tri.o obj/main.o -o bin/main

为什么第一次编译时会忽略
VPATH

您的依赖项是错误的。例如,在
main
的规则中,您告诉make它依赖于本地目录中的
.o
文件。
.o
文件又有一个本地规则,该规则依赖于
$(SRC)
中的文件,但其中compile命令生成
$(OBJ)
中的文件

这不行

您可以通过在与
.c
文件相同的子目录中生成
.o
来避免此类问题。通常,您会在那里有一个单独的makefile,这样您就可以通过递归调用进入该目录进行make。差不多

objects : src
       $(MAKE) -C src
如果您确实希望在单独的目录中生成可执行文件,那么该目录中也应该有一个makefile,您可以递归地进入该目录。

基本更改:

%.o : $(SRC)/%.c
        @echo "----" $@ "----"
        $(COMPILER) -c $< -o $(OBJ)/$@
%.o:$(SRC)/%.c
@回声“----$@---”
$(编译器)-c$<-o$(OBJ)/$@
致:

$(OBJ)/%.o:$(SRC)/%.c
$(编译器)$<-o$@

是,但是
VPATH
应该做这项工作,不是吗?不,我认为这还不够。它告诉make在哪里搜索,而不是在哪里生产。这可能是make然后在第二次运行时发现问题的原因。请您更详细地解释一下好吗?(我对makefile很陌生)。如果我没有错的话,您是说makefile在错误的位置生成.o文件。如果第二条规则中的gcc输出是正确的目录,这怎么可能呢?此外,在链接之前,
ls
显示文件位于正确的位置。发生这种情况是因为VPATH的计算在一开始时只执行一次,而没有编译任何内容吗?这是迄今为止我能找到的唯一解释。据我所知,
VPATH
仅在开始时被扫描,以查找不存在的文件,通常是源文件。它不会查找最终可能由规则生成的中间文件。您生成
.o
文件的规则就是这样,make认为您实际上是在本地目录中生成它们。
%.o : $(SRC)/%.c
        @echo "----" $@ "----"
        $(COMPILER) -c $< -o $(OBJ)/$@
$(OBJ)/%.o: $(SRC)/%.c
        $(COMPILER) $< -o $@