How are .lib files structured? - visual-c++

I'm currently trying to incorporate some libraries into a Windows C++ project. Now I used to assume that .lib files were used for static libraries and .dll were used for dynamic libraries. Feel free to correct this thought.
However, after trying to actually use libraries (whether that be static or dynamic), it seems like you are required for provide a .lib. So that makes me think that .libs are not associated with just static libraries, but also dynamic libraries.
So how exactly are .lib files structured? How can your project determine whether or not a .lib file is associated with a static library or dynamic library? I assume there must be some information encoded into the .lib file that states whether or not this .lib file actually contains compiled classes/functions, or if it doesn't (in the case of dyanmic library).

Related

gnu linker doesn't include unreferenced modules in a shared library

I have a shared library that consists of quite a few .c modules, some of which are themselves linked into the shared library from other static .a libraries. Most of these are referenced internally within the library, but some are not. I'm finding that the linker does not include those modules in the shared library unless there is at least one call to a function in the module from within the shared library. I've been working around this problem by adding calls in a dummy ForceLinkages() function in a module that I know will be included.
That's okay, but it's surprising, since I'm using a .version file to define a public API to this library. I would've thought including functions in those unreferenced .c modules in the .version file would constitute a reference to the modules and force them to be included in the library.
This library was originally developed on AIX, which uses a .exp file to define the public API. And there, I've never had the issue of unreferenced modules not getting included. I.e., referencing the modules in the .exp file was enough to get the linker to pull them in. Is there a way to get the linux linker to work like that. If not, I can continue to use my silly ForceLinkages() function to get the job done...
That's okay, but it's surprising, since I'm using a .version file to define a public API to this library.
The .version file (assuming it's a linker version script) does not define the library API. If only determines which functions are exported from the library (and with which version label) and which are hidden.
I would've thought including functions in those unreferenced .c modules in the .version file would constitute a reference to the modules and force them to be included in the library.
The version script is applied after the linker has decided which objects are going to be part of the library, and which are going to be discarded, and has no effect on the decisions taken earlier.
This is all working as designed.
You need to either use --whole-archive --no-whole-archive (this has a danger of linking in code you don't need and bloating your binaries), or keep adding references as you've done before.

Why are C/C++ 'obj' files valid only for a specific compiler?

After much struggling with attempting to link a C++ project to a 3rd party static library (.lib), I think I have solved the issue by verifying that I compile my project using the same compiler in which the .lib file was compiled (MSVC11).
Until this point, I assumed all .obj files were equivalent, thus I could take a .lib file (containing various .objs), and use that with any other project I might want to develop in the future. However, this was an incorrect assumption.
So I'm curious as to why (in the context of MSVC) .obj files differ from one version of the compiler to the next. Assuming you're targeting an x86 application, shouldn't the obj files be comprised of the same types of instructions regardless of whether or not you compiled using MSVC11/12/14?
TLDR; Why can't I link a project to an .obj that was created using a different MSVC compiler?
That's because it could be linked to another version of Visual C++ runtime libraries, which is incompatible with the version you are using.
This problem could be even with DLLs if you try to expose C++ objects from it.

What is a 'library' file? ie: shared library

For example, the description of /lib/ is that it contents shared library files for the system.
What exactly is a library? Are we talking about library files similarly to importing a library in C? What is contained in a library file and what are they used for?
What relation does it have to a .dll
A library is just a block of code, and sometimes data, that can be used by other programs. Objects in a static library get physically included in a program's code at linking time, and each program using them will have its own copy. Objects in a shared library will be accessed by a program at run time. A .dll is just Microsoft's word for a shared library, the equivalent on Linux would usually be .so.
A library is a collection of routines that can be called from different programs or libraries. Dynamic (shared) libraries can be loaded at runtime, so the library can be swapped without having to recompile the programs using it. /lib/ contains the libraries available on your operating system, but they don't have to be C libraries.
.dll is the Windows equivalent of shared libraries (.so).

Installing package from source on an initial ram filesystem

I'm trying to install multiple packages into an initial ram file system. I'm using uclibc as my C library. This could be a stupid question but...
Would the compiled program also need a C library installed onto the initramfs?
Am I right in thinking that when a program is compiled from source, it is compiled into some sort of executable? Will the application on the initramfs be ready to run once I have make installed (with the correct prefix and providing dependencies are met )?
Whether a compiled program needs a C library - or any kind of library, for that matter - depends on how it was linked.
In general, if your program was linked statically then it does not have any external dependencies - it only needs a working kernel. The executable code of any library that it depends on will have been incorporated into the final executable.
If, on the other hand, it is linked dynamically, then it still needs the shared object files of the libraries it depends on. On Linux, most library shared objects (also known as shared libraries) follow the convention of having a filename with either a .so extension or, in general, a *.so.* format. For example /lib/libssl3.so and /lib/libncurses.so.5.9 are both shared libraries on my system.
It is also possible to have an executable that is statically linked against some libraries and dynamically linked against others. A common case where this happens is when rare or proprietary libraries are linked in statically, while standard system libraries are linked in dynamically.

Linking against shared objects at compile time

In Windows, many .dlls come with a static .lib counterpart. My understanding is that the .lib counterpart basically contains LoadProcAddress calls so that the programmer doesn't have to do it him/herself. Essentially, a time saver. When I switched to Linux, I was assuming the situation was the same, replacing .dll with .so and .lib with .a, but I have come to a situation that is showing me this is wrong and I can't figure out what is going on:
I am using a library that comes as a .a/.so pair. I was linking against the .a, but when I executed ldd on the binary that was produced, it contained no reference to the corresponding .so file. So then, I tried linking against the .so file and to my surprise, this worked. In addition, the .so file showed up when I executed ldd against the resulting binary.
So, I am really confused as to what is going on. In Windows, I would never think to link against a .dll file. Also, in Windows, if a .dll file was accompanied with a .lib and I linked against the .lib at compile-time, then I would expect to have a dependency on the corresponding .dll at runtime. Both these things are not true in this case.
Yes, I have read the basic tutorials about shared objects in Linux, but everything I read seems to indicate that my initial assumption was correct. By the way, I should mention that I am using Code::Blocks as an IDE, which I know complicates things, but I am 99% sure that when I tell it to link against the .so file, it is not simply swapping out the .a file because the resulting binary is smaller. (Plus the whole business about ldd...)
Anyway, thanks in advance.
I was linking against the .a, but when I executed ldd on the binary that was produced, it contained no reference to the corresponding .so file.
This is expected. When you link statically, the static library's code is integrated into the resulting binary. There are no more references to or dependencies on the static library.
So then, I tried linking against the .so file and to my surprise, this worked.
What do you mean, that the static linking did not work? There's no reason that it shouldn't...
.lib are used in Windows to dynamically link. You don't have them in Linux, you link with .so directly.
The .a file is the statically built library, you use it to link statically.
To add to already correct answer by tharibo - in some situations (e.g. delayed shared library load) it might be desirable to do it the Windows way i.e. by linking against a static stub instead of .so. Such stubs can be written by hand, generated by project-specific scripts or by generic Implib.so tool.

Resources