Packaging for Debian and Ubuntu
前期准备
安装虚拟开发机
- 你需要 VirtualBox, 可以在 下载页面 取得。
- 你需要 Ubuntu 的 ISO,可以在 Ubuntu 台湾站 取得,大陆的下载太慢。32 位的就行。第一个原因是 Ubuntu 的 64 bit 做的太差; 第二个原因是如果你选择 PPA 作为分发源的话,Launchpad 对 64 位的编译要排很久的队,严重影响我们的效率。
安装虚拟机。需要注意的是:
- 2D 视频加速是开启不了的。因为那个只支持 Windows 作为虚拟机。
- 不要给超过 1 个 CPU。那样只会慢不会快。
- 显存给大点
- IDE 控制器请用 PIIX4 而不是 ICH9, 后者属于实验性的且只支持 Windows 作为虚拟机。
- 使用默认的 8GB 就够用。我们只是作为开发机,不装软件。
配置虚拟开发机
piix4_smbus: SMBus base address uninitialized
装好了的 Ubuntu 开发机在开机时会跳出一条错误信息: "piix4_smbus 0000.00.07.0: SMBus base address uninitialized - upgrade bios or use force_addr=0xaddr"
原因是 Virtualbox 是没有 smbus 的。但 Ubuntu 就要它。
解决办法是进入 Ubuntu 之后,打开终端(找不到的可以在 unity dash home 里面搜索 terminal,不是 konsole,这点和 openSUSE 有点不一样),由于 Ubuntu 默认安装后是没有 VIM 的,在命令行直接编辑文件有些困难,我们把要改动的文件权限从 root 改成 users:
sudo chmod 777 /etc/modprobe.d/blacklist.conf
打开它,在最后面添加 "blacklist i2c_piix4",然后把权限改回去:
sudo chmod 644 /etc/modprobe.d/blacklist.conf
最后更新一下引导缓存 initramfs
sudo update-initramfs -u -k all
或者直接用命令行来做:
sudo echo "blacklist i2c_piix4" >> /etc/modprobe.d/blacklist.conf //注意是 >> 而不是 >,后者会把原来的文件抹干净。 sudo update-initramfs -u -k all
这样开机就没有这个错误了。
安装虚拟机的驱动
首先你得先安装 synaptic(新利得),Ubuntu 默认没带这东西,是不是很崩溃?openSUSE 没有版权多媒体编解码器就很让人崩溃了,居然还有连软件管理器都不带的发行版。我以为只有腾讯微信跟腾讯 QQ 抢生意,没想到这还有一例争抢 "现金牛" 的例子。
打开 Ubuntu Software Center,搜索 synaptic,你要搜索两次,第一次你搜到它,它下面是有一个 "use this source" 的按钮,点它不会安装,而是添加了一个软件源,我当初就是以为安装了,等了老半天没装上才知道。第二次点它才是下载并安装。然后在 dash home 里面搜索 synaptic, 把它拖到左边面板上,同样的还有 terminal,Ubuntu software center 就可以寿终正寝了。
我们之所以要安装新利得是为了安装 kernel-devel 这个包,但是 Ubuntu 不叫这个名字,很让人崩溃,叫做 linux-headers-generic-pae,有了它才能编译 Vitualbox 虚拟驱动的内核模块。
这个步骤是没法用命令行来完成的,因为一开始什么软件源都没启用,apt-get 是没用的。
然后点击 Virtualbox 的视图,安装增强功能,Ubuntu 会自动挂载这个 ISO 并弹出提示,跟着提示走就可以。
安装开发必备的软件包
有几类软件包你需要安装:
- deb 开发相关的软件包。用新利得或者命令行安装如下软件包:
sudo apt-get update sudo apt-get install dpkg-dev debhelper dh_make devscripts vim //这里一定要把 vim 装上,不然你以后编辑文件的时候都要用 gedit,会很麻烦。
- OBS 上传相关的软件包(可选)
首先要添加 OBS 的软件源 openSUSE:Tools。找到 OBS 给 Ubuntu 使用的软件源的方法是:进入 build.opensuse.org,在右上角的 search 里搜索软件源的名字,进入软件源页面,在右边找到你的发行版,点名字,然后 go to download repository,随便找个文件点 details,MirrorBrain 最下面会说 found n mirrors in other parts of the world,里面有个地址比如是:
http://widehat.opensuse.org/repositories/openSUSE:/Tools/xUbuntu_12.04/Packages
去掉你刚才随便点的那个文件名字比如 Packages,就是给 apt-get 用的软件源:
http://widehat.opensuse.org/repositories/openSUSE:/Tools/xUbuntu_12.04/
添加方法:新立得是在 Settings - Repositories - Other software - Add,APT-Line 写:
deb http://widehat.opensuse.org/repositories/openSUSE:/Tools/xUbuntu_12.04/ ./
然后点 Add Source。
接着使用新立得搜索 osc,安装。上面那些麻烦步骤同样也可以用命令行来简化:
sudo echo "deb http://widehat.opensuse.org/repositories/openSUSE:/Tools/xUbuntu_12.04/ ./" >> /etc/apt/sources.list sudo apt-get update sudo apt-get install osc
- PPA 上传相关的软件包(可选)
sudo apt-get install dput
打包步骤
配置你的姓名和邮件地址
cat >>./.bashrc <<EOF >>DEBEMAIL="your.email.address@example.org" >>DEBFULLNAME="Firstname Lastname" >>export DEBEMAIL DEBFULLNAME >>EOF 其中第一行是你初始要输入的命令,然后会给出一个以 >> 开头的命令行中的命令行, 在里面输入三行内容,输入 EOF 是保存并关闭。
vi .bashrc //查看一下对不对。
处理上游源代码包为 orig.tar.gz/bz2
首先你需要解压上游的源代码包,比如:
tar.gz: tar -xzvf source-version.tar.gz tar.bz2: tar -xjvf source-version.tar.bz2 tar.xz: tar -xvf source-version.tar.xz
当然如果你直接用压缩管理器解开了,没有压缩包,你可能需要重压缩一下:
tar.gz: tar -czvf source-version.tar.gz source-version tar.bz2 tar -cjvf source-version.tar.bz2 source-version
原始的压缩方式不要删,然后进入源代码目录:
cd source-version <== 一般源代码目录都是 名称 + 版本号 这样的格式命名的。
在源代码目录里运行:
dh_make -f ../source.tar.gz|bz2 //压缩后缀看你的选择,一般用 bz2, 比 gz 压缩能力强一些。 //但要是源代码目录就没到 1MB,随便了,省不了多少。
会问你:
Type of package: single binary, indep binary, multiple binary, library, kernel module, kernel patch? 软件包类型:单 .deb 软件包,预编译好的独立二进制包,多个 .deb 软件包(一个主包带一堆子包),库文件,内核模块,内核补丁? [s/i/m/l/k/n] s 我们一般选 s,毕竟一个 RPM 党给 deb 系打包也不会去做太难的么。
然后它会接着问:
Maintainer name : Marguerite Su Email-Address : marguerite@unknown Date : Wed, 13 Jun 2012 21:25:16 +0800 Package Name : kdoubanfm Version : 0.2 License : blank Type of Package : Single Hit <enter> to confirm: 回车
会自动在 source-version 目录的上一层目录,也就是 source-version.tar.gz|bz2 的同级目录下创建一个名为 source_version.orig.tar.gz|bz2 的压缩文件,这个就是 deb 用的源代码包。同时还会在 source-version 目录创建一个 debian 子目录,里面是一些打包的标准命令文件。
修改打包命令文件
进入 debian 目录:
cd debian
删除无用帮助文件
删掉后缀是 .ex 和 .EX 的文件,不然如果你没编辑它们并重命名为不带 .ex/.EX 后缀的同名文件,在打包完成的 lintian 检查时会有一条错误叫做:Debin 帮助文件被打包进了 .debian.tar.gz
rm -rf *.ex rm -rf *.EX
至于 .ex 和 .EX 是干嘛的,看下面这个列表:
- emacsen 开头的是针对基于 emacs 这个 IDE 的名为 emacsen 的编辑器的安装/删除/启动脚本。是打包类似 emacsen 插件这样的程序才会用到的。但是 emacsen 这个项目 2007 年就不更新了。于是无用。
- initd.ex 是启动脚本,你的软件要开机自启动,才需要去编辑并重命名它,比如输入法。否则无用。
- cron.d.ex 定时服务。除非你的软件有服务,并需要按周期运行。否则无用。同理 default.ex 也是这样。
- doc-base.EX 是 deb 系专用的。大概意思是告诉系统各种不同格式的帮助手册在哪里可以找得到。你在乎手册吗?
- manpage.*.ex 是具体的各个格式的帮助手册。
- post*.ex 跟 RPM 系的 post 一样。postinst 管安装,postrm 管删除。一般是库文件会用。而且这个无需你去干预,改名去掉 .ex 就可以,dh_installdeb 会自动帮你填写。
- watch.ex 是 Debian 专有的,意思是关注某个 url,有变化就邮件通知你来升级。跟 OBS 的 auto check 差不多。除了更新狂谁都用不到。而且里面是用正则表达式写的,要是不懂就算了吧。
接着要删除 README*。
rm -rf README*
其中 README.debian 是类似于 RPM 的 changelog 这样的一个存在。比如你加了补丁,改动了什么,写进去。 README.source 是描述源代码是否满足 Debian 策略的文件,我们打的包都不通过 Debian 官方分发,管它做什么。
修改编译控制文件
于是我们还剩下:changelog compat control copyright docs rules source/format 这些文件。
- compat 和 source/format 是不用改的。
- docs 跟 RPM 文件章节中的 %doc 标签一样的作用,你要在这个文件里罗列源代码目录中想要成为 docs 的文件名,比如 AUTHORS ChangLog 这些。
- rules 除非你需要添加 ./configure --? 或 cmake -D? 中的参数,需要使用:
override_dh_auto_configure: dh_auto_configure -- \ -DCMAKE_INSTALL_PREFIX=`kde4-config --prefix` \ -DENABLE_WEBKIT=1
或者
override_dh_auto_configure: dh_auto_configure -- \ --with-webkit
来覆盖默认的参数,否则不用改。
- changelog:
首先是 unstable,如果你选择上传 OBS,那这里不用动,但如果你选择上传 PPA,这里就需要改成 Ubuntu 的那些古怪名字,比如 oneiric/precise,不然即使上传成功 Launchpad 也会发邮件告诉你:"Unable to find distroseries: unstable"。
其次是编辑具体的 changelog 条目是需要注意,格式和 RPM 的 changelog 是一样的。唯一不同就是,你前面必须有一个空格,而且条目的上下行中间不能有空格。否则就视为 changelog 中止。那样 dpkg 最后就会找不到你的日期和作者签名。
另外如果你选择上传 launchpad,成功了之后又改动了一些东西,再上传可能会邮件通知你这个错误:
File source-version.debian.tar.gz already exists in whose ppa, but uploaded version has different contents
这时你需要编辑 changelog 在 0.9.2-1 这样的 版本号 + 释出号 格式里把释出号加一,变成 0.9.2-2 再上传就没有问题了。
- copyright:
首先是 source:,把你下载源代码的项目 url 贴上去。其次是 License,如果你用的不是 GPL 系列,就需要对照下面的文本写/贴; 如果你用的是 GPL,就把上面的帮助行删掉用下面默认的 GPL License。
由于只有 Debian 和 Ubuntu 的官方包才会查授权文件,我们一般都用默认给的 GPL。
- control
Homepage 就是上面 copyright 的 source 相同的 url。
Standards-version 改成 3.9.3。不然 lintian 打包检查会报错。
Description 跟 changelog 的写法一样。需要注意的是,第一行相当于 RPM 的 spec 范式文件中的 Summary,下面的才相当于 %description。
Section 根据你是给 Debian 或 Ubuntu 打包,分别去 http://packages.debian.org/en/sid/ 或 http://packages.ubuntu.com/en/oneiric/ 查找就可以(两者其实差不多),分类名就是 Section 名。
Build-Depends
如果你可以找到一个 RPM,那么它的 BuildRequires 就是你的参考对象,唯一不同的是包名,你需要去 package.debian.org 或者 package.ubuntu.com 去搜索,找到这个包在 deb 系发行版中的通用名,比如 libkde4-devel 在 deb 系发行版就叫做 kdelibs5-dev。
如果没有这样的 RPM 供你参考,你需要去项目网站找找有没有 compile/build 这样的内容,里面会有依赖关系。或者:
- 如果是 cmake 的,也就是说有 CMakeLists.txt 这样的文件,就去那里面找 find_package 字段,会提示你依赖关系。
- 如果是 configure 的,那就在本地运行一下,缺的包会告诉你。(反正你一会儿也要安装这些包进行本地编译。)也可以打开它,查找一些关键词,比如 found,因为 configure 是类 makefile 文件,找不到依赖关系的错误提示也写在里面,一般都是 xxx not found。找到它,你就知道需要用什么作为依赖关系了。
本地编译测试
下面你需要使用 sudo apt-get install 来装上你前面在 Build-Depends 里写上去的依赖。然后使用:
dpkg-buildpackage
来进行本地编译测试。过程没有什么好说的,如果不是依赖关系缺失一般不会出错。
如果出现这样的警告:
gpg: skipped "Marguerite Su <marguerite@unknown>": secret key not available gpg: [stdin]: clearsign failed: secret key not available [...] dpkg-buildpackage: warning: Failed to sign .dsc and .changes file
请放心,这是因为你没有制作 openpgp 金钥来给你的作品签名。但在上层目录还是会有你的作品的 .deb 的。
至于怎样制作金钥并签名将会在下面讲。这时你上层目录的文件就可以被上传到 OBS 来进行编译分发了,OBS 会自动提供一个经过认证的金钥。但如果你最终选择上传 Launchpad,那么你还需要多走几步,而且这几步非常麻烦。
上传并分发
上传到 OBS 构建服务
准备工作
你需要在 build.opensuse.org 申请一个帐号。然后在网页上创建你的 home repository,在 Repository Tab 下面选择 .deb 系列的发行版的名称和具体版本,添加那些源。具体 OBS 支持的 .deb 系发行版的列表请见:Build Service Debian builds。
开始上传
用于上传到 OBS 上的文件有:
- *.dsc
- *.debian.tar.gz
- *.orig.tar.gz|bz2
首先新建一个 OBS 工作目录:
mkdir OBS cd OBS
然后撷取你的 home:
osc co home:MargueriteSu
第一次使用 OBS 会让你输入你在 b.o.o 的用户名密码(密码是看不见的)。
由于它是空的,所以会很快。然后创建一个软件包
osc mkpac kdoubanfm cd kdoubanfm
把那三个文件移动到这个软件包的工作目录下:
mv /home/marguerite/*.dsc ./ mv /home/marguerite/*.debian.tar.gz ./ mv /home/marguerite/*.orig.tar.gz|bz2 ./
把这三个文件添加到 osc 的上传序列中:
osc add * //查看一下 osc status
然后上传:
osc ci
至此,完成。你可以在网页上观察编译的进展。一般来说,如果不是在 Ubuntu 12.04 precise 上创建的软件包然后拿到 OBS 的 Debian 6.2 去编译的话,是不会出错的。
如果你想实机测试一下的话,可以选择上文中提到过的添加软件源的方法(openSUSE:Tools 的例子),也可以直接下载 binary,方法是在你的软件包首页,点击软件源名称,比如 xUbuntu_12.04,接着点击那个 .deb 的名字,就能下载到还没公布在软件源上的 .deb 文件了。
上传到 Launchpad PPA
准备工作
你需要在 launchpad 注册一个帐号,并创建一个 PPA。
方法是点击右上角你的帐号,在帐号管理页面:Personal package archives - Create a new PPA。
准备 OpenPGP 金钥
分为在本地计算机中准备和在虚拟开发机中准备两种。为了更好的覆盖性,本地计算机使用 KDE 系统,虚拟开发机是 Ubuntu 的 Unity 也就是变种的 GNOME(部分程序是相通的)。
在虚拟开发机中准备(简单)
- 创建金钥
首先在 dash home 中搜索 key,打开 Passwords and Keys 程序。File - New - PGP Key,然后就是填空题。
- 同步金钥
选中你创建好的金钥,Remote - Sync and Publish Keys,然后选择 Key servers,在 Publish keys to 的下拉列表里选择 keyserver.ubuntu.com,这个只要 10 分钟就可以被 launchpad 识别,其他的需要 2 小时。下面的两个勾也打上,close。
然后点击同步,等 10 分钟。
在 launchpad 的账户管理页面,点击 OpenPGP keys 这个分类右上角的编辑,会进入一个 Import an OpenPGP key 的页面,需要你创建的金钥的 fingerprint 指纹。该指纹可以在 Passwords and Keys 程序的 My personal keys,右键点你创建的金钥,Properties - Details 中找到。
粘贴进去,点击 import key,过一会儿会金钥中指定的邮箱会收到一封来自 launchpd.net 的邮件。里面有一封加密信。这封加密信大部分 Linux 下的邮件客户端都能阅读,但存在着一个问题:你要在虚拟机中安装该客户端,或者把你创建的金钥导入到你的本地计算机中。这就麻烦了。Gmail 可以配合 FireGPG 这个火狐扩展直接看,但问题也一样,你可能用的是本地计算机打开的这封邮件。
我们使用最简单的办法,先把加密的内容,从 "-----BEGIN PGP MESSAGE-----" 到 "-----END PGP MESSAGE-----" 的内容复制到一个 email.txt 里,然后在虚拟机的终端中使用:
gpg -d email.txt
就能在终端里看到一个链接,复制那个链接在浏览器中打开,是一个 launchpad.net 的链接,跟随指示,OpenPGP 金钥就添加完成了。
在本地计算机中准备(复杂)
如上所述,本地计算机使用 KDE 桌面。我们先 alt + F2 打开 krunner,输入 kgpg 回车,打开 kgpg 金钥工具。
Keys - Generate key pairs, 输入用户名和电子邮件(注意上面的注意),确定,输入密码,就会生成好一个金钥。
然后选择 Key server dialog(密钥服务器对话框)- export(导出),点击下面的导出按钮。
这回等的比较久,因为 KDE 下没有 Ubuntu 的 keyserver 嘛。快捷的方法也是有的,且不只一种,当然最简单的就是干等:
- kgpg 中点击创建好的密钥,点上面的导出,导出一个 i.asc,然后邮件也好,Virtualbox 共享文件夹也好,传到虚拟机中去,在虚拟机的 Passwords and Keys 的 File - import 导入,再上传到 Ubuntu 的 keyserver。太麻烦。
- 我们注意到虚拟机的 Passwords and Keys 中 Remote - find remote keys 中有三个服务器地址:keyserver.ubuntu.com, pool.sks-keyservers.net 和 keyserver.pgp.com。我们只要访问 keyserver.ubuntu.com, 在 kgpg 中导出公钥,打开导出的那个文件,把里面的内容贴到网页上,然后 submit this key to the keyserver!就可以了。这样就能解决 launchpad 那边的问题了。在 Passwords and Keys 中 find remote keys 找一下,就能从服务器导入金钥到本地了。
但是我们导入的其实是一个公钥,OpenPGP 对你的软件包签名时候还需要一个私钥。由于设计的原因,私钥的意义就在于谁也不知道,所以通过服务器来传递是不可能的。有两种方法:
- 命令行
公钥就不说了,下面的命令去掉 secret key 的部分就是导出公钥的。
marguerite@linux:~>gpg --list-keys /home/marguerite/.gnupg/pubring.gpg ----------------------------------- pub 1024D/C9B9ECD4 2012-06-07 [有效至:2013-06-07] uid Marguerite Su (瑪麗蘇的百合 PPA) <marguerite@unknown> sub 1024g/1C79C962 2012-06-07 [有效至:2013-06-07]
这样列出所有公钥,红色字的部分就是金钥的 ID,remote import 的时候需要知道的。后面打包的时候也是需要知道的。kgpg 的界面横向滚动条往右拉在 ID 中也能看到,Passwords and Keys 则直接显示为 Key ID。下面导出私钥:
marguerite@linux:~> gpg --list-secret-keys /home/marguerite/.gnupg/secring.gpg ----------------------------------- sec 1024D/C9B9ECD4 2012-06-07 [有效至:2013-06-07] uid Marguerite Su (瑪麗蘇的百合 PPA) <marguerite@unknown> ssb 1024g/1C79C962 2012-06-07 //先查看一下私钥的 ID gpg --export-secret-key -a C9B9ECD4 > secret.key
导出了私钥,接着拿到虚拟机上去:
gpg --import --allow-secret-key-import ./secret.key
- 图形界面
公钥就不说了。正常的导出功能导出的就是公钥。
用 kgpg 生成的,在 key 上点右键有一个 "导出绝密密钥" 功能可以导出私钥,拿到虚拟机去直接 import 就导入了私钥。
用 Passwords and Keys 生成的,在 Properties - Details - Export complete key 可以导出私钥。
至此,金钥准备完成。
关于金钥的额外注意事项
首先是金钥应该有一个期限。上述的两种金钥创建工具都可以附加有效期限。到期更新一个金钥就是,方法同上。
其次已经上传到服务器的金钥是没有删除选项的。但是有 revoke 选项。
kgpg 的 Keys - revoke 可以吊销密钥。
Passwords and Keys 是在 Properties - Details 下面内置窗口中分别选中 ID,然后点左边的 revoke。
revoke 好了以后,再次同步到服务器上,这样那个金钥就不会被滥用了。
命令行版本是:
gpg --output ./revoke.asc --gen-revoke 金钥 ID //生成吊销信息 gpg --import ./revoke.asc //导入吊销信息来吊销密钥 gpg --keyserver keyserver.ubuntu.com --send-keys 金钥 ID //发送到服务器 //发送到一个服务器就会自动同步到所有服务器,这个不用担心。
接着你可以选择继续保留那个 revoked 金钥,这样如果后续收到该金钥加密的文件你不会素手无策,如果确认已经不会再有用该金钥加密的文件了,你可以删除这个密钥对。
生成用于上传的 _source.changes 文件
Launchpad 不接受 OBS 那样直接上传文件,它需要一个 source_version-release_source.changes 文件来做引导。生成方法为,在 source-version 目录:
debuild -S -sa -kC9B9ECD4
C9B9ECD4 是金钥 ID,与 -k 之间没有空格。
-sa 代表 include source,也就是上传 .orig.tar.gz|bz2 源代码包。也可以用 -sd,例如:
debuild -S -sd -kC9B9ECD4 // 不包括源代码包,主要适用于只改了 debian 目录中的控制文件这样的小升级。
如果初始上传使用 -sd,launchpad 会报错,错误代码是:
Unable to find source_version.orig.tar.bz2 in upload or distribution.
PS: 同样你有了金钥之后也可以使用:
dpkg-buildpackage -kC9B9ECD4
进行本地编译,不会有那个警告了。
开始上传
经历了千辛万苦,我们终于可以上传了。
dput ppa:i-5lmm/marguerite kimtoy_1.9-2_source.changes dput ppa:PPA 名称 source_version-release_source.changes
成功了!