有没有一种方法可以在设置dpkg控制文件时自动确定依赖关系?

9

大多数dpkg(Debian)控制文件中的字段都很简单。棘手的是确定依赖项列表(Depends:)。我希望通过查看软件包目录中可执行文件的ldd输出,dpkg-gencontrol可以为我完成这项工作。也许它可以,但我无法使其正常工作。

如果这就是dpkg-gencontrol的用途,那么我遇到的错误是:

dpkg-gencontrol: error: syntax error in control_template at line 7: first block lacks a source field.

供参考,该命令为dpkg-gencontrol -v1.1 -ccontrol_template -lchangelog -Pdebian。control_template文件包含以下内容:

Package: my-package
Maintainer: Joe Coder <joe@coder.com>
Description: The my-package system
 A longer description that runs to the end of one line and then 
 extends to another line.
Priority: optional

如果dpkg-gencontrol不是用于此目的,是否有人能提出建议,我该怎么做,或者怎样设置依赖关系列表,最好是自动完成的?识别依赖关系可能是一个非常困难的问题,特别是如果您将搜索范围扩展到脚本和其他程序。我希望有一些工具可以在大多数情况下正常工作。请注意,这仅供内部分发使用。我不会构建要进入Linux分发版甚至被普通公众下载的软件包,因此如果需要,我很乐意弯曲/打破标准规则。
2个回答

15
经过受thiton答案启发的深入挖掘和大量试错后,我终于找到了解决问题的方法。原来dpkg-gencontrol不是从可执行文件中推断软件包依赖关系的工具,而是dpkg-shlibdeps。然而,需要仔细设置这两个程序以帮助生成软件包。请继续阅读...
运行dpkg-shlibdeps -O <executable>将列出需要安装的包和版本,以使该可执行文件运行。完美。几乎。理想情况下,dpkg-gencontrol可以在其处理中使用此功能,它声称可以通过其变量替换功能实现。
为了使这个过程顺利进行,我必须创建一个与Debian打包工具的期望相匹配的目录结构。它看起来基本上是这样的:
my_project_directory/
  main.c (or other source code, etc.)
  debian/
    changelog    (created by hand; see below)
    control      (this is basically a template, created by hand; see below)
    files        (created by dpkg-gencontrol)
    substvars    (created by dpkg-shlibdeps and used by dpkg-gencontrol)
    tmp/         (tmp is the root of the target system's filesystem)
      path/
        to/
          my/
            project/
              executable_1  (this will be installed at /path/to/my/project)
              executable_2  (this, too)
      var/
        www/
          index.php  (this will be installed at /var/www on target systems)
      DEBIAN/        (create this by hand)
        control      (created by dpkg-gencontrol and used in the final package)

请注意,Debian打包工具会保留debian/tmp/下所有文件的所有者和组。因此,如果您希望在安装时拥有root或其他用户的文件,则需要做些麻烦的事情。其中一个选项是以root身份准备debian目录树,并根据需要设置所有者。如果您不想作为root运行,或者不被允许,还有另一种方法。
创建一个调用chown等命令以按需调整所有权的脚本,最后一行是dpkg-deb -b debian/tmp .(用于构建.deb包,请参阅下面的示例)。通过fakeroot运行它,另一个Debian工具,像这样:fakeroot ./fix_ownerships_and_build.sh。Fakeroot使程序能够表现得像它们是root一样,而不会像root一样更改东西。它就是为这种情况而创建的。
我查看了dpkg-gencontrol为什么会生成"第一个块缺少源字段"错误,甚至读了它的Perl源代码。常常发生的是,错误代码很精确,但没有足够的上下文信息来知道该怎么做:控制文件确实需要一个名为"source"的字段,在其两个块中的第一个块中。
有两种Debian软件包,源代码包和二进制包。我原以为只需要二进制包,因为我只想把编译好的可执行文件放进去,但是我没能让它正常工作。我尝试了一个源代码包,并在我的控制文件中添加了一个源字段。这消除了“第一块缺少源字段”的错误,但引发了另一个错误。仔细阅读文档后,我意识到源代码包在其控制文件中需要两个“段落”。一旦我将我的控制文件更改为如下所示,它就开始工作了(几乎):
Source: my-package
Maintainer: Joe Coder <joe@coder.com>

Package: my-package
Priority: optional
Architecture: amd64
Depends: ${shlibs:Depends}, apache2, php5
Description: The My-Package System
 A longer description that runs to the end of one line and then
 extends to another line.

还缺少一个变更日志文件。这是一个文件,用于保存软件包发布的历史记录,包括重要更改、版本号、日期和负责人。我通常会使用自己的格式来维护这样的文件,然后将其精确转换为Debian变更日志格式。由于某些原因,变更日志被省略了,因此我只能使用占位符来代替我的历史记录文件,它看起来像这样:

my-package (1.0) unstable; urgency=low
  * placeholder changelog to satisfy dpkg-gencontrol
 -- Joe Coder <joe@coder.com>  Thu, 3 Nov 2011 16:49:00 -0700

在带有星号的行上的两个前导空格是必需的,带有“ - ”的行上的单个前导空格也是如此,电子邮件地址和日期之间的两个空格也是如此。是的,日期需要那么精确,包括时区等,尽管它不需要准确。

将所有内容放在一起,使用如上所述设置debian目录树,构建软件包所需的命令序列如下:

dpkg-shlibdeps debian/tmp/path/to/my/project/executable_1 \
               debian/tmp/path/to/my/project/executable_2
dpkg-gencontrol -v1.1  (or whatever version you are building)
fakeroot ./fix_ownerships_and_build.sh

在 fix_ownerships_and_build.sh 中,代码如下:

chown -R root:root debian/tmp/path  (or whatever user is appropriate)
chown -R www-data:www-data debian/tmp/var/www/*  (same goes here)
dpkg-deb -b debian/tmp .  (this leads to a nice my-package_1.1_amd64.deb file)

就是这样。希望这个答案能够帮助其他人比我更快地取得进展。


干得不错,但你重新编写了 dpkg-buildpackage 的很大一部分。你知道那个工具吗? - thiton
有点吧。有数十个与dpkg相关的工具,我对保持简单感兴趣。Debian工具似乎也非常专注于从上游源代码创建软件包以便与Debian本身一起分发,这不完全是我想做的。我开始构建一个简单的目录树、最小的控制文件和一个对dpkg-deb -b的单个调用。我试图找到最小的添加来得到我想要的东西。它有点变大了。:) 我会研究dpkg-buildpackage。重新发明轮子通常是学习的重要组成部分。 - Randall Cook

1

实际上,查看包含的库列表对于C程序来说是非常普遍的,这只是shlibs助手(dpkg-shlibdeps)的工作。查看其手册以获取帮助,但基本上归结为在您的依赖行中使用${shlibs:Depends}


这是启发我朝着解决方案迈出第一步的线索。谢谢,thilton。供参考,帮助我的不是dh_shlibdeps,而是dpkg-shlibdeps。 - Randall Cook

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接