Compiling error with errors like "multiple definition" - c

I am trying to compile my C program and I am getting some weird compiling errors and I have no idea where it is coming from. I already found similar posts, but their solution of specifying the output with -o is not working.
SO this is how my makefile looks like (shortened up):
CC = gcc -O3 -Wextra -Wall -pg -g -std=c99
OBJ = ./src/main.o ./src/FUNC.o ./src/getRoot.o ./src/getTree.o
out: $(OBJ)
g++ -std=c99 -g -o ./myProgramm $(OBJ)
./src/FUNC.o: src/FUNC.c
$(CC) -c src/FUNC.c -o ./src/FUNC.o
./src/main.o: src/main.c
$(CC) -c src/main.c -o ./src/main.o
./src/getRoot.o: src/getRoot.c
$(CC) -c src/getRoot.c -o ./src/getRoot.o
./src/getTree.o: src/getTree.c
$(CC) -c src/getTree.c -o ./src/getTree.o
This is a part of the errors i am getting:
./src/FUNC.o:(.rodata+0x78): multiple definition of `khStrInt'
./src/main.o:(.rodata+0x0): first defined here
./src/FUNC.o: In function `get_nbr_edge_kmer':
/home/Documents/EXAMPLE_CODE/src/FUNC.c:126: multiple definition of `DISTANCE_MAX'
./src/main.o:(.rodata+0x4): first defined here
./src/getRoot.o:(.rodata+0x0): multiple definition of `DISTANCE_MAX'
./src/main.o:(.rodata+0x4): first defined here
./src/main.o:(.rodata+0x4): first defined here
./src/getTree.o:(.rodata+0x0): multiple definition of `DISTANCE_MAX'
./src/main.o:(.rodata+0x4): first defined here
./src/getRoot.o:(.rodata+0x0): multiple definition of `khStrInt'
Does someone maybe have some idea what i am doing wrong here :/

Inside your header file, you should declare your variable like:
extern const int khStrInt;
Then in a .c file, you should define it like:
const int khStrInt = 33;
This means the variable definition is only generated once by the compiler when compiling the .c file and so the linker doesn't see multiple definitions. Also, having the declaration in the header file allows other files which include the header to be able to use the variable.

Quite likely the problem is caused by lack of #include guards.
To prevent a file from being included more than once
#ifndef myheader_h
#define myheader_h
#define DISTANCE_MAX 1000
#endif

Related

Linking error: Undefined reference to functions that're defined in a separate file?

I'm probably forgetting something obvious that'll solve this. While there's other questions on SO with the same issue, none of the solutions have been applicable to my situation.
I have a main file, sim.c, a header file net.h, a header file friends.h, and a file with the functions, net.c. I have a makefile, which I created with gmakemake > Makefile, and its contents are very basic.
Header.mak (makefile template):
CFLAGS = -Wall -Wextra -pedantic -std=c99 -ggdb
LFLAGS = -ggdb
LDFLAGS =
Makefile relevant contents:
CPP_FILES =
C_FILES = net.c sim.c
PS_FILES =
S_FILES =
H_FILES = net.h friends.h
SOURCEFILES = $(H_FILES) $(CPP_FILES) $(C_FILES) $(S_FILES)
.PRECIOUS: $(SOURCEFILES)
OBJFILES =
#
# Main targets
#
all: net sim
net: net.o $(OBJFILES)
$(CC) $(CFLAGS) -o net net.o $(OBJFILES) $(CLIBFLAGS)
sim: sim.o $(OBJFILES)
$(CC) $(CFLAGS) -o sim sim.o $(OBJFILES) $(CLIBFLAGS)
#
# Dependencies
#
net.o: net.h
sim.o: net.h
My sim.c file contains:
#include "net.h"
#include "friends.h"
My header file contains the functions in net.c and defines them all as stubs. I copied and pasted them to create the function headers, so there shouldn't be any typos.
My net.c file contains:
#include "net.h"
Yet any time a function in sim.c tries to call a function in net.c, it errors on that line with:
"undefined reference to `function_name`".
How can I make sim.c able to access the functions in net.c?
The message undefined reference to 'function_name' implies that of all the object files you're giving to the linker, none of them has a definition for function_name. That means that either
You're not linking with net.o
net.c (as compiled) does not contain a definition for function_name -- by 'as compiled' I mean with all of the various preprocessor options you use on it.
Since you show neither your link command line nor the contents of net.c, we can't tell which is the problem.
edit
with your edit, we can see clearly that you have the first problem -- when you try to link sim, you do not include net.o on the link command line. Most commonly, you would link sim with a makefile entry like:
sim: sim.o net.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $# $^ $(LDLIBS)
or more simply just:
sim: sim.o net.o
relying on the default make actions for linking object files
For the two functions "see" each other make sure that:
Both c/cpp files are included in the makefile
Both definition(c/cpp) and declaration (h) files contains the same definition of the function: name/params/return value
The function being called must not be static.
Make sure you don't declare (or include) the same type with different structure in the source files.
That should do, unless you are using a very old complier with even more evil things that can go wrong ;)

Including static library and header Makefile questions (C)

My file stacking is as follows
dir1/
mylib.a
myheader.h
file.c
executable
dir2/
dependentfile.c // depends on functions in myheader.h implemented in mylib.a
I would like to link my static library file in my Makefile WITHOUT using its name, but just indicating its path. What I have is as follows:
Makefile for dir2/
CC = gcc
CFLAGS = -g -Wall $(INCLUDES)
INCLUDES = -I../dir1
LDFLAGS = -g -L../dir1
exec: dependentfile.o
dependentfile.o: dependentfile.c
Running 'make' just gives me a bunch of implicit declaration errors, and undefined references because it's not looking in the paths I have specified with -L and -I. My dependentfile.c also has the line
#include "myheader.h"
which it can't find.
How should I modify the makefile in order to make this work? I have tried multiple things, even specifying the lib file with -l and writing the complete path to no avail.
Any help is appreciated!
#
EDIT: Figured it out!
Turns out I was forgetting LDLIBS. So for everyone else, the makefile ended up looking like:
CC = gcc
CFLAGS = -g -Wall $(INCLUDES)
INCLUDES = -I../dir1
LDFLAGS = -g -L../dir1
LDLIBS = -lmylib (my actual file was named libmylib.a, forgo the "lib")
exec: dependentfile.o
dependentfile.o: dependentfile.c
I think you should use
#include "myheader.h"
Your header file name should be quoted.

Calling a function from another C file

I am writing a graphics program in C/C++ using OpenGL. I have a bunch of .c files and right now, I am trying to call a function from main.cpp in assignment1gui.c. The teacher has given me a file with the compile code. It looks like this:
OBJS = assignment1gui.o shadertools.o main.o
TARGET = ass1
CXX = gcc
DBFLAGS = -O0 -g3 -ggdb3 -fno-inline
WFLAGS = -Wall -ansi
GLFLAGS = `pkg-config --cflags gtk+-2.0`
LGLFLAGS = `pkg-config --libs gtk+-2.0` -lGL -lGLEW -lGLU -lglut
CXXFLAGS = $(WFLAGS) $(DFLAGS) $(GLFLAGS)
LDFLAGS = -export-dynamic -lXext -lX11 $(LGLFLAGS)
all: $(TARGET)
clean:
rm -f $(OBJS) $(TARGET)
.SUFFIXES: .cc
.cc.o:
$(CXX) -c $(CXXFLAGS) $<
.c.o:
$(CXX) -c $(CXXFLAGS) $<
$(TARGET): $(OBJS)
$(CXX) -o $(TARGET) $(OBJS) $(LDFLAGS)
The function I am trying to call is "drawPloygonLine()". I have declared this in "assignment1gui.h", and the definition, as I mentioned earlier, is in main.cpp.
From all the help on the Internet, I realized that there must some problem with the compile code. But I am not sure. Could someone please help me out?
Sorry I left out this part earlier. The errors I am getting are:
assignment1gui.o: In function `on_btn_color_color_set':
assignment1gui.c:(.text+0x1c): undefined reference to `drawPolygonLine'
assignment1gui.o: In function `on_rb_tool_line_toggled':
assignment1gui.c:(.text+0x8b): undefined reference to `drawPolygonLine'
assignment1gui.o: In function `on_rb_tool_circle_toggled':
assignment1gui.c:(.text+0xfc): undefined reference to `drawPolygonLine'
assignment1gui.o: In function `on_rb_tool_rect_toggled':
assignment1gui.c:(.text+0x16d): undefined reference to `drawPolygonLine'
assignment1gui.o: In function `on_rb_tool_edit_toggled':
assignment1gui.c:(.text+0x24a): undefined reference to `drawPolygonLine'
collect2: ld returned 1 exit status
make: *** [ass1] Error 1
The C/C++ files I have in the folder are main.cpp, assignment1gui.c and shadertools.c. I also have two header files- assignment1gui.h and shadertools.h. As I have mentioned earlier, I used the assignment1gui.h file to declare the new function "drawPolygonLine();"
Addition:
The declaration of the "drawPolygonLine();" is now in "main.h" and it looks like this:
#ifndef MAIN_H
#define MAIN_H
extern void drawPolygonLine();
#endif /* MAIN_H */
Both main.cpp and assignment1gui.c have "#include "main.h"" at their beginning. The definition of drawPolygonLine() is:
void drawPolygonLine()
{
if(option[opCount-1]==4 && drawn==false)
{
vCount++;
vertex[vCount].x=A;
vertex[vCount].y=B;
lines=lines+2;
vCount++;
vertex[vCount].x=polyX;
vertex[vCount].y=polyY;
clicks=0;
drawn=true;
}
}
All the variables used in the function are global in main.cpp.
An example of how I am calling drawPolygonLine(); in assignment1gui.c is in this function:
void on_btn_color_color_set(GtkColorButton *colorbutton, gpointer user_data)
{
drawPolygonLine();
GdkColor color;
gtk_color_button_get_color(colorbutton, &color);
printf("Color set rgb=(%i,%i,%i)\n",color.red,color.green,color.blue);
}
I hope this makes it clear.
The problem is that main.cpp isn't understood by this make file, since it only has rules for .cc or .c files. I suspect that main.o isn't being built - or, more likely, since you're getting as far as a failed compile, there is another file called main.c or main.cc which IS included in your program, but doesn't have drawPolygonLine() defined in it.
To solve this:
Remove or rename any existing main.c or main.cc files.
If your program is actually a C program, then change the filename to main.c
If your program is a C++ program, you could try changing the extension to .cc, but I suspect you'll then run in to problems since you're using gcc rather than g++. In this case, I'd also change:
CXX = gcc
to
CXX = g++
Remember that although a lot of C code is also valid C++ code, there are many subtle differences - and the best practices are very different in each language. For this reason, it's best to treat C and C++ as different languages.
If this doesn't fix it:
Check that the function signature of drawPolygonLine() declared in your header file is the same as the way it's defined in your main file. Check that these declarations match with the way you've called it.
Check that the files that call drawPolygonLine() have #include "assignment1gui.h" at the top
Check that drawPolygonLine() isn't declared as static (static functions aren't visible outside their translation unit - so the linker won't see them when compiling two output files together)
Also, it's good practice to have the function declaration in the header file corresponding to the source file it's defined in - so if you want to call a function in main.c from assignment.c, you would usually put the declaration in main.h, and #include it at the top of assignment.c. This won't be the cause of the problem that you're having, but it's good practice to get used to.

Figuring out multiple file compilation with make & C

For a project, I was working with a partner writing a decision tree implementation. Since both of us are relative newcomers to C and had to work quickly, we basically dumped all the functionality in a single file, which ended up being over 1600 lines. It was a quick and dirty project to get working, but now the next assignment has us responsible for extending and re-implementing the code. In its current condition, that isn't going to happen.
Right now, I'm breaking up the original source based on function responsibility. Thing is, many of the functions are intertwined, and I'm getting major errors with my make file. More specifically, the other source files are reporting implicit declaration of functions that are declared in a separate file.
I really have no experience with multiple file makefiles. The current syntax is borrowed from a simple shell implmentation in last years Systems Programming class, although this current project is an order of magnitude greater in complexity.
cc= gcc
CFLAGS= -g -Wall -lm
proj2: main.o split.o tree.o id3.o output.o
$(CC) $(CFLAGS) -o proj2 main.o split.o tree.o id3.o output.o
I also tried a previous version where each object file was compiled separately like
main.o: main.c split.c tree.c id3.c output.c
$(CC) $(CFLAGS) -o main.c split.c tree.c id3.c output.c
and this repeated to create a .o file for each source, which then was compiled into an executable.
However, that didn't work and I got about 500 lines of compiler complaints and warnings, mainly about implicit function declarations.
So, essentially I have two related questions:
is it possible to intertwined function calls between different source files?
if so, how can I make it possible here?
First a word about your makefiles.
proj2: main.o split.o tree.o id3.o output.o
$(CC) $(CFLAGS) -o proj2 main.o split.o tree.o id3.o output.o
This should work (if the code is correct) but if you're using GNUMake (which you should) you can tidy it up:
proj2: main.o split.o tree.o id3.o output.o
$(CC) $(CFLAGS) -o $# $^
Now you have only one copy of the object list to maintain.
The other version is just wrong:
main.o: main.c split.c tree.c id3.c output.c
$(CC) $(CFLAGS) -o main.c split.c tree.c id3.c output.c
First, you're trying to compile all of the source files into one object file, which kind of defeats the purpose of object files. Second, you're naming your one object file main.o when that name should really belong to an object file made from main.cc. Third, the command tells the compiler to compile all of the other source files (split.c, tree.c, ...) into an object file called "main.c"-- not illegal, but you're bound to trip yourself up.
Also, you should try to use C++, not C, but that's for another day.
Now for breaking up the Big Ball of Mud. I assume you know how to break big functions into smaller ones, so the problem is segregating functions into different source files (and then compiling and linking them correctly). Suppose main() calls a function foo():
/* main.c */
void foo()
{
// do foo things
}
int main()
{
// do main things
foo();
return(0);
}
As you know, the foo must come first, otherwise the compiler would balk when main tried to call an undeclared function. But we can declare foo beforehand:
/* main.c */
void foo();
int main()
{
// do main things
foo();
return(0);
}
void foo()
{
// do foo things
}
When the compiler reaches the call to foo(), it already knows that such a function exists, and trusts us to define it later. Now here's the trick: if we instruct the compiler to compile, but not link (that is, produce an object file like main.o, not an executable like proj2), it will trust us even farther:
/* main.c */
void foo();
int main()
{
// do main things
foo();
return(0);
}
That will compile into main.o quite nicely. The compiler trusts us to provide the definition of void foo() in some other object file when we link things together into an executable. The definition will be in another file like so:
/* foo.c */
void foo()
{
// do foo things
}
We could build this by hand:
gcc -g -Wall -lm -c foo.c -o foo.o
gcc -g -Wall -lm -c main.c -o main.o
gcc -g -Wall -lm foo.o main.o -o proj2
But that gets tedious fast, so we'll write a makefile:
cc= gcc
CFLAGS= -g -Wall -lm
proj2: main.o foo.o
$(CC) $(CFLAGS) -o $# $^
%.o: %.c
$(CC) $(CFLAGS) -c -o $# $<
So far so good. If this much is clear then we can move on to header files...
You need to create header files for each of the source code to have the declarations in them. You then #include the appropriate header files at the top of the source code.

Undefined reference maybe makefile is wrong?

I had some issues earlier with declaring my array set of records. Now I think there is something wrong with my Makefile or something.
Here is my Makefile:
EEXEC = proj1
CC = gcc
CFLAGS = -c -Wall
$(EXEC) : main.o set.o
$(CC) -o $(EXEC) main.o set.o
main.o : main.h main.c
$(CC) $(CFLAGS) main.c
set.o : set.h set.c
$(CC) $(CFLAGS) set.c
There are more functions I have in my set.c file but these are the functions I am testing at the moment:
DisjointSet *CreateSet(int numElements);
DisjointSet *MakeSet(DisjointSet *S,int ele, int r);
void Print(DisjointSet *S);
And the errors I am receiving in the terminal is:
main.o: In function `main':
main.c:(.text+0x19): undefined reference to `CreateSet'
main.c:(.text+0x43): undefined reference to `MakeSet'
main.c:(.text+0x5f): undefined reference to `Print'
The errors that you're getting are linker errors, telling you that while linking your program the linker can't find a function named 'CreateSet' (etc.). It's not immediately obvious why that should be the case, because it appears that you're including "set.o" in the build command.
To troubleshoot build problems, it's often useful to figure out what make is trying to do, and then run the commands individually one at a time so you can see where things go wrong. "make -n" will show you what commands "make" would run, without actually doing them. I would expect to see a command like:
gcc -o proj1 main.o set.o
try running that by hand and see where it gets you.
Make sure you have included set.h in main.c
Also you declare EEXEC but use EXEC...
If these are all on one line in the makefile:
EEXEC = proj1 CC = gcc CFLAGS = -c -Wall
Then you have one macro EEXEC whose value is proj1 CC = gcc CFLAGS = -c -Wall, and you have no CC or CFLAGS macro. CC probably has a default, which is why that much is working.

Resources