14

This is an iOS question.

I build a static library (a framework in iOS) which is then included in an app. The size of the result binary (500kb) is smaller than the size of the static library (6mb). How does this work? My understanding of static library is that the static library is included in the final binary

Evil Nodoer
  • 1,927
  • 3
  • 23
  • 32

2 Answers2

25

Because you are not using all the functions of your library. A static library of archive type .a is a collection of .o object files and only the object files needed in your program are included at link time.

ouah
  • 142,963
  • 15
  • 272
  • 331
  • 1
    In addition to this, a properly-factored library has each function (or family of tightly-related functions) in a separate `.o` file. In such usage, `.o` file header overhead can easily be 25% of the file size for each `.o` file, and in the worst case the overhead can be tens or hundreds of times the code size. That is to say, a well-factored `.a` file might typically be 50% code and 50% `.o` file headers. Of course this works together with ouah's answer: the better-factored a library is, the more opportunities the linker has to omit unneeded object files. – R.. GitHub STOP HELPING ICE Mar 30 '12 at 00:11
  • I agree in principle with @R..'s comment. But these days the tools can do some of these tasks automatically (e.g. gcc's `-ffunction-sections` (effectively puts each function in a `.o` file) et al.), so maybe doing this at the source code level is not as important as it once was. – ldav1s Oct 29 '13 at 17:45
  • @ldav1s: While `-ffunction-sections` and related options are available, I don't think they're in widespread use, and I'm not clear on whether the necessary linker options are even enabled by default. There are also some cases, like static structures containing function pointers, where `-ffunction-sections` might (again, I'm not sure) be insufficient to eliminate the unneeded functions. – R.. GitHub STOP HELPING ICE Oct 29 '13 at 20:01
  • @ouah what happens when you use the `-Objc` linker flag which forces inclusion of all functions regardless of whether they are used? – Tony Sep 17 '16 at 00:23
3

Whenever you statically link an executable, the linker can go ahead and resolve all symbol names (i.e. map them to an address) since all the symbols it will know about you have provided to the linker now (in the form of .o files and .a libraries which are really just a collection of .o files). If there are names that aren't there, you'll get a link error (this is different than dynamic linking where you may be able to load another library at runtime). In your case, you have extra symbols that are unreferenced by the executable. Since these symbols are known to the linker as being unused they are simply removed from the executable output. So your executable will be smaller than the input libraries in this case.

ldav1s
  • 15,885
  • 2
  • 53
  • 56
  • What happens when you add the `-Objc` or `-all_load` flag? – Tony Sep 17 '16 at 00:40
  • The effects of `-Objc` [described here](https://developer.apple.com/library/content/qa/qa1490/_index.html) says it will "load all members of static libraries that implement any Objective-C class or category.", and as a caveat says "But it can make the resulting executable larger, and may pickup unnecessary objects.". So this will make the executable larger than regular linking (if you have those objects). `-all_load` sounds even more aggressive including object code according to [this description](http://stackoverflow.com/a/2906210/425738), including more object code. – ldav1s Sep 17 '16 at 01:26
  • Does that mean that when you add the flags the executable should be just as large as the combination of libraries it includes? In practice that does not appear to be the case. – Tony Sep 19 '16 at 09:04
  • Not necessarily. As I parenthetically stated before, those objects affected by `-Objc` and `-all_load` need to be in the object code. If those objects (e.g. extra Objective-C classes or categories) aren't in the libraries or collection of .o files, then they aren't going to linked to the executable. – ldav1s Sep 19 '16 at 15:58