MacPorts打包過程簡介

小米運維發表於2019-04-09
本文主要為大家介紹一下MacPorts的打包過程。
MacPorts打包過程簡介

MacPorts 與 Homebrew

Homebrew 相信很多人都聽說過,它是 macOS 上使用者最多的包管理軟體。但 macOS 上的包管理軟體並非只有 Homebrew 一家,MacPorts、Nix 也是各有其獨特之處的 macOS 包管理器。

MacPorts 與 Homebrew 相比有什麼優點呢?

首先,MacPorts 的包數量特別多

根據 repology 統計,Homebrew 的官方源大約有四千六百個包,與之相比 MacPorts 社群維護了足足一萬一千多個官方包。不過由於包數量過多和缺少維護者,MacPorts 在軟體更新速度上要比 Homebrew 慢不少。

其次,MacPorts 對於老版本的 macOS 提供了良好的支援。

Homebrew 現在已經要求 macOS 10.12 及以上版本的系統才可以正常安裝使用,而 MacPorts 在社群成員的支援下至今仍在提供低至 Mac OS X 10.5 系統的支援,很多常用的包例如 curl、perl 都可以直接安裝二進位制包。

最後,MacPorts 和傳統包管理軟體一樣要求使用 root 許可權執行包的安裝、解除安裝等操作。

或許對於很多人來說,每次安裝包都要加上 sudo 並輸一次密碼比較繁瑣,但只有這樣才能確保 MacPorts 管理的檔案只有 root 使用者有許可權修改。筆者認為,保護好包管理目錄,對於管理大量 Mac 裝置的系統管理員來說十分重要。

如果任何程式都能隨意在包管理的路徑下建立、刪除檔案,就有可能因第三方程式的修改,出現包不可用或安裝包時檔案被覆蓋的情況。

說了這麼多,讓我們迴歸正題介紹一下 MacPorts 是怎麼從原始碼編譯出一個傳統的使用 autoconf 的上游專案的吧。

包“配方”(Portfile)

在 MacPorts 每個包都必須有一個對應的 Portfile 檔案。這個檔案說明了包的原始碼從哪裡獲取、編譯需要哪些工具、依賴的庫、編譯引數等等。接下來我會以 getdns 這個包為例介紹一下從原始碼的下載到執行配置指令碼、編譯、打包和安裝的全過程和對應的 Portfile 寫法。

下載和解壓原始碼

Portfile 只是一個配方,包的原始碼還是需要從網上下載。下面這兩行程式碼指定了包的主頁和原始碼 tar 包的下載位置。

homepage            https://getdnsapi.net/master_sites        ${homepage}dist/複製程式碼

name                getdnsversion             1.5.1複製程式碼

MacPorts 預設會下載 ${name}-${version}.tar.gz 檔案,包名和包版本由上面兩行程式碼定義。使用 port distfiles getdns 命令可以檢視要下載的檔名、儲存路徑、Portfile 中記錄的雜湊值、檔案大小和下載檔案的 URL。雜湊值和檔案大小是為了保證上游或第三方沒有修改包的內容,這樣可以避免網站被黑客攻擊後檔案被惡意替換的問題。

--->  Distfiles for getdns[getdns-1.5.1.tar.gz] /opt/local/var/macports/distfiles/getdns/getdns-1.5.1.tar.gz rmd160: 94aa50f60099fdb001da4903bba2be538d109c15 sha256: 5686e61100599c309ce03535f9899a5a3d94a82cc08d10718e2cd73ad3dc28af size: 1075728  https://getdnsapi.net/dist/getdns-1.5.1.tar.gz  https://distfiles.macports.org/getdns/getdns-1.5.1.tar.gz複製程式碼

以 getdns 為例,MacPorts 會從軟體的官網或 MacPorts 的官方映象(有兩個在中國哦)下載這個 tar 包到 /opt/local/var/macports/distfiles/getdns/ 目錄下。下載成功後會用 Portfile 中記錄的 checksums 校驗檔案,通過後才會解壓下載的 tar 包。解壓成功的話進入下一步執行配置指令碼。

checksums           rmd160  94aa50f60099fdb001da4903bba2be538d109c15 \                    sha256  5686e61100599c309ce03535f9899a5a3d94a82cc08d10718e2cd73ad3dc28af \                    size    1075728複製程式碼

使用了 autoconf 框架的軟體在編譯時需要執行 ./configure 命令才能開始用 make 編譯。但 MacPorts 並沒有使用預設的 /usr/local 目錄,而是為了和使用者自行安裝的軟體隔離開使用了 /opt/local 字首。所以 MacPorts 在執行這個指令碼時會預設加上 --prefix=/opt/local 引數來調整安裝目錄。同時為了讓編譯器能找到依賴庫的標頭檔案和庫檔案,MacPorts 會配好 CPPFLAGS、LDFLAGS 等環境變數。最後,MacPorts 會將 Portfile 中指定的配置引數加到 --prefix 之後,這可以用來開啟或關閉一些功能。

configure.args      --enable-stub-only \                    --with-libevent \                    --without-libidn複製程式碼

編譯

編譯在這個例子裡非常簡單,只要在原始碼目錄下執行 make 命令,MacPorts 就會預設開啟並行編譯,即新增 -jN 引數,N 為 port 命令根據 CPU 和記憶體自動判斷的並行任務數。

make -j2複製程式碼

打包與安裝

編譯成功後進入 destroot 階段,這個階段 MacPorts 仍然執行 make 命令,但帶上了 install 和 DESTDIR 兩個引數。make install 用於把編譯好的檔案安裝到指定的目錄。DESTDIR=... 則表示不要直接把檔案安裝到之前配置的 prefix 下,而是安裝到 MacPorts 臨時建立的目錄下。

make -w install DESTDIR=/opt/local/var/macports/build/...複製程式碼

通過指定臨時建立的 DESTDIR 目錄,MacPorts 在“安裝”成功後可以直接用 tar 命令把二進位制包打到 /opt/local/var/macports/software/getdns/getdns-1.4.2_1.darwin_17.x86_64.tbz2 裡。MacPorts 官方提供的二進位制包就是用這種方式生成並在符合協議規範的前提下上傳到映象站上供使用者下載的。

最後,MacPorts 會將打好的二進位制包解壓到 /opt/local 下,並清理打包過程中產生的臨時檔案。這樣就完成了 getdns 的安裝。

—end—

排版/許曄

文/SRE

本文首發於小米運維微信公眾號,原文請戳連結MacPorts打包過程簡介



相關文章