makefile for a yacc and flex [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have a make-based project involving yacc and lex, but make is performing actions that I do not expect and cannot explain from my makefile:
a.out: lex.yy.o y.tab.o ass3_14CS101.o
gcc lex.yy.o y.tab.o ass3_14CS101.o -lfl
ass3_14CS101.o: ass3_14CS101.c
gcc -c ass3_14CS101.c
lex.yy.o: lex.yy.c
gcc -c lex.yy.c
y.tab.o: y.tab.c
gcc -c y.tab.c
lex.yy.c: ass3_14CS101.l y.tab.h
flex ass3_14CS101.l
y.tab.c: ass3_14CS101.y
yacc -dtv ass3_14CS101.y -W
y.tab.h: ass3_14CS101.y
yacc -dtv ass3_14CS101.y -W
clean:
rm lex.yy.c y.tab.c y.tab.h lex.yy.o y.tab.o ass3_14CS101.o y.output a.out
test:
./a.out < ass3_14CS101_test.c
Here is the output of one make run:
yacc -dtv ass3_14CS10061.y -W
ass3_14CS10061.y:48.10: warning: empty rule without %empty [-Wempty-rule]
statement : ;
^
flex ass3_14CS10061.l
ass3_14CS10061.l:77: warning, rule cannot be matched
gcc -c lex.yy.c
gcc -c y.tab.c
yacc ass3_14CS10061.y
mv -f y.tab.c ass3_14CS10061.c
gcc -c ass3_14CS10061.c
gcc lex.yy.o y.tab.o ass3_14CS10061.o -lfl
ass3_14CS10061.o: In function `yyparse':
ass3_14CS10061.c:(.text+0x20): multiple definition of `yyparse'
y.tab.o:y.tab.c:(.text+0x289): first defined here
ass3_14CS10061.o: In function `yyerror':
ass3_14CS10061.c:(.text+0x7f6): multiple definition of `yyerror'
y.tab.o:y.tab.c:(.text+0xd61): first defined here
collect2: error: ld returned 1 exit status
make: *** [a.out] Error 1
Where did the mv -f command (the bold line above) come from? There is no such command in the Makefile, and it is causing the build to fail.

You have:
a.out: lex.yy.o y.tab.o ass3_14CS101.o
gcc lex.yy.o y.tab.o ass3_14CS101.o -lfl
ass3_14CS101.o: ass3_14CS101.c
gcc -c ass3_14CS101.c
The first rule says the compilation needs to ensure ass3_14CS101.o is up to date. The second rule says you create ass3_14CS101.o by compiling ass3_14CS101.c. None of the other specified rules say anything about how to create ass3_14CS101.c, but make is clever.
Given that there's a file ass3_14CS101.y, make knows how to create ass3_14CS101.c from it: it runs yacc and moves yy.tab.c to ass3_14CS101.c. So, that's what you see it doing.
You might note that make is running the yacc command again before the mv you noted; and that invocation is different from the first.
You need to use more macros. YACC contains the name of the Yacc-like program, and YFLAGS conventionally contains the arguments to it (it looks like you prefer -dtv -W as the Yacc flags). Similarly with the C compiler (CC and CFLAGS) and linking often adds LDFLAGS and LDLIBS — so you end up with a command line like:
${CC} -o $# ${CFLAGS} ${OBJECTFILES} ${LDFLAGS} ${LDLIBS}
as the linking command line. The macro I designated as ${OBJECTFILES} is a list of the object files that should be linked. Note that ${CFLAGS} is included; it often contains the -g option for debug information, and you need that in the link command line as well as the object file command lines.
One major benefit of using macros is that you can adjust the compilation from the make command line if need so be — without editing the makefile.

Related

Makefile linking against a library

I have the following makefile.I have the shared library lcustom in the path /usr/local/lib. I am using the functions from that library in my program test.y but it is giving undefined reference for the functions defined in libcustom.so.What is wrong with my makefile below.
all: test
test.tab.c test.tab.h: test.y
bison -d test.y
lex.yy.c: test.l test.tab.h
flex test.l
test: lex.yy.c test.tab.c test.tab.h test_util.c
gcc -lcustom -o test test.tab.c test_util.c lex.yy.c
clean:
rm test test.tab.c lex.yy.c test.tab.h
It has been long time since last time I write a serious makefile, please point it out if I am wrong.
there are ways to avoid encounter such issue by using implicit rules:
.PHONY: all clean
LDFLAGS=-lcustom
CFLAGS= # your gcc options start here
all: test
test.tab.c test.tab.h: test.y
bison -d test.y
lex.yy.c: test.l test.tab.h
flex test.l
lex.yy.o: lex.yy.c
tast.tab.o: test.tab.c test.tab.h
test_util.o: test_util.c
test: lex.yy.o test.tab.o test_util.o
clean:
rm -f test test.tab.c lex.yy.c test.tab.h *.o
then you avoided all painful stuff.
in general, it's better to generate .o files explicitly then use linker to deal with them, such that if a build fails, you will definite know what's wrong with it, specifically compile time error, or linker error.
about the cause of your question, I think you should put -lcustom in a correct position to make it work. I rarely see people put -l flag right after gcc so I am pretty sure it's not correct. I would guess you should put it at the very end.
PS: in my comment, nm is a tool to list out the symbols in a object file. specifically, in your output, T means the function is in text segment and it's exported so it should be able to be linked. check man nm for more info.

Unix: Project Management with Make

My instructions are:
The steps necessary to produce this program are:
Compile cpp2html.c to produce cpp2html.o. (Important: the source code in this project is C, not C++, and so must be compiled and linked with gcc, not g++.)
Run the command
flex cppscanner.l
to produce the file lex.yy.c from the language description in cppscanner.l.
Compile lex.yy.c to produce lex.yy.o. (This often produces a warning message about extra tokens. Ignore it.)
Link the .o files to produce an executable program named cpp2html
Write a makefile that will carry out these steps. Your makefile should result in only the minimum required amount of steps when any input file to this process is changed. (Note: you will probably not be able to base this makefile upon my self-updating makefile as in the earlier part of the assignment. Instead, you will probably find it necessary to write this one from scratch.
Here is my makefile:
cpp2html: cpp2html.o lex.yy.o
gcc -g -DDEBUG cpp2html.o lex.yy.o
mv a.out cpp2html
lex.yy.o: lex.yy.c
gcc -g -DDEBUG lex.yy.c
lex.yy.c:
flex cppscanner.l
cpp2html.o: cpp2html.c
gcc -g -DDEBUG cpp2html.c
What am I doing wrong here? I get an error message saying:
collect2: error: ld returned 1 exit status
make: *** [cpp2html.o] Error 1
Your makefile does not build 'cpp2html' when invoked:
gcc -g -DDEBUG cpp2html.c
This is due tonight, so any suggestions would be greatly appreciated.
It's complaining about the following:
cpp2html.o: cpp2html.c
gcc -g -DDEBUG cpp2html.c
This line is trying to compile cpp2html.c to a.out.
Change that to
cpp2html.o: cpp2html.c
gcc -g -DDEBUG -c cpp2html.c
Do the same thing for the line that compiles lex.yy.c to lex.yy.o. The -c option tells gcc to only generate the object file and write it to the .o file.
You can take advantage of other options and some built-in variables. Here's a suggestion:
cpp2html: cpp2html.o lex.yy.o
gcc -g -DDEBUG -o $# $?
$# evaluates to the name of the target. $? evaluates to the list of dependencies (the .o files). The -o option tells gcc to write the resulting binary to the specified file name instead of a.out.
You can also take advantage of implicit rules:
%.o : %.c
gcc -g -DDEBUG -c $<
This will build any .c file to the corresponding .o file, so you don't need to repeat the same commands for cpp2html.c and lex.yy.c.
Edit
FWIW, here's how I'd structure the makefile (with annotations; assumes Gnu make):
# Variables used by implicit rules
CFLAGS=-g -DDEBUG -Wall -Werror # flags for gcc
LFLAGS= # flags for flex, currently none
LEX=flex # lexer
CC=gcc # C compiler
# Variables to make life easier
LSRCS=cppscanner.l # All of our flex source files
SRCS=cpp2html.c $(patsubst %.l,%.c,${LSRCS}) # All of our C source files
OBJS=$(patsubst %.c,%.o,${SRCS}) # All of our object files
TARGET=cpp2html # Final target name
${TARGET} : ${OBJS}
${CC} ${CFLAGS} -o $# $^ # Explicit rule to build target
# $# expands to target name
# $^ expands to list of all prerequisites
clean:
rm -rf *.o $(patsubst %.l,%.c,${LSRCS})
That's it. We're relying on implicit rules to build the .l file to a .c file, and to build the .c files to .o files. The implicit rules use the LEX, CC, LFLAGS and CFLAGS variables to run the right commands with the right options. We only need the single explicit rule to build our final executable.
The advantage of structuring a makefile like this is that you can add files to the project without having to add new rules.
I think all of the above is correct; my main box is shut down at the moment so I can't test it. Refer to the Gnu Make manual for more details.

creating a makefile

So I have to create a makefile that would generate the application described below and make sure each generated file has its own rule.
For the makefile:
The first tool is flex, which takes a file called spec.l and generates a file called lex.yy.c. Another tool called bison expects a file calledspec.y and will generate the file spec.tab.c. If bison is called using the directives -vd, it will also generate a file called spec.tab.h (which is needed when compiling lex.yy.c). The two C files can be compiled into object files and then linked together with the yacc (-ly) and lex (-ll) libraries to generate the compiler (a.out.
The makefile you describe must generate the following commands if you were starting just with spec.l and spec.y:
flex spec.l
bison -vd spec.y
gcc -c lex.yy.c
gcc -c spec.tab.c
gcc spec.tab.o lex.yy.o -ly -ll
i am not sure where to start with this problem
edit: what i have so far
compiler: spec.tab.o lex.yy.o
gcc spec.tab.o lex.yy.o -ly –ll
lex.yy.c: spec.l
flex spec.l
spec.tab.c: spec.y
bison -vd spec.y
spec.tab.o: spec.tab.c
gcc -c spec.tab.c
lex.yy.o: lex.yy.c spec.tab.h
gcc –c lex.yy.c
clean:
rm –f *.c *.o a.out
You have to tell the make about the dependencies. For example, lex.yy.c depends on spec.l:
lex.yy.c: spec.l
flex spec.l
The first line say lex.yy.c depends on spec.l. The second tells how to generate an updated version of lex.yy.c when spec.l is newer. We pretty much repeat that pattern with the other files. In the case of calledspec.y, we have two results that are produced from the same input/command. At least with GNU make, you can specify that like this:
spec.tab.c spec.tab.h: calledspec.y
bison -vd calledspec.y
Then you pretty much repeat the process for dependencies of .o (or .obj, etc.) files on headers and C files:
lex.yy.o: lex.yy.c spec.tab.h
$(cc) -c lex.yy.c
One final note: unless you specify otherwise, make will build the first target specified in the makefile, so you normally want to arrange it with the final executable first, and other targets after that:
parser: lex.yy.o y.tab.o
$(cc) -o parser lex.yy.o y.tab.o
lex.yy.o: lex.yy.c spec.tab.h
$(cc) -c lex.yy.c
And so on. This only applies to targets though, not to macros, so you'll typically see a few things like:
cflags = -O2
...at the beginning of a make file. Then the lines the invoke the compiler will use that, something like:
lex.yy.o: lex.yy.c spec.tab.h
$(cc) $(cflags) -c lex.yy.c
And when this is executed, the cflags macro will be expanded, so the command that gets executed is gcc -O2 -c lex.yy.c (and it predefines cc to the name of the compiler it normally expects to use, so Microsoft's make sets it to cl, GNU to gcc, etc.)

Calling flex from a makefile

I would like to call flex to build a .l file, then call gcc to build everything.
I tryed:
comp:
lex scanner.l \
gcc -o a.out main.c hash.c -I.
error:
lex scanner.l \
gcc -o a.out main.c hash.c -I.
lex: impossible to opne gcc
/usr/bin/m4:stdin:2994: ERROR: end of file in string
and
lex scanner.l
<tab> gcc -o a.out main.c hash.c -I.
error: missing separator.
The lex.yy.c generate by lex has is being included in the main file.
Thanks in advance,
Pedro
Try this:
lex.yy.c: scanner.l
lex scanner.l
comp: main.c hash.c
gcc -o a.out main.c hash.c -I.
main.c: lex.yy.c
The first rule set tells make that lex.yy.c needs to be rebuilt any time scanner.l changes and provides the command to recreate lex.yy.c. The second rule set tells make that the fake target comp depends on main.c and hash.c. If either file changes, then invoking make comp will cause a recompile. The last line is a stand-alone dependency that tells make to consider main.c as dirty any time that lex.yy.c changes. It will also force an invocation of make comp to create lex.yy.c if it does not exist.
all: a.out
lex.yy.c: scanner.l
lex scanner.l
a.out: lex.yy.c main.c hash.c
gcc -o a.out main.c hash.c -I.
Remove the backslash, or add a semicolon (;) before it.
As it is now, the two commands are added together on one line, and executed as one long command.
IIRC the usual Makefle pattern is
a.out: lex.yy.c main.c hash,c
<tab> gcc -o a.out main.c hash.c lex.yy.c -I. -ll
lex.yy.c: scanner.l
<tab> lex scanner.l
This is wrong, because in the original code, main.c includes lex.yy.c
This assumes the original code is changed so that main.c does not include lex.yy.c
Without that change, this will fail because there will be two definitions of yylex(), one from its #include in main.c, and one because it is supplied as a source code compilation unit. I encourage folks to not include a .c file into another .c file.
In general, the convention is to use a different file extension (.i) for included source files which generate unique symbols and code.

make is automatically attempting to link even when I pass -c in my makefile

I'm new to makefiles, so I apologize in advance if this is a silly question. Also I removed most variables from my makefile because they weren't working properly (gnu make tells me that $(myvar) should be completely replaces by the value of myvar, however the output of make was showing me that this was not happening), so I apologize for the ugliness and the more than 80 character lines.
acolibobj = acoLibInit acoGlobalDefs
acolibinterface: $(acolibobj).o
acoLibInit.o:
gcc -fPIC -g -c -Wall -I/usr/include/dc1394 -o acoLibinit.o acoCommands/acoLibInterface/acoLibInit.c
acoGlobalDefs.o:
gcc -fPIC -g -c -Wall -I/usr/include/dc1394 -o acoGlobalDefs.o acoCommands/acoLibInterface/acoGlobalDefs.c
When I run this makefile I get:
gcc -fPIC -g -c -Wall -I/usr/include/dc1394 -o acoLibinit.o acoCommands/acoLibInterface/acoLibInit.c
cc acoLibInit.o -o acoLibInit
gcc: acoLibInit.o: No such file or directory
gcc: no input files
make: *** [acoLibInit] Error 1
So far as I can tell, what's happening is that make is trying to compile AND link, even though I explicitly added the -c flag. When I run "gcc -fPIC -g -c..." myself (from bash), I do not get any problems at all. Why does make go on to try "cc acoLibInit.o -o acolibInit"?
make is trying to build acoLibInit. It probably has built-in rule that specifies "whatever" can be produced by linking "whatever.o", which is why you get that cc line.
This line:
acolibinterface: $(acolibobj).o
expands to:
acolibinterface: acoLibInit acoGlobalDefs.o
(note the absence of .o on the first dependency). This is why it's trying to link acoLibInit.
Try this:
acolibinterface: $(addsuffix .o,$(acolibobj))
if you want only the .o files as dependencies for that target.
$(acolibobj).o expands to acoLibInit acoGlobalDefs.o. Thus, you're really saying:
acolibinterface: acoLibInit acoGlobalDefs.o
Simply define acolibobj = acoLibInit.o acoGlobalDefs.o and use acolibinterface: $(acolibobj).

Resources