Using function from another c file by including its header - c

I am writing C code (not C++) on a Linux system. I am trying to compile one executable from 2 .c files and 1 header file: main.c, sort.c, and sort.h.
main.c's first line reads: #include "sort.h"
inside sort.h, each function in sort.c is defined like this example:
extern void aFunct(int param);
However, when I try to call a function in sort.c from main.c, I get the following error upon compilation: "undefined reference to 'aFunct'".
If i replace #include "sort.h" with #include "sort.c" my program works without issue. However, as I understand it, this is bad form and I would prefer to avoid this. Thanks for any help.
edit: I am compiling this with a makefile containing the following code:
all: index sort.o
sort.o: sort.c sort.h
gcc -Wall -g -c sort.c
index: main.c sort.o
gcc -Wall -g -o index main.c
clean:
rm index
rm sort.o
edit: I have fixed the problem. The problem did not stem from a misunderstanding of C files and how they link, but rather a misunderstanding of the makefile/gcc commands themself. My program works with the following makefile:
all: index sort.o
sort.o: sort.c
gcc -Wall -g -c sort.c
index: main.c sort.o
gcc -Wall -g -o index main.c sort.o
clean:
rm sort.o
rm index

You should include #include "sort.h" in sort.c as well.
You might be doing this already.
The important point is, you need to make sure that you are building both the .c files [main.c and sort.c]
Now both these obj files [main.o and sort.o] should be the input to linker.
As per my guess, you are not compiling sort.c , so linker is not able to see the implementation of the functions.

When you include one source code file to other (e.g. #include "sort.c") you can have a troubles if you include sort.c file to more than one c-file of the same project. But as I understand you just compile one c-file in which you include sort.c... so it works. But, better read some tutorials, for example How to Create Multi-Module Programs

Related

Where to change LD_LIBRARY_PATH

I want to compile these files into executable.
//main.c
#include <stdio.h>
#include <mylib.h>
int main(void){
call_hello_world();
return 0;
}
//mylib.h
void call_hello_world(void);
//mylib.c
#include <mylib.h>
#include <stdio.h>
void call_hello_world( void ) {
printf( ”Hello world!” );
}
I tried
gcc -c -I. -fPIC -o mylib.o mylib.c
gcc -shared -o libmylib.so mylib.o
gcc -c -o main.o main.c
gcc -o hello main.o -L. -lmylib
but at the third step, I got stucked because it couldn't find my 'mylib.h'. My professor said I needed to change 'LD_LIBRARY_PATH' so I tried to add this export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/dev/shm my .zshrc but it still didn't work for me. Any suggestions what I should do?
There are several issues with your approach.
First, there is a difference between including a header file like this #include <mylib.h> and including it like that #include "mylib.h".
The first option is usually used to include standard library header files, that should be located in the standard set of directories according to the FHS on Linux.
The latter is the option you might want to use as it is usually used to include user-defined headers and tells the preprocessor to search in the directory of the file containing the directive. (See #quest49 answer's https://stackoverflow.com/a/21594/3852949)
The LD_LIBRARY_PATH environment variable is used to indicate where libraries should be searched for first before looking into the standard set of directories.
So what you would want to do to make your main.c file compile, and after changing #include <mylib.h> directive to #include "mylib.h", is to either :
Add the include file into the directory where your main.c file is located
Indicate where the include file path is with -I option to gcc
These are the commands needed :
gcc -c -I. -fPIC -o mylib.o mylib.c
gcc -shared -o libmylib.so mylib.o
gcc -c -I. -o main.o main.c
gcc -o hello main.o libmylib.so
Then in your shell:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/full/path/of/directory/containing/libmylib-so

Unable to identify issue GNU archiver. Compiling with *.o works but libname.a dosen't

I'm trying to make a static library (.a) but facing issues that I'm unable to understand. So in brief compiling with *.o succeeds but archiving them using ar and then using the .a file to compile gives me an undefined reference to 'symbol' error.
So here is a simple code.
test.c
#include <stdio.h>
#include <string.h>
int main()
{
hello_world();
return 0;
}
hello_world.c
#include<stdio.h>
void hello_world (void) {
printf("Hello World\n");
}
Compile.
gcc -c -o hello_world.o hello_world.c
ar crs libhello.a hello_world.o
gcc libhello.a -o test test.c
gives me the error
/tmp/ccsO7AJl.o: In function `main':
test.c:(.text+0xa): undefined reference to `hello_world'
Instead doing this works(Compiles and runs fine)
gcc -c -o hello_world.o hello_world.c
gcc hello_world.o -o test test.c
I have no idea what I have done wrong so any help is appreciated.
This is an almost duplicate of Why does the order of '-l' option in gcc matter? - but the behaviour can be replicated without the -l switch by specifying the archive name on command line.
The GNU linker as executed by GCC will, by default, link from left to right, and only use those .o files from the library archive that are needed to satisfy undefined references so far. Since your library precedes the main translation unit on the command line, hello_world is not required at the time the linker is processing it.
The solution is to mention the library after the translation units/object files that depend on it:
gcc -o test test.c libhello.a

compile .so with .h

I have three files:
list.c, recursive.c, recursive.h
the 2nd and third are the header and .c of an auxiliary function called: recursive.
The first one is a file that im trying to compile as a .so. It does an include of recursive.h with:
#include "recursive.h"
Normally i would compile it with:
gcc -Wall -shared -fPIC -o list.so list.c
but whenever i run the code from a client program i get the following:
./shell: symbol lookup error: /home/list.so: undefined symbol: recursive
As suggested by Ctx. The solution was to compile with:
gcc -Wall -shared -fPIC -o list.so list.c recursive.c

Source file cannot find the header files

I have looked at these links : This one
and This
and a couple of other similar ones.
None of the answers given here are working methods are working.
I have a two source files a1.c , a2.c and two header files a1.h and a2.h . I want to include the header files in both these files (and a2.c in a1.c as there is a function I need to use from a2.c)
I have included
#include "a1.h"
#include "a2.h"
in the source files of a1.c
I'm using GCC on Ubuntu. and using the command gcc a1.h -o a1.out -lm
and that didn't work.
I tried with
gcc -c -I/Home/Documents/ctests/ a1.c -o a1.out
as well as
gcc -c a1.c -I/Home/Documents/ctests/ -o a1.out
My spellings are okay as well (there's hardly any room for error there with one letter and a number as the filename anyway).
Also, all the files are in the same folder.
I know this may be a trivial question but I am stuck on this one and would appreciate any help. I am relatively new to programming and completely new to Linux and Unix as far as using the command line goes.
Many thanks!
gcc -c
tells gcc to compile the file to object (the .o files you see everywhere). To be linked later with some other .o files to an executable.
So what you want to do is either compile the two files separately and link them later. like this.
gcc -I"/Home/Documents/ctests/" -c a1.c
gcc -I"/Home/Documents/ctests/" -c a2.c
gcc -o myprogram a1.o a2.o
Or just compile and link at the same time.
gcc -I"/Home/Documents/ctests/" a2.c a1.c -o myprogram
And then run your program like
path_to/myprogram
Compile everything, and link it together.
If all files are in one directory, this should work:
gcc a1.c a2.c -o myapp
When you want to create separate object files, do this:
gcc -c a1.c a2.c
Then you can then link together to create an application:
gcc a1.o a2.o -o myapp
Your gcc command should be like this
gcc -I/Home/Documents/ctests/ -o a1.out a1.c
and you have to include a1.h and a2.h header file in your a1.c like this
#include "a1.h"
#include "a2.h"
If you are calling some function from a2.c in your a1.c then you have to build your program in this way
gcc -I/Home/Documents/ctests/ -o a1.out a2.c a1.c

Is it a header file or library? in a makefile

I already know the differences between a header file and a library. However, when I'm writing my makefile, I have some difficulties on deciding if I should put something as a dependency of the file or just at the linking rule.
For example: I have 2 simple files:
main.c:
#include <stdio.h>
main(){
printf("this is the sine or 90");
sinus(90);
}
and func.c:
#include <math.h>
sinus(int num){
return sin(num);
}
and my makefile is:
main: main.o func.o
gcc main.o func.o -lm -o main
func.o: func.c
main.o: main.c
Well, my question is why this makefile works and this one doesn't:
main: main.o func.o
gcc main.o func.o -lm -o main
func.o: func.c math.h
main.o: main.c
You don't need to make func.o depend on math.h as that file is very unlikely to change.
Regarding the error you get if you do is because you don't explicitly specify how make should compile the file so it tries to deduce how to compile it and it only works in simple cases. I'm not sure exactly how make does it but I think it just does gcc -o target.o -c <your deps>.
Because make is looking for a file "math.h" in the current directory and trying to do cc func.c math.h to produce func.o
Problem is that you don't know exactly how Makefile is resolved after using implicit rules - definitely there's one which causes problems you have. (maybe try to compile math.h, or math.h is not found etc.. (you didn't posted errors you have so we can only speculate).
I would advice you to disable implicit rules by calling make with "-r" and do everything explicitly - this way you will learn more as you'll know how makefile works instead of knowing how to write makefiles which works under some circumstances.
More on implicit rules: Make documentation - Implicit rules
More on make Make documentation

Resources