文档说明
适用范围
本文档适用于需要将 OpenBMC 组件迁移到 openUBMC 框架的开发人员和技术团队。
文档目标
- 提供快速上手的迁移流程指导
- 重点说明构建系统迁移(Conan2)
- 提供常见问题解决方案
- 帮助开发者高效完成组件迁移
反馈渠道
如有问题或建议,请通过以下方式反馈:
- openUBMC社区论坛
1. 概述
1.1 为什么迁移?
迁移背景:多家伙伴存在 OpenBMC 的历史资产,为了应对快速迁移、低成本应用迁移的需求,我们提供了 OpenBMC 资产迁移的一整套解决方案。
解决方案:
- 构建系统迁移:采用 Conan2 作为包管理器,提供可预测的依赖管理、二进制包高效分发和跨平台构建支持
- 运行时兼容:通过
dbus-proxy实现OpenBMC D-Bus 接口映射,OpenBMC 组件代码基本无需修改即可运行 - 预置核心框架:已预先提供了 OpenBMC 核心框架的 Conan 包(如
stdplus、sdbusplus等) - 基于 openUBMC 的适配层:对于 OpenBMC 和 openUBMC 都具备的功能,我们借助 dbus-proxy 代理层,实现将原本依赖 OpenBMC 组件的能力,无缝切换为 openUBMC 现有组件的能力,减少适配工作量,提升迁移效率。
迁移成本:极低!您只需:
- 在
conan_index中配置组件元数据 - 在
manifest.yml中声明依赖 - 执行构建命令
即可完成组件迁移,无需修改业务代码。
1.2 迁移流程概览
迁移遵循"准备→构建→配置→验证"的简单流程:
迁移路径:
- 单个组件迁移:按第2-4章直接迁移,通常无需深入代码分析。
- 系统级迁移:涉及多个组件时,参考附录A 代码分析进行依赖关系分析。
1.3 关键决策点
- 迁移范围:单个组件直接迁移,系统级迁移需先进行代码分析(附录A)。
- 功能策略:评估 openUBMC 是否已有类似功能,决定完整迁移或功能替代。
2. 迁移前准备
环境准备确保开发环境、依赖库和构建工具的正确配置,为后续构建提供基础。
2.1 环境准备
开发环境搭建:参考 openUBMC 社区文档,无需额外配置。文档地址:https://www.openubmc.cn/docs/zh/development/quick_start/prepare_environment/ubuntu_env.html
依赖库安装:
- BiSheng编译器:需要开发者单独申请,并解压至
/opt目录下 - profile文件配置:用于添加新编译器的路径,模板如下:
{% 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 包管理,统一集成"**策略:
+-----------------------+ +-----------------------+
| 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_index(https://gitcode.com/openUBMC/conan_index) 作为引入开源/自定义组件的标准途径,确保依赖的透明性、可控性与合规性。
目录结构:
.
└── 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 编写规范
versions:
"1.0.0": # 声明组件的特定版本
folder: "all" # 指示该版本对应的Conan recipe文件所在的目录3.2.1.2 conandata.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 模板:
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 目录,按照目标系统的目录结构组织运行时配置文件:
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配置步骤:
创建
rootfs目录结构:按照目标系统的目录结构创建rootfs目录,将 D-Bus 策略文件和 systemd 服务文件放置到对应位置。在
conanfile.py中导出和打包:- 在
export_sources()方法中导出rootfs目录 - 在
package()方法中将rootfs目录内容复制到package_folder
- 在
D-Bus Policy 配置:将 D-Bus 策略文件(
.conf)放置在rootfs/etc/dbus-1/system.d/目录下。详细编写规范请参阅第4章 服务配置迁移。Systemd 服务自启动:将 systemd 服务文件(
.service)放置在rootfs/usr/lib/systemd/system/目录下,并在rootfs/usr/lib/systemd/system/multi-user.target.wants/目录下创建指向服务文件的软链接。详细配置请参阅第4章 服务配置迁移。
优势:使用 rootfs 目录结构可以清晰地组织运行时配置文件,便于管理和维护,同时与目标系统的目录结构保持一致。
3.2.1.5 组件构建注意事项
- 明确依赖关系:在
conanfile.py中精确声明所有直接和间接的 Conan 依赖,避免循环依赖 - Meson 配置适配:确保 Meson 项目的
meson.build文件能够正确接收来自 Conan 的配置 - 代码补丁管理:尽量保持对上游代码的修改最小化,补丁文件与组件版本严格对应
- 编译器和 C++ 标准兼容性:确保组件代码在 BiSheng LLVM 和 GCC 7.3 下都能正确编译
3.2.1.6 组件构建与打包命令
在 conan_index 目录下,执行以下命令进行组件的构建:
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 文件定义了构成最终产品的所有组件、版本和构建选项。
配置步骤:
产品仓拉取:拉取产品仓 https://gitcode.com/openUBMC/manifest,定位到
build/product/BMC/openUBMC/manifest.yml文件添加
expand_product配置:
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 依赖列表,支持name、name/version或name/version@user/channel格式
完成配置后,openUBMC 产品构建系统将能够识别、获取并集成所需的 OpenBMC 组件,最终生成包含所有兼容组件的完整产品包。
4. 服务配置迁移
4.1 systemd 服务文件迁移
systemd 服务文件定义了组件的启动方式、依赖关系和运行环境。
4.1.1 服务文件结构
标准 systemd 服务文件包含三个主要部分:
[Unit]
Description=服务描述
After=依赖的服务
[Service]
Environment=环境变量
ExecStart=启动命令
SyslogIdentifier=日志标识
Type=服务类型
BusName=D-Bus服务名(如为D-Bus服务)
[Install]
WantedBy=目标单元示例:以 phosphor-post-code-manager 的服务文件为例:
[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.target4.1.2 服务自启动配置
在 conan_index 配置中,推荐使用 rootfs 目录结构来组织服务配置和自启动描述:
目录结构:
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.py的export_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] 段中显式声明依赖关系,这样更加直接和可控:
[Unit]
After=dbus.service
Requires=dbus.service4.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 策略文件为例:
<!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 策略文件配置要点
- 服务名注册权限:
<allow own="服务名"/>允许指定用户注册该 D-Bus 服务名 - 接口访问权限:
<allow send_destination="服务名" send_interface="接口名"/>:允许向指定服务的指定接口发送消息<allow receive_sender="服务名" receive_interface="接口名"/>:允许接收来自指定服务的指定接口的消息
- 权限策略类型:
<policy user="root">:针对 root 用户的策略<policy user="*">:针对所有用户的策略<policy context="default">:默认策略
- 配置原则:最小权限原则,明确接口,服务名一致性
4.2.3 策略文件安装配置
推荐方式:使用 rootfs 目录
在 conan_index 配置中,推荐将 D-Bus 策略文件放置在 rootfs 目录下:
目录结构:
all/
├── rootfs/
│ └── etc/
│ └── dbus-1/
│ └── system.d/
│ └── service_name.conf # D-Bus 策略文件
├── conandata.yml
└── conanfile.py在 conanfile.py 的 export_sources() 和 package() 方法中处理 rootfs 目录(参考第3.2.1.3节),策略文件会自动被打包到 Conan 包的 /etc/dbus-1/system.d/ 目录。
传统方式:在 meson.build 中安装
如果组件使用 Meson 构建系统,也可以在 meson.build 中安装 D-Bus 策略文件:
# 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 构建问题
编译错误:
- 头文件找不到:检查
meson.build内容是否存在绝对路径、pkg-config 指定错误等问题 - C++ 类型检查编译错误:推荐使用 clang15 版本进行本地编译调试,clang 在类型检查上通常更加严格
- C++20 以上的特性编译错误:BiSheng LLVM 仅支持 C++20 的特性,对于高版本特性需要进行 C++ 降版本
链接错误:
最可能出现的链接问题就是
conan_index中未声明 pkg-config 的路径。使用require或者添加 pkg-config 的 path 路径:方式一:通过
conandata.yml的requires声明 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.py的requirements()方法中读取上述声明:pythondef requirements(self): requires = self.conan_data.get("requires", {}).get(self.version, []) for req in requires: self.requires(req)声明后,Meson 即可通过
dependency('sdbusplus')等正常找到对应库并完成链接。方式二:在
conanfile.py的generate()中手动追加 pkg-config 路径适用场景:依赖的库为系统库或暂未纳入 Conan 管理,其
.pc文件存在于PKG_CONFIG_PATH中,但 Meson 工具链默认不包含该路径。pythonfrom 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 目录),可手动扩展列表:
pythondef 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 运行时问题
服务启动失败:
- 服务未自启动:检查是否配置了
multi-user.target.wants。如果已经配置,尝试手动执行服务配置中的启动命令,如果可以启动,那么最大的可能就是启动顺序问题,检查服务配置中是否配置了After=dbus.service - 手动拉起服务也失败:通常是由于服务中出现 core dump 之类的错误导致程序退出,通过
journalctl -xeu <service的名称>来查看错误日志
D-Bus 问题:
- 服务注册失败:
- 检查 D-Bus 策略文件中是否配置了服务名注册权限(
<allow own="服务名"/>) - 确认策略文件已正确安装到
/etc/dbus-1/system.d/目录 - 验证服务运行的用户身份
- 检查是否有其他服务已占用相同的服务名
- 检查 D-Bus 策略文件中是否配置了服务名注册权限(
- 接口调用失败:
- 检查 D-Bus 策略文件中是否配置了接口访问权限
- 确认接口名称拼写正确
- 验证服务端是否已正确导出接口
- 权限拒绝:
- 审查 D-Bus 策略文件的权限配置,确保遵循最小权限原则
- 确认策略文件中的权限范围足够
- 验证策略文件的语法正确性
附录
附录A:代码分析
适用场景:本章节主要面向系统级迁移场景,即需要迁移多个组件或整个子系统的情况。对于单个组件的迁移,通常不需要进行深入的代码分析,可以直接参考前面的章节进行迁移。
A.1 依赖关系分析
依赖关系分析是 OpenBMC 组件迁移前期至关重要的一项任务。本迁移指导书推荐采用如下的维度进行分析:
构建时依赖 (Build-Time Dependencies):
- Meson 构建工程/Subprojects
- 代码生成依赖
运行时依赖 (Run-Time Dependencies):
- 动态链接库 (Dynamic Libraries)
- 系统服务与守护进程
- 配置文件与数据源
组件间接口依赖 (Inter-Component Interface Dependencies):
- D-Bus 接口
- 组件 ABI 接口
- 组件对外进程接口
- Lib 库依赖
外部接口依赖 (External Interface Dependencies):
- 开源软件依赖
- 驱动接口依赖
被依赖项 (该组件对外提供的接口):
- D-Bus 服务对外提供的接口
- 组件 ABI 接口
- 组件对外进程接口
- 工具接口
A.2 C++ 特性分析
在本 OpenBMC 资产迁移项目中,我们提供了完全支持 C++20 特性的 BiSheng LLVM 编译器。如果您的项目当前使用了 C++23 或更高版本的特定高级特性,那么在迁移到 C++20 兼容的 BiSheng LLVM 环境时,您需要进行审慎评估,可能需要对高级特性进行重写或适配。
A.3 功能特性分析
在迁移 OpenBMC 组件之前,进行彻底的功能特性分析是至关重要的一步。具体而言,功能特性分析应包括以下几个方面:
核心功能匹配度评估:
- 功能对齐:详细列出待迁移组件的所有核心功能,并逐一与 openUBMC 现有功能进行对比
- 功能冗余识别:如果 openUBMC 已经提供了相同或类似的功能,需要评估是否可以利用现有实现
- 功能差距分析:对于 openUBMC 尚未实现或部分实现的功能,需要明确功能差距
性能与资源考量:
- 性能基线对比
- 资源需求评估
安全性与合规性分析:
- 安全漏洞评估
- 合规性检查
可维护性与可扩展性:
- 架构适配性
- 代码质量评估
附录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 处理器来实现
工作流程:
OpenBMC 组件请求
↓
OpenBMC D-Bus System Bus (虚拟对象)
↓
dbus-proxy (RequestRouter)
├─→ 配置化映射 (PropertyProxy/MethodProxy/SignalProxy)
└─→ 代码化处理器 (Handler)
↓
openUBMC D-Bus User Bus (真实对象)B.2 属性映射配置示例
属性映射用于将 OpenBMC 组件的属性读取/写入请求转发到 openUBMC 的对应属性。
基本属性映射示例:
{
"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_type 和 target_type,以避免类型自动推断时的潜在错误。
带类型转换的属性映射:
{
"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开始),对于属性读取,通常为0target_index:目标端参数的索引source_type:源端 D-Bus 类型签名(如d表示 double,s表示 string,y表示 uint8)target_type:目标端 D-Bus 类型签名conversion:类型转换函数名称(可选),如kelvin_to_celsius、multiply_1000等
更多 D-Bus 迁移内容:包括方法映射、信号映射、Handler 处理器编写等详细内容,请参考dbus-proxy
附录C:配置文件模板
C.1 rootfs 目录结构模板
推荐使用 rootfs 目录组织运行时配置文件:
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 服务文件模板
[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.targetC.4 D-Bus 配置文件模板
<!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:参考资源
- openUBMC 社区文档:https://www.openubmc.cn/docs
- conan_index:https://gitcode.com/openUBMC/conan_index
- dbus-proxy:https://gitcode.com/openUBMC/obmc_dbus_proxy
- bingo:https://gitcode.com/openUBMC/bingo
附录E:术语表
- Conan2:C/C++ 包管理器,用于依赖管理和二进制包分发
- dbus-proxy:D-Bus 兼容性组件,实现 OpenBMC 与 openUBMC 之间的 D-Bus 接口映射
- BiSheng LLVM:基于 LLVM-17 的嵌入式编译工具链,支持 C++20
- conan_index:中心化的组件配置仓库,用于管理 Conan 包的元数据和构建逻辑
- manifest.yml:产品级配置清单,定义构成最终产品的所有组件和版本