使用自定义 .deb 文件打包 snapcraft

使用自定义 .deb 文件打包 snapcraft

我正在尝试为名为 igotu2gpx 的软件打包 snap。该软件是 qt4 并使用libmarble。我查看了 repos(并使用虚拟机尝试了它)-Ubuntu 14.04 是最后一个提供libmarbleqt4 的版本。之后,软件包消失了或被同名的 qt5 版本取代了(!)。

现在,为了构建 snap(适用于 Ubuntu 18.04),我手动下载了所有必要的 .deb 文件并想直接从我的 snap 中引用它们。

我首先在额外部分中使用自定义插件。这有效,但仅适用于构建阶段。在准备阶段,我必须在包含和构建源的部分内直接引用这些 .deb,但为了定义额外的 apt 源,我需要定义一个插件,并且插件空间已被插件占用qmake。此外,我需要固定或类似的机制,因为在定义时PLUGIN_STAGE_SOURCES我必须明确引用旧软件包。并且build-packages/stage-packages不允许明确定义版本号。

那么,我怎样才能做一些“简单的事情”,比如添加自定义 .deb 文件?

snapcraft.yaml:

name: igotu
base: core18 # the base snap is the execution environment for this snap
version: bzr-227
title: GUI for i-gotU USB GPS travel logger
summary: MobileAction i-gotU USB GPS travel logger
description: |
    MobileAction i-gotU USB GPS travel logger
license: unknown

grade: devel
#confinement: strict
confinement: devmode

apps:
  igotugui:
    command: usr/local/bin/igotugui
    plugs:
    - hardware-observe
    - raw-usb
    - x11
    environment:
      LD_LIBRARY_PATH: $LD_LIBRARY_PATH:$SNAP/usr/local/lib
  igotu2gpx:
    command: usr/local/bin/igotu2gpx
    plugs:
    - hardware-observe
    - raw-usb
    environment:
      LD_LIBRARY_PATH: $LD_LIBRARY_PATH:$SNAP/usr/local/lib

parts:
  app:
    source-type: bzr
    source: lp:igotu2gpx
    # expect to pull a 0.4 version rev. 227
    plugin: qmake
    qt-version: qt4

    build-packages:
      - libqtgui4
      - pkg-config
      - ctags
      - gdb
      - chrpath
      - libboost-all-dev
      - libboost-program-options-dev
      - libusb-dev

    stage-packages:
      # to be cleaned up and marble to be added
      - libqt4-declarative
      - libqt4-opengl
      - libqt4-svg
      - libqt4-xml
      - libqt4-xmlpatterns
      - libqtcore4
      - libqtdbus4
      - libqtgui4
      - libqtwebkit4
      - libxt6
      # [...]
      # the following declarations must point to the .deb files
      - libastro1=4:4.13.0-0ubuntu1
      - libmarblewidget18=4:4.13.0-0ubuntu1
      - marble-data=4:4.13.0-0ubuntu1
      - marble-plugins=4:4.13.0-0ubuntu1

  extradebs:
    plugin: extradebs

    extra-debs:
      - 3rdParty/deb/other/libgps20_3.9-3_amd64.deb
      - 3rdParty/deb/other/libqextserialport1_1.2.0~rc1+git7-g3be3fbf-1_amd64.deb
      - 3rdParty/deb/other/libqtlocation1_1.2.0-3ubuntu5_amd64.deb
      - 3rdParty/deb/other/libquazip0_0.6.2-0ubuntu1_amd64.deb
      - 3rdParty/deb/other/libshp1_1.2.10-7_amd64.deb

      - 3rdParty/deb/marble/libastro1_4:4.13.0-0ubuntu1_amd64.deb
      - 3rdParty/deb/marble/libastro-dev_4:4.13.0-0ubuntu1_amd64.deb
      - 3rdParty/deb/marble/libmarble-dev_4:4.13.0-0ubuntu1_amd64.deb
      - 3rdParty/deb/marble/libmarblewidget18_4:4.13.0-0ubuntu1_amd64.deb
      - 3rdParty/deb/marble/marble-data_4:4.13.0-0ubuntu1_all.deb
      - 3rdParty/deb/marble/marble-plugins_4:4.13.0-0ubuntu1_amd64.deb

    build-packages:
      #- libmarble-dev=4:4.13.0-0ubuntu1 depends on
      - libqtcore4
      - libqtgui4
      - libqt4-dev

      #- libmarblewidget18=4:4.13.0-0ubuntu1 depends on
      - libphonon4
      - libqt4-dbus
      - libqt4-declarative
      - libqt4-network
      - libqt4-script
      - libqt4-svg
      - libqt4-xml
      #- libqtcore4
      #- libqtgui4
      - libqtwebkit4
      - phonon

      #- marble-plugins=4:4.13.0-0ubuntu1 depends on
      #- libphonon4
      #- libqextserialport1
      #- libqt4-declarative
      #- libqt4-network
      #- libqt4-script
      - libqt4-sql
      #- libqt4-svg
      #- libqt4-xml
      #- libqtcore4
      #- libqtgui4
      #- libqtwebkit4
      #- phonon
      - libwlocate0

      #- libgps20 depends on
      - libbluetooth3
      - libusb-1.0-0

插件/extradebs.py:

import snapcraft
import os
import subprocess
from typing import List
import collections
import logging
from snapcraft.internal import errors

logger = logging.getLogger(__name__)

class ExtraDebs(snapcraft.BasePlugin):

    @classmethod
    def schema(cls):
        schema = super().schema()

        # Add a new property called "my-property"
        schema['properties']['extra-debs'] = {
            "type": "array",
            "uniqueItems": True,
            "items": {"type": "string"},
        }

        # The "my-option" property is now required
        #schema['required'].append('extra-debs')

        return schema

    def pull(self):
        super().pull()

        print ('Start pulling extra debs')
        deb_files = ["%s/../../project/snap/%s" % (self.partdir, file) for file in self.options.extra_debs]
        self._install_extra_debs(deb_files)

    #def build(self):
    #    super().build()
    #    print('Look ma, I built!')

    @classmethod
    def _install_extra_debs(cls, deb_files: List[str]) -> None:
        deb_files.sort()
        logger.info("Installing extra deb files: %s", " ".join(deb_files))
        env = os.environ.copy()
        env.update(
            {
                "DEBIAN_FRONTEND": "noninteractive",
                "DEBCONF_NONINTERACTIVE_SEEN": "true",
                "DEBIAN_PRIORITY": "critical",
            }
        )

        dpkg_command = [
            "sudo",
            "--preserve-env",
            "dpkg",
            "-i",
        ]

        try:
            subprocess.check_call(dpkg_command + deb_files, env=env)
        except subprocess.CalledProcessError:
            raise errors.BuildPackagesNotInstalledError(packages=deb_files)

        package_names = [deb.split("/")[-1].split('_')[0] for deb in deb_files]
        try:
            subprocess.check_call(["sudo", "apt-mark", "auto"] + package_names, env=env)
        except subprocess.CalledProcessError as e:
            logger.warning(
                "Impossible to mark packages as auto-installed: {}".format(e)
            )

答案1

一个更简单的方法是使用make插件并自定义其步骤:

...
parts:
  app:
    after: [extradebs]
    ...
  ...
  extradebs:
    ...
    plugin: make
    override-pull: |
      ...
    override-stage: |
      ...
    override-build: | 
      ...
    override-install: |
      ...
    ...
  ...
...

参考:

答案2

这可以使用转储插件直接。例如

  libsqlite:
    plugin: dump
    source: http://ports.ubuntu.com/pool/main/s/sqlite3/libsqlite3-0_3.31.1-4_amd64.deb

请注意,这当然会对架构进行硬编码。如果您需要进行多架构构建,则可以使用类似以下方法https://forum.snapcraft.io/t/alias-request-for-snap-google-cloud-cli-arm/29718/5

最后,如果你尝试“覆盖”已由另一部分安装的文件,则会收到类似以下错误

Failed to stage: Parts 'x' and 'y' have the following files, but with different contents

您可以通过在其定义中添加以下内容来删除第一部分安装的过时文件:

    stage:
      - -file/to/remove
      - -other/file/to/remove

相关内容