views:

1887

answers:

2

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.

+2  A: 

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 )

Kent Fredric
"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
+2  A: 
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.

Jonathan Leffler
It doesn't work :-( But thanks for the try.
Fernando Miguélez
You got the correct answer, though I had already done it by myself by means of "cut" command. Thanks.
Fernando Miguélez