我如何更正我的 Makefile 以便它构建我所有的源文件? (答案:检查隐藏的选项卡)

How do I correct my Makefile so that it builds all my source files? (Answer: check for hidden tabs)

在使用 clang v7.0.2 和 make v3.81 的 OS X v10.10.5 中,我在当前项目中遇到了一些我认为是直接的 Makefile 的问题。

当我再添加一对 .h/.c 文件时出现了问题——之前一切似乎都运行良好。现在 make 不会 'pick up' 并构建新的源代码,即使我可以成功地手动构建它。 Make 似乎认为 .o 文件是最新的,即使它似乎根本不存在。

这里是我的相关项目目录的转储以供参考:

$ ls -R
.:
LICENSE  Makefile  README.md  docs  include  src

./docs:
ptscheme.ebnf

./include:
lispbool.h  lispchar.h  lisperr.h  lispint.h  lisppair.h  lispstr.h memmanager.h  ptscheme.h

./src:
lispbool.c  lispchar.c  lisperr.c  lispint.c  lisppair.c  lispstr.c  memmanager.c  ptscheme.c

而且,这是我的 Makefile 的内容:

$ cat Makefile
# Basic Makefile for ptscheme

# Set our paths to traditional locations for files:
#      ./src - c source files
#      ./include - c header files

vpath %.c src
vpath %.h include

CC = clang
CPPFLAGS = -std=c99 -Wall -g -I include
objects = ptscheme.o memmanager.o lispbool.o lispchar.o lispint.o \
          lispstr.o lisperr.o lisppair.o

all: ptscheme

ptscheme: $(objects)
    clang $(CPPFLAGS) -o ptscheme $(objects)

ptscheme.o: ptscheme.h memmanager.h

memmanager.o: ptscheme.h memmanager.h

lispbool.o: ptscheme.h memmanager.h lispbool.h

lispchar.o: ptscheme.h memmanager.h lispchar.h

lispint.o: ptscheme.h memmanager.h lispint.h

lispstr.o: ptscheme.h memmanager.h lispstr.h

lisperr.o: ptscheme.h memmanager.h lisperr.h

lisppair.o: ptscheme.h memmanager.h lisppair.h

# clean - Implement standard 'clean' target to clean up after ourselves

.PHONY: clean
clean:
    rm -f ptscheme $(objects)

这是我尝试 运行 时发生的情况:

   $ make
   clang  -std=c99 -Wall -g -I include  -c -o ptscheme.o src/ptscheme.c
   clang  -std=c99 -Wall -g -I include  -c -o memmanager.o src/memmanager.c
   clang  -std=c99 -Wall -g -I include  -c -o lispbool.o src/lispbool.c
   clang  -std=c99 -Wall -g -I include  -c -o lispchar.o src/lispchar.c
   clang  -std=c99 -Wall -g -I include  -c -o lispint.o src/lispint.c
   clang  -std=c99 -Wall -g -I include  -c -o lispstr.o src/lispstr.c
   clang  -std=c99 -Wall -g -I include  -c -o lisperr.o src/lisperr.c
   clang   ptscheme.o memmanager.o lispbool.o lispchar.o lispint.o lispstr.o lisperr.o lisppair.o   -o ptscheme
   clang: error: no such file or directory: 'lisppair.o'
   make: *** [ptscheme] Error 1

显然,lisppair.o 没有被构建,即使我在我的 Makefile 中有一个条目,它遵循与其他条目相同的模式。

这是一个验证文件丢失的目录:

$ ls -al *.o
-rw-r--r-- 1 ptdecker  4392 Dec 22 22:00 lispbool.o
-rw-r--r-- 1 ptdecker  3360 Dec 22 22:00 lispchar.o
-rw-r--r-- 1 ptdecker  3376 Dec 22 22:00 lisperr.o
-rw-r--r-- 1 ptdecker  3344 Dec 22 22:00 lispint.o
-rw-r--r-- 1 ptdecker  3776 Dec 22 22:00 lispstr.o
-rw-r--r-- 1 ptdecker  3244 Dec 22 22:00 memmanager.o
-rw-r--r-- 1 ptdecker 15324 Dec 22 22:00 ptscheme.o

当我尝试让 运行 只是 lisppair.o 收据时,make 告诉我它认为我想要的目标文件是最新的 (!?):

$ make lisppair.o
make: `lisppair.o' is up to date.

我可以手动编译:

$ clang -std=c99 -Wall -g -I include -c -o lisppair.o src/lisppair.c

生成目标文件:

$ ls -al *.o
-rw-r--r-- 1 ptdecker  4392 Dec 22 22:00 lispbool.o
-rw-r--r-- 1 ptdecker  3360 Dec 22 22:00 lispchar.o
-rw-r--r-- 1 ptdecker  3376 Dec 22 22:00 lisperr.o
-rw-r--r-- 1 ptdecker  3344 Dec 22 22:00 lispint.o
-rw-r--r-- 1 ptdecker  5664 Dec 22 22:03 lisppair.o
-rw-r--r-- 1 ptdecker  3776 Dec 22 22:00 lispstr.o
-rw-r--r-- 1 ptdecker  3244 Dec 22 22:00 memmanager.o
-rw-r--r-- 1 ptdecker 15324 Dec 22 22:00 ptscheme.o

然后让我重新运行 使我的最终构建和链接完成:

$ make
clang   ptscheme.o memmanager.o lispbool.o lispchar.o lispint.o lispstr.o lisperr.o lisppair.o   -o ptscheme

让我最终到达我想去的地方:

$ ./ptscheme
>

感谢您的帮助和反馈!显然,我遗漏了一些基本的东西。

可以找到所有这些的完整来源 in my github repository

只有查看 github 中的原始 Makefile,问题才会明显。第 37 行(# clean 注释之后的行)有一个错误的选项卡。删除该选项卡,您应该可以开始了。