一、背景介紹
公司開發的一個底層庫被用在了Mac平台的多個產品中。在開發這個底層庫的初期,對於Mac OSX下的Install name 並沒有過多的了解。對於XCode中的install name項也沒有進行過多的配置,於是生成動態庫文件在應用到各個產品中時都要修改install name才能用。后來在使用到CUDA庫時,偶然發現了@rpath這個東西在CUDA動態庫中被廣泛使用。於是就好好研究了下@rpath的一些應用場景。
二、@executable_path、@loader_path、@rpath的對比
(1)@executable_path。這個path很少用,本質上就是可執行程序的路徑。在動態庫中基本上不使用這個path.
(2) @loader_path。這個path在之前的應用中用的非常多,可以通過這個path來設置動態庫的install path name。但是它有自己的局限性,就是當一個動態庫同時被多個程序引用時,如果位置不一樣的話仍然需要手動修改。這個在參考鏈接中有說明。

(3) @rpath。這個就是今天要介紹的重點,它是run path的縮寫。本質上它不是一個明確的path,甚至可以說它不是一個path。它只是一個變量,或者叫占位符。這個變量通過XCode中的run path選項設置值,或者通過install_name_tool的-add_rpath設置值。設置好run path之后,所有的@rpath都會被替換掉。此外,run path是可以設置多個值的,這樣看來就和Windows下的PATH變量差不多了。run path指定的多個值就可可以完美解決掉參考鏈接中說的問題了。
三、使用方法
(1)在XCode中設置
在編譯動態鏈接庫文件(*.dylib)時,應當將install name設置為@rpath/library.dylib。

這樣編譯出來的*.dylib文件的install name如下:

在其他程序中使用這個動態庫時,需要設置好run path。打開XCode的Build Settings,直接搜索"runpath":

這里的runpath是可以設置多個值的,其作用如前述所說。這樣就可以徹底替代前面的設置path的方式,擺脫對具體路徑的依賴。用這種方式生成的動態庫也具備較好的適應性,在多種應用場景下也能自如使用。
(2)命令行中設置
如果不打算在XCode中使用,而是使用Makefile來組織工程的,那么使用install_tool_name也是可以的。在編譯鏈接動態庫鏈接庫時,注意添加如下選項:
$(CC) -dynamiclib -o $@ $+ $(LIBRARIES) $(CFLAGS) -framework opencl -install_name @rpath/libinsvmedia.dylib
這樣也能在鏈接階段對動態鏈接庫的install name進行修改。不過在其他程序引用這個動態鏈接庫時,相應的也要使用install_tool_name來添加runpath了。
install_name_tool [-change old new] ... [-rpath old new] ... [-add_rpath new] ... [-delete_rpath old] ... [-id name] input
(3)從比較@executable_path, @loader_path, @rpath來看,@rpath是最具靈活性的,也是Apple官方最推崇的方式。
