Jacob’s Tech Tavern

Jacob’s Tech Tavern

Static, Dynamic, Mergeable, oh, my!

A theoretical guide to libraries, frameworks, and linking

Jacob Bartlett's avatar
Jacob Bartlett
Nov 18, 2024

A primer on libraries, frameworks, and linking, and an explanation of what’s meant by static and dynamic. We’ll finish by learning about the new mergeable libraries.

If you want to embarrass a senior iOS engineer, ask them to explain the difference between Dynamic Frameworks and Static Libraries.

These concepts are enormously important, but for years, they were packaged up in a box in my brain labelled “I’ll learn about these one day, but until then, I’ll have impostor syndrome”.

Unless you’re working to reduce app bundle size, simplify your dependency graph, optimise launch performance, or speed up build times, you won’t get to put this knowledge into practice.

Let’s change that with a primer on libraries, frameworks, and linking, and then let’s understand what is meant by static and dynamic. We’ll finish by learning about the new mergeable libraries available in Xcode.

Libraries vs Frameworks

Libraries and Frameworks are actually very straightforward if you approach them with fresh eyes. 

The main reason they feel confusing is because they are usually explained very poorly.

Libraries

Libraries are pure code. They can be imported into your projects to provide reusable classes and functions. Libraries can be static (.a) or dynamic (.dylib). We’ll look at the differences between static and dynamic libraries later in the section on linking.

Frameworks

Frameworks are folders which contain a library. This library can be either static or dynamic, which the folder inherits — it becomes a static framework if it contains a static library, and a dynamic framework if it contains a dylib.

Alongside the library, framework folders contain additional resources & metadata, including: 

  • Asset catalogues 

  • Strings, Nib files, Obj-C headers, & metadata

  • Code signatures

  • Documentation

Here’s what a real (dynamic) .framework folder looks like: 

Dynamic framework folder containing assets, code signature, Info.plist, and Unix executable

You can see the assets, code signature, and Info.plist metadata. The code itself is packaged into a binary (Unix Executable File). This is compiled and ready to link to the app.

Library Assets & Bundles

Libraries themselves do not contain assets, but you can create them with a resource bundle (in Swift Packages this is named Media by default). These resources are included in the app as part of a .bundle file.

This sample app includes a TavernUI library, containing a design system & assets. The code from the TavernUI library is linked directly into the main executable, TavernTools. The TavernUI.bundle file which contains the assets was packaged separately inside the main .app bundle.

An asset bundle from a library visible inside the .app bundle

What is Linking?

In Computer Science, a linker combines compiled object files together into a single executable entity.

If you work for a company with a large, complex app, it probably consists of a main target (plus extensions), several feature modules, additional layers for core utilities, and third-party dependencies. 

These modules are processed by the Swift Compiler, then the linker… well, links these compiled modules together. They are ultimately merged into a single program that the OS can run: your app.

When does this linking happen? It depends.

Static Linking

Static linking is the last stage of the Swift compiler. After processing Swift through SIL, optimisations, and LLVM IR, it ends up as machine code (a.k.a. ARM assembly) inside object files (.o) which look like this:

mov x0, #0x0   ; Move 0 into register x0
bl  _printf    ; Branch to the printf function
ret            ; Return from the function

This assembly code is represented in the object file as TEXT. As well as this finely-optimised machine code, object files also contain:

  • A symbol table, which maps functions and variables to memory addresses in your running program.

  • Global and static variables, represented in the file as DATA.

  • Debug information, a.k.a. DWARF.

Static Copying

If your library or framework is static, then its compiled object files are copied into the main Unix executable during static linking.

This copying is critical to understand: the performance characteristics of static vs dynamic linking are all downstream consequences of this compile-time copying.

If you have large libraries, it takes a long time to copy them all into the binary. Even worse, if your app has a complex dependency graph, importing many inter-dependent libraries, this copying will happen repeatedly, even for incremental builds. To developers, this manifests as a longer build time.

After static linking finishes, we are left with a single Mach-O executable. This consists of the compiled object files in your main app, linked with the object files from all the static libraries & frameworks throughout your dependency graph.

This single statically-linked executable is loaded up by the OS to run your app. Since it’s just a single file, this launches pretty fast.

This makes static linking pretty great for end-users. This UX benefit is why non-system modules are statically linked into your app by default.

Static Bloat

If you have a big or complicated app, you may include extension targets such as widgets or a notification share extension. 

If you’re not careful, you might experience the biggest drawback to static linking: static libraries & frameworks — alongside their associated resource bundles — are copied into every target. 

This can dramatically bloat the size of your app.

TavernUI resource bundle copied into an app + each extension target

Dynamic Linking

Dynamically linked libraries and frameworks are linked at runtime by a system called dyld. 

Subscribe for free to continue reading

Enter your email and get every post from Jacob’s Tech Tavern.
Already have an account? Sign in
© 2026 Jacob Bartlett · Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture