这是我为编译一个小程序而制作的简单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)/*
似乎没事,但是当我尝试构建我的可执行文件时,我得到了这个输出:
---- io.o ----
gcc -g -I include -c src/io.c -o obj/io.o
---- alea.o ----
gcc -g -I include -c src/alea.c -o obj/alea.o
---- tri.o ----
gcc -g -I include -c src/tri.c -o obj/tri.o
---- main.o ----
gcc -g -I include -c src/main.c -o obj/main.o
--------------LINKING----------------
ls obj
alea.o io.o main.o tri.o
gcc -g -I include io.o alea.o tri.o main.o -o bin/main
gcc: error: io.o: No such file or directory
gcc: error: alea.o: No such file or directory
gcc: error: tri.o: No such file or directory
gcc: error: main.o: No such file or directory
gcc: fatal error: no input files
compilation terminated.
make: *** [main] Error 4
正如您所看到的,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
?
答案 0 :(得分:0)
你的依赖是错误的。例如,在main
的规则中,您告诉它它取决于本地目录中的.o
个文件。 .o
文件依次具有本地规则,该规则依赖于$(SRC)
中的文件,但编译命令在$(OBJ)
中生成文件。
这无效。
您可以通过在.o
文件所在的子目录中生成.c
来避免此类问题。通常你会有一个单独的makefile,这样你就可以通过递归调用进入该目录。像
objects : src
$(MAKE) -C src
如果你真的想在一个单独的目录中生成你的可执行文件,那么该目录中应该有一个makefile,你会递归到那个。
答案 1 :(得分:0)
基本上改变:
%.o : $(SRC)/%.c
@echo "----" $@ "----"
$(COMPILER) -c $< -o $(OBJ)/$@
要:
$(OBJ)/%.o: $(SRC)/%.c
$(COMPILER) $< -o $@