I'm aware that shared objects under Linux use "so numbers", namely that different versions of a shared object are given different extensions, for example:

  • example.so.1
  • example.so.2

I understand the idea is to have two distinct files such that two versions of a library can exist on a system (as opposed to "DLL Hell" on Windows). I'd like to know how this works in practice? Often, I see that example.so is in fact a symbolic link to example.so.2 where .2 is the latest version. How then does an application depending on an older version of example.so identify it correctly? Are there any rules as to what numbers one must use? Or is this simply convention? Is it the case that, unlike in Windows where software binaries are transferred between systems, if a system has a newer version of a shared object it is linked to the older version automatically when compiling from source?

I suspect this is related to ldconfig but I'm not sure how.

4 Answers 4


Binaries themselves know which version of a shared library they depend on, and request it specifically. You can use ldd to show the dependencies; mine for ls are:

$ ldd /bin/ls
    linux-gate.so.1 =>  (0xb784e000)
    librt.so.1 => /lib/librt.so.1 (0xb782c000)
    libacl.so.1 => /lib/libacl.so.1 (0xb7824000)
    libc.so.6 => /lib/libc.so.6 (0xb76dc000)
    libpthread.so.0 => /lib/libpthread.so.0 (0xb76c3000)
    /lib/ld-linux.so.2 (0xb784f000)
    libattr.so.1 => /lib/libattr.so.1 (0xb76bd000)

As you can see, it points to e.g. libpthread.so.0, not just libpthread.so.

The reason for the symbolic link is for the linker. When you want to link against libpthread.so directly, you give gcc the flag -lpthread, and it adds on the lib prefix and .so suffix automatically. You can't tell it to add on the .so.0 suffix, so the symbolic link points to the newest version of the lib to faciliate that

  • The equal sign "=ls" should not be present. Just use "ldd ls" Sep 6, 2017 at 21:05
  • 1
    @bmacnaughton That will probably give you an error because ldd requires the complete path to the executable. =ls does that in zsh, but I changed it since not everyone uses that shell Sep 6, 2017 at 21:54
  • Interesting. I'm running bash on Ubuntu and it seems to work without the full path. Thanks for the explanation - I don't use zsh. Sep 6, 2017 at 22:40
  • 3
    " so the symbolic link points to the newest version of the lib to faciliate that" the reason for the symlink is to point to the .so.X file that matches the installed headers on the system. Not to point to the newest-version .so.X file. It often is the newest, but there are also often cases where it isn't (particularly during development.. outside of that, the symlink is useless anyway). Nov 12, 2019 at 17:59
  • 3
    " You can't tell it to add on the .so.0 suffix" <- Actually, you can tell it you want a certain version of the library; see this answer.
    – einpoklum
    Jul 21, 2020 at 8:19

The numbers in the shared libraries are convention used in Linux to identify the API of a library. Typically the format is:


And as you noticed usually there is a symbolic link from libFOO.so to libFOO.so.MAJOR.MINOR. ldconfig is responsible for updating this link to the newest version.

The MAJOR is typically incremented when the API changes (new entry points are removed or the parameters or types changed). The MINOR typically is incremented for bug fix releases or when new APIs are introduced without breaking existing APIs.

A more extensive discussion can be found here: Dissecting shared libraries

  • Hi Miguel, thanks for that, shame I can't accept two answers because that complements the above nicely. +1 from me, excellent link too, thanks again!
    – user119
    Aug 15, 2010 at 14:22
  • 4
    That is nearly correct, but it is actually libFOO.so.MAJOR.MINOR (so not at the end)
    – JonnyJD
    Mar 4, 2013 at 17:34
  • 26
    This answer is so wrong. First, the numbers you see have nothing to do with the API, these are purely ABI. Second, the convention here is not semantic versioning AT ALL like you answer suggest. Rather it's a libtool convention that has the nice property of mapping to a single library version number that ld.so can compare (see gnu.org/software/libtool/manual/html_node/… for more information)
    – NewbiZ
    Aug 15, 2018 at 9:06
  • ldconfig does not update the dev symlink. ldconfig only updates the symlink from libFOO.so.<part of the version that is included in the SONAME> to libFOO.so.<full version, often includes patchlevel> so that when starting binaries - which depend on SONAMES, not on full versions usually - they find the libraries by way of the ldconfig-created symlink. Jun 30, 2023 at 13:29

Shared libraries should be versioned according to the following scheme:



  • X = backwards incompatible ABI release
  • Y = backwards compatible ABI release
  • Z = Internal changes only - no change to the ABI

Typically you only see the first digit like hello.so.1 because the first digit is the only thing needed to identify the "version" of the library since all the other digits are backwards compatible.

ldconfig maintains a table of what shared libraries are available on a system and where the path to that library exists. You can verify this by running:

ldconfig -p

When a package is built for something like Red Hat, the shared libraries being called out in the binary will be looked up and added as dependencies of the package at RPM build time. Therefore, when you go to install the package, the installer will look up whether or not hello.so.1 is installed on the system by checking ldconfig.

You can see the dependencies of a package by doing something like:

rpm -qpR hello.rpm

This system (unlike Windows) allows for multiple versions of the hello.so to be installed on a system and be used by different applications at the same time.

  • 1
    I think this is the best answer.
    – Kemin Zhou
    Nov 19, 2017 at 1:04
  • 7
    Shared libraries should be versioned according to the following scheme (…) – Could you please provide reference for this statement? Mar 19, 2019 at 15:15
  • can you please give a source for that? I really like the answer, but without credible source I am having a hard time Dec 23, 2021 at 13:55

libNAME.so is the filename used by the compiler/linker when first looking for a library specified by -lNAME. Inside a shared library file is a field called the SONAME. This field is set when the library itself is first linked into a shared object (so) by the build process. This SONAME is actually what a linker stores in an executable depending on that shared object is linked with it. Normally the SONAME is in the form of libNAME.so.MAJOR and is changed anytime the library becomes incompatible with existing executables linked to it and both major versions of the library can be kept installed as needed (though only one will be pointed to for development as libNAME.so) Also, to support easily upgrading between minor versions of a library, libNAME.so.MAJOR is normally a link to a file like libNAME.so.MAJOR.MINOR. A new minor version can be installed and once completed, the link to the old minor version is bumped to point to the new minor version immediately upgrading all new executions to use the upgraded library. Also, see my answer to Linux, GNU GCC, ld, version scripts and the ELF binary format -- How does it work?

You must log in to answer this question.