Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
559 views
in Technique[技术] by (71.8m points)

macos - clang, change dependent shared library install name at link time

Related, but do not answer the question:

On OSX, I have a dynamic library provided by a packager manager, installed in a non standard directory, which install_name is just the filename. For example:

$ ROOT=$PWD
$ mkdir $ROOT/foo 
$ cd $ROOT/foo
$ echo 'int foo(int a, int b){return a+b;}' > foo.c
$ clang foo.c -dynamiclib -install_name libfoo.dylib -o libfoo.dylib

I don't want to change (absolute path, @RPATH, ...) the install_name of libfoo.dylib using install_name_tool -id.

Now I link a program with the library, for example:

$ mkdir $ROOT/bar
$ cd $ROOT/bar
$ echo 'int foo(int,int); int main(){return foo(2,4);}' > main.c
$ clang main.c -L../foo -lfoo   

The program can't run:

$ ./a.out
dyld: Library not loaded: libfoo.dylib
  Referenced from: $ROOT/bar/./a.out
  Reason: image not found
Trace/BPT trap: 5

because:

$ otool -L ./a.out
./a.out:
        libfoo.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)

I can change the path of the dependant library:

$ install_name_tool -change libfoo.dylib ../foo/libfoo.dylib a.out

so:

$ otool -L ./a.out
./a.out:
        ../foo/libfoo.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)

and the program can execute:

$ ./a.out
$ echo $?
6

Is there a clang option I can add to the command:

$ clang main.c -L../foo -lfoo 

to avoid having to run:

$ install_name_tool -change libfoo.dylib ../foo/libfoo.dylib a.out

Note: I don't want to modify DYLD_LIBRARY_PATH or such other environment variable.

?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I've been hitting my head against this for some time and think I have finally figured out how to do this without using install_name_tool, at least for Mac OS 10.9 and later (as far as I've tested).

While you may have already figured this out, I'm posting it here in case anyone else needs it.

Basically you have two options:

  1. You can do it when you compile the library, defining its install_name in terms of @executable_path
ROOT=$PWD
mkdir $ROOT/foo
mkdir $ROOT/bar

cd $ROOT/foo
echo 'int foo(int a, int b){return a+b;}' > foo.c
clang foo.c -dynamiclib -install_name @executable_path/../foo/libfoo.dylib -o libfoo.dylib

cd $ROOT/bar
echo 'int foo(int,int); int main(){return foo(2,4);}' > main.c
clang main.c -L../foo -lfoo -o main

./main
echo $?
# output is '6'
  1. Or you can do it in two steps using @rpath, which you then set when you compile the executable:
ROOT=$PWD
mkdir $ROOT/foo
mkdir $ROOT/bar

cd $ROOT/foo
echo 'int foo(int a, int b){return a+b;}' > foo.c
clang foo.c -dynamiclib -install_name @rpath/libfoo.dylib -o libfoo.dylib

cd $ROOT/bar
echo 'int foo(int,int); int main(){return foo(2,4);}' > main.c
clang main.c -L../foo -lfoo -rpath @executable_path/../foo/ -o main

./main
echo $?
# output is '6'

The end result will be the same in both cases:

bar $ otool -L main
main:
  @executable_path/../foo/libfoo.dylib (compatibility version 0.0.0, current version 0.0.0)
  /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)

The second one is probably preferable, since then you can compile the library once, and have any executable that uses it define where it will load it from using its own rpath.

Please check here for detailed explanations of @executable_path, @rpath and @load_path (which I did not use here).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...