Makefile error : duplicate symbol _main in - c

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

Related

makefile: undefined reference to main

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.

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

Cannot find -lCommunication collect2: error: ld returned 1 exit status

I do not know gcc and c well. In my /home/pi/Desktop/intern/adis16227_generic directory I have following 5 files.
ADIS16227.c
ADIS16227.h
Communication.c
Communication.h
main.c
main.c
#include<stdio.h>
#include "Communication.h" // Communication definitions.
int main() {
printf("hello!!\n");
unsigned char status = 0;
status = SPI_Init(0, 1000000, 1, 1);
printf("%u", status);
return 0;
}
Run command:
$ sudo gcc -L /home/pi/Desktop/intern/adis16227_generic main.c -lCommunication
Error:
/usr/bin/ld: cannot find -lCommunication
collect2: error: ld returned 1 exit status
Question:
What I am missing here?
What do I need to run the code?
-l is for libraries, and you never built a library from your Communication.c. The simplest solution is just add Communication.c to your compiler command line.
For larger projects, compile each translation unit separately with the -c switch like this:
gcc -c -Wall -Wextra -pedantic -omain.o main.c
gcc -c -Wall -Wextra -pedantic -oCommunication.o Communication.c
and so on ... (as a suggestion, I added some common warning options here, they help you spot errors)
The resulting .o files are object code. That's already compiled machine code, but with meta-information needed for a linker to link it with other object code into a complete executable.
Then link them all with one command:
gcc -oprogram main.o Communication.o
If you actually want a library from -- say -- Communication.c and ADIS16227.c, you could compile both to object code:
gcc -c -Wall -Wextra -pedantic -oCommunication.o Communication.c
gcc -c -Wall -Wextra -pedantic --oADIS16227.o ADIS16227.c
and then use ar to create a static library from them:
ar rcs libCommunication.a Communication.o ADIS16227.o
Then your initial compiler command would work (with the -lCommunication switch).
Final piece of advice: Never compile as root. This is completely unnecessary. So remove your sudo here.
those options:
-L /home/pi/Desktop/intern/adis16227_generic -lCommunication
suggest that the linker should find libCommunication.a (or .so) in the /home/pi/Desktop/intern/adis16227_generic directory.
But there are only sources in this directory. The linker won't build the sources of your "Communication" library for you.
So you could build the library and link with it:
gcc -c ADIS16227.c Communication.c
ar r libCommunication.a ADIS16227.o Communication.o
but maybe the fastest & quickest way to achieve a successful build would be:
sudo gcc -o main *.c
so it compiles all the files of the directory into the executable called main
Of course, it makes compilation times longer, but maybe it's not noticeable.
First move into the /home/pi/Desktop/intern/adis16227_generic directory:
cd /home/pi/Desktop/intern/adis16227_generic
Then, compile the source:
gcc ADIS16227.c Communication.c main.c -I .
You can now run your compiled program (called by default a.out):
./a.out
You have to compile separatedly files and then compile main with related obj file.
gcc -c Communication.c Communication.h
gcc main.c Communication.o -o main

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

linking pthread library issue

Am facing a problem that may be slightly complicated to explain and understand as giving the entire picture would be too big and difficult.
Please excuse me for it.
Consider the following Makefile:
all: clients.so simulator backup
LD_PRELOAD=/home/Juggler/client/clients.so ./simulator
backup: backup.c libclient.a
gcc backup.c -o backup -L /home/Juggler/client -L. -lclient -ldl
simulator: simulator.c libclient.a
gcc -g simulator.c -o simulator -L /home/Juggler/client -L. -lclient -ldl -pthread
libclient.a: libclient.o client.o
ar rcs libclient.a libclient.o client.o
libclient.o:libclient.c
gcc -c libclient.c -o libclient.o -pthread
clients.so: client.o client_invoke.o
ld -shared -o clients.so client_invoke.o client.o -ldl
client_invoke.o: client_invoke.c
gcc -Wall -fPIC -DPIC -c -g client_invoke.c
client.o: client.c
gcc -Wall -fPIC -DPIC -c -g client.c -ldl -pthread
We call function written in client.c from libclient.c and these functions in client.c make call to pthread_key_create(), pthread_setspecific..etc.
Threads are created by simulator.c and theses threads access functions written in he other files.
On doing make...Errors like the following appear.
/home/Juggler/client/libclient.a(client.o):In function 'setup_connection':
/home/Juggler/client/client.c:35: undefined reference to 'pthread_setspecific'
pthread.h has been included in both client.c and libclient.c
Would be grateful for anypointers . I understand information is very less...
Thanks
On linux, pthread functions live in the libpthread library. So you have to link to that.
The proper way, when using pthreads, is to compile and link using the -pthread , which, among other things, will link in the pthread library. You have the -pthread flag for some of your executables, but not for others, and not for your clients.so library, so add the flag where required.
Also, remember, when you are creating a shared library, you should compile the source files with the -fPIC flag.
(And, seems you are calling ld directly to produce the client.so library, you really should use gcc to do the linking.)

Resources