Search code examples
linkerldnode-gyp

why does the linker change shared library name?


Using linker command line options passed via 'node-gyp' I specify that the library path and library name that I want the program to link with. But the resulting executable does not reference the file I specified, it references a different name in /usr/lib.

I'm using the libraries section in binding.gyp to reference a local lib directory.

      'libraries': [
        '-lao-oboe',
        '-L<(module_root_dir)/lib/',
        '-Wl,-rpath-link,<(module_root_dir)/lib/',
        '-Wl,-rpath,<(module_root_dir)/lib/'
      ],

node-gyp seems to be passing the options correctly because the linker returns /usr/bin/ld: cannot find -la-oboe if I change the -L path to one that doesn't contain libao-oboe.so. The linker also returns an error if I change the name of the requested library to be different than the one in lib.

The problem is that the local library will not be loaded at runtime. ldd shows that the node-gyp output file is not referencing the file that was specified - it is referencing a library with a different name altogether - /usr/lib/liboboe-1.0.so.1. See the second line of ldd output:

linux-vdso.so.1 =>  (0x00007ffee20f5000)
liboboe-1.0.so.1 => /usr/lib/liboboe-1.0.so.1 (0x00007fa476377000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fa475ff5000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa475c2b000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa475a27000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa47580a000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa475501000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa476922000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fa4752eb000)

The local library directory contains:

lrwxrwxrwx  1 bruce bruce      15 Sep  8 02:50 libao-oboe.so -> libao-oboe.so.1`  
-rw-r--r--  2 bruce bruce 1640848 Aug 31 15:01 libao-oboe.so.1

It is the case that the local library file, libao-oboe.so.1 is the same as the system library file being referenced in the executable (as shown by ldd): /usr/lib/liboboe-1.0.so.1.

Does the linker somehow notice that the local file is the same (via hashing or some signature) and substituting the library file from the standard location?

Why does node-gyp's output file reference a library file that was never requested as part of the build process?


Solution

  • According to wikipedia - soname the SONAME field in the .so file is the "base compatible version". It's clear from the behavior I found in the problem above that ld inserts the SONAME into the file being linked to the shared library - not the filename specified in the ld command.

    Renaming a .so file doesn't change the SONAME so an executable linked to a renamed file will try to load a library named by the SONAME field, not the filename.

    My solution was to not rename the file.