I have to compile those files in that order: a first and then b because of other requirements.
now the files are of this form:
a.h
void caller_func(void);
a.c
#include "a.h"
#include "b.h"
void caller_func(void){
called_func(void);
}
b.h
void called_func(void);
b.c
#include "b.h"
void called_func(void){
//any action
}
and on compilation i get
a.so: undefined reference to 'called_function'
is there anyway to go around this (besides changing compilation order)?
The code, as written, should not have a problem. However, you must insure that you both compile a.c into a.o and b.c into b.o and link them.
Your compile line should look something like:
gcc a.c b.c -o a.out
Or:
gcc -c a.c b.c
ld -o a.out a.o b.o
In the first example, gcc will invoke ld behind the scenes to link the executable for you. In the second example, you're explicitly carrying out the compile and link steps.
I have to compile those files in that order: a first and then b because of other requirements.
No, you don't have this requirements. Both modules have nothing todo with each other.
What you have to do is maybe linking in the correct order if one of the modules is contained in a library. But I don't think that is the problem here.
Another hint: It is not important to include the declaration before the definition here if both are identical!
What you have to do is simple: compile & link in one stage like
gcc a.c b.c -o prog
or compile in 2 steps ( order doesn't matter at all )
gcc a.c -c
gcc b.c -c
gcc a.o b.o -o prog
All this is on the assumtion you take gcc on linux. But most other compilers will behave in the same way. Feel free to ask for special compilers or environments or OSs.
"undefined reference to 'called_function'" means the linker can't find the machine code generated from compiling b.c; either you're not compiling that file, or the object code generated from compiling it isn't being included in the final link command.
Assuming gcc, you'd do something like
gcc -c a.c # compiles a.c, generates object file a.o
gcc -c b.c # compiles b.c, generates object file b.o
gcc -o prog a.o b.o # links the object files into an executable named prog
It sounds like you've written something like
gcc a.c
which compiles a.c, then attempts to link it into an executable (default name a.out or a.exe, depending on your platform).
Related
I have written c program, Which has 3 file(.c ) , Main program has
two threads and one file has mysql connection function, One file has
thread functions definition. I don't know how to compile all these
codes, Normally I tried like this,
cc -pthread main.c
But if I compile like this I am getting error called mysql functions
are undefined But I have written thread as separate program and
mysql as separate program and complied individually , it complied
successfully and I got output. So please help me to compile my
project File names are,
main.c (2 threads are declared) functions.c (thread function
definition, and mysql func declared) db.c ( mysql function
definition)
please help to compile my code?
You have two basic options when compiling multiple .c files:
Option 1)
cc file1.c file2.c file3.c -o executable_name
Advantage: simple
Disadvantage: if all you change is one file you are recompiling all the files
Option 2)
cc file1.c -c -o file1.o
cc file2.c -c -o file2.o
cc file3.c -c -o file3.o
cc file1.o file2.o file3.o -o executable_name
Advantage: If you change one file you do not have to recompile everything
Disadvantage: Multiple commands (but you should use a Makefile at this point)
The -c flag tells the compiler to compiler but not link. You don't want to link as you have not compiled all of your files. The final invocation of cc links all the .o files into the executable executable_name
It is a little bit difficult to understand exactly what you need, but I can tell you from what you've stated that you'll need to include specific libraries in your compile statement you currently are not. Also, a -l flag needs to prefix your libraries.
Try something like this:
gcc -lpthread main.c functions.c db.c -o main $(mysql_config --libs)
To explain, mysql_config --libs returns all the configuration libraries needed to run mysql ddl inside your C program.
Given your updates on your file declarations I'm guessing you're a Java programmer. C is not Java. If you are declaring functions you are only going to use once in main.c you should put them inside main.c unless you need them to be portable.
What linking step am I missing? I'm trying to make a dynamic library from file c.c:
#include "a.h"
#include "b.h"
int my_function(void)
{
return a() + EIGHT;
}
which depends on a.c:
int a(void)
{
return 1;
}
and b.h:
enum {
EIGHT = 8,
};
I run gcc -c c.c -o c.o to compile the object file. Then I run
gcc -Wall -dynamiclib -o libc.dylib c.c
and I get this error.
Undefined symbols for architecture x86_64:
"_a", referenced from:
_b in ccx5LSkL.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
How can I properly link the files? References addressing this specific problem would be awesome.
So your first line, gcc -c c.c -o c.o, compiled the object file c.o. Now you then have to use c.o for creating the final result. So your linking step should be using c.o, not c.c.
Next, the error you are getting is that the symbol "_a" was not found. This is coming from you calling the function a(), but not including it in the linking step. To do that you need to also compile a.c and include it when linking your final product.
So in total, your process should be:
1) compile:
gcc -c a.c -o a.o
gcc -c c.c -o c.o
2) link:
gcc -Wall -dynamiclib -o libc.dylib a.o c.o
Note that to compile libc.dylib, you had to include all the sources that the final result would depend on.
Finally, you don't actually need to compile all of the object files separately. You can compile and link together in one combined step by just providing the *.c files right away.
gcc -Wall -dynamiclib -o libc.dylib a.c c.c
So your problem was really just about not including both sources together. (Other than -dynamiclib, everything actually works basically just like compiling a regular executable.)
I have a custom header file example.h which has prototypes for a few functions. There is a .C file example.c that I implemented which "includes" (#include "example.h") and has the implementations of the functions that has prototype in example.h.
Now, I have another function test.c that has to call the functions that are prototyped in example.h and are implemented in example.c. How Can I do it?
You need to link them all at the end (assuming you have already included the prototypes into your test.c). So if you're compiling, you can compile both of the .c files together into one executable. More commonly, however, is to compile these without linking (which produces object files). Then, at the end, link all of the object files together. To do this depends on your compiler, but an example would be:
gcc -c -o example.o example.c
gcc -c -o test.o test.c
gcc -o my_application test.o example.o
Or, for a small project, this works just as well
gcc -o my_application example.c test.c
Just #include "example.h" in test.c (and don't forget to link all of the object files!)
header.h declares a function prototype void InitializeTestData();
a.c declares it void InitializeTestData() { ... }
b.c calls it InitializeTestData();
and the GCC linker reports b.c:108: undefined reference to '_InitializeTestData'
I must be overlooking something obvious, but what?
header.h does have an include guard (and its #define is used only in that file).
There are no other preprocessor directives involved ... no #if wrapped around the prototype or declaration.
Without me having to post the whole project, can someone suggest something to make me say d'oh!?
Update: Netbeans handles it and has no problems with the dozen other files with external functions and data.
Answer: a.c was actually a NetBeans test file. NetBeans handles these differently from other files, since they each need to have an amain(). That means that they each have their own Makefile and b.o was not linking with a.o in that file. Solution, move the declaration to a file c.c which is not a Netbeans test file.
Are you linking a.o with b.o? Most likely you aren't.
The error is from the linker and it means the reference of the function InitializeTestData in b.o is not resolved.
The reason is you are not liking a.o (which contains the definition) with the b.o.
You need to do:
# this will compile both the .c files and also link the resultant .o
gcc -o output a.c b.c
or
gcc -c a.c # get a.o
gcc -c b.c # get b.o
gcc -o output a.o b.o # link them
Something is calling _InitalizeTestData (note the underscore), but you probably don't define it in either file. Could you have put an underscore somewhere by mistake, of forgotten to implement that?
I'm trying to learn how to create a C/C++ library in a linux environment but I'm having a problem (probably a trivial one) that online tutorials had not helped to solve.
For definiteness let's say I have a foo.c file with the following code:
//file: foo.c
#include <stdio.h>
void hello(void)
{
printf("hello!\n");
}
a foo.h:
//file: foo.h
void hello(void);
and a program that uses the function hello() from foo.c, named prog.c:
//file: prog.c
#include "foo.h"
int main(void)
{
hello();
return 0;
}
The three files are all on the same directory. Then I compiled foo.c with:
gcc -fPIC -c foo.c
and got a foo.o file. Then I used ld to create the library file:
ld -G foo.o -o libfoo.so
But when I try to compile prog.c with:
gcc -o prog prog.c -lfoo
I got an error message:
/usr/bin/ld: cannot find -lfoo
collect2: ld returned 1 exit status
I'm convinced that this is some kind of trivial path problem, but I couldn't find the solution. So my question is really if this procedure above is wrong or if I have to put the libfoo.so file in a special path.
Another question is how this changes if I'm using g++ instead of gcc.
Thanks.
EDIT:
I know I can compile both prog.c and foo.c to prog.o and foo.o an then link them to make an executable. But in my original problem I want to compile foo.c in a way that I can distribute to people who will use my functions in their own programs.
ld doesn't search the current directory by default. If you want it to do this you need to use the -L command line option, so if your library is in the current directory you need to add -L. to the last gcc call. If the library is dynamically linked you also need to add the current directory to the environment variable LD_LIBRARY_PATH (I assume you're on linux).
Of course, if your library is in any other non-standard path you need to use that instead of the current directory.
Try
gcc -o prog prog.c -lfoo -L.
The -L switch adds its argument to the set of paths that ld looks in for library files. The syntax is identical for g++.