Debian-maint-guide/3

来自Ubuntu中文
跳到导航跳到搜索

Debian新维护人员手册

第 3 章 - 修改源代码

通常情况下,程序会把它们自己安装到/usr/local子目录中。但是Debian的软件包绝对不能使用那个目录,因为它被保留给系统管理员(或者用户)使用。这就是说你必需要仔细看一下你的程序的构造系统(build system),通常从Makefile开始。它是make(1)将会使用的用于自动构造程序的脚本。要了解更多关于Makefiles的内容,请参考“rules”文件, 第 4.4 节。

注意如果你的程序使用了GNU的automake(1)和/或autoconf(1),也就意味着源代码是在Makefile.am和/或Makefile.in文件中,相应的,你需要修改这些文件。这是因为在每一次automake的调用中,Makefile.in等文件中的信息将会通过Makefile.am等文件来重新产生,并且每次调用./configure时,类似的操作会执行在Makefile等文件上,它们会被根据Makefile.in文件重新产生。修改Makefile.am文件需要一些关于automake的知识,你可以阅读automake的info项目,然而修改Makefile.in文件和修改Makfile文件是差不多的,不过要注意一下变量,例如,任何被“@”包围的字符串如@CFLAGS@或@LN_S@将会在每次 ./configure 调用时用实际的值替换掉。

还需要注意的是,在这里我们没有地方讨论所有的修改上游源代码的细节,这里我们只有一些人们经常会会遇到的问题。

3.1 在一个子目录中安装

大多数的程序都能够以某种方式把自己安装到系统现有的目录结构上,所以它们的可执行文件已经存在于你的$PATH中,并且你也可以在通常的位置找到它们的文档和手册。然而,如果你这样做,这些程序将会和你系统上的其它程序混合在一起。这样的话,对于打包工具而言要想把它们同不属于这个软件包的程序区分开就很困难了。

因此,你还必须要做一些其它的事情:把程序安装到一个临时的子目录中,从这里打包工具可以创建一个可以工作的.deb软件包。在这个目录中的所有内容都将会被安装到用户的系统中,当他们安装你的软件包时,唯一的不同是dpkg将会把这些文件安装到文件系统的根目录上。

这个临时文件目录通常创建在源代码目录的debian/子目录中。通常情况下,它的名字是debian/packagename。

有一件事情请记住,尽管你要把程序安装到debian/packagename目录中,但在安装.deb文件的时候,它仍应当可以正常地安装到根目录中。所以你绝对不能让软件包的构造系统把类似于/home/me/deb/gentoo-0.9.12/usr/share/gentoo的字符串写入到软件包中。

对于使用GNU autoconf的程序而言,这个工作是非常简单的。大多数这样的程序的makefile脚本缺省状态下就允许程序被安装到任何的子目录中,并以(例如)/usr 作为它的典型前缀。当检测到你的程序使用了autoconf时,dh_make发现将会自动设定命令完成这一任务,因此你可以跳过下面的部分。但对于其它的程序,你极有可能不得不检查并修改Makefile文件。

这里是gentoo的Makefile文件的相应部分:

      # Where to put binary on 'make install'?
      BIN     = /usr/local/bin
    
      # Where to put icons on 'make install'?
      ICONS   = /usr/local/share/gentoo

我们发现这个文件被设定成为安装到/usr/local目录下。将这些路径改为:

      # Where to put binary on 'make install'?
      BIN     = $(DESTDIR)/usr/bin
    
      # Where to put icons on 'make install'?
      ICONS   = $(DESTDIR)/usr/share/gentoo

但为什么要在这个目录中而不是其它的呢?这是因为Debian绝不会把文件安装到/usr/local目录中——那个目录是留给系统管理员用的。这些文件在Debian系统上都会被安装到/usr目录下。

在文件系统层次标准中描述了更多的关于二进制、图标、文档等文件放置位置的信息(请参考/usr/share/doc/debian-policy/fhs/)。我建议你浏览一下其中可能与你的软件包有关的部分。

因此,我们应该把二进制文件安装在/usr/bin目录中而不是/usr/local/bin目录中,把手册安装在/usr/share/man/man1目录中而不是/usr/local/man/man1目录中。也许你注意到在gentoo的makefile中并未涉及到手册文件,但Debian政策要求每个程序都要有一篇手册,因此我们稍后会制作一份并把它安装到/usr/share/man/man1中。

有一些程序并不像这样使用makefile的变量来定义其路径。这就意味着你不得不去修改一些C源程序来使其能够在正确的位置找到文件。但到哪里去找又改找些什么呢?你可以使用这样的命令:

      grep -nr -e 'usr/local/lib' --include='*.[c|h]' .

grep会递归地搜索整个源代码目录树,并在找到相应的字符串时告诉你它所在文件的名字和在文件中所处行的行号。

修改那些文件,并用usr/*替换掉原来的/usr/local/*以及所有相关的内容。注意不要为了修改这些地方而把代码的其它部分搞乱。 :-)

之后,你应该找到install目标(查找以“install:”开始的行)并修改所有对于目录的引用,使其和在Makefile的开始部分定义的一致。最初的时候,gentoo的install目标是下面的样子:

      install:        gentoo
                      install ./gentoo $(BIN)
                      install icons/* $(ICONS)
                      install gentoorc-example $(HOME)/.gentoorc

在我们修改以后它变成了这个样子:

      install:        gentoo-target
                      install -d $(BIN) $(ICONS) $(DESTDIR)/etc
                      install ./gentoo $(BIN)
                      install -m644 icons/* $(ICONS)
                      install -m644 gentoorc-example $(DESTDIR)/etc/gentoorc

你一定已经注意到在其它命令之前有一个install -d命令。原来的makefile脚本没有它是因为通常情况下在运 行“make install”时,/usr/local/bin和其它的目录都已经存在于文件系统上了。然而,我们是要把文件安装到我们的空的(或者是根本不存在的)目录中,因此我们不得不首先创建每一个目录。

在rule文件的结尾,我们还可以加入其它的内容,比如安装上游作者忽略掉的附加文档,如下所示:

                      install -d $(DESTDIR)/usr/share/doc/gentoo/html
                      cp -a docs/* $(DESTDIR)/usr/share/doc/gentoo/html

细心的读者应该已经注意到我把“install:”一行中的“gentoo”改成了“gentoo-target”。这被称为无关bug修复 :-)

当你做了一些并不特定地与Debian软件包相关的修改时,请一定要把它们发送给上游的维护者,这样这些修改就可以被包含在软件的下一个版本中,这样会对其他人非常有用。还要记住不要使你的修改只是针对Debian或者Linux(甚至是Unix!),在发送它们之前——让它们具有可移植性。这将会使你的修改更容易被接受。

注意,你不需要把debian/*文件也发送给上游的人。

3.2 不一样的库名称

有一个非常普遍的问题:在不同的平台上链接库通常是不一样的。例如,Makefile中包含了对一个库的引用,但Debian系统上并没有这个库。在这种情况下,我们需要把它修改成为一个在Debian中确实存在并且完成相同功能的库。

因此,如果在你的程序的Makefile(或者Makefile.in)中有类似于下面的一行(并且使你的程序无法编译了):

      LIBS = -lcurses -lsomething -lsomethingelse

可以把它改成这样,通常情况下它都能工作:

      LIBS = -lncurses -lsomething -lsomethingelse

(作者已经注意到这并不是最好的例子,因为我们现在使用的libncurses软件包在发布的时候包含了一个libcurses.so的符号链接,但他没能想到更好的。欢迎你 提些建议 :-)