笔记:如何创建一个debian包并上传到debian official中

编译打包和其他
回复
xiechy
帖子: 1074
注册时间: 2006-01-18 15:01

笔记:如何创建一个debian包并上传到debian official中

#1

帖子 xiechy » 2007-01-22 13:03

写在前面:为什么要将包上传到debian?

ubuntu和debian的关系比较复杂,一方面,ubuntu基于debian的unstable,所以大部分包debian的unstable分支比ubuntu要新。但另一方面,ubuntu对于一些关键的包,例如gnome,Xorg,libc,python,是自己建立的分支,这些包反而是ubuntu比较新。不过要从debian的包转换成ubuntu的二进制包不难。所以:
a、为了更好的兼容性,和更好的在各个distro中分享,我个人觉得应该将自己创建的包上传到debian而不是ubuntu中会比较好。
b、如果你的包只有ubuntu版本,当上游的debian中有了相同的软件时,ubuntu的维护者会怎么做呢?为了保证系统的连续性,他们会选择debian的上游包,而不是你的。这种定期的同步过程一直是保持的。
c、其实已经有很多包是这样的了,例如sun-java6,这个包是首先在feisty中加入的,但之后很快,作者就将这个包上传到了debian。这样可以保证自己的包不会被洗掉。而且也是很好的说明debian和ubuntu不是竞争者,而是互相合作的关系。

1、如果有包找不到怎么办?

代码: 全选

apt-get build-dep icecream
apt-get source icecream
cd the-directory-of-iceream
dpkg-buildpackage -rfakeroot
就可以将debian的包借用过来了。由于最新版本的ubuntu基于unstable,半年一换,所以基本上编译系统差别不大。一般都可以编译成功为deb。而很多时候,debian的sid(unstable的别名)分支已经有了这个包,但ubuntu还没有来得及同步,这种时候应该首先想到从debian中借用包。
例如说:昨天有个同学要找一个包meep,说是ubuntu中没有。我随手打了个checkinstall的包,后来发现,在最新的sid中的science的部分已经有了这个包了。


2、如果debian中也没有怎么办?
查找网页:http://www.debian.org/devel/wnpp/
这里有已经有人提了要求要上传的包,如果这里面有你所要求的包,那么也许只要等待一段时间,就可以享用了。当然也有可能从此就没有了音信~~例如我下面说的libsbml包──已经等待了三年了还在prepare中。
如果已经有了这个包名,但是却没有音信,那么应该首先和这个包的maintainer联系,问问为什么没有维护下去,如果没有这个包名,那么就要想想是不是应该自力更生了。

注意我们这里不管是wishlist(提出要求)还是自力更生,都要用reportbug工具来更新bug状态。

3、自力更生
怎样创建包可以说的东西很多,有各种各样的方式,也有很多要注意的地方。具体可以:

代码: 全选

apt-get install maint-guide-zh debian-policy
来查看,这里只讲我自己的经历就好了。

3.1 前期准备
一般的编译环境什么的恕不多说了。我要讲的是密钥的生成和干净的编译系统的生成。

代码: 全选

gpg --gen-key
选择都是默认的就行了,一路傻瓜化的填好自己的名字,邮件地址,这样会生成你的公钥和密钥。这在后面的编译签名和上传验证中是需要的。

代码: 全选

gpg --export --armor your-email-address > public-key-file
这样你的公钥文件就生成好了,以后别人只要

代码: 全选

apt-key add public-key-file
就可以对你签名的文件验证了。

我们的系统是ubuntu,哪来的debian安装环境呢?难道要装虚拟机?
这里我们用一个工具debootstrap来构建debian基本系统。
首先

代码: 全选

sudo su 
变成root

代码: 全选

debootstrap sid /sid-root http://debian.ustc.edu.cn/debian
echo "proc /sid-root/proc proc none 0 0" >> /etc/fstab
mount proc /sid-root/proc -t proc
cp /etc/hosts /sid-root/etc/hosts
chroot /sid-root /bin/bash
现在,这个目录就是你的纯净的debian sid系统了。以后想要进入只要sudo chroot /sid-root 就可以进入了。可以在这个目录里apt-get,和真实的系统一样。以后,我们的编译环境就是在这个系统中完成的。

3.2 制作包
首先下载包的官方压缩包libsbml-2.3.4.zip(一般来说,新维护者不要先打太复杂的包。也就是说不要什么内核模块阿,多包阿,库阿,不是用tar.gz,tar.bz2格式压缩的源码阿之类的)
解压缩,进入libsbml-2.3.4目录

代码: 全选

dh_make -e panchoat@gmail.com -f ../libsbml-2.3.4.tar.gz
选择最后一项,也就是用cdbs的方式打包。这种方式比较傻瓜化,很方便,相对比较新。初学者建议用这种方式。
这样已经将debianize的框架做好了。
最后我还是用的debhelper的方式打包。因为cdbs太傻瓜化,定制能力还是不如debhelper的好,而这个lib包又确实有点变态(也不能怪上游作者,这个包是windows native的,能够支持linux和mac就不错了),要改的地方颇多。

如果试过debhelper的打包和cdbs的打包,最明显的区别就是debian/rules文件。cdbs的明显要简洁很多,很多包甚至只要include一下就好了。而debhelper则不然,充斥着大量的细节,比较象原始的makefile,只是在最后有一个以dh_xxxxx的脚本段,在这里可以帮你把一些工作省略。

如果源码包不是bz2或者是gz怎么办呢?
要明白这个问题,首先我们要知道dh_make帮我们做了什么。它将源代码包变成packagename_version.orig.tar.gz的形式。在最后的生成deb的时候,对这个orig的压缩包和我们修改过的目录中的文件进行比较,生成diff.gz文件。但是如果不是gz或者是bz2的格式的源码包,dh_make是不能帮你完成这个转化的。所以其实,上面的libsbml.tar.gz是省略了将libsbml-2.3.4.zip解包,然后将其中的CVS目录都删掉,然后重新打包成libsbml-2.3.4.tar.gz过程。注意这个过程不要违反debian policy。另外,最好在debian/README.Debian-source中说明一下你是怎么进行改动的。让别人可以复制这个过程。还要说明为什么要改动。

单源码,多packages的打包。
对这种情况,我们一般用debhelper比较好,cdbs也可以,但没那么自由。
比如说我要从source libsbml打包出libsbml1, libsbml-dev ,python-sbml,sbml-examples,libsbml-java,libsbml-perl,libsbml-lisp这n个包,首先在control中加入各种包的说明,这个可以参看例子或者是apt-get source 之后看看别人是怎么写的。
然后,创建 python-sbml.install python.dirs libsbml-perl.manpages等等,注意,这些文件(install,dirs,docs,manpages……)在单源码包打包时,就是所要打的包的配置文件,在多包中,就是前面的子包的配置文件。不管是cdbs,还是debhelper,都会通过这些配置来进行打包。所以说这个方法是通用的。

如果是debhelper打的包,默认的rules文件中有一行
dh_install

改成
dh_install --sourcedir=debian/tmp
具体的dh_xxx是怎么用的,可以man一个看看。

因为默认的安装的位置在debian/tmp。所以我们要将这个完整的tmp目录中的内容瓜分,就重新将这个目录定为源目录,等于是编译的顺序是这样的:
a、以debian的要求的位置编译代码。(例如gconf不能在/etc目录下,java的jar文件应该在/usr/share/java下,不能利用/usr/local目录等等)
b、将文件编译后“安装”(也就是复制拉)到debian/tmp目录下,这个目录就是假想的系统的根目录了。
c、将这个“根目录”的文件复制到debian/package-name目录下,由于package-name不同,所以就成功的实现了瓜分。


libsbml-java.install:
usr/lib/jni/libsbmlj.so
usr/share/java/libsbmlj.jar
这说明这个包只是将debian/tmp/usr/lib/jni/libsbmlj.so和debian/tmp/usr/share/java/libsbmlj.jar两个文件复制到debian/libsbml-java子目录下面去。

另一个包g2ipmsg的debian/manpages
debian/g2ipmsg.1
debian/g2ipmsg_applet.1
说明这两个文件是要安装的man文件,系统会自动对他们进行处理的了。
debian/libsbml1.links:
usr/lib/libsbml.2.3.4.so usr/lib/libsbml.so.1
将前者做一个符号连接到后者。
还有很多对应的脚本什么shlib(对共享库的本地定义)拉,postinst,postrm,prerm,preinst,(在安装/删除 包 的 前/后 执行)等等等等,可以说,debian中为方便维护者,创造的工具真实太方便了~~~

在cdbs中也有类似的配置。如:
configure/package-name::
(a tab key) pod2man --name g2ipmsg --section 1 --center=g2ipmsg debian/g2ipmsg.pod > debian/g2ipmsg.1
就是对配置后,编译前,所要执行的命令,也有很多阶段的选项,自己看看/usr/share/doc/cdbs下面的说明就好了。

代码: 全选

rm -rf debian/*.ex
rm -rf debian/*.EX
删掉多余的模板文件。
主要的要编辑的文件有三个:
changelog:记录了修改信息,还有打包者,邮件地址,时间等等。

小tips:时区信息可以用822-date命令生成
rules:怎样编译的配置文件。(其实就是makefile文件,debhelper和cdbs的也不例外)
cdbs系统对一般的配置项都已经默认了,而且有各种各样的mk模板可以套用,直接include就好了。具体可以看cdbs-doc包中的介绍。
control:对依赖的记录,对包的类型的记录等等。
有一个比较常用的脚本,用于检查编译依赖。

代码: 全选

strace -f -o /tmp/log ./configure
# or make instead of ./configure, if the package doesn't use autoconf
for x in `dpkg -S $(grep open /tmp/log|\
        perl -pe 's!.* open\(\"([^\"]*).*!$1!' |\
        grep "^/"| sort | uniq|\
        grep -v "^\(/tmp\|/dev\|/proc\)" ) 2>/dev/null|\
        cut -f1 -d":"| sort | uniq`; \
        do \
                echo -n "$x (>=" `dpkg -s $x|grep ^Version|cut -f2 -d":"` "), "; \
        done
将这些搞定之后,可以试着

代码: 全选

dpkg-buildpackage -rfakeroot
编译试试,然后反复修改,直到可以正常编译为止。

对修改进行些补充:
我们的修改大多在这么几个地方:1、对编译报错的源代码的修改 2、对makefile.in或xxx.m4文件的修改,也就是对编译的参数进行修改。 3、debian/目录下的文件的修改。
在制作包的时候,由于有orig.tar.gz的存在,所以可以生成一个简单的diff.gz文件,这个文件记录了所有的修改,包括在debian目录下的或者是debian外的。但是我们知道,对于1,2这两种修改,很不直观,经常不知道到底是在哪里修改了。要改回来也不方便。所以,我们推荐使用dpatch系统,这样所有的修改都在debian/目录下,我们如果对什么部分需要撤销修改也方便。而且还有个好处,就是只要将debian目录放到源代码目录下就可以使用dpkg-buildpackage了。源代码是“干净的”。
dpatch的使用可以看manpage,这里只讲简单的。
1、创建patch
在源代码目录执行:

代码: 全选

dpatch-edit-patch <patch_name>
然后进行修改,退出shell的时候会生成一个patch文件。
将生成的patch加入到debian/patches/00list中
所有的patch都在debian/patches/目录下
还有

代码: 全选

diff -u source-tree-original/the-file source-tree/the-file | dpatch patch-template -p "number_short_desctiption" "What the patch is doing" >   path/to/debian/patches/number_short_desctiption.dpatch
2、测试patch

代码: 全选

dpatch apply-all
dpatch deapply-all
分别是应用patch和回复
3、将dpatch加入到rules中。
include /usr/share/dpatch/dpatch.make
……
……
clean: unpatch
……
……
这样,在每次开始编译时时,就会将dpatch都应用了。

例如说libsbml,如果要加入matlab支持,就必须修改Makefile.ac,而且必须用g++-3.4才能编译,g++-4.x是不能编译成功的,还有很多细节的小地方。挺烦人的,不过一般这么烦的比较少见。象上面提到的meep,就基本上不需要改。只要rules中添加一个
DEB_CONFIGURE_EXTRA_FLAGS = --with-libctl=/usr/share/libctl3参数就可以了,根本不用改其他。

我编译的库函数包,按照debian的政策,共享库得有个SONAME,这样可以解决在不同版本的共享库同时存在时的并存和兼容性,最好的例子就是libc6和libc5的关系。但是这个库没有在连接中加入这一项。要修改make-file-actions.mk文件。按照debian政策,如果编译选项变了的话,是必须更改soname和packagename的。否则会不兼容。所以对以后的上游包,也必须同样更改。

编译到最后,会用changelog中的打包者和邮件名的那个key来加密,最后会提示你用于验证的密码,就是你自己最开始生成时用到的。这样打好的包,别人可以相信是你,而不是什么危险分子打的包。

3.3 打包质量检查

代码: 全选

linda package-version.changes
lintian package-version.changes
piuparts binpackage-version.deb
这三个工具都可以直接apt-get得到,它们都可以告诉你你打的包有什么地方不合规范。对不合规范的地方要进行修改。
lintian会对你的包有什么错误进行检查,并给出一个tag告诉你是什么错误。要知道这个错误的详细解释,用下面的命令:

代码: 全选

lintian-info --tags some-error-or-warnning-tags
3.4 上传到debian官方。
首先在http://mentors.debian.net创建账号,这时,你要注册你用于打包的全名和邮件地址,还有提供你刚才建立的key文件。建立好账号之后,你要用dput或者是dupload工具来上传:
dput:配置文件 ~/.dupt.cf
[mentors]
fqdn = mentors.debian.net
method = ftp
login = anonymous
incoming = .
allow_unsigned_uploads = 0
run_dinstall = 0
progress_indicator = 2
passive_ftp = 1

代码: 全选

dput mentors cream_0.32-2_i386.changes
dupload: 配置文件 ~/.dupload.conf
package config;

$cfg{'mentors'} =
{
fqdn => 'mentors.debian.net',
incoming => '/',
dinstall_runs => 1,
passive => 1,
};
1;

代码: 全选

dupload -t mentors cream_0.32-2_i386.changes
之后你要等待sponsor(不是赞助人的意思哦!是指debian developer,他们才有权直接上传到debian系统)审查你的包,然后上传到官方。
在这个过程中,可能会有几个回合的交流,对不合规范的地方进行修改等等。当然,你也可以直接联系你认识的developer,这样被sponsor检查的速度和方便程度都好点。当你想直接加入debian计划的时候,也可以由你认识的sponsor给你的key签名,之后加入。

有些包是多维护者的,这种情况会比较方便,如果需要更新,当其中任何一个维护者有时间时,都可以维护,这样对包的管理更方便。
alioth.debian.org:
首先在这里注册,你的mentor会把你加入到具体的组织里,然后开始用svn和你的合作者一起管理你的包吧。也就是把debian目录的内容加进去就可以了。

代码: 全选

svn-inject  yournewpackage.dsc svn+ssh://[EMAIL PROTECTED]/svn/debian-med/trunk/packages/.
将我要的包get到本地

代码: 全选

svn co svn://svn.debian.org/svn/debian-med/trunk/packages/libsbml/trunk libsbml
merge模式要自己将orig.tar.gz添加入。

代码: 全选

mkdir tarballs
cp where-the-gz-is/libsbml_2.3.4.orig.tar.gz tarballs
然后我们就可以在libsbml子目录下进行svn-buildpackages了。
对加入的修改,我们记得要svn commit 提交上去。注意,要加上-m 参数,添加log。

有修改会更正。以后可能会把编译包的部分详细讲讲。
2007.1.23修正
加入source package的格式问题。
加入library package的要求。
加入cdbs和debhelper比较。
2007.1.26修改
加入为什么要上传的理由。
加入lintian检查错误。
加入单源码,多包的打包。
2007.2.5修改
加入dpatch系统说明
加入多maintainer维护和alioth说明
2007.2.7修改
加入svn工具使用。
上次由 xiechy 在 2007-02-07 17:28,总共编辑 6 次。
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙

#2

帖子 eexpress » 2007-01-22 13:09

这么详细的文章哦。那公钥文件不是源统一的吗?
● 鸣学
xiechy
帖子: 1074
注册时间: 2006-01-18 15:01

#3

帖子 xiechy » 2007-01-22 14:05

是把所有官方developer的密钥打包了吧。每个作者的都是不一样的。对于非developer的maintainer,会有一个developer做你的sponsor,他负责上传,你是他的下线,他会对你的签名进行签名(用他自己的key,这句话好碍口),所以最后的系统中,只要有他的就可以了。
头像
freeflying
帖子: 521
注册时间: 2005-03-26 9:38

#4

帖子 freeflying » 2007-02-09 12:29

如果需要上传到ubuntu官方源的,可以找我sponsor。 :)
图片
xiechy
帖子: 1074
注册时间: 2006-01-18 15:01

#5

帖子 xiechy » 2007-02-10 17:00

谢谢freeflying!
呵呵,现在debian的包还没传上去呢,在svn里待着,主要是licence的问题,sponsor是早有了,还有两个做backup~~~感觉debian确实有点GNU偏执狂了,连对contrib section都反感的很。现在有点知道为什么ubuntu会比debian更受欢迎了,毕竟大多数人对GNU还没有到偏执的地步,只是要一个好用的系统就可以了。
头像
freeflying
帖子: 521
注册时间: 2005-03-26 9:38

#6

帖子 freeflying » 2007-03-02 16:22

你现在维护的是什么包?
图片
xiechy
帖子: 1074
注册时间: 2006-01-18 15:01

#7

帖子 xiechy » 2007-03-09 14:40

是libsbml,都快出version 3了,2的这个包还是等待状态中吧,sponsor要求不要对non-free的latex2html的依赖,但是编译文档时的makefile是perl的脚本,对latex2html依赖太重,修改很麻烦,我perl又不熟,然后现在他提出了对latex2html作者的请求,要求用GPL发布latex2html,之后就没有音信了~~

这是co-maintianer的包,包括我有3个maintainer,有两个人赞成把文档编译部分暂时就停掉,但是sponsor不赞成。
现在反正自己用上包,但是对debian developer的GNU偏执症也深有体会~

version 3应该就不会依赖latex2html了,所以对版权问题,我们也只有等待的份~
回复