Skip to content

Your read me says to use "-all_load" but you should use -force_load #169

Closed
dhoerl18 opened this Issue Apr 15, 2012 · 8 comments

3 participants

@dhoerl18

When someone uses "-all_load", every imported library is forced into memory whether its needed or not. A much better technique is "-force_load":

-force_load $(BUILT_PRODUCTS_DIR)/libarc.a

This insures that ONLY your library is loaded, not every library.

http://developer.apple.com/mac/library/qa/qa2006/qa1490.html

IMPORTANT: For 64-bit and iPhone OS applications, there is a linker bug that prevents -ObjC from loading objects files from static libraries that contain only categories and no classes. The workaround is to use the -all_load or -force_load flags. -all_load forces the linker to load all object files from every archive it sees, even those without Objective-C code. -force_load is available in Xcode 3.2 and later. It allows finer grain control of archive loading. Each -force_load option must be followed by a path to an archive, and every object file in that archive will be loaded.

@odrobnik

How is this an issue? You are welcome to modify the readme if there is a better technique.

@dhoerl18

OK - will send in a pull request. The issue is that for users of your library, adding -all_load means that other libraries they link too - even c based ones - get loaded into memory immediately when their app launches (bloating the size of their runtime). On the Mac it would not be so bad - you have virtual memory - but on the iPhone this is REAL precious ram getting used for no reason.

@odrobnik

I think you are confusing two things here. On iOS all libraries are static and the linker will copy all code into the binary from them. There will be no memory difference on an iOS device.

@dhoerl18

Hah - yes, I stand corrected on the memory. However, I still suspect the behavior is different although I cannot think of how at this moment. If the behavior was the same, why would Apple provide the two flags? We know that classes do not get their initialize message until they are loaded, and categories do not receive a "load" message til loaded. Perhaps the all_load flag forces internal categories to load immediately before they are really needed. I cannot find anything on the web on this, yet if all_load was the same as force_load, why provide both? Apple's own doc's say you get a "finer grain control" with force_load.

@dhoerl
dhoerl commented Apr 17, 2012

OK - there is a thread on this in the objc-language@lists.apple.com forum on Apple's site. Note that Greg Parker is the compiler guru at Apple with thread "iOS -force_load versus -all_load":


-all_load and -force_load act a link time, not at load time. -all_load and -force_load tell the linker to link the entire static archive in the final executable, even if the linker thinks that parts of the archive are unused.

When you link a traditional C static archive (.a file), any code from the archive that is never referenced in the final executable is simply omitted from the executable. So if you had a static archive with 999 functions you did not call and 1 function that you did call, your final executable would include only that one function.

Objective-C categories break the C static archive model, because you want the Objective-C category to appear in the final executable even though there are no C symbol references to it from the executable.

The best solution for Objective-C categories in static archives is the -ObjC linker option, which tells the linker that all Objective-C categories in the archives are "used" but to apply the usual reference algorithm for everything else in the archives.

The -ObjC option is broken in some versions of the linker. For those cases the -force_load and -all_load options work. The final executable may be larger than necessary with those options, if there were classes or C functions that could have been omitted by the linker. If you have multiple archives and only some of them have Objective-C code then -force_load may generate smaller output than -all_load.

-- Greg Parker Runtime Wrangler


D Hoerl comment:

If you want to minimize your footprint, use -force_load, not -all_load

@odrobnik

I understand this as: try first only the -ObjC flag. If the app crashes due to an unrecognized selector use one of the force parameters.

Since you probably only have one or two static libraries then there will be no difference in binary size between these two flags, since dynamic libraries code is not merged into your app. So a force load and an all load with a single library should produce identical output.

When in doubt I prefer the simpler solution, which is force load since it does not require to determine the path of the lib.

@odrobnik

I updated the Readme accordingly: 300a8d8

@odrobnik odrobnik closed this Apr 17, 2012
@dhoerl
dhoerl commented Apr 17, 2012

Well sort of. -ObjC should work for all ObjC libraries, but it has a bug and does not link in files with just categories. So the force_load flag, as is on the thread but not posted here, really a linker flag.

The issue with with you using -all_load in your README is that people incorporating your library may have many other libraries loaded as well (as I do).

In case you don't have the exact line handy, here it is: -force_load $(BUILT_PRODUCTS_DIR)/libarc.a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.