Attempting to Fix Makefile of an 80's Source Code - makefile

I am trying to run the makefile from the source code of Chris Crawford's Balance of Power 1990 using GNU-make. Quite honestly, I have no experience with makefiles nor do I have any idea what I'm doing. The makefile looks like this:
GlobDebug=FALSE
"{BOPO}"BOPSRace1 ト "{BOPO}"BOP2.code "{BOPS}"NewResrc.r
rez "{BOPS}"NewResrc.r -o "DataFrame:BOP2_ト:BOP2"
"{BOPO}"BOP2.code ト "{BOPO}"Globals.p.o カ
"{BOPO}"AsmCode.a.o カ
"{BOPO}"Init.p.o カ
"{BOPO}"Titles.p.o カ
"{BOPO}"Background.p.o カ
"{BOPO}"StdRoutines.p.o カ
"{BOPO}"History.p.o カ
"{BOPO}"PlanMove.p.o カ
"{BOPO}"CrisisU.p.o カ
"{BOPO}"Main.p.o
link "{Libraries}"Interface.o カ
"{Libraries}"Runtime.o カ
"{PLibraries}"Paslib.o カ
"{BOPO}"Globals.p.o カ
"{BOPO}"AsmCode.a.o カ
"{BOPO}"Init.p.o カ
"{BOPO}"Titles.p.o カ
"{BOPO}"Background.p.o カ
"{BOPO}"StdRoutines.p.o カ
"{BOPO}"History.p.o カ
"{BOPO}"PlanMove.p.o カ
"{BOPO}"CrisisU.p.o カ
"{BOPO}"Main.p.o カ
-o "{BOPO}"BOP2.code
"{BOPO}"AsmCode.a.o ト "{BOPS}"AsmCode.a
Asm -o "{BOPO}" "{BOPS}"AsmCode.a
"{BOPO}"Globals.p.o ト "{BOPS}"Globals.p
Pascal -d DebugFlg={GlobDebug} -o "{BOPO}" "{BOPS}"Globals.p
"{BOPO}"Init.p.o ト "{BOPS}"Init.p "{BOPS}"Globals.p
Pascal -d DebugFlg={GlobDebug} -o "{BOPO}" "{BOPS}"Init.p
"{BOPO}"Titles.p.o ト "{BOPS}"Titles.p "{BOPS}"Globals.p
Pascal -d DebugFlg={GlobDebug} -o "{BOPO}" "{BOPS}"Titles.p
"{BOPO}"Background.p.o ト "{BOPS}"Background.p "{BOPS}"Globals.p
Pascal -d DebugFlg={GlobDebug} -o "{BOPO}" "{BOPS}"Background.p
"{BOPO}"StdRoutines.p.o ト "{BOPS}"StdRoutines.p "{BOPS}"Globals.p
Pascal -d DebugFlg={GlobDebug} -o "{BOPO}" "{BOPS}"StdRoutines.p
"{BOPO}"History.p.o ト "{BOPS}"History.p "{BOPS}"Globals.p
Pascal -d DebugFlg={GlobDebug} -o "{BOPO}" "{BOPS}"History.p
"{BOPO}"PlanMove.p.o ト "{BOPS}"PlanMove.p "{BOPS}"Globals.p
Pascal -d DebugFlg={GlobDebug} -o "{BOPO}" "{BOPS}"PlanMove.p
"{BOPO}"CrisisU.p.o ト "{BOPS}"CrisisU.p "{BOPS}"Globals.p
Pascal -d DebugFlg={GlobDebug} -o "{BOPO}" "{BOPS}"CrisisU.p
"{BOPO}"Main.p.o ト "{BOPS}"Main.p "{BOPS}"Globals.p
Pascal -d DebugFlg={GlobDebug} -o "{BOPO}" "{BOPS}"Main.p
Even as a total makefile-noob I can tell that there are some serious encoding errors (ト and カ, which showed up as umlaut-A and ¶ in notepad++).
What I Tried
I kept getting the "no target specified" error, so I moved the "GlobDebug=False" from the top.
Then I got the "target pattern contains no %" error.
I assumed the (ト) was supposed to be (:), and after replacing them it yielded the "multiple target patterns" error.
At this point I am clueless.
Questions
How should these (ト) and (カ) be fixed? Are there any other obvious problems with this makefile?
Thanks in advance.

The ト should be : and the カ should be \ and last character of the line. Then , you will have to check that the first character of the lines of the recipes is a tab, not spaces. Example in:
"{BOPO}"BOPSRace1 : "{BOPO}"BOP2.code "{BOPS}"NewResrc.r
rez "{BOPS}"NewResrc.r -o "DataFrame:BOP2_ト:BOP2"
the recipe is the second line and it must start with a tab.

Related

make recompiles everything every time, why?

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.

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