[CMake] CMAKE uses wrong symlink to so

Michael Hertling mhertling at online.de
Fri Dec 31 08:48:21 EST 2010


On 12/31/2010 11:56 AM, Michael Wild wrote:
> On 12/30/2010 07:55 PM, j s wrote:
>> Hello Michael Wild,
>>
>> I regret deciding to go with an Python parser for my application.  I use
>> such a small subset of the API, I was hoping to be able to rerelease my app
>> everytime it changes.
>>
>> Apparently Python 2.6 is frozen.
>>
>> In the future, the Python people are hoping to stabilize the ABI in the 3
>> series so that I can just link against a libpython3.so:
>> http://www.python.org/dev/peps/pep-0384/
>>
>> As stated by Michael Hertling, the symlinks are not being recursively
>> resolved.  The soname is encoded into the so, so the linker chooses to
>> ignore the original filename.
>>
>> Regards,
>>
>> Juan
>>
>> On Thu, Dec 30, 2010 at 6:23 AM, Michael Wild <themiwi at gmail.com> wrote:
>>
>>> On 12/30/2010 12:28 AM, j s wrote:
>>>> I specified the full name to an so in CMAKE 2.8.1.  Unfortunately it
>>> links
>>>> against the versioned so name,
>>>> libpython2.6.so.1.0
>>>>
>>>> instead of the exact name I specified.
>>>> /usr/lib/libpython2.6.so
>>>>
>>>> SET (PYTHON_ARCHIVE /usr/lib/libpython2.6.so)
>>>> TARGET_LINK_LIBRARIES (myapp  parser engine ${PYTHON_ARCHIVE}
>>>> ${OPENSSL_ARCHIVE})
>>>>
>>>> Is there any way to tell cmake to do the right thing in Linux?  For some
>>>> strange reason using -l on the link line, and doesn't even use the
>>>> corresponding -L to the path I specify.
>>>>   -lpython2.6
>>>>
>>>>
>>>> Regards,
>>>>
>>>> Juan
>>>
>>> There's nothing CMake can do about this, this is the linker getting in
>>> your way. E.g. on my Ubuntu, /usr/lib/libpython2.6.so is a symlink to
>>> /usr/lib/libpython2.6.so.1 which itself is a symlink to
>>> /usr/lib/libpython2.6.so.1.0. The linker recursively resolves all
>>> symlinks during the linking, and CMake can't do anything about it. You
>>> could pass the full path to the /usr/lib/libpython2.6.so symlink instead
>>> of -lpython2.6 and you would still get the same result.
>>>
>>> Actually, this is considered to be a feature. This way, newly compiled
>>> programs will always link against the "current" version (the one pointed
>>> to by the symlink-chain), while old programs can still use  older
>>> versions of the library without requiring to be recompiled.
>>>
>>> Michael
> 
> 
> Huh?
> 
> $ echo "int main(){}" | gcc -x c -c -o test.o -
> $ gcc test.o /usr/lib/libpython2.6.so
> $ ldd a.out | grep libpython2.6
> libpython2.6.so.1.0 => /usr/lib/libpython2.6.so.1.0 (0x00007fbb350f1000)
> 
> $ ls -l /usr/lib/libpython2.6.so*
> ... /usr/lib/libpython2.6.so -> libpython2.6.so.1
> ... /usr/lib/libpython2.6.so.1 -> libpython2.6.so.1.0
> ... /usr/lib/libpython2.6.so.1.0
> 
> Sure looks like recursive symlink resolution to me...

No, it's the soname that gets incorporated in the resulting binary;
recursively resolving the symlinks is insignificant in this regard:

echo "void f(void){}" > f.c
echo "void g(void){}" > g.c
gcc -o libf.so -shared -fPIC -Wl,-soname,xyz f.c
gcc -o libg.so.1.0 -shared -fPIC g.c
ln -sf libg.so.1.0 libg.so.1
ln -sf libg.so.1 libg.so
ls -l libg.so*
... libg.so -> libg.so.1
... libg.so.1 -> libg.so.1.0
... libg.so.1.0

echo "int main(void){return 0;}" > main.c
gcc -o main main.c libf.so libg.so
LD_LIBRARY_PATH=. ldd main
...
        xyz => not found
        libg.so => ./libg.so (0xb7fbd000)
...

A recursive symlink resolution would make the main executable being
linked against libg.so.1.0 instead of libg.so. In fact, main is linked
against the library specified by the soname - if present - even if that
library doesn't exist at all like xyz in the example above. If there is
no soname the linker incorporates the library as denoted on the command
line. With libpython2.6, the executable is linked against .so.1.0 since
this is the library's soname, but not due to the .so-->so.1-->.so.1.0
symlink resolution. BTW, the soname denoting the non-existing xyz is
completely artificial, of course, and designed only to clarify the
concern. Usually, ldconfig ensures that there is a valid symlink
soname --> actual library file.

Regards,

Michael


More information about the CMake mailing list