Bash script to create symbolic links to shared libraries

27,980

Solution 1

for baselib in "$@"
do
     shortlib=$baselib
     while extn=$(echo $shortlib | sed 's/\.[0-9][0-9]*$//')
           [ -n "$extn" ]
     do
         shortlib=$(basename $shortlib $extn)
         ln -s $baselib $shortlib
     done
done

I've cheated - all the links go to the base library (libmythings.so.1.1); if you really want to chain, then you need:

for baselib in "$@"
do
     shortlib=$baselib
     while extn=$(echo $shortlib | sed 's/\.[0-9][0-9]*$//')
           [ -n "$extn" ]
     do
         shorterlib=$(basename $shortlib $extn)
         ln -s $shortlib $shorterlib
         shortlib=$shorterlib
     done
done           

Beware - untested code.


Hubris precedes nemesis.

Comment arrived that the code above doesn't work - and the comment is correct. A fixed version with test in situ is:

set -- libname.so.5.1.1

for baselib in "$@"
do
    shortlib=$baselib
    while extn=$(echo $shortlib | sed -n '/\.[0-9][0-9]*$/s/.*\(\.[0-9][0-9]*\)$/\1/p')
          [ -n "$extn" ]
    do
        shortlib=$(basename $shortlib $extn)
        echo ln -s $baselib $shortlib
    done
done

The change is in the sed command. This version doesn't print anything by default (-n), matches only lines ending with a dot followed by digits, and then deletes everything except that suffix, and prints what remains for assignment to extn. As amended, the script generates the output below. Remove the echo to get it to execute the link commands.

ln -s libname.so.5.1.1 libname.so.5.1
ln -s libname.so.5.1.1 libname.so.5
ln -s libname.so.5.1.1 libname.so

The script illustrates an interesting and often overlooked point about shell scripts: the sequence of operations in the condition block of a while need not be a single command. The status of the line with the edit operation doesn't affect whether the test as a whole succeeds; the exit status of the last command, the '[ -n "$extn" ]', controls whether the loop continues.

Solution 2

I believe ldconfig is the standard tool that does this.

I recall somewhere it can generate symlinks based on internal version info, but can't find the source right now.

EDIT Yes, if you run

ldconfig -v 

You'll see it generating all the links based on library internals.

ldconfig /path/to/dir 

Will only create links for files in that dir

A note though, I played with it and it doesn't seem to consistently create .so$, just .so.{major}

I'm not sure how its internals work, but I do know:

lib # rm libmagic.so
lib # rm libmagic.so.1
lib # ldconfig 
lib # file libmagic.so.1   
libmagic.so.1: symbolic link to `libmagic.so.1.0.0'
lib # file libmagic.so 
libmagic.so: cannot open `libmagic.so' (No such file or directory)

So what determines how this works is a mystery to me

Edit Upon Further Discetion, .la files have no influence on behaviour.

The "SO" name field indicates what the symlink will be called.

And there will only be one.

0x000000000000000e (SONAME) Library soname: [libmagix.so ]

This is after hacking the code and replacing the ".1" with spaces.

ldconfig generated "libmagic.so " ( yes, spaces included )

Solution 3

Derived from the script from Jonathan Leffler (I've added this as a script called 'liblinks' in my ~/bin )

#!/bin/bash
# liblinks - generate symbolic links 
# given libx.so.0.0.0 this would generate links for libx.so.0.0, libx.so.0, libx.so
#

# By adding sudo to the ls command, we get permission to do the linking (or get an empty list)
LIBFILES=`sudo ls lib*.so.*`
for FILE in $LIBFILES;
   do
   echo $FILE
    shortlib=$FILE
    basename=$FILE
    while extn=$(echo $shortlib | sed -n '/\.[0-9][0-9]*$/s/.*\(\.[0-9][0-9]*\)$/\1/p')
          [ -n "$extn" ]
    do
        shortlib=$(basename $shortlib $extn)
        sudo ln -fs $basename $shortlib
        basename=$shortlib
    done

   done
Share:
27,980
Fernando Miguélez
Author by

Fernando Miguélez

Updated on April 01, 2021

Comments

  • Fernando Miguélez
    Fernando Miguélez about 3 years

    I think this question is rather easy for you shell scripting monsters.

    I am looking for the most elegant and shortest way to create symbolic links to shared libraries for Unix by means of a bash shell script.

    What I need is starting out with a list of shared library files such as "libmythings.so.1.1, libotherthings.so.5.11", get the symbolic links created such as:

    libmythings.so -> libmythings.so.1 -> libmythings.so.1.1
    libotherthings.so -> libotherthings.so.5 -> libotherthings.so.5.11
    

    The library files are inside a directory which contains other files such as other shell scripts.

    EDIT: Well, "ldconfig -nN ." could work OK, but I also need the link without the major number of the library appended after ".so", at least one of the libraries, since one or more libraries are the entry points of JNI calls from Java, so when a library is instanced by means of System.loadlibrary("libraryname") it expects a library called "libraryname.so", not "libraryname.so.X".

    The solution with just ldconfig -nN could work if there were a workaround for the Java part.

  • Fernando Miguélez
    Fernando Miguélez over 15 years
    "ldconfig -nN ." just works great for current directory, but it only creates up to major version of the library (libmylib.1 -> libmylib.1.10).
  • Fernando Miguélez
    Fernando Miguélez over 15 years
    You got the correct answer, though I had already done it by myself by means of "cut" command. Thanks.