Do C/C++ compilers typically remove duplicate libraries? - c++

I'm compiling a Static (added static after reading comments) C++ library PoDoFo and some of its dependencies are optional, such as libJPEG, libTiff and libPNG. Though, a lot of the libraries have an option to depend on one another as well. For instance you can enable JPEG support in libTiff by compiling libTIFF with libJPEG.
In a perfect world I would hope that libTIFF would enable the libJPEG functions by realizing it has access to libJPEG because I included it in my compilation of PoDoFo. Sadly I think enabling/disabling functions is decided when I first compile libTIFF.
So then that means my PoDoFo library will contain libJPEG multiple times, probably even identical copies if I use the same library.
Will GCC compiler realize this and eliminate/relink the libraries to just one copy of libJPEG?

Basically yes, it'll only include one copy.
The compile switches you are changing don't actually include one library into another, they just enable functionality that requires those libraries, e.g. libTIFF might include functions to convert between jpeg and tiff formats if you enable libJPEG support, but allows you to compile the rest of the library without that functionality if you don't want that.
When you link a final application with PoDoFo, you will also have to link all of the optional dependencies you enabled. This can be automatic for dynamic libraries but the dependencies will all be required at runtime.
In almost all cases there is only one copy of each library linked with the final application - the one exception is if you mix static and dynamic libraries, but that's a whole new can of worms.

Assuming all library are dynamically linked, runtime linker would only load a single copy of each dependent library (so a single copy of libJPEG will be loaded).
In a perfect world I would hope that libTIFF would enable the libJPEG functions by realizing it has access to libJPEG because I included it in my compilation of PoDoFo, but sadly I think enabling/disabling functions is decided when I first compiled libTIFF.
The feature that you describe is called delayed loading and is supported in Windows but not on Linux (at least not by default, see Implib.so tool).

Related

about Linux c++ static library

here I have several problem for static libraries need your help.
From some books I learned that, a static library (.a in Linux) contains a set of compiled objects, when it's linked into an executable, the link tool will only take out those objects that are actually referenced.
So if the .a contains 1.o, 2.o and 3.o and my application only uses functions in 1.o, then only 1.o will be built into the executable, is this correct?
Then let's go further, say we have 2 .a libs, first contains 1.o, 2.o and 3.o and second contains 3.o 4.o and 5.o. If my application only uses functions in 1.o 2.o 3.o and 4.o then only these these 4 .o will be built into the executable, is it correct?
I raised this question because I'm building some .a files to use with MSVC. These .a libraries are built in MinGW and then should be compatible with MSVC. I could include these libs into the MSVC project and build my program successfully. But the generated executable is 5 MB (the total size of all .a should be about 8MB) even when my program is an empty one (only have an empty main function).
Does this mean, .a when used in MSVC or .lib (static libs for Win) will be built into executable as a whole, but not in the way it behaves under Linux?
and also I have a question for below content
If I could use -static to link to static version of lib tiff, then why it needs to link to other libs? Should a static lib already contains all the code it needs?
Thanks
A static library won't have all code it needs. Imagine a library that uses printf() to output error messages. This library will still depend on the static version of libc, it won't include the code for printf itself.
In your case, since Tiff supports various internal representation formats, one of which is jpeg, the static libtiff wants you to link the static libjpeg.
There is no fundamental difference in this between windows and linux. When you do a static link against libtiff and libjpeg, only the libjpeg functions that are actually needed by libtiff get linked, but not, for example, the parts that handle the JFIF Jpeg wrapper.
EDIT - answer to comments
There's a lot of stuff going on before your main() gets called. It's not that much on linux/unix, where the OS delivers arguments the way main() wants them, but on Windows, a different function, normally called WinMain() gets control when the program starts. This WinMain() is hidden in the library. It gets the whole command line in one string and has to parse arguments to pass them to main(), which means checking for spaces, which is probably implemented using isspace(), which pulls in ctype, which pulls in lots of locale-dependent stuff, and so on. So much of your 5 MB might be code that serves to make your program work in windows just like it would in unix. Also, if you're compiling with debug options on, these debug symbols take a lot of space as well.
Keltar's comment about a static library calling a dynamic one is right as well - but that adds a complication you don't need very often. There's more or less 2 reasons for static linkage:
You want your program be able to run even when something goes wrong with dynamic libraries. If i accidentially rm /lib/libc.so.* i will be glad if i have statically linked versions of mount and cp to copy it from somewhere else. Thus, installers and "emergency programs" are often linked static
You want to make sure your program uses a specific version of libraries, that was current on your system when you compiled it, not the dynalink version that might be installed on some system 5 years later.
Both these reasons don't make much sense if some but not all libraries are static.
There's exceptions though: imagine you need a specific feature in libtiff. You browse the documentation and it says nothing about the feature. You check the source code and find that it implements specific_feature(), with a big "This is experimental and might go away in a future version" comment. If you decide you need that feature now, you might want to link libtiff statically to protect your program from failing when future versions of libtiff don't implement the function any more. Of course, you'll still want the dynamic versions of libjpeg and libc. I'll leave the decision if this is good practise to you.
Windows is a special case as it always uses kernel.dll and user32.dll as there are no static versions, even if the rest of your program is linked statically.
So while a libtiff.a could require a libjpeg.so, and a libtiff.lib could require a libjpeg.dll, there's generally not much reason to do so.

Confused about .so version and linking strategy when distributing a api library

We have been porting our Java API to C++, and creating a library file (.a file) for Linux. Our API has dependency on the boost framework and also on log4cxx. (We discussed with the first user for this, and they are okay with those dependencies).
When I compile a sample application which uses our library file, it is linking against .so files for the dependencies (libboost_system.so, libboost_thread.so, and liblog4cxx.so). When the application runs, it needs to find the specific versioned file names for each of those .so files, e.g. liblog4cxx.so.10.
If the user is using a newer version of boost (for example), would s/he be able to link against their local version and run with that newer version (assuming bacwards compatibility)? Is there some other way to deal with versions/dependencies like these (i.e. do you try to link in the external referenced libraries to your own library)?
Yes, the program can link to newer libraries with a compatible interface. The numbers in the filename encode the library Application Binary Interface (ABI).
FreeBSD's handbook has more information about library versioning. The basic rules are:
Start from 1.0
If there is a change that is backwards compatible, bump minor number (note that ELF systems ignore the minor number)
If there is an incompatible change, bump major number
The linker will sort out the details to use the newest library version with a compatible interface. There is also more information available here on stackoverflow.

How do I statically link against two versions of xerces-c (or any library for that matter)?

I know this is not a very clean thing to do but how do I do it nonetheless?
Basically, I am statically linking a third party library that uses xerces-c 2.7 and I want to use xerces-c 3.1 (for some of the newer latest and greatest features not really available in 2.x)
The modules that use 2.7 (used internally by the third party library and never exposed to my code) have nothing in common with the modules using 3.1 (in my code).
Any way how to do this? I know it's not a good thing but I shudder to think of the lead time between submitting an upgrade request for the library and actually getting it done. Probably months at least and I don't want to go down that unholy path.
A generic compiler independent solution would ofc be much better.
Another solution aside from that mentioned in " Linking libraries with incompatible dependecies " is to isolate the different versions by building them into different dynamic libraries. The simplest approach may be to move the code that uses xerces 3.1 into a new dynamic library, and create an interface to it. Since you're statically linking against Xerces, this will keep the references internal to the dynamic library. You may need to change the gcc visibility settings to ensure that only selected function names are exported from the dynamic library.

How to use ffmpeg so that there would be no need in including its dlls in your app folder?

So my point is to find normal ffmpeg in form of .lib for c/C++ windows developers so to be capable of including all needed functions inside my app - so to say one exe no extra dlls.
So I am looking thrue its windows /autobuilds/ in search for such array of .lib files. as for now closest to what I wanted was that ffmpeg-swscale-mingw32-shared-dev\lib folder with .lib and .dll.a files. problem is I am quite new to C/C++ development so I wonder if this build is what I need or I need something else?
And what are .dll.a files for in ffmpeg mingw32 shared dev build after all?
A shared build will depend on external DLLs, you need to find static built FFmpeg libraries so they will be linked to exe.
You will always need the following files:
libavcodec.a
libavformat.a
libavutil.a
There are also optional components depending on your code:
libavfilter.a
libavdevice.a
libswscale.a
You should be aware that if you intend to distribute a program linked to FFmpeg this way, you must either make your program free/opensource or at least distribute object files for your program so that end-users can re-link it with a modified version of FFmpeg. If you choose the latter option (i.e. if you don't want to make your program free software), you must be sure that your static FFmpeg library omits the optional GPL-licensed functionality, or your use will be infringing and the only way you will be able to get out of trouble is to release your entire program under a GPL-compatible license.

Linking libpng with Borland C++

I made a program on Mac OS X using OpenGL and dynamically linking libpng. I'm now trying to port it to Windows. Whenever I try to compile and link my ported program in Borland it gives me this error and about 10 more that are the same, but with a different '_png_create_read_struct':
Error: Unresolved external '_png_create_read_struct' reference from C:\PROGRAMMING\PNGTEST.OBJ
I assume it's because I have not properly set up libpng with Borland C++ 5.5.1 for Win32. I've put png.h and pngconf.h into the include folder into C:\Borland\BCC55\Include, and I have put libpng12.dll.a, libpng13.a, libpng13.dll.a, libpng.a, libpng.dll.a, libpng12.def, libpng.def, libpng12.la, and libpng.la into C:\Borland\BCC55\Lib (there is probably no need for them all, but as a noob I have no idea which ones are needed and not).
Do I need to put a libpng.obj file in there too? And if so how would I make/get one? I have tried using makefile.bc32 to set up libpng, yet that gives me a missing separator error.
Here are my command-line options:
bcc32 -tW pngtest.cpp -lpng
I include png.h in my code. What am I doing wrong or is there an even better way to load images with alpha that doesn't need libpng, or even a better compiler to get for Windows?
You're probably better off with the MinGW compiler than Borland. Borland is not well supported any longer.
You could also download DevC++ and see if it has a libpng package in its addon mechanism.
DevC++ is an IDE that uses the MinGW C/C++ compiler.
That said, if you feel you must use BCC, you'll either have to
a) Build libpng with Borland. This is the best solution if you're going to use borland.
b) Use, I think, Impdef to create an import library from libpng.dll. You'll find impdef.exe or imp(something).exe in the borland bin directory.
Note that some libraries will not work with impdef as there is static code linked to the dll that causes it to fail without the proper runtime.
First of all, I would not have "polluted" the BC55 installation with third-party libraries; it will make moving the project to other build environments much more difficult. It would have been better to place them in a folder within your project.
Secondly do you know that the export library you are attempting to link is built for BC55? The .a extension suggests a GNU library (Borland libraries conventionally use .lib extension), in which case it would not link with BC55 which uses a different object file format. If this is the case you will need to rebuild the library as you attempted to do, so I suggest that you should really be asking a question about the problem you had with doing just that. I wonder whether the makefile is written for Borland make or GNU make, since they have differing syntax?
The command line option -lpng might be correct for GCC (where it will link libpng.a), but is meaningless to BCC. The -l option merely passes the text that follows to the linker. The linker command line, requires that the complete name be passed, and if no extension is provided, .lib is added implicitly.
You should probably just use coff2omf to convert the library. The DLL files are almost certainly in "Microsoft" COFF format.
See COFF2OMF.EXE, the Import Library Conversion Tool.