Makefile linking against a library - c

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.

Related

C Makefile error: ld returned 1 exit

My teacher is not the best at explain C so I'm having a bit of trouble understanding the connection of makefiles. I have already added the code for complex.c, complex.h, and main.c. I'm just having trouble compiling it all using the make command. I followed the example on the powerpoint he handed up and I don't understand why its failing to get to complex.
makefile
complex: main.o complex.o
gcc -o complex main.o complex.o
main.o: main.c complex.h
gcc -c main.c -lm
complex.o: complex.c complex.h
gcc -c complex.c -lm
clean:
rm*.o complex
ls
main.o
main.o: complex.h
gcc -c main.c
complex.o
complex.o: complex.h
gcc -c complex.c
Error
mason% make
gcc -o complex main.o complex.o
ld: fatal: file main.o: unknown file type
ld: fatal: file processing errors. No output written to complex
collect2: error: ld returned 1 exit status
*** Error code 1
make: Fatal error: Command failed for target `complex'
It looks like you have put Makefile fragments inside main.o and complex.o. These should be generated by the compiler, not by you.
Delete these files, and make again.
Additionally, your make clean rule is missing a space.
clean:
rm *.o complex
ls
One more thing. No need for -lm in the compile lines.
main.o: main.c complex.h
gcc -c main.c
complex.o: complex.c complex.h
gcc -c complex.c
You should add -lm at the linking phase.
complex: main.o complex.o
gcc -o complex main.o complex.o -lm
The "Makefile" defines and controls the build dependencies.
For example, you can't build the main executable binary without first building the binary object/module files that go with it. In this case, those are main.o and complex.o.
Generally any object file you need also needs a rule (though some rules can use "wildcards" to build more).
This is all rather academic. Best to take errors at their word and try to disprove them (this one basically says that main.o exists and is incorrect). In this case the hypothesis that main.o exists is supported by the fact that it didn't compile when you ran the make command.
Until you learn more you could invoke "make" using "targets". Like: make clean and make complex. It might help bring clarity.
A lot of makefiles put an "all" target to sort of reset the build. That then depends on "clean" and the executable and library targets. Like:
all: clean complex
So then you "make all" to clean and build.
A good tutorial is here. Mrbook Makefile Tutorial

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.

make rules with existing target, existing prerequisites but no recipe

I was looking at the net-snmp code and I found something odd in the Makefile of the snmplib itself. The last couple of thousands of lines are nothing but rules in this form:
./dir_utils.lo: ../include/net-snmp/output_api.h
for EVERY library object and header file. Even those that are not compiled, depending on which flags are selected in the configure script.
I looked at the "make" manual but I didn't find this exact case. It may be (as stated in 5.9) that they do this to exclude the possibility that an implicit recipe is called on the target, but other than that I have no idea.
Another reason might be to "break" the compilation if the library is tampered with (deleting whatever header in the project causes in fact the makefile to crash because it can't execute the rule).
This is an educated guess but I would like to know the theory behind this. I mean the makefile already builds whatever it has to build, why include all these rules in explicit form?
Thanks
As I expect you know, the Makefile is generated by the ./configure script.
All the lines that interest you are auto-generated dependencies. Actually,
they are just the appended contents of the file Makefile.depend in the same
directory, which is part of the distribution and was generated with the aid
of gcc ahead of time.
So e.g.
./dir_utils.lo: ../include/net-snmp/output_api.h
just informs make of the vitally important fact that ./dir_utils.lo
depends on ../include/net-snmp/output_api.h. Then if ./dir_utils.lo
is older than ../include/net-snmp/output_api.h, make will re-make
./dir_utils.lo provided it has some recipe to do that, which it has.
Here is a project:
main.c
#include "hw.h"
#include <stdio.h>
int main(void)
{
puts(HW);
return 0;
}
hw.h
#ifndef HW_H
#define HW_H
#define HW "Hello World"
#endif
Makefile
CC := gcc
.PHONY: all clean
all: hw
hw: main.o
$(CC) -o $# $<
clean:
rm -f hw main.o
Build and run it:
$ make && ./hw
gcc -c -o main.o main.c
gcc -o hw main.o
Hello World
But there's a bug in the makefile. It doesn't know that main.o
depends on hw.h:
$ touch hw.h
$ make
make: Nothing to be done for 'all'.
Append that dependency to the makefile:
main.o: hw.h
and retry:
$ make
gcc -c -o main.o main.c
gcc -o hw main.o
Bug fixed.

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

Resources