What is the 'soname' option for building shared libraries for?
Asked Answered
T

5

73

I learned the "Program Library HOWTO". It mention that using soname to manage the version like follow.

gcc -shared -fPIC -Wl,-soname,libfoo.so.1  -o libfoo.so.1.0.0 foo.c
ln -s libfoo.so.1.0.0  libfoo.so.1
ln -s libfoo.so.1 libfoo.so

And I get the information that if the soname is not set. it will be equal to libfoo.so.1.0.0 ,see the answer from here.

And I find that it also can work without soname , like following

 gcc -shared -fPIC -o libfoo.so.1.0.0 foo.c
 ln -s libfoo.so.1.0.0  libfoo.so.1
 ln -s libfoo.so.1 libfoo.so

So I think that the only one useful point is that the soname option can tell you the version of the shared library when you use readelf -d libfoo.so command to check it.

What else can it do?

Terror answered 28/9, 2012 at 10:2 Comment(0)
L
73

soname is used to indicate what binary api compatibility your library support.

SONAME is used at compilation time by linker to determine from the library file what actual target library version. gcc -lNAME will seek for libNAME.so link or file then capture its SONAME that will certainly be more specific ( ex libnuke.so links to libnuke.so.0.1.4 that contains SONAME libnuke.so.0 ).

At run time it will link with this is then set into ELF dynamic section NEEDED, then a library with this name ( or a link to it ) should exists. At Run time SONAME is disregarded, so only the link or the file existence is enough.

Remark: SONAME is enforced only at link/build time and not at run time.

'SONAME' of library can be seen with 'objdump -p file |grep SONAME'. 'NEEDED' of binaries can be seen with 'objdump -p file |grep NEEDED'.

[EDIT] WARNING Following is a general remark, not the one deployed in linux. See at the end.

Let's assume you have a library with libnuke.so.1.2 name and you develop a new libnuke library :

  • if your new library is a fix from previous without api change, you should just keep same soname, increase the version of filename. ie file will be libnuke.so.1.2.1 but soname will still be libnuke.so.1.2.
  • if you have a new library that only added new function but didn't break functionality and is still compatible with previous you would like to use same soname than previous plus a new suffix like .1. ie file and soname will be libnuke.so.1.2.1. Any program linked with libnuke.1.2 will still work with that one. New programs linked with libnuke.1.2.1 will only work with that one ( until new subversion come like libnuke.1.2.1.1 ).
  • if your new library is not compatible with any libnuke : libnuke.so.2
  • if your new library is compatible with bare old version : libnuke.so.1.3 [ ie still compatible with libnuke.so.1 ]

[EDIT] to complete : linux case.

In linux real life SONAME as a specific form : lib[NAME][API-VERSION].so.[major-version] major-version is only one integer value that increase at each major library change. API-VERSION is empty by default

ex libnuke.so.0

Then real filename include minor versions and subversions ex : libnuke.so.0.1.5

I think that not providing a soname is a bad practice since renaming of file will change its behavior.

Lamarckian answered 30/1, 2013 at 20:56 Comment(7)
Philippe, according to David A. Wheeler (bit.ly/1CkQJmR), the soname has a single version number, like libnuke.so.1 or libnuke.so.4. Do you know if a second version number can indeed be part of the soname, like libnuke.so.1.2?Imco
Well, sonmae with multiple digit exist, by example for openssl library : SONAME:libssl.so.0.9.8, but you are right it is more general than "Program Library HOWTO" that is debian that seems more restrictive indeedLamarckian
You seem to be describing that the filename and soname should be set differently but you don't describe how the soname should be set in the later cases.Elk
@Gabriel I will update (later) my answer that in fact is just too general and in fact wrong for most linux cases (too bad, no other answer came ).Lamarckian
Could someone knowledgeable on the issue update this answer if they find the time?Lammastide
You can have file libx.so with SONAME libx.so.1 compile and link just fine until you run it on Android, which always expects filenames to end in .so and will fail to load the lib if the SONAME is versioned. If it's an open-source lib you can tinker with the build files, otherwise rpl may be your only option.Unclose
The ELF standard's SONAME and NEEDED tags were defined at Linker and Libraries Guide, ch6 and the guidelines for "External Versioning" are given in ch 5.5, should you need a reference.Chapter
M
8

You created a dynamic library named libx.1.0.0 in naming tradition libname.{a}.{b}.{c}

{a} stand for primary version, should changes when APIs changes(which making things incompatible).
{b} stand for sub version, should changes by adding APIs.
{c} stand for mirror version, should changes by bug fixing or optimizing

Now you are releasing libx.1.2.0, and you need to declare that libx.1.2.0 is compatible with libx.1.0.0 since just adding functions and people's executable would not crashes, just link it like in the old time by:

Setting libx.1.0.0 and libx.1.2.0 to have the same soname, for example libx.1

This's what soname does.

Midyear answered 15/3, 2019 at 18:4 Comment(1)
But one still need to manually create a symbolic link right? Is it correct to say that soname is a symlink name?Industrious
C
5

Here is an example supporting Johann Klasek's answer.

In short, SONAME is needed at run time. At compilation time, only a linker name or real name is needed (e.g. g++ main.cpp -L. -ladd or g++ main.cpp -L. -l:libadd.so.1.1). The definitons of linker name and real name follow Program Library HOWTO: 3. Shared Libraries.

Source tree:

├── add.cpp
├── add.h
├── main.cpp
└── Makefile

Makefile:

SOURCE_FILE=add.cpp
# main.cpp includes `add.h`, whose implementation is `add.cpp`
MAIN_FILE=main.cpp
SONAME=libadd.so.1
REAL_NAME=libadd.so.1.1
LINKER_NAME=libadd.so
OUTPUT_FILE=a.out

all:
   g++ -shared -fPIC -Wl,-soname,${SONAME} -o ${REAL_NAME} ${SOURCE_FILE}
   ln -s ${REAL_NAME} ${LINKER_NAME}
   g++ main.cpp -I. -L. -ladd -o ${OUTPUT_FILE} 
   # Same as `ldconfig -n .`, creates a symbolic link
   ln -s ${REAL_NAME} ${SONAME}
   #./a.out: error while loading shared libraries: libadd.so.1: cannot open 
   # shared object file: No such file or directory
   LD_LIBRARY_PATH=. ./${OUTPUT_FILE}
clean:
   rm ${SONAME} ${REAL_NAME} ${LINKER_NAME} ${OUTPUT_FILE}
Cumulus answered 28/7, 2018 at 14:4 Comment(1)
Apparently, this answer is different from the accepted answer, at when 'SONAME' taking effect, runtime or compiling.Megillah
P
3

Let's assume libA.so depends on libB.so, and they all in a directory(of course the directory cannot be found by dynamic linker). If you didn't set soname then dlopen doesn't work:

auto pB = dlopen("./libB.so", RTLD_LAZY | RTLD_GLOBAL);
auto pA = dlopen("./libA.so", RTLD_LAZY | RTLD_GLOBAL);

Because runtime linker cannot find libB.so, so pA is set to NULL.

In this case soname will save you from hell...

Perreira answered 15/8, 2016 at 7:27 Comment(0)
B
1

Another aspect: At least on Linux the SONAME entry provides a hint for the runtime-linker system on how to create appropriate links in /lib, /lib64 etc. Running the command ldconfig tries to create a symbolic link named with SONAME which is also taken into the run-time linker cache. The newest one of the libraries tagging the same SONAME wins the link-race. If some software relies on the specific SONAME and you want to renew a library you have to provide this SONAME to get ldconfig stick on this new library (if ldconfig is used to rebuild the cache and the links). E.g. libssl.so.6 and libcrypto.so.6 are such cases.

Bochum answered 14/3, 2016 at 15:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.