views:

95

answers:

4

New to the idea of makefiles. Here is my Makefile:

.PHONY: all homework1
CFLAGS= -g -O0 -Wall -Werror -Wno-unused-function
LDFLAGS= -lm

all : homework1

homework1 : program.tab.o program.lex.o
%.o : %.c
    gcc -o$@ -c $(CFLAGS) $<
%.lex.c : %.lex %.tab.h
    flex -o$@ $<
%.tab.c %.tab.h : %.y
    bison --verbose -o$@ -d $<

Whenever I try to compile, I get the warning make: Circular program.lex <- program.lex.o dependency dropped. I don't see how program.lex is dependent on program.lex.o at all in the makefile. I see how the dependency tree is about 4 layers deep, but it doesn't look circular.

How can I better write my makefile?

+1  A: 

run make with -d:

Considering target file `all'.
 File `all' does not exist.
  Considering target file `homework1'.
   File `homework1' does not exist.
    Considering target file `program.lex.o'.
     File `program.lex.o' does not exist.
     Looking for an implicit rule for `program.lex.o'.
     Trying pattern rule with stem `program.lex'.
     Trying implicit prerequisite `program.lex.c'.
     Found an implicit rule for `program.lex.o'.
      Considering target file `program.lex.c'.
       Looking for an implicit rule for `program.lex.c'.
       Trying pattern rule with stem `program'.
       Trying implicit prerequisite `program.lex'.
       Found an implicit rule for `program.lex.c'.
        Considering target file `program.lex'.
         Looking for an implicit rule for `program.lex'.
         Trying pattern rule with stem `program.lex'.
         Trying implicit prerequisite `program.lex.o'.
         Found an implicit rule for `program.lex'.
make: Circular program.lex <- program.lex.o dependency dropped.

there is implicit link rule which gets invoked, not lex I originally put down

get rid off ".lex.*" extensions

aaa
No - it's the rule that tries to link programs made from a single object file.
Jack Kelly
+1  A: 

The trouble is that there is an implicit rule in Make (well, in GNUMake anyway) for linking a single object file to build en executable. Your makefile says nothing about how to build program.lex, so Make falls back on the implicit rule to build it from program.lex.o.

Since your your layout seems to depend on having program.lex to begin with, you can suppress the implicit rule by adding your own rule for program.lex (which does nothing):

program.lex:;
Beta
Nice trick to silence the implicit rule. I hadn't seen that before.
Jack Kelly
A: 

My immediate reaction was that you need an action after the rule that says homework1: program.tab.o program.lex.o:

 homework1:  program.tab.o program.lex.o
         ${CC} -o $@ program.tab.o program.lex.o ${LDFLAGS}

However, since you've also marked homework1 as .PHONY, maybe you are not ready to link the program yet. But your problem reproduces...

Conventionally, the source for Lex (or Flex) is kept in a .l file, not in a .lex file, so I changed the makefile to:

.PHONY: all homework1
CFLAGS= -g -O0 -Wall -Werror -Wno-unused-function
LDFLAGS= -lm

all : homework1

homework1 : program.tab.o program.lex.o

%.o : %.c
    gcc -o $@ -c $(CFLAGS) $<
%.lex.c : %.l %.tab.h
    flex -o $@ $<
%.tab.c %.tab.h : %.y
    bison --verbose -o $@ -d $<

The warning message goes away. (I created your environment by using 'touch program.lex program.y' initially; I then moved program.lex to program.l).

However, I'm still not quite sure what is going on in the broken version - but it probably does revolve around implicit rules as suggested by @Beta.

Jonathan Leffler
The "breakage" in the "broken version" is from the "Linking a single object file" rule (`foo.o` -> `foo`).
Jack Kelly
+2  A: 

@aaa carp is correct that is an implicit rule, but it's not one of the LEX rules, because they build N.c or N.r from N.l, and this is a rule that's building N from N.o. That looks to me like the "Linking a single object file" rule, described in info (make) Catalogue of Rules. Renaming your .lex files to .l files will fix this problem.

Also: running flex, I don't think you really need the .tab.h file to build the lexer source. Try this instead:

%.l.c: %.l
    flex -o$@ $<
program.l.o: program.tab.h

This will add the extra dependency to program.l.o.

Jack Kelly
+1, I stand corrected, realized it just now
aaa
Thanks! Fixes the problem. Wish I knew all of these implicit rules. Do you know if I can turn them off?
Mike
@Mike: http://www.gnu.org/software/make/manual/make.html#Catalogue-of-Rules is the catalogue of all rules. `make -r` will run without implicit rules, but I don't remember if that works as a setting in the `MAKEFLAGS` variable or if it must be specified on the command line.
Jack Kelly