Let us imagine that the change to libcommon.cpp was something small and innocuous, maybe fixing a typo in an internal string constant that gets logged. In a small example like this, it isn’t too painful that we needed to relink so many things. But in a larger project it can definitely hurt. It feels wrong to do so much linking for such a little change. Especially in the dynamic build, a small change deep in the library dependency graph can lead to a long chain of transitive relinking, even when many of the libraries are completely unaltered. Can we do better?

With static linking, no, not really. That updated string constant needs to exist in both executables, so we really need to relink them so that the new string constant is extracted from libcommon.a .

With dynamic linking, it turns out that we can do better. The key observation is to consider what would happen if we rebuilt only libcommon.so , and intentionally didn’t relink the other dynamic libraries or executables (even though the build system thinks we should), and then tried to run the executables. Would they work, and work as expected?

For the case of our proposed private string constant modification in libcommon.cpp , the answer is a definite yes. Changing that internal string constant didn’t alter the Application Binary Interface (ABI) of libcommon.so in any way, and when the executables are run, the updated value of the string constant will be reflected in the output because the string constant wasn’t copied into the executables: it lives in the now replaced libcommon.so .

We got away with this because our change didn’t alter the ABI of libcommon.so . If we had made a change that altered its ABI, rebuilt libcommon.so , and then tried running the executables without relinking them, we would probably be looking at a very subtle runtime crash. No fun.

In theory then you could minimize relinking by individually naming targets to build when you knew that you had ABI affecting changes. But in practice that is clearly error prone and just a terrible idea. But if we had a tool that could tell us when the ABI of a library had changed, then we could teach our build system how to invoke this tool as it did its dependency walk, and automatically skip any unnecessary relinks in the case of ABI preserving modifications.