I am building a library from my source code which contain both header (.hpp) and source (.cpp) files. I have a make file which compiles all the source files into respective object file individually and then a library creation (ar rcs ..) statements which combines all the *.o files and builds a static library out of it. The resulting size of the library file is huge (around 17 Mb). Instead when I do g++ -o a.out *.cpp the out file has a size of 1.4 Mb. Is the archiver command (ar rcs) not removing redundant information from all the individual object files ? I also created shared objects and those were small as well, but I need a static library file for my purpose
Try strip the library, the debug and symbol information and tables might take the extra space.
Also, the ar s option might inflate the resulting archive (again, strip, or just don't use ar rcs, just ar rc).
What happens when you link your static library into a final binary? There's a lot of extra data that should get stripped out during the link process into a binary.
Related
I have multiple static libraries in C++. For example:
lib a
lib b
lib c
lib a uses lib c and lib c uses a and b uses both. We have a circular dependencies between the libs. Because they are static libs is the output size bigger if they are circular, because they are included both in b. a is included in c and c in a sode the code is in b twice :(
Can somebody explain me how this works?
And if a, b and c would be linked to d would be the code of c inside d twice too?
is the output size bigger [when linked multiple times]?
No, the output size of your executable does not change with the order of your libs and also not with the number of times you specify the libs.
Can somebody explain me how this works?
When creating an executable (not a library): The linker usually links on *.o file granularity, which means that either a *.o file is included in the executable or not. But each *.o file is included in the executable only once. This is why the size does not differ, even if you link lib a three times.
And if a, b and c would be linked to d would be the code of c inside d
twice too?
Static libraries are usually not linked together. They are just repackaged together as a new ar archive. And, like in the executable case, each *.o file stays in the new library (the new ar archive) only once, so the size does not get bigger, even if you add a library twice, directly or indirectly.
Reducing executable size: If you are concerned about the size of your executable and you are using gcc or LLVM, there is a nice way which allows you to reduce it:
Tell gcc to put each individual function into an individual section: -ffunction-sections
Then tell the linker to garbage collet (discard) unused sections: -Wl,--gc-sections
It is surprising that this is not the default. Without these options always the entire *.o file is present in the executable if at least one thing in this *.o file is referenced. Unused *.o files are always discarded as well (unless specific options are provided), but not on function-level.
Linking dynamic libraries (shared objects, DSO, whatever you want to call them) is again a different matter on UNIX systems and more complex.
Libraries don't get statically linked to each other; they get statically linked in to executables.
So, it doesn't matter what libraries refer to each other — lib a will never contain a copy of lib c (excepting the possibility of code inlining).
Your linker, when building your executable, will also pull in each dependent library only once.
However, said executable will be larger than it would be if you were dynamically linking these libraries, and every other executable that you make with the same libraries will have its own copy of them too. That's the layer to be thinking about here.
I've been recently reading about static and dynamic linking and I understood the differences and how to create static and dynamic library and link it to my project
But, a question came to my mind that I couldn't answer or find answer for it as It's a specific question ... when I compile my code on linux using the line
#include <stdio.h>
int main()
{
printf("hello, world!\n");
}
compiling using this command
[root#host ~]# gcc helloworld.c -o helloworld
which type of linking is this??
so the stdio.h is statically or dynamically linked to my project???
Libraries are mostly used as shared resources so, that several different programs can reuse the same pre-compiled code in some manner. Some libraries come as standard libraries which are delivered with the operating system and/or the compiler package. Some libraries come with other third party projects.
When you run just gcc in the manner of your example, you really run a compiler driver which provides you with few compilation-related functions, calling different parts of the compilation process and finally linking your application with a few standard libraries. The type of the libraries is chosen based on the qualifiers you provide. By default it will try to find dynamic (shared) libraries and if missing will attempt for static. Unless you tell it to use static libs only (-static).
When you link to project libraries you tell the gcc/g++ which libraries to use in a manner (-lname). In such a way it will do the same as with the standard libraries, looking for '.so' first and '.a' second, unless -static is used. You can directly specify the path to the full library name as well, actually telling it which library to use. There are several other qualifiers which control the linking process, please look man for 'g++' and 'ld'.
A library must contain real program code and data. The way it is linked to the main executable (and other libraries) is through symbol tables which are parts of the libraries. A symbol table contains entries for global functions an data.
There is a slight difference in the structure of the shared and static libs. The former one is actually a pre-linked object, similar to an executable image with some extra info related to the symbols and relocation (such a library can be loaded at any address in the memory and still should work correctly). The static library is actually an archive of '.o' files, ready for a full-blown linking.
The usual steps to create a library is to compile multiple parts of your program into '.o' files which in turn could be linked in a shared library by 'ld' (or g++) or archived in .a with 'ar'. Afterwards you can use them for linking in a manner described above.
An object file (.o) is created one per a .cpp source file. The source file contains code and can include any number of header files, as 'stdio.h' in your case (or cstdio) or whatever. These files become a part of the source which is insured by the cpp preprocessor. The latter takes care of macros and flattening all the #include hierarchies so that the compiler sees only a single text stream which it converts into '.o'. In general header files should not contain executable code, but declarations and macros, though it is not always true. But it does not matter since they become welded with the main source file.
Hope this would explain it.
which type of linking is this?? so the stdio.h is statically or
dynamically linked to my project???
stdio.h is not linked, it is a header file, and contains code / text, no compiled objects.
The normal link process prefers the '.so' library over the '.a' archive when both are found in the same directory. Your simple command is linking with the .so (if that is in the correct path) or the .a (if that is found in a path with no .so equivalent).
To achieve static linking, you have several choices, including
1) copy the '.a' archive to a directory you create, then specify that
directory (-L)
2) specify the path to the '.a' in the build command. Boost example:
$(CC) $(CC_FLAGS) $< /usr/local/lib/libboost_chrono.a -o $# $(LIB_DIRs) $(LIB_NMs)
I have used both techniques, I find the first easier.
Note that archive code might refer to symbols in another archive. You can command the linker to search a library multiple times.
If you let the build link with the .so, this does not pull in a copy of the entire .so into the build. Instead, the .so (the entire lib) is loaded into memory (if not already there) at run-time, after the program starts. For most applications, this is considered a 'small' start-up performance hit as the program adjusts its memory map (auto-magically behind the scenes) Note that the app itself can control when to load the .so, called dynamic library.
Unrelated:
// If your C++ 'Hello World' has no class ... why bother?
#include <iostream>
class Hello_t {
public:
Hello_t() { std::cout << "\n Hello" << std::flush; }
~Hello_t() { std::cout << "World!" << std::endl; }
void operator() () { std::cout << " C++ "; }
};
int main(int, char**) { Hello_t()(); }
I'm using code blocks IDE and GNU GCC compiler. when i create a simple program like e.g. add.cpp (for adding two number) it usually creates two file add.exe (executing file) add.o(object file) according to some of them add.o is linked to add.exe while executing.
my question is i deleted the add.o still the add.exe is executing and still producing the required results. how this is possible if the object file is missing ?? and please also explain me what object file really does ??
The object file is linked at compilation time... The object file is then redundant post all the compilation. The o files are maintained between builds so you don't need to rebuild unchanged parts of your application.
From source to executable (in a really oversimplified sort of way):
1) The pre-processor gathers the #include'd files for each .cpp in turn, runs macros, etc, and produces a "translation unit" for each file. These contain all the includes, and the macros have been evaluated: it's otherwise recognisable as source code.
2) The compiler runs over each translation unit, and turns the source into machine-instructions in "object files". These object files contain references (called "symbols") to the functions and variables it has defined, and those that are mentioned but never defined.
3) The linker grabs all the object files, and matches up the symbols across different object files. It then produces an executable.
You can freely run your executable without either the source or object files: these were read in order to produce the next step. Object files are left behind because usually you don't need to rebuild everything each time you press compile: if you only changed one source file, you only need build one new object file, and one new executable.
Files .o are not linked to exe at runtime, they are linked to it at compile time (specifically, during the linking step). Once you have an executable, you can safely remove all object files that were linked into it. It is also OK to remove all static libraries that were statically linked into the exe, because their content becomes part of the executable.
the object file contain the result of the compilation. the exe file contain the result of the link. You can delete the o file if you want exe still working
There are 2 types of linking: static and dynamic. When you compile something the compiler produces object files which are linked statically into your executable. Only if you use an external library and only if you link dynamically against it will you need to have access to it.
The .o file is used for compiling, the .exe. Where the .o is an compiled object code to be later used to compile other programs.
Where as the .exe is the compiled file, and does not require .o.
Given compiling:
g++ -c Hello.cpp -o Hello.o
g++ Hello.o main.cpp -o mainprogram.exe
The first line, creates a .o file but does not do external linking. The second line uses this .o and .cpp file and links your program together.
The only files you require for a program to function that are not in .exe are .so files or .a which are shared and static libraries respectively.
For object file this may help http://en.wikipedia.org/wiki/Object_file
I have 2 library files, lib1.a and lib2.a in my project. Lib1.a is using lib2.a . I have given source code of lib2.a but I don't have source code of lib1.a. For my project I changed lib2.a lets say I add a local variable inside a function.
My question, function names didn't changed, do I need to recompile lib1.a with changed lib2.a ?
Is there anyway I tell to linker "lib1.a should use new lib2.a" without source code of lib1.a ?
If it's just something like an added local variable as you say, there should be no need to rebuild the other library. This is because static libraries don't typically link each other directly, but rather the executable eventually links them all together.
I am migrating a C++ dynamic DLL library from Windows OS to iOS with static library(.a).
And some issues come up about the binary image size.
Here are some data I got.
Image size:
dynamic library (DLL compiled in Windows OS) : 1.4M
static library(.a,complied with Touch Static Library): 34M.
I checked each complied C++ source file between 'Obj' and 'o'. The size of them are almost same.while,after linked them together,the size of DLL is 1.4M, while the '.a' image size is 34M.It seems image size of '.a' approximate to the summation of all the '.o' files.
Is there any suggestion and guideline for migration C++ code to iOS?,especially in image size.
Is there any link flag for compiling C++ source code in Cocoa Touch Static Library project?
In Unix-based systems (including iOS), a ".a" file is simply an archive (man 5 ar) combining a bunch of ".o" files in a single unit (possibly with the inclusion of a symbol table). So, your observation the size of the ".a" file is the summation of the ".o" files is exactly correct.
When you link an application against a ".a" file, the final executable will include only the elements of the ".a" file that are actually referenced.