QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

楼主: KDE

rpm 建包原理(2010.11.22 更新)

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

使用道具 举报

发表于 2006-9-6 23:13:29 | 显示全部楼层
1、那会很多………………要知道 Linux 程序员很懒的………………
2、错误信息很简单:未定义的接口(英文忘了)
3、同 1 ,那会很多……………………
4、明白,原来是和上面讨论的无关。
回复

使用道具 举报

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

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

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

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

其实linux下的软件最大的好处就是不用到处找,要二进制的包到软件库,要源代码到开发者的发布网站。
回复

使用道具 举报

发表于 2006-9-7 09:12:37 | 显示全部楼层
安装软件软件的时候你非要跨发行版进行二进制安装,那选跨平台的开发环境好了,听说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
回复

使用道具 举报

发表于 2006-9-7 14:30:56 | 显示全部楼层
对于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部分的包,这是打包人的失误.
回复

使用道具 举报

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

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

总之,我做的包只是一种尝试,结果还不得而之,现在做rpm遇到一些问题,主要是怎么添加菜单,添加桌面快捷方式等,还是先试试看吧~~
回复

使用道具 举报

发表于 2006-9-7 21:47:01 | 显示全部楼层
static 程序可以解决部分库的问题,但会也带来更多的问题,比如曾经的 Opera ,static 版本就不能用 scim 输入。
回复

使用道具 举报

发表于 2006-9-7 22:37:44 | 显示全部楼层
[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能把需要的整个系统的库都带全么??
回复

使用道具 举报

发表于 2006-9-8 09:12:16 | 显示全部楼层
首先:我说一个现象,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:38 | 显示全部楼层
"怎么自带所有的库(包括so依赖的so)呢?其实你知道/usr/lib/rpm/find-providers 和 /usr/lib/rpm/find-requires的原理就明白了,这里就不详细说明了。所以自带哪些库就是用这两个脚本是查出来的。(不管是源码编译,还是直接的执行程序,打包之前都查一下就知道了)。 "
那个是查已有rpm包提供库和依赖的,不是你未打包之前的,不同系统打出的包依赖是不同的,提供的库也有可能是不同的,就是你说的so,打包不只是打个应用程序包那么简单。
“还有安装之后系统不会增大多少,相同的文件会覆盖的”
在你对一个系统不了解的情况下,不要这么做,很危险的,如果你打的是系统的一些核心包,有可能导致系统崩溃甚至无法启动的
回复

使用道具 举报

发表于 2006-9-8 13:19:45 | 显示全部楼层
那个是查已有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还能正常运行吗?谢谢!
回复

使用道具 举报

发表于 2006-9-9 21:35:10 | 显示全部楼层
最后提个问题,大家一起讨论一下,因为我玩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进行优化编译的基本原理。

没认真学过编译原理,再具体就只能请高手出来解释了。
(虽然编译原理是计算机专业必开的课程,但我不是计算机专业的)。
回复

使用道具 举报

发表于 2006-9-10 11:20:07 | 显示全部楼层
不一定能正确运行,因为两个文件的接口名称及数量,以及同一接对应的函数的实现不一定完全一样。
但如果你有这个bin的原代码,和这个so对应的head文件,重新进行编译,就没问题了。

既然接口都变了,你再怎么编译也没有用啊,除非你修改bin的代码,让它适应新的接口。

我觉得这是完全有可能的。
因为linux的软件是原代码发行的,同样的原代码在不同的环境,和用不同的参数进行编译,编译出来的二进制代码是不一样的。(还有很多情况是两个不同的发行版本有的编译器也不完全一样)
这就是为什么可以针对不同的CPU进行优化编译的基本原理。

恩,这点我已经亲身体验过了,不仅编译出来的二进制代码不完全相同,就是同样的二进制代码,在用打包时也会被修改,使本来能正常执行的bin出现***段错误***!!!主要原因是rpmbuild在打包的过程中会自动去除bin文件里的一些多余符号,使bin的体积减小,这对于大部分程序没什么影响,但对某些bin则会导致错误!然后我把去符号的过程去掉之后就一切正常~~
回复

使用道具 举报

发表于 2006-9-10 14:35:46 | 显示全部楼层
既然接口都变了,你再怎么编译也没有用啊,除非你修改bin的代码,让它适应新的接口。

因为编译的过程中(应该是连接的时候)会自动使用新的接口名称。

我估计具体原因可能是:

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

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

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

连接分两种一种是静态连接(static 程序),一种是动态连接(非static 程序)。
回复

使用道具 举报

发表于 2006-9-10 14:58:02 | 显示全部楼层
主要原因是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

希望有人提供二进制代码的可移植性问题,代码复用,动态连接库的使用的相关电子书。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-4-25 09:12 , Processed in 0.056275 second(s), 12 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表