Code for purposes written utilizing C often has a number of supply information, however in the end you will have to compile them right into a single executable.
You can do that in two methods: by making a static library or a dynamic library (additionally known as a shared library). These two varieties of libraries differ when it comes to how they’re created and linked. Your alternative of which to make use of is determined by your use case.
In a previous article, I demonstrated the right way to create a dynamically linked executable, which is the extra generally used technique. In this text, I clarify the right way to create a statically linked executable.
Using a linker with static libraries
A linker is a command that mixes a number of items of a program collectively and reorganizes the reminiscence allocation for them.
The capabilities of a linker embody:
- Integrating all of the items of a program
- Figuring out a brand new reminiscence group so that each one the items match collectively
- Reviving addresses in order that this system can run below the brand new reminiscence group
- Resolving symbolic references
As a results of all these linker functionalities, a runnable program known as an executable is created.
Static libraries are created by copying all needed library modules utilized in a program into the ultimate executable picture. The linker hyperlinks static libraries as a final step within the compilation course of. An executable is created by resolving exterior references, combining the library routines with program code.
Create the item information
Here’s an instance of a static library, together with the linking course of. First, create the header file mymath.h
with these perform signatures:
int add(int a, int b);
int sub(int a, int b);
int mult(int a, int b);
int divi(int a, int b);
Create add.c
, sub.c
, mult.c
and divi.c
with these perform definitions:
// add.c
int add(int a, int b){
return (a+b);
}//sub.c
int sub(int a, int b){
return (a-b);
}//mult.c
int mult(int a, int b){
return (a*b);
}//divi.c
int divi(int a, int b){
return (a/b);
}
Now generate object information add.o
, sub.o
, mult.o
, and divi.o
utilizing GCC:
$ gcc -c add.c sub.c mult.c divi.c
The -c
choice skips the linking step and creates solely object information.
Create a static library known as libmymath.a
, then take away the item information, as they’re now not required. (Note that utilizing a trash
command is safer than rm
.)
$ ar rs libmymath.a add.o sub.o mult.o divi.o
$ trash *.o
$ ls
add.c divi.c libmymath.a mult.c mymath.h sub.c
You have now created a easy instance math library known as libmymath
, which you should use in C code. There are, in fact, very complicated C libraries on the market, and that is the method their builders use to generate the ultimate product that you just and I set up to be used in C code.
Next, use your math library in some customized code after which hyperlink it.
Create a statically linked software
Suppose you’ve got written a command for arithmetic. Create a file known as mathDemo.c
and paste this code into it:
#embody <mymath.h>
#embody <stdio.h>
#embody <stdlib.h>int fundamental()
{
int x, y;
printf("Enter two numbersn");
scanf("%d%d",&x,&y);
printf("n%d + %d = %d", x, y, add(x, y));
printf("n%d - %d = %d", x, y, sub(x, y));
printf("n%d * %d = %d", x, y, mult(x, y));if(y==0){
printf("nDenominator is zero so can't perform divisionn");
exit(0);
}else{
printf("n%d / %d = %dn", x, y, divi(x, y));
return 0;
}
}
Notice that the primary line is an embody
assertion referencing, by identify, your personal libmymath
library.
Create an object file known as mathDemo.o
for mathDemo.c
:
$ gcc -I . -c mathDemo.c
The -I
choice tells GCC to seek for header information listed after it. In this case, you are specifying the present listing, represented by a single dot (.
).
Link mathDemo.o
with libmymath.a
to create the ultimate executable. There are two methods to specific this to GCC.
You can level to the information:
$ gcc -static -o mathDemo mathDemo.o libmymath.a
Alternately, you may specify the library path together with the library identify:
$ gcc -static -o mathDemo -L . mathDemo.o -lmymath
In the latter instance, the -lmymath
choice tells the linker to hyperlink the item information current within the libmymath.a
with the item file mathDemo.o
to create the ultimate executable. The -L
choice directs the linker to search for libraries within the following argument (just like what you’d do with -I
).
Analyzing the end result
Confirm that it is statically linked utilizing the file
command:
$ file mathDemo
mathDemo: ELF 64-bit LSB executable, x86-64...
statically linked, with debug_info, not stripped
Using the ldd
command, you may see that the executable shouldn’t be dynamically linked:
$ ldd ./mathDemo
not a dynamic executable
You can even verify the scale of the mathDemo
executable:
$ du -h ./mathDemo
932K ./mathDemo
In the instance from my previous article, the dynamic executable took up simply 24K.
Run the command to see it work:
$ ./mathDemo
Enter two numbers
10
510 + 5 = 15
10 - 5 = 5
10 * 5 = 50
10 / 5 = 2
Looks good!
When to make use of static linking
Dynamically linked executables are usually most well-liked over statically linked executables as a result of dynamic linking retains an software’s elements modular. Should a library obtain a essential safety replace, it may be simply patched as a result of it exists outdoors of the purposes that use it.
When you utilize static linking, a library’s code will get “hidden” inside the executable you create, which means the one option to patch it’s to re-compile and re-release a brand new executable each time a library will get an replace—and you’ve got higher issues to do together with your time, belief me.
However, static linking is an affordable choice if the code of a library exists both in the identical code base because the executable utilizing it or in specialised embedded gadgets which might be anticipated to obtain no updates.