Linkers and Libraries

I've been building a framework for about a year now that builds an OOP for SDL (recently updated for SDL3). Now I would like to set it up so my user only has to call g++ theirCode.cpp -lMyFramework instead of having to link to the 4 or so SDL libraries that are already linked inside my framework.

The framework, however, is meant to work along-side SDL. I want the user to still be able to call the raw SDL functions and types. If I try to remove -lSDL3 -lSDL3_image -lSDL3_mixer -lSDL3_etc from the client side compile-line, I get 'ld' linking errors for those function calls.

The only options that I have found that might work would be dynamically linking the libSDL*.so (providing a pointer to each function) and/or wrapping the entire library with my own function calls. These two options are too much effort for so little reward.

Is there another way to provide access to the SDL libs that are already linked through my lib?

Here's the actual error message. (lgf is my library, I have it copied to /usr/local/lib/liblgf.so)
make
g++ main.cpp tictactoe.cpp -llgf -L. -I./include  -o tictactoe
/usr/bin/ld: /tmp/cc4TRz8N.o: undefined reference to symbol 'SDL_CreateRenderer@@SDL3_0.0.0'
/usr/bin/ld: /usr/local/lib/pkgconfig/../../lib/libSDL3.so.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make: *** [Makefile:11: tictactoe] Error 1
Last edited on
Well, do you want to provide your framework as a "static" library (.a file) or as a "shared" library (DLL or .so file) ???


As far as "static" libraries are concerned, they are just archives (similar to ZIP files) containing a bunch of pre-compiled object (.o) files. Merging two or more "static" libraries into one is possible, just like you can merge the contents of two ZIP files into one.

See here for details:
https://stackoverflow.com/a/23621751

Though I don't think this is a very good idea to merge third-party dependencies (e.g. SDL) into your "static" library. For example, the user won't be able to update the the third-party dependencies independently from your framework. What if SDL releases in important security fix? The user would depend on you to provide an updated framework release, rather than simply updating the SDL library...


Things are more complicated if you want to provide your framework as a "shared" library (DLL file). Sure, when building your framework DLL file, you could link the third-party dependencies as "static" libraries into your DLL file. This way, you create a sort of "all in one" DLL file and the third-party dependencies won't appear as separate DLL files. But: This will only satisfy dependencies on the third-party libraries within your framework code (DLL file). If the "main" program also wants to call the third-party library directly (not only through your framework), then they won't be able to do this with your "all in one" DLL – unless you provide "wrapper" functions that pass through the calls.

Note: While you can link a "static" library into a "shared" one (DLL file), merging multiple "shared" libraries (DLL files) into one is not (easily) possible. If you link a "shared" library against another "shared" library, then both "shared" libraries will still be required at runtime!
Last edited on
I definitely have a preference towards shared libraries, mostly because of certain copy-left licenses (gnu GPL) left me in analysis paralysis.
SDL 2 and 3 are zlib licensed, so GPL is not something to fear in this case. It is funny how much anxiety I have even thinking about researching static libraries at this point.

I see you just made an edit, so I'm re-reading your post.

Thank you Kigar, it helps to know that this wasn't just a simple fix. I can't seem to get motivated to do static linking at this point, but there are a couple of things I can do:

1. Finish off my framework to the point that it can operate without SDL functions being called by the user. It would then be optional to them to include the SDL libs should they want to use those functions.

2. Just accept that I am making a helper library, and provide some examples and instructions for how to compile a program that utilizes it.

3. Look into setting up pgk-config. This might be the best option since it could provide all dependencies and tags in a single command (if i properly understand how it works).
Last edited on
1. Finish off my framework to the point that it can operate without SDL functions being called by the user. It would then be optional to them to include the SDL libs should they want to use those functions.

If you want to stick with "shared" libraries, and if you framework internally makes use of SDL, then your users still will need to link the "shared" SDL libraries, in addition to your framework "shared" library, or at the very least have them available at runtime.

Keep in mind: Linking a "static" library kind of absorbs that library into the EXE (or DLL) that your are building. Meanwhile, linking against a "shared" library (i.e. .so file or DLL) only tells the compiler where the required symbols can be found, but does not copy the library code into the EXE (or DLL) that your are building! Instead, if an executable was linked against a certain "shared" library, then that "shared" library must be available at runtime. This also applies in a recursive fashion: Supposed that "main.exe" was linked against "framework.dll" and that the "framework.dll" was linked against "SDL.dll". Then, effectively, "main.exe" will depend on both, "framework.dll" and "SDL.dll", even if it doesn't call anything from "SDL.dll" directly. You can use Dependencies (Windows) or ldd (Linux) to track "shared" library dependencies.

https://github.com/lucasg/Dependencies

https://man7.org/linux/man-pages/man1/ldd.1.html
Last edited on
Pkg-config was really easy to set up, it just requires writing a single text file placed in
/usr/local/lib/pkg-config/myFramework.pc
-- It does require sudo in order to edit or create anything in /usr/local since they are system files. I ended up copying SDL3_ttf.pc and modifying it to fit my framework's requirements.

Here's what I have so far as my
/usr/local/lib/pkg-config/lgf.pc
sorry that this is kind of a Linux specific solution:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
prefix=/usr/local
exec_prefix=${prefix}
libdir=${prefix}/lib
includedir=${prefix}/include

Name: lgf
Description: LGF - Light Game Framework which provides simple objects for making SDL3 games.
Version: 3.0.0
Requires: sdl3 >= 3.0.0
Requires: sdl3-ttf >= 3.0.0
Requires: sdl3-image >= 3.0.0
Requires: sdl3-mixer >= 3.0.0
Libs: -L${libdir} -llgf -lSDL3_image -lSDL3_ttf -lSDL3_mixer -lSDL3
Requires.private:
Libs.private:
Cflags: -I${includedir} -I${includedir}/lgf


And now I can compile with this one-liner
g++ main.cpp `pkg-config --cflags --libs lgf`,
the back-tick (found under escape key) is important since it expands the output of pkg-config before g++ runs.
Also note that I have previously installed my liblgf.so file in /usr/local/lib/liblgf.so so it will be found correctly.

Thank you kigar, I didn't know about ldd, it will be useful when I try to make my future install media.
Last edited on
Topic archived. No new replies allowed.