Is it a compiled library portable? - c

I have a conceptual question about writing a library in plain c. I have some functions that I have to use in different programs in the same folder, so I was thinking about writing a library to host these functions. I have to write the whole code in a folder that will be copied to another computer (where the programs will run). If I create and compile the library in this folder, will be the user able to run the programs without rebuilding the library from source or he might have some unpredictable errors? The user will build the programs that use the library anyway, he won't build the lib itself.
Thanks
Lorenzo

In general, no, it is not portable in the sense that a compiled library can be linked on an arbitrary other system. The compiled library has to be compatible to the target architecture, the OS, the compiler system, to name some.
But you have another choice, concluded from your comment: It seems that you also provide some shell script or makefile to build the programs.
Because a library consists of "just" a set of compiled translation units before some of them get linked into the programs, you can take the set of sources of these translations unit and compile them with the sources of each program, where appropriate.
As an example, let's say you have 2 functions (each in its own source file) you use in different combinations in 3 programs. "prg1" uses func1(), "prg2" uses func2(), and "prg3" uses both.
This can be the commands to build the programs with a (static) library:
gcc -c func1.c -o func1.o
gcc -c func2.c -o func2.o
ar -r lib.a func1.o func2.o
gcc prg1.c lib.a -o prg1
gcc prg2.c lib.a -o prg2
gcc prg3.c lib.a -o prg3
Instead of the library you compile the programs' sources directly:
gcc prg1.c func1.c -o prg1
gcc prg2.c func2.c -o prg2
gcc prg3.c func1.c func2.c -o prg3
The results are the same, at least as long as you had linked statically to the library.
But even with a shared (dynamic) library the approach will be the same. Shared libraries "only" save some RAM if several programs using them are run concurrently. If only one program runs at a time, a dynamically linked program might need more RAM and loads slower.

Related

Why does SDL2 need both static and dynamic libraries for compilation

Basically when using SDL2 library why do I need to use both SDL2.dll (dynamic) file and .a (static) for compilation?
For an example to compile a simple program I need to tell gcc where lib files (static .a) are located to compile the program. Why not just use the .dll file instead?
My first thought is that .a files are needed for the compiler to check if program can compile with the library and .dll is only needed when running the program (and program is not statically linked in the end), but still that wouldn't explain why do i need the .a files instead of just .dll file.
example:
gcc -I src/include src/lib -o main.exe main.c -lmingw32 -lSDL2main -lSDL2
There are two .a files: libSDL2.a and libSDL2.dll.a (not counting libSDL2main.a, which is always static).
The first one is a true static library. -lSDL2 doesn't prefer it by default, it prefers libSDL2.dll.a. And if you force it to use the former, because the latter is unavailable, the resulting app won't depend on SDL2.dll.
The second one is an import library. In the old days, MinGW couldn't link against a .dll directly, and you had to use those. Modern MinGW can link .dlls directly, and those should in theory be unnecessary.
I'd still recommend using the import library if it's available, just because it's more common and more widely tested.

What is the difference between shared and dynamic libraries in C?

I don't understand the difference between the two types of libraries, and many websites say that they are the same thing, but at school we use two different commands to create them
dynamic library
$ gcc -shared -o libsample.so lib.c
$ gcc -o main main.c -ldl
to execute:
$ ./main ./libsample.so
shared library
$ gcc -shared -o libsample.so lib.c
$ gcc -o main main.c -L. -lsample
to execute:
$ LD_LIBRARY_PATH=. ./main
Can someone help me in understanding the difference between the two "codes"?
Dynamic Linked Library (.DLL) is the terminology used by Microsoft Windows. Shared Object (.so) is the terminology used by Unix and Linux.
Other than that, conceptually they're the same.
Regarding your snippets of commands, I guess the difference (and I'm only guessing here, because you didn't show us the relevant parts) is how the library is loaded. There is "link time loading" where the library is tied to the executable by the linker¹. And there is "runtime loading", where the program sort of "ingests" the dynamic/shared library.
runtime loading is done in Windows with the LoadLibrary (there's an …A and a …W variant) function, and on Unix/Linux with dlopen (which is made available by libdl which is linked to by that -ldl library link statement).
1: The linker is the program that creates the actually executable file from the intermediary objects created by the various compiler stages.
Dynamic and shared libraries are usually the same. But in your case, it looks as if you are doing something special.
In the shared library case, you specify the shared library at compile-time. When the app is started, the operating system will load the shared library before the application starts.
In the dynamic libary case, the library is not specified at compile-time, so it's not loaded by the operating system. Instead, your application will contain some code to load the library.
The first case is the normal case. The second case is a special use and it's mainly relevant if your application support extensions such a plug-ins. The dynamic loading is required because there can be many plug-ins and they are built after your application. So their names are not available at compile-time.

GCC have include but not library

I'm writing my own kernel for fun, and in doing so I've needed to install glibc to use the standard C libraries. However, after installing the library to the desired directory, my kernel.c program includes the stdio.h header and attempts to use fopen, however I come across this error:
kernel.c:(.text+0x238): undefined reference tofopen'`
After looking around I noticed that I don't have any actual code to all of the header files, just the header files themselves. So I went and added the -L flag to GCC to add the lib folder that was created during the compilation of glibc and what I've found out is that the lib folder has nothing of what I need.
I poked around and found that the build directory I used when compiling glibc has the .o files I'm looking for (e.g it has iofopen.o for the fopen method).
So what's going on?
If needed, the commands I am using to compile my kernel are:
#!/bin/bash
nasm -felf32 boot.asm -o boot.o
/home/noah/opt/cross/bin/i686-elf-gcc -I/home/noah/Documents/NoahOS/include/ -L/home/noah/Documents/glibc/build -c *.c -std=gnu99 -ffreestanding -Wall -Wextra
/home/noah/opt/cross/bin/i686-elf-gcc -I/home/noah/Documents/NoahOS/include/ -L/home/noah/Documents/glibc/build -T linker.ld -o noahos.bin -ffreestanding -O2 -nostdlib *.o -lgcc
First line builds the boot file, which is assembly.
Second line runs gcc on all of the C language .c files and creates their object files.
Third line links all of the files together with linker.ld and outputs the final kernel to noahos.bin which is a runnable kernel using
qemu-system-i386 -kernel noahos.bin
If needed more information can be provided. Please ask.
You are correctly compiling your kernel using -nostdlib because the kernel can't use the standard library. Why not? Because it doesn't make sense: the standard library is the interface between user programs and the kernel, so that application developers don't need to know the system call specification for your kernel, all that is required is a port of the C library.
Oh, there's the answer. You need a port of the C library to use your own system calls. Starting with glibc might not be the easiest to port (it comes with the kitchen sink).

C - Compile with dependencies included

I have some code which I want to run on a machine which I do not have root access to.
That machine does not have some of the libraries needed to run this code.
Is there any way to include all dependencies when I compile? I realize the resultant file may be quite large.
What you're looking for is static compiling. Performing static compilation includes all of the libraries into the executable itself, so you don't have to worry as much about dependency chains on a specific system, distribution, etc.
You can do this with:
gcc -Wl,-Bstatic -llib1 -llib2 file.c
The -Wl passes the flags following to the linker, -Bstatic tells it to link static if possible, and then lib1, lib2, are the libs you intend to link.
Alternatively, try:
gcc -static file.c
The compilation will still need to match the architecture of the non-privileged system. And you need to have the static libraries installed on the compiling system (lib.a)
If compiled properly, it should show "not a dynamic executable" when you run:
ldd a.out

Two method for linking a object using GCC?

I've known that I should use -l option for liking objects using GCC.
that is gcc -o test test.c -L./ -lmy
But I found that "gcc -o test2 test.c libmy.so" is working, too.
When I use readelf for those two executable I can't find any difference.
Then why people use -l option for linking objects? Does it have any advantage?
Because you may have either a static or a shared version of the library in your library directory, e. g. libmy.a and libmy.so, or both of them. This is more relevant to system libraries: if you link to libraries in your local build tree, you know which version you build, static or shared, but you may not know other systems' configuration and libraries mix.
In addition to that, some platforms may have different suffixes. So it's better to specify it in a canonical way.
The main reason is, -lname will search for libname.a (or libname.so, etc.) on the library search list. You can add directories to the library search list with the -L option. It's a convenience built into the compiler driver program, making it easier to find libraries that have been installed in standard places on the system.

Resources