
iOS Static Libraries Are, Like, Really Bad - wooster
http://landonf.bikemonkey.org/code/ios/Radar_15800975_iOS_Frameworks.20140112.html
======
itripn
I had a pretty detailed discussion with iOS engineers at a WWDC a couple of
years back. It was a somewhat frustrating conversation, mostly because of how
badly I wanted true user generated Framework support, but also because the
engineers had decent reasons for the existing state of things. Primarily that
Frameworks (in their fullest expression) are dynamically loaded.

Apple has made a decision that allowing 3rd parties to dynamically load code
(outside of Apple certified frameworks) is a security issue on a mobile
platform in particular. I don't have a solid counter argument, although there
are certainly some technical constraints they could put in place to help
mitigate the risk.

Anyway, agree with your essay in general. But I also understand how we got
here.

Cheers

~~~
binarycrusader
If anything, in my mind, _not_ using shared libraries is a security issue.

For example, if every application links to a static version of some image
loading library, then all of the applications must be patched if there is a
vulnerability in that library.

Whereas if they all share the same copy, you patch the library, and they all
get fixed.

I'm aware that model works better when the same vendor is providing all of the
binaries, but there are cases where it's also appropriate for general ISVs.

~~~
CoolGuySteve
It's a two sided coin, if you update a dynamically loaded library that subtly
breaks backwards compatibility, you end up with apps that mysteriously stop
working because of some other update in the system.

Really, it's up to the app maintainer to update their program, and if it has a
vulnerability, in theory the sandbox will prevent it from doing damage to
others.

~~~
binarycrusader
If someone updates a library incompatibility, they deserve what they get.
That's why shared libraries have versioning.

In the mobile space, it would be even more beneficial if platform holders and
ISVs actually followed this; the memory and space usage savings could be
substantial.

~~~
binarycrusader
I'm uncertain why someone would downvote my comment above, but shared library
versioning is a real thing, and it is a best practice:

[http://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html](http://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html)

[http://tldp.org/HOWTO/Program-Library-HOWTO/shared-
libraries...](http://tldp.org/HOWTO/Program-Library-HOWTO/shared-
libraries.html)

[https://www.usenix.org/legacy/publications/library/proceedin...](https://www.usenix.org/legacy/publications/library/proceedings/als00/2000papers/papers/full_papers/browndavid/browndavid_html/)

Linux distributions heavily depend on this for the GCC runtime libraries (such
as libgcc_s); it's how they provide backwards compatibility.

Many operating system distributors also rely on symbol versioning for their
shared libraries as well so they can compatibly evolve interfaces for
consumers.

So my original point stands, if someone incompatibly updates a shared library
without accounting for versioning, they're doing it wrong.

------
fleitz
If you can distribute source Cocoapods is an excellent alternative to static
libs.

And if you have to distribute static libs Cocapods again makes it much easier.

~~~
seivan
+1, cocoapods is really great and solves 99% of the issues.

EDIT: Issues I had with integrating third party libs into projects as
dependencies in the past, not issues in regards to the blog post.

~~~
therealkerni
You might want to read the blog post again: CocoaPods does NOT solve the
mentioned issues or provides the system that should be made available for
developers as it exists on OS X.

~~~
seivan
Sorry, you're right, but still mean my own issues with dealing with third
party libraries, it does help out quickly adding something so I could get to
use it.

------
mwcampbell
I wish that embedding resources in programs as const byte arrays were more
common. I think that approach leads to a tightly integrated, low-overhead app,
especially on platforms (not iOS) where users and third-party programs are
free to do stupid things with the file system; the app either works completely
or isn't there at all.

~~~
liuliu
You mean like:
[https://github.com/liuliu/mopack](https://github.com/liuliu/mopack)? But
unable to inspect the embedded resource at programming time is a big show-
stopper for me.

~~~
frou_dh

        $ xxd -i some_file

~~~
liuliu
last time I checked, Microsoft has a weird restriction on their c++ compiler
(they don't have a c compiler) that only allows 4k length const chars, you
have to concatenate consts to get arbitrary length.

------
pjmlp
I really don't see why dynamic libraries couldn't be allowed per app, in a
similar vein to other mobile OS.

It is also sad state of affairs that Objective-C builds up on C's tradition of
not having proper namespace support.

~~~
simonh
> I really don't see why dynamic libraries couldn't be allowed per app, in a
> similar vein to other mobile OS.

Apple considers it a security issue, so presumably they have figured out
attacks that exploit dynamic library loading.

In general though, "Because another platform does it" isn't always a good
argument for a particular feature in a platform, particularly when that choice
involves a tradeoff. Taken to an extreme, you would end up with a lowest
common denominator of samey platforms that just copy each other's design
decisions.

In this case Apple has decided that security is a top priority for them even
if it comes at a price in terms of developer convenience. Other platforms are
free to make different tradeoffs, and that gives users and developers a
diverse choice of distinctive platforms available to them. This is a good
thing. iOS doesn't have to become Android any more than Android has to become
iOS.

~~~
pjmlp
By other mobile OS, I meant :

\- Epoch OS

\- Symbian

\- Windows CE/Pocket PC

\- Windows Phone 7/8

\- Android

\- Blackberry

\- Bada

The above vendors do have/had secure deployments mechanisms despite support
for dynamic libraries.

~~~
simonh
Are these validated to be secure, in this way, or are you just asserting that
they are? Bear in mind that many intentional features of Android would
considered by Apple to be severe user privacy violations. There platforms
aren't just different technically, their standards for what security is
considered to be vary significantly. That's fine because if you want those
features in Android, then Android has them, but if you prefer a garden with a
higher wall, there's iOS.

~~~
pjmlp
You surely seem to have a problem with Android it seems, as you selectivly
ignore all the other ones on your remarks.

------
jheriko
As much as I generally dislike the iOS ecosystem, Xcode and Apple in general
this feels like complaining about nothing much of importance to me...

If you want to share code this becomes a non-issue - you include the code
which can detect things like architecture and target at compile time and then
its possible to not just transcend the boundary between iOS and OS X, but also
Windows Desktop + RT, Android, other *nix flavours and that great operating
system that will be released in 7 years time that we don't even know about
yet...

a static library is a convenience of pre-compiled code, but also an
inconvenience where you can't see inside or implement the many cool things you
can with the preprocessor, meta-programming or even scripts that generate code
or enforce constraints if you feel so inclined...

Why do you really want static libraries to be usable? Are they really a good
thing? Is it really any more convenient than just including a folder of source
code in the project?

The only real argument I can see is if you want to keep your code secret which
I am philosophically opposed to in the general case...

~~~
therealkerni
The blog post contains lots of reasons, you might want to read it.

Here is only one example of why including via source code can be a bad thing:

> In the years past, for example, I saw issues related to a specific linker
> bug that resulted in improper relocation of Mach-O symbols during final
> linking of the executable, and crashes that thus only occurred in the
> specific user's application, and could only be reproduced with a specific
> set of linker input.

In addition: the writers frameworks/libraries are all (!!) open source! And
you claim the only reason for using libraries is keeping the source secret.
Yeah!

~~~
jheriko
i had a good read... what precisely is the hole in my argument?

there are a few arguments there but they are not especially compelling imo and
I feel the advantages of using naked code far outweigh the disadvantages of
using a library (the only advantage i can think of which is genuine is hiding
your code as binary). let me give my counter to some of the arguments made for
why a library is a good thing by way of demonstration:

> a single atomic distribution bundle that applications developers can drag
> and drop into their projects.

this is programming - drag and drop is a fantastic luxury and a terrifying one
if you like to understand what happens. in any case dragging and dropping a
folder in to xcode containing code and resources is just as easy but has the
benefit of being absolutely transparent.

> One of the significant features of frameworks on Mac OS X is the ability to
> bundle resources. This doesn't just include images, nibs, and other visual
> data, but also bundled helper tools, XPCServices[1], and additional
> libraries/frameworks that their framework itself depends on.

loose files have this desirable property except for being in a convenient
package - including a folder reference or duplicating it as a group in xcode
is a drag and drop operation.

> One of the features that is possible to achieve with static libraries is the
> management of symbol visibility.

Yeah... loose code files have this /better/ than a library typically does if
you like all symbols to be visible. (otherwise its a valid point and lets you
hide your code again...)

> Dependent Libraries

including dependencies is a pain, but it makes sure people can use your code
immediately. i like one-step processes - every project i've done in the last 5
years or so works with a single check-out from source control - in some cases
even if you are lacking the ide or other important tools. the bloat is not
relevant today, even on mobile platforms... although i don't seem capable of
creating many multiple megabytes of code no matter how much i do except for
including some enormous 3rd party library (freetype is the last one i had this
problem with - i never use it any more).

> result in builds of the library being unique

this is a genuine problem - kinda - if your code doesn't build under multiple
platforms and compilers to have the same behaviour then you have much worse
technical debt than this to fix first... like making your code actually cross-
platform and deterministic (if you actually need that).

however all of that aside I think my point about being super cross platform
across *nix, iOS, OS X, Windows RT/Desktop, Android, Windows Phone 8 and
unknown future operating systems trumps the lot...

EDIT: as a real world example consider stb_image.c - a fantastically useful
header providing a very clean image loading interface for the most common
formats (especially compared to any of the OS library alternatives on all of
the platforms where the amount of boilerplate and needless operations is quite
staggering for something so simple). I've used this on all of the above
platforms and the only problem I have is that the author is not so keen on
using the maximum level of warnings like I do... (I like the compiler to never
be confused and have the best information available about my program, and
incidentally libraries deny the compiler valuable information in many cases
too...)

~~~
therealkerni
1\. Sadly you ignored the example I posted completely.

2\. Integrating by source code is valid for some use cases, but it is
definitely not for all. E.g. low level libraries like crash reporters which
can not be platform independent. Or libraries that rely on platform specifics,
like UIKit on iOS.

There is not one approach, one way that fits all. For some
libraries/frameworks are the best, for others direct source code inclusion is
best.

~~~
jheriko
i didn't see it and still can't maybe i am being blind or selectively
filtering it without realising... :/

> low level libraries like crash reporters which can not be platform
> independent.

> Or libraries that rely on platform specifics, like UIKit on iOS.

this is actually not true and i can quite comfortably demonstrate this and
have worked in multiple code bases that do such things across all the major
platforms, including games consoles...

these pieces are the unavoidable platform dependent bits and can be
conditionally compiled accordingly - they are however usually quite small, and
also something which a library can not do

this is imo far and way the biggest strength of source code inclusing and
precisely what i refer to by 'you can run on every current platform and even
ones that don't exist yet'

even 'cross-platform' APIs like OpenGL necessitate this because they make
mistakes, or have ES flavour on mobile with breaking changes vs. Desktop
OpenGL.

EDIT: "> In the years past, for example, I saw issues related to a specific
linker bug that resulted in improper relocation of Mach-O symbols during final
linking of the executable, and crashes that thus only occurred in the specific
user's application, and could only be reproduced with a specific set of linker
input."

ah i guess you mean this. in which case how does a library avoid this? the
linker inputs are usually roughly equivalent to libraries... the compiler
generated a bad object file consistently? I'll agree that compiler and linker
bugs exist but they are the exception and not the case - that effects source
code and not the library is indeed an advantage of a pre-compiled library. I
consider it vanishingly unimportant against being able to work across /all
platforms/.

~~~
saurik
The issue isn't about "conditional compilation": the issue is about symbol
visibility. In fact, I don't think _any_ of the issues discussed in this
article--excepting the bug at the end with MH_OBJECT--would be solved by
giving someone source code: adding a directory of C files to your project is
_semantically identical_ to adding a .a file using -all_load. This is clear
and somewhat obvious, as the only thing I did to create a .a file was to
compile the .c files to .o files for you, which will be the very first thing
your compiler does with the .c file anyway: all I'm doing is saving you CPU
time and some hassle, I'm not changing what happens when the code hits the
linker, and that's where the problem lies. Let's look at one random specific
example from the article (which again, is full of things that happen at link
time, and so would be exactly identical whether you started with source code
or archive files): PLCrashReporter includes a custom build of sqlite3 that has
different options than Apple's; you want the user's code to continue using the
version of sqlite3 that comes on iOS, but you want PLCrashReporter and
PLCrashReporter only to use the custom build. If I give you a giant wad of
course code files, which would then of course include the custom build of
sqlite3 with the extra options PLCrashReporter needs turned on, all of that is
going to be compiled down to .o files (again, exactly what would be in a .a
file that I'd give you were I to have compiled it ahead of time), and the
sqlite3 symbols from the included modified copy would then take precedence
over the ones that come with Apple's SDK for all files in the project: you
solved nothing.

------
malkia
I miss one feature - ffi, and this is not only limited to iOS - with a
.dylib/.so/.dll and some kind of readable interface ("C") you can export
functions for other languages. For exampe luajit, python (ctypes, cffi),
common lisp (cffi), etc.

Another thing is "replacement" \- switch one version with another. This way
I've found that sqlite 3.8.2 was misbehaving for us lately, which points to be
some kind of MSVC related error (compiled 64-bit for windows using VS2010).

Quickly switching to the previous one, without recompiling did another thing -
I had to think less about other possible changes, since only one component
changed - not the whole executable.

Then there are times where I wished everything was statically compiled :) - On
all fronts (Linux, OSX, Windows) there are too many gotchas of pointing the
right way to your dlls.

I seem to favor Windows (get the DLLs first from the apps' folder... well not
strictly, but in general) - but then that's because Windows did not have good
place to put the dlls to begin with (unlike unix).

------
scoopr
I've always thought that since an (iOS) app needs to be fully self contained,
having only static linking makes perfect sense. You also gain dead code
stripping, and linking only the archs that the main binary supports as well.

Most libraries I've dealt with have mostly amounted to interfaces to
respective web apis. In those, having source code distribution makes perfect
sense, even preferable when the libraries are fairly simple and that gives the
freedom to compile them as one wishes. Doing it with sub-xcode projects I've
found to be fairly simple, even if mucking around with header search paths is
still a pain.

Granted, I haven't really experienced library author side of things, but most
of these issues are about drag'n'drop ease of use, which I don't think
_requires_ dynamic libs but is more of a tooling side problem, and frankly has
always been a problem in the c/c++ land at least.

The lack of two-level namespace is a real problem that I've actually
encountered. Then it was a simple rename of a class name away, but I can
easily fathom a situation where it isn't that easy (like the example of
embedded sqlite3).

Also I hadn't realised that the simulator and device builds are lipo'ed
manually, that indeed should have a better way. But would dynamic libs really
help in that situation, you would still ship x86+arm glued together without
notion of the platform, even worse, you might be shipping the x86 as extra
weight on appstore builds.

~~~
lucian1900
Just because dynamic linking is used doesn't mean the library doesn't get
shipped with the app package.

------
memracom
Why use dynamic libraries if you don't need to save storage space or RAM?

We have moved beyond the era of scarcity and even on desktop platforms, lots
of people are including static libraries so that they are not dependent on the
upstream developers' idea of what is needed. So much of this code is open
source that it makes sense to build your own static library, and maybe leave
out cruft that you don't need.

Sure it would be nice to have a choice, but static libraries are not evil.

------
belluchan
I can't read this article without resizing my browser window. Fluid text width
is awful. And yes wikipedia has the same problem.

~~~
asperous
I think fluid text works well for phones and stuff where if you rotate the
screen it flows nicely. The problem is huge displays-- I'm at like 2560x
width.

Edit: A solution I think works okay is simply adding

    
    
        max-width: 500px;
    

to the css properties for p.

~~~
barrkel
You're not maximizing your browser, are you?

The monitor my browser is on has 2560 width, but the client area of the
browser window itself isn't much more than 1200 pixels wide. I keep terminals
and the tree-style tabs to the left of the browser.

------
rburhum
Besides maintainability, there is the issue of not being able to use certain
open source libraries (without some legal complexity) when you statically link
libraries. IMHO, that is a much greater problem.

~~~
eropple
The problems you refer to will still exist with the LGPL (inability to replace
dynamic libraries).

~~~
rburhum
Not sure what you mean. If I had the ability to use shared libraries, I would
be able to use LGPL code.

~~~
eropple
iOS still requires signed code. My understanding is that the LGPLv3, like the
GPLv3, will prohibit this because the user can't deploy it.

~~~
rburhum
In practice, LGPLv3 is much different than previous versions of the LGPL. The
truth is that many excellent projects have chosen to either stick to not go
the v3 route intentionally (because of the extra restrictions), and if they
do, several of them choose to dual license under both versions. I can think of
numerous projects that are under LGPL v2 (like ffmpeg, GEOS, mapnik, custom
webkit) which would cause an amazing suite of iOS applications to surface, but
with the current situation, they cannot. Signing is not a requirement of any
of those libraries mentioned.

~~~
eropple
OK, how does Joe Enduser replace an LGPLv2 library on iOS, as is his legal
right under the license?

~~~
rburhum
Would you kindly point out which section of the LGPLv2 gives you explicitly
that right?

[http://www.gnu.org/licenses/lgpl-2.1.html](http://www.gnu.org/licenses/lgpl-2.1.html)

I would emphasize the terms "work that uses the library" vs "derivative work
of the library" which have historically been used to differentiate between
static vs dynamic linking.

In addition, how would I go about doing this in Android? And how does Apple
distribute LGPL libraries (like Webkit) without "[allowing] Joe Enduser [to]
replace an LGPLv2 library on iOS"?

------
jarjoura
Xcode (and the entire tool-chain) has support for static frameworks that would
negate any distribution problems the OP wants. Apple snips that functionality
out of the iOS SDK for some unknown reason, but I suspect that would be a much
better request to ask for.

I do agree that the iPhoneSimulator and iPhoneOS SDKs should be better
integrated at compile time. Yet, they were architected as completely different
environments, so I suspect that won't be an easy request to fulfill.

Anyway, what benefit would having a dynamically loaded library give you when
each app runs sandboxed? I can just imagine a scenario where one framework
uses a version of ASINetworking and another uses AFNetworking and they both
attempt to use some version of JSONKit to parse out the result. Objective-C
and its amazing namespace collision management will just carefully (and by
carefully, I mean, not at all) pick one implementation over the other and
leave a happy warning for all to see.

~~~
teacup50
Did you even read the article? All of this is covered.

The question of "what benefit would having a dynamically loaded library give
you when each app runs sandboxed" seems to be answered in great detail under
"Debugging Info and Consistency" and "Missing Shared Library Features"

------
wesnerm2
A workaround is to write iOS applications in Monotouch, which does support
DLLs.

~~~
pikachu_is_cool
The problem isn't that Darwin doesn't support dynamic linking (see: 99% of
jailbreak tweaks). The problem is that you can't share the same library across
different applications because of the sandbox / closed platform.

~~~
cstejerean
That's actually not the problem at all, as described by the article. The
problem you describe is a completely separate issue.

~~~
pikachu_is_cool
I suck at reading.

------
ID_HOME
Apple doesn't want small developers on iOS. I thought this was clear 5 years
ago. Every thing they've done in both the market, the UI, and the OS makes it
difficult for small developers to get a leg up and for new technologies to be
adopted. To Apple, integrating 3rd party libraries is not a concern of
there's, that's for the professionals to try to get to work, then use as a
competitive barrier, thus increasing the quality of the top apps in the
market, the only apps that matter.

~~~
gte910h
I think you're seeing intentional malice where really there is a lot of
indifference at some times, and lack of understanding what it's like to start
in this ecosystem.

Cocopods is PAINFUL to get compliant with ruby sometimes, but other then that,
works for a lot of the problems you'll see. It is a leap though.

~~~
ID_HOME
Indifference for small developers? Whatever you want to call it, I don't care.
An indifference at times about how they control the app ecosystem? No.. Just
no.

~~~
pikachu_is_cool
It isn't about not wanting small developers on iOS. That's ridiculous.

