How to build a shared library (.so) without hardcoded full dependency paths?

前端 未结 6 1575
面向向阳花
面向向阳花 2020-12-29 07:37

I need to build two 3rd party shared libraries, so their .so files will be reused by other projects. However, after build one of these libraries contains hardcoded path to a

相关标签:
6条回答
  • 2020-12-29 07:59

    When I run ldd libB.so it gives:

    libA.so.2 => /home/alex/dev/A-install/lib/libA.so.2

    The low-level solution to this problem is to use the option "-soname=libA.so" when you link the libA.so library. By having SONAME defined for a shared object, the linker will not embed absolute paths when linking against that shared object.

    The OP is using "configure", so this isn't an easy solution to implement unless he is willing to go into the bowels of the Makefile generated by the configure script.

    0 讨论(0)
  • 2020-12-29 08:05

    I just got caught out thinking I had the same problem. None of the above answers helped me. Whenever I tried

    ldd libB.so 
    

    I would get in the output:

    libA.so.1 => /home/me/localpath/lib/libA.so.1.0
    

    and so I thought I had a hardcoded path. Turns out that I had forgotten I had LD_LIBRARY_PATH set for local testing. Clearing LD_LIBRARY_PATH meant that ldd found the correct installed library in /usr/lib/

    0 讨论(0)
  • 2020-12-29 08:07
    -Wl,-rpath,~/deps/A/lib:~/deps/B/lib:~/dev/MyApp/bin
    

    This linker option is responsible for saving the path inside the library. You need somehow to remove this.

    See with ./configure --help if there's some option that could influence this. Another option is to edit manually the makefile and remove this option.

    == edit2 == One more thing

    -L~/deps/A/lib -L~/deps/B/lib ~/deps/A/lib/libA.so ~/deps/B/lib/libB.so
    

    If libA.so and libB.so don't have SONAME, linking them like "~/deps/A/lib/libA.so" will also cause saving the path. Soname is set using -Wl,-soname,<soname> linker option when building shared library.

    If soname is set in the shared library, linking it using "~/deps/A/lib/libA.so" form is ok.

    Like Jan mentioned in the comments, the better way is using "-Llibrary/path -llibrary_name" without rpath.

    -L~/deps/A/lib -L~/deps/B/lib -lA -lB
    
    0 讨论(0)
  • 2020-12-29 08:10

    Shared libraries and executables have a list of directories to look for shared libraries, in addition to the list in the operating system's configuration. RPATH is used to add shared library search paths, used at runtime. If you want a relative path to be used in RPATH, there is a special syntax that most Linux/UNIX (but not AIX) systems support - $ORIGIN or ${ORIGIN}.
    $ORIGIN will expand at runtime to the directory where the binary resides - either the library or executable.

    So if you put executable binaries in prefix/bin/ and shared libraries in prefix/lib/ you can add an entry to RPATH like ${ORIGIN}/../lib and this will expand at runtime to prefix/bin/../lib/

    It's often a little trick to get the syntax correct in a Makefile, because you have to escape the $ in ORIGIN so it will not be expanded. It's typical to do this in a Makefile:

     g++  -Wl,-rpath=\$${ORIGIN}/../lib
    

    Both Make and the shell will want to look in your environment for a variable called ORIGIN - so it needs to be double-escaped.

    0 讨论(0)
  • 2020-12-29 08:12

    You have to use --prefix value that will be valid in the runtime environment for both packages!

    Than you override prefix or DESTDIR (prefix replaces the prefix, DESTDIR is prepended to it, but works more reliably) on the make command-line when installing. Like:

    ~/dev/A$ ./configure
    ~/dev/A$ make 
    ~/dev/A$ make install prefix=~/dev/A-install
    ~/dev/B$ ./configure --with-A=~/dev/A-install
    ~/dev/B$ make
    ~/dev/B$ make install prefix=~/dev/B-install
    

    or (which is preferred and is how all package-building tools use it):

    ~/dev/A$ ./configure
    ~/dev/A$ make 
    ~/dev/A$ make install DESTDIR=~/dev/A-install
    ~/dev/B$ ./configure --with-A=~/dev/A-install/usr/local
    ~/dev/B$ make
    ~/dev/B$ make install prefix=~/dev/B-install
    

    because this way you are installing to ~/dev/A-install/$prefix, so with default prefix ~/dev/A-install/usr/local. The advantage of this later option is, that if you redefine some specific installation paths without refering to prefix (say --sysconfdir=/etc), DESTDIR will still get prepended to it, while it won't be affected by prefix.

    0 讨论(0)
  • 2020-12-29 08:15

    Perhaps using the -rpath and -soname options to ld could help (assuming a binutils or binutils.gold package for ld on a recent Linux system)?

    0 讨论(0)
提交回复
热议问题