creating a makefile - c

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.)

Related

Configure automake to target assembly

Is it possible to configure automake to generate a Makefile which, in addition to building the .o files and linked binary, also has targets for %.s? I want to be able to review the compiler output in a text format without having to invoke binutils on the .o files.
Specifically, if I have main.c as a source file, I want to be able to run make main.s. The desired recipe would be the same as that for main.o, but using CC1 := $(CC) -S.
The question is a little XY.
You want to be able make the intermediate assembly file foo.s, where
the source file foo.c is one of the sources in an autotooled project, using
a makefile that is generated by the project's ./configure script. You
assume that to do this you must do something to the automake inputs -
the Makefile.ams? - that will cause ./configure to generate Makefiles
that include assembly targets *.s matching all object targets *.o.
Well you could, but then your project would not be a regular autotooled
project as usually distributed, and there is no need to make it irregular
to get what you want.
The GCC option -save-temps
exists to let developers see the intermediate files of compilation - the preprocessor
output, the assembly.
$ gcc -c -o foo.o foo.c
outputs foo.o
$ gcc -save-temps -c -o foo.o foo.c
outputs:
foo.o
foo.i # preprocessed source
foo.s # assembly
As I expect you know, GNU Make receives compiler options from the make-variable
CFLAGS, and automake respects this convention, independently of and in addition to any compiler
options prescribed by the project's autotooling. So, if you would otherwise generate
makefiles with:
$ ./configure ...
then, to add -save-temps to the C compiler options, generate makefiles instead
with:
$ ./configure CFLAGS=-save-temps ...
And if you are already using CFLAGS, e.g.
$ ./configure CFLAGS="-g -O0" ...
then append -save-temps:
$ ./configure CFLAGS="-g -O0 -save-temps" ...
Then,
$ make main.o
will make main.o, main.i and main.s up-to-date.
To disable -save-temps, of course, rerun ./configure, removing it from
the CFLAGS.
If the project involves C++ compilation, then CXXFLAGS affects the C++
compiler in the same way that CFLAGS affects the C compiler. Note that
the generated preprocessed C++ sources will be called *.ii, not *.i.
With -save-temps enabled, make clean will not delete the *.i and *.s
files. You may not care, since compilation will always clobber them. If you
do care, you may take advantage of automake's standard phony target clean-local,
which is supported to let an autotooling maintainer extend the behaviour of
clean. Add the following recipe to the Makefile.am of each source directory
in the project:
clean-local:
$(RM) *.i *.ii *.s
Then update the autotooling and regenerate Makefiles:
$ autoreconf
$ ./configure ...
While the COMPILE variable in the generated Makefile.in is technically an internal detail, and this solution relies on the compiler to understand -c -S, adding:
.c.s:
$(COMPILE) -c -S $<
to the Makefile.am has worked for as long as I've been using the autotools. It might also be convenient to add:
clean-local:
rm -f *.s
I find this useful in development to have a look at the assembly output for specific configure and CC, CFLAGS options.
The COMPILE variable will be defined as something like:
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
Similarly, for C++ source we have:
.cc.s:
$(CXXCOMPILE) -c -S $<

makefile for a yacc and flex [closed]

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.

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.

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.

Resources