OpenBMC资产迁移指导
更新时间: 2026/05/23
在Gitcode上查看源码

文档说明

适用范围

本文档适用于需要将 OpenBMC 组件迁移到 openUBMC 框架的开发人员和技术团队。

文档目标

  • 提供快速上手的迁移流程指导
  • 重点说明构建系统迁移(Conan2)
  • 提供常见问题解决方案
  • 帮助开发者高效完成组件迁移

反馈渠道

如有问题或建议,请通过以下方式反馈:

  • openUBMC社区论坛

1. 概述

1.1 为什么迁移?

迁移背景:多家伙伴存在 OpenBMC 的历史资产,为了应对快速迁移低成本应用迁移的需求,我们提供了 OpenBMC 资产迁移的一整套解决方案。

解决方案

  • 构建系统迁移:采用 Conan2 作为包管理器,提供可预测的依赖管理、二进制包高效分发和跨平台构建支持
  • 运行时兼容:通过 dbus-proxy 实现OpenBMC D-Bus 接口映射,OpenBMC 组件代码基本无需修改即可运行
  • 预置核心框架:已预先提供了 OpenBMC 核心框架的 Conan 包(如 stdplussdbusplus等)
  • 基于 openUBMC 的适配层:对于 OpenBMC 和 openUBMC 都具备的功能,我们借助 dbus-proxy 代理层,实现将原本依赖 OpenBMC 组件的能力,无缝切换为 openUBMC 现有组件的能力,减少适配工作量,提升迁移效率。

迁移成本:极低!您只需:

  1. conan_index 中配置组件元数据
  2. manifest.yml 中声明依赖
  3. 执行构建命令

即可完成组件迁移,无需修改业务代码。

1.2 迁移流程概览

迁移遵循"准备→构建→配置→验证"的简单流程:

迁移路径

  • 单个组件迁移:按第2-4章直接迁移,通常无需深入代码分析。
  • 系统级迁移:涉及多个组件时,参考附录A 代码分析进行依赖关系分析。

1.3 关键决策点

  1. 迁移范围:单个组件直接迁移,系统级迁移需先进行代码分析(附录A)。
  2. 功能策略:评估 openUBMC 是否已有类似功能,决定完整迁移或功能替代。

2. 迁移前准备

环境准备确保开发环境、依赖库和构建工具的正确配置,为后续构建提供基础。

2.1 环境准备

开发环境搭建:参考 openUBMC 社区文档,无需额外配置。文档地址:https://www.openubmc.cn/docs/zh/development/quick_start/prepare_environment/ubuntu_env.html

依赖库安装

  • BiSheng编译器:需要开发者单独申请,并解压至 /opt 目录下
  • profile文件配置:用于添加新编译器的路径,模板如下:
ini
{% set target_host = "aarch64-linux-gnu" %}
{% set standalone_toolchain = "/opt/BiSheng_arm64le" %}
{% set sysroot = "/opt/RTOS/208.10.0/arm64le_5.10_ek_preempt_pro/sdk" %}
{% set sdkroot = "/opt/hi1711sdk" %}
{% set cc_compiler = "clang" %}
{% set cxx_compiler = "clang++" %}

[settings]
os=Linux
arch=armv8
build_type=Release
compiler=clang
compiler.version=15
compiler.cppstd=20
compiler.runtime=dynamic
compiler.runtime_type=Release
compiler.runtime_version=v144

[buildenv]
PATH=+(path){{ standalone_toolchain }}/bin
KERNEL_PATH={{ sysroot }}/usr/src/kernel/
CONAN_CMAKE_SYSROOT={{ sysroot }}
CONAN_CMAKE_FIND_SDK_ROOT={{ sdkroot }}
CHOST={{ target_host }}
AR=llvm-ar
AS=as
LD=ld.lld
STRIP=llvm-strip
CC={{ cc_compiler }}
HOSTCC={{ cc_compiler }}
CXX={{ cxx_compiler }}
PKG_CONFIG_PATH={{ sysroot }}/lib64/pkgconfig:{{ sysroot }}/usr/lib64/pkgconfig
PKG_CONFIG=/usr/share/bingo/pkg_config.sh
SYS_ROOT = {{standalone_toolchain}}/sysroot
CFLAGS=-Wall -fPIC -fstack-protector-all -Os -fPIE -fno-common -std=gnu11
CXXFLAGS=-I{{ standalone_toolchain }}/{{ target_host }}/include/c++/v1 -I{{sysroot}}/usr/include -nostdinc++ -Wno-error -Wno-c99-extensions
LDFLAGS=-L{{standalone_toolchain}}/sysroot/lib64 -L{{sysroot}}/lib64

[conf]
tools.build:sysroot={{sysroot}}
tools.gnu:host_triplet={{target_host}}

注意:请确认 PATH 路径与实际 BiSheng 编译器安装路径一致。

构建工具配置:构建工具是 bingo,执行 init.py 后自动安装最新版本。由于目前该技术项目还在开发调试中,bingo 主仓还不支持资产迁移能力,因此您还需要拉取代码 https://gitcode.com/openUBMC/bingo.git , 执行 sh install_local.sh,重新安装该调试版本 bingo。


3. 构建系统迁移

openUBMC 采用 Conan2 作为核心 C/C++ 包管理器,实现可预测的依赖管理二进制包高效分发跨平台构建支持。我们已预先提供了 OpenBMC 核心框架的 Conan 包,您只需声明依赖即可快速构建。

3.1 构建框架介绍

双编译器策略:OpenBMC 组件使用 BiSheng LLVM 编译(支持 C++20),openUBMC 组件使用 GCC 7.3 编译。采用**"独立构建,Conan 包管理,统一集成"**策略:

text
+-----------------------+                          +-----------------------+
| OpenBMC 组件          |                          | openUBMC 组件          |
| (源代码)              |                          | (源代码)              |
+-----------------------+                          +-----------------------+
        | BiSheng LLVM 编译                                | GCC 7.3 编译
        v                                                  v
+-----------------------+                          +-----------------------+
| OpenBMC Conan 包      |                          | openUBMC Conan 包     |
| (BiSheng LLVM 编译版本) |                          | (GCC 7.3 编译版本)    |
+-----------------------+                          +-----------------------+

                                   |
                                   | 产品集成阶段 (Conan 包管理器)
                                   v
             +-------------------------------------------------------------+
             | manifest/manifest.yaml (声明所需 OpenBMC & openUBMC Conan 组件) |
             +-------------------------------------------------------------+
                                   |
                                   | Conan 包管理器解析依赖并解决冲突
                                   | (若组件在 openUBMC 中已存在,则以 GCC 7.3 编译版本为主)
                                   v
             +-------------------------------------------------------------+
             | 统一的 Conan 缓存                                         |
             | (包含所有兼容的 OpenBMC & openUBMC 组件二进制包)             |
             +-------------------------------------------------------------+
                                   |
                                   v
             +-------------------------------------------------------------+
             | 最终产品包 (hpm)                                             |
             | (openUBMC + OpenBMC 组件)                                    |
             +-------------------------------------------------------------+

3.2 Conan 依赖管理

3.2.1 Conan 组件构建策略

使用 conan_index:我们推荐使用 conan_indexhttps://gitcode.com/openUBMC/conan_index) 作为引入开源/自定义组件的标准途径,确保依赖的透明性、可控性与合规性。

目录结构

text
.
└── repo
    └── recipes2
        └── component_name
            ├── all
            │   ├── patches  # 存储特定版本的代码补丁
            │   │   ├── 0001-1.0.0-adapting-conan-build.patch
            │   ├── rootfs  # 运行时配置文件目录(推荐)
            │   │   ├── etc
            │   │   │   └── dbus-1
            │   │   │       └── system.d  # D-Bus 策略文件
            │   │   └── usr
            │   │       └── lib
            │   │           └── systemd
            │   │               └── system  # systemd 服务文件
            │   ├── conandata.yml
            │   ├── conanfile.py
            └── config.yml

文件作用

  • config.yml:定义组件基线版本,确保版本一致性
  • conandata.yml:承载组件元数据(源码下载链接、分支/提交、补丁、依赖配置)
  • conanfile.py:定义组件构建工程和包的创建逻辑
  • rootfs/:运行时配置文件目录,用于组织 systemd 服务文件、D-Bus 策略文件等运行时配置(推荐使用此目录结构)
3.2.1.1 config.yml 编写规范
yml
versions:
  "1.0.0": # 声明组件的特定版本
    folder: "all" # 指示该版本对应的Conan recipe文件所在的目录
3.2.1.2 conandata.yml 编写规范
yml
sources:  # 注意:使用 sources(复数)而非 source
  "1.0.0": # 对应于config.yml中定义的组件版本
    url: "https://gitcode.com/xxxx/xxxx.git" # 组件源码的Git仓库地址
    branch: "main" # 指定Git分支,推荐使用稳定的分支或标签
    shallow: true  # 可选:浅克隆,加快下载速度
    # commit: "abcdef1234567890abcdef1234567890abcdef12" # 或者,更精确地指定commit哈希

patches:
  "1.0.0": # 补丁应用于哪个版本
    - patch_file: "patches/0001-1.0.0-adapting-conan-build.patch" # 补丁文件的相对路径

requires:
  "1.0.0": # 该版本组件的运行时/构建时依赖
    - xxxx/1.0.0@openubmc.dev/dev # 依赖的其他Conan包及其版本
    - yyyy/[>=1.0.0]  # 支持版本范围声明
    - .... # 可以列出多个依赖项
3.2.1.3 conanfile.py 编写规范

对于基于 Meson 构建系统的 OpenBMC 组件,以下是 conanfile.py 模板:

python
import os
from conan import ConanFile
from conan.tools.meson import Meson, MesonToolchain
from conan.tools.files import copy, files
from conan.tools.layout import basic_layout
from conan.tools.scm import Git

required_conan_version = ">=2.13.0"

class ComponentConan(ConanFile):
    name = "component_name" # 组件名称,与conan_index中的目录名一致
    version = "1.0.0" # 组件版本,与config.yml和conandata.yml中的版本一致

    # 项目描述信息
    license = "GPL-2.0-or-later"
    author = "Your Name <your.email@example.com>"
    url = "https://gitcode.com/openUBMC/conan_index"
    description = "A brief description of your OpenBMC component."
    topics = ("openbmc", "conan", "meson")

    # 构建和包类型相关设置
    settings = "os", "compiler", "build_type", "arch"
    options = {"shared": [True, False], "fPIC": [True, False]}
    default_options = {"shared": False, "fPIC": True}
    generators = "PkgConfigDeps", "VirtualBuildEnv"

    def layout(self):
        # 定义源文件和构建输出的布局
        basic_layout(self)
        # 自定义包目录结构(可选)
        self.cpp.package.resdirs = ["usr/share"]
        self.cpp.package.bindirs = ["usr/bin"]

    def requirements(self):
        # 依赖项 (运行时和构建时)
        requires = self.conan_data.get("requires", {}).get(self.version, [])
        for req in requires:
            self.requires(req)

    def build_requirements(self):
        # 构建时工具依赖
        self.tool_requires('pkgconf/2.0.3')

    def export_sources(self):
        # 导出源代码和配置文件
        files.export_conandata_patches(self)
        # 导出 rootfs 目录(包含运行时配置文件)
        files.copy(self, "rootfs/*", self.recipe_folder, self.export_sources_folder)
        # 导出其他配置文件(如果有)
        # files.copy(self, "config.json", self.recipe_folder, self.export_sources_folder)

    def source(self):
        # 获取组件的源代码
        git = Git(self)
        git.fetch_commit(
            url=self.conan_data["sources"][self.version]["url"],
            commit=self.conan_data["sources"][self.version]["branch"])

    def generate(self):
        # 生成Meson所需的构建工具链文件
        tc = MesonToolchain(self)
        # 可以添加额外的编译标志(如果需要)
        # cxxflag = ["-I/path/to/include"]
        # tc.extra_cxxflags.extend(cxxflag)
        tc.generate()

    def build(self):
        # 应用补丁
        files.apply_conandata_patches(self)
        # 执行Meson构建命令
        meson = Meson(self)
        meson.configure()
        meson.build()
        meson.install()

    def package(self):
        # 将构建好的文件打包到Conan包中
        # Meson install 已经执行,这里主要处理 rootfs 目录
        # 复制 rootfs 目录内容到 package_folder,覆盖 meson 安装的文件
        files.copy(self, "*", 
                   os.path.join(self.export_sources_folder, "rootfs"), 
                   self.package_folder)
        # 如果有其他配置文件需要覆盖,可以在这里处理
        # config_dst_dir = os.path.join(self.package_folder, "usr/share/component_name")
        # os.makedirs(config_dst_dir, exist_ok=True)
        # files.copy(self, "config.json", 
        #            src=self.export_sources_folder, 
        #            dst=config_dst_dir)

    def package_info(self):
        # 定义包的消费者信息,例如库名、链接标志等
        self.cpp_info.libs = ["component_name"]  # 如果生成了库文件
        self.cpp_info.include_dirs = ["include"]
        self.cpp_info.set_property("cmake_find_mode", "both")
        self.cpp_info.set_property("pkg_config_name", "component_name")

关键方法说明

  • layout():定义源文件和构建输出的布局,可自定义包目录结构
  • requirements():声明组件的直接依赖项
  • build_requirements():声明构建时工具依赖(如 pkgconf)
  • export_sources():导出源代码和配置文件(包括 rootfs 目录)
  • source():获取源代码(使用 Git 工具从 conandata.yml 配置的仓库获取)
  • generate():生成 Meson 构建工具链文件
  • build():应用补丁并执行 Meson 构建
  • package():打包构建产物,将 rootfs 目录内容复制到包目录
  • package_info():定义包的消费者信息
3.2.1.4 运行时依赖管理

推荐使用 rootfs 目录组织运行时配置文件:在 conan_index 的组件目录下创建 rootfs 目录,按照目标系统的目录结构组织运行时配置文件:

text
all/
├── rootfs/
│   ├── etc/
│   │   └── dbus-1/
│   │       └── system.d/          # D-Bus 策略文件目录
│   │           └── service_name.conf
│   └── usr/
│       └── lib/
│           └── systemd/
│               └── system/        # systemd 服务文件目录
│                   ├── service_name.service
│                   └── multi-user.target.wants/  # 服务自启动软链接目录
│                       └── service_name.service -> ../service_name.service
├── conandata.yml
└── conanfile.py

配置步骤

  1. 创建 rootfs 目录结构:按照目标系统的目录结构创建 rootfs 目录,将 D-Bus 策略文件和 systemd 服务文件放置到对应位置。

  2. conanfile.py 中导出和打包

    • export_sources() 方法中导出 rootfs 目录
    • package() 方法中将 rootfs 目录内容复制到 package_folder
  3. D-Bus Policy 配置:将 D-Bus 策略文件(.conf)放置在 rootfs/etc/dbus-1/system.d/ 目录下。详细编写规范请参阅第4章 服务配置迁移

  4. Systemd 服务自启动:将 systemd 服务文件(.service)放置在 rootfs/usr/lib/systemd/system/ 目录下,并在 rootfs/usr/lib/systemd/system/multi-user.target.wants/ 目录下创建指向服务文件的软链接。详细配置请参阅第4章 服务配置迁移

优势:使用 rootfs 目录结构可以清晰地组织运行时配置文件,便于管理和维护,同时与目标系统的目录结构保持一致。

3.2.1.5 组件构建注意事项
  1. 明确依赖关系:在 conanfile.py 中精确声明所有直接和间接的 Conan 依赖,避免循环依赖
  2. Meson 配置适配:确保 Meson 项目的 meson.build 文件能够正确接收来自 Conan 的配置
  3. 代码补丁管理:尽量保持对上游代码的修改最小化,补丁文件与组件版本严格对应
  4. 编译器和 C++ 标准兼容性:确保组件代码在 BiSheng LLVM 和 GCC 7.3 下都能正确编译
3.2.1.6 组件构建与打包命令

conan_index 目录下,执行以下命令进行组件的构建:

shell
cd conan_index
bingo build -cp component_name/1.0.0@openubmc/dev --conan2 -pr profile.llvm.ini

命令参数说明

  • -cp component_name/1.0.0@openubmc/dev:Conan 包的完整引用(name/version@user/channel
  • --conan2:指定使用 Conan 2.x 版本
  • -pr profile.llvm.ini:指定 BiSheng LLVM 编译器的配置文件

成功执行后,bingo build 会在 Conan 本地缓存中创建并存储对应的二进制包。

3.2.2 Conan 产品构建:集成 OpenBMC 组件到 openUBMC 产品包

产品构建核心manifest.yml 文件定义了构成最终产品的所有组件、版本和构建选项。

配置步骤

  1. 产品仓拉取:拉取产品仓 https://gitcode.com/openUBMC/manifest,定位到 build/product/BMC/openUBMC/manifest.yml 文件

  2. 添加 expand_product 配置

yml
expand_product:
  product_name: openbmc
  profile: profile.llvm.ini
  dependencies:
    - conan: stdplus/1.0.0@openubmc/stable
    - conan: component_name/1.0.0@openubmc/dev

配置说明

  • product_name:需要注入资产的源产品名称
  • profile:构建该产品组件使用的 profile 文件(需确认 ~/.conan2/profiles 目录下存在该文件;profile 文件的编写规范请参考第 2.1 节的 profile 模板)
  • dependencies:OpenBMC 组件的 Conan 依赖列表,支持 namename/versionname/version@user/channel 格式

完成配置后,openUBMC 产品构建系统将能够识别、获取并集成所需的 OpenBMC 组件,最终生成包含所有兼容组件的完整产品包。


4. 服务配置迁移

4.1 systemd 服务文件迁移

systemd 服务文件定义了组件的启动方式、依赖关系和运行环境。

4.1.1 服务文件结构

标准 systemd 服务文件包含三个主要部分:

ini
[Unit]
Description=服务描述
After=依赖的服务

[Service]
Environment=环境变量
ExecStart=启动命令
SyslogIdentifier=日志标识
Type=服务类型
BusName=D-Bus服务名(如为D-Bus服务)

[Install]
WantedBy=目标单元

示例:以 phosphor-post-code-manager 的服务文件为例:

ini
[Unit]
Description=Post code manager
After=dbus.service

[Service]
Environment=LD_LIBRARY_PATH=/lib
ExecStart=/bin/post-code-manager --host 0 --config /usr/share/phosphor-post-code-manager/post-code-handlers.json
SyslogIdentifier=post-code-manager
Type=dbus
BusName=xyz.openbmc_project.State.Boot.PostCode0

[Install]
WantedBy=multi-user.target

4.1.2 服务自启动配置

conan_index 配置中,推荐使用 rootfs 目录结构来组织服务配置和自启动描述:

目录结构

text
all/
├── rootfs/
│   └── usr/
│       └── lib/
│           └── systemd/
│               └── system/
│                   ├── service_name.service  # systemd 服务文件
│                   └── multi-user.target.wants/  # 自启动软链接目录
│                       └── service_name.service -> ../service_name.service
├── conandata.yml
└── conanfile.py

配置说明

  • 将 systemd 服务文件放置在 rootfs/usr/lib/systemd/system/ 目录下
  • rootfs/usr/lib/systemd/system/multi-user.target.wants/ 目录下创建指向服务文件的软链接,实现服务自启动
  • conanfile.pyexport_sources()package() 方法中处理 rootfs 目录(参考第3.2.1.3节)

示例:以 phosphor-post-code-manager 为例,在 rootfs/usr/lib/systemd/system/ 目录下创建服务文件,并在 rootfs/usr/lib/systemd/system/multi-user.target.wants/ 目录下创建软链接。

4.1.3 服务依赖关系配置

推荐直接在服务文件的 [Unit] 段中显式声明依赖关系,这样更加直接和可控:

ini
[Unit]
After=dbus.service
Requires=dbus.service

4.2 D-Bus 服务配置迁移

D-Bus 策略文件定义了 D-Bus 服务的访问权限。在迁移到 Conan2 构建系统后,需要手动编写 D-Bus 策略配置文件

4.2.1 D-Bus 策略文件结构

D-Bus 策略文件采用 XML 格式,文件通常命名为 <服务名>.conf,安装到 /etc/dbus-1/system.d/ 目录。

示例:以 phosphor-post-code-manager 的 D-Bus 策略文件为例:

xml
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
  <!-- Allow root user to own the service -->
  <policy user="root">
    <allow own="xyz.openbmc_project.State.Boot.PostCode0"/>
    <allow send_destination="xyz.openbmc_project.State.Boot.PostCode0"/>
    <allow receive_sender="xyz.openbmc_project.State.Boot.PostCode0"/>
  </policy>

  <!-- Allow regular users to access the service -->
  <policy user="*">
    <allow send_destination="xyz.openbmc_project.State.Boot.PostCode0"/>
    <allow receive_sender="xyz.openbmc_project.State.Boot.PostCode0"/>
    <allow send_destination="xyz.openbmc_project.State.Boot.PostCode0"
           send_interface="xyz.openbmc_project.State.Boot.PostCode"/>
    <allow receive_sender="xyz.openbmc_project.State.Boot.PostCode0"
           receive_interface="xyz.openbmc_project.State.Boot.PostCode"/>
  </policy>

  <!-- Allow other users/processes to send messages to the service -->
  <policy context="default">
    <allow send_destination="xyz.openbmc_project.State.Boot.PostCode0"
           send_interface="xyz.openbmc_project.State.Boot.PostCode"/>
    <allow receive_sender="xyz.openbmc_project.State.Boot.PostCode0"
           receive_interface="xyz.openbmc_project.State.Boot.PostCode"/>
  </policy>
</busconfig>

4.2.2 策略文件配置要点

  1. 服务名注册权限<allow own="服务名"/> 允许指定用户注册该 D-Bus 服务名
  2. 接口访问权限
    • <allow send_destination="服务名" send_interface="接口名"/>:允许向指定服务的指定接口发送消息
    • <allow receive_sender="服务名" receive_interface="接口名"/>:允许接收来自指定服务的指定接口的消息
  3. 权限策略类型
    • <policy user="root">:针对 root 用户的策略
    • <policy user="*">:针对所有用户的策略
    • <policy context="default">:默认策略
  4. 配置原则:最小权限原则,明确接口,服务名一致性

4.2.3 策略文件安装配置

推荐方式:使用 rootfs 目录

conan_index 配置中,推荐将 D-Bus 策略文件放置在 rootfs 目录下:

目录结构

text
all/
├── rootfs/
│   └── etc/
│       └── dbus-1/
│           └── system.d/
│               └── service_name.conf  # D-Bus 策略文件
├── conandata.yml
└── conanfile.py

conanfile.pyexport_sources()package() 方法中处理 rootfs 目录(参考第3.2.1.3节),策略文件会自动被打包到 Conan 包的 /etc/dbus-1/system.d/ 目录。

传统方式:在 meson.build 中安装

如果组件使用 Meson 构建系统,也可以在 meson.build 中安装 D-Bus 策略文件:

meson
# Install D-Bus policy file
install_data(
    'xyz.openbmc_project.State.Boot.PostCode.conf',
    install_dir: '/etc/dbus-1/system.d')

注意:如果同时使用两种方式,rootfs 目录中的文件会在 package() 方法中覆盖 Meson 安装的文件。


5. 常见问题与故障排除

5.1 构建问题

编译错误

  1. 头文件找不到:检查 meson.build 内容是否存在绝对路径、pkg-config 指定错误等问题
  2. C++ 类型检查编译错误:推荐使用 clang15 版本进行本地编译调试,clang 在类型检查上通常更加严格
  3. C++20 以上的特性编译错误:BiSheng LLVM 仅支持 C++20 的特性,对于高版本特性需要进行 C++ 降版本

链接错误

  • 最可能出现的链接问题就是 conan_index 中未声明 pkg-config 的路径。使用 require 或者添加 pkg-config 的 path 路径:

    方式一:通过 conandata.ymlrequires 声明 Conan 依赖

    适用场景:所依赖的库已在 conan_index 中以 Conan 包形式托管,Conan 会自动将其 .pc 文件路径注入 PKG_CONFIG_PATH

    yaml
    # conandata.yml
    requires:
      "1.0.0":
        - sdbusplus/1.0.0@openubmc/stable   # 依赖已入库的 Conan 包
        - phosphor-logging/1.0.0@openubmc/stable

    conanfile.pyrequirements() 方法中读取上述声明:

    python
    def requirements(self):
        requires = self.conan_data.get("requires", {}).get(self.version, [])
        for req in requires:
            self.requires(req)

    声明后,Meson 即可通过 dependency('sdbusplus') 等正常找到对应库并完成链接。

    方式二:在 conanfile.pygenerate() 中手动追加 pkg-config 路径

    适用场景:依赖的库为系统库或暂未纳入 Conan 管理,其 .pc 文件存在于 PKG_CONFIG_PATH 中,但 Meson 工具链默认不包含该路径。

    python
    from conan.tools.meson import MesonToolchain
    from conan.tools.env import VirtualBuildEnv
    
    def generate(self):
        tc = MesonToolchain(self)
        ms = VirtualBuildEnv(self)
        # 将 Conan 管理的 PKG_CONFIG_PATH 追加到 Meson 的搜索路径
        pkg_path = ms.vars().get("PKG_CONFIG_PATH")
        if pkg_path:
            tc.properties["pkg_config_libdir"] = pkg_path.split(":")
        tc.generate()

    若需要额外追加自定义路径(例如交叉编译 sysroot 下的 pkgconfig 目录),可手动扩展列表:

    python
    def generate(self):
        tc = MesonToolchain(self)
        ms = VirtualBuildEnv(self)
        pkg_paths = []
        pkg_path = ms.vars().get("PKG_CONFIG_PATH")
        if pkg_path:
            pkg_paths = pkg_path.split(":")
        # 补充 sysroot 下的 pkgconfig 目录(交叉编译场景)
        sysroot = "/path/to/sysroot"
        pkg_paths += [
            f"{sysroot}/usr/lib64/pkgconfig",
            f"{sysroot}/usr/share/pkgconfig",
        ]
        tc.properties["pkg_config_libdir"] = pkg_paths
        tc.generate()

5.2 运行时问题

服务启动失败

  1. 服务未自启动:检查是否配置了 multi-user.target.wants。如果已经配置,尝试手动执行服务配置中的启动命令,如果可以启动,那么最大的可能就是启动顺序问题,检查服务配置中是否配置了 After=dbus.service
  2. 手动拉起服务也失败:通常是由于服务中出现 core dump 之类的错误导致程序退出,通过 journalctl -xeu <service的名称> 来查看错误日志

D-Bus 问题

  1. 服务注册失败
    • 检查 D-Bus 策略文件中是否配置了服务名注册权限(<allow own="服务名"/>
    • 确认策略文件已正确安装到 /etc/dbus-1/system.d/ 目录
    • 验证服务运行的用户身份
    • 检查是否有其他服务已占用相同的服务名
  2. 接口调用失败
    • 检查 D-Bus 策略文件中是否配置了接口访问权限
    • 确认接口名称拼写正确
    • 验证服务端是否已正确导出接口
  3. 权限拒绝
    • 审查 D-Bus 策略文件的权限配置,确保遵循最小权限原则
    • 确认策略文件中的权限范围足够
    • 验证策略文件的语法正确性

附录

附录A:代码分析

适用场景:本章节主要面向系统级迁移场景,即需要迁移多个组件或整个子系统的情况。对于单个组件的迁移,通常不需要进行深入的代码分析,可以直接参考前面的章节进行迁移。

A.1 依赖关系分析

依赖关系分析是 OpenBMC 组件迁移前期至关重要的一项任务。本迁移指导书推荐采用如下的维度进行分析:

  1. 构建时依赖 (Build-Time Dependencies)

    • Meson 构建工程/Subprojects
    • 代码生成依赖
  2. 运行时依赖 (Run-Time Dependencies)

    • 动态链接库 (Dynamic Libraries)
    • 系统服务与守护进程
    • 配置文件与数据源
  3. 组件间接口依赖 (Inter-Component Interface Dependencies)

    • D-Bus 接口
    • 组件 ABI 接口
    • 组件对外进程接口
    • Lib 库依赖
  4. 外部接口依赖 (External Interface Dependencies)

    • 开源软件依赖
    • 驱动接口依赖
  5. 被依赖项 (该组件对外提供的接口)

    • D-Bus 服务对外提供的接口
    • 组件 ABI 接口
    • 组件对外进程接口
    • 工具接口

A.2 C++ 特性分析

在本 OpenBMC 资产迁移项目中,我们提供了完全支持 C++20 特性的 BiSheng LLVM 编译器。如果您的项目当前使用了 C++23 或更高版本的特定高级特性,那么在迁移到 C++20 兼容的 BiSheng LLVM 环境时,您需要进行审慎评估,可能需要对高级特性进行重写或适配。

A.3 功能特性分析

在迁移 OpenBMC 组件之前,进行彻底的功能特性分析是至关重要的一步。具体而言,功能特性分析应包括以下几个方面:

  1. 核心功能匹配度评估

    • 功能对齐:详细列出待迁移组件的所有核心功能,并逐一与 openUBMC 现有功能进行对比
    • 功能冗余识别:如果 openUBMC 已经提供了相同或类似的功能,需要评估是否可以利用现有实现
    • 功能差距分析:对于 openUBMC 尚未实现或部分实现的功能,需要明确功能差距
  2. 性能与资源考量

    • 性能基线对比
    • 资源需求评估
  3. 安全性与合规性分析

    • 安全漏洞评估
    • 合规性检查
  4. 可维护性与可扩展性

    • 架构适配性
    • 代码质量评估

附录B:D-Bus 迁移

B.1 D-Bus 映射简介

dbus-proxy 是 openUBMC 项目中专门设计的 D-Bus 兼容性组件,它扮演着 OpenBMC D-Bus 接口与 openUBMC D-Bus 接口之间的"翻译官"角色。其核心价值在于实现反向代理:在 OpenBMC D-Bus 总线上创建"虚拟"的 OpenBMC 资源,使得迁移后的 OpenBMC 组件能够像在原生 OpenBMC 环境中一样调用这些虚拟资源,而 dbus-proxy 则将这些调用转发到 openUBMC 的真实 D-Bus 资源。

架构设计dbus-proxy 采用**"配置化映射 + 代码化处理器"**的混合架构:

  • 配置化映射:对于简单的 D-Bus 到 D-Bus 映射,通过 mapping_rules.json 配置文件即可实现,无需编写代码
  • 代码化处理器(Handler):对于复杂的业务逻辑,通过编写 C++ Handler 处理器来实现

工作流程

text
OpenBMC 组件请求

OpenBMC D-Bus System Bus (虚拟对象)

dbus-proxy (RequestRouter)
    ├─→ 配置化映射 (PropertyProxy/MethodProxy/SignalProxy)
    └─→ 代码化处理器 (Handler)

openUBMC D-Bus User Bus (真实对象)

B.2 属性映射配置示例

属性映射用于将 OpenBMC 组件的属性读取/写入请求转发到 openUBMC 的对应属性。

基本属性映射示例

json
{
    "id": "sensor_value_property",
    "type": "property_to_property",
    "source": {
        "bus_domain": "system",
        "bus": "xyz.openbmc_project.Sensors",
        "path": "/xyz/openbmc_project/sensors/temperature/cpu0",
        "interface_name": "xyz.openbmc_project.Sensor.Value",
        "member": "Value"
    },
    "target": {
        "bus_domain": "user",
        "bus": "bmc.kepler.sensor",
        "path": "/bmc/kepler/sensors/temperature/cpu0",
        "interface_name": "bmc.kepler.Sensor",
        "member": "Reading"
    },
    "return_mappings": [
        {
            "source_index": 0,
            "target_index": 0,
            "source_type": "d",    // 显式声明:double 类型
            "target_type": "d"     // 显式声明:double 类型
        }
    ]
}

注意:即使源端和目标端的类型相同,也强烈推荐显式声明 source_typetarget_type,以避免类型自动推断时的潜在错误。

带类型转换的属性映射

json
{
    "id": "temperature_kelvin_to_celsius",
    "type": "property_to_property",
    "source": {
        "bus_domain": "system",
        "bus": "xyz.openbmc_project.Sensors",
        "path": "/xyz/openbmc_project/sensors/temp",
        "interface_name": "xyz.openbmc_project.Sensor.Value",
        "member": "Value"
    },
    "target": {
        "bus_domain": "user",
        "bus": "bmc.kepler.sensor",
        "path": "/bmc/kepler/sensors/temp",
        "interface_name": "bmc.kepler.Sensor",
        "member": "ValueCelsius"
    },
    "return_mappings": [
        {
            "source_index": 0,
            "target_index": 0,
            "source_type": "d",
            "target_type": "d",
            "conversion": "kelvin_to_celsius"
        }
    ]
}

参数映射字段说明

  • source_index:源端参数的索引(从0开始),对于属性读取,通常为0
  • target_index:目标端参数的索引
  • source_type:源端 D-Bus 类型签名(如 d 表示 double,s 表示 string,y 表示 uint8)
  • target_type:目标端 D-Bus 类型签名
  • conversion:类型转换函数名称(可选),如 kelvin_to_celsiusmultiply_1000

更多 D-Bus 迁移内容:包括方法映射、信号映射、Handler 处理器编写等详细内容,请参考dbus-proxy


附录C:配置文件模板

C.1 rootfs 目录结构模板

推荐使用 rootfs 目录组织运行时配置文件

text
all/
├── rootfs/
│   ├── etc/
│   │   └── dbus-1/
│   │       └── system.d/
│   │           └── component_name.conf  # D-Bus 策略文件
│   └── usr/
│       └── lib/
│           └── systemd/
│               └── system/
│                   ├── component_name.service  # systemd 服务文件
│                   └── multi-user.target.wants/
│                       └── component_name.service -> ../component_name.service  # 自启动软链接
├── patches/
│   └── 0001-1.0.0-adapting-conan-build.patch
├── conandata.yml
└── conanfile.py

说明

  • rootfs/etc/dbus-1/system.d/:放置 D-Bus 策略文件(.conf
  • rootfs/usr/lib/systemd/system/:放置 systemd 服务文件(.service
  • rootfs/usr/lib/systemd/system/multi-user.target.wants/:放置服务自启动软链接

C.2 conanfile.py 模板

(见第3.2.1.3节)

C.3 systemd 服务文件模板

ini
[Unit]
Description=Component Name Service
After=dbus.service

[Service]
Environment=LD_LIBRARY_PATH=/lib
ExecStart=/bin/component_name
SyslogIdentifier=component-name
Type=dbus
BusName=xyz.openbmc_project.Component.Name

[Install]
WantedBy=multi-user.target

C.4 D-Bus 配置文件模板

xml
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
  <policy user="root">
    <allow own="xyz.openbmc_project.Component.Name"/>
    <allow send_destination="xyz.openbmc_project.Component.Name"/>
    <allow receive_sender="xyz.openbmc_project.Component.Name"/>
  </policy>

  <policy user="*">
    <allow send_destination="xyz.openbmc_project.Component.Name"/>
    <allow receive_sender="xyz.openbmc_project.Component.Name"/>
    <allow send_destination="xyz.openbmc_project.Component.Name"
           send_interface="xyz.openbmc_project.Component.Interface"/>
    <allow receive_sender="xyz.openbmc_project.Component.Name"
           receive_interface="xyz.openbmc_project.Component.Interface"/>
  </policy>

  <policy context="default">
    <allow send_destination="xyz.openbmc_project.Component.Name"
           send_interface="xyz.openbmc_project.Component.Interface"/>
    <allow receive_sender="xyz.openbmc_project.Component.Name"
           receive_interface="xyz.openbmc_project.Component.Interface"/>
  </policy>
</busconfig>

附录D:参考资源


附录E:术语表

  • Conan2:C/C++ 包管理器,用于依赖管理和二进制包分发
  • dbus-proxy:D-Bus 兼容性组件,实现 OpenBMC 与 openUBMC 之间的 D-Bus 接口映射
  • BiSheng LLVM:基于 LLVM-17 的嵌入式编译工具链,支持 C++20
  • conan_index:中心化的组件配置仓库,用于管理 Conan 包的元数据和构建逻辑
  • manifest.yml:产品级配置清单,定义构成最终产品的所有组件和版本