You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Snapcraft执行prime命令时在pull步骤无限挂起的问题求助

问题描述

首次尝试用Snapcraft为包含3个应用的项目构建snap包,单独执行snapcraft stage a --use-lxd可成功完成对应部件的stage步骤,但执行snapcraft prime --use-lxd时,构建卡在2023-01-08 16:22:11.505 check if Part('websocket'):Step.PULL is outdated \ (31013.8s)步骤。已提前单独构建所有部件且无明显错误,但整体构建不会跳过已完成阶段,怀疑检查pull是否过时的逻辑陷入无限目录递归,需要优化snapcraft配置。

当前snapcraft.yaml配置如下:

name: test
summary: ...
description: ...
confinement: strict
base: core22
grade: stable
version: "1"
architectures:
  - build-on: amd64

apps:
  a:
    command: /usr/share/a/app
    plugs:
      - network
      - home

  b:
    command: /usr/share/b/app
    plugs:
      - network
      - home

  c:
    command: /usr/share/c/app
    plugs:
      - network
      - home

parts:

  source:
    plugin: nil
    source: https://github.com/flutter/flutter.git
    source-type: "git"
    source-depth: 1
    source-branch: "master"
    build-packages: [clang, cmake, git, ninja-build, pkg-config, libgtk-3-dev, liblzma-dev, curl, unzip]
    stage-packages: [libgtk-3-0, libblkid1, liblzma5]
    override-pull: |
      craftctl default
      git fetch --unshallow
      PATH="$CRAFT_PART_SRC/bin:$PATH" flutter doctor
      PATH="$CRAFT_PART_SRC/bin:$PATH" flutter channel master
      PATH="$CRAFT_PART_SRC/bin:$PATH" flutter precache
    override-build: |
      set -eux
      mkdir -p $CRAFT_PART_INSTALL/usr/bin
      mkdir -p $CRAFT_PART_INSTALL/usr/libexec
      cp -r $CRAFT_PART_SRC $CRAFT_PART_INSTALL/usr/libexec/flutter
      ln -sf $CRAFT_PART_INSTALL/usr/libexec/flutter/bin/flutter $CRAFT_PART_INSTALL/usr/bin/flutter
      ln -sf $CRAFT_PART_INSTALL/usr/libexec/flutter/bin/dart $CRAFT_PART_INSTALL/usr/bin/dart
      export PATH="$CRAFT_PART_INSTALL/usr/bin:$PATH"
    override-prime: ""

  packages:
    source: packages
    source-type: local
    plugin: nil
    build-packages: [rsync]
    override-pull: |
      echo "$(pwd)"
      rsync -r --exclude snap --exclude .git --exclude .vs --exclude .plugin_symlinks --exclude TestResults --exclude releases --exclude .dart_tool --exclude .vscode --exclude node_modules --exclude build $SNAPCRAFT_PROJECT_DIR/packages/* $SNAPCRAFT_PART_SRC/
    override-build: |
      rsync -r $SNAPCRAFT_PART_SRC/* $SNAPCRAFT_PART_INSTALL
    override-stage: ""
    override-prime: ""

  websocket:
    source: websocket
    source-type: local
    plugin: nil
    build-packages: [rsync]
    override-pull: |
      rsync -r --exclude snap --exclude .git --exclude .vs --exclude .plugin_symlinks --exclude TestResults --exclude releases --exclude .dart_tool --exclude .vscode --exclude node_modules --exclude build $SNAPCRAFT_PROJECT_DIR/websocket/* $SNAPCRAFT_PART_SRC/
    override-build: |
      rsync -r $SNAPCRAFT_PART_SRC/* $SNAPCRAFT_PART_INSTALL
    override-stage: ""
    override-prime: ""

  dummy:
    plugin: nil
    build-packages: [rsync]
    build-snaps: [ yq ]
    stage-packages: [dotnet-sdk-6.0, dotnet-runtime-6.0]
    after: [source, packages, websocket]
    override-pull: ""
    override-build: ""
    override-prime: ""

  a:
    source: a_src
    source-type: local
    plugin: nil
    after: [dummy]
    override-pull: |
      mkdir -p packages
      mkdir -p a_src
      mkdir -p websocket
      rsync -r ~/parts/websocket/install/* $SNAPCRAFT_PART_SRC/websocket
      rsync -r ~/parts/packages/install/* $SNAPCRAFT_PART_SRC/packages
      rsync -r --exclude snap --exclude .git --exclude .vs --exclude .plugin_symlinks --exclude TestResults --exclude releases --exclude .dart_tool --exclude .vscode --exclude node_modules --exclude build $SNAPCRAFT_PROJECT_DIR/a_src/* $SNAPCRAFT_PART_SRC/a_src
      #craftctl default
      cd a_src
      flutter clean
      flutter pub get
    override-build: |
      craftctl default
      cd a_src
      flutter build linux
      rsync --mkpath -r build/linux/x64/release/bundle/* $SNAPCRAFT_PART_INSTALL/usr/share/a
    override-stage: |
      rsync –-ignore-existing -r $SNAPCRAFT_PART_INSTALL/* $SNAPCRAFT_STAGE

  b:
    source: b_src
    source-type: local
    plugin: nil
    after: [dummy]
    override-pull: |
      mkdir -p packages
      mkdir -p b_src
      mkdir -p websocket
      rsync -r ~/parts/websocket/install/* $SNAPCRAFT_PART_SRC/websocket
      rsync -r ~/parts/packages/install/* $SNAPCRAFT_PART_SRC/packages
      rsync -r --exclude snap --exclude .git --exclude .vs --exclude .plugin_symlinks --exclude TestResults --exclude releases --exclude .dart_tool --exclude .vscode --exclude node_modules --exclude build $SNAPCRAFT_PROJECT_DIR/b_src/* $SNAPCRAFT_PART_SRC/b_src
      #craftctl default
      cd b_src
      flutter pub get
    override-build: |
      craftctl default
      cd b_src
      flutter build linux
      rsync --mkpath -r build/linux/x64/release/bundle/* $SNAPCRAFT_PART_INSTALL/usr/share/b
    override-stage: |
      rsync –-ignore-existing -r $SNAPCRAFT_PART_INSTALL/* $SNAPCRAFT_STAGE

  c:
    source: c_src
    source-type: local
    plugin: nil
    after: [dummy]
    override-pull: |
      mkdir -p packages
      mkdir -p c_src
      mkdir -p websocket
      rsync -r ~/parts/websocket/install/* $SNAPCRAFT_PART_SRC/websocket
      rsync -r ~/parts/packages/install/* $SNAPCRAFT_PART_SRC/packages
      rsync -r --exclude snap --exclude .git --exclude .vs --exclude .plugin_symlinks --exclude TestResults --exclude releases --exclude .dart_tool --exclude .vscode --exclude node_modules --exclude build $SNAPCRAFT_PROJECT_DIR/c_src/* $SNAPCRAFT_PART_SRC/c_src
      #craftctl default
      cd c_src
      flutter clean
      flutter pub get
    override-build: |
      craftctl default
      cd c_src
      flutter build linux
      rsync --mkpath -r build/linux/x64/release/bundle/* $SNAPCRAFT_PART_INSTALL/usr/share/c
    override-stage: |
      rsync –-ignore-existing -r $SNAPCRAFT_PART_INSTALL/* $SNAPCRAFT_STAGE

  test:
    after: [a, c, b]
    plugin: nil

优化方案

1. 移除跨部件手动文件复制,依赖Snapcraft原生机制

当前a/b/c部件的override-pull中手动从~/parts/...复制websocket和packages内容,会导致Snapcraft的文件哈希检查陷入递归循环,同时破坏依赖追踪逻辑。

解决方法:

  • 删除a/b/c部件中mkdir -p packages/websocket及对应rsync命令
  • 在a/b/c的override-pull中,通过环境变量让Flutter直接引用stage目录中的依赖:
    cd $CRAFT_PART_SRC
    flutter clean
    # 指向stage中的依赖目录,避免重复复制
    flutter pub get --offline --directory=$CRAFT_PART_SRC
    
  • 确保a/b/c部件的after字段包含packages和websocket,让Snapcraft自动处理依赖顺序

2. 修复语法错误

所有override-stage中的rsync –-ignore-existing使用了中文全角破折号,会被rsync识别为无效参数,导致文件同步异常,让Snapcraft误判文件状态变化。需改为英文半角破折号--ignore-existing。

3. 移除无用部件

  • dummy部件仅用于依赖管理和安装dotnet包,可将其build-packages、build-snaps、stage-packages合并到基础部件中
  • test部件无实际逻辑,直接删除

4. 简化Flutter安装

当前source部件手动克隆并复制整个Flutter仓库,可直接使用官方Flutter snap包作为构建依赖,避免手动配置:

flutter-base:
  plugin: nil
  build-snaps: [flutter/latest/stable, yq/latest/stable]
  build-packages: [clang, cmake, ninja-build, pkg-config, libgtk-3-dev, liblzma-dev, rsync]
  stage-packages: [libgtk-3-0, libblkid1, liblzma5, dotnet-sdk-6.0, dotnet-runtime-6.0]
  override-pull: |
    craftctl default
    flutter precache --linux

5. 明确文件同步规则,减少冗余

在packages和websocket部件中使用organize字段指定安装路径,避免无差别复制:

packages:
  source: packages
  source-type: local
  plugin: nil
  after: [flutter-base]
  organize:
    "*": usr/share/packages/

修改后的示例配置

name: test
summary: ...
description: ...
confinement: strict
base: core22
grade: stable
version: "1"
architectures:
  - build-on: amd64

apps:
  a:
    command: /usr/share/a/app
    plugs:
      - network
      - home

  b:
    command: /usr/share/b/app
    plugs:
      - network
      - home

  c:
    command: /usr/share/c/app
    plugs:
      - network
      - home

parts:
  flutter-base:
    plugin: nil
    build-snaps: [flutter/latest/stable, yq/latest/stable]
    build-packages: [clang, cmake, ninja-build, pkg-config, libgtk-3-dev, liblzma-dev, rsync]
    stage-packages: [libgtk-3-0, libblkid1, liblzma5, dotnet-sdk-6.0, dotnet-runtime-6.0]
    override-pull: |
      craftctl default
      flutter precache --linux

  packages:
    source: packages
    source-type: local
    plugin: nil
    after: [flutter-base]
    organize:
      "*": usr/share/packages/
    override-pull: |
      rsync -r --exclude='snap' --exclude='.git' --exclude='.vs' --exclude='.plugin_symlinks' --exclude='TestResults' --exclude='releases' --exclude='.dart_tool' --exclude='.vscode' --exclude='node_modules' --exclude='build' $CRAFT_PROJECT_DIR/packages/* $CRAFT_PART_SRC/

  websocket:
    source: websocket
    source-type: local
    plugin: nil
    after: [flutter-base]
    organize:
      "*": usr/share/websocket/
    override-pull: |
      rsync -r --exclude='snap' --exclude='.git' --exclude='.vs' --exclude='.plugin_symlinks' --exclude='TestResults' --exclude='releases' --exclude='.dart_tool' --exclude='.vscode' --exclude='node_modules' --exclude='build' $CRAFT_PROJECT_DIR/websocket/* $CRAFT_PART_SRC/

  a:
    source: a_src
    source-type: local
    plugin: nil
    after: [flutter-base, packages, websocket]
    override-pull: |
      rsync -r --exclude='snap' --exclude='.git' --exclude='.vs' --exclude='.plugin_symlinks' --exclude='TestResults' --exclude='releases' --exclude='.dart_tool' --exclude='.vscode' --exclude='node_modules' --exclude='build' $CRAFT_PROJECT_DIR/a_src/* $CRAFT_PART_SRC/
      cd $CRAFT_PART_SRC
      flutter clean
      flutter pub get --offline --directory=$CRAFT_PART_SRC
    override-build: |
      cd $CRAFT_PART_SRC
      flutter build linux --release
      rsync --mkpath -r build/linux/x64/release/bundle/* $CRAFT_PART_INSTALL/usr/share/a
    override-stage: |
      rsync --ignore-existing -r $CRAFT_PART_INSTALL/* $CRAFT_STAGE

  b:
    source: b_src
    source-type: local
    plugin: nil
    after: [flutter-base, packages, websocket]
    override-pull: |
      rsync -r --exclude='snap' --exclude='.git' --exclude='.vs' --exclude='.plugin_symlinks' --exclude='TestResults' --exclude='releases' --exclude='.dart_tool' --exclude='.vscode' --exclude='node_modules' --exclude='build' $CRAFT_PROJECT_DIR/b_src/* $CRAFT_PART_SRC/
      cd $CRAFT_PART_SRC
      flutter clean
      flutter pub get --offline --directory=$CRAFT_PART_SRC
    override-build: |
      cd $CRAFT_PART_SRC
      flutter build linux --release
      rsync --mkpath -r build/linux/x64/release/bundle/* $CRAFT_PART_INSTALL/usr/share/b
    override-stage: |
      rsync --ignore-existing -r $CRAFT_PART_INSTALL/* $CRAFT_STAGE

  c:
    source: c_src
    source-type: local
    plugin: nil
    after: [flutter-base, packages, websocket]
    override-pull: |
      rsync -r --exclude='snap' --exclude='.git' --exclude='.vs' --exclude='.plugin_symlinks' --exclude='TestResults' --exclude='releases' --exclude='.dart_tool' --exclude='.vscode' --exclude='node_modules' --exclude='build' $CRAFT_PROJECT_DIR/c_src/* $CRAFT_PART_SRC/
      cd $CRAFT_PART_SRC
      flutter clean
      flutter pub get --offline --directory=$CRAFT_PART_SRC
    override-build: |
      cd $CRAFT_PART_SRC
      flutter build linux --release
      rsync --mkpath -r build/linux/x64/release/bundle/* $CRAFT_PART_INSTALL/usr/share/c
    override-stage: |
      rsync --ignore-existing -r $CRAFT_PART_INSTALL/* $CRAFT_STAGE

内容的提问来源于stack exchange,提问作者Lawrence Kok

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 07:11:06