Red
Red

Reputation: 27

why isn't there a -g option(gdb) when i execute make even if i wrote it in makefile

I am writting a makefile for my tiny project,here is my 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

but when i execute make,it appears that no -g option,thus i can't debug with gdb here is part of the output of make:

gcc -I.   -c -o lisod.o lisod.c
gcc -I.   -c -o csapp.o csapp.c

Upvotes: 0

Views: 46

Answers (1)

John Bollinger
John Bollinger

Reputation: 181574

but when i execute make,it appears that no -g option,thus i can't debug with gdb

If you look carefully at your output, you will realize that the issue is not so much the -g flag specifically, but that the pattern rule you've provided is not being used at all. The fact that the -I. option appears first instead of last establishes this.

What you are getting is the default rule for building .o files from corresponding .c files. Rules you provide override built-in ones when both apply, but in make's analysis, your pattern rule does not (always) apply because it designates prerequisites (at least y.tab.h) that may not initially exist and for which there is no build rule. (See How Patterns Match in the GNU Make manual.)

You're in fact running into a classic problem with make's model of the world: it doesn't deal very cleanly with recipes that generate multiple outputs that serve as prerequisites for other rules. You might be interested in the Automake manual's discussion of this topic, which is mostly addressed generically at conforming make implementations, and which provides a series of increasingly complex (and increasingly flexible) rules. This simple pattern is recommended as "enough for most cases":

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 $@ $<

Note that I moved the CFLAGS to the beginning of the compile command instead of the end. Though it probably does not make a difference in your case, it is not entirely stylistic, as the order of options on the build command line is significant. That effects link commands greatly, but it can effect compile commands too, depending on the options involved.

Update:

As long as you're relying on feature specific to GNU make (pattern rules) anyway, however, you might as well make full use of them. As @MadScientist observed in comments, GNU make treats pattern rules with multiple targets differently than it (and other makes) treat ordinary rules with multiple targets: it understands and expects one execution of the rule's recipe to create all the targets matched to one set of prerequisites via the pattern.

Thus, if you're going to use pattern rules at all, then as MS observes, this is even better than the above "enough for most cases" alternative:

%.tab.c %.tab.h : parser.%
    yacc -d $^

%.o: %.c $(DEPS)
    $(CC) $(CFLAGS) $(FLAGS) -c -o $@ $<

Upvotes: 1

Related Questions