iOS 編譯部署路徑

來源:互聯網
上載者:User

標籤:運行   還需要   add   ram   依賴   相對   size   變數   ios   

在 OSX 上初次接觸到這些變數, 有些暈. 看了一些文檔之後, 覺得弄明白了. 做一個總結.


在編譯一個動態庫比如 libfoo.dylib 的時候, 你需要指定 INSTALL_PATH. 也就是它的安裝路徑.


一個可執行程式比如 bar.app 使用 libfoo.dylib, 那麼在編譯 bar.app 的時候, libfoo.dylib 的 INSTALL_PATH 會被記錄到 bar.app 中, 用來定位這個 dylib. 用如下命令可以查看:


$ otool -L bar.app/Contents/MacOS/bar
bar.app/Contents/MacOS/bar:
     /usr/local/lib/libfoo.dylib (compatibility version 1.0.0, current version 1.0.0)
     /System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 19.0.0)
     /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 945.0.0)
     …
這裡的 /usr/local/lib 就是預設的 INSTALL_PATH. 要 bar.app 能正常運行, 必須先把 libfoo.dylib 拷貝到這個目錄. 如果 libfoo.dylib 只是被 bar.app 使用, 那麼拷貝到系統目錄可能是不合適的. 一個解決問題的辦法就是修改 libfoo.dylib 的 INSTALL_PATH, 使用相對路徑. 因而就需要用到下面這三個變數.


看 dyld 的 manual, 有這三個變數的解釋.


@executable_path 這個變數表示可執行程式所在的目錄. 比如 /path/bar.app/Contents/MacOS/ .


@loader_path 這個變數表示每一個被載入的 binary (包括可執行程式, dylib, framework 等) 所在的目錄. 在一個進程中, 對於每一個模組, @loader_path 會解析成不用的路徑, 而 @executable_path 總是被解析為同一個路徑(可執行程式所在目錄). 比如一個會被多個程式調用的 plugin, 位於 /path/Myfilter.plugin/Contents/MacOS/Myfilter, 依賴 /path/Myfilter.plugin/Contents/dylib/libfoo.dylib. 那麼 libfoo.dylib 的 INSTALL_PATH 可以設定為 @loader_path/../dylib, 這樣設定的話, 不論 Myfilter.plugin 目錄放到什麼位置, libfoo.dylib 都能正確的被載入.


@rpath 和前面兩個不同, 它只是一個儲存著一個或多個路徑的變數. 比如 libfoo.dylib 被兩個 .app 使用, 且被包含的路徑不同, 如下:


     bar.app/
          Contents/
               MacOS/
                    bar
               libfoo.dylib


     baz.app
          Contents/
               MacOS/
                    baz
               dylibs/
                    libfoo.dylib
將 libfoo.dylib 的 INSTALL_PATH 設定成 @loader_path/.. 或 @loader_path/../dylibs 都只能滿足其中一個 .app 的需求. 要解決這個問題, 就可以用 @rpath. 將 libfoo.dylib 的 INSTALL_PATH 設定成 @rpath, 然後在編譯 bar.app, baz.app 時分別指定 @rpath 為 @loader_path/.., @loader_path/../dylibs, 問題得到瞭解決. @rpath 的另一個優點是可以設定多個路徑. 如果 bar.app 還需要使用另一個 .framework (假設它的 INSTALL_PATH 也設定成了 @rpath), 位於 @loader_path/../frameworks, 把這個路徑加到 @rpath 即可.


道理說清楚了, 怎麼設定這些變數呢?
在 libfoo.dylib 的項目屬性中設定 INSTALL_PATH 設定為 @rpath


在 bar.app 中設定 @rpath 為 @loader_path/.. @loader_path/dylibs

對於一個編譯好的 binary, 有幾個命令列工具可以查看, 修改 rpath:


查看 @rpath


$ otool -l bar.app/Contents/MacOS/bar 
...
Load command 19
          cmd LC_RPATH
      cmdsize 32
         path @loader_path/.. (offset 12)
Load command 20
          cmd LC_RPATH
      cmdsize 40
         path @loader_path/../dylibs (offset 12)

install_name_tool 還可以刪除/替換/添加 @rpath, 比如:


$ install_name_tool -add_rpath @loader_path/../frameworks bar.app/Contents/MacOS/bar 
它還可以修改依賴的動態庫的載入路徑, 比如:


$ otool -L bar.app/Contents/MacOS/bar
bar.app/Contents/MacOS/bar:
     @rpath/libfoo.dylib (compatibility version 1.0.0, current version 1.0.0)

$ install_name_tool -change @rpath/libfoo.dylib @loader_path/libfoo.dylib bar.app/Contents/MacOS/bar
$ otool -L bar.app/Contents/MacOS/bar
bar.app/Contents/MacOS/bar:
     @loader_path/libfoo.dylib (compatibility version 1.0.0, current version 1.0.0)
...
看看 otool, install_name_tool 的協助瞭解這幾個命令的細節

iOS 編譯部署路徑

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.