When building an app or a program, you’ll need to link libraries or other programs for execution.
Your app or program needs to run steps in a sequence to instruct operating systems to run a certain task. During this process, the operating system needs to convert source code stored in your program’s libraries to machine code for execution.
Linking refers to the way you combine external programs with the operating system for successful execution. There are two main methods for achieving this: static linking and dynamic linking.
The method you choose depends on several factors, like file size and load time. In this post, you’ll learn the difference between static and dynamic linking, as well as when to use each.
Table of Contents
- What is static linking?
- What is dynamic linking?
- Static Versus Dynamic Linking
- Working With Multiple Executables: Static or Dynamic Linking?
- Combining Static and Dynamic Libraries
What is static linking?
Static linking is the practice of copying all the libraries your program will need directly into the final executable file. This occurs right at the end of compilation and is performed by a linker.
First, the linker combines the program code with all required libraries. Once that’s complete, everything is compiled into one executable file. When the program is installed, all libraries required are loaded into memory.
That’s where the term “static” comes into play. Now that everything is shipped together, you need to perform this whole process again if any changes are made to the external libraries.
It sounds like a long process, but there are several benefits to using static linking.
- Static linking can simplify the process of distributing binaries to multiple environments or operating systems, as the program already has everything it needs to run.
- Static linking can result in a slightly faster start-up depending on the program’s complexity. This also results in less chance of compatibility issues.
But static linking has its downsides, too.
- Since you’re compiling and shipping all libraries in one executable file, the program can be much larger and use a lot of resources. That includes cache, RAM, and disk space.
- If any changes occur in external programs, they won’t automatically be reflected in your executable file. You’ll need to perform the whole compilation and linking process again.
Now, let’s discuss your other option: dynamic linking.
What is dynamic linking?
Dynamic linking is when external or shared libraries are copied into the executable file by name right at the point of run time. It’s only then that any required libraries are loaded to memory by the operating system.
During dynamic linking, the operating system locates the external libraries when the program is run. If any changes occur to the libraries now loaded to memory, the executable file does not need to be re-compiled and shipped as a new executable file.
Dynamic linking has a number of benefits.
- Dynamic linking leads to smaller file sizes. The code of linked libraries does not need to be shipped with the executable file. This means less resource usage such as disk space or RAM.
- If a shared library is already available in the operating system, the start-up time can be reduced.
- You can update routines in libraries without needing to relink, meaning bug fixes and other changes can be executed without any need to ship a new executable file.
- There are lower maintenance costs and a reduced need for support.
While it sounds more efficient overall, dynamic linking comes with its own set of risks.
- The removal of a library can cause the program to break. Or if any changes are made to a library, you might run into compatibility issues and rework the application as a result.
- If you have an inflexible dynamic linker, you could find the program no longer launches at all or doesn’t work correctly (also known as “DLL hell”).
Now that you know the pros and cons of each, let’s compare these two linking methods.
Static Versus Dynamic Linking
Essentially, static linking involves compiling libraries into your app or program as part of the build process. Dynamic linking lets the operating system hold off and load shared libraries into memory only when the app is launched.
Both of these linking processes are different in how they are built, shipped, and managed. But the difference between static and dynamic linking isn’t just about your preferences or user experience. You’ll need to choose based on individual use cases, including what you’re building and where you’ll be shipping it.
Sometimes, the decision to use one over the other might be taken out of your hands.
For example, you’ll always need to use dynamic linking for building plugins. Similarly, it can be the only practical way to meet requirements for free-software licenses such as LGPL.
Your compiler may be a limitation. Some compilers (such as the Google Go compiler commonly used to work with Google Cloud data sources) will only let you compile binaries statically.
But how do you choose when the decision is left up to you?
- If it comes down to performance, you might want to consider dynamic linking. If multiple programs are using the same shared libraries, dynamic linking can outperform a statically linked app.
- Consider whether your program makes a high volume of library calls or a lot of small calls to library routines. In that instance, statically linked programs may perform better.
Another consideration is the level and frequency of updates that you’re predicting. Shipping bug fixes and updates are far less efficient with statically linked programs. You would need to compile and ship the entire executable file again each time.
With dynamic linking, users will load the latest version of a program every time it's run because it will make a call to the latest version of the libraries. So you can make the changes required without needing to re-compile everything.
Working With Multiple Executables: Static or Dynamic Linking?
All of the above assumes that we’re working with one, neatly compiled executable. But what about extensions?
There are scenarios where static linking will be completely impractical, and this is one of them.
Let’s say you have a mobile application that contains the main app but uses extensions for specific functions. This can include extensions for things like push notifications, for example.
In this instance, the extensions probably only use a small number of the libraries used by the main app. However, the extensions likely share a lot of code with the main app.
If you were to statically link each executable file, you’d be duplicating code that’s common to all extensions and the main app. This leads to a huge amount of wasted space on a device and, in the case of extensions, the operating system may have strict limits for building this type of functionality using dynamic linking.
Combining Static and Dynamic Libraries
Static and dynamic linking can work in tandem in some ways. For example, you might end up in a scenario where you need a static library to form part of a dynamic library.
In that case, you’ll want to make sure you won’t end up with unresolved symbols when you run the executable file. This requires creating a dynamic library that contains all the symbols from a separate static library.
When creating the static library, make an option for the compiler to create position-independent code (PID) for each object within the static library. Making your status library objects PID ensures that they are relocatable just like a dynamic library (which is what the operating system will ultimately use to make calls).
Using Static and Dynamic Linking
Static and dynamic linking are two fundamentally different ways to compile and ship a program. Each has its own merits and benefits related to load time, overall performance, and ease of updating.
The method you choose depends entirely on your use case and where you’re deploying your app. Before you decide, carefully consider the implications of different operating systems, user experience, and your ability to quickly deploy patches and updates.