[Topic DIscussion] chatgpt4给出的玲珑软件包构建教程,各位大佬帮忙看看有什么错误
Tofloor
poster avatar
玄圭SwenGway
deepin
2025-05-04 22:28
Author

它的回答感觉比deepseek强了很多

我会涵盖从准备源码、配置环境、编写 manifest 文件、构建 layer 到生成 uab 格式软件包的完整步骤。完成后我会通知你。

玲珑(Linglong)包格式概述

玲珑采用两种主要的包格式:layerUAB。其中 layer 是联网安装包格式,由两部分组成:*_binary.layer(包含运行时所需的基本文件)和可选的 *_develop.layer(包含调试环境)。它适用于可以连接玲珑仓库的场景,利用增量更新以节省带宽。相比之下,UAB(Universal Application Bundle)是一种自包含的离线分发格式,包含了应用运行所需的一切内容。在可以联网的情况下,推荐使用 layer 格式;在离线或需要打包为单一文件分发时,则使用 UAB 格式。例如,运行 ll-builder export 默认会生成 .uab 文件(如 appid_version_arch.uab),而使用 --layer 参数则会输出 *_binary.layer 和可选的 *_develop.layer

1. 准备源代码

在开始打包之前,需要准备好要打包的软件源码。可以从 Git 仓库克隆、下载源码压缩包,或将现有代码放入工程目录中。一个典型的做法是:在项目根目录下创建 linglong/sources 子目录,然后把源码复制或下载到这个目录里。打包时,玲珑会根据 linglong.yaml 中的 sources 配置自动获取源码,并将其存放在该目录下。例如,如果使用 Git 源码,可以这样配置:

sources:
  - kind: git
    url: https://github.com/username/your-project.git
    version: master    # 或指定 tag/分支
    # 如果需要指定某个具体提交:
    # commit: abc123def456...
    # 可以设置 name 来指定克隆后的目录名(可选):
    # name: your-project-src

如上所示,kindgit 表示使用 Git 工具拉取源码。玲珑支持多种 sources 类型,包括 gitarchive(下载并解压压缩包)、file(下载单个文件)、dsc(Debian 源码包)等。不论哪种方式,获取后的源码会放在 linglong/sources/ 目录下。对于简单示例,也可以直接将源码(如单个 .c 文件或小的源码树)手动复制到 linglong/sources/,然后在 linglong.yaml 中设置相应类型。

2. 编写 linglong.yaml 清单文件

linglong.yaml 是玲珑项目的元数据文件,用于描述包的基本信息、依赖和构建过程。以下是常用字段及含义:

  • version:配置文件语法版本,目前固定为 "1"

  • package: 包的基本信息块(必需),包含:

    • id:包的唯一标识,如反向域名 com.example.myapp
    • name:包的名称(可读)。
    • version:包的版本号,建议使用四段数字,如 1.0.0.0
    • kind:包类型,通常为 app(应用)或 runtime(运行时环境),表明该包的类别。
    • description:对包的简要描述,可以使用多行文本(YAML 的 | 语法)。
    • architecture (可选):目标架构,如 amd64arm64 等。
    • channel (可选):发布通道,如 stablebeta 等。
  • command:应用的启动命令。通常为一个字符串列表,第一个元素是可执行文件路径(容器内路径),后面可跟参数。例如:

    command:
      - "/opt/apps/com.example.myapp/files/bin/myapp"   # 可执行文件路径
      - "--some-option"                                # 可选参数
    

    这个命令告诉玲珑如何在容器中运行该应用。

  • base(必需):指定构建时使用的基础系统环境 ID,格式为 id/version。。例如:org.deepin.base/23.1.0。这个基础环境包含最小的根文件系统,用于构建和运行应用。版本号支持三位模糊匹配(如填写 23.1.0 可以匹配多个具体版本)。

  • runtime(可选):指定应用运行时所需的额外环境 ID,例如图形库或其他基础库。如果应用需要额外的运行时支持,可以配置 runtime,其格式也为 id/versionruntime 通常也作为构建时依赖安装。如果不设置,构建时只使用 base 环境。

  • sources:源码信息列表(必需)。定义源码获取方式(参见上文“准备源代码”)。sources 是一个列表,每项说明一种源码获取方式。示例:

    sources:
      - kind: git
        url: https://github.com/username/myapp.git
        version: master
      # 如果有多个源码来源,可以再添加项
      # - kind: archive
      #   url: https://...
    

    玲珑会自动将下载或解压得到的源码放到 linglong/sources/ 目录。

  • build:构建步骤脚本(必需)。这是一个 YAML 字符串块(用 | 表示)内的 Shell 命令列表,在容器环境中依次执行。比如编译一个简单 C 程序:

    build: |
      gcc hello.c -o ${PREFIX}/bin/hello
    

    这里 ${PREFIX} 是一个内置变量,表示应用的安装前缀路径(如 /opt/apps/com.example.myapp)。所有编译输出应该安装到 ${PREFIX} 下。

  • buildext(可选):扩展配置,主要用于指定构建时的系统包依赖。常用的是 apt,可以列出 构建时依赖 (build_depends) 和 运行时依赖 (depends)。例如:

    buildext:
      apt:
        build_depends:
          - build-essential
          - cmake
        depends:
          - libssl-dev
    

    其中 build_depends 列出的包会在容器内用于编译(但不会出现在最终安装包中),depends 列出的包会包含在最终应用的运行时环境里。

  • modules(可选):定义如何将 ${PREFIX} 下的文件拆分成多个模块(例如主程序、插件、文档等)。如果不定义 modules,玲珑默认会自动生成两个模块:binary(主运行时所需文件)和 develop(包含调试文件的拓展)。通常新手可以省略此项,让系统自动分配即可。

下面给出一个简单示例(应用 com.example.hello 的配置)供参考,注释说明了每项的作用:

version: "1"

package:
  id: com.example.hello        # 唯一ID
  name: hello                  # 应用名
  version: 0.1.0               # 版本号
  kind: app                    # 应用类型
  description: |               # 描述
    A simple Hello World program.
  architecture: amd64          # (可选) 架构

base: org.deepin.base/23.1.0   # 构建基础环境
runtime: org.deepin.runtime.base/23.1.0  # (可选) 运行时环境

command:
  - /opt/apps/com.example.hello/files/bin/hello  # 启动可执行文件及参数

sources:
  - kind: file
    url: ./hello.c            # 假设源码为当前目录下的 hello.c 文件

build: |
  gcc hello.c -o ${PREFIX}/bin/hello  # 在容器中编译并安装到 PREFIX

buildext:
  apt:
    build_depends:
      - build-essential     # 编译所需的基本工具
    # 运行时依赖可以放在 depends 中,这里示例中不需要额外依赖

以上示例仅供参考。 实际使用时请根据您的程序修改 id, name, version,以及 baseruntime 等字段。如需安装额外的系统库,可在 buildext.apt.depends 中列出。

3. 使用 Linglong CLI 构建 Layer 包

有了源码和 linglong.yaml 后,就可以开始构建了。请打开终端,进入项目根目录(即包含 linglong.yaml 的目录),然后执行:

cd com.example.hello     # 进入项目目录
ll-builder build        # 开始构建

以上命令会自动在容器环境中执行 build 字段中的脚本。构建完成后,产物会提交到本地的 ostree 缓存中。若想在构建之前进入容器调试环境,可以加上 --exec 参数:

ll-builder build --exec /bin/bash

这样会先进入容器的 shell,您可以手动检查和执行命令,然后退出后再继续构建。构建过程结束后,如果编译成功,就可以进行导出了。

4. 导出 Layer 或 UAB 包

构建完成后,使用 ll-builder export 命令将构建结果导出为安装包文件。默认情况下,ll-builder export 会导出 UAB 文件(后缀 .uab),这是推荐的离线包格式。例如:

ll-builder export        # 在当前目录生成 com.example.hello_0.1.0_amd64.uab

导出后,您会在项目目录(或使用 -o 指定的路径)看到类似 com.example.hello_0.1.0_amd64.uab 的文件。如果需要,可以用 --icon 指定应用图标,或用 -z 指定压缩算法等。

如果需要导出 layer 文件(不推荐,因为已被弃用),可加 --layer 参数。例如:

ll-builder export --layer --no-develop -o hello_layer

这将生成 hello_layer_binary.layer(运行时文件)和可选的 hello_layer_develop.layer(调试文件)。加上 --no-develop 则只产生二进制部分。注意: 在联网和需要增量更新的场景下,更推荐直接使用 UAB 文件。

5. 示例:打包 Hello World 应用

下面以一个简单的 “Hello World” C 程序为例,演示整个流程:

  1. 编写源代码。创建一个文件 hello.c,内容如下:

    cat > hello.c << 'EOF'
    #include 
    int main() {
        printf("Hello, Linglong!\n");
        return 0;
    }
    EOF
    
  2. 创建项目并生成清单。使用 ll-builder create 创建项目框架:

    ll-builder create com.example.hello
    

    这会创建 com.example.hello/ 目录并生成一个模板 linglong.yaml

  3. 准备源码目录。将 hello.c 拷贝到项目的 linglong/sources/ 目录下(请先创建该目录):

    mkdir -p com.example.hello/linglong/sources
    cp hello.c com.example.hello/linglong/sources/
    cd com.example.hello
    
  4. 编辑 linglong.yaml。按照上述说明填写清单文件,例如:

    version: "1"
    package:
      id: com.example.hello
      name: hello
      version: 0.1.0
      kind: app
      description: |
        A simple Hello World application.
    base: org.deepin.base/23.1.0
    command:
      - /opt/apps/com.example.hello/files/bin/hello
    sources:
      - kind: file
        url: ./hello.c
    build: |
      gcc hello.c -o ${PREFIX}/bin/hello
    buildext:
      apt:
        build_depends:
          - build-essential
    

    这里 sources 使用了 kind: file 并指定了相对路径(假设构建器支持此种方式)。在实际情况中,您也可以将源码打包为压缩包并使用 kind: archive 等方式。需要注意,编译过程中需要 build-essential,因此在 buildext 中添加了它作为构建依赖。

  5. 构建并导出。运行构建命令:

    ll-builder build
    ll-builder export
    

    构建结束后,目录下会生成 com.example.hello_0.1.0_amd64.uab 文件。

  6. 调试运行。可以使用 ll-builder run 在容器中运行编译好的程序进行测试:

    ll-builder run /opt/apps/com.example.hello/files/bin/hello
    

    这将在玲珑容器中直接执行 hello 可执行文件,输出 “Hello, Linglong!”。

  7. 安装和运行。将生成的 UAB 或 layer 包安装到系统中:

    • 使用玲珑命令行工具安装:

      ll-cli install ./com.example.hello_0.1.0_amd64.uab
      

      (或如果是 layer 文件,则 ll-cli install hello_binary.layer)。安装后,玲珑会将应用添加到本地仓库。

    • 使用玲珑运行:

      ll-cli run com.example.hello
      

      这样就可以像普通应用一样启动它。

这样,一个简单的 “Hello World” 应用就完成了从源码到玲珑包的整个流程。

6. 调试、安装和运行测试

  • 调试构建过程:如果构建失败,可以使用 --exec 进入容器手动调试(见上文),也可以查看构建日志(在 ~/.cache/linglong-builder 下)。确保 build 脚本中路径和变量正确,${PREFIX} 指向 /opt/apps/你的包id/files/

  • 运行测试:如上所述,ll-builder run <可执行文件路径> 可以在容器中测试运行应用。此方法无需先导出安装包即可验证功能。

  • 安装包测试:若导出了 .uab.layer 文件,可用 ll-cli install 安装它们。安装后,再用 ll-cli run 包ID 运行应用。在某些平台上,.uab 文件本身也可以通过给予执行权限直接运行:

    chmod +x myapp.uab
    ./myapp.uab
    

    这会在容器中“即时”运行应用,不过推荐使用 ll-cli install 以完成依赖安装。

7. 常见问题排查

  • 找不到基础环境:确认 baseruntime 字段所使用的 ID 在您系统的玲珑仓库中可用。例如在 Ubuntu 24.04 上,您可能需要先添加玲珑的仓库源并安装相关包。查看 Base 和 Runtime 介绍 获取正确的环境 ID。
  • YAML 语法错误linglong.yaml 对缩进和格式敏感,请注意空格和冒号,尤其是 | 后需要换行对齐。可以使用 YAML 校验工具检查语法。
  • 缺少依赖导致构建失败:查看错误日志,如果提示某些命令或头文件不存在,可在 buildext.apt.build_depends 中添加所需的开发包名称。
  • 模块划分问题:如果忘记配置 modules,系统会默认创建 binarydevelop 两个模块。如果您只想要一个简单的包,可以不用定义 modules。反之,如果应用需要拆分模块,请在 modules 中指定包含哪些文件。
  • 无法安装包或运行:使用 ll-cli install 时请确保路径和文件名正确。如果安装层文件(.layer),可能需要同时安装 binarydevelop(或者用 --module 参数指定)。如果 .uab 无法执行,检查是否已 chmod +x
  • 容器网络或权限问题:在容器中编译时可能需要联网获取包,或需要特定权限。您可以尝试加上 --offline 跳过网络获取(适用于源码已在本地的情况),或确认宿主机用户对构建目录有读写权限。

以上步骤和提示可帮助零基础用户在 Ubuntu 24.04 上从源码构建玲珑的 layer 和 uab 包。整个过程相对直观:准备源码 → 编写 manifest → ll-builder build → ll-builder export → ll-cli 安装运行。遇到问题时,可参考玲珑官方文档和日志信息逐步排查。

参考资料: 玲珑官方文档对构建流程和配置文件的详细说明。上述内容综合了官方指南和社区资源,便于初学者理解。

Reply Favorite View the author
All Replies

No replies yet