摘 要:Linux系統由于自由開源特性,許多個人、組織以及商業機構都能夠進行Linux操作系統的構建,因此出現了眾多各有特色的Linux發行版,每個發行版采用的包管理與軟件分發技術不盡相同。文中主要介紹了Snap、Flatpak以及AppImage等Linux發行版常用軟件打包技術,由于AppImage具有單一文件免安裝的獨有特性,作者對AppImage的原理及技術進行了詳細分析,并將局域網即時通信軟件Iptux進行了單文件打包。經測試驗證,軟件打包后能夠在申威統信服務器操作系統以及麒麟服務器操作系統上正常運行,實用性強,為申威平臺的軟件打包提供了更多的思路和方法。
關鍵詞:申威平臺;單文件;軟件打包;AppImage;跨發行版;Linux
中圖分類號:TP39 文獻標識碼:A 文章編號:2095-1302(2024)06-0-04
0 引 言
在Linux系統生態建設過程中,應用軟件的打包與分發是Linux生態系統中不可忽視的一環。應用軟件的打包與分發是指將軟件源代碼編譯成可執行二進制文件,并打包成一個安裝包,通過軟件倉庫和第三方軟件源將軟件分發給用戶,使用戶能夠方便地進行應用軟件的安裝、升級和卸載。在Linux系統中,常用的軟件打包格式包括RPM和DEB兩
種[1]。RPM是Red Hat Package Manager的縮寫,是Red Hat開發的一種軟件包管理工具,主要用于Red Hat系列的Linux發行版。DEB是Debian Package的縮寫,是Debian開發的一種軟件包格式,主要用于Debian系列的Linux發行版。由于不同的Linux發行版之間存在差異,軟件打包也存在不同。首先,不同的發行版使用不同的包管理工具,因此需要為每個發行版打包不同的軟件包。其次,不同的發行版之間存在著不同的依賴關系,因此需要為每個發行版打包不同的依賴關系。這些問題使得軟件打包變得復雜和繁瑣,同時也增加了軟件開發者的工作量[2]。為解決這些問題,一些新的軟件打包和分發工具正在被開發和推廣,其中,AppImage是一種新型軟件打包和分發工具,它可以將軟件打包成一個獨立的、可執行的二進制文件,使得軟件可以在不同的Linux發行版之間運行,并且不受系統依賴關系的影響,使得軟件的安裝和升級變得更加方便和簡單。
1 Linux常用軟件打包
通常一個應用軟件在Linux系統上打包需要針對不同的Linux發行版生成不同的軟件包格式,工作量大且繁瑣。為了使Linux系統上應用軟件的開發和打包過程更加簡單和高效,開發人員構建了與發行版無關的軟件包格式,其中包括Snap、Flatpak以及AppImage[3],這些軟件包具有共同的特點,即包含了應用程序所需的所有庫和依賴項,能夠獨立于操作系統環境運行,應用開發人員無需為不同的Linux系統構建不同的軟件包,即一個軟件打包一次,可以在多個發行版上安裝、運行以及更新。
1.1 Snap打包
Snap是一種通用的、跨平臺的打包方式,由Canonical公司開發,最早出現在Ubuntu發行版中。它旨在簡化軟件的安裝和更新過程,同時提供更好的安全性、隔離性和依賴管理。
(1)跨平臺:Snap支持多種Linux發行版,包括Ubuntu、Fedora、Arch Linux等。開發者只需創建一個Snap包就可以在所有支持Snap的發行版上運行。
(2)安全性:Snap應用程序運行在沙箱環境中,與系統其它部分隔離,降低了安全風險。
(3)依賴管理:Snap軟件打包包含了應用程序運行所需的所有依賴庫,避免軟件運行時缺少依賴或者依賴沖突,使應用程序在不同的系統和環境中保持一致的行為。
1.2 Flatpak打包
Flatpak是一種靈活、安全、跨發行版的應用程序打包和分發技術,它將應用程序打包成一個獨立的容器,并包含所有運行所需的庫和依賴項,使應用程序可以在不同的Linux發行版上運行。
(1)跨發行版支持:Flatpak可以在不同的Linux發行版上運行,無需重新編譯或適配。
(2)隔離環境:Flatpak應用程序運行在一個獨立的容器中,與主系統隔離,可以防止應用程序之間的沖突和干擾,同時防止惡意軟件的攻擊。
(3)自依賴:Flatpak應用程序包含所有運行所需的庫和依賴項,不依賴主系統上安裝的軟件包。
1.3 AppImage打包
AppImage是一種可以將應用程序打包成一個獨立可執行文件的軟件打包技術,包含所有運行所需的庫和依賴項,可以在不同的Linux發行版上運行。與傳統的軟件包管理不同,AppImage無需解壓或安裝,用戶可以直接運行和刪除應用程序,而不會對系統造成影響。
(1)跨發行版支持:使用AppImage打包的應用程序可以在許多發行版上運行,無需重新編譯或適配。
(2)自依賴:一個應用程序就是一個文件,包含所有運行所需的庫和依賴項,不依賴主系統上的環境獨立運行。
(3)環境隔離:AppImage應用程序運行在一個獨立的隔離環境中,通過Linux內核的Namespaces和Cgroups機制隔離不同應用的文件系統,不會干擾系統以及系統上的其它程序。
(4)非root權限:無需root權限,運行AppImage應用程序前,通過設置環境變量、掛載臨時文件系統、設置用戶權限等,確保應用程序在運行時有足夠的權限和資源。
除Snap、Flatpak和AppImage外,Deepin的玲瓏軟件包也是一種具有跨發行版、自依賴、與主系統隔離等特點的應用打包方式,主要運用在深度Linux操作系統中,這些新穎的打包方式很好地解決了Linux系統中軟件安裝和軟件依賴的問題,減少了軟件打包和發布的工作量[4],同時改善了Linux系統的軟件使用體驗,提高了軟件的安全性。
2 AppImage實現原理及技術分析
2.1 AppImage實現原理
AppImage軟件包主要由兩部分組成[5]─AppImage運行時Runtime以及一個只讀壓縮文件系統SquashFS,兩部分共同打包成一個可執行二進制文件。相比Snap與Flatpak打包,AppImage的自解壓、自掛載、免安裝運行是其最為獨特的一個特性。
當用戶運行AppImage文件時,由運行時Runtime將AppImage中的只讀壓縮文件系統SquashFS解壓到系統臨時目錄中,并使用Linux內核的fusefs用戶態文件系統來掛載SquashFS,完成掛載后在臨時虛擬文件系統中運行應用程序。當退出軟件時,運行時Runtime自動卸載虛擬文件系統并清理相關臨時文件,保持系統整潔。
SquashFS文件系統包含了應用軟件運行時所需的二進制可執行程序、動態鏈接庫、圖標文件以及配置文件等,這也是AppImage應用程序能夠在不同Linux發行版上運行的主要原因。AppImage應用程序就是一個二進制可執行文件,無需安裝直接運行,并且刪除AppImage文件本身即完成卸載,極大地方便了用戶對應用軟件進行更新和管理。AppImage軟件包組成如圖1所示。
2.2 AppImage技術分析
2.2.1 AppImage運行時Runtime
運行時Runtime是AppImage的核心組成部分之一,由C語言編寫,通常使用靜態鏈接來實現在不同Linux發行版上的兼容性。同時為了兼顧輕量、快速的運行,在嵌入式Linux應用中,Runtime一般采用musl C Library構建,musl C Library具有更小的二進制文件和更快的啟動速度,能夠顯著減小AppImage并加快程序啟動,使應用程序更加簡潔高效。Runtime在AppImage中主要實現的功能有:
(1)解壓縮AppImage文件:運行時Runtime首先會使用appimage_get_elf_section_offset_and_length()函數獲取Runtime的大小以及SquashFS在AppImage中的偏移量,解壓縮SquashFS到一個臨時目錄中。
(2)掛載SquashFS文件系統:通過build_mount_point()函數創建掛載點,在臨時目錄中以.mount_appname-xxxx命名隱藏文件,并以fusefs用戶態文件系統掛載。
(3)啟動應用程序:Runtime使用execv()函數啟動SquashFS中的AppRun,AppRun設置一些環境變量并啟動應用程序。
(4)卸載SquashFS文件系統并清理緩存:在應用程序退出時,Runtime清理臨時目錄中解壓的SquashFS文件。
2.2.2 AppImage應用載體SquashFS
SquashFS是一個包含AppImage應用程序主體文件的目錄結構AppDir,通常是一個以$APPNAME.AppDir命名的文件夾。在構建AppImage時,應用程序以及它所需的依賴庫會被復制到AppDir中,搜集和復制的過程可以手動進行也可以使用AppImageKit提供的工具,如使用Open Build Service(OBS)、Qt部署工具linuxdeployqt等來完成。
AppDir的目錄結構通常包含以下幾部分:
(1)usr目錄:應用程序和它所需的依賴庫目錄通常包括bin目錄、lib目錄和share目錄等。
(2)AppRun腳本:AppRun腳本是一個可執行腳本或是一個可執行程序的軟鏈接,用于啟動應用程序,它通常會設置一些環境變量,如APPDIR、LD_LIBRARY_PATH、PATH等。其中,APPDIR變量指向AppImage文件所在的目錄,LD_LIBRARY_PATH變量用于指定動態鏈接庫搜索路徑,PATH變量用于指定可執行文件配置項搜索路徑。
(3)desktop文件:該文件是一個用于在桌面環境中顯示應用程序圖標和名稱的配置文件,通常包含應用程序的名稱、圖標、描述和啟動命令等信息。
(4)圖標文件:該文件是用于在桌面環境中顯示應用程序圖標的文件。
AppDir目錄結構如圖2所示。
2.2.3 Qt應用打包linuxdeployqt
linuxdeployqt是一個Qt應用程序打包工具,它可以自動處理應用程序的依賴關系,利用ldd讀取可執行文件的頭部信息來確定需要哪些依賴庫,并將依賴庫和資源打包到AppDir中,同時使用patchelf工具修改可執行文件的依賴庫路徑、RPATH路徑等信息[6],將應用程序運行時尋找依賴的路徑限定在AppDir內。
linuxdeployqt在打包應用程序時,會自動生成AppRun腳本來啟動應用程序,如果需要自定義AppRun腳本,可以在AppDir目錄下手動創建AppRun腳本,linuxdeployqt會優先使用自定義的AppRun腳本。
linuxdeployqt使用-appimage參數進行可執行程序和依賴庫的打包:
$ linuxdeployqt path/to/your/app -appimage
3 申威平臺應用軟件AppImage打包
目前支持申威平臺的Linux發行版本主要有統信UOS、麒麟KylinOS以及openEuler,采用的應用軟件打包方式主要為Debian系列的DEB包和Red Hat系列的RPM包,因此在申威平臺上應用軟件的分發需要針對不同的發行版單獨進行打包和適配,增加了工作量,限制了軟件的通用性和易用性。為此,通過前文對AppImage軟件打包實現原理及技術的分析,現將Linux局域網即時通信軟件Iptux在申威平臺上進行單文件AppImage構建,一次打包能夠在多個發行版上兼容運行[7-9]。
3.1 Iptux編譯移植
Iptux是一款開源局域網即時通信軟件,可以在局域網內實現點對點聊天、文件傳輸、遠程桌面共享等功能。由于采用GTK+編寫,因此Iptux的編譯移植需要首先完善編譯主機的GTK開發環境,以使用apt包管理的統信UOS為例:
$ apt install gcc-c++ cmake gettext gflags libgoogle-glog-dev libgtk-3-dev libglib2.0-dev libjsoncpp-dev ninja-build meson libsigc++-2.0-dev libfuse-dev patchelf
根據meson.build中的定義生成具體的構建定義文件build.ninja,并使用ninja完成Iptux的編譯:
$ meson builddir --default-library static amp;amp; ninja -C builddir
編譯完成后生成申威平臺的Iptux二進制可執行文件以及動態鏈接庫libiptux-core.so、libiptux-core.so.0和libiptux-core.so.0.8.3,因為這些文件用于后續AppImage打包,因此不需要通過ninja-C builddir install進行Iptux安裝。
3.2 linuxdeployqt編譯移植
進入linuxdeployqt源碼目錄并修改tools/linuxdeployqt/main.cpp中的版本檢查:
/*if (strverscmp (glcv, \"2.27\") gt;= 0) {//注釋版本檢查
qInfo() lt;lt; \"ERROR: The host system is too new.\";
...
return 1;
}*/
編譯linuxdeployqt,生成申威平臺的linuxdeployqt-sw_64:
$ cmake CMakeLists.txt amp;amp; make
3.3 AppDir構建
AppDir是AppImage應用軟件的主體部分,根據前文分析說明的AppDir目錄結構將Iptux編譯生成的二進制可執行文件、動態鏈接庫以及應用圖標文件復制到對應usr/bin、usr/lib和usr/share目錄中,并使用linuxdeployqt工具將Iptux運行時所依賴的動態鏈接庫打包進AppDir的usr/lib目錄中,linuxdeployqt打包動態鏈接庫命令:
$ linuxdeployqt-sw_64 Iptux.AppDir/usr/bin/iptux -appimage
完成打包后Iptux.AppDir目錄結構:
$ ls Iptux.AppDir/AppRun" .DirIcon" iptux.desktop" iptux-icon.png" usr
3.4 AppImage運行時RunTime編譯移植
運行時Runtime使用靜態鏈接構建,以滿足在不同Linux發行版上的兼容性要求,主要依賴組件有squashfuse、fuse、zstd等,編譯runtime.c,生成申威平臺的runtime:
$ gcc runtime.c -o runtime-fuse-sw_64 -std=gnu99 -s -Os -D_FILE_OFFSET_BITS=64 -DGIT_COMMIT=\\"1.0.0\\" -T data_sections.ld -ffunction-sections -fdata-sections -Wl,--gc-sections -I/usr/local/include/squashfuse -I/usr/include/fuse -L/usr/local/lib -lsquashfuse -lsquashfuse_ll -L/opt/zstd/usr/lib -lzstd -lfuse -llzma -lz -ldl -llz4 -lpthread -static
3.5 AppImage構建
根據前文分析,AppImage軟件包主要由運行時Runtime以及只讀壓縮文件系統SquashFS組成,因此拼接Runtime和SquashFS壓縮文件即可完成AppImage構建:
$ mksquashfs Iptux.AppDir Iptux.squashfs -root-owned -noappend
$ cat runtime-fuse-sw_64 gt;gt; Iptux-sw_64.AppImage
$ cat Iptux.squashfs gt;gt; Iptux-sw_64.AppImage
生成的Iptux-sw_64.AppImage是一個單一文件的可執行文件,其包含Iptux可執行文件以及運行時所依賴的動態鏈接庫、圖標以及配置文件,經測試驗證,能夠在申威統信UOS Server以及麒麟V10上免安裝運行,具有很好的Linux跨發行版兼容性和便攜性[10]。
4 結 語
國產CPU廠商近年來奮楫前行,軟硬件生態建設有了長足的發展,特別是在黨政、金融領域,大量適配軟件已經能夠滿足用戶需求,但在消費領域,軟件生態建設仍然需要廣大開發者和用戶的共同努力。文中提出的AppImage單文件軟件打包具有很強的實用性,極大地方便了軟件的分發與使用,希望能夠為申威軟件生態建設者在軟件打包與分發方面提供一些新的思路,也為國產CPU的發展和生態建設提供支持。
參考文獻
[1]岑鵬瑞,吳玲達,楊超.淺談Linux平臺下軟件管理現狀[J].電腦知識與技術,2015,11(17):56-59.
[2]趙正旭,陶智,徐騫.基于國產操作系統應用軟件部署對策的探討[J].微型機與應用,2016,35(18):16-18.
[3] Flatpak vs.Snap vs.AppImage [EB/OL].(2022-06-08). https://phoenixnap.com/kb/flatpak-vs-snap-vs-appimage
[4]馬俊,周凱,任怡,等.面向操作系統版本構建的軟件包依賴關系分析[J].計算機工程與科學,2021,43(11):1926-1933.
[5] AppImage中文文檔[DB/OL].https://doc.appimage.cn/docs/appimage/
[6]蔣立兵,申秋,韓隆隆.內網漫游過程中的編譯方法研究[J].通信技術,2021,54(7):1690-1695.
[7]柴赟達.面向國產申威平臺的編譯訪存優化技術研究[D].鄭州:鄭州大學,2021.
[8]高順凱.一種基于申威平臺可靠性評測方法的設計與實現[J].艦船電子工程,2021,41(10):150-154.
[9]陳偉.一種基于申威平臺的AppImage應用軟件打包裝置及其方法:CN116661904B [P]. 2023-10-13.
[10]倪杰,何佩佩,王俊,等.一種針對申威平臺代碼遷移的軟件依賴檢測及判斷方法:CN202111525606.3 [P]. 2022-04-19.