makefile: undefined reference to main - c

I am working on a simple project that generates 2 executable files, main and Server.
The program in Main.c makes use of code present in user_interface.c through the header file user_interface.h.
The Makefile I have written is as follows,
all: main user_interface.o Server
main: user_interface.o main.c
gcc main.c user_interface.o -o main
user_interface.o: user_interface.c user_interface.h
gcc user_interface.c -o user_interface.o
Server: Server.c
gcc Server.c -o Server
clean:
rm -rf main *.o Server
When I type make on the terminal, I get the following error:
gcc user_interface.c -o user_interface.o
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [Makefile:18: user_interface.o] Error 1
How do I navigate past this error?

Your rule for user_interface.o is wrong. You need to use the -c option to tell it that it's creating an object file rather than an executable, so it doesn't need a main() function.
all: main Server
main: user_interface.o main.o
gcc main.o user_interface.o -o main
main.o: main.c
gcc -c main.c
user_interface.o: user_interface.c
gcc -c user_interface.o
Server: Server.c
gcc Server.c -o Server
clean:
rm -rf main *.o Server
make actually has a built-in rule for compiling .c to .o, so you don't actually need those rules.

I think you're not using makefiles properly.
so a section of your makefile might look something like this:
core: WitchCraft NeuralServer AmoebaServer CDS NLPServer HollyServer
test: ENiX4NeuralCLI DataInjector NNTestServer ENiX4AmoebaCLI CLINLPTest
WitchCraft: ENiX_Net.o ENiX_IPC.o ENiX_SHM.o ENiX_Seq.o ENiX_Packet.o WitchCraft.o ENiX_Config.o ENiX_Disk.o ENiX_Binary.o
g++ -ggdb -O0 ENiX_Net.o ENiX_IPC.o ENiX_SHM.o ENiX_Seq.o ENiX_Packet.o WitchCraft.o ENiX_Config.o ENiX_Disk.o ENiX_Binary.o -o WitchCraft.bin -std=c++11 -lreadline
These things before the colon, are called targets. The can be called with:
make <target>
e.g.
make WitchCraft
So for the first line of your target you've got source files inside there for some reason and it looks like you're trying to compile user_interface.o as a binary, rather than an object, but you're not linking it to main.o.
So I suspect you want something like:
main: main.o user_interface.o
gcc main.o user_interface.o -o main
And what that should do is cause make to look for the source code for main.o (i.e. main.c) likewise for interface.o (i.e. interface.c) and then compile these into object files (i.e. .o files).
Then you'd link these object files into a binary, using gcc with the -o to specify the binary output file in this case, "main".
And you'd need to do something similar with the server.

Related

Makefile To Compile Multiple Files

I am trying to compile my TCP client server program through Make but I can not get everything linked together.
My current files I am using:
client.c
connectioninfo.c
connectioninfo.h
server.c
splinter.c
splinter.h
All .c files use the two .h files in their code.
Here is what my makefile looks like:
splinter : server.o client.o splint.o connectioninfo.o
server.o: server.c splinter.h connectioninfo.h
gcc -o server server.c
client.o: client.c splinter.h connectioninfo.h
gcc -o client client.c
splint.o: splinter.c splinter.h connectioninfo.h
gcc -o splint splinter.c
connectioninfo.o: connectioninfo.c splinter.h connectioninfo.h
gcc -o connectioninfo connectioninfo.c
I get the errors :
gcc -o server server.c
/tmp/ccAu7sDE.o: In function `main':
server.c:(.text+0x6e): undefined reference to `alloc_serverinfo'
server.c:(.text+0x87): undefined reference to `getconnectioninfo'
server.c:(.text+0xcd): undefined reference to `port'
server.c:(.text+0xdc): undefined reference to `host'
server.c:(.text+0xe7): undefined reference to `s_bind'
server.c:(.text+0x1a5): undefined reference to `s_accept'
collect2: error: ld returned 1 exit status
Makefile:4: recipe for target 'server.o' failed
make: *** [server.o] Error 1
Any idea on how i can get everything to compile? Thanks
You are currently calling gcc to build applications, not object files, for each source file. Please use the option -c and give the appropriate file name for the output, for example
gcc -c -o server.o server.c
Now change the rule for the application so that it is linked:
splinter : server.o client.o splint.o connectioninfo.o
gcc -o splinter server.o client.o splint.o connectioninfo.o
To debug your Makefile and see what commands will be generated without executing them you can use
make -n
You can call commands explicitly like i.e. gcc -c -o server.o server.c in your shell to check each step.
Oh, and you can name the object file splinter.o which is compiled from the source file splinter.c. There will be no problem with the resulting executable splinter.
Now you could also simplify your Makefile to use automatic variables; please see the documentation for make.
All put together, you could use:
splinter : server.o client.o splinter.o connectioninfo.o
gcc -o $# $^
server.o: server.c splinter.h connectioninfo.h
client.o: client.c splinter.h connectioninfo.h
splinter.o: splinter.c splinter.h connectioninfo.h
connectioninfo.o: connectioninfo.c splinter.h connectioninfo.h
%.o: %.c
gcc -o $# $<
For compiling multiple files you will need to do it in two steps:
Compile each source file into an object file (note the use of -c to compile only) as the busybee suggested:
somefile1.o : somefile1.c
gcc -c somefile1.c -o somefile1.o
somefile2.o : somefile2.c
gcc -c somefile2.c -o somefile2.o
Link your object files - create myapp executable
myapp : somefile1.o somefile2.o
gcc somefile1.o somefile2.o -o myapp

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 error : duplicate symbol _main in

I can compile my two files serveur.c and client.c separately but when I try to use a makefile, it shows me an error. What I want is very simple : two compiled files : serveur.o and client.o.
Here is the code when I compile my two files separately :
gcc -lpthread serveur.c -o serveur.o
And
gcc -lpthread client.c -o client.o
Here is my makefile :
chatroom: serveur.o client.o
gcc serveur.o client.o -o chatroom
serveur.o: serveur.c
gcc -lpthread serveur.c -o serveur.o
client.o: client.c
gcc -lpthread client.c -o client.o
And here is the error when I write : "make -f makefile" in the terminal
gcc serveur.o client.o -o chatroom
duplicate symbol _main in:
serveur.o
client.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [chatroom] Error 1
Thanks for your help ! :)
If you successfully managed to build the two separate parts into a program each, it implies that both of the source files contain a main() or main(int, char*[]). However, you can have only one main() function per program (the restriction that you can have each function defined just once actually applies to all functions).
If each of the two files contains a complete program it is unlikely that you can just link them together: aside from the duplicate main() each of the programs will have some set up and some control. That is, simply getting rid of one of the main() functions is unlikely to result in a working program.
If you just added a main() function to one of the sources because otherwise it wouldn't "compile", you'll need to get rid of this main() and make sure that you actually compile the code into object files by passing the -c option. You'd leave the -c option off when linking the code.
Maybe there is some missunderstanding in the way compiler, assembler and linker work in creating an executable.
The usual convention is to give the .o extension to object files generated after the assembler stage not to executables!
As gcc will act as compile, assemble and link manager performing all steps in one run without beeing told to stop at an earlier stage, gcc -lpthread serveur.c -o serveur.o and
gcc -lpthread client.c -o client.o will both create executables not object files.
To make gcc stop after the assembly stage you have to pass it the -c switch. gcc -c serveur.c and gcc -c client.c. In this case giving -o serverveur.o and -o client.o is not necessary, as gcc will use them by default.
To link the generated object files the last thing to do would be gcc -lpthread serveur.o client.o -o chatroom
A Makefile to accomplish all that could look like that:
chatroom: serveur.o client.o
gcc -lpthread $^ -o $#
Unfortunately this will still not fix your problem of having two definitions of a main() function, one in serveur.c and one in client.c.
As gcc -lpthread serveur.c -o serveur.o and gcc -lpthread client.c -o client.o would have been rejected by the linker with an unresolved reference to main without, I am quite sure both of your sources contain a definition.
If instead of building one executable all you wanted to do is have make create two executables, serveur and client for you, your Makefile should look something like this.
.PHONY: all
all: serveur client

How to compile this lib for usage?

I'm new to C programming, and I'm trying to compile this Simple training example with GCC on Ubuntu 12.10.
Looks like fann.h should not be included (as stated on the file itself), so I included fixedfann.h instead.
First attempt (without include, just to see what the compiler will ask for):
$ gcc main.c -o output
/tmp/cckKyM92.o: In function `main':
main.c:(.text+0x62): undefined reference to `fann_create_standard'
main.c:(.text+0x7a): undefined reference to `fann_set_activation_function_hidden'
main.c:(.text+0x8e): undefined reference to `fann_set_activation_function_output'
main.c:(.text+0xba): undefined reference to `fann_train_on_file'
main.c:(.text+0xce): undefined reference to `fann_save'
main.c:(.text+0xda): undefined reference to `fann_destroy'
collect2: ld returned 1 exit status
fann_create_standard is on fann.h and fann.c. As fann.h is included by fixedfann.h, and fann.h should not be included directly, I believe I have to compile fann.c and fixedfann.c, and link then (tell me if I'm doing any mistake, I'm still not familiar with this "linking" stuff).
So I did:
$ gcc fann/fixedfann.c -o fann/fixedfann.o
fann/fixedfann.c:22:20: fatal error: config.h: No such file or directory
compilation terminated.
and then I did:
$ gcc fann/fixedfann.c -o fann/fixedfann.o -include fann/include/config.h
fann/fixedfann.c:22:20: fatal error: config.h: No such file or directory
compilation terminated.
Now, why it's not finding the config.h file here?
--update
Thanks #JonathanLeffler, I could make some steps here. But now I'm stuck at:
$ gcc fann/fixedfann.c -o fann/fixedfann.o -I./fann/include/ -lm
/usr/lib/gcc/i686-linux-gnu/4.6/../../../i386-linux-gnu/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
collect2: ld returned 1 exit status
and, with grep, I could not find any reference to main on the fann folder... Also no function _start, and I don't know who is linking this crt1.o... Any idea what's wrong here?
--update2
Ok, I got the .o files using Harmeet's Makefile, now I'm trying to link everything.
I created the main.o with gcc -c main.c, and I tried:
gcc -o output main.o fann/fixedfann.o -lm
(-lm for the libmath, that is needed) and I got:
main.c:(.text+0xba): undefined reference to `fann_train_on_file'
This fann_train_on_file is on fann_train_data.c, so I tried:
gcc -o output main.o fann/fixedfann.o fann/fann_train_data.o -lm
but I got lots of multiple definition of... errors... :/
Looks like fann_train_data.o is already included/linked, but if so, why it's not finding fann_train_on_file?
--update3
I'm still really stuck here... Any idea of which (if any) of this two lines should work?:
gcc -o output main.o hello.o fann/fixedfann.o fann/fann_train_data.o -lm
or
gcc -o output main.o hello.o fann/fixedfann.o -lm
--update for Harmeet
The output was:
$ make
gcc -L./fann -lfann main.o -o main
main.o: In function `main':
main.c:(.text+0x62): undefined reference to `fann_create_standard'
main.c:(.text+0x7a): undefined reference to `fann_set_activation_function_hidden'
main.c:(.text+0x8e): undefined reference to `fann_set_activation_function_output'
main.c:(.text+0xba): undefined reference to `fann_train_on_file'
main.c:(.text+0xce): undefined reference to `fann_save'
main.c:(.text+0xda): undefined reference to `fann_destroy'
collect2: ld returned 1 exit status
make: *** [main] Error 1
You can use ar to make a static library and work with that.
Create a Makefile under your hello-fann-3/fann/ folder with the following contents -
SOURCES = $(wildcard *.c)
OBJECTS = $(SOURCES:.c=.o)
CFLAGS = -c -Iinclude
all: libfann.a
libfann.a: $(OBJECTS)
ar rcs $# $^
%.o: %.c
gcc $(CFLAGS) $^
Then use the make command in hello-fann-3/fann/ to build the static library. The above Makefile will generate libfann.a that you can link to your program.
Create a Makefile under your hello-fann-3/ folder with the following contents -
SOURCES = $(wildcard *.c)
OBJECTS = $(SOURCES:.c=.o)
CFLAGS = -c -I./fann/include
LFLAGS = -L./fann -lfann
main: $(OBJECTS)
gcc $(LFLAGS) $^ -o $#
%.o: %.c
gcc $(CFLAGS) $^
Then use the make command in hello-fann-3/ to build the main program.
In your main.c, you must include fan.h like -
#include "fann.h"
If you do not understand the Makefile, you can read about it here -
http://www.gnu.org/software/make/manual/html_node/index.html
You just need to link the fann library.
If you compile manually do this
gcc main.c -lfann -lm -o main
then simply run it like
./main
If you are on Ubuntu and you faced the following error
./main: error while loading shared libraries: libfann.so.2: cannot open shared object file: No such file or directory
Then run
sudo ldconfig
If you are using NetBeans, then simply Right click on your project -> Properties -> Build -> Linker,
then in the Libraries section click on the browse button [...] then in the new window click on Add Library...
Then add fann library (for example my fann library path is: /usr/local/lib/libfann.a) and click Ok
A fellow helped me, and we came to this line that compiled everything, and make the executable:
$ gcc fann/fann.c fann/fann_io.c fann/fann_train.c fann/fann_train_data.c fann/fann_error.c fann/fann_cascade.c main.c -Ifann/include -lm
And this is the answer.
That said, this is exactly what fixedfann.c is doing (include all this .c files). But if I try:
$ gcc fann/fixedfann.c main.c -Ifann/include -lm
..I get:
undefined reference to `fann_train_on_file'
This fann_train_on_file is on fann_train_data.c, which is included by fixedfann.c, so why it is undefined? I don't know... :/
--update
I realized that:
$ gcc fann/fixedfann.c main.c -Ifann/include -lm
will work if I comment the headers on fixedfann.c:
//#include "config.h"
//#include "fixedfann.h"
#include "fann.c"
#include "fann_io.c"
#include "fann_train.c"
#include "fann_train_data.c"
#include "fann_error.c"
#include "fann_cascade.c"

Am I writing this makefile correctly?

I am learning how to write C code in Linux and I am learning makefiles at a very beginner level.
I am having problems when making shared libraries.
The exercise is to make a simple function calculator C program with files:
main.c
add.c
subt.c
mult.c
div.c
The names of the files define the function they do.
The function in the file subt.c is in the static library:
libsubstatic.a
The function in the file mult.c is in the shared library:
libmultshared.so
For this program, I write the following makefile:
calc.exe: main.o add.o div.o libsubstatic.a libmultshared.so
gcc -o calc.exe main.o add.o div.o libsubstatic.a -Wl,-rpath,/home/ahmed/Desktop/labTask3 -lmultshared.so
main.o: main.c header.h
gcc -c main.c
add.o: add.c header.h
gcc -c add.c
libsubstatic.a: subt.o
ar cr libsubstatic.a subt.o
subt.o: subt.c header.h
gcc -c subt.c
libmultshared.so: mult.o
gcc -shared -fPIC -o libmultshared.so mult.o
mult.o: mult.c header.h
gcc -c -fPIC mult.c
div.o: div.c header.h
gcc -c div.c
The path where the code and makefile is placed:
/home/ahmed/Desktop/labTask3
I get the following message after I type "make" in the terminal:
gcc -o calc.exe main.o add.o div.o libsubstatic.a -Wl, -rpath, /home/ahmed/Desktop/labTask3 -lmultshared.so
gcc: error: unrecognized command line option ‘-rpath,’
make: *** [calc.exe] Error 1
What am I missing? Did I write this makefile correctly?
Please explain shared libraries, my concept might be faulty.
Please help.
Note that, I'm new to linux and I don't have much experience in makefiles.
EDIT: I removed the spaces as directed in the first answer. Now the terminal says:
gcc -o calc.exe main.o add.o div.o libsubstatic.a -Wl,-rpath,/home/ahmed/Desktop/labTask3 -lmultshared.so
/usr/bin/ld: cannot find -lmultshared.so
collect2: error: ld returned 1 exit status
make: *** [calc.exe] Error 1
Should I do something with the "-lmultshared.so"? What should I do?
-Wl, -rpath, /home/ahmed/Desktop/labTask3
Get rid of the spaces. This should all be one long argument.
-Wl,-rpath,/home/ahmed/Desktop/labTask3
See this excellent answer by #KerrekSB for a detailed explanation about passing arguments to the linker with -Wl.

Resources