Board logo

标题: rpm 建包原理(2010.11.22 更新) [打印本页]

作者: KDE    时间: 2004-10-3 22:46     标题: rpm 建包原理(2010.11.22 更新)

为什么要打包?
    制作 rpm 不仅仅是打包,更可以解决菜单创建、打补钉、完成大量预配置、与其他软件包互动等操作。使用源代码安装要求用户了解基本的编译过程、能够应付各种不能编译的意外、必须自己完成抽象的配置、甚至懂得软件开发,能够自己打补钉,……对非计算机专业的用户而言简直就是天方夜谭。这是把软件开发的最后一步抛给了用户,作为发行版,这是极不负责任的!也是不现实的,除非用 lfs,但那是一本菜谱,不是真正的发行版。

    软件作者发布源代码是正确的,负责的作者一般都同时提供 rpm 和 deb 包以及它们的源代码包。除非他们不会制作。愿意使用什么,那是个人的自由,但对外就不能只想到自己。GNU 精神是一种公益精神,没有奉献精神,在自由软件领域是要遭唾弃的!

    直接使用其他发行版的 rpm 常常是不行的。不知道大家看没看“恼人的依赖关系”这个帖子。可以在技术支持区搜索一下。任何两个发行版本在二进制上都是不能兼容的!他们实际是不同的操作系统。不仅使用的库文件不同,配置也迥异。特别是同一个发行版的不同版本更不兼容。任何包都必须在本地重新编译,而且不一定通得过,因为还有 spec 宏的兼容问题!如果要在别的发行版上使用,必须用源码编译,这是常识。考虑文件布局和配置问题,有时直接编译也是不够的,必须修改 spec,甚至自己打补丁。



如何创建 rpm 包?
    rpm 建包原理其实不复杂。写 spec 相当于一种脚本编程,主要是在 spec 里提供一些软件相关信息,以及安装、卸载前后要执行的脚本,然后展开压缩的源代码包,打上补丁,执行编译,然后利用 make install 可以重新指定安装目的地的特性,把编译好的文件安装到指定的虚拟根目录下的指定位置里,一般是虚拟的 /usr 里,然后把这些目录、信息和脚本打成一个压缩包,即 rpm 包。同时可选地生成源码包 src.rpm。当然有很多具体细节问题。您应该首先阅读软件的 readme 和 INSTALL 文件。



打包原则
1. 任何人都应该在系统现有 src.rpm 的 spec 基础上修改更新,除非没有这样的包。这可以省去很多麻烦,少走弯路。
2. 任何人都无权删除别人的 changelog 和原始打包者的信息,这是对别人的不尊重。但你可以追加自己的信息。
3. 尽可能在 spec 里使用系统的标准宏定义,而不要用非标准写法。
4. 任何人都不应该直接提供修改后的源代码,而应该以补丁形式发布你的修改,在 spec 里完成打补丁操作。务必做到一个补丁只解决一个问题,这样才能确保补丁的可重用性,否则版本升级后补丁很容易失效。如果你确信自己的补丁是清洁补丁,尽可能发给上游开发者,这样才能一劳永逸。你所打的任何补丁,其授权方式必须和被修改源代码保持一致。
5. rpm 不是跨平台打包技术。确保软件的二进制代码能够跨平台运行,不是系统软件打包者要考虑的事,而是应用软件作者和独立二进制代码发布者应该考虑的事。我们没有责任和义务确保从我们系统里拆解下来的部件能够运行于其他系统上,不支持,更不提倡这种移花接木的作法。

试图解决跨平台问题的打包技术,我印象中有 autopackage 和 klik 技术,参见:
http://autopackage.org
http://klik.atekon.de


预备知识:
首先我们观察一下 rpm 文件名的特点。一个 rpm 包文件名通常由 5 段组成:
%{name}-%{version}-%{release}.ix86.rpm
cutedict-1.1-1mgc.i686.rpm
这里 %{name}=cutedict,%{version}=1.1,%{release}=1mgc,ix86=i686,如果是为 athlon 芯片家族编译的包,这里就是 athlon,依此类推。

注意:
下面是一个spec 模板。
1. 凡是行首加上 # 的都被注释掉了,实际运行时不起作用,如要使其生效,请去掉注释符 #。
2. 凡是以 %{***} 和 %*** 形式出现的符号都是“宏”,很多宏都是系统预定义的[注2],也可以是自己定义的。
3. 下面的黑体字是 spec 文件的关键字,不能写错。
4. 有不明白的地方可以参见跟帖里的参考文献。
5. 如果软件没有使用 GNU autotool 创建,而是自己写的 Makefile,这就导致不能按照常规方法打包,非常麻烦。
6. 服务器软件通常都需要大量预配置工作,spec 打包绝非一两天能解决,需要深入研究很多东西和反复实践,建议初学者不要尝试。
7. 其他发行版的 spec 与 src.rpm 是很好的教材,建议打包前先找找 Fedora 或 SuSE 的文件学习,能借鉴最好,但不应该不修改照搬过来或使用 Mandrake/Mandriva 的文件,因为它使用的大量专有宏定义和我们不兼容,甚至 src.rpm 直接编译都通不过。

------------------------------------------------------------------

[spec 文件头部]

# Initial spec file created by autospec #这里是一些注释
%define  _noautoreq perl(Plot) perl(WidgetDemo) #这里用 %define 自定义一个系统里没有的叫做 _noautoreq 的宏,后面可以用 %{_noautoreq} 引用。
Name: software #这是软件包名称,后面可以用 %{name} 引用
Summary: a software #这是软件包的内容提要
#Summary(zh_CN): #这里写入中文内容提要(如果有必要。不建议使用,因为如果系统里的默认编码与此处不符,会导致显示乱码。例如:我们使用 GBK,如果这里的中文是 UTF-8 编码,在 kpackage 里就会显示乱码,但是 synaptic 可能能够正确显示,但需要把 zh_CN 改为 zh_CN.UTF-8 )
Version: number #这是软件的实际版本号,例如 2.1.6、2.2final 等,后面可以用 %{version} 引用
Release: number #发布序列号,我们用 1mgc、2mgc 等等,标明这是第几次打包。如果软件本身是预览版,比如 pre6 版,则写成 pre6_1mgc、pre6_2mgc,后面可以用 %{release} 引用
Group: Applications/Multimedia #这是软件分组,建议使用标准分组,参见下面:[注1]
#Group(zh_CN): #中文软件分组(如果有必要)
License: GPL #这是软件授权方式,通常是 GPL
Source: %{name}-%{version}.tar.gz #这是源代码(通常是压缩包),可以带有完整的网址,可以用正整数标识多个源 Source0 Source4 Source5 Source100,数字不必连续排列,后面可以用 %{SOURCE0}、%{SOURCE4}、%{SOURCE5}、%{SOURCE100} 引用。例如 http://www.example.net/src/%{name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot  #这是 make install 时使用的“虚拟根目录”也称为“构建根目录”,通常是 /var/tmp/软件名称-版本号-发布序列号-buildroot。对于服务器环境,可能同时有多人操作,为了确保编译软件时临时目录不会相互覆盖,还需要加上当前用户的标识:BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot-%(%{__id_u} -n)
make install 时一般会将软件安装在 /var/tmp/软件名称-版本号-发布序列号-buildroot/usr/  下的 bin/ 下(可执行文件)、share/ 下(数据、资源文件)、lib/ 下(动态共享库文件,即 .so 文件 <Share Object>,相当于 windows 下的 DLL 文件)等等,例如 /var/tmp/cce-0.51-1mgc-buildroot/usr/bin/cce。不过实际不一定都是这样,具体情况具体对待
# 下面是可选的字段
URL: http://www.example.net/ #这是软件主页地址
#Vendor:  Red Hat Co.,ltd. #这是发行商或者打包组织的信息,我们统一写成 MGC Group,不过这一行可以省略,把它写入 /usr/lib/rpm/macros 标准宏定义文件里,该文件的 Vendor 这行定义是空的,而且通常前面用 # 注释掉了
#Distribution: Red Hat Linux #这是软件针对的发行版标识,我们是 Magic Linux
Patch: src-%{version}.patch #这是补丁源代码(可以是压缩包),可以用正整数标识多个源 Patch1 Patch4 Patch6,数字不必连续排列。
Prefix: %{_prefix} #指定 make install 时在虚拟根目录里的安装位置,通常用标准的 %{_prefix} 宏,它代表 /usr。这里指定后,用户可以在 rpm 安装阶段重新指定安装到其他位置,如 /opt,否则就不能改变安装位置。
Prefix: %{_sysconfdir} #如果软件有些文件并非都安装到 %{_prefix},那么你需要指明其他位置。例如你需要把一个配置文件放到 /etc 下面,这显然不在 /usr 下面,此时你需要前方这种写法。%{_sysconfdir} 宏代表 /etc。这里指定后,用户可以在 rpm 安装阶段重新指定这些文件安装到其他位置,如 /opt/etc,否则就不能改变安装位置。[注3]
#BuildArch: noarch #编译目标处理器架构,就是今后软件运行时的 CPU 类型。noarch 是不指定架构,通常标准默认是 i386,定义在了系统的标准宏定义文件 /usr/lib/rpm/macros 里 [注2]。实际编译时可以在 rpmbuild 命令行用 --target=i686 参数,spec 里通常不写这行。
#Requires:  libpng-devel >= 1.0.20 zlib libpng #这里罗列所有安装本包时需要先行安装的包(依赖包),通常软件会依赖这些包里的一部分文件。可以分成多行来写。如果这里不写明依赖包,打包时系统仅仅会自动把具体依赖的 .so 文件写进 rpm 包,而不会注明这些文件属于哪些软件包,这会对用户造成困惑,因为他们很难知道这些文件属于哪些软件包。注意:如果使用 >= 这样的符号,务必在其两边各保留一个空格 [注6]
#Obsoletes: #这里列出的软件包都是“陈旧”的,当升级安装本包的时候,这里列出的包都会被自动卸载!
NoAutoReq: %{_noautoreq} #这里的意思是禁止自动查找对 spec 文件头部预定义的 _noautoreq 宏里定义的两个软件包[perl(Plot)  和 perl(WidgetDemo)]的依赖关系,通常对于 prel 模块需要这样处理。因为即便你在 Requires 字段指明了本包所依赖的包含这两个模块的那些软件包,安装 本包的时候系统仍然会直接查找是否安装有这些 perl 模块,而不会查找那些包含这两个模块的软件包是否已经安装。
#PreReq: loop #如果在 %pre 字段执行的脚本需要使用一些特殊命令,例如 loop,你需要在此标明
#Requires(pre): loop #这是上面一行的另一种写法,依此类推,还有其他几个类似的关键字:
#Requires(post)
#Requires(preun)
#Requires(postun)
#Autoreq: 0  #这里使用 0 关闭了自动标注本软件包需要的依赖关系的功能,使用 1 或者不写此行(默认)就是开启自动标注依赖关系的功能。自动依赖校验只会通过 pkgconfig 找出依赖的 .so 文件,而绝对不是软件包!可以通过命令反查生成的 rpm 包所依赖的这些 .so 文件属于哪个包,再把这些依赖的包的名称写进 spec,最后重新编译就行了。
#Autoprov: 0 #这里使用 0 关闭了自动标注本软件包提供的依赖关系的功能,使用 1 或者不写此行(默认)就是开启自动标注依赖关系的功能
#Autoreqprov: 0 此关键字兼具上述两条的功能
#BuildRequires: libpng-devel >= 1.0.20 #这是编译时依赖的包
#Provides: lda #这里标注本软件包提供的某些特定功能。例如 sendmail 在没有本地递送代理 [local delivery agent (lda)] 时不能工作,而你的软件包恰好提供了这一功能,你需要在此标明。而在 sendmail 的 spec 里你需要写明:Requires: lda
Packager: Tony Black <tony@magiclinux.org> #这是打包者的信息

%description 软件的详细说明
This is the description...

#%description -l zh_CN 中文软件说明(如果有必要。不建议使用,因为如果系统里的默认编码与此处不符,会导致显示乱码。例如:我们使用 GBK,如果这里的中文是 UTF-8 编码,在 kpackage 里就会显示乱码,但是 synaptic 可能能够正确显示,但需要把 zh_CN 改为 zh_CN.UTF-8 )

[spec 文件体部]

%prep #下面开始预处理

%setup -n %{name}-%{version} #到这里,系统把源码包从 /usr/src/mBuild/SOURCES 解压缩到 /usr/src/mBuild/BUILD/%{name}-%{version} ,并转到那里展开的压缩包目录(%{name}-%{version} )里,以便完成打补丁等准备工作,最后还要退回到 /usr/src/mBuild/BUILD 目录下。-n 后面指定的参数代表 tar 包展开后生成的目录名,一般 -n %{name}-%{version} 是不需要的,除非 tar 包名称和展开后生成的目录名不符,或者你要处理多个 tar 包。如果打包时报告找不到 ./configure 说明 -n 参数指定的目录不对,或者软件源代码目录里没有 configure 脚本 (比如你的代码是从 cvs 里 commit out 出来的,你需要进行一些准备工作,比如通过运行 autogen.sh 脚本来自动创建 configure 脚本。这具体看是哪个软件,不同软件有不同的方法)。如果有多个源代码包要编译,用“-n 名称”指定多个 setup 字段。

%patch #这里开始打补丁。例如 %patch0 -p1,%Patch2 -p1 -b .xxx.patch 这里 %patch0 是对第一个补丁的引用,%Patch2 -p1 -b .xxx.patch 表明第二个补丁是压缩包,要先解压缩,再打补丁。 -p1 是 patch 命令的常用参数,代表忽略 patch 时的第一(顶)层目录。(为什么?因为创建补丁时两个比照的目录或者文件名肯定是不同的。参见[注5])

%configure #系统重新进入 /usr/src/mBuild/BUILD/%{name}-%{version} 执行 configure 脚本进行配置,然后返回  /usr/src/mBuild/BUILD 目录下。%configure 是 rpm 定义的标准配置宏,含义很复杂,但绝对标准。具体含义参见 [注2]。非标准写法:
CFLAGS="$RPM_OPT_FLAGS" \
CXXFLAGS="$RPM_OPT_FLAGS" \
./configure --prefix=%{_prefix}
或者:
CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{_prefix}

%build #开始构建包。系统重新进入 /usr/src/mBuild/BUILD/%{name}-%{version} 执行 make,然后返回  /usr/src/mBuild/BUILD 目录下。
make  %{?_smp_mflags} OPTIMIZE="%{optflags}" #这是 make 命令,其两个参数的含意是:
%{?_smp_mflags} 如果系统里定义了make 的并行编译参数,则使用这个参数。例如: -j2 表示 make 同时执行两个文件的编译操作。如果你使用多个 CPU 或者非单核 CPU,这个参数可以明显提高编译速度,但是这里指定的数字不宜超过你的 CPU 内核数量+1。
OPTIMIZE="%{optflags}"  如果系统里定义了 gcc 的优化参数,则在软件默认优化参数的基础上追加使用这里指定的优化参数。例如: -O2 -g -pipe 表示使用 gcc 第二优化级、为调试工具 GDB 提供额外的支持信息、使用管道而不是临时文件以便加快编译速度。
这两个参数具体定义在:/usr/lib/rpm/mBuild/macros 里。

%install #下面开始将编译好的软件安装到虚拟的根目录。系统重新进入 /usr/src/mBuild/BUILD/%{name}-%{version} 执行 make install,然后返回  /usr/src/mBuild/BUILD 目录下。
rm -rf $RPM_BUILD_ROOT #先清理安装目的地——虚拟根目录

%makeinstall #这是 rpm 定义的标准的安装宏,含义很复杂,但绝对标准。具体含义参见 [注2]。
非标准写法: make DESTDIR=$RPM_BUILD_ROOT  install 或者 make prefix=$RPM_BUILD_ROOT  install
注意:并非所有情况都支持 DESTDIR,有时必须使用 prefix 参数。比如遇到某些不规范的 Makefile 只含有 prefix 参数。另一些时候,某些拙劣的作者甚至采用了硬编码形式直接将文件安装的绝对路径手工写入了 Makefile,这种情况下 DESTDIR 和 prefix 参数都无效,需要我们手工修改 Makefile!

%clean #清扫战场,打包完成后删掉编译过程产生的中间文件、目录
[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf "$RPM_BUILD_ROOT"  #如果虚拟根目录不是真正的 / 目录,就删除掉。这里将软件打包时安装到的虚拟根目录删掉。通常直接用 rm -rf $RPM_BUILD_ROOT 就很安全。
rm -rf $RPM_BUILD_DIR/%{name}-%{version} #将 /usr/src/mBuild/BUILD/软件名称-版本号 目录删掉。这里是编译过程生成的中间文件。注意:这里的 %{name}-%{version} 必须和 %setup -n %{name}-%{version} 指定的相应内容保持一致。

按照我们在 /usr/lib/rpm/macros 里的定义,通常
%clean
rm -rf $RPM_BUILD_ROOT
rm -rf $RPM_BUILD_DIR/%{name}-%{version}
也可以写成
%clean
%{__rm} -rf %{buildroot}
%{__rm} -rf %{_builddir}/%{name}-%{version}

%pre #rpm 包安装前执行的脚本。

%post #rpm 包安装后执行的脚本。
/sbin/ldconfig #这里举例,ldconfig 用于安装库文件后进行“注册”,这么说不准确,但好理解。这里可以是任何 sh 脚本。

%preun #rpm 包卸载前执行的脚本。

%postun #rpm 包卸载后执行的脚本。
if [ "$1" = "0" ]; then
/sbin/ldconfig
fi
或者写作:
if [ $1 -eq 0 ]; then
/sbin/ldconfig
fi

★★★
如果您的包作为系统包的一部分,需要通过发行版本的安装程序安装的话,不要指望能使用内嵌脚本执行任何重要操作,包括创建任何文件。因为安装程序的运行环境不可能完全等同于安装后实际运行时的系统环境,某些操作是不能正确执行的。一般,安装程序在安装后期会执行一些补偿操作,来完成诸如库文件和内核模块注册、初始环境设置等操作,所以你不必担心库文件安装不正确。
具体举例来说:最常见的 %post 小节的脚本在系统初始化安装阶段就很可能得不到正确执行。因为安装程序所处的小 linux 系统环境不同于安装后的真实系统,而此时的真实系统还不完整,即便立即 chroot 切换入真实系统也未必能正确执行,况且安装一个 rpm 时其内嵌脚本不可能等你切换入真实系统才执行。所以除了 ldconfig 之类的命令外,尽可能不要使用内嵌脚本,特别是不要创建任何文件,比如配置文件或者 desktop 文件,所有这些都必须静态创建好。您可以在 install 字段完成这些创建工作,也可以事先创建好,并把它们作为 source 的一部分。
既然内嵌脚本在系统初始化安装阶段都是不可靠的,那么上文提到的 ldconfig 又有什么作用呢?原来,通常安装程序都会在安装包结束后,自动创建 /etc/ld.so.conf,并且执行一次 ldconfig,从而完成对所有库文件的注册。如果这个包是在系统安装后额外安装的,那么所有的内嵌脚本都应该被这个真实的系统正确执行,此时的 ldconfig 就会被正确执行。


★★★
我们可以看到,在 postun 小节定义的脚本里多出来一个 if 判断语句,这是干什么用的呢?这里的 $1 是什么意思呢?原来 rpm 相当强大,以其包升级操作为例,它会这样执行:
新包的 pre 脚本
安装文件
新包的 post 脚本
旧包的 preun 脚本
删除安装过程没有覆盖的全部文件,但不包括重要配置文件
旧包的 postun 脚本
如果有“触发”脚本,实际操作会更复杂。
通常在 postun 脚本里我们执行的都是一些清扫垃圾的操作,比如删除程序额外创建的临时文件、配置文件(我们建议通过交互式方式执行此操作,询问用户是否删除程序运行时创建的配置文件,因为有些配置文件用户未必想要删除)。卸载软件包没问题,但是升级操作就可能造成灾难性后果:刚刚安装好的软件包被删掉了一部分文件。为了避免这样的局面,rpm 提供了一种信号机制,不同操作会返回不同信号,并且把它存放到默认变量 $1 当中:0 代表卸载、1 代表安装、2 代表升级。这样我们就可以通过判断 $1 的值来决定怎样执行脚本。上面的脚本就表示:仅当执行卸载操作的时候才执行 /sbin/ldconfig 命令。

★★★
在 rpm 内嵌脚本里的重要命令需要使用完整的或称绝对路径,例如 /sbin/ldconfig 等,这是为了确保正确的命令被执行。由于用户自己可能重新定义了 PATH 环境变量,导致其他位置上的 ldconfig 可执行程序的搜索路径先于 /sbin/ldconfig,可能产生难以预料的后果。


%files #本节定义哪些文件、目录将被打进 rpm 包里。如果你认为哪些文件不必打进 rpm 包里(一般是 debug、src 和 devel 文件、目录),你就不要列在这里,或者使用 %exclude 关键字指明哪些文件不打进 rpm 包里。你甚至可以在 spec 文件的其他字段安装或者删除一些特定的文件,这就是比较复杂的技术了。但是如何才能知道到底软件向系统内安装了哪些目录和文件呢?这个问题有点复杂。参见[注4]。注意:此处系统的当前路径指的就是虚拟的根目录。所以虚拟的根目录路径(例如 /var/tmp/cce-0.51-1mgc-root/)不要写在这里。应该直接用类似 %{_bindir} 的宏(表示 /usr/bin ) 来指定包含的目录,也可以单独指定一个或一组文件。
%defattr(-,root,root) 指定包装文件的属性,代表(mode, owner, group) 即文件属性、文件属主、用户群组,- 代表属性为默认值,对文本文件是八进制数0644,可执行文件是 0755。下面指定具体哪些目录或文件将被打进包里,很多宏的定义要看你的具体系统 [注2]
#下面具体指定打进 rpm 包的文件、目录,例如:
%dir %{_datadir}/tst/
%dir %{_datadir}/tst/plugin/
%{_bindir}/tst
%{_datadir}/tst/plugin/libtest.so
"/usr/share/tst/plugin/*.png"
%{_datadir}/tst/plugin/test.plugin
%config %{_datadir}/tst/tst.conf

%exclude /usr/src #如果上面列出的目录里包含一些你不想要的东西,比如源代码(src),你可以在此将他们“抠”出去。这里指定具体哪些目录或文件将被排除在包外,即不打进包,一般是 debug、src 和 devel 文件、目录。

%files devel  #这里分出 devel 包,主要包含与软件开发相关的头文件与库文件包。
%defattr(-,root,root)
%{_includedir}

[code:1]
这是 %files 小节的最简单写法:
%files
%defattr(-,root,root)
%{_sysconfdir}    #如果您提供了位于 /etc 的设置文件,需要这行
%{_prefix}    #将安装目标目录里的所有东西都打进 rpm 包,除了 %exclude 列出的内容
%exclude %{_prefix}/*/debug*    #除掉所有的 debug 调试文件*
%exclude %{_prefix}/src    #除掉所有的源代码文件*
*注意:如果没有这样的文件、目录,则打包过程会出错,只要在 %exclude 前方加上 # 注释掉这行就行了。
[/code:1]

★★★
在较大程序的打包过程中如果 spec 档中有打包前未发现的错误,打包过程中断是否有办法补救呢?
打包过程中断是很常见的现象。并非没有办法补救,我们曾经用这种偷懒的方法对付需要反复编译巨大软件包的困境。但是也发现有时会造成一些难以发现,或者难以解释的错误。如果你在 make 阶段就出了错,我们建议重头来过,不建议使用这种方法,因为这是非常不可靠的。所以还是不要偷懒为好。

如果编译已经通过,但是在分包过程中中断,单纯为了验证 rpm 的分包是否有错,可以这样做:
1、不删除编译产生的所有文件(即 mBUILD 目录里的东西),并删除先前生成的虚拟根目录(即 /var/tmp/软件名称-版本号 目录)
2、建立一个当前 spec 的副本,删除其中 prepare 小节以后和 install 小节以前的部分,对这个 spec 运行建包命令,即可跳过所有编译过程,直接安装、打包。


[spec 文件尾部]

%changelog #下面是标准变更日志,日期一定不能写错,只能是英文格式。建议将邮件地址中的 @ 符号替换成 {at} 或者其他符号,而 . 替换成 {dot}。这是为了避免你的邮件地址被网络上各种垃圾邮件发送程序识别出来,从而使你的邮箱爆满。如下所示:

* Sun Oct 31 2004  Tony Black <tony@magiclinux.org>
- modify the spec file and rebuild

* Sun Oct 03 2004  Lover <root {AT} Lover {dot} org>
- initial spec file created by autospec ver. 0.8 with rpm 3 compatibility




-----------------------------------------------------------------------
把源代码压缩包、补丁等等放到 /usr/src/mBuild/SOURCES 目录里,把 spec 文件放到 /usr/src/mBuild/SPECS 目录里,在 SPECS 目录里以 root 身份执行:

rpmbuild -ba --target=i686 xxx.spec

即可在  /usr/src/mBuild/RPMS/i686 里生成 rpm 包,一般还会有 debug info 包,对普通用户基本没什么用。在  /usr/src/mBuild/SRPMS 里则生成 src.rpm 包。

如果只想生成二进制包,使用下面命令:

rpmbuild -bb --target=i686 xxx.spec

如果只想生成源代码包,使用下面命令:

rpmbuild -bs --target=i686 xxx.spec

注意:出于安全和灵活操作的考虑,晚近的 rpm 设置都已不再采用 /usr/src 作为 rpm 构建目录,转而采用在用户的家目录下创建一个以 . 开头的隐含目录作为 rpm 构建目录,比如 MagicLinux 从 2.5 版开始就是这样。

★★★
如何避免生成 debuginfo 包?
打包过程默认会创建 debuginfo 包。大部分情况下,打包的软件已经是稳定版,我们并不需要调试程序,而普通用户也没有能力调试,所以每次都生成 debuginfo 包就显得没有太大必要了。我们可以创建一个自己家目录下的 rpm 配置文件 .rpmmacros,写入一行定义来禁止打包过程生成 debuginfo 包:
echo '%debug_package %{nil}' >> ~/.rpmmacros




注1
rpm 软件包系统标准分组在这里:
/usr/share/doc/rpm-4.3.2/GROUPS

大致内容如下:
Amusements/Games
Applications/Archiving
Applications/Communications
Applications/Databases
Applications/Editors
Applications/Emulators
Applications/Engineering
Applications/File
Applications/Graphics
Applications/Internet
Applications/Multimedia
Applications/Productivity
Applications/Publishing
Applications/System
Applications/Text
Development/Debuggers
Development/Languages
Development/Libraries
Development/System
Development/Tools
Documentation
System Environment/Base
System Environment/Daemons
System Environment/Kernel
System Environment/Libraries
System Environment/Shells
User Interface/Desktops
User Interface/X
User Interface/X Hardware Support

注2
各种宏定义在系统这里:
/usr/lib/rpm/macros

通常我们要对其适当优化一下,修改如下(左侧是宏名,右侧是相应的定义,后方以井号开头的是我们提供的注释说明):
%vendor        MGC Group
%optflags      -O2 -g -pipe   #这里 -O2 代表采用第二优化级,通常不要使用 -O3,因为那样编译得到的二进制文件体积会增大,但是性能能否改善却是不确定的;-g 表示生成的二进制包提供额外的调试信息,方便开发者除错,如果不需要调试软件,可以不使用这个参数;-pipe 表示编译过程使用内存中的管道而不是临时文件保存中间数据,从而提高了编译速度。
%_arch               i686   #这里相当于 rpmbuild 的参数 --target=i686 指将来运行软件包时的环境
%_build_arch      i686   #这里相当于 rpmbuild 的参数 --build=i686 指建包时的环境(你的机器),这可以比默认的 i386 快一些。

常见宏定义:
   %_prefix  /usr
    %_exec_prefix      %{_prefix} #展开后是 /usr
    %_bindir               %{_exec_prefix}/bin #展开后是 /usr/bin
    %_sbindir             %{_exec_prefix}/sbin #展开后是 /usr/sbin
    %_libexecdir         %{_exec_prefix}/libexec #展开后是 /usr/libexec
    %_datadir             %{_prefix}/share #展开后是 /usr/share
    %_sysconfdir         %{_prefix}/etc #展开后是 /usr/etc 但是在 magic linux 里 %_sysconfdir 代表的是 /etc,这是由另一个被发行版特殊定制的文件决定的!
    %_sharedstatedir %{_prefix}/com #展开后是 /usr/com
    %_localstatedir     %{_prefix}/var #展开后是 /usr/var
    %_libdir                 %{_exec_prefix}/lib #展开后是 /usr/lib
    %_includedir         %{_prefix}/include #展开后是 /usr/include
    %_infodir              %{_prefix}/info #展开后是 /usr/info
    %_mandir             %{_prefix}/man #展开后是 /usr/man 在 magic linux 里 %_mandir 代表的是 /usr/share/man

***注意***
    仅当你使用标准配置宏 %configure 的时候,文件才会被指定到上述标准位置上。否则,如果你在 %file 字段使用这些标准宏就可能出错,系统可能报告找不到这些文件,因为它们可能默认安装到了别处。
*********

已安装的 RPM 包数据库在这里:
/var/lib/rpm/

注3
软件包安装时用参数 --prefix=<dir> 重新指定安装位置。例如:
软件包默认安装到 /usr 下,你希望安装到 /opt/usr 下,则使用命令:
rpm -ivh --prefix=/opt/usr xxx.rpm
如果你还有一些文件默认安装到 /etc 下,你需要安装到 /usr/etc 下,则要改用参数 --relocate=<old>=<new>,例如:
rpm xxx.rpm --relocate=/usr=/opt/usr --relocate=/etc=/usr/etc

如何知道 rpm 软件包到底向系统什么位置安装了什么文件呢?,你可以使用下面的命令查询:
rpm -qpl xxx.rpm

注4
任何没有被列在 %files  字段的目录或文件都不会被自动打进 rpm 包里。反之如果你在任何 %files 字段指定了虚拟根目录里并不存在的东西,系统就会报错,包括用 %exclude 排除的东西也是这样。通常我们只需要在 %files  字段指定所有顶层目录就可以了。若要了解软件到底向系统内安装了哪些目录和文件,你可以采取下列办法:

1. 在 %files 字段内只写进 %{_prefix}:
%files
%defattr(-,root,root)
%{_prefix}
这样所有东西都将被打进 rpm 包。打好包之后,用如下命令查询生成的 rpm 包的目录结构:
rpm -qpl  xxx.rpm

2. 打包前手工执行配置、安装,当 ./configure 执行后,重定向安装到一个虚拟根目录里。例如(注意大小写):
./configure
make (这步可以省略,不信就试试)
make DESTDIR=/var/tmp/xxx install 或者 make prefix=/var/tmp/xxx install
然后进入 /var/tmp/xxx 目录查看里面的目录结构:
cd /var/tmp/xxx
tree

3. 打包前手工执行配置、安装,当 ./configure 执行后,查看生成的 Makefile 的 install 字段。注意:如果软件不符合 GNU 规范,可能并没有提供 configure 脚本,而是直接提供了 Makefile。这些通常都是游戏软件。这比较复杂,如果你不懂编程,可能看不懂 Makefile。

注5
补丁通常是这样创建的:
diff -Nur directory.old directory.new > xxx.patch
directory.old 代表旧源代码目录,directory.new 代表修改过的新源代码目录。

注6[NEW]
默认情况下,rpm 打包后会自动生成所依赖文件的列表,其实是调用了 ldd 命令。然后反查这些 .so 文件的 rpm 包,将它们加入依赖列表就可以了。
ldd prints the shared libraries required by each program or shared library specified on the command line.
例如在 coreutils-7.0-7mgc25.i686 这个包里包含一个文件 /bin/mkdir,这样查询它的依赖关系(需要给出文件的绝对路径):
复制内容到剪贴板
代码:
[root@MagicLinux athena]# ldd /bin/mkdir
        linux-gate.so.1 =>  (0xb770d000)
        libc.so.6 => /lib/libc.so.6 (0x49f6b000)
        /lib/ld-linux.so.2 (0x49200000)
接着反查其中一个文件的来源(同样需要给出文件的绝对路径):
复制内容到剪贴板
代码:
[root@MagicLinux athena]# rpm -qf /lib/libc.so.6 
glibc-2.10.1-2mgc25.i686
如果想做绿色软件,就要在 rpm 中包含这些依赖的 .so 文件,同时这些 .so 文件同样依赖着另一些 .so 文件,必要时也要打进 rpm 包。理论上在  postinstall 和 postuninstall 脚本里执行 /sbin/ldconfig ".so 文件所在目录" 就可以“注册”这些库文件,然后就能直接使用这些依赖的文件,而不用安装那些依赖的 rpm 包了。

[ 本帖最后由 KDE 于 2010-11-22 23:38 编辑 ]
作者: KDE    时间: 2004-10-3 23:00

这里有一个由压缩包直接创建 rpm/srpm 包的工具,但是它无法知道那些文件、目录应该被打进包里,你需要自己指定:
http://sourceforge.net/project/s ... amp;release_id=7939


下面是一个实际例子:
-------------------------------------------------------
复制内容到剪贴板
代码:
Summary:                        Challenging 2D Moto cross Platform Game
Summary(zh_CN):            富有挑战性的 2D 摩托跨平台游戏
Name:                              xmoto
Version:                           0.3.1
Release:                          1mgc
Source0:                          http://download.tuxfamily.org/xmoto/xmoto/%{version}/xmoto-%{version}-src.tar.gz
Source1:                          xmoto.desktop
Source2:                          xmoto.png
Patch0:                            xmoto-man.patch
URL:                                http://xmoto.sourceforge.net
Group:                             Amusements/Games
Group(zh_CN):                娱乐/游戏
Packager:                        Pascal Bleser <guru@unixtech.be>, kde <athena_star {at} 163 {dot} com>
Distribution:                     Magic Linux 2.1
License:                           GPL
BuildRoot:                        %{_tmppath}/%{name}-%{version}-%{release}-buildroot-%(%{__id_u} -n)

Requires:                         SDL, libgcc, libstdc++, libogg, libvorbis, lua, ode
BuildRequires:                 gcc-c++, libstdc++, libstdc++-devel
BuildRequires:                 SDL_mixer-devel, SDL_ttf-devel
BuildRequires:                 curl-devel
BuildRequires:                 ode-devel
BuildRequires:                 lua-devel >= 5.0
BuildRequires:                 libGL-devel
BuildRequires:                 libGLU-devel
BuildRequires:                 libjpeg-devel
BuildRequires:                 libpng-devel
BuildRequires:                 bzip2-devel
BuildRequires:                 sqlite-devel

%description
X-Moto is a challenging 2D moto cross platform game, where physics play an all
important role in the gameplay. You need to control your bike to its limit, if
you want to have a chance finishing the more difficult of the challenges.

%description -l zh_CN
X-Moto 是一个极富挑战性的 2D 摩托车跨平台游戏。在游戏中,您可以亲历
所有重要角色。如果您想有机会完成更高难度的挑战,您必须竭尽全力控制
您的摩托车。

%prep
%setup -q
%patch0
#fix encoding
sed -i 's/\r//' src/xmscene/Camera.cpp
sed -i 's/\r//' src/xmscene/Camera.h

#fix permissions
chmod 644 src/xmscene/Camera.*

%build
export LDFLAGS=-L%{_prefix}/X11R6/%{_lib}
%configure --with-enable-zoom=1
%{__make} %{?_smp_mflags}

%install
%{__rm} -rf "%{buildroot}"
%{__make} DESTDIR="%{buildroot}" install

# Install desktop file and icon
%{__mkdir_p} "%{buildroot}/usr/share/applications"
%{__install} -m 0644 "%{SOURCE1}" "%{buildroot}/usr/share/applications/"
%{__mkdir_p} "%{buildroot}/usr/share/pixmaps"
%{__install} -m 0644 "%{SOURCE2}" "%{buildroot}/usr/share/pixmaps/"

# Locale files
%find_lang %{name} %{name}.lang

%clean
%{__rm} -rf %{buildroot} %{_builddir}/%{buildsubdir}

%files -f %{name}.lang
%defattr(-,root,root)
%attr(0644,root,root) %doc AUTHORS ChangeLog COPYING NEWS README
%{_bindir}
%{_datadir}/xmoto
%{_datadir}/applications/xmoto.desktop
%{_datadir}/pixmaps/xmoto.png
%{_mandir}

%changelog
* Thu Jul 12 2007 kde <athena_star {at} 163 {dot} com> - 0.3.1-1mgc
- update to release 0.3.1

* Thu Dec 29 2005 kde <jack@linux.net.cn> 0.1.10-1mgc
- update to release 0.1.10


* Sat Oct 29 2005 kde <jack@linux.net.cn> 0.1.6-1mgc
- port to Magic Linux 2.0

* Thu Oct 13 2005 Pascal Bleser <guru@unixtech.be> 0.1.6-1
- new upstream version

* Mon Oct  3 2005 Pascal Bleser <guru@unixtech.be> 0.1.4-1
- new package
几点注意:
1、要求必须翻译 spec,翻译必须符合 i18n 规范,统一使用 gb18030 编码和 locale;
2、rpm 标准分组信息参见上文;
3、注意例子里的标准构建根和 clean 小节的写法;
4、所有非命令行程序,都必须给出符合 magic 规范的菜单文件,即 desktop 文件:
(a) 提供简、繁体中文菜单,这样就能良好支持繁体中文区的用户,具体就是翻译 desktop 文件
(b) desktop 文件必须使用 utf-8 编码
(c) desktop 文件的分类(Categories)参考系统里其他相似类别的文件,例如:游戏统一写成 Categories=Application;Game;

例如 bzflag.desktop:
复制内容到剪贴板
代码:
[Desktop Entry]
Encoding=UTF-8
Name=BZFlag
GenericName[zh_CN]=铁甲威龙
GenericName[zh_TW]=鐵甲威龍
Comment=A multiplayer 3D tank battle game
Comment[zh_CN]=一个多人 3D 坦克战斗游戏
Comment[zh_TW]=一個多人 3D 坦克戰鬥游戲
Exec=bzflag
Icon=bzflag.xpm
Terminal=false
Categories=Application;Game;
Type=Application
繁体中文有自己的特定用语,有时和简体中文不一样,比如大陆叫“宏”,台湾叫“巨集”,载入“配置”,台湾叫载入“组态”,我们叫“文件”和“文档”,台湾刚好相反,管文件叫文档,管文档叫文件,这个比较麻烦,我也只有一个不完善的繁体--->简体转换脚本,没有反向的。(参见置顶帖)。

[ 本帖最后由 KDE 于 2009-8-29 14:22 编辑 ]
作者: KDE    时间: 2004-10-3 23:13

参考文献:

1. http://www-900.ibm.com/developerWorks/cn/linux/management/package/rpm/part1/index.shtml
2. http://www-900.ibm.com/developerWorks/cn/linux/management/package/rpm/part2/index.shtml
3. http://www-900.ibm.com/developerWorks/cn/linux/management/package/rpm/part3/index.shtml
4. /usr/share/doc/rpm-4.3.2/
5. http://www.rpm.org/RPM-HOWTO/build.html#SCRIPTS
作者: sejishikong    时间: 2004-10-4 09:31

%exclude宏好像ML中竟然没有。
作者: lovewilliam    时间: 2004-10-4 11:15

%exclude

ML有的。
作者: sejishikong    时间: 2004-10-4 12:56

没查到啊。
作者: lovewilliam    时间: 2004-10-4 17:02

晕,明明就是有嘛,

如果没有那rpm怎么做的?
作者: Fujinsan    时间: 2004-10-4 22:00

有几个问题想请教:
1、怎样增加一个文件到rpm包中?例如:把libqq.so集成到gaim的rpm中;
2、怎样在安装时自动修改某个配置文件?例如:安装aaa.rpm时修改/etc/bbb.conf第32行或者某个指定的字段?
3、怎样实现在安装aaa.rpm时自动检查是否有所依赖的libbbb.so、如果没有就自动从%URL字段所指的位置下载libbbb.so的包?
作者: KanKer    时间: 2004-10-4 23:04

1、在spec中加入一个source1:libqq.so
在%install段,用install -m 755 %{SOURCE1} $RPM_BUILD_ROOT/要指定的目录。
2、在spec的%post段,用echo或grep之类的脚本实现对配置文件的修改。
3、在spec的%pre段,加入依赖检查及文件下载安装脚本。
作者: KDE    时间: 2004-10-5 00:17

[quote:0365843587="sejishikong"]%exclude宏好像ML中竟然没有。[/quote]

%define
%description
%prep
%setup
%install
%clean
%files
%changelog
这些在 /usr/lib/rpm/macros 都没有定义,不是照样使用?难道哪个发行版定义了?
作者: sejishikong    时间: 2004-10-5 09:21

噢,是我不对了,因为我在写SPEC的时候,这个exclude不像其它的宏会变颜色,我就以为没有呢。
作者: 京儿    时间: 2004-10-5 21:21

谢谢啊!正是我需要的,置顶加精!
作者: wjping119    时间: 2004-10-10 22:55

我就觉得rpm包不如tgz包好用.看看有多麻烦!!!
作者: lanche    时间: 2004-10-10 23:00

提示: 作者被禁止或删除 内容自动屏蔽
作者: Fujinsan    时间: 2004-10-11 00:37

rpm的机理确实比tgz复杂一些,但对于用户则更简易一些。

其实目前存在的几种软件包格式都有一定的不足:
1、tarball格式对于开发者来说比较容易理解,只要按照规范,做起来也容易,但对于用户来说却并不是最简单的;
2、rpm和deb都功能强大,deb在解决倚赖性方面甚至更胜一筹,但制作起来都比较麻烦,对于用户也不是完全那么简易的。

DOS/Windows下,过去没有统一的软件包格式,一般都是分为压缩包直接拷贝和自行开发安装程序,最后发展出多种安装程序制作工具。微软受到rpm和deb的启发后开发了msi软件包格式,逐渐将以前的安装程序制作工具整合为一种统一的类似rpm的格式,从而使安装包的制作和使用更加简便。

解决软件包问题是Magic Linux推广普及的一个重要关口,解决这个问题只需要做两件事情:
1、开发使软件包制作更加简易的工具。这个工具应解决软件包维护、集成套件打包、自开发软件打包等问题,让即使是初学者、刚加入ML项目的朋友也能够完成软件包的制作工作。
2、开发适用于所有Linux软件包格式的用户工具。将现有的rpm管理工具、deb管理工具、tarball管理工具等软件管理工具集成起来,建立统一的软件包倚赖关系树,同时解决单独的软件包管理工具的缺陷和不足之处。

以上是我的一点拙见,对彻底解决感兴趣的朋友不放尝试一下。
作者: KDE    时间: 2004-10-11 23:44

[quote:32b0d82c16="wjping119"]我就觉得rpm包不如tgz包好用.看看有多麻烦!!![/quote]
如果你是指开发者,那是因为你习惯了不为用户考虑软件包依赖关系和用户易用性这种偷懒的做法。如果你的开发环境具有别人没有的软件包,别人是猜不出来你的软件包到底依赖什么的,要使你的包运行起来,简直是一场噩梦。开发者偷懒,就意味着普通用户无穷无尽的麻烦。不要把普通用户当成高手或者系统管理员。
如果你是指普通用户,那就丝毫道理也没有。开发者尽量把一切问题都预先考虑进去,自然会带给普通用户舒适。如果说 rpm 不如 win 下的安装程序简单易用,倒还情有可原,毕竟使用 rpm 还需要手工输入命令行。
对于用户而言,deb 和 rpm 都有很好的工具解决依赖关系,前提是开发者预先精心做好软件包。这其实是开发者的本分。
作者: asmcat2000    时间: 2004-10-23 14:20

不错,解决了对RPM认识的细节问题,问一下:已安装的RPM包总 数据库在/etc下哪个文件?
作者: KanKer    时间: 2004-10-23 18:06

/var/lib/rpm/下面。
作者: suowei1979    时间: 2004-10-27 17:00

good
作者: yongq    时间: 2004-11-7 08:43

[quote:ac4d017423="Fujinsan"]rpm的机理确实比tgz复杂一些,但对于用户则更简易一些。

其实目前存在的几种软件包格式都有一定的不足:
1、tarball格式对于开发者来说比较容易理解,只要按照规范,做起来也容易,但对于用户来说却并不是最简单的;
2、rpm和deb都功能强大,deb在解决倚赖性方面甚至更胜一筹,但制作起来都比较麻烦,对于用户也不是完全那么简易的。[/quote]
deb 的制作比 rpm 复杂很多, rpm 只要编辑一个 .spec 文件就可以了, deb 则是把相应的文件放在一个叫 debian 的目录下. rpm 的 source package 就一个 .src.rpm 文件, 而 deb 的 source package 通常会包含很多文件. 这两方面的比较使得 rpm 和 deb 从表面上就显得风格迥异.

这些差异的出现或许有其偶然因素, 不过应该都有各自的理由, 我本来也嫌 deb 的 source package 包含太多的文件而感到不可思议:"搞这么多文件, 别人复制起来可真是麻烦!", 但事实并非我原先想象的那么简单, Debian 的开发者分布于全球各处, 合计有上千人, 他们都需要把制作好的 source 和 binary 包送到 Debian 的那一两台 server 上, 有些人的网速很慢, 传一次不容易, 如果你每次为一个小修改而上传整个 source 包就很浪费事件了, 这样 deb 的 source package 就会以一个 .orig.tar.gz 和 一些 patch 的形式出现, 当每次 revision 后只要把 patch 部分上传就行了.

再看 deb 的制作, 前面说过 deb 需要写很多个小文件, 不象 rpm 只要写一个 .spec 即可. rpm 格式的 build 基本上由 rpm 这一个程序主导(好像现在又有了 rpmbuild), 而 deb 不同, deb 主要依靠一个名为 rules(由包维护者自己提供) 的可执行文件, 它的参数是一个目标的名字, 比如 build, configure, clean 和 binary 等. 你可能想不到的是: 通常这个 rules 文件是一个 Makefile, deb 通过 make 对目标的依赖性来方便地控制 build 的流程(这给调试节省了宝贵的时间). 而且由于编写这个文件的人是你自己, 所以控制权完全在你自己手里. 在此, rpm 和 deb 的设计体现出很不相同的哲学.

Debian 是一个复杂而严谨的系统, 为了规范设计, Debian 提供了很多 Policy http://www.debian.org/devel/. 我没见过哪个 RPM based 的系统提供这些东西, 当然这跟包格式本身并不相干, 不过在 deb 包在制作出来的时候, 有相关的程序会被调用来检测 deb 包有那些不符合 Policy 之处.

另外, 你要是做过 deb 的话, 会发现 Debian 里有 tons of 相关开发工具, 如果你熟悉了这些工具, 制作 deb 就变得简单多了. 当然, 要做一个高质量的完全符合 Policy 的 deb, 你还需要好好下点工夫. 我想, 其实最对一条对做任何事情都成立.
引用:
DOS/Windows下,过去没有统一的软件包格式,一般都是分为压缩包直接拷贝和自行开发安装程序,最后发展出多种安装程序制作工具。微软受到rpm和deb的启发后开发了msi软件包格式,逐渐将以前的安装程序制作工具整合为一种统一的类似rpm的格式,从而使安装包的制作和使用更加简便。

解决软件包问题是Magic Linux推广普及的一个重要关口,解决这个问题只需要做两件事情:
1、开发使软件包制作更加简易的工具。这个工具应解决软件包维护、集成套件打包、自开发软件打包等问题,让即使是初学者、刚加入ML项目的朋友也能够完成软件包的制作工作。
2、开发适用于所有Linux软件包格式的用户工具。将现有的rpm管理工具、deb管理工具、tarball管理工具等软件管理工具集成起来,建立统一的软件包倚赖关系树,同时解决单独的软件包管理工具的缺陷和不足之处。

以上是我的一点拙见,对彻底解决感兴趣的朋友不放尝试一下。

作者: ygw_ycf    时间: 2004-11-13 08:31

http://yynet.w28.west263.cn/dzds/root/shownews1.asp?NewsID=601
作者: KDE    时间: 2004-11-26 21:54

更正了一处重要错误,对不起大家。
作者: chaobill    时间: 2004-12-3 20:18

对于我来说,要安装一个软件,有可能用到的库有三种
系统库,通用库,私有库

对于一个软件的更新,无非是
添加文件,替换文件,删除文件

对于一个软件的卸载
是否删除通用库,是否删除用户资料

/usr/bin 下挤了所有软件是很笨的想法
我曾从a开始运行了几个可执行的文件,好几个都是Demo
一个软件就应该有它的目录
作者: KanKer    时间: 2004-12-3 22:09

如果一个软件就有一个软件的目录,那控制台下的命令自动提示功能就没用了。至于每个软件的私有库本来就是放在其各自目录下的。
作者: 碧轩    时间: 2004-12-16 02:56

哈,受益非浅,谢谢了!
作者: baif    时间: 2005-1-28 17:28     标题: 关于关键字epoch

搞明白了,是版本控制的一个关键字。
作者: KDE    时间: 2005-3-30 06:44

更新!
作者: jiangtao9999    时间: 2005-4-13 18:44

有没有 if 语句的用法?
以及其他语句的是用方法~~
作者: KDE    时间: 2005-4-20 07:11

[quote:2e4c4d2e92="chaobill"]对于我来说,要安装一个软件,有可能用到的库有三种
系统库,通用库,私有库

对于一个软件的更新,无非是
添加文件,替换文件,删除文件

对于一个软件的卸载
是否删除通用库,是否删除用户资料

/usr/bin 下挤了所有软件是很笨的想法
我曾从a开始运行了几个可执行的文件,好几个都是Demo
一个软件就应该有它的目录[/quote]

典型的 windows 用户后遗症。linux 是一个庞大的多用户、多任务网络操作系统,对于熟悉她的人来说,很多情况下使用控制台会更加高效,特别是没有 x 环境的服务器。要是完全把每个软件都分开存放,将使控制台下强大的自动命令补齐功能失效!否则你必须把所有软件的私有目录加入路径,这是可怕的,不讲操作是否可行,仅仅浪费在搜索路径上的时间就足以使你精神崩溃。
作者: KDE    时间: 2005-4-20 07:30

那些强调开发自有包管理系统的人的人都是典型的程序员脑袋,整天就想着怎么搞出个新玩意来。

开发一个新的包管理系统,对用户而言,就意味着引入了新的不兼容性,因为很可能拿你的包到别的系统里根本不能用,除非你能“通吃”,至少现阶段这是不现实的。标准化的意义何在?对于那些这样做的人,你是否负责任地真正替用户考虑一下?在前人的基础上加以改进才是正确的,即便如此,对原有技术的扩展也必须做到向下兼容,这是为了保护用户既往在这个产品上的经济、智慧和体力上的投资。

对于那些使用古怪包管理工具的发行版,除非拥有庞大的软件包打包队伍,否则会使用户面临软件包匮乏的尴尬局面。这会导致什么后果,你心理清楚。

还是那句话,先进的不一定是好的,也不一定会被接受。市场是检验产品的唯一标准。
作者: yzcdf    时间: 2005-7-25 20:38

真是学习的好地方阿!
作者: iamagoodmaster    时间: 2005-9-25 22:36

怎样制作一个rpm文件,在安装的时候可以输入序号才可以安装?lanche,
作者: iamagoodmaster    时间: 2005-9-25 22:37

怎样制作一个rpm文件,在安装的时候可以输入序号才可以顺利安装,否则不能安装?
KDE,
作者: demonlj    时间: 2005-9-26 01:28

In linux i have never saw what u said before.
作者: sejishikong    时间: 2005-9-26 10:07

[quote:60fd30a47c="iamagoodmaster"]怎样制作一个rpm文件,在安装的时候可以输入序号才可以顺利安装,否则不能安装?
KDE,[/quote]
rpm可以写pre脚本,不过看不出来这么做的意义。

如果要做这类安装包,最好用installbuilder/installanywhere一类的做。
作者: KDE    时间: 2005-9-26 21:21

lanche 你好,这样做的意义不大,因为在 linux 下很容易解开 rpm 包,在 magic 下只要右键点击就可以。毕竟 rpm 是开放的。若要实现,可以在 spec 的 pre 段写入交互脚本,如果输入序列号正确,就可以安装,但是这样的脚本也是很容易查看到的,你的密码岂不是昭然若揭?使用 bin 打包格式会好一点,但我不能确定是否就真的有效。sejishikong 说的你可以试试。
作者: linuxpgy    时间: 2006-9-1 15:35

引用:
典型的 windows 用户后遗症。linux 是一个庞大的多用户、多任务网络操作系统,对于熟悉她的人来说,很多情况下使用控制台会更加高效,特别是没有 x 环境的服务器。要是完全把每个软件都分开存放,将使控制台下强大的自动命令补齐功能失效!否则你必须把所有软件的私有目录加入路径,这是可怕的,不讲操作是否可行,仅仅浪费在搜索路径上的时间就足以使你精神崩溃。
是的,很多人都有Windows的后遗症。但是我们选择使用linux决不是因为它是什么多用户网络操作系统,而是它的开放,自由,分享。我们用linux是做桌面的,不是拿来做服务器,一个月维护一次就够了,我们要每天在上面装软件,上网,打游戏,而命令自动补齐对于习惯双击的我们有何意义?那些在/usr/bin里的很多程序居然不能双击运行,太搞笑了~~让熟悉Win的用户再去玩Shell(只比dos多个命令自动补其的东西),岂不是一种倒退?
作者: linuxpgy    时间: 2006-9-1 16:03

引用:
对于那些使用古怪包管理工具的发行版,除非拥有庞大的软件包打包队伍,否则会使用户面临软件包匮乏的尴尬局面。
我觉得那些刚从Window转到linux的用户来说,rpm就是一个非常古怪的包管理工具,居然在magic上的发行包不能在mandriva上安装,真是不可思议**他们本来以为rpm会像一个setup.exe那样通吃一切,所以迷茫了,还是把linux删掉吧。究其原因就是每个rpm并不是一个完整的像setup.exe那样的安装包,只是包含了整个软件的一部分,其依赖的库由其他的rpm来安装。而依赖不只是缺少文件那样简单,找依赖库的过程会让你意志消沉,直至放弃安装为止。
所以,我有一个疑问为什么不把rpm包做大一点,包含依赖的库,即使下载时大点,也无所谓。安装的时候重复就覆盖,又不会导致系统当机。不要什么复杂的依赖检查,自己带库就行了,如果要依赖也只依赖一些比较大的(比如gtk),有些几k的还要单独搞个rpm,有时搞不到真能把人气死。
当前的各大发行版皆按这种方式发行,真不知道为什么没人打包的时候想到这一点呢?
作者: jiangtao9999    时间: 2006-9-1 20:29

引用:
所以,我有一个疑问为什么不把rpm包做大一点,包含依赖的库,即使下载时大点,也无所谓。
一个包带全部的Linux 库程序?需要 xxxM ??
作者: linuxpgy    时间: 2006-9-3 12:15

引用:
引用:

所以,我有一个疑问为什么不把rpm包做大一点,包含依赖的库,即使下载时大点,也无所谓。

一个包带全部的Linux 库程序?需要 xxxM ??
没说要带全部的依赖库啊,基本的linux 系统库,X,gtk,qt,不要自带,其他的小点的比如什么SDL,stdc++,之类带上就不用用户再去下载了,万一系统中没这些小玩意,不就装不上了吗?

这其实不是主要的麻烦,如果你的系统有SDL1.2但是你要装的程序是依赖SDL2.0,这时你也不得不去下载SDL2.0去装,同时装2个SDL先不管有没有冲突,就是没有冲突,用户也要分清版本去下载,不然下了也白下,这又添加了不少麻烦。
作者: jiangtao9999    时间: 2006-9-3 15:14

[quote:a70cfc0cb6="linuxpgy"]
引用:
引用:

所以,我有一个疑问为什么不把rpm包做大一点,包含依赖的库,即使下载时大点,也无所谓。

一个包带全部的Linux 库程序?需要 xxxM ??
没说要带全部的依赖库啊,基本的linux 系统库,X,gtk,qt,不要自带,其他的小点的比如什么SDL,stdc++,之类带上就不用用户再去下载了,万一系统中没这些小玩意,不就装不上了吗?

这其实不是主要的麻烦,如果你的系统有SDL1.2但是你要装的程序是依赖SDL2.0,这时你也不得不去下载SDL2.0去装,同时装2个SDL先不管有没有冲突,就是没有冲突,用户也要分清版本去下载,不然下了也白下,这又添加了不少麻烦。[/quote]
真正依赖问题,都不是小型的系统库,都是大型库,也就是说 SDL、stdc++ 都不是问题。
编译程序的时候用 static 就可以了,但大型库依赖根本不能解决。
Linux 的特点就是依赖库程序所提供的功能,一个程序很可能引用了系统里一半的库(这似乎也是 Linux 有统一目录树结构的原因)。而不像 Windows ,仅仅使用系统提供的库。
而且 Windows 系统的库经常好几年不更新,库之间的功能基本不重叠。Linux 经常更新系统库来增加新的程序,而且经常有好几种库提供相同的功能,让大家选择使用。
作者: linuxpgy    时间: 2006-9-4 09:26

引用:
真正依赖问题,都不是小型的系统库,都是大型库,也就是说 SDL、stdc++ 都不是问题。
编译程序的时候用 static 就可以了
编译程序的时候用 static 就可以了?对于别人已经编译好的文件就没有办法了,做rpm的时候再把别人的源码拿过来再编译太浪费时间了(而且我的机器连gcc都没有装!),我只是想做一个依赖很少或没有依赖的包。
引用:
但大型库依赖根本不能解决。
自带就行了,虽然大了很多,我打包一个mplayer+mencoder+gmplayer+win32-codecs 包含所有用到的系统库只有23M左右,看来rpm压缩算法挺好的 ,而且有些可以踢掉的,linux.so.2 glibc.so.2之类的,基本每个系统都带的吧~
引用:
Linux 经常更新系统库来增加新的程序
关键问题是怎么更新呢?如果是版本升级,比如linux.so.2--&gt;linux.so.3那正好,自带linux.so.2的话,也可以在只有linux.so.3的系统中安装 。对于小版本升级,比如linux.so.2.0--&gt;linux.so.2.1,所有的程序只是使用linux.so.2这个符号连接,如果安装的时候你提供了一个linux.so.2.0,而系统中的是linux.so.2.1,那么会不会冲突呢?这点还请高人指点.
引用:
而且经常有好几种库提供相同的功能,让大家选择使用。
正是因为这一点,所以我们才有自带库的必要!虽然好几种库提供的功能相同,但是实际编译出来的binary文件只会对特定编译时使用的库依赖,举个例子wxWidget可以跨平台编译,但是你决不能把windows下编译的binary拿到linux下用,同样wxWidget可以在gtk上编译,也可以在qt上编译,但是运行的时候gtk编译的还只能在包含gtk的系统运行,而不能那到只有qt的系统中运行。 不知道我理解的对不对,如果理解有误请指正,谢谢!

补充一点,关于rpm制作,不一定非要root身份(**很危险哦!!**),所以把打包工作防在/usr/src/mBuild/稍显不方便,查了一些资料有说到:
引用:
可以通过更改 %_topdir 设置来告诉 RPM 查找和创建不同目录集中的文件。按照下面的方法在您的主目录下创建一个名为 .rpmmacros的文件:

%_topdir /home/peter/rpm    #这里一定要是全路径,把peter换成你的用户名

这个文件会告诉 RPM:它先前在 /usr/src/redhat 下查找的所有目录应该改为在 /home/your_userid/rpm 下查找。 现在,您应该创建这样一个完整的目录树:~/rpm ~/rpm/SOURCES ~/rpm/SPECS ~/rpm/BUILD ~/rpm/RPMS ~/rpm/RPMS/i386 ~/rpm/SRPMS

~/rpm
~/rpm/SOURCES
~/rpm/SPECS
~/rpm/BUILD
~/rpm/RPMS
~/rpm/RPMS/i386
~/rpm/SRPMS
这样就方便多了,普通用户也可以方便建包了。详细请见:http://www.uplinux.com/www/dev/01/426.shtml
作者: jiangtao9999    时间: 2006-9-4 22:02

……………………………………………………………………………………………………………………

1、要是让你自己编译了,用 static 干什么?
2、要知道 linux 里,一个系统需要几百个包,自己带自己的,被携带的库重复次数 &gt;10 很容易(要知道Linux的依赖是可以用排队来形容的)。
3、重新编译,换个参数,就能导致不兼容,0.0001的版本变化,就会变换接口。
4、你带你的库,我带我的库,结果咱俩用同一种。比如 jpeg ,用的太多了,还好他不是多种库并存并且不通用。WxWiget 你是打算携带还是不带?他本来就是为了兼容而制作的类似桥接的库。
5、我喜欢用 root 制作 rpm ,kanker 他就用非 root,这个是习惯的问题,我用非 root ,一样会丟数据,用 root ,也没有 rm -fr / 过。这些东西,没有必须的,只有自愿的。
作者: linuxpgy    时间: 2006-9-5 12:16

[quote:483be91a81="jiangtao9999"]……………………………………………………………………………………………………………………

1、要是让你自己编译了,用 static 干什么?
2、要知道 linux 里,一个系统需要几百个包,自己带自己的,被携带的库重复次数 &gt;10 很容易(要知道Linux的依赖是可以用排队来形容的)。
3、重新编译,换个参数,就能导致不兼容,0.0001的版本变化,就会变换接口。
4、你带你的库,我带我的库,结果咱俩用同一种。比如 jpeg ,用的太多了,还好他不是多种库并存并且不通用。WxWiget 你是打算携带还是不带?他本来就是为了兼容而制作的类似桥接的库。
5、我喜欢用 root 制作 rpm ,kanker 他就用非 root,这个是习惯的问题,我用非 root ,一样会丟数据,用 root ,也没有 rm -fr / 过。这些东西,没有必须的,只有自愿的。[/quote]

第1条.没看懂~~太笨~~
第2条.事实上Window下的安装程序为了能装上软件,以mfc42.dll为例,重复何止10次!!!甚至可以用成千上万来形容。到目前也没有听说某某安装程序因为多带了mfc42.dll,导致系统问题~
第3条.好像没那么夸张吧,一个动态库lb.so.2(这只是个符号链接) ,不管它链接到lib.so.2.5.0 还是链接到libso.2.6.1 依赖lib.so.2的程序都是可以工作的,如果接口变的话开发者会直接升级到lib.so.3的,这点不用担心。 不信可以自己试试
第4条.基本和上面一样,就是版本确定了这个软件的功能,一般不太可能这里的lib.so.2和那里的lib.so.2完全不一样(如果不一样也是某人的原因),小版本号理论上不应该影响上层应用,还是那句话自己试试就知道了。wxWidget的问题上次没有说清楚,其实他是静态链接的,所以不用带。
第5条.我说了"不一定非要root身份",只是给大家一个建议,采不采纳是自己的事,我没强制大家非要非root打包啊??
作者: jiangtao9999    时间: 2006-9-5 21:54

1、没懂就没懂吧。
2、一个 mfc42 有多大?win里,你能需要自带几个dll?
3、我每次emerge -u world ,如果更新了 KDE 相关(主要是 arts )那么 amarok 基本上就需要重新编译,还有别的支持 arts 输出的软件,也需要重新编译才能用。
4、但问题是,你能保证 0.2 这个比较大的版本号可以等到多长时间?反正 windows 基础库的更新一般都是跟随 windows 大版本一同更新。你的程序所依赖的库都是这么整齐划一的同时更新?
5、那你说他干啥?
作者: linuxpgy    时间: 2006-9-6 09:13

1.不管是一个或几十个dll,只要是你程序需要的,而且你又不能确定目标系统肯定有的,你就必须带上,这是对用户的负责!linux的rpm包,除了带自己写so,用到的其他人的so一个不带,让用户自己去找去吧!!
2.更新kde,就需要把上面的软件重新编译?我没做过,不知道是什么原因~~也许是你的设置有问题,比如库收索路径等等~~还有你说不能用的出错信息是什么?
3.正是因为更新不能完全同时,所以才需要自带库啊!!!!VC7编译的软件基本都自带msvcrt7.dll,不然根本无法运行,因为系统中只有msvcrt6.dll!!
4.我说它的目的是告诉大家可以不用root权限来打包rpm,就这样,understand?
作者: jiangtao9999    时间: 2006-9-6 23:13

1、那会很多………………要知道 Linux 程序员很懒的………………
2、错误信息很简单:未定义的接口(英文忘了)
3、同 1 ,那会很多……………………
4、明白,原来是和上面讨论的无关。
作者: lanzinc    时间: 2006-9-7 00:26

按照所有linux都是一样的逻辑:
考虑到我的软件需要内核的oss模块,考虑到目标用户用的可能是alsa没把oss支持编译进内核,于是我就带了一个内核,接着我考虑到内核的改变会影响显卡驱动,我把显卡驱动也带进去,接着考虑到显卡驱动和xserver相关,不知道目标用户用的是xorg还是xfree86我决定把xorg7.1也带进去,考虑到到xorg7.1上面目标用户的GTK2和QT都可能不能平滑运行,我还得把GTK2和QT带进去,那KDE和GNOME呢要不要带,算了一起带把鬼才知道目标用户用的那个版本的呢。

对于绝大多数成熟的二进制发行版本,linux是基于软件库,在发行版范围内自动解决包依赖的。而且绝大多少的软件就在库里面。linux的逻辑是开发人员的任务是完成源代码的编写,以原代码的形式发布,为了调试选几个发行版编译试一试,高兴就提交给发现版的维护者。其他发行版的维护者要用软件,到自己的环境下编译好了,不能通过,该打补丁就打补丁,该扩展软件库就扩展软件库,还用不了,你自己实现好了,反正我的代码你也能看到,实现的时候你就挑着用好了。

如果编程者想要自己的软件通用一点就把开发的基础降低一点,用通用一些的库就行了。其他东西原代码里实现了就行了,要用到某个不太流行的库里的功能,那把原代码直觉拷贝过来好了,干吗要到编译完了的时候再来???

安装软件软件的时候你非要跨发行版进行二进制安装,那选跨平台的开发环境好了,听说java开发的东西到了哪儿都能用,听说而已。

其实linux下的软件最大的好处就是不用到处找,要二进制的包到软件库,要源代码到开发者的发布网站。
作者: linuxpgy    时间: 2006-9-7 09:12

引用:
安装软件软件的时候你非要跨发行版进行二进制安装,那选跨平台的开发环境好了,听说java开发的东西到了哪儿都能用,听说而已。
这点提的很好,我就是要做一种rpm可以跨发行版安装,为什么呢?就以在magiclinux下装anjuta来说,直接rpm -ivh anjuta.xxx.rpm 会提示很多包没有装,很多so没有找到. 所以只用一个发行版的软件库,似乎对普通用户来说装anjuta几乎是不可能了~ 当然高级用户完全没有这个问题,rpm装不上大不了自己重新编译一个。

这就需要一种rpm自带自己需要的库(要带libgnome.so.2之类,因为目标可能是KDE桌面),以方便普通用户安装。

需要自带内核那种软件建议还是用户自己去升级内核去吧,我们只考虑一般应用软件,毕竟只依赖某些库文件而已。还有一点一个软件需要gtk或qt也没必要带所有的so,因为它有的没有使用到。虽然大了点,但是我觉得解决了用户的麻烦还是值得的(某些所有发行版必带的库可以省掉liblinux.so.2之类,可以减少一点体积)。

当然,这种包给谁用呢?就是普通用户。谁来做呢?现在当然还没有人在做,但是linux的繁荣需要大家的努力,如果有志同道合的人请看这里:http://waxb.blog.com.cn/archives/2006/1527213.shtml
作者: lanzinc    时间: 2006-9-7 14:30

对于anjuta这个具体问题我是这么看的:
1.对于magic在gnome的支持上的定位,我是这么认为的(我的看法不代表magic官方的看法,我只是magic的一个fans):magic默认安装不提供及于gnome上开发的软件的支持,但正在努力通过apt提供运行gnome软件的基本环境,如果可能提供一个完整的gnome桌面,但这一切都通过apt提供。
2.如果你只是想在magic上用anjuta的话,你应该先用apt查找一下,说不定库里已经有了;如果库里没有,你可以发个贴,说我需要anjuta for magic的rpm包,最好是一个包,但是如果是一堆包也没关系,只要是需要的包光盘和apt都能拿到就行,这样也许有人已经做好了RPM的包,他email给你,或者放到apt,你用apt安装;如果在你能够等待的期限之内没有结果,或着你可以一边等一边尝试自己从原代码安装,成功了,如果有能力就做成RPM提交给apt的维护者,没有能力就写个帖子发到论坛或wiki,把过程写清楚,如果决定没有必要,就写给日记,收好,下次有人发贴求助的时候,可以发给他;
当然编译之前看看文章可以少走弯路。
象:Anjuta 2.x Dependencies
http://anjuta.sourceforge.net/downloads
是必看的,作者提出的运行环境你得事先准备好(一个原则照单抓药,缺什么装什么,当然最好他要的包都是apt上有的)。
当然编译安装(或编译打包)也可以使用自动化的工具。比如rpmbuild,archlinux的makepkg。只要你有条件用他们,rpmbuild需要src.rpm的包,这个你可以用其他发行版本的src.rpm包来改,因为这样的包是原代码包,只是附加了更多的信息,当然要注意的是这样的包可能已经被组合或分拆过了,你要拿到全部需要的包。
如果在你的能力和想做的事情都做完了,anjuta还是没装上,OK,这说明magic不适合你,可以考虑换发行版了。(我在红旗上曾经很多软件都很没道理的装不上,后来知道是红旗修改了流行的软件的代码,KDE在红旗上虽然叫KDE但是已经不是原来的KDE了,于是我放弃了红旗。)
如果你用了一遍的各种发行版,还是有问题,那就是考虑放弃linux的时候了。
拿别的发行版的二进制rpm包到magic上用的方法不是解决问题的正确方法。
3.如果你是想说现在的rpm包管理和打包系统,已经可以做出跨发行版本的rpm二进制包,只是没有人发现这一真理(我属于认为现有的RPM做不出跨发行版本的rpm二进制包的人),那你就应该写一篇FAQ或HOWTO把你的发现公布于众,爱因斯坦的相当论现在不是也有人认为不对吗?
4.如果你是觉得现在的rpm不够好用,做不出来跨发行版本的rpm二进制包,是一个不可原谅的错误,而且现在全世界都找不到合理的解决方案,并且你认为解决的办法是存在的,那你可以起草一项计划,或启动一项工程,吸引更多的脑袋参与进来。linux不就是这样诞生的吗。不过那时候,你最后不用把你新的打包系统叫rpm。
5.libgnome.so.2只是他所属的库中的一个文件,并不表明libgnome.so.2离开了其他的文件能独立工作。如果事实上是确实是只需要这样一个文件,而不是整个库,那你应该告诉开发者,他应该在原代码就解决这个问题,这样可以去掉对一个库的需要。
事实上我见过这样的事情,一个包只是需要另一个包里的一个图标,但打包的人却添加了对一整个包的需要,而且那个包含图标的包还不是该发行版里base部分的包,这是打包人的失误.
作者: linuxpgy    时间: 2006-9-7 17:27

非常感谢lanzinc, 提供给我了这么多的信息。我拿anjuta只是做一个例子,因为这个例子比较典型。(ps:事实上装anjuta对我来说没什么大的障碍,不管是rpm还是apt,还是源码。)但它很能说明我要达到的目的--&gt;对,就是你说的第3点,用rpm制作跨发行版的安装包。当然如果完全可行我会告诉大家的,现在正在实验,更详细的信息在我的博客里(上面的链接)。
其实也没有什么神秘的,只是把需要的库自己带上,看看可不可行,虽然会让rpm变得超大,但是我喜欢尝试新的东西。有很多事情就是这样,技术不能决定一切,用的人多了,也就成了标准,就像Windows~~

一个程序需要libgnome.so.2,可以肯定它也需要libgtk.so.2,不是它直接需要,是因为libgnome需要~~这点我注意到了,所以这样的包会很大,至于大到什么程度,可不可以接受,只有等出来才知道~~ 不过我想这样的包对于只有KDE环境没什么关系,反正安装anjuta这些文件都是要的,不如装一个包来的快。对于GNOME环境就感觉这个包带了一大堆系统已经有的文件,无缘无故的浪费我的下载带宽,占我的硬盘空间。所以一个新东西出来肯定会同时引来赞扬和贬低,这是正常的。

总之,我做的包只是一种尝试,结果还不得而之,现在做rpm遇到一些问题,主要是怎么添加菜单,添加桌面快捷方式等,还是先试试看吧~~
作者: jiangtao9999    时间: 2006-9-7 21:47

static 程序可以解决部分库的问题,但会也带来更多的问题,比如曾经的 Opera ,static 版本就不能用 scim 输入。
作者: 再见情人    时间: 2006-9-7 22:37

[quote:05f218cfb5="linuxpgy"]1.不管是一个或几十个dll,只要是你程序需要的,而且你又不能确定目标系统肯定有的,你就必须带上,这是对用户的负责!linux的rpm包,除了带自己写so,用到的其他人的so一个不带,让用户自己去找去吧!!
2.更新kde,就需要把上面的软件重新编译?我没做过,不知道是什么原因~~也许是你的设置有问题,比如库收索路径等等~~还有你说不能用的出错信息是什么?
3.正是因为更新不能完全同时,所以才需要自带库啊!!!!VC7编译的软件基本都自带msvcrt7.dll,不然根本无法运行,因为系统中只有msvcrt6.dll!!
4.我说它的目的是告诉大家可以不用root权限来打包rpm,就这样,understand?[/quote]
关于第一个问题,linux的rpm包,各大基于rpm的发行版的官方的rpm都有特定对应的系统,比如for rh9 fr1 fr5等等,你要你满足了依赖关系,一般不会有问题,但是如果你把不同发行版之间的rpm互用,满足不了其他的so,那不关发行版本身的问题。
2,更新一个软件,可能很多联带的软件都需要更新,很多接口都不同,你编译的时候都会出现 undefined symbol......., 或者undefined defination....,如果直接用不同发行版之间的rpm,用的时候就更不用说了。你没做过,说明你自己软件安装升级之类的经验还需要累积。

3,自带库没有问题阿,你打包时候每个包都用自带库,系统会增大多少? 此其一,另外你如何自带库,带多少库,你只会打包,不是开发者的话,你如何知道到底需要用什么样的库,你怎么在打包的source中把所有的库添加,你从源码安装,configure make make install, configure 会告诉你缺什么软件,但你知道添加该软件的什么库么?你找到了一个so,你知道这个so又会需要多少系统原有的什么样库呢?

4, 非root当然可以打包,可以简单创建一个环境,但是有些命令有可能仍然需要
root权限,我做过这样的包

“用rpm制作跨发行版的安装包”首先 static 包会引来很多问题。 在你想这个问题之前,我相信很多人都想过这个问题,不同的发行版配置,路径都不完全相同,打包rpm不只是一个简单的程序那么简单,很多设置都是rpm包完成的,谁能打出一个包配置所有不同的发行版???,不同的发行版谁都不能保证自己什么时候升级,用的基础库都不一样,如何知道哪个发行版带了什么样的库,一个rpm能把需要的整个系统的库都带全么??
作者: linuxpgy    时间: 2006-9-8 09:12

首先:我说一个现象,mplayer需要mplayer-win32包,可是各发行版包的名字不同,导致装了mplayer-win32mgc的系统不能装mplayer-mdk,即使mplayer-win32mgc和mplayer-win32mdk内容完全一样,也不让你装mplayer-mdk,因为打包mplayer-mdk的时候明确写了需要mplayer-win32mdk,而不是mplayer-win32mgc。
所以各发行版之间的包互用几乎不可能,这是包级依赖。还有一种依赖就是系统缺少什么so,的so级依赖。
不过这些都不是问题,我做的这种包没有包级依赖,同时自带所有库解决so级依赖。怎么自带所有的库(包括so依赖的so)呢?其实你知道/usr/lib/rpm/find-providers 和 /usr/lib/rpm/find-requires的原理就明白了,这里就不详细说明了。所以自带哪些库就是用这两个脚本是查出来的。(不管是源码编译,还是直接的执行程序,打包之前都查一下就知道了)。

还有安装之后系统不会增大多少,相同的文件会覆盖的,还有,因为你安装的是程序运行所需的库,是必装的,就像你不会因为装个photoshop太占硬盘而不装吧?

路径和配置是一大麻烦,确实如你所说,以编辑菜单为例,各家有各家的做法~~晕~~
另:static包是什么东西?
作者: 再见情人    时间: 2006-9-8 12:47

"怎么自带所有的库(包括so依赖的so)呢?其实你知道/usr/lib/rpm/find-providers 和 /usr/lib/rpm/find-requires的原理就明白了,这里就不详细说明了。所以自带哪些库就是用这两个脚本是查出来的。(不管是源码编译,还是直接的执行程序,打包之前都查一下就知道了)。 "
那个是查已有rpm包提供库和依赖的,不是你未打包之前的,不同系统打出的包依赖是不同的,提供的库也有可能是不同的,就是你说的so,打包不只是打个应用程序包那么简单。
“还有安装之后系统不会增大多少,相同的文件会覆盖的”
在你对一个系统不了解的情况下,不要这么做,很危险的,如果你打的是系统的一些核心包,有可能导致系统崩溃甚至无法启动的
作者: linuxpgy    时间: 2006-9-8 13:19

引用:
那个是查已有rpm包提供库和依赖的,不是你未打包之前的,不同系统打出的包依赖是不同的,提供的库也有可能是不同的,就是你说的so,打包不只是打个应用程序包那么简单。
你看过那两个脚本之后再说吧。而且我要做的就是一般应用程序包,内核补丁什么的,我也不会做。对于依赖问题,只要这个包没有任何依赖就行了。

覆盖会发生危险的话,那应该是最原始开发者或者编译打包人员的问题,就是出现这个系统的libsome.so.2和另一个系统的libsome.so.2完全是两个文件。这种可能性是比较小的。

最后提个问题,大家一起讨论一下,因为我玩linux的时间不太多。就是假设一个bin需要libsome.so.2运行,然后其实libsome.so.2是libsome.so.2.0的符号链接(几乎所有库都样做的)。现在假如我找到了一个libsome.so.2.1(新版本),然后把libsome.so.2的链接指向libsome.so.2.1,那么这个bin还能正常运行吗?谢谢!
作者: lanzinc    时间: 2006-9-9 21:35

引用:
最后提个问题,大家一起讨论一下,因为我玩linux的时间不太多。就是假设一个bin需要libsome.so.2运行,然后其实libsome.so.2是libsome.so.2.0的符号链接(几乎所有库都样做的)。现在假如我找到了一个libsome.so.2.1(新版本),然后把libsome.so.2的链接指向libsome.so.2.1,那么这个bin还能正常运行吗?谢谢!
不一定能正确运行,因为两个文件的接口名称及数量,以及同一接对应的函数的实现不一定完全一样。

但如果你有这个bin的原代码,和这个so对应的head文件,重新进行编译,就没问题了。
引用:
这个系统的libsome.so.2和另一个系统的libsome.so.2完全是两个文件。这种可能性是比较小的。
我觉得这是完全有可能的。
因为linux的软件是原代码发行的,同样的原代码在不同的环境,和用不同的参数进行编译,编译出来的二进制代码是不一样的。(还有很多情况是两个不同的发行版本有的编译器也不完全一样)

这就是为什么可以针对不同的CPU进行优化编译的基本原理。

没认真学过编译原理,再具体就只能请高手出来解释了。
(虽然编译原理是计算机专业必开的课程,但我不是计算机专业的)。
作者: linuxpgy    时间: 2006-9-10 11:20

引用:
不一定能正确运行,因为两个文件的接口名称及数量,以及同一接对应的函数的实现不一定完全一样。
但如果你有这个bin的原代码,和这个so对应的head文件,重新进行编译,就没问题了。
既然接口都变了,你再怎么编译也没有用啊,除非你修改bin的代码,让它适应新的接口。
引用:
我觉得这是完全有可能的。
因为linux的软件是原代码发行的,同样的原代码在不同的环境,和用不同的参数进行编译,编译出来的二进制代码是不一样的。(还有很多情况是两个不同的发行版本有的编译器也不完全一样)
这就是为什么可以针对不同的CPU进行优化编译的基本原理。
恩,这点我已经亲身体验过了,不仅编译出来的二进制代码不完全相同,就是同样的二进制代码,在用打包时也会被修改,使本来能正常执行的bin出现***段错误***!!!主要原因是rpmbuild在打包的过程中会自动去除bin文件里的一些多余符号,使bin的体积减小,这对于大部分程序没什么影响,但对某些bin则会导致错误!然后我把去符号的过程去掉之后就一切正常~~
作者: lanzinc    时间: 2006-9-10 14:35

引用:
既然接口都变了,你再怎么编译也没有用啊,除非你修改bin的代码,让它适应新的接口。
因为编译的过程中(应该是连接的时候)会自动使用新的接口名称。

我估计具体原因可能是:

对应的head文件已经作了相应的变化,bin的代码只要include相应的新的head文件.又因为, head文件的文件名不变,bin的代码不需要改变.

另外原代码引用的是函数或过程名而不是接口名称,接口名称是编译器编译和连接时候才引入的。连接器根据实际情况进行源代码字符串名到接口名的转换。

比如:原代码用的是过程的字符串名,而二进制用的是偏移量作为入口。
又比如:原代码用的是类名,而二进制用的是二进制的ClassID。

连接分两种一种是静态连接(static 程序),一种是动态连接(非static 程序)。
作者: lanzinc    时间: 2006-9-10 14:58

引用:
主要原因是rpmbuild在打包的过程中会自动去除bin文件里的一些多余符号,使bin的体积减小
这常被称为二进制文件的去皮或去壳
这也可以在编译的过程就来完成,就是编译的时候使用特定的参数来要求编译器进行特定的操作。

编译原理:
http://book.hitce.net/view.asp?id=213
另外更好的有:
http://book.chinaunix.net/showbook.php?id=16341
但找不到电子版

原代码在可移植性上的问题
http://www.linuxfans.org/nuke/modules.php?name=Site_Downloads&op=geninfo&did=4532

希望有人提供二进制代码的可移植性问题,代码复用,动态连接库的使用的相关电子书。
作者: linuxpgy    时间: 2006-9-11 08:51

引用:
对应的head文件已经作了相应的变化,bin的代码只要include相应的新的head文件.又因为, head文件的文件名不变,bin的代码不需要改变.
head文件名不变,内容做了改变?改其他东西无所谓,比如加个函数什么的,但是把以前的函数声明改了,是不可能编译的,就像bin需要getA(),你把getA改成getB,当然会提示找不到getA了。如果你不改变getA的声明,而是改getA的代码,这样怎么改都无所谓了,而且bin也不需要编译,直接调用getA好了,因为bin只认接口,这样bin还是可以运行的。(这就是用动态库的一大好处!修改部分不需要编译整个工程!)
引用:
这常被称为二进制文件的去皮或去壳
但是会使某些bin去皮之后发生了"段错误"~~看来这个过程并不是安全的~~~

再提个问题:因为编译问题(gcc版本和优化选项等问题,其他因素暂不考虑)会导致一个平台编译的libsome.so.2和另一个平台的libsome.so.2会不同,那么如果一个包包含libsome.so.2就会和系统的libsome.so.2冲突(confilct with file from...)。如果直接使用--replacefiles 选项安装会不会有问题呢? 还有,如何打包使rpm不检测这种文件冲突,直接自动覆盖,就像用户输入了--replacefiles一样呢?
作者: jiangtao9999    时间: 2006-9-11 20:01

引用:
如果直接使用--replacefiles 选项安装会不会有问题呢? 还有,如何打包使rpm不检测这种文件冲突,直接自动覆盖,就像用户输入了--replacefiles一样呢?
欢迎来到 DLL 地狱。

Linux 软件包管理器,有一个功能就是避免这个用的。
作者: KDE    时间: 2006-9-11 23:46

应用程序自带的库,应该尽可能放到私有目录里,比如 /usr/share/软件名称-版本号/lib/ 或者 /usr/local/lib/  或者 /opt/local/lib/,也就是说编译时就指定使用这些位置里的库文件。

rpm 不支持企图在打包时实现 rpm 安装阶段不检测这种文件冲突,你应该把是否覆盖的选择权交给用户。你应尽可能避免冲突,而不应该是悄无声息地替换系统文件,如果你实现了这样的操作,那无异于恶意程序。

确保软件的二进制代码能够跨平台运行,不是系统软件打包者要考虑的事,而是应用软件作者和独立二进制代码发布者应该考虑的事。我们没有责任和义务确保从我们系统里拆解下来的部件能够运行于其他系统上,不支持,更不提倡这种移花接木的作法。

试图解决跨平台的技术,我印象中有 autopackage 和 klik 技术,参见:
http://autopackage.org
http://klik.atekon.de
作者: linuxpgy    时间: 2006-9-12 09:51

看来我的好心可能害了用户~~~~如果不覆盖系统库的话不是不行,只要系统中保证有这些系统文件就行了,那样也能实现跨发行版安装。关键问题就是linux有那些系统文件是像user32.dll,kernel32.dll那样每个系统都带的呢?
如果不确定带哪些的话,是否有这样的选项,即安装的时候自动跳过已经存在的文件,而不是提示冲突中止安装呢?请高手指点!

关于autopackage,klik我会研究一下,不过rpm还是大部分linux使用的包管理系统,毕竟用的人不多。看看有没有借鉴之处~~谢谢啦!
作者: 再见情人    时间: 2006-9-12 13:04

[quote:fe4af95701="linuxpgy"]看来我的好心可能害了用户~~~~如果不覆盖系统库的话不是不行,只要系统中保证有这些系统文件就行了,那样也能实现跨发行版安装。关键问题就是linux有那些系统文件是像user32.dll,kernel32.dll那样每个系统都带的呢?
如果不确定带哪些的话,是否有这样的选项,即安装的时候自动跳过已经存在的文件,而不是提示冲突中止安装呢?请高手指点!

关于autopackage,klik我会研究一下,不过rpm还是大部分linux使用的包管理系统,毕竟用的人不多。看看有没有借鉴之处~~谢谢啦! [/quote]
即便是系统满足了所有的库,只是文件名相同的话,不在当前系统编译的rpm包安装后也未必正常运行,即相同名字的库因为编译它的环境configure时的参数等等不能替换使用,所以即使你跳过了文件也未必解决问题,这也是为什么不能盲目直接替换文件的原因,各个linux系统文件版本都不同,提供的so名字可能不尽相同,很难说哪个文件是所有系统都带的。
作者: linuxpgy    时间: 2006-9-12 13:42

虽然说系统库有相同文件名但是内容不一样,替换可能会导致其他程序有问题,不替换可能导致这个程序不能运行,但是仅仅是可能!有谁能证明一下吗? 这里引用一下论坛某人(忘了是谁了)的签名:
引用:
少说,多干!

作者: lanzinc    时间: 2006-9-12 13:49

引用:
引用:
少说,多干!
这句话是没错,但是重复发明轮子和制造永动机都是不应该干的。
作者: linuxpgy    时间: 2006-9-12 14:01

引用:
这句话是没错,但是重复发明轮子和制造永动机都是不应该干的。
我最讨厌的就是重复发明轮子!!不过这和我们讨论的没什么关系吧?
作者: jiangtao9999    时间: 2006-9-12 20:42

很有关系,因为你在重走 rpm 等包管理曾经走过的路。
作者: linuxpgy    时间: 2006-9-12 22:32

引用:
很有关系,因为你在重走 rpm 等包管理曾经走过的路。
是吗?我怎么没听说过?那你举个例子……不要光说好不好啊~~说谁不会~~
作者: 江涛的马甲    时间: 2006-9-13 09:45

对于你来说,库文件不能被替换不符合你的想法。
但这个问题却在所有包管理器里放在首位。
作者: lanzinc    时间: 2006-9-13 14:53

假如windows也是原代码发行,而不是同一份二进制文件的拷贝,大家用的也是在各自的编译环境和参数下编译的话,继续使用windows原始的包管理机制,那会怎样?
作者: jiangtao9999    时间: 2006-9-13 16:50

Windows 发行版只有一个,所以你携带了自己的 dll 去覆盖系统的 dll 不会导致多大的问题(其实问题也不小,不然不会从 xp 开始,系统给 dll 增加了保护,vista 的保护更严格)。而且因为版本单一,实际系统提供了足够的统一样式的库,不需要还要自己携带很多的库程序。

linux 发行版不同,他们提供的基础库也有出入。
作者: linuxpgy    时间: 2006-9-13 20:36

linux的dll就那么脆弱吗?覆盖一个会有问题吗?又不是随便拿个so去替换系统库的,基本可以保证是一份代码编译出来的,理论上不会太大问题,等有问题再解决吧。最近太忙了,都没时间做rpm了~~~
作者: jiangtao9999    时间: 2006-9-13 20:46

…………………………
你以为 so 就象 dll 那样哪???
作者: linuxpgy    时间: 2006-9-14 08:43

引用:
…………………………
你以为 so 就象 dll 那样哪???
of course. They are the Same.
作者: lanzinc    时间: 2006-9-14 11:46

对dll不太了解
dll好象有很多种, 什么OLE COM COM+ 等等的能介绍一下吗
作者: linuxpgy    时间: 2006-9-14 12:01

http://support.microsoft.com/default.aspx?scid=kb;zh-cn;815065
这里说的很详细了~~~
作者: jiangtao9999    时间: 2006-9-14 20:25


so 和 dll 不一样………………
windows 的主要 dll ,是微软随同系统一同发布,且没有源代码,不能更改的………………
作者: linuxpgy    时间: 2006-9-15 09:11

linux的lib hell!!!!!!!!

Under Windows, you have the infamous "DLL hell", where you can have dozens
of different programs which require different versions of the same
third-party DLL with the same name.  This page --
http://www.faqs.org/docs/artu/ch03s02.html -- describes it best:

    Because Windows does not handle library versioning properly, it suffers
    from a chronic configuration problem called "DLL hell", in which
    installing new programs can randomly upgrade (or even downgrade!) the
    libraries on which existing programs depend. This applies to the
    vendor-supplied system libraries as well as to application-specific ones:
    it is not uncommon for an application to ship with specific versions of
    system libraries, and break silently when it does not have them.

Unfortunately, we've seen this under OS/2 as well, with the inability of
Mozilla-based applications to coexist without awkward workarounds.

Unix-based systems like Linux, on the other hand, avoid "DLL hell" by
linking to specific named versions of shared libraries.  Essentially, it
trades it for "lib hell" instead, where every single application can
depend on a different point version of a library, and refuse to run
until a copy of that exact version is hunted down and installed.  When you
have hundreds of programs, each of which can depend on a dozen or more
such libraries, it's enough to turn a person prematurely grey.

It's exacerbated, of course, by Linux's continued adherence to the
fundamental Unix design philosophies, notably "never implement what you
can rely on an existing program or library for".

I just finished assembling a WarpIn install package for the GIMP 2.2.8,
and the number of external libraries it depends on is insane.  (And it's
not even the worst offender by a long shot.)

At least Debian-based Linuxes have an intelligent package management
system that keeps track of all dependencies for you (and offers to
download and install them automatically if it finds them missing).
作者: linuxpgy    时间: 2006-9-20 18:45

autopackag刚刚用了一下,感觉和rpm类似,只是图形化而已,缺少的包还是要自己去下载。
装giam运行结果:
[code:1]
Checking for required C library versions ...  OK
Checking for GTK+ user interface toolkit ...  OK
Checking for Audio File Library ...  OK
Checking for libao cross platform audio library ...  OK
Checking for GtkSpell Spell Checking Library ...  failed

Error&#58; Could not find 'GtkSpell Spell Checking Library'. Try using the native package manager for Mandriva Linux &#40;urpmi&#41; to install a package with similar name to 'gtkspell'.

Error&#58; Unable to prepare package Gaim Internet Messenger.
[/code:1]
等会试试klik
作者: linuxpgy    时间: 2006-9-20 19:27

klik比autopackage聪明多了,就像apt比rpm聪明一样,它会下载所需的deb包装上,自己解决依赖关系,可以试试。 总之一句话,只要上网,依赖关系就可以解决!

关于前几天讨论的自带库的rpm问题,现在我有了新的想法。跨发行版安装基本不行,(有些极端的手段也许可以,但是问题很多)。二进制层兼容性很差。不像windows只有一家在发行系统二进制库,linux的发行版太多了(据说有386个。。),编译环境,库的版本(linux lib hell)都不一样,这里运行好好的程序拿到另一个系统就有问题。

linux什么时候才能统一呢?如果只有一个linux发行版,一种桌面环境,就不用考虑跨发行版带来的种种问题,那样的话安装一个新软件会容易的多。。 :neutral:
作者: KDE    时间: 2006-9-20 20:44

[quote:68b74396c7="linuxpgy"]klik比autopackage聪明多了,就像apt比rpm聪明一样,它会下载所需的deb包装上,自己解决依赖关系,可以试试。 总之一句话,只要上网,依赖关系就可以解决!

关于前几天讨论的自带库的rpm问题,现在我有了新的想法。跨发行版安装基本不行,(有些极端的手段也许可以,但是问题很多)。二进制层兼容性很差。不像windows只有一家在发行系统二进制库,linux的发行版太多了(据说有386个。。),编译环境,库的版本(linux lib hell)都不一样,这里运行好好的程序拿到另一个系统就有问题。

linux什么时候才能统一呢?如果只有一个linux发行版,一种桌面环境,就不用考虑跨发行版带来的种种问题,那样的话安装一个新软件会容易的多。。 :neutral:[/quote]
绕了一圈,你终于明白了,可喜可贺。
作者: jiangtao9999    时间: 2006-9-20 20:52

解决的最好办法就是提供从源代码编译!
作者: linuxpgy    时间: 2006-9-21 08:53

原代码编译?
首先,并不是每个人都装了gcc,及所有编译所需的sdk,其次,不是每个人都是编程狂人,能应对编译错误,再次,不是每个人都能忍受漫长的编译时间……所以这种方法不适合普通用户。

既然magic也是基于rpm管理的,rpm不能跨平台,所以为这个平台打包的软件必须丰富起来,不然要装anjuta之类的还需要其他发行版的包。有个非官方的软件包,做的很不错,如果有更多适合magic的rpm就好了。   所以我觉得magic应该在做rpm上加大力度,系统的升级可以慢一点,平时补丁打打就好了,这样我相信magic会成为中国唯一的linux的。

magic也有apt源,不知道里面有什么软件,里面很多吗?
作者: jiangtao9999    时间: 2006-9-21 20:10

开发人员数量决定软件包的数量…………
作者: ququ01    时间: 2006-9-28 17:33

我有个问题  急盼回复   这是我的SPEC

ummaryhotoDVD is a very sample application which enables you to create and burn photos slideshow to DVD.

Name: PhotoDVD

Version: 1.0

Release: 1mgc

Copyright: Commercial

Group: Graphics

Source0:%{name}-%{version}.tar.gz

%description
PhotoDVD helps you use DVD or CD burner to create photo album on DVD disc playable on TV with background music, a lot of pictures, transition effects.
%prep
#tar xzvf $RPM_SOURCE_DIR/%{name}-%{version}.tar.gz -C $RPM_BUILD_DIR/

%setup -n %{name}-%{version}
%build

%install
mkdir  /Colorlife
mkdir -p /EB_Workshop/EB_Dependence

cd $RPM_BUILD_DIR/%{name}-%{version}

cp -R Lib /EB_Workshop/EB_Dependence
cp -R MainconCeptLib/*  /usr/lib
cp -R sharedlib/* /usr/lib
cp -R PhotoDVD /Colorlife

%clean
rm -rf $RPM_BUILD_DIR/PhotoDVD

%files
%defattr(-,root,root)
/Colorlife/PhotoDVD/
/usr/lib/libipp*.so
/usr/lib/libmcmpgvout.001
/usr/lib/libmcmpgvout.002

%changelog


然后我 rpmbuild -ba PhotoDVD-1.0-1.spec

生成的PhotoDVD-1.0-1mgc.i386.rpm  
两个问题
我在干净的环境中第一次运行 程序总是报错 启动不了.
2.我在另一台机器下安装,根本就没有CP
作者: linuxpgy    时间: 2006-9-28 19:16

错误信息是什么?详细一点
作者: KDE    时间: 2006-10-2 01:15

to: ququ01
1、你根本就没有仔细阅读 rpm 建包原理,严重违反了一些基本建包原则。
2、你在 %files 丢了东西,难道你在执行 rpmbuild -ba PhotoDVD-1.0-1.spec 就不看看错误输出么?
3、我们不会对不开源的商业软件提供任何额外的无偿 rpm 建包技术支持。现有文献就是你最好的学习资料。
作者: ququ01    时间: 2006-10-8 10:04

KDE
请你帮帮我  我知道%file下缺的一些东西
作者: yyjie    时间: 2006-10-8 13:53

楼主辛苦了,我跑错地方了,看得头都晕了,开始学linux了,天天看书了,脑袋看大了,眼睛看肿了,要是搞懂了,那也就直了,可是~~~   唉~
作者: lanzinc    时间: 2006-10-12 22:21

草草看了一遍LFS-book,对打包这项工作又有了新的理解。打包比LFS更上了一个台阶。
作者: ahlongxp    时间: 2006-10-29 22:31

纷发源码是最合适的,看看gentoo
作者: KDE    时间: 2006-11-3 16:05

[quote:0731b521b4="ahlongxp"]纷发源码是最合适的,看看gentoo[/quote]那为什么最流行的并不是 gentoo?
合适与否,关键是看用户的体验。
作者: JavelinJS    时间: 2008-7-6 00:01

[/quote]那为什么最流行的并不是 gentoo?
合适与否,关键是看用户的体验。 [/quote]

道中要害
作者: wangdu2002    时间: 2008-10-13 01:31     标题: 学习了

不过刚接触sLinux不久,为什么ML用Rpm呢,而不是用deb包呢?
楼主也说deb包解决依赖性更强啊.
作者: dgy18787    时间: 2010-2-20 00:59

这篇文章我转载到我的博客里面作为以后要看的东西了。做一个转载声明。




欢迎光临 中国Linux公社论坛 (http://forum.linuxfans.org/) Powered by Discuz! 6.1.0F