compile .so with .h - c

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

Related

C Link External Library in Makefile

I am having issues linking a library (termbox) when compiling. I get the error:
make: *** No rule to make target `termbox.h', needed by `test.o'. Stop.
Makefile:
edit: test.o
gcc -Wall -o edit test.o
test.o: test.c termbox/src/termbox.h
gcc -Wall -c test.c -ltermbox/src
Include:
#include "termbox/src/termbox.h"
I have also tried using the compiled library but ran into similar issues. Do I have to use some sort of combination of specifying the header file and the location of the compiled library?
The directory of my termbox folder is in the same directory as test.c.
Thanks!
You have managed to compile and include the header file for the library, but you did not yet tell the compiler where the code (definitions) are - i.e. you did not tell it to link in the library yet.
You will need to do that next, this is done in a similar way to telling the linker what files to link, but with some extra syntax. It appears to be a static library (.a suffix) so you can link like this:
test.o: test.c termbox/src/termbox.h
gcc -Wall -c test.c -Itermbox/src -Lsrc -ltermbox
Where -L... specifies where libraries can be found and -l... specifies the library name to link to minus the lib prefix and the .a or .so suffix. Also note that order is important, so leave the library linkage at the end.
More on library linking order here
UPDATE
Sorry I added the linking to the wrong line! - here is the updated answer:
# The linker stage
edit: test.o
gcc -Wall -o edit test.o -Lsrc -ltermbox
# Compile stage
test.o: test.c termbox/src/termbox.h
gcc -Wall -c test.c -ltermbox/src

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

Custom C library: can functions in the same library refer to each other?

I've just started to create my own C libraries to keep my commonly used functions tidy. However, I've hit a new problem and I struggled to find information on the best route to take.
I generate my library of two functions using the following:
gcc -I. -c -fpic rand_site.c
gcc -I. -c -fpic rand_spin.c
gcc -shared -o libstatphys.so rand_site.o rand_spin.o
Each of these source files contained a single function. I was hoping to create a third function for my library that uses the two functions above but I'm not sure how to use functions from within the same library.
Am I going about this the right way? What is the best practice for doing this?
Yes, you can.
Create a header file rand_site.h and put the declaration of the function defined in rand_site.c in it.
Create a header file rand_spin.h and put the declaration of the function defined in rand_spin.c in it.
Use #include to include the two .h files in the third file, say foo.c.
Then compile foo.c and add it to the library using:
gcc -I. -c -fpic foo.c
gcc -shared -o libstatphys.so rand_site.o rand_spin.o foo.o
If you would like to create a second shared library that has foo.o, you can use:
gcc -I. -c -fpic foo.c
gcc -shared -o libfoo.so foo.o -lstatphys
If you would like to create an executable using foo.o, you can use:
gcc -I. -c foo.c
gcc foo.o -lstatphys

C - programming a makefile and how they work

So given three files:
main.h
#include <stdio.h>
void printFunc(*char);
main.c
#include "main.h"
int main(){
printFunc("Hello World\n");
return 0;
}
printFunc.c
#include "main.h"
void printFunc(char *string){
printf("%s", string);
return;
}
You can compile using gcc on a linux machine as follows:
gcc -g -Wall -c file1.c //compile but do not link file
gcc -g -Wall -c file2.c //same
gcc file1.o file2.o -o main //executable "main"
or
gcc -g -Wall file1.c file2.c -o main
But I am concerned with how the header file gets included. I came across this when I was working on creating a "makefile" when I noticed that some tutorials will do something like this:
main : main.o printFunc.o
gcc -o main main.o printFunc.o
main.o : main.c
gcc -g -Wall -c -o main.o main.c
printFunc.o : printFunc.c
gcc -g -Wall -c -o printFunc.o printFunc.c
and others will include the header file as a dependent with:
main : main.o printFunc.o //main.h EDIT
//commands
main.o : printFunc.o main.h
//commands
Finally:
So, is it necessary to include the header file as a dependent to the executable? When does the include file get placed within the sources?
And also one could use this command:
executableName : dependencies.o //and a header file?
gcc -g -Wall -o executableSource.c
Which could be done with the line:
gcc -g -Wall -o executableName executableSource.c
Will the second command be run but the first is shorthand notation?
And finally, I thought the "-o" command was "send output to", if you will. If that way, it seems intuitive to run the command like:
gcc compileThisFile andSendOutputTo thisExecutableFile
gcc someSource.c -o executableFile
But with the notation listed above its more like:
gcc sendOutputTo thisExecutableFile fromThisSource
Is that correct?
main : main.o printFun.o main.h is definitely wrong. That's saying that the header is a prerequisite for linking. A header is a prerequisite for compilation.
Assuming what you really meant was to specify the header as a compilation dependency (e.g. printFunc.o : printFunc.c printFunc.h), this means that if the header changes, the object file will be automatically regenerated. If you don't, then it won't.
A dependency in Makefile is saying that whenever any of the listed files change, run the command again. It does not mean that the listed file will be included into the compilation or linking. You still need the regular #include "main.h" in your sources.
Thus, this works too:
printFunc.o : printFunc.c someReadmeFile.txt
gcc -g -Wall -c -o printFunc.o printFunc.c
Whenever printFunc.c or someReadmeFile.txt is updated, gcc -g -Wall .... will be executed again.
I hope it's clearer now.

Build .so file from .c file using gcc command line

I'm trying to create a hello world project for Linux dynamic libraries (.so files). So I have a file hello.c:
#include <stdio.h>
void hello()
{
printf("Hello world!\n");
}
How do I create a .so file that exports hello(), using gcc from the command line?
To generate a shared library you need first to compile your C code with the -fPIC (position independent code) flag.
gcc -c -fPIC hello.c -o hello.o
This will generate an object file (.o), now you take it and create the .so file:
gcc hello.o -shared -o libhello.so
EDIT: Suggestions from the comments:
You can use
gcc -shared -o libhello.so -fPIC hello.c
to do it in one step. – Jonathan Leffler
I also suggest to add -Wall to get all warnings, and -g to get debugging information, to your gcc commands. – Basile Starynkevitch

Resources