Aside from inclusion of 3rd party software, why would you make a static library for a project. If your writing the source yourself you could just build it as a part of the project and if it's a library to be used more than once wouldn't it make more sense to dynamically link and sit on a run-time library?
Dynamic libraries have a run-time cost due to relocations†because the base and relative load address of the library is unknown until run-time. That is, the function calls and variable access to dynamic libraries are indirect. For this reason the code for shared libraries must be compiled as position-independent code (-fPIC flag in gcc).
Whereas with static libraries it can use cheaper program counter relative access even with address-space randomization because the relative position of that static library (object files really) is available to the linker.
Note that calls to virtual functions are resolved through the vtable (which the dynamic linker can patch on load), so that the cost of calling a virtual function is always the same regardless of where that function resides. (IIRC, I may need to double-check this statement).
See How To Write Shared Libraries by Ulrich Drepper for full details.
Linking to shared libraries is easier though because they contain a list of other shared libraries they depend upon.
Whereas when linking against a static library one must also link explicitly the dependencies of that static library (because a .a is just a bunch of .o files).
A build system should do extra handling for static libraries so that the user does not have to list static library dependencies every time when linking it.
When linking against a static library the linker only pulls in those .o files from the .a that resolve any unresolved symbols, whereas an entire shared library is loaded at run-time. So that if you have a global object in a .o with constructor/destructor side-effects, those side effects will not happen with a static library unless that global object is linked in. Extra care must be taken to make sure that global object is always linked in.
When linking against a shared librarie residing in a non-standard location, along with -L<path> one must specify -Wl,-rpath=<path> as well for the run-time linker to find the shared library there and/or use -Wl,-rpath=$ORIGIN if the shared library is shipped with the executable. Having to set LD_LIBRARY_PATH is a wrong way.
†What is PLT/GOT?
The use of dynamic libraries has three main advantages: a) When you release an update of your app it can live in a DL, which is smaller for downloading from Internet than the whole app. b) If your app is a great RAM eater, then you can load and unload DL as needed. c) Its obvious purpose: share the same code in different apps, in a machine with low resources.
a) May lead to dll hell, where different files, same or different versions, populate the directory tree and mess what app uses what .dll
b) Is only possible if you reserve an excesive amount of stack RAM. Likely bad design.
c) This may be right for broad used libs, like stdio, drivers, and most of OS helpers.
The usage of static libraries avoids a) and b). The disadvantage are that they make the final executable bigger and that, when code changes, they require likely a full re-compilation of the project
Related
In reference to this answer:
There are two Linux C/C++ library types.
Static libraries (*.a) are archives of object code which are linked with and becomes part of the application. They are created
with and can be manipulated using the ar(1) command (i.e. ar
-t libfoo.a will list the files in the library/archive).
Dynamically linked shared object libraries (*.so) can be used in two ways.
The shared object libraries can be dynamically linked at run time but statically aware. The libraries must be available during
compile/link phase. The shared objects are not included into the
binary executable but are tied to the execution.
The shared object libraries can be dynamically loaded/unloaded and linked during execution using the dynamic linking loader system
functions.
what does it mean to make a dynamic lib tied to the execution?
Is this like Windows manifest files that allow the application to load in a specific dll?
What's the mechanism to control the .so loaded?
There must be such a mechanism otherwise the "compiled" .so is the only one ever allowed to be loaded which defeats the purpose of making it dynamic?
It means that the library is available at link time, so the linker can verify that the functions that you reference from the .so are present in the .so. The advantage is that calls to these functions are done transparently to you. In other words, if you are linking to an .so with
int foo(double bar);
you call it like this
int res = foo(4.2);
The linker makes sure that foo is there, and that it takes one argument of type double. After that it "links" the call site int res = ... to the function.
Dynamically loading/unloading during the execution time lets you link without .so present on the build system (hence, no "static awareness"). In exchange for this added flexibility you open your system up to a possibility of not finding the functions that you want in the target .so. Your calls sequence also look considerably trickier than foo(4.2), because you need to go through dlopen preparation step. More info on calling functions from .so is in this Q&A.
I have been involved in some debate with respect to libraries in Linux, and would like to confirm some things.
It is to my understanding (please correct me if I am wrong and I will edit my post later), that there are two ways of using libraries when building an application:
Static libraries (.a files): At link time, a copy of the entire library is put into the final application so that the functions within the library are always available to the calling application
Shared objects (.so files): At link time, the object is just verified against its API via the corresponding header (.h) file. The library isn't actually used until runtime, where it is needed.
The obvious advantage of static libraries is that they allow the entire application to be self-contained, while the benefit of dynamic libraries is that the ".so" file can be replaced (ie: in case it needs to be updated due to a security bug) without requiring the base application to be recompiled.
I have heard some people make a distinction between shared objects and dynamic link libraries (DLL's), even though they are both ".so" files. Is there any distinction between shared objects and DLLs when it comes to C/C++ development on Linux or any other POSIX compliant OS (ie: MINIX, UNIX, QNX, etc)? I am told that one key difference (so far) is that shared objects are just used at runtime, while DLL's must be opened first using the dlopen() call within the application.
Finally, I have also heard some developers mention "shared archives", which, to my understanding, are also static libraries themselves, but are never used by an application directly. Instead, other static libraries will link against the "shared archives" to pull some (but not all) functions/resources from the shared archive into the static library being built.
Thank you all in advance for your assistance.
Update
In the context in which these terms were provided to me, it was effectively erroneous terms used by a team of Windows developers that had to learn Linux. I tried to correct them, but the (incorrect) language norms stuck.
Shared Object: A library that is automatically linked into a program when the program starts, and exists as a standalone file. The library is included in the linking list at compile time (ie: LDOPTS+=-lmylib for a library file named mylib.so). The library must be present at compile time, and when the application starts.
Static Library: A library that is merged into the actual program itself at build time for a single (larger) application containing the application code and the library code that is automatically linked into a program when the program is built, and the final binary containing both the main program and the library itself exists as a single standalone binary file. The library is included in the linking list at compile time (ie: LDOPTS+=-lmylib for a library file named mylib.a). The library must be present at compile time.
DLL: Essentially the same as a shared object, but rather than being included in the linking list at compile time, the library is loaded via dlopen()/dlsym() commands so that the library does not need to be present at build time for the program to compile. Also, the library does not need to be present (necessarily) at application startup or compile time, as it is only needed at the moment the dlopen/dlsym calls are made.
Shared Archive: Essentially the same as a static library, but is compiled with the "export-shared" and "-fPIC" flags. The library is included in the linking list at compile time (ie: LDOPTS+=-lmylibS for a library file named mylibS.a). The distinction between the two is that this additional flag is required if a shared object or DLL wants to statically link the shared archive into its own code AND be able to make the functions in the shared object available to other programs, rather than just using them internal to the DLL. This is useful in the case when someone provides you with a static library, and you wish to repackage it as an SO. The library must be present at compile time.
Additional Update
The distinction between "DLL" and "shared library" was just a (lazy, inaccurate) colloquialism in the company I worked in at the time (Windows developers being forced to shift to Linux development, and the term stuck), adhering to the descriptions noted above.
Additionally, the trailing "S" literal after the library name, in the case of "shared archives" was just a convention used at that company, and not in the industry in general.
A static library(.a) is a library that can be linked directly into the final executable produced by the linker,it is contained in it and there is no need to have the library into the system where the executable will be deployed.
A shared library(.so) is a library that is linked but not embedded in the final executable, so will be loaded when the executable is launched and need to be present in the system where the executable is deployed.
A dynamic link library on windows(.dll) is like a shared library(.so) on linux but there are some differences between the two implementations that are related to the OS (Windows vs Linux) :
A DLL can define two kinds of functions: exported and internal. The exported functions are intended to be called by other modules, as well as from within the DLL where they are defined. Internal functions are typically intended to be called only from within the DLL where they are defined.
An SO library on Linux doesn't need special export statement to indicate exportable symbols, since all symbols are available to an interrogating process.
I've always thought that DLLs and shared objects are just different terms for the same thing - Windows calls them DLLs, while on UNIX systems they're shared objects, with the general term - dynamically linked library - covering both (even the function to open a .so on UNIX is called dlopen() after 'dynamic library').
They are indeed only linked at application startup, however your notion of verification against the header file is incorrect. The header file defines prototypes which are required in order to compile the code which uses the library, but at link time the linker looks inside the library itself to make sure the functions it needs are actually there. The linker has to find the function bodies somewhere at link time or it'll raise an error. It ALSO does that at runtime, because as you rightly point out the library itself might have changed since the program was compiled. This is why ABI stability is so important in platform libraries, as the ABI changing is what breaks existing programs compiled against older versions.
Static libraries are just bundles of object files straight out of the compiler, just like the ones that you are building yourself as part of your project's compilation, so they get pulled in and fed to the linker in exactly the same way, and unused bits are dropped in exactly the same way.
I can elaborate on the details of DLLs in Windows to help clarify those mysteries to my friends here in *NIX-land...
A DLL is like a Shared Object file. Both are images, ready to load into memory by the program loader of the respective OS. The images are accompanied by various bits of metadata to help linkers and loaders make the necessary associations and use the library of code.
Windows DLLs have an export table. The exports can be by name, or by table position (numeric). The latter method is considered "old school" and is much more fragile -- rebuilding the DLL and changing the position of a function in the table will end in disaster, whereas there is no real issue if linking of entry points is by name. So, forget that as an issue, but just be aware it's there if you work with "dinosaur" code such as 3rd-party vendor libs.
Windows DLLs are built by compiling and linking, just as you would for an EXE (executable application), but the DLL is meant to not stand alone, just like an SO is meant to be used by an application, either via dynamic loading, or by link-time binding (the reference to the SO is embedded in the application binary's metadata, and the OS program loader will auto-load the referenced SO's). DLLs can reference other DLLs, just as SOs can reference other SOs.
In Windows, DLLs will make available only specific entry points. These are called "exports". The developer can either use a special compiler keyword to make a symbol an externally-visible (to other linkers and the dynamic loader), or the exports can be listed in a module-definition file which is used at link time when the DLL itself is being created. The modern practice is to decorate the function definition with the keyword to export the symbol name. It is also possible to create header files with keywords which will declare that symbol as one to be imported from a DLL outside the current compilation unit. Look up the keywords __declspec(dllexport) and __declspec(dllimport) for more information.
One of the interesting features of DLLs is that they can declare a standard "upon load/unload" handler function. Whenever the DLL is loaded or unloaded, the DLL can perform some initialization or cleanup, as the case may be. This maps nicely into having a DLL as an object-oriented resource manager, such as a device driver or shared object interface.
When a developer wants to use an already-built DLL, she must either reference an "export library" (*.LIB) created by the DLL developer when she created the DLL, or she must explicitly load the DLL at run time and request the entry point address by name via the LoadLibrary() and GetProcAddress() mechanisms. Most of the time, linking against a LIB file (which simply contains the linker metadata for the DLL's exported entry points) is the way DLLs get used. Dynamic loading is reserved typically for implementing "polymorphism" or "runtime configurability" in program behaviors (accessing add-ons or later-defined functionality, aka "plugins").
The Windows way of doing things can cause some confusion at times; the system uses the .LIB extension to refer to both normal static libraries (archives, like POSIX *.a files) and to the "export stub" libraries needed to bind an application to a DLL at link time. So, one should always look to see if a *.LIB file has a same-named *.DLL file; if not, chances are good that *.LIB file is a static library archive, and not export binding metadata for a DLL.
You are correct in that static files are copied to the application at link-time, and that shared files are just verified at link time and loaded at runtime.
The dlopen call is not only for shared objects, if the application wishes to do so at runtime on its behalf, otherwise the shared objects are loaded automatically when the application starts. DLLS and .so are the same thing. the dlopen exists to add even more fine-grained dynamic loading abilities for processes. You dont have to use dlopen yourself to open/use the DLLs, that happens too at application startup.
I suspect some kind of misunderstanding here, but header files, at least of the .h variety used for compiling source code, are most definitely NOT checked during link time.
.h, and for that matter, .c/.cpp files, are only involved during the compilation phase, which includes preprocessing. Once the object code has been created the header file is long gone well before the linker gets around to dealing with things.
I'm having difficult understanding my text, and I want to know each section extremely well. Please, be as descriptive as possible. Thank you, very much.
Programmers often find they have some code they would like to use in several programs, or code they would like to allow other programmers to make use of. They could copy-and-paste the logic into every program, or they could place the logic in common header and implementation files that they include in every project. Neither of those approaches is terribly elegant (or efficient).
Static libraries are one way to share logic so that other programs and programmers can make use of it. A static library is a binary file (often with a .LIB extension) suitable for input to the linker. A programmer consumes the static library by writing code to call one or more functions implemented in the static library and by arranging for the linker to read that static library file as an additional input. During the build, the linker will resolve all references including those to functions implemented within the static library. Often a static library is paired with a header file that describes the functions implemented in the library.
Dynamic Link Libraries are another way to share logic. Dynamic libraries are also binary files (often with a .DLL extension). Unlike static libraries, DLLs are not used as input to the linker. Instead, DLLs are loaded dynamically during program execution. DLLs may be explicitly loaded by calls to LoadLibraryEx and GetProcAddress or implicitly loaded when the consuming program is loaded.
A static library is a library that is included into your binary. It's said to be static because it's linked against your program when the linker runs. A DLL is a dynamically linking library, so it's shared code that is linked against your binary program when the program is loaded into memory, not when it's compiled and linked.
The names say it all - static libraries are static (you compile with them linked using a linker and they become part of your program) and DLLs (dynamically linked libraries) are linked to dynamically at runtime, by filename, then you call their methods. It's external.
I have a software library and I used to create .a files, so that people can install them and link against them: g++ foo.o -L/path/to -llibrary
But now I often encounter third-party libraries where only .so files are available (instead of .a), and you just link against them without the -l switch, e.g. g++ foo.o /path/to/liblibrary.so.
What are the differences between these solutions? Should I prefer creating .so files for the users of my library?
Typically, libfoo.a is a static library, and libfoo.so is a shared library. You can use the same -L/-l linker options against either a static or shared. Or you can name the full path to the lib with static or shared. Often libraries are built both static and shared to provide application developers the choice of which they want.
All the code needed from a static lib is part of the final executable. This obviously makes it bigger, but it also means it's self-contained. Once it is compiled, you can run your app without the lib.
Code from a shared lib is not part of the executable. There are just some hooks in place to make the executable aware of the name of the lib it needs. In order to run your app, the shared lib has to be present in the lib search path (e.g. $LD_LIBRARY_PATH).
If you have two apps that share the same code, they can each link against a shared lib to keep the binary size down. If you want to upgrade parts of the app without rebuilding the whole thing, shared libs are good for that too.
Good overview of static, shared dynamic and loadable libraries at
http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html
Some features that aren't really called out from comments I've seen so far.
Static linkage (.a/.lib)
Sharing memory between these compilation units is generally ok because they should(?will) all be using the same runtime.
Static linkage means you avoid 'dll hell' but the cost is recompilation to make use of any change at all. static linkage into Shared libraries (.so) can lead to strange results if you have more than 1 such shared library used by the final executable - global variables may exist multiple times and which one is used and when they are initialised can cause an entirely different hell.
The library will be part of the shipped product but obfuscated and not directly usable.
Shared/Dynamic libraries (.so/.dll)
Sharing memory between these compilation units can be hazardous as they may choose to use different runtime. This can mean you provide different Shared/Dynamic libraries based on the debug/release or single/multi threaded or...
Shared libraries (.so) are less prone to 'dll hell' then Dynamic libraries (.dll) as they include options for quite specific versioning.
Compiling against a .so will capture version information internal to the file (hard to fake) so that you get quite specific .so usage. Compiling against the .lib/.dll only gives a basic file name, any versioning is done managed by the developer (using naming or manually loading the library and checking version details by hand)
The library will have to ship with the final product (somebody else can pick it up and use it)
But now I often encounter third-party libraries where only .so files are available [...] and you just link against them without the -l switch, e.g. g++ foo.o /path/to/liblibrary.so.
JFYI, if you link to a shared library which does not have a SONAME set (compare with readelf -a liblibrary.so), you will end up putting the specified path of liblibrary.so into your target object (executable or another shared library), and which is usually undesired, for users have their own ideas of where to put a program and its associated files. The preferred way is to use -L/path/to -llibrary, perhaps together with -Wl,-rpath,/whatever/path/to if this is the final path (such pathing decisions are made by Linux distributions for example).
Should I prefer creating .so files for the users of my library?
If you distribute source code, the user will make the particular choice.
I have a bunch of projects that all could share a "common" static library of classes.
What confuses me is if I make a static library out of these classes and link against it in my projects that I still need the headers of the classes in the static library in my main projects.
What is the benefit of the static library then?
How do companies like Adobe deal with this?
Static libraries allow you to create a library and use that library in many projects.
The need for header files:
Since the project using the library is programmed and compiled independent of the library, that program needs to know the declaration of the things you're using. Otherwise how would your compiler know you're writing valid code?
A compiler only takes source code as input and produces output. It does not deal with compiled object files or static libraries on input.
The need for linking in the library:
So having the headers allows you to write valid code in your project, but when it comes to link time you'll need to provide the definition which is contained inside the static library.
The linker takes all object files (compiled code) and also all static libraries and produces an executable or binary.
More info about static libraries (benefits, comparing dynamic, etc...):
Amongst other things, it is nice to separate your project into libraries so that you don't end up with 1 huge monolithic project.
You do not need to distribute the source code (typically in the .cpp files) this way.
If you were to simply include all the .cpp files in every project that used the common library then you would have to compile the .cpp files each time.
An advantage of static libraries over dynamic libraries is that you can always be sure that your programs will be self contained and that they are using the correct version of the library (since they are compiled into the executable itself). You will also have a slight speed advantage over dynamic linking.
Disadvantages of static libraries over dynamic libraries include that your file sizes will be bigger because each executable needs their own copy, and that you can't swap out a different version of the library since it's not dynamically loaded.
Re your question: How do companies deal with this:
A typical company will make use of both static and dynamic libraries extensively.
The typical way you make use of a static library is to have a target in your Makefile (or whatever build system you use) that installs the headers into an appropriate location at the same time that it installs the library.
So, your static library ends up in /usr/local/lib, and the headers go into /usr/local/include or wherever.
Also, when compared with linking against object files, linking against static library may result is a smaller final executable. The reason for this is, if you don't call any of the functions from a particular object file (included in the static library), the linker will not include the code for those functions in you final executable. See Extraneous Library Linkage