Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RPM Packaging

趙惟倫
February 18, 2014

RPM Packaging

趙惟倫

February 18, 2014
Tweet

More Decks by 趙惟倫

Other Decks in How-to & DIY

Transcript

  1. 趙惟倫 <[email protected]> 2014 年 2 月 18 日 製作 製作

    RPM RPM 套件 套件 TOSSUG 主題分享
  2. RPM RPM 套件管理系統 ( 安裝、解除安裝、驗證、查詢、更新 ) 原名 Redhat Package Manager

    後改為 RPM Package Manager 原始碼套件 (source rpm) 包含原始碼、補丁與規格檔 安裝套件 (install rpm) 包含待安裝的檔案與目錄 套件檔 (rpm file) 為 cpio 格式的封裝檔 規格檔 (spec file) 為整合所有動作的巨集文字檔 使用 RPM 來管理套件的 GNU/Linux 發行版: RedHat 、 Fedora 、 CentOS 、 ALT 、 SUSE 、 Mageia… www.rpm.org
  3. 命名規則 命名規則 主要名稱 [- 次要名稱 ]- 版本編號 - 釋出編號 .

    平臺屬性 .rpm firefox xterm libs devel 2.1.3 20080724 1 2.el5 3.fc20 0.rc1.4 src i686 x86_64 armv7hl noarch 套件名稱:主要名稱 [- 次要名稱 ][. 平臺屬性 ]
  4. 相關套件 相關套件 基本套件 – ( 必要 ) rpm, rpm-libs, rpm-python

    製作套件 – ( 必要 ) rpm-build, redhat-rpm-config – ( 選用 ) rpmdevtools, rpmlint 前端套件 – ( 必要 ) dnf – ( 選用 ) rpmorphan – ( 圖形介面 ) yumex-dnf, gnome-packagekit
  5. 相關路徑 相關路徑 預設組建位置: $HOME/rpmbuild/* BUILD/, BUILDROOT/, RPMS/, SOURCES/, SPECS/, SRPMS/

    個人巨集設定: $HOME/.rpmmacros #%_topdir $HOME/rpmbuild #%dist .fc24 #%fedora 24 %packager Wei-Lun Chao <[email protected]> 套件庫設定: /etc/yum.conf, /etc/yum.repos.d/*
  6. 常用命令 常用命令 RPM 製作: rpmbuild -bs 規格檔案 rpmbuild -ba [--nodeps]

    規格檔案 rpmbuild –showrc RPM 操作: rpm -Uvh [--force|--nodeps|--test] 套件檔案… rpm -e [--noscripts] 套件名稱… rpm -qa [--queryformat=' 巨集變數列表 '] 套件名稱樣式 rpm -qf 檔案或目錄路徑 rpm -qi 套件名稱 |-p 套件檔案 rpm -ql 套件名稱 |-p 套件檔案
  7. 命令範例 命令範例 > dnf download joe --source > rpm -Uvh

    joe-4.2-1.fc24.src.rpm > cd $HOME/rpmbuild/SPECS > ls ../SOURCES/ > $EDITOR joe.spec > dnf builddep joe.spec > rpmbuild -ba joe.spec > ls ../BUILD/joe-4.2 > rpm -qpl ../SRPMS/joe-4.2-1.fc24.src.rpm > rpm -Uvh ../RPMS/i686/joe-4.2-1.fc24.i686.rpm > rpm -ql joe
  8. deb deb 控制檔 控制檔 忽略 debhelper, debconf 刪除 -[.0-9]* 版本號

    libgnomevfs2 改為 gnome-vfs2 pkg-config 改為 pkgconfig libdbus-glib 改為 dbus-glib libgnome-menu 改為 gnome-menus libclutter 改為 clutter libgconf2 改為 GConf2 python-gnome2 改為 gnome-python2 python-dbus 改為 dbus-python python-glade2 改為 pygtk2-libglade python-serial 改為 pyserial python-notify 改為 notify-python python-twisted 改為 python-twisted-core xdg-utils 改為 pyxdg python-tz 改為 pytz -dev 改為 -devel gtkhtml 改為 gtkhtml3 libgtk2.0 改為 gtk2 libglib2.0 改為 glib2
  9. ALT-linux ALT-linux 規格檔 規格檔 KOI8-R 或 WINDOWS-1251 另存 UTF-8 BuildPreReq:

    改為 BuildRequires: Xfree86-devel 改為 libX11-devel dbus-tools-gui 改為 dbus-x11 xpm-devel 改為 libXpm-devel libgtk+2-devel 改為 gtk2-devel libncurses-devel 改為 ncurses-devel xorg-cf-files 改為 imake libqt3-devel 改為 qt-devel %__autoreconf 改為 autoreconf %_man?dir 改為 %{_mandir}/man? %_iconsdir 改為 %{_datadir}/pixmaps %_x11dir/bin 改為 %{_bindir} perl-devel 改為 perl subst 改為 sed -i qt3dirs.sh 改為 qt.sh netcat 改為 nc %make 改為 make freetype2 改為 freetype %python_sitelibdir 改為 % {python_sitearch} libreadline-devel 改為 readline-devel %_x11sysconfdir 改為 % {_sysconfdir}/X11
  10. Mandriva/Mageia Mandriva/Mageia 規格檔 規格檔 %mkrel %rel 改為 1%{?dist} %makeinstall_std 改為

    %makeinstall %_iconsdir 改為 %{_datadir}/pixmaps libnspr-devel 改為 nspr-devel libnss-devel 改為 nss-devel libxp-devel 改為 libXp-devel libxt-devel 改為 libXt-devel %_install_info 改為 install-info qt4-linguist 併入 qt4-devel gtk+2-devel 改為 gtk2-devel libimlib2-loaders 改為 imlib2 procps-devel 改為 procps libgnome2-devel 改為 libgnome-devel libxext-devel 改為 libXext-devel libstdc++6 改為 libstdc++ bluez-devel 改為 bluez-libs-devel %make 改為 make libdirectfb 改為 directfb libboost 改為 boost libx11_6 改為 libX11 qscintilla-qt4-devel 改為 qscintilla-devel %_iconsdir/hicolor 改為 % {_datadir}/icons/hicolor %{_libdir}/apache- extramodules 改為 % {_libdir}/httpd/modules %py_platsitedir 改為 % {python_sitearch}
  11. PLD/SUSE PLD/SUSE 規格檔 規格檔 Release: 之後附加 %{?dist} ISO-8859-2 字集改為 UTF-8

    %rpmcflags 改為 %optflags %rpmldflags 改為 -s %tmpdir 改為 %_tmppath %_desktopdir 改為 % {_datadir}/applications %_pixmapsdir 改為 % {_datadir}/pixmaps %date 改為上一次 revision 日期 perl-base 改為 perl OpenGL 改為 mesa-lib OpenGL-GLX 改為 mesa-libGL xorg-lib-* 改為 * Copyright: 改為 License: sgmltool 改為 linuxdoc-tools update-alternatives 改為 chkconfig libsmpeg 改為 smpeg Mesa 改為 mesa-libGL python-pygame 改為 pygame python-gtk 改為 pygtk2 update-desktop-files 改為 desktop-file-utils 刪除 %debug_package %install_info 改為 install-info
  12. 舊版 舊版 Fedora Fedora 規格檔 規格檔 docbook-xsl-stylesheets 改為 docbook-style-xsl alsa-devel

    改為 alsa-lib-devel pulseaudio-devel 改為 pulseaudio-libs-devel xorg-x11-devel 改為 xorg-x11-proto-devel lesstif-devel 改為 motif-devel freetype2-devel 改為 freetype-devel python-distribute 改為 pythons-setuptools gtk-devel 改為 gtk+-devel
  13. 輔助命令 輔助命令 新建: rpmdev-newspec foo.spec 檢查: rpmlint foo.spec 模板: Name:

    foo Version: Release: 1%{?dist} Summary: License: URL: Source0: BuildRequires: Requires: %description %prep %setup -q %build %configure make %{?_smp_mflags} %install %make_install %files %doc %changelog
  14. 內容結構 內容結構 常用 屬性區段 描述區段 準備區段 組建區段 安裝區段 檔案區段 變更記錄區段

    選用 定義區段 次套件屬性區段 次套件描述區段 次套件檔案區段 命令稿區段 次套件命令稿區段
  15. 定義區段 定義區段 說明: 以 %global 起始的巨集定義 選用組合: %global realname Foo

    %global svn 384 %global _missing_build_ids_terminate_build %{nil} %global debug_package %{nil} %global __debug_install_post %{nil} %global __arch_install_post %{nil} %global __os_install_post %{nil} %global __spec_install_post %{nil}
  16. 屬性區段 屬性區段 說明: 套件的必要區段 不需要起始巨集指令 常用組合: Name: foo Summary: A

    Multimedia Tool Version: 1.2.3svn384 Release: 1%{?dist} URL: http://www.foo.org/ License: MIT Source0: http://www.foo.org/% {name}-%{version}.tar.gz BuildRequires: bar1-devel BuildRequires: desktop-file-utils 選用組合: Summary(zh_TW): 繁中概要 Source1: foo.png Patch0: foo-desktop.patch Patch1: foo.zh_TW.patch AutoReqProv: off Requires: bar1, bar2 Provides: libfoo Obsoletes: foo-beta Conflicts: foo1 NoSource: 0 BuildArch: noarch
  17. 描述區段 描述區段 說明: 以 %description 起始的描述 常用組合: %description Foo is

    a tool for multimedia files. 選用組合: %description -l zh_TW Foo 是用於多媒體檔案的工具。
  18. 次套件屬性、描述區段 次套件屬性、描述區段 說明: 以 %package 起始的屬性定義 以 %description 起始的描述 常用組合:

    %package devel Summary: A Multimedia Tool Requires: %{name} = %{version}-% {release} %description devel Development files for %{name}. 選用組合: %package data Summary: A multimedia game BuildArch: noarch %description -n lib%{name} Library files for %{name}. %description -n lib%{name} -l zh_TW %{name} 所需的函式庫檔案。
  19. 準備區段 準備區段 說明: 以 %prep 起始的前置動作 %setup 解壓後進入工作目錄 預設 %{name}-%{version}

    常用組合 ( 附加 ) : %setup -q %setup -qc %setup -qn %{realname} %setup -qa 1 %setup -T %setup -qTb 1 -n % {realname} 選用組合 ( 附加 ) : %setup -q %patch0 %patch1 -p2 %patch2 -p1 %setup -q cp %{SOURCE1} data sed -i '1i #include <cstdio>|' m.cpp sed -i 's|2\.18\.0|2.14.0|' configure* sed -i '/curl\/types\.h/d' src/url_utils.c
  20. 組建區段 組建區段 說明: 以 %build 起始的組建動作 會先進入工作目錄 有些 noarch 套件不需此巨集

    常用組合 ( 附加 ) : %configure make %{?_smp_mflags} export LIBS="-lX11" ./configure --prefix=/usr --disable-static make 選用組合 ( 附加 ) : cmake . -DCMAKE_INSTALL_PREFIX=/usr make %qmake_qt5 -recursive make xmkmf -a make python setup.py build gcc -Wl,-soname,libfoo.so.0 -fPIC -shared -o libfoo.so.0 -I. libfoo.c gcc -o foo *.o -ldl -lm scons build prefix=/usr xbuild foo.sln
  21. 安裝區段 安裝區段 說明: 以 %install 起始的安裝動作,會先進入工作目錄 常用組合 ( 附加 )

    : %make_install desktop-file-validate %{buildroot}/%{_desktopdir}/%{name}.desktop %find_lang %{name} 選用組合 ( 附加 ) : python setup.py install -O1 --root=%{buildroot} install -Dm755 %{name} %{buildroot}%{_bindir}/%{name} mkdir -p %{buildroot}%{_datadir}/%{name} cp -a * %{buildroot}%{_datadir}/%{name} desktop-file-install %{SOURCE3} --dir=%{buildroot}%{_desktopdir} make install INSTALL_ROOT=%{buildroot} scons install stage_dir=%{buildroot}
  22. 檔案區段 檔案區段 / / 次套件 次套件 說明: 以 %files 起始的檔案列表

    常用組合: %files -f %{name}.lang %license COPYING %doc AUTHORS NEWS %{_bindir}/%{name} %{_datadir}/%{name} %{_mandir}/man?/%{name}.* %{_desktopdir}/*.desktop %{_datadir}/pixmaps/*.png 選用組合: %files %{_bindir}/%{name} %{_datadir}/locale/*/LC_MESSAGES/* %files devel %{_libdir}/%{name}/*.so %{_libdir}/pkgconfig/*.pc %{_includedir}/%{name} %exclude %{_libdir}/%{name}/*.la
  23. 命令稿區段 命令稿區段 / / 次套件 次套件 說明: %pre,%preun, %post,%postun (

    安裝、解除之前 / 後 ) 等巨集起始的命令稿 常用組合: %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %post /usr/bin/fc-cache %postun /usr/bin/fc-cache 選用組合: %post data %{_bindir}/update-mime-database % {_datadir}/mime &> /dev/null %{_bindir}/gtk-update-icon-cache --quiet %{_iconsdir}/hicolor %postun data %{_bindir}/update-mime-database % {_datadir}/mime &> /dev/null %{_bindir}/gtk-update-icon-cache --quiet %{_iconsdir}/hicolor
  24. 變更記錄區段 變更記錄區段 說明: 以 %changelog 起始的變更記錄,最近一次修改在最上方 常用組合 ( 附加 )

    : * Tue Feb 18 2014 Wei-Lun Chao <[email protected]> 1.0-2 - Rebuild for FC20 選用組合 ( 附加 ) : * Tue Feb 18 2014 Wei-Lun Chao <[email protected]> 2.0-1 - Update to 2.0 - Add locale file for zh_TW * Tue Aug 6 2013 Wei-Lun Chao <[email protected]> 1.0-1 - Initial package
  25. 嵌入檔案 嵌入檔案 .src.rpm .spec Source0: .tar.gz .tar.bz2 .tar.xz .zip Patch*:

    .diff.gz .patch Source*: .rar .7z .rpm .deb .jar .swf .po .ts .ico .gif .png .desktop .sh
  26. 取得原始碼 取得原始碼 直接下載原始碼軟體包 或是仿製後再壓縮封裝 git clone git://github.com/user/foo.git ; rm -rf

    foo/.git bzr branch lp:foo svn export http://foo.sourceforge.net/trunk/foo hg clone http://code.google.com/p/foo/ fossil clone http://www.fossil-scm.org/foo
  27. .rar .7z ( .rar .7z ( 特殊格式 特殊格式 ) )

    使用 .rar : Source0: %{name}-src-%{version}.rar BuildRequires: unar %prep %setup -T -c unar %{SOURCE0} 使用 .7z : Source0: %{name}-%{version}.7z BuildRequires: p7zip
  28. .rpm .deb ( .rpm .deb ( 安裝套件 安裝套件 ) )

    使用 .rpm : Release: 1%{?dist}.bin Source0: %{name}-%{version}- 1.i386.rpm %prep %setup -T -c rpm2cpio %{SOURCE0} | cpio -i --make-directories %install mkdir -p %{buildroot} cp -a * %{buildroot} 使用 .deb : Release: 1%{?dist}.bin Source0: %{name}_%{version}- 1_i386.deb %prep %setup -T -c ar -x %{SOURCE0} %install mkdir -p %{buildroot} tar xf data.tar.gz -C %{buildroot} 備註: spec 檔內容可參考 deb 控制檔或者 rpm -q 的輸出
  29. .jar .swf ( .jar .swf ( 虛擬架構軟體 虛擬架構軟體 ) )

    使用 .jar : Release: 1%{?dist}.bin Source0: %{name}.jar Requires: jre BuildArch: noarch %prep %setup -T -c unzip -p %{SOURCE0} gui/icon.png > %{buildroot}%{_datadir}/%{name}/% {name}.png cp %{SOURCE0} %{buildroot}% {_datadir}/%{name}/%{name}.jar 使用 .swf : Release: 1%{?dist}.bin Source0: %{name}.swf Requires: flash-player BuildArch: noarch %prep %setup -T -c cp %{SOURCE0} %{buildroot}% {_datadir}/%{name}.swf
  30. .po .ts ( .po .ts ( 訊息翻譯 訊息翻譯 ) )

    使用: Source1: %{name}-1.2.3.zh_TW.po BuildRequires: gettext %prep #sed -i 's/LINGUAS="/LINGUAS="zh_TW /' configure* echo zh_TW >> po/LINGUAS cp %{SOURCE1} po/zh_TW.po %build #make -C po zh_TW.gmo #msgfmt po/zh_TW.po -o po/zh_TW.gmo %install #msgfmt %{SOURCE1} -o %{buildroot}% {_datadir}/locale/zh_TW/LC_MESSAGES/%{name}.mo
  31. .ico .gif .png ( .ico .gif .png ( 圖示 圖示

    ) ) 取得: 從軟體網站或搜尋自 http://www.google.com.tw/imghp 使用: Source1: %{name}.ico BuildRequires: ImageMagick %prep convert -transparent white %{SOURCE1} %{name}.png %install install -Dm644 %{name}.png %{buildroot}%{_datadir}/pixmaps/% {name}.png
  32. .desktop ( .desktop ( 選單 選單 ) ) 使用: Source1:

    %{name}.desktop %install desktop-file-install % {SOURCE1} --dir=%{buildroot}% {_desktopdir} 備註: Categories=AudioVideo;Developm ent;Education;Network;Graphic s;Office;Settings;System;Util ity;Game; 內嵌: %setup cat << EOF > %{name}.desktop [Desktop Entry] Encoding=UTF-8 Name=%{realname} Comment=%{summary} Exec=%{name} Icon=%{name} Terminal=false Type=Application Categories=Application;Graphics;View er; EOF
  33. .sh ( .sh ( 命令稿 命令稿 ) ) 使用: Source1:

    %{name}.sh %install install -Dm755 %{SOURCE1} %{buildroot}%{_bindir}/%{name} 內嵌: %install cat > %{buildroot}%{_bindir}%{name} << EOF #!/bin/bash cd %{_datadir}/%{name} exec ./%{name} EOF chmod 755 %{buildroot}%{_bindir}/%{name}
  34. .diff.gz ( .diff.gz (deb deb 補丁 補丁 ) ) 來源:

    Debian 原始碼庫所提供的補丁檔 使用: Patch0: %{name}.diff.gz %setup %patch0 -p1 %build while read i; do mkdir -p debian/%{name}$i; done < debian/dirs %install mkdir -p %{buildroot} cp -pr debian/%{name}/* %{buildroot}
  35. .patch ( .patch ( 原始碼補丁 原始碼補丁 ) ) 使用 diff

    : 程式來自 diffutils 套件,是較為傳統的一般做法。 假設軟體 foo 的原始碼軟體包展開後為一個目錄 foo-x.y.z 1. 執行 cp -a foo-x.y.z foo-x.y.z.orig 以備份未修改版本 2. 進入 foo-x.y.z 目錄以修改程式 3. 執行 cp -a foo-x.y.z foo-x.y.z.fixed 4. 進入 foo-x.y.z.fixed 目錄以組建軟體並測試成果 5. 修改完成時回到上層目錄,否則回到步驟 2. 6. 執行 diff -Nur foo-x.y.z.orig foo-x.y.z > foo-x.y.z-what.patch 要應用於 foo-x.y.z.orig 時,須進入該目錄執行 patch -p1 < ../foo- x.y.z-what.patch
  36. .patch ( .patch ( 原始碼補丁 原始碼補丁 ) ) 使用 gendiff

    : 程式來自 rpm-build 套件,是較為適合原始碼套件的做法。 假設組建時將原始碼展開於 $HOME/rpmbuild/BUILD/foo-x.y.z 1. 執行 find foo-x.y.z -name *.orig 若已有此類檔案則另選副檔名 2. 進入 foo-x.y.z 目錄以備份每個將要修改的程式 cp bar.c bar.c.orig 3. 如果要新增檔案則先 touch new.c new.c.orig 4. 修改程式並組建軟體與測試,全部完成時回到上層目錄 5. 執行 gendiff foo-x.y.z .orig > ../SOURCES/foo-x.y.z-what.patch 要應用於 foo.spec 時,須於檔頭部分加入 Patch1: foo-x.y.z-what.patch 並於 %setup 之後加入 %patch1 -p1
  37. rpm5 rpm5 說明 Jeff Johnson 基於 rpm-4.x 繼續開發 與 RedHat

    主導的 4.x 版同時安裝會產生衝突 現況 2012-07-06 版本 5.4.10 <http://rpm5.org> 套件 × Fedora 套件庫 △其他 RPM 套件庫 × 各類 DEB 套件庫 使用 與 4.x 版大致相容
  38. alien alien 說明 各類套件格式的轉換軟體 執行時依賴 DEB 套件系統 現況 2015-09-11 版本

    8.95 <http://joeyh.name/code/alien/> 套件 ◦Fedora 套件庫 ◦其他 RPM 套件庫 ◦各類 DEB 套件庫 使用 alien --to-rpm 套件檔名
  39. 其他工具 其他工具 debian2spec : from Debian source directory cabal2spec :

    from Haskell Cabel package oct2spec : from Octave package R2spec : from R package pyp2rpm : from Python index package gem2rpm : from Ruby gems package cpan2rpm : from Perl module package npm2rpm : from Node.js module package pom2rpm : from Java Maven package pkg2rpm : from Solaris Pkg package pear2rpm : from PHP Pear package
  40. 一般 一般 檔案應以 UTF-8 編碼、無 BOM 的純文字格式儲存 檔案本身權限應為 644 各區段以空一列分隔較為清楚

    描述區段中的文字應於超過 80 欄之前換列 專屬軟體 License: 可用 Commercial ;一般開放原始碼可用 MIT,Apache License,PD ;自由軟體可用 GPL,LGPL ;免費軟 體可用 freeware,shareware 新增 %changelog 項目應註明 Version 與 Release 不可將非自製軟體修改後重新封裝,除非已派生專案 套件應在異種平臺以一般使用者身分測試組建、執行
  41. 巨集規則 巨集規則 要接參數的巨集名稱不可加上大括號 巨集會先由 rpmbuild 解析,不受引號的限制 巨集是依組建系統的環境展開,而非安裝系統 %{} 與 %()

    的用法類似對應的 bash 用法 $HOME/.rpmmacros 中可定義 dist,packager,buildroot 內嵌 script 檔案時,注意 $ 與 % 之前要加 \ 可利用列首加 # 以備註,列首巨集則應將 % 改為 # 條件判斷巨集: %if ... %else ... %endif 架構判斷巨集: %ifarch ... %else ... %endif %clean 已不再需要
  42. 路徑巨集 路徑巨集 %{_prefix}→/usr %{_bindir}→/usr/bin %{_sbindir}→/usr/sbin %{_libdir}→/usr/%{_lib} %{_includedir}→/usr/include %{_sysconfdir}→/etc %{_datadir}→/usr/share %{_mandir}→%{_datadir}/man

    %{_desktopdir}→%{_datadir}/applications %{_iconsdir}→%{_datadir}/icons %{python_sitelib}→/usr/lib/python2.*/site-packages %{python3_sitearch}→%{_libdir}/python3.*/site-packages
  43. 定義、屬性 定義、屬性 使用 %global 替代 %define 屬性 Name 應與規格檔主檔名相同且不可有句點 屬性

    Packger,BuildRoot,Group,Epoch 不需要 屬性 Vendor,PreReq 不應設定 Summary 首字母大寫且不以句點結尾 修改後 Release 應加 1 ,版本如果更新則重置為 1 加強版 Release 加後綴 . 代號,搶鮮版再多加前綴 0. Source0 應為實際檔名做結尾的完整 URL ,例外應加備註 Requires 與 BuildRequires 儘量每列一項 次套件通常依存主套件, data 則相反 次套件 data,doc,themes 可改設 noarch
  44. 組建、安裝 組建、安裝 組建過程中不應有連線下載的動作 安裝過程會自動先執行清除 BuildRoot 以 %make_install 替代 %makeinstall install

    引數不可使用 -s 使用 %find_lang %{name} 與 %files -f %{name}.lang python setup.py install 時不應使用 INSTALLED_FILES 來源檔案應以工作目錄的相對路徑指定 %{buildroot} 與 $RPM_BUILD_ROOT 相同 不應在過程中直接修改 %{SOURCE*} 內容 以 desktop-file-utils 套件來安裝或驗證 .desktop 檔案 可執行的非程式檔會誘發產生除錯套件
  45. 檔案、命令稿 檔案、命令稿 %doc 指定 %{_datadir}/doc/%{name} 內的文件 %license 指定 %{_datadir}/license/%{name} 內的文件

    不需多寫預設的 %defattr(-,root,root,0755) 不可安裝於 /bin,/sbin,/opt,/usr/local 安裝共享函式庫於系統路徑的套件,應在命令稿中執 行 /sbin/ldconfig 不應安裝 *.la 類型的檔案 %files 中儘量使用路徑巨集 %files 只應列出專屬該套件的檔案或最上層目錄 %{_libdir} 之後不可只使用 * 以避免安裝 debug 目錄 呼叫 sh 的 if 時,只能使用 [ ] 而無法用 test