之前接觸到了snap打包自己的應用程序與依賴,但它的默認沙盒隔離的機制導致其訪問系統庫有局限性,它在訪問硬件資源的時候沒有的那些權限需要額外聲明,不符合應用發布的便攜性要求。
本文學習下如何用deb打包的方式打包自己需要調用系統庫的程序。順便將之前的gcc動態鏈接庫的流程走一遍
本文失敗的部分是,并沒有像預期的那樣能將我的so文件復制到usr/local/lib,正常的打包解包是可以的,感覺就只是和壓縮包一樣......
目錄
DEB包的組成:
準備需要打包的程序:
GPIO_LED.c? 與 GPIO_LED.h?:
編譯動態鏈接庫:
程序文件調用動態鏈接庫LED_light.c:
編譯C文件為可執行文件:
驗證程序運行:
安裝必要的工具:
創建 ledlight 的 DEB 包:
創建項目目錄結構:
創建control文件:
依賴庫的處理_postinst文件:
創建install文件:?
卸載前腳本_prerm?文件:
構建規則rules 文件:
創建changelog版本號文件:
設定文件權限:
生成deb包:
解包deb:
參考文章:
DEB包的組成:
DEB(Debian Package)是Debian及其衍生系統(如Ubuntu)使用的軟件包格式,主要用于軟件的安裝、升級和管理。
一個DEB包本質上是一個ar歸檔文件,他在構建前,包含以下核心組成部分:
myapp-1.0/ # 項目根目錄(通常與包名+版本一致) ├── debian/ # Debian 打包專用目錄(必須存在) │ ├── control # 包的元數據(名稱、版本、依賴等) │ ├── changelog # 包的更新日志(生成版本號) │ ├── rules # 構建規則(Makefile 風格的腳本) │ ├── copyright # 版權信息 │ ├── compat # 兼容性聲明(如 "10" 表示 Debian Policy 10) │ ├── source/ # 源碼包相關配置(可選) │ ├── install # 指定安裝文件的規則(如 `usr/bin/* usr/bin`) │ ├── preinst # 安裝前腳本(可選) │ ├── postinst # 安裝后腳本(可選) │ ├── prerm # 卸載前腳本(可選) │ ├── postrm # 卸載后腳本(可選) │ └── conffiles # 配置文件列表(如 `/etc/myapp/config.conf`) ├── src/ # 項目源碼目錄(可選) │ ├── main.c │ └── Makefile └── build/ # 構建臨時目錄(通常自動生成)
文件名 類型 說明 control
純文本文件 定義包的元數據(無后綴)。 changelog
純文本文件 記錄版本更新歷史(無后綴,格式遵循 Debian Policy
)。rules
可執行腳本 構建規則(無后綴,本質是 Makefile
腳本,需chmod +x
)。copyright
純文本文件 版權聲明(無后綴)。 compat
純文本文件 兼容性聲明(無后綴,內容如 10
)。install
純文本文件 定義文件安裝路徑(無后綴,如 usr/bin/* usr/bin
)。preinst
可執行腳本 安裝前腳本(無后綴,需 #!/bin/sh
和chmod +x
)。postinst
可執行腳本 安裝后腳本(無后綴)。 prerm
可執行腳本 卸載前腳本(無后綴)。 postrm
可執行腳本 卸載后腳本(無后綴)。 conffiles
純文本文件 列出需要保留的配置文件(無后綴,每行一個路徑如 /etc/myapp.conf
)。
準備需要打包的程序:
這一部分先不要在?/home/orangepi/DEB_GPIOLED 進行寫程序,推薦另起一個文件夾,后續將必要的內容復制過去即可
GPIO_LED.c? 與 GPIO_LED.h?:
GPIO_LED.c? 與 GPIO_LED.h
這是基礎的LED初始化與點亮程序 , 被注釋部分用于測試其子函數是否奏效
該程序需要被構建為一個libGPIO_LED.so動態鏈接庫
#include "GPIO_LED.h"void GPIO_LED_init(void) {// 初始化 wiringPi(必須調用,否則會報錯)wiringPiSetup(); // 使用 wiringPi 的引腳編號pinMode(LED_BLUE,OUTPUT);pinMode(LED_RED,OUTPUT);pinMode(LED_GREEN,OUTPUT); //初始化全滅digitalWrite(LED_BLUE ,LOW);digitalWrite(LED_RED ,LOW);digitalWrite(LED_GREEN ,LOW); }//控制LED 紅色亮滅 void LED_RED_(char flag) {if(flag == 1){digitalWrite(LED_RED ,HIGH);}else if(flag == 0){digitalWrite(LED_RED ,LOW); } }//控制LED 藍色亮滅 void LED_BLUE_(char flag) {if(flag == 1){digitalWrite(LED_BLUE ,HIGH);}else if(flag == 0){digitalWrite(LED_BLUE ,LOW); } }//控制LED 綠色亮滅 void LED_GREEN_(char flag) {if(flag == 1){digitalWrite(LED_GREEN ,HIGH);}else if(flag == 0){digitalWrite(LED_GREEN ,LOW); } }/* int main(void) {GPIO_LED_init();while(1){LED_GREEN_(0);LED_RED_(1);delay(500);LED_GREEN_(1); LED_RED_(0); delay(500); } } */
#include <stdio.h> #include <wiringPi.h>#define LED_BLUE 13 #define LED_RED 15 #define LED_GREEN 18void GPIO_LED_init(void); void LED_RED_(char flag); void LED_BLUE_(char flag); void LED_GREEN_(char flag);
編譯動態鏈接庫:
編譯動態鏈接庫:
gcc GPIO_LED.c -fPIC -shared -o libGPIO_LED.so
將該動態鏈接庫復制到目錄
/usr/local/lib
:?下:sudo cp libGPIO_LED.so /usr/local/lib
更新動態鏈接器緩存:
sudo ldconfig
檢查動態鏈接庫:
ldd libGPIO_LED.so
但我們發現ldd命令檢查出的libGPIO_LED.so是靜態的,這是
ldd
的誤判,ldd
通常用于檢查動態庫的依賴關系,但如果庫 沒有依賴任何其他動態庫(比如沒有調用libc
的函數,或者 GCC 靜態鏈接了部分庫)如果
GPIO_LED.c
沒有使用任何libc
函數(如printf
、malloc
等),并且沒有鏈接其他庫(如-lpthread
),那么ldd
會認為它“靜態鏈接”,因為沒有外部依賴。
此時使用file命令更準確徹底:
根據
file
命令的輸出,libGPIO_LED.so
確實是一個 動態鏈接庫(shared object),并且顯示為dynamically linked
,這與之前ldd
顯示的statically linked
?不同。
程序文件調用動態鏈接庫LED_light.c:
現在我有個程序文件交LED_light.c,他會調用動態鏈接庫 libGPIO_LED.so,以及WiringPi庫
他會讓LED紅藍交替閃爍:
#include <stdio.h> #include "GPIO_LED.h" #include <wiringPi.h>int main(void) {GPIO_LED_init();while(1){LED_BLUE_(0);LED_RED_(1);delay(500);LED_BLUE_(1); LED_RED_(0); delay(500); } }
編譯C文件為可執行文件:
編譯將LED_Light.c與動態庫libGPIO_LED.so 以及libwiringPi 鏈接生成執行文件ledlight
gcc LED_Light.c -lGPIO_LED -lwiringPi -o ledlight
驗證程序運行:
sudo ./ledlight
LED交替亮滅
?
安裝必要的工具:
sudo apt-get update
sudo apt-get install dh-make dpkg-dev build-essential
創建 ledlight
的 DEB 包:
?每個文件的代碼里的注釋要刪去!
創建項目目錄結構:
一、先創建一個?DEB_GPIOLED?構建Deb包的目錄:
cd /home/orangepi
mkdir DEB_GPIOLEDcd /home/orangepi/DEB_GPIOLED
二、創建打包目錄:
mkdir DEBIAN
mkdir src
mkdir build
創建control文件:
進入目錄:
cd?/home/orangepi/DEB_GPIOLED/debian/
使用文本編輯器創建
control
文件nano control
確保wiringpi可通過
apt
安裝apt-cache show wiringpi
Package: ledlight Version: 1.0-1 Architecture: arm64 # arm64/amd64/armhf Maintainer: Your Name <your.email@example.com> Description: Control LED lights via GPIOA simple program to control LED lights using GPIO pins,dynamically linked to libGPIO_LED.so and WiringPi library. Depends: libc6 (>= 2.28), wiringpi (>= 2.50) # 不寫 libgpio-led ,libgpio-led (>= 1.0) Section: utils Priority: optional
在 Debian/Ubuntu 的
control
文件中,Depends
字段是核心的依賴聲明部分,它會告訴包管理系統(如apt
/dpkg
)在安裝當前軟件包時自動安裝所依賴的包。
將程序文件LED_light.c 和?ledlight復制到 /home/orangepi/DEB_GPIOLED/src/:
依賴庫的處理_postinst文件:
/usr/local/lib/libGPIO_LED.so?是我自定義的庫,手動安裝的,不在 APT 倉庫中,因此不能通過Depends自動安裝,
因此這里將其放在項目的lib文件夾中,以便檢查到目標機器沒有這個庫就復制一個到 /usr/local/lib。
因為庫沒有打包為debian,所以在
postinst
腳本中執行ldconfig
更新庫緩存:nano postinst
#!/bin/sh set -e# 符合FHS的路徑定義 TEMP_LIB="/var/lib/ledlight/libGPIO_LED.so" TARGET_LIB="/usr/local/lib/libGPIO_LED.so"case "$1" inconfigure)if [ ! -f "$TARGET_LIB" ]; thenecho "Installing libGPIO_LED.so to /usr/local/lib/"mkdir -p /usr/local/libcp "$TEMP_LIB" "$TARGET_LIB"chmod 644 "$TARGET_LIB"ldconfigfi# 總是清理臨時文件rm -f "$TEMP_LIB"rmdir --ignore-fail-on-non-empty /var/lib/ledlight;;abort-upgrade|abort-remove|abort-deconfigure)# 安裝失敗時也清理rm -f "$TEMP_LIB"rmdir --ignore-fail-on-non-empty /var/lib/ledlight;; esacldconfig # 確保系統能找到 /usr/local/lib 下的庫exit 0
最后別忘了把libGPIO_LED.so復制到/home/orangepi/DEB_GPIOLED/lib:
cd?/home/orangepi/DEB_GPIOLED/
mdir lib
cd /home/orangepi/gcc_cpp_codes/? ?#有libGPIO_LED.so的目錄
cp libGPIO_LED.so /home/orangepi/DEB_GPIOLED/lib/
1
?
創建install文件:?
nano install
將項目目錄下的
lib/libGPIO_LED.so
文件安裝到目標系統的
/var/lib/ledlight/
目錄(DEB 包內路徑)lib/libGPIO_LED.so var/lib/ledlight/
卸載前腳本_prerm
?文件:
nano prerm
#!/bin/sh set -eTARGET_LIB="/usr/local/lib/libGPIO_LED.so"case "$1" inremove|upgrade|failed-upgrade)# 僅在完全卸載(purge)時刪除庫文件if [ "$1" = "remove" ] || [ "$1" = "failed-upgrade" ]; thenif [ -f "$TARGET_LIB" ]; thenecho "Removing libGPIO_LED.so from /usr/local/lib/"rm -f "$TARGET_LIB"fifi;;purge)# 徹底清除時強制刪除if [ -f "$TARGET_LIB" ]; thenecho "Purging libGPIO_LED.so from /usr/local/lib/"rm -f "$TARGET_LIB"fi;; esacldconfig # 更新庫緩存 exit 0
構建規則rules 文件:
nano rules
#!/usr/bin/make -f%:dh $@ --with autotools-devoverride_dh_auto_configure:@:override_dh_auto_build:$(MAKE) CC="$(CC)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS) -lWiringPi -L/usr/local/lib -lGPIO_LED" ledlightoverride_dh_auto_install:# 安裝可執行文件到 /usr/bininstall -D -m 0755 ledlight $(CURDIR)/debian/ledlight/usr/bin/ledlight# 將庫文件安裝到臨時位置(由postinst處理)install -D -m 0644 libGPIO_LED.so $(CURDIR)/debian/ledlight/var/lib/ledlight/libGPIO_LED.sooverride_dh_shlibdeps:dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info
創建changelog版本號文件:
基本格式:
package (version) distribution; urgency=urgency* change detail 1* change detail 2* change detail 3-- Maintainer Name <email@address> Date
對應編寫:
nano changelog
ledlight (1.0-1) unstable; urgency=medium* Initial release.* Includes ledlight executable and libGPIO_LED.so library.* Post-install script handles library installation to /usr/local/lib.-- Your Name <your.email@example.com> Mon, 24 Jun 2024 14:30:00 +0800
生成日期以更新:
可以通過終端得到當前日期以更新changelog中的日期文件
date -R
如果時區不對,如此設置時區為上海:
sudo timedatectl set-timezone Asia/Shanghai
?
設定文件權限:
chmod 755 debian/postinst debian/prerm
chmod 644 lib/libGPIO_LED.so
生成deb包:
dpkg-deb --build . ../ledlight_1.0-1_arm64.deb
解包deb:
這里我先rm刪除掉以前存在的libGPIO_LED.so
?嘗試解包:
# 創建解壓目錄并解包 mkdir -p ledlight_extracted dpkg -x ledlight_1.0-1_arm64.deb ledlight_extracted/# 單獨提取控制文件(元數據和腳本) dpkg -e ledlight_1.0-1_arm64.deb ledlight_extracted/DEBIAN
發現并沒有像預期的那樣將我的so文件復制到usr/local/lib :
參考文章:
如何把代碼打包成一個 deb package_嗶哩嗶哩_bilibili文字稿在 haoduoshipin.com, 視頻播放量 3715、彈幕量 0、點贊數 42、投硬幣枚數 20、收藏人數 88、轉發人數 10, 視頻作者 好奇貓學院, 作者簡介 編程,區塊鏈,密碼學等等。,相關視頻:數字簽名原理,如何把 deb 軟件包上傳到 apt 倉庫中,動畫演示 Diffie-Hellman 密鑰交換算法,挑戰魔改1300天前的塔防代碼 | 手把手教你做冰凍炮臺??,【網安】編寫一個木馬有多簡單?,什么是密碼學?,RSA 算法基本原理,如何使用 font-awesome “字體圖標”,什么是 Ajax ?,最大的開放標準--古代中國
https://www.bilibili.com/video/BV1kE411G7vt/?spm_id_from=333.337.search-card.all.click&vd_source=090e0b0724f6022d9ce8b14853097061
deb包構建詳解_deb包制作詳解-CSDN博客