Deb安装包的制作方法
1. 源代码准备
如果项目是一个eclipse项目,则首先确保项目在eclipse中至少以发行版本成功的编译过一次,这么做的目的是让eclipse生成需要的Makefiles,然后将项目复制一份出来,以后工作就针对这个拷贝进行。接下来对复制出来的源代码目录名称改成deb标准的形式:[package-name]-[version],如:
foobar-0.1.0
如果此项目有配置文件,则需要将配置文件以合理的方式组织到源代码目录中,并且一会还需要在第7节中描述的install中将这些配置文件安装(这是一个假的安装,参见第7节的描述)到目标位置上;
最后需要对目录内容进行清理,除了之前生成的Release目录中所有Makefiles以外,所有的编译的中间文件(*.[d|o])、隐藏文件、工程文件、源码控制文件最好都删除,即只保留源代码、Makefile和需要的配置文件。再将Release改名为build(可以是任意名,但在第7中的build-stamp和clean目标中应该与之对应),至此源代码准备完成。
2. 修改Makefile
对Makefile的修改主要是头文件包含路径的修改。进入build目录,打开所有的子目录中的subdir.mk文件,把编译选项中的不标准的头文件包含路径修改为标准的形式,如要使用libSESData的头文件,当前可能是“/home/user/workspace/LibSESData/include”,则可能需要将其修改成“/usr/include/libSESData”的形式,具体修改成哪个路径取决于依赖的目标库(这里就是libSESData)的dev版本的头文件安装位置。
3. 生成用于制作deb包的模板文件
在终端中进入到源代码根目录,运行命令:
foobar-0.1.0/ # dh_make –r –s
-r 指定创建一个新的包配置;
-s 指定创建只生成一个安装包的配置;
运行命令后,会显示包的汇总信息,直接回车确认即可。此时项目已经被debian化了(debianize),当前目录中已经生成一个叫做debian的目录,这个目录中就包含了与制作deb包相关的所有配置文件,以后的工作都围绕在这个目录中的文件展开。
在成功的创建模板后,如果安装包有一个发行版本号(如netbook0natick1),那么还要将源代码目录的名称追加上发行版本(如果在dh_make之前加上,dh_make会报错),如:
foobar-0.1.0netbook0natick1
4. 修改debian/control文件
在debian目录中有一个control文件,这个文件是安装包的一个定义文件,它至少包含两个段落(各个段落由一个空行分隔),第一个段落是源代码描述信息,从第二个段落开始,就是包的描述(定义),在同一个文件中可以定义多个包,它的内容看起来可能像下面这个样子(这里加上了行号信息):
1 Source: [package-name]
2 Section: unknown
3 Priority: extra
4 Maintainer: root <root@unknown>
5 Build-Depends: debhelper (>= 5)
6 Standards-Version: 3.7.2
7
8 Package: [package-name]
9 Architecture: any
10 Depends: ${shlibs:Depends}, ${Misc:Depends}
11 Description: <insert up to 60 chars description>
12 <insert long description, indented with spaces>
这个文件包含两个段落,第一个段落定义源代码信息,
第1行Source字段指定源代码包的名称,一般与包的名称相同;
第2行Section指定项目的一个分类;
第3行为优先级;
第4行为维护者的名称和email;
第5行比较重要,它指定了能够成功编译源代码所需要的依赖项的包名称,多数是项目依赖的链接的库的开发版本(例如程序使用了GTK,那么这里就需要加上 gtk2.0-dev的依赖了),多个依赖以‘,’分隔;
第8行这里指定的是包的名称;
第9行指定平台信息,保持其为any即可,在创建包的时候会根据所在平台自动检测;
第10行也比较重要,在这里指定程序的运行时的依赖库,如第5行指定了gtk2.0-dev,那么这里就应该有gtk2.0的运行时库的名称;另一方面,如果一切正常,此依赖关系会在创建包的时候自动检测,并保存在变量${shlibs:Depends}中,这个变量的值定义在debian/[package-name].substvars文件中,这个文件是在创建包的过程中自动生成的,在创建包之后应该查看此文件内容是否有未检测到的依赖,如果有,则手动将它们补在这一行中,并重新创建安装包。$(Misc:Depends)可以删除;
第11行Description指定包的描述信息,如果需要多行,则从第二行开始的每一行都应该以一个空格开始。
如果针对同一个项目需要创建多个包(如库的包可能需要一个运行时的版本和一个开发版本),可以仿照8-12行在文件后边追加新的包描述段落,每个段落声明一个包,各个包的名称不能有重名;
5. 修改debian/dirs文件
这个文件描述了包的的目录结构信息,其中的每一行是一个路径,不能以‘/’开始,例如包需要向“/usr/bin”下安装一个程序,那么这个文件应该有一行:“usr/bin”;
如果在control文件中定义了一个包,则使用debian/dirs文件来描述即可,如果定义多个包,则不应该使用单个的dirs文件,应该使用 [package-name].dirs的名称加以区分;
在创建包的时候,系统会为每一个在control文件中定义的包在debian目录中生成一个以包名命名的目录(这些目录中的内容就是对应包要安装的文件),同时根据dirs文件(或者[package-name].dirs)中指定的目录,在对应包的目录中生成需要的目录项。
在debian/rules(见第7节)中的dh_installdirs命令会根据这个(些)文件的内容在每个包对应的目录中创建指定目录项。
6. 修改/创建debian/links文件
这个文件描述了包在安装的时候需要创建的链接文件,其格式如下:
链接源文件1 链接名称1
链拉源文件2 链拉名称2
…
每一行定义一个链接,如果定义了多个包,则应该使用[package-name].links来对应每个包的链接。在创建包的过程中,debian/rules(见第7节)文件中的binary-arch目标下的dh_link会根据这个(些)文件进行链接的创建。
7. 修改debian/rules文件
这个文件本质上就是一个Makefile,创建包的过程中系统使用这个文件对源代码一个编译、安装(假安装),它包含几个标准的Target:
build-stamp 用于对源代码进行编译的目标,这里我们需要在这个目标下的命令列表的touch $@ 之前加入一行:
$(MAKE) –C build
让make执行我们之前准备好的build目录中的makefile,以对源代码进行编译。其中的“build”是在第1节中修改的包含Makefile的目录。
注:在创建包的时候所处的目录是源代码的根目录。
clean 系统在创建包的一第步会执行此目标,它应该负责将在创建包过程中生成的中间文件(目录)全部删除,我们在这里的dh_clean之前加上一行:
-$(MAKE) –C build clean
确保在clean的时候我们的源代码也是clean的状态。
install 这个目标是在“安装”的时候使用的,注意这是一个假的安装,我们需要在这里把安装包中需要安装的文件(包含之前提到的配置文件)复制到目录debian/[package-name]中去,这个目录就是映射到将来安装时的系统根目录。
注:
不要在这里创建文件夹,文件夹的创建参见第5节。
不要在这里创建链接,链接的创建参见第6节。
更不要在这里修改文件的权限,因为在这里修改权限是无效的,binary-arch目标中的dh_fixperms会对所有文件进行重新设置的。
8. 修改debian/[pre|post][inst|rm]脚本
如果安装包在安装/卸载的之前或之后需要做一些额外的工作,你可以将这些工作放到这些脚本中,进行,这样的脚本有四个:
preinst 在安装之前被调用
postinst 在安装之后被调用
prerm 在卸载之前被调用
postrm 在卸载之后被调用
9. 相关的信息文件
还有一些文件在标准的时候也需要处理的:
changelog 更改维护的记录文件,注意要修改其中的版本信息。(使用dch命令修改)
copyright 版权信息,比较重要,最好能够填写上。
10. *daemon的安装
如果你的项目是(或者需要安装)一个daemon程序,尽量不要在rules/install中进行,系统提供标准的方法来安装daemon,可以使用debian/initrc文件进行[未完待续……]
11. 创建安装包
当上面的一切准备完毕后,就可以创建安装包了,先删除由第3节dh_make生成的一些没有使用到的模板文件,然后在终端下进入源代码根目录,运行:
foobar-0.1.0/ # debuild –us –uc
如果没有错误,安装包就创建成功了,默认的安装包生成在源代码根目录的上一级目录中。
12. 注意问题
1. 在使用安装包安装之前,如果当前系统已经安装过相同版本的安装包,为了避免不必要的麻烦,应该将原版本进行彻底删除,然后再安装新的包,删除使用命令:
sudo dpkg –P [package-name]