我正在为我的小项目编写一个makefile,这是我的makefile:
CC=gcc
CFLAGS=-I.
DEPS = parse.h y.tab.h
OBJ = y.tab.o lex.yy.o parse.o
FLAGS = -g -Wall
LDFLAGS = -lpthread
default:all
all: lisod
lex.yy.c: lexer.l
flex $^
y.tab.c: parser.y
yacc -d $^
%.o: %.c $(DEPS)
$(CC) $(FLAGS) -c -o $@ $< $(CFLAGS)
example: $(OBJ) example.o
$(CC) -o $@ $^ $(CFLAGS)
lisod: lisod.o csapp.o $(OBJ) $(LDFLAGS)
$(CC) -o $@ $^ $(CFLAGS) $(FLAGS)
# hello:
# echo hello
clean:
rm -f *~ *.o example lex.yy.c y.tab.c y.tab.h lisod
但是当我执行make时,似乎没有-g选项,因此我无法使用gdb进行调试 这是make输出的一部分:
gcc -I. -c -o lisod.o lisod.c
gcc -I. -c -o csapp.o csapp.c
答案 0 :(得分:1)
但是当我执行make时,似乎没有-g选项,因此我无法使用gdb进行调试
如果仔细查看输出,您将意识到问题不仅仅在于-g
标志,而是您提供的模式规则根本没有被使用 。 -I.
选项首先出现而不是最后出现的事实证明了这一点。
您得到的是从相应的.c文件构建.o文件的默认规则。您提供的规则会同时覆盖内置规则,但在make
的分析中,您的模式规则不会(始终)适用,因为它指定了最初可能不存在的先决条件(至少为y.tab.h
)并且没有构建规则。 (请参阅GNU Make手册中的How Patterns Match。)
实际上,您在make
的世界模型中遇到了一个经典问题:它不能很干净地处理生成多个输出(作为其他规则的先决条件)的配方。您可能对the Automake manual's discussion of this topic感兴趣,该问题通常在遵循make
的实现中得到通用解决,并且提供了一系列越来越复杂(也越来越灵活)的规则。建议将这种简单的模式作为“足够用于大多数情况”:
y.tab.c: parser.y
yacc -d $^
# Add this, so make knows where y.tab.h comes from:
y.tab.h: y.tab.c
# I assume that parse.h is an ordinary source, not a generated one
%.o: %.c $(DEPS)
$(CC) $(CFLAGS) $(FLAGS) -c -o $@ $<
请注意,我将CFLAGS
移到了编译命令的开头而不是结尾。尽管这可能不会对您造成影响,但是由于构建命令行中的选项顺序很重要,因此它并不完全是风格。这会大大影响链接命令,但也可能会影响编译命令,具体取决于所涉及的选项。
更新:
无论如何,只要您依赖于GNU make
(模式规则)特有的功能,您就可以充分利用它们。正如@MadScientist在评论中观察到的那样,GNU make
对具有多个目标的模式规则的处理方式不同于对它(和其他make
s对具有多个目标的普通规则的处理方式):它理解并希望执行该规则的配方能够通过模式创建与一组先决条件匹配的 all 目标。
因此,如果您完全要使用模式规则,那么正如MS所观察到的,这甚至比上述“大多数情况下足够”替代方案更好:
%.tab.c %.tab.h : parser.%
yacc -d $^
%.o: %.c $(DEPS)
$(CC) $(CFLAGS) $(FLAGS) -c -o $@ $<