Mac dylib動態(tài)庫加載路徑問題(以OpenCV為例)

在自己的Mac上寫了一個基于OpenCV的簡單程序;需要傳給其他人共同調試,但是可執(zhí)行文件在他人的Mac上無法運行;執(zhí)行時會提示:

dyld: Library not loaded: /usr/local/Cellar/opencv/2.4.12/lib/libopencv_features2d.2.4.dylib

這樣就引申出來一個問題:在xcode下編譯出的程序,在開發(fā)機器上運行是沒有問題的。但是給其他用戶用,就可能出問題。因為用戶不一定有這個庫。
有兩種方法可以解決這個問題;一是給其他用戶也安裝依賴的庫文件;二是將所有的dylib隨行發(fā)布,消除依賴。
第一種方案不考慮,大部分時候這樣做并不現實;下面說說如何隨行發(fā)布dylib。

單純將依賴的dylib文件拷貝到可執(zhí)行文件目錄下一同傳輸過去是不能消除依賴的;執(zhí)行的時候還是報錯;
在編譯一個動態(tài)庫的時候, 你需要指定 INSTALL_PATH. 也就是它的安裝路徑;編譯完成后如果一個可執(zhí)行程序使用了該動態(tài)庫, 那么在編譯可執(zhí)行程序的時候, 動態(tài)庫的 INSTALL_PATH 會被記錄到可執(zhí)行程序中, 用來定位這個動態(tài)庫。

因此我們首先需要將用到的dylib文件都拷貝到可執(zhí)行文件目錄下,然后改變動態(tài)庫的INSTALL_PATH;將其改到可執(zhí)行文件所在目錄;
需要注意的是:如果依賴多個動態(tài)庫,用到的動態(tài)庫已會依賴其他動態(tài)庫,因此用到的所有的動態(tài)庫的依賴動態(tài)庫路徑都需要修改。

以OpenCV為例子,假設最終編譯出來的可執(zhí)行文件為 macimgproc;執(zhí)行命令:otool -L macimgproc可看到如下的輸出:

macimgproc:
    /usr/local/opt/opencv/lib/libopencv_calib3d.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    /usr/local/opt/opencv/lib/libopencv_contrib.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    /usr/local/opt/opencv/lib/libopencv_core.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    /usr/local/opt/opencv/lib/libopencv_features2d.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    /usr/local/opt/opencv/lib/libopencv_flann.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    /usr/local/opt/opencv/lib/libopencv_gpu.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    /usr/local/opt/opencv/lib/libopencv_highgui.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    /usr/local/opt/opencv/lib/libopencv_imgproc.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    /usr/local/opt/opencv/lib/libopencv_legacy.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    /usr/local/opt/opencv/lib/libopencv_ml.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    /usr/local/opt/opencv/lib/libopencv_nonfree.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    /usr/local/opt/opencv/lib/libopencv_objdetect.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    /usr/local/opt/opencv/lib/libopencv_ocl.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    /usr/local/opt/opencv/lib/libopencv_photo.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    /usr/local/opt/opencv/lib/libopencv_stitching.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    /usr/local/opt/opencv/lib/libopencv_superres.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    /usr/local/opt/opencv/lib/libopencv_video.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    /usr/local/opt/opencv/lib/libopencv_videostab.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 307.4.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1238.0.0)

說明macimgproc依賴所有的OpenCV動態(tài)庫文件;因此首先需要將所有動態(tài)庫文件拷貝到macimgproc所在目錄,然后需要將macimgproc文件中的所有/usr/local/opt/opencv/lib/libopencv_xxx修改為@executable_path/libopencv_xxx;

@executable_path表示可執(zhí)行文件所在目錄;指示所有OpenCV動態(tài)庫從可執(zhí)行文件所在目錄查找;
更多@executable_path的介紹以及其他變量參見文章 @rpath, @loader_path, @executable_path
使用命令install_name_tool -change {old.dylib} {new.dylib} {filename}修改動態(tài)庫的INSTALL_PATH,例如:

install_name_tool -change /usr/local/Cellar/opencv/2.4.12/lib/libopencv_flann.2.4.dylib @executable_path/libopencv_flann.2.4.dylib macimgproc

執(zhí)行后重新otool -L macimgproc可看到如下的輸出:

macimgproc:
    ...
    /usr/local/opt/opencv/lib/libopencv_features2d.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    @executable_path/libopencv_flann.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    /usr/local/opt/opencv/lib/libopencv_gpu.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
    ...

依次修改所有依賴即可。

整個OpenCV庫大概有19個dylib文件,因此寫了一個簡單的批量修改腳本:

#!/usr/bin/ruby

Preview=0

def fix_opencv_lib_link(file,rlib)
    if(rlib.include?('libopencv'))
        name = rlib.split('/').last
        cmd = "install_name_tool -change #{rlib} @executable_path/#{name} #{file}"
        if Preview == 1
            puts "Preivew: #{cmd}"
        else
            `#{cmd}`
        end
    else 
        puts "ignore rlib: #{rlib}";
    end
end

def fix_file_rely_lib(file)
  puts "===============start change #{file}==============="
  linklibs = `otool -L #{file}`.split("\n")
  linklibs.delete_at(0)
  linklibs.each_with_index do |rlib,i|
    rlib = rlib.split()[0]
    fix_opencv_lib_link(file,rlib)
  end
end

def doopencvlist
  # puts "Preview: #{Preview}"
  `ls |grep libopencv`.split().each_with_index do |file,i|
    fix_file_rely_lib(file)
  end
end

def viewlib(file)
    puts `otool -L #{file}`
end

if __FILE__ == $0
  if ARGV[0] == 'preview'
    Preview = 1;
    doopencvlist();
  elsif ARGV[0] == 'view'
    `ls |grep libopencv`.split().each_with_index do |file,i|
      # puts "===============start view #{file}==============="
      viewlib(file)
    end
  elsif ARGV[0] == 'do'
    doopencvlist();
  elsif ARGV[0] == 'previewfile'
    Preview = 1;
    fix_file_rely_lib(ARGV[1])
  elsif ARGV[0] == 'file'
    fix_file_rely_lib(ARGV[1])
  else
    puts "please input command [preview,do,previewfile,file,view] "
  end
end

參考鏈接

http://blog.csdn.net/openglnewbee/article/details/17783909
如何使用第三方的dylib
@rpath, @loader_path, @executable_path
Apple Developer:Overview of Dynamic Libraries
Apple Developer: Run-Path Dependent Libraries

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 僅以方便自己查閱記錄前言1.靜態(tài)庫和動態(tài)庫有什么異同?靜態(tài)庫:鏈接時完整地拷貝至可執(zhí)行文件中,被多次使用就有多份冗...
    190CM閱讀 4,515評論 0 4
  • 靜態(tài)庫與動態(tài)庫的區(qū)別 首先來看什么是庫,庫(Library)說白了就是一段編譯好的二進制代碼,加上頭文件就可以供別...
    吃瓜群眾呀閱讀 12,313評論 3 42
  • 原文地址 ,此簡書只做備份,強烈推薦原文,畢竟格式比簡書好看,還清晰 起因 去年,鏈家網iOS端,之前由于所有的業(yè)...
    南梔傾寒閱讀 12,694評論 29 130
  • 一個人陪伴另一個人是緣分,也是一種幸福。而我希望你們幸福。 01 剛得知他們分手的消息,我是不相信的,我以為她在和...
    熒火蟲和土豆閱讀 365評論 0 0
  • /小雨文圖 十月,我來到這片湖 沒有人告訴我它的名字 我暫且叫它未名湖 我只是偶然經過,不作停留 水在水里,岸在岸...
    小雨飄飄閱讀 378評論 0 1

友情鏈接更多精彩內容