Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I add rpath with $ORIGIN, @loader_path and @executable_path? #5827

Closed
waruqi opened this issue Jul 9, 2020 · 9 comments
Closed

How can I add rpath with $ORIGIN, @loader_path and @executable_path? #5827

waruqi opened this issue Jul 9, 2020 · 9 comments

Comments

@waruqi
Copy link

waruqi commented Jul 9, 2020

I need add rpath with $ORIGIN for elf, @loader_path and @executable_path for macho.

But zig build-exe -rpath $ORIGIN/@loader_path does not work.

@daurnimator
Copy link
Contributor

But zig build-exe -rpath $ORIGIN/@loader_path does not work.

Before investigating further, I assume you quoted $ORIGIN correctly for your shell?

@waruqi
Copy link
Author

waruqi commented Jul 9, 2020

I am not executing zig in the shell. I run the zig command directly through posix_spawnp().

for g++, like this. -Wl,-rpath=$ORIGIN it works.

/usr/bin/g++ -o build/linux/x86_64/release/test build/.objs/test/linux/x86_64/release/src/test.c.o -Lbuild/linux/x86_64/release -Wl,-rpath=$ORIGIN -s -L/usr/local/lib -L/usr/lib -lshared_library_c -m64

for zig, use -rpath $ORIGIN?

/usr/bin/zig build-exe -Lbuild/linux/x86_64/release -rpath $ORIGIN --strip -L/usr/local/lib -L/usr/lib -ltestlib -target x86_64-linux-gnu --output-dir build/linux/x86_64/release --name test --object build/.objs/test/linux/x86_64/release/src/main.zig.o

@daurnimator
Copy link
Contributor

What do readelf --dynamic ./your/executable and readelf -l ./your/executable say?

@waruqi
Copy link
Author

waruqi commented Jul 9, 2020

By default, the version will be appended to the so library file, causing the link to fail. e.g. libtestlib.so.0.0.0

I rename libtestlib.so.0.0.0 to libtestlib.so first and do link.

/usr/bin/zig build-exe -Lbuild/linux/x86_64/release -rpath '$ORIGIN' --strip -L/usr/local/lib -L/usr/lib -ltestlib -target x86_64-linux-gnu --output-dir build/linux/x86_64/release --name test --object build/.objs/test/linux/x86_64/release/src/main.zig.o

build/linux/x86_64/release/test executable project will be generated, but run failed.

$ ./build/linux/x86_64/release/test 
Segmentation fault

It will load libtestlib.so.0 not libtestlib.so/libtestlib.so.0.0.0

And -rpath $ORIGIN not works too.

$ ldd ./build/linux/x86_64/release/test 
	linux-vdso.so.1 =>  (0x00007ffd53bfe000)
	libtestlib.so.0 => not found
$ readelf --dynamic ./build/linux/x86_64/release/test 

Dynamic section at offset 0x2910 contains 14 entries:
  Tag        Type                         Name/Value
 0x000000000000001d (RUNPATH)            Library runpath: [$ORIGIN]
 0x0000000000000001 (NEEDED)             Shared library: [libtestlib.so.0]
 0x0000000000000015 (DEBUG)              0x0
 0x0000000000000017 (JMPREL)             0x200288
 0x0000000000000002 (PLTRELSZ)           24 (bytes)
 0x0000000000000003 (PLTGOT)             0x2059f0
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000006 (SYMTAB)             0x200200
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000005 (STRTAB)             0x200264
 0x000000000000000a (STRSZ)              29 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x200230
 0x0000000000000004 (HASH)               0x20024c
 0x0000000000000000 (NULL)               0x0

@waruqi
Copy link
Author

waruqi commented Jul 9, 2020

I saw 0x000000000000001d (RUNPATH) Library runpath: [$ORIGIN]. It exists.

Maybe it's just the library file name problem.

@andrewrk
Copy link
Member

andrewrk commented Oct 4, 2020

I don't think linux supports these things. Are they darwin-isms?

@andrewrk andrewrk added this to the 0.8.0 milestone Oct 4, 2020
@waruqi
Copy link
Author

waruqi commented Oct 4, 2020

-rpath '$ORIGIN' works fine. but -ltestlib will load libtestlib.so.0 not libtestlib.so/libtestlib.so.0.0.0

$ ldd ./build/linux/x86_64/release/test 
	linux-vdso.so.1 =>  (0x00007ffd53bfe000)
	libtestlib.so.0 => not found

I think that -ltestlibshould load libtestlib.so instead of libtestlib.so.0

@codehz
Copy link
Contributor

codehz commented Oct 4, 2020

I don't think linux supports these things. Are they darwin-isms?

glibc's ld-linux (man ld-linux)

   Dynamic string tokens
       In several places, the dynamic linker expands dynamic string tokens:

       o  In the environment variables LD_LIBRARY_PATH, LD_PRELOAD, and
          LD_AUDIT,

       o  inside the values of the dynamic section tags DT_NEEDED, DT_RPATH,
          DT_RUNPATH, DT_AUDIT, and DT_DEPAUDIT of ELF binaries,

       o  in the arguments to the ld.so command line options --audit,
          --library-path, and --preload (see below), and

       o  in the filename arguments to the dlopen(3) and dlmopen(3)
          functions.

       The substituted tokens are as follows:
       $ORIGIN (or equivalently ${ORIGIN})
              This expands to the directory containing the program or shared
              object.  Thus, an application located in somedir/app could be
              compiled with
                  gcc -Wl,-rpath,'$ORIGIN/../lib'
              so that it finds an associated shared object in somedir/lib no
              matter where somedir is located in the directory hierarchy.
              This facilitates the creation of "turn-key" applications that
              do not need to be installed into special directories, but can
              instead be unpacked into any directory and still find their
              own shared objects.
       $LIB (or equivalently ${LIB})
              This expands to lib or lib64 depending on the architecture
              (e.g., on x86-64, it expands to lib64 and on x86-32, it
              expands to lib).
       $PLATFORM (or equivalently ${PLATFORM})
              This expands to a string corresponding to the processor type
              of the host system (e.g., "x86_64").  On some architectures,
              the Linux kernel doesn't provide a platform string to the
              dynamic linker.  The value of this string is taken from the
              AT_PLATFORM value in the auxiliary vector (see getauxval(3)).

@andrewrk andrewrk modified the milestones: 0.8.0, 0.9.0 Nov 6, 2020
@andrewrk andrewrk modified the milestones: 0.9.0, 0.10.0 May 19, 2021
@mikdusan
Copy link
Member

mikdusan commented Jan 1, 2023

zig sends -rpath properly to the underlying linker and is effective on both linux and macos platforms.

I rename libtestlib.so.0.0.0 to libtestlib.so first and do link.

Not a bug. .so are encoded with a name for forward compatibility purposes. The idea is at build time you find the library through any means, then the linker reads the elf format and finds SONAME and encodes that SONAME into the executable. So if SONAME has libfoo.so.1 then that is linked in. You can even have a totally different name at build time and the executable will still use the encoded SONAME. MacOS does something similar, as do other OS's.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants