1.解析 Conan 依赖
mds/service.json 里声明了构建依赖 libmc4lua/[>=1.1.0]。Conan 安装后会在构建目录的 generators/ 生成 libmc4lua-config.cmake 等文件;find_package 会加载它们。
2.注册可用的 CMake 目标(现代用法)
加载后可以使用 imported target,例如:
libmc4lua::libcutils --- 在 sml_base、sml_histore、platform 等里链接
libmc4lua::libmc4lua --- 在 l_sml/CMakeLists.txt 里链接(聚合了 libcutils)
设置传统变量(兼容旧写法)
同时会设置如 libmc4lua_INCLUDE_DIRS、libmc4lua_LIBRARIES 等,供仍用变量方式的 CMake 使用。
拉取传递依赖
生成的 config 还会 find_dependency 其依赖(如 json、huawei_secure_c、boost、liblogger 等),保证链接 libmc4lua 时依赖链完整。
set_target_properties(${L_SML_LIB} PROPERTIES PREFIX "") 用来去掉共享库文件名前面的默认 lib 前缀。
背景
第 4 行用 add_library(sml SHARED ...) 建的是共享库。在 Linux 上,CMake 默认会给共享库加 lib 前缀,产物一般是:
默认:libsml.so
设置 PREFIX "" 后:sml.so
为什么要这样
第 37 行把它安装到 opt/bmc/luaclib,这是 Lua 的 C 模块目录。Lua 用 require("sml") 加载时,会按 package.cpath 去找名为 sml.so 的模块,不会去找 libsml.so。
若不加这句,编译出来是 libsml.so,运行时 require("sml") 会找不到模块。
小结
设置 产物文件名 Lua 能否 require("sml")
不写(默认)
通常不行
PREFIX ""
可以
这是构建 Lua C 扩展(luaclib) 时的常见写法:让生成的 .so 文件名与 require 的模块名一致
pkg_search_module(GLIB REQUIRED glib-2.0) 通过 pkg-config 查找系统里的 GLib 2.0,并把结果放进以 GLIB_ 为前缀的 CMake 变量,供后面编译、链接使用。
会生成哪些变量
典型包括:
GLIB_INCLUDE_DIRS --- 头文件目录(如 /usr/include/glib-2.0)
GLIB_LIBRARIES --- 链接库(如 glib-2.0)
GLIB_CFLAGS / GLIB_LDFLAGS 等
使用:
target_include_directories(${L_SML_LIB}
...
PUBLIC GLIBINCLUDEDIRS)targetlinklibraries({GLIB_INCLUDE_DIRS} ) target_link_libraries(GLIBINCLUDEDIRS)targetlinklibraries({L_SML_LIB}
PUBLIC ${GLIB_LIBRARIES}
和 find_package(libmc4lua) 的区别
pkg_search_module:查系统/构建环境里通过 pkg-config 安装的库(GLib 一般由系统或 Conan 的 PkgConfigDeps 提供)
find_package(libmc4lua):查 Conan 包提供的 CMake 配置
service.json 的 dependencies:给 Conan 构建系统 用
在 MDS / 应用元数据 层声明:storage 构建时需要哪些 Conan 包。
会和 conanbase.py 里的 requirements() 一起参与依赖解析、安装、生成 CMake 配置。
conanbase.py 里也有类似声明:
def requirements(self):
self.requires("libmc4lua/[>=1.1.0]@openubmc/stable")
self.requires("mctpd/[>=0.0.1]@openubmc/stable")
self.requires("libmgmt_protocol/[>=1.70.6, include_prerelease=True]@openubmc/stable")
dependencies / requirements 负责 把包装进构建环境;find_package 负责 让 CMake 在编译时能用这些包。
对 libmc4lua、libmgmt_protocol 这类包,两边通常都要出现(一个拉包,一个链接)。
l_array.h的作用:
这是一个 纯静态工具类(无实例成员),职责只有两件事:
register_to:在模块加载时,把 SML_ARRAY_INFO_S 注册进 sml_core 导出表。
def_properties:声明该结构体在 Lua 里有哪些字段/属性(实现藏在 .cpp)。
和同目录的 l_ld、l_pd、l_ctrl 完全同一套模式:一个 C 结构体 ↔ 一个 l_xxx 类 ↔ 一个 register_to。
模块入口在 l_sml.cpp 里统一汇总:
LUA_EXPORT int luaopen_sml_core(lua_State *L)
{
...
l_array::register_to(L, t);
l_pd::register_to(L, t);
l_ld::register_to(L, t);
...
return 1;
}
编译产物是 sml.so(require 时模块名 sml_core),l_array 只是其中的一个子注册单元。
l_sml.h: 提供了2个模板函数
// 把结构体清空
template
void reset_zero(T *o) { ... }
// 把C的定长数组,如pd_ids[10] 转化成lua table
template
int push_array(lua_State *L, T *arr, size_t n)
{
auto t = luawrap::stack::new_table(L, n);
for (size_t i = 0; i < n; ++i) {
t.set(i + 1, arr[i]); // Lua 下标从 1 开始
}
return 1;
}
flowchart LR
A["require 'sml.core'"] --> B["luaopen_sml_core(L)"]
B --> C["创建空 table t"]
C --> D["各 l_xxx::register_to 往 t 填内容"]
D --> E["t.set 常量"]
E --> F["return 1 → Lua 得到模块表"]
F --> G["init.lua / cmds.lua 使用 sml_core.xxx"]










一句话
动态链接下:编译时必须靠头文件知道 debug_log 长什么样;libpd_log_parse_open.so 里只有调用和"依赖 liblogging.so"的记录;真正执行时由系统加载 liblogging.so 并提供实现------这就是 target_link_libraries(liblogger::liblogger) + #include 的标准分工。

