Why does SDL2 need both static and dynamic libraries for compilation - c

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.

Related

How can I use my C library as others like stdio

I recently made a small library in C, and I wanted to put it together with the standard libraries so I don't have to always copy the files for each new project.
Where do I have to put it so I can import it like the standard libraries?
Compiler : MinGW
OS: Windows
You need to create a library, but you don't necessarily need to put it in the same place as MinGW's standard libraries (in fact I think that's a bad idea).
It is better to put your own library/libraries in specific place and then use the -I compiler flag to tell the compiler where to find the header files (.h, .hpp, .hh) and the -L linker flag to tell the linker where to find the library archives (.a, .dll.a). If you have .dll files you should make sure they are in your PATH environment variable when you run your .exe or make sure the .dll files are copied in the same folder as your .exe.
If you use an IDE (e.g. Code::Blocks or Visual Studio Code) you can set these flags in the global IDE compiler/linker settings so you won't have to add the flags for each new project.
Then when building a project that uses your library you will need to add the -l flag with the library name to your linker flags, but without the lib prefix and without the extension (e.g. to use libmystuff.a/libmystuff.dll.a specify linker flag -lmystuff). The use of the -static flag will tell the linker to use the static library instead of the shared library if both are available.
I have created a minimal example library at https://github.com/brechtsanders/ci-test to illustrate on how to create a library that can be build both as static and shared (DLL) library on Windows, but the same code also compiles on
macOS and Linux.
If you don't use build tools like Make or CMake and want do the steps manually they would look like this for a static library:
gcc -c -o mystuff.o mystuff.c
ar cr libmystuff.a mystuff.c
To distribute the library in binary form you should distribute your header files (.h) and the library archive files (.a).

What does g++ / gcc do when asked to link against .a files?

I'm reading a tutorial about C development with the SDL library on MingW and Windows. (The tutorial is actually about C++ but I'm assuming installation and building is the same).
The tutorial gives the following command for building the program:
g++ 01_hello_SDL.cpp -IC:\mingw_dev_lib\include\SDL2 -LC:\mingw_dev_lib\lib -w -Wl,-subsystem,windows -lmingw32 -lSDL2main -lSDL2 -o 01_hello_SDL
In this command we use -L and -l to tell g++ where to find .a files (not .DLL or .so files) for linking. However, as far as I understand - this command is supposed to dynamically link the library. And as we know, .a files are static library files. What am I missing?
Why are we not linking with the .DLL file of the library, but instead we link with these .a files? When executing, the .DLL file will have to be present near the executable, but the .a won't have to as far as I understand. Again, what am I missing?
-l is not only for dynamic libraries. It can also be used to link static libraries.
On Linux, it is normal to directly link with a .so file (equivalent to a .dll). On Windows, it is still possible to do this (I think), but it is more normal to link with a .lib file called an import library, which wraps the .dll (you link to the .lib and the .lib links to the .dll). Since you are not using the Microsoft toolchain, it's possible that your toolchain still uses import libraries, but calls them .a files instead of .lib files.

How can I compile a library archive with a source code file with gcc?

TL;DR - I need to compile archive.a with test.o to make an executable.
Background - I am trying to call a function in a separate library from a software package I am modifying but the function (a string parser) is creating a segmentation violation. The failure is definitely happening in the library and the developer has asked for a test case where the error occurs. Rather than having him try to compile the rather large software package that I'm working on I'd rather just send him a simple program that calls the appropriate function (hopefully dying at the same place). His library makes use of several system libraries as well (lapack, cblas, etc.) so the linking needs to hit everything I think.
I can link to the .o files that are created when I make his library but of course they don't link to the appropriate system libraries.
This seems like it should be straight forward, but it's got me all flummoxed.
The .a extension indicates that it is a static library. So in order to link against it you can use the switches for the linking stage:
gcc -o myprog -L<path to your library> main.o ... -larchive
Generally you use -L to add the path where libraries are stored (unless it is in the current directory) and you use -l<libname> to sepecify a library. The libraryname is without extension. If the library is named libarchive.a you would still give -larchive.
If you want to specify the full name of the library, then you would use i.e. -l:libname.a
update
If the libraypath is /usr/lib/libmylibrary.a you would use
-L/usr/lib -lmylibrary

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

Creating static libraries

I'm trying to create a static library to use inside my PHP extension. To do that, I'm compiling my .c files using gcc -c file.c -o file.o and obtaining .o files. I then use ar rcs lib.a *.o to archive all the compiled objects into an .a file.
After doing this, I'm referring to this .a file when compiling my PHP extension, but I get the following error:
*** Warning: Linking the shared library <extension>.la against the
*** static library lib.a is not portable!
If I use the .o files instead of the .a file, I get:
*** Warning: Linking the shared library <extension>.la against the non-libtool
*** objects file1.o file2.o is not portable!
What am I doing wrong and what's the correct way of doing this?
The short answer: shared libraries (of which a PHP extension is a special case) cannot depend on static libraries.
Actually that's not quite entirely true. As long as your static library is built as position-independent code (PIC), using it from a shared library will work; whatever .o files from the archive are needed to satisfy the undefined symbols in the .o files you explicitly linked to make the .so will get pulled in and become part of the shared library file.
Linking non-PIC .o files into a shared library will also work on some archs (like i386) but it's not portable (and won't work on x86_64).
As for what you should do, if it's possible, I would just forget about the intermediate .a file and link all your .o files explicitly into the .so file for the extension. This is clean and simple. Or you could keep doing it the way you're doing as long as you're sure all your files got built as PIC (i.e. with the -fPIC option).
What I would not do is make and install an extra .so file that the main .so file for the extension will then depend on. All this does is create bloat, increase load time, and make lots of trouble with deployment/integration.
Linking shared libraries to static libraries is not possible (unless you really know very well what you are doing). Don't do it.
The first warning is from libtool. It tells you, that the operation you asked for will do different things on different systems and some of those things are probably not what you want. Often it's just going to fail in various spectacular ways, because code that goes in shared and static libraries needs to be compiled with different compiler flags.
i have faced same problem once but i have solved it by corrcting some linking flag in make file you can see
What is the meaning of “Warning: Linking the shared library against static library is not portable”?

Resources