make recompiles everything every time, why? - makefile

Here's my makefile:
all: lex yacc compile
lex: sql.l
lex -i sql.l
yacc: sql.y
yacc -d -v sql.y
compile: y.tab.c lex.yy.c
$(CC) -o sql_parser y.tab.c lex.yy.c -ly -ll
test: all
#./parsesql.sh selecttest.sql
#./parsesql.sh insertintotest.sql
#./parsesql.sh deletefromtest.sql
#./parsesql.sh createtest.sql
cleanup:
rm test.tab.cacc
rm y.output
Running make will always trigger a full recompile, even if nothing has changed:
parsesql> make
lex -i sql.l
yacc -d -v sql.y
cc -o sql_parser y.tab.c lex.yy.c -ly -ll
parsesql> make
lex -i sql.l
yacc -d -v sql.y
cc -o sql_parser y.tab.c lex.yy.c -ly -ll
parsesql> make
lex -i sql.l
yacc -d -v sql.y
cc -o sql_parser y.tab.c lex.yy.c -ly -ll
None of the files have changed, so why is it doing this? The lex and yacc commands should only trigger if sql.l or sql.y respectively have changed, no?

Your targets are all not real files. Make them the names of the actual files you're generating so that make can find them and check timestamps.
Example:
all: sql_parser
lex.yy.c: sql.l
lex -i sql.l
y.tab.c: sql.y
yacc -d -v sql.y
sql_parser: y.tab.c lex.yy.c
$(CC) -o sql_parser y.tab.c lex.yy.c -ly -ll
test: all
#./parsesql.sh selecttest.sql
#./parsesql.sh insertintotest.sql
#./parsesql.sh deletefromtest.sql
#./parsesql.sh createtest.sql
cleanup:
rm test.tab.cacc
rm y.output
You can add .PHONY: all test cleanup to indicate to make that those targets are not intended to be real files.

Related

make file : yacc command not found and [y.tab.c] error 127 after installing bison

There is a given r-tree code by Toni Guttman(it's been modified for my homework), however, if I change an parameter(the dimension of the node), then "make" will cause such errors:
yacc y.spec
make: yacc:command not found
make: *** [y.tab.c] error 127
I've installed bison and flex, and "which yacc" shows that
alias yacc='bison'
/usr/bin/bison
What should I do to solve the problem?
Here is the "Makefile":
# %W% %G%
# use flag -O for optimized code, slower compile
FLAGS=
SRC= main.c index.c newtid.c node.c rectangle.c \
printstats.c clock.c y.spec allocate.c error.c\
split.l.c \
split.q.c \
split.e.c
HEADERS= options.h macros.h index.h assert.h
ALL= $(SRC) $(HEADERS) split.l.h split.q.h split.e.h
OBJ= main.o index.o newtid.o node.o rectangle.o \
printstats.o clock.o y.tab.o allocate.o error.o
OBJLIN= split.l.o
OBJQ= split.q.o
OBJEXP= split.e.o
$(OBJ): $(HEADERS)
$(OBJLIN): $(HEADERS) split.l.h
$(OBJQ): $(HEADERS) split.q.h
$(OBJEXP): $(HEADERS) split.e.h
# assembler chokes if graphics.c is compiled with -g option, do it without.
# graphics.o: graphics.c $(HEADERS)
# cc -c graphics.c
# assembler chokes if y.tab.c is compiled with -g option, do it without.
# y.tab.o: y.tab.c $(HEADERS)
# cc -c y.tab.c
.c.o: $(HEADERS)
cc -c $(FLAGS) $*.c
linear: $(OBJ) $(OBJLIN)
cc $(FLAGS) $(OBJ) $(OBJLIN) -lm -o linear
quad: $(OBJ) $(OBJQ)
cc $(FLAGS) $(OBJ) $(OBJQ) -lm -o quad
exp: $(OBJ) $(OBJEXP)
cc $(FLAGS) $(OBJ) $(OBJEXP) -lm -o exp
y.tab.c: y.spec $(HEADERS)
yacc y.spec
edit:
sccs edit $(SRC) $(HEADERS) split.l.h split.q.h split.o.h
unedit:
sccs unedit $(ALL)
rm -f tags
delta:
sccs delta $(ALL)
rm -f tags
get:
sccs get $(ALL)
clean:
rm -f *.o core y.tab.c tags
tags: $(SRC)
ctags *.c
lint:
rm -f lint.out
lint *.c > lint.out
You don't have yacc installed, as you've seen. Changing an alias in your shell won't help, because it's make that is trying to run the yacc command, not the shell. You have to edit your makefile, and add a line like:
YACC = bison -y
(the -y flag makes bison behave like yacc)
Since you didn't show your actual makefile we can't be sure that this will do it, but it's likely.
EDIT:
I your makefile above, change the reference to yacc to say bison -y instead.
Your makefile is not following many best practices but that's for another day.
manually add this script /usr/bin/yacc is simply a script containing:
#! /bin/sh
exec '/usr/bin/bison' -y "$#"

Configuring my makefile for gdb

I've used gdb before, but never with a makefile and only configuring in very simple ways. g++ -g -o file.cpp, etc. I've tried everything, and I cannot get it to recognize debugging objects. I want to debug all of my executable compile.
I'm running g++ and Ubuntu.
compile: scanner.o parser.o listing.o locals.o globals.o
g++ -o compile scanner.o parser.o listing.o locals.o globals.o
scanner.o: scanner.c locals.h globals.h listing.h tokens.h
g++ -c scanner.c
scanner.c: scanner.l
flex scanner.l
mv lex.yy.c scanner.c
parser.o: parser.c listing.h locals.h globals.h
g++ -c parser.c
parser.c tokens.h: parser.y
bison -d -v parser.y
mv parser.tab.c parser.c
mv parser.tab.h tokens.h
listing.o: listing.cc
g++ -c listing.cc
locals.o: locals.cc
g++ -c locals.cc
globals.o: globals.cc
g++ -c globals.cc
Do not override the default rules. Just assign CC and CFLAGS as necessary. In other words, your Makefile should be (in its entirety):
CC=g++ # Not best practice. See comments below
CFLAGS=-g
compile: scanner.o parser.o listing.o locals.o globals.o
$(CC) $(CFLAGS) -o $# $^
scanner.o: scanner.c locals.h globals.h listing.h tokens.h
parser.o: parser.c listing.h locals.h globals.h
scanner.c: scanner.l
flex scanner.l
mv lex.yy.c scanner.c
parser.c tokens.h: parser.y
bison -d -v parser.y
mv parser.tab.c parser.c
mv parser.tab.h tokens.h
As an aside, you really should use CXX to specify a C++ compiler and name your source code files appropriately. (Use *.c for C, *.cxx for C++) Since you are using non standard names, you need to fool make by using a C++ compiler for CC, which is not really the best practice.

Make adds unexpected mv command

I'm using a makefile to build my flex/bison project. I'm having problems as it is adding a call to yacc and a mv command thus overwriting one of my files.
user#dk ~/calc ±master⚡ » make clean
rm -rf lex.yy.c calc.tab.h calc.tab.c calc
user#dk ~/calc ±master » make
bison -d calc.y
flex calc.lex
g++ -o calc calc.tab.c lex.yy.c calc.c
user#dk ~/calc ±master⚡ » make clean
rm -rf lex.yy.c calc.tab.h calc.tab.c calc
user#dk ~/calc ±master » touch calc.y
user#dk ~/calc ±master » make
bison -d calc.y
flex calc.lex
yacc calc.y
mv -f y.tab.c calc.c
g++ -o calc calc.tab.c lex.yy.c calc.c
... Failure ...
I simplified the makefile to the bare minimum to reproduce this. Using bison to create two files: calc.tab.c and calc.tab.h. I do not have the .h file as a target as I'm not sure what the correct way to do that is. The call to bison will generate both of the calc.tab.* files so that is not my main concern.
What is the correct way to structure this makefile to avoid the calls to yacc and mv from being generated?
calc: calc.tab.c lex.yy.c calc.c
g++ -o calc calc.tab.c lex.yy.c calc.c
calc.tab.c: calc.y
bison -d calc.y
lex.yy.c: calc.lex calc.tab.h
flex calc.lex
clean:
rm -rf lex.yy.c calc.tab.h calc.tab.c calc
The mv comes from make's built-in rules, which contain:
%.c : %.y
$(YACC.y) $<
mv -f y.tab.c $#
It looks like make is trying to create calc.c from calc.y. Some solutions to this are to redefine that rule yourself, or rename calc.y to something that won't trigger that rule for calc.c, or disable make's built-in rules.
You can list all built-in rules with make -p.

How to add an all rule to this Makefile?

I want to just type 'make all' and have the following Makefile do everything it's supposed to do:
LEX = lex
YACC = yacc
CC = gcc
calcu: y.tab.o lex.yy.o
$(CC) -o calcu y.tab.o lex.yy.o -ly -lfl
y.tab.c y.tab.h: parser.y
$(YACC) -d parser.y
y.tab.o: y.tab.c parser.h
$(CC) -c y.tab.c
lex.yy.o: y.tab.h lex.yy.c
$(CC) -c lex.yy.c
lex.yy.c: calclexer.l parser.h
$(LEX) calclexer.l
clean:
rm *.o
rm *.c
rm calcu
What all is it supposed to do? If you just want it to build calcu, all you have to do is type make and it will make it along with everything it depends on, because it is the first rule in the file.
If you still want to make an all rule, it can be done like this. I recommend putting this above all other rules, so that you can just type make instead of make all.
all: calcu

What's wrong with this Makefile?

When I run make all on the following Makefile I get this error:
Makefile:5: *** missing separator. Stop.
What's wrong with it and how do I fix it?
LEX = lex
YACC = yacc
CC = gcc
calcu: y.tab.o lex.yy.o
$(CC) -o calcu y.tab.o lex.yy.o -ly -lfl
y.tab.c y.tab.h: parser.y
$(YACC) -d parser.y
y.tab.o: y.tab.c parser.h
$(CC) -c y.tab.c
lex.yy.o: y.tab.h lex.yy.c
$(CC) -c lex.yy.c
lex.yy.c: calclexer.l parser.h
$(LEX) calclexer.l
clean:
rm *.o
rm *.c
rm calcu
G'day,
You need tabs to indent the lines underneath each target.
LEX = lex
YACC = yacc
CC = gcc
calcu: y.tab.o lex.yy.o
$(CC) -o calcu y.tab.o lex.yy.o -ly -lfl
y.tab.c y.tab.h: parser.y
$(YACC) -d parser.y
y.tab.o: y.tab.c parser.h
$(CC) -c y.tab.c
lex.yy.o: y.tab.h lex.yy.c
$(CC) -c lex.yy.c
lex.yy.c: calclexer.l parser.h
$(LEX) calclexer.l
clean:
rm *.o
rm *.c
rm calcu
BTW General convention is that you should use braces rather than brackets for your macros. Using brackets are a legacy thing left over from substituting an object back in to an archive. So the above is better expressed as:
LEX = lex
YACC = yacc
CC = gcc
calcu: y.tab.o lex.yy.o
${CC} -o calcu y.tab.o lex.yy.o -ly -lfl
y.tab.c y.tab.h: parser.y
${YACC} -d parser.y
y.tab.o: y.tab.c parser.h
${CC} -c y.tab.c
lex.yy.o: y.tab.h lex.yy.c
${CC} -c lex.yy.c
lex.yy.c: calclexer.l parser.h
${LEX} calclexer.l
clean:
rm *.o
rm *.c
rm calcu
HTH
You need to indent like so. (Note: they changed my tabs into a 4space. Make sure to indent with the tab character.)
LEX = lex
YACC = yacc
CC = gcc
calcu: y.tab.o lex.yy.o
$(CC) -o calcu y.tab.o lex.yy.o -ly -lfl
y.tab.c y.tab.h: parser.y
$(YACC) -d parser.y
y.tab.o: y.tab.c parser.h
$(CC) -c y.tab.c
lex.yy.o: y.tab.h lex.yy.c
$(CC) -c lex.yy.c
lex.yy.c: calclexer.l parser.h
$(LEX) calclexer.l
clean:
rm *.o
rm *.c
rm calcu
The extra blank lines aren't required but the indenting is. You'll also need to make an all rule if you want to make all.
Generally, this sort of error means that you have erroneously used spaces instead of a tab when indenting lines in your Makefile.
Your example appears to have been pasted without indenting, but I can't tell whether your file really looks like that or whether there was a paste error. In the following:
calcu: y.tab.o lex.yy.o
$(CC) -o calcu y.tab.o lex.yy.o -ly -lfl
the whitespace before $(CC) must be a tab, not spaces:
calcu: y.tab.o lex.yy.o
$(CC) -o calcu y.tab.o lex.yy.o -ly -lfl
|tab-->|
Whitespace formatting can make answering this difficult. In Make whitespace is critical. Actions must have a tab character in front to be recognised as such by Make. e.g.
calcu: y.tab.o lex.yy.o
\t$(CC) -o calcu y.tab.o lex.yy.o -ly -lfl y.tab.c y.tab.h: parser.y
Note that \t means <tab>. Not 4 spaces, not any spaces, but tab!
Also ensure there is a blank line between dependencies, i.e. if you're going to say file: dependencies then ensure there is a blank line immediately above.

Resources