RPM製作簡單說明

在此直接以我在公司開發的 lcd daemon 來作為實例
首先把我的 lcd daemon 編譯過,得到 lcdctld, 假設為 1.0.0 版,release 第一次
接著,隨便在某個地方建立目錄,命名為 lcdctld-1.0.0
在裡面建立 /usr/sbin
然後把 lcdctld 放到 lcdctld-1.0.0/usr/sbin 裡面去
利用
tar cvzf lcdctld-1.0.0.tar.gz lcdctld-1.0.0
這個指令得到 tar.gz 檔案
把這個檔案丟到 /usr/src/redhat/SOURCES 裡面去
接著就是最重要的地方了
要編輯 lcdctld.spec 檔案
內容如下:

%define name lcdctld
%define ver 1.0.0
Summary: MS-9507 LCD Daemon
Name: %{name}
Version: %{ver}
Release: 1
License: Micro Star Inc.
Group: System Environment/Daemons
BuildRoot: %{_tmppath}/%{name}-%{ver}-root%
description
lcdctld is a daemon that listen MS-9507 device.
%prep
%setup -q
%build
%install
rm -rf $RPM_BUILD_ROOT
%{__mkdir} $RPM_BUILD_ROOT/
%{__mkdir} $RPM_BUILD_ROOT/usr
%{__mkdir} $RPM_BUILD_ROOT/usr/sbin
install -m555 usr/sbin/lcdctld $RPM_BUILD_ROOT/usr/sbin
rm -f tmp
%cleanrm -rf $RPM_BUILD_ROOT
%files/usr/sbin/lcdctld

這裡面有很多東西,建議直接找個範本來修改比較好,我是直接拿 thttpd 的來作修改.
主要要修改的有上面的欄位:Summary, License, Name, Version, Group, …等等的
還有 %install 開始的地方,這裡主要就是寫複製檔案的 script.事實上, RPM 會自動把你 SOURCES 下的 tar.gz 檔解開,所以你只要把對應的檔案複製到 RPM_BUILD_ROOT 對應的目錄去就好了.
最後還有 %files ,如果這裡沒有東西,rpm 會發生錯誤.這裡主要是放檔案的列表,讓 rpm 知道這個 package 裡面有什麼檔案.
編輯好 lcdctld.spec 之後,輸入
rpm -bb lcdctld.spec
順利的話,你應該會在 /usr/src/redhat/RPMS/i386 目錄下看到 lcdctld-1.0.0-1.rpm 才對~~
你可以使用
rpm -Uvh lcdctld-1.0.0-1.rpm
來安裝
然後使用
rpm -e lcdctld-1.0.0-1
來移除
.spec 裡面的一些用法
%define -> 定義一些變數
%{xxx} -> 引用變數
%{_tmppath} -> 會指到 /var/tmp 下面
%{__command}-> shell的指令幾乎都可以引用,只是前面要加上兩個底線,例如 mkdir 就是 %{__mkdir}.
%prep
%setup
%build
%install
%clean
%files -> 這些都是表示特定的步驟,雜誌上只說在 %install, %clean, %files 要加東西而已,其他不清楚
我想這樣子在目前的使用上,應該就足夠了吧~
將來如果有新的發現,會在這個主題上繼續累加~
資料參考來源: Linuxer 雜誌第 12 期以及 Linux in a NutShell
Linux in a NutShell 只有說明 rpm 指令有哪些參數而已,完全沒有說明 .spec 檔要如何編輯

NumLock

在 Red Hat 環境下,NumLock 老是關閉的(Mandrake 不會)
如果懶得一個一個去把 NumLock 按成 On
可以在
/etc/rc.local 最後,放如下指令:[bash]# Enable NumLock
for tty in /dev/tty[1-6]; do
setleds -D +num < $tty
done[/bash]
即可
另外,此行據稱可以加速,但我不知道是什麼意思
[bash]echo “base=0xd8000000 size=0x800000 type=write-combining” > /proc/mtrr[/bash]
也可以一併放在 /etc/rc.local 中

Build Library How-to

程式碼
======
假設 main() 呼叫 iloveso() 這個函式,而且程式分開的話,程式碼就會像這樣子:
callso.c
#include <stdio.h>
void iloveso(void);
int
main(void)
{
printf(“\nmain() begin\n”);
iloveso();
printf(“main() end\n”);
}
iloveso.c
#include <stdio.h>
extern void iloveso(void);
void
iloveso(void)
{
printf(“here is so!!\n”);
}
一般做法
========
一般的情況下,我們會這樣去編譯程式
gcc callso.c iloveso.c –o callso
編譯出來後,直接執行 ./callso 就可以執行程式了。
靜態連結
========
因為 iloveso() 這個函式,其他程式也可能會使用到,我們希望把他獨立出來,這樣子,別人就可以直接連結他,而不需要重新編譯一次。
我們可以先編譯為 obj 檔之後,再利用 ar 指令,將 obj 檔變為 .a (靜態library) 檔。
再執行Ranlib 以確保 .a 檔能跟 unix 相容。
gcc -c iloveso.c -o iloveso.o
ar rcv libiloveso.a iloveso.o
ranlib libiloveso.a
為了驗證這樣子是可行的,請先在 /etc/ld.so.conf 最後加上 /usr/local/lib。
接著執行 ldconfig。然後將 libiloveso.a 放到 /usr/local/lib
執行
gcc –o callso callso.c –liloveso
沒有錯誤訊息的話表示成功,請執行 ./callso 試試。
如果有錯誤的話,通常是因為 ld.so.conf 檔案未設定,或設定後未執行 ldconfig 的緣故。
動態連結
========
當有很多程式都使用同一個靜態Library時,每個程式都會將該靜態連結檔給含括進來,所以會造成空間浪費,我們可以利用動態連結避免掉這個缺點。
同樣的,我們可以利用下列的程式來編譯動態連結檔
gcc -shared -Wl,-soname,libiloveso.so -o libiloveso.so iloveso.c -lc
這樣子就直接產出 libiloveso.so 了。
接下來同樣安裝到 /usr/local/lib,確定ld.so.conf有增加/usr/local/lib後,執行 ldconfig,以完成設定。
然後利用如下指令編譯 callso.c
gcc -o callso callso.c –liloveso
這樣就 ok 了,你可以試著用 ldd callso 去驗證一下,是不是真的有連結到。
結論及注意事項
==============
發現了嗎??不管是靜態或動態,程式碼和程式指令都不曾變更過,只有編譯Library 檔時,有些許差別而已。這對程式設計師來說,真是方便很多。
要特別注意的是Library檔必須以 lib 為開頭;另外,當 .a 和.so 同時存在時,gcc 會自動以 .so 作為優先連結對象,若你要強迫gcc作靜態連結,就要在編譯時加上 –static 。