已开启
feat: 新增 community/cmp 三方库适配 #2278
feat: 新增 community/cmp 三方库适配 #2278
已开启
STF-Zero创建于 10月4日
共 11 个文件变更+412-0
@@ -0,0 +1,195 @@
1+# Copyright (c) 2026 STF-Zero
2+# Licensed under the Apache License, Version 2.0 (the "License");
3+# you may not use this file except in compliance with the License.
4+# You may obtain a copy of the License at
5+#
6+# http://www.apache.org/licenses/LICENSE-2.0
7+#
8+# Unless required by applicable law or agreed to in writing, software
9+# distributed under the License is distributed on an "AS IS" BASIS,
10+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+# See the License for the specific language governing permissions and
12+# limitations under the License.
13+#
14+# Contributor: STF-Zero <caoningxu@gmail.com>
15+# Maintainer: STF-Zero <caoningxu@gmail.com>
16+# buildtools=make HPKBUILD 骨架
17+pkgname=cmp
18+pkgver=v20
19+pkgrel=0
20+pkgdesc="cmp: a MessagePack (msgpack) serialization library written in C99 (single-file cmp.c/cmp.h)"
21+url="https://github.com/camgunz/cmp"
22+license=("MIT")
23+makedepends=()
24+source="https://github.com/camgunz/cmp/archive/refs/tags/v20.tar.gz"
25+archs=("armeabi-v7a" "arm64-v8a" "x86_64")
26+builddir=${pkgname}-${pkgver}
27+buildtools="make"
28+downloadpackage=true
29+autounpack=false
30+packagename=${pkgname}-${pkgver}.tar.gz
31+patchflag=false
32+depends=()
33+ 
34+prepare() {
35+ cd ${PKGBUILD_ROOT}
36+ extract_archive() {
37+ local _arc="$1" _dst="$2"
38+ cd "$_dst" || return 1
39+ case "$_arc" in
40+ *.tar.gz|*.tgz) tar -xzf "$_arc" ;;
41+ *.zip) unzip -qo "$_arc" ;;
42+ *) echo "unsupported archive: $_arc"; return 1 ;;
43+ esac
44+ }
45+ if [ ! -d "$builddir" ]; then
46+ extract_archive "${packagename}" "${PKGBUILD_ROOT}" || return 1
47+ fi
48+ # 目录名规范化:解压目录可能与 $builddir 不同名(pkgver 带 v 前缀、
49+ # GitHub 归档含 commit hash),finalize 清源重建时依赖此逻辑
50+ if [ ! -d "$builddir" ]; then
51+ for _d in *; do
52+ if [ -d "$_d" ] && [ "$_d" != "logs" ] && [ "$_d" != "hpkbuild_history" ] \
53+ && ! echo "$_d" | grep -q -- '-build$'; then
54+ if [ -f "$_d/CMakeLists.txt" ] || [ -f "$_d/configure" ] \
55+ || [ -f "$_d/Makefile" ]; then
56+ mv "$_d" "$builddir" 2>/dev/null && break
57+ fi
58+ fi
59+ done
60+ fi
61+ # 唯一目录兜底:patch 创建构建系统的库在打补丁前无构建标记,唯一普通
62+ # 目录直接规范化(poly1305 真实案例);多个候选时 fail closed。
63+ if [ ! -d "$builddir" ]; then
64+ _candidates=()
65+ for _d in *; do
66+ if [ -d "$_d" ] && [ "$_d" != "logs" ] && [ "$_d" != "hpkbuild_history" ] \
67+ && [ "${_d:0:1}" != "." ] && ! echo "$_d" | grep -q -- '-build$'; then
68+ _candidates+=("$_d")
69+ fi
70+ done
71+ if [ "${#_candidates[@]}" -eq 1 ]; then
72+ mv "${_candidates[0]}" "$builddir" 2>/dev/null || return 1
73+ fi
74+ fi
75+ [ -d "$builddir" ] || return 1
76+ # 双层嵌套规范化(nspr 实证):归档根 builddir/ 内含唯一源码目录
77+ # (如 builddir/nspr/ 有 configure)时提升到 builddir,否则 build() 在
78+ # 错误目录触发 autoreconf -> "configure.ac is required"。
79+ if [ ! -f "$builddir/configure" ] && [ ! -f "$builddir/configure.ac" ] \
80+ && [ ! -f "$builddir/CMakeLists.txt" ]; then
81+ _inner=""
82+ for _d in "$builddir"/*/; do
83+ [ -d "${_d%/}" ] || continue
84+ case "${_d%/}" in *-build|*logs*|*hpkbuild_history*) continue;; esac
85+ if [ -f "${_d}configure" ] || [ -f "${_d}configure.ac" ] \
86+ || [ -f "${_d}configure.in" ] || [ -f "${_d}CMakeLists.txt" ] \
87+ || [ -f "${_d}Makefile" ] || [ -f "${_d}meson.build" ]; then
88+ if [ -z "$_inner" ]; then _inner="${_d%/}"; else _inner=""; break; fi
89+ fi
90+ done
91+ if [ -n "$_inner" ]; then
92+ mv "$_inner" "${builddir}-__inner"
93+ rm -rf "$builddir"
94+ mv "${builddir}-__inner" "$builddir"
95+ echo "[nest] 双层嵌套源码已提升: $builddir" >> $buildlog
96+ fi
97+ fi
98+ # patch 应用:H+P 项目 clean rebuild 必须重放补丁(poly1305 真实案例)
99+ if $patchflag; then
100+ cd "$builddir" || return 1
101+ if [ ! -f .oh_patch_applied ]; then
102+ _PATCHED=0
103+ for _pl in 1 0 2; do
104+ patch -N -p${_pl} --batch --forward < "../${pkgname}_oh_pkg.patch" >/dev/null 2>&1
105+ _rc=$?
106+ if [ $_rc -eq 0 ]; then _PATCHED=1; break; fi
107+ _first=$(grep -m1 '^+++' "../${pkgname}_oh_pkg.patch" | sed 's/^+++ //; s/[[:space:]].*//; s/^[ab]\///')
108+ if [ -n "$_first" ] && [ -f "$_first" ]; then _PATCHED=1; break; fi
109+ done
110+ [ "$_PATCHED" -eq 1 ] || { echo "patch 应用失败(-p1/-p0/-p2 均无效)" >> $buildlog; return 1; }
111+ touch .oh_patch_applied
112+ fi
113+ cd ${PKGBUILD_ROOT}
114+ fi
115+ source envset.sh
116+ rm -rf ${builddir}-${ARCH}-build
117+ cp -r ${builddir} ${builddir}-${ARCH}-build
118+ return 0
119+}
120+ 
121+build() {
122+ cd ${PKGBUILD_ROOT}/${builddir}-${ARCH}-build || return 1
123+ # 按 ARCH 加载交叉编译环境(source envset.sh 只定义函数,必须调用
124+ # setarm32ENV/setarm64ENV/setx86_64ENV 才会设置 CC/AR/RANLIB——否则 make 得到空 CC)
125+ source envset.sh 2>/dev/null
126+ case "${ARCH}" in
127+ armeabi-v7a) setarm32ENV ;;
128+ arm64-v8a) setarm64ENV ;;
129+ x86_64) setx86_64ENV ;;
130+ *) echo "unsupported ARCH: ${ARCH}" >&2; return 1 ;;
131+ esac
132+ export CC AR RANLIB CFLAGS LDFLAGS
133+ # 上游 Makefile 的编译规则混入了:
134+ # EXTRA_CFLAGS ?= -Werror -Wall ... --pedantic-errors
135+ # CMPCFLAGS ?= -std=c89 -Wno-c99-extensions
136+ # 交叉编译 (cmp.c, clang) 时,cmp.h 经 <stdbool.h> 展开的 `_Bool` 属于
137+ # extension/pedantic 组诊断(非 -Wc99-extensions 组),故 -Wno-c99-extensions
138+ # 无法抑制它,--pedantic-errors + -Werror 直接把它升级为致命错误
139+ # ("'_Bool' is a C99 extension [-Werror,-Wc99-extensions]")。
140+ # 另外 default target(all) 会链接依赖 cmocka 的单元测试,交叉环境必然失败。
141+ # 修复:命令行覆盖这两个变量(make 命令行赋值优先于 Makefile 的 ?= 默认值),
142+ # 改用 -std=c99(_Bool 为标准类型,不再产生该告警),去掉 -Werror 与
143+ # --pedantic-errors,并只编译单文件库目标 cmp.o。
144+ make -j${JOB:-4} CC="${CC}" AR="${AR}" RANLIB="${RANLIB}" \
145+ CFLAGS="${CFLAGS}" LDFLAGS="${LDFLAGS}" \
146+ EXTRA_CFLAGS="-Wall -Wextra -funsigned-char -fwrapv" \
147+ CMPCFLAGS="-std=c99" \
148+ cmp.o >> $buildlog 2>&1 || return 1
149+ return 0
150+}
151+ 
152+package() {
153+ cd ${PKGBUILD_ROOT}/${builddir}-${ARCH}-build || return 1
154+ # package 与 build 未必共享 shell,重新加载交叉环境以拿到 CC/AR
155+ source envset.sh 2>/dev/null
156+ case "${ARCH}" in
157+ armeabi-v7a) setarm32ENV ;;
158+ arm64-v8a) setarm64ENV ;;
159+ x86_64) setx86_64ENV ;;
160+ esac
161+ export CC AR RANLIB CFLAGS LDFLAGS
162+ 
163+ # lycium 约定的安装前缀:lycium/usr/<pkgname>/<ARCH>。
164+ # 不能依赖未定义的 ${INSTALL_PREFIX}(为空会误建根目录 /include,
165+ # 触发 "mkdir: cannot create directory '/include': Permission denied")。
166+ local prefix="${LYCIUM_ROOT}/usr/${pkgname}/${ARCH}"
167+ mkdir -p "${prefix}/include" "${prefix}/lib" || return 1
168+ 
169+ # 先尝试上游 install 规则;cmp 是单文件库,上游 Makefile 只负责编译,
170+ # 可能根本没有 install 目标,此时继续走下面的手工安装(输出仍进 $buildlog)
171+ make install PREFIX="${prefix}" >> $buildlog 2>&1 \
172+ || echo "[cmp] 上游无可用 install 目标,回退为手工安装 cmp.h / libcmp.a" >> $buildlog
173+ 
174+ # 单文件库的稳定安装契约:cmp.h 头文件 + libcmp.a 静态库,
175+ # 供消费者冒烟程序直接 #include "cmp.h" 并链接
176+ if [ ! -f "${prefix}/include/cmp.h" ]; then
177+ cp -f cmp.h "${prefix}/include/cmp.h" >> $buildlog 2>&1 || return 1
178+ fi
179+ if [ ! -f "${prefix}/lib/libcmp.a" ]; then
180+ "${CC:-cc}" ${CFLAGS} -fPIC -I. -c cmp.c -o .oh_cmp.o >> $buildlog 2>&1 || return 1
181+ "${AR:-ar}" rcs "${prefix}/lib/libcmp.a" .oh_cmp.o >> $buildlog 2>&1 || return 1
182+ [ -z "${RANLIB}" ] || "${RANLIB}" "${prefix}/lib/libcmp.a" >> $buildlog 2>&1
183+ fi
184+ return 0
185+}
186+ 
187+cleanbuild() {
188+ cd ${PKGBUILD_ROOT}
189+ rm -rf ${PWD}/${builddir} ${PWD}/${builddir}-*-build
190+ return 0
191+}
192+ 
193+check() {
194+ echo "The test must be on an OpenHarmony device!"
195+}
@@ -0,0 +1,57 @@
1+#!/bin/sh
2+# Copyright (c) 2026 STF-Zero
3+# Licensed under the Apache License, Version 2.0 (the "License");
4+# you may not use this file except in compliance with the License.
5+# You may obtain a copy of the License at
6+#
7+# http://www.apache.org/licenses/LICENSE-2.0
8+#
9+# Unless required by applicable law or agreed to in writing, software
10+# distributed under the License is distributed on an "AS IS" BASIS,
11+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+# See the License for the specific language governing permissions and
13+# limitations under the License.
14+#
15+# Contributor: STF-Zero <caoningxu@gmail.com>
16+# Maintainer: STF-Zero <caoningxu@gmail.com>
17+# HARNESS_EXPECTED_CASES = 1
18+# HARNESS_TEST_ORIGIN = harness_authored
19+# HARNESS_HPKCHECK_AUTOGENERATED = 1
20+# HARNESS_SMOKE_SOURCE = consumer_smoke(cmp.h + libcmp.a)
21+# HARNESS_RUNTIME_FILES = harness_smoke/cmp_smoke
22+# HARNESS_RUNTIME_INSTALL = full
23+. ./HPKBUILD >/dev/null 2>&1
24+logfile=${LYCIUM_THIRDPARTY_ROOT}/${pkgname}/${pkgname}_${ARCH}_harness_test.log
25+build_root=${LYCIUM_THIRDPARTY_ROOT}/${pkgname}/${builddir}-${ARCH}-build
26+checkprepare() {
27+ for _d in "${LYCIUM_ROOT}"/usr/*/"${ARCH}"/lib; do
28+ [ -d "$_d" ] && LD_LIBRARY_PATH="${_d}:${LD_LIBRARY_PATH}"
29+ done
30+ export LD_LIBRARY_PATH
31+}
32+run_case() {
33+ case_name=$1
34+ binary=$2
35+ shift 2
36+ case_log=${logfile}.${case_name}
37+ if [ ! -x "${binary}" ]; then
38+ echo "missing harness smoke executable: ${binary}" > "${case_log}"
39+ result=1
40+ else
41+ (cd "${build_root}" && "${binary}" "$@") > "${case_log}" 2>&1
42+ result=$?
43+ fi
44+ cat "${case_log}" >> "${logfile}"
45+ if [ ${result} -eq 0 ]; then
46+ echo "HARNESS_CASE ${case_name} PASS" | tee -a "${logfile}"
47+ else
48+ echo "HARNESS_CASE ${case_name} FAIL" | tee -a "${logfile}"
49+ fi
50+ return ${result}
51+}
52+openharmonycheck() {
53+ : > "${logfile}"
54+ status=0
55+ run_case harness-smoke "${build_root}/harness_smoke/cmp_smoke" || status=1
56+ return ${status}
57+}
@@ -0,0 +1,16 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<configuration>
3+ <oatconfig>
4+ <filefilterlist>
5+ <filefilter name="copyrightPolicyFilter" desc="Filters for compatibility,license header policies">
6+ <filteritem type="filename" name="SHA512SUM" desc="SHA512SUM文件,不添加版权头"/>
7+ </filefilter>
8+ <filefilter name="defaultPolicyFilter" desc="Filters for compatibility,license header policies">
9+ <filteritem type="filename" name="SHA512SUM" desc="SHA512SUM文件,不添加版权头"/>
10+ </filefilter>
11+ <filefilter name="binaryFileTypePolicyFilter" desc="Filters for resources files policies">
12+ <filteritem type="filename" name="*.png" desc="指导文档需要的png图片"/>
13+ </filefilter>
14+ </filefilterlist>
15+ </oatconfig>
16+</configuration>
@@ -0,0 +1,11 @@
1+[
2+ {
3+ "Name": "cmp",
4+ "License": "MIT",
5+ "License File": "https://github.com/camgunz/cmp/blob/master/LICENSE",
6+ "Version Number": "v20",
7+ "Owner": "caoningxu@gmail.com",
8+ "Upstream URL": "https://github.com/camgunz/cmp",
9+ "Description": "cmp: a MessagePack (msgpack) serialization library written in C99 (single-file cmp.c/cmp.h)"
10+ }
11+]
@@ -0,0 +1,27 @@
1+# cmp三方库说明
2+ 
3+## 功能简介
4+ 
5+cmp: a MessagePack (msgpack) serialization library written in C99 (single-file cmp.c/cmp.h)
6+ 
7+- 上游地址:https://github.com/camgunz/cmp
8+- 版本:v20
9+- 开源协议:MIT
10+- 支持的架构:armeabi-v7a, arm64-v8a, x86_64
11+- 构建方式:make
12+ 
13+## 三方库版本
14+ 
15+- v20
16+ 
17+## 已适配功能
18+ 
19+- CMP is a C implementation of the MessagePack serialization format. It currently implements version 5 of the MessagePack Spec
20+ 
21+## 使用约束
22+ 
23+- [IDE和SDK版本](../../docs/constraint.md)
24+ 
25+## 集成方式
26+ 
27+[应用包hap集成](docs/hap_integrate.md)
@@ -0,0 +1 @@
1+f747cb9672592d8c06d08786152a0bfbd6ae4d759d7006805913781c502bf3796241ade636ce2cf9c049f68dd2899e2d5d7008815f29c1a91fc797590a26a9fd cmp-v20.tar.gz
@@ -0,0 +1,105 @@
1+# cmp如何集成到应用hap
2+ 
3+本库已基于 OpenHarmony 镜像完成交叉编译与设备端加载验证(版本 v20)。
4+ 
5+实测环境:`arm64-v8a`(QEMU 裁剪镜像(模拟),目标 `127.0.0.1:5855`,`uname -m=aarch64`);`armeabi-v7a`(QEMU 裁剪镜像(模拟),目标 `127.0.0.1:5755`,`uname -m=armv7l`)。
6+ 
7+以上均为**模拟运行环境,不是物理真机**;真机(开发板/手机/平板)验证:**未做**(上方均为模拟环境)。
8+社区标准验证环境为 [润和 RK3568 开发板](https://gitee.com/openharmony-sig/knowledge_demo_temp/tree/master/docs/rk3568_helloworld)(OpenHarmony 3.2 Release 镜像),本库未使用该开发板;验证过程与结果见 `docs/pic/` 截图。
9+ 
10+## 准备应用工程
11+ 
12+### 准备应用开发环境
13+ 
14+- [开发环境准备](../../../docs/hap_integrate_environment.md)
15+ 
16+### 增加构建脚本及配置文件
17+ 
18+本库的构建脚本与配置文件:`HPKBUILD`(交叉编译脚本)、`HPKCHECK`(设备端测试入口)、`OAT.xml`(版权头豁免),详见 [HPKBUILD](../HPKBUILD) 与 [HPKCHECK](../HPKCHECK)。
19+ 
20+应用工程侧,在最外层(cpp 目录下)`CMakeLists.txt` 中添加如下语句:
21+ 
22+```shell
23+ #将三方库加入工程中
24+ target_link_libraries(entry PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/cmp/${OHOS_ARCH}/lib/libcmp.so)
25+ 
26+ #将三方库的头文件加入工程中
27+ target_include_directories(entry PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/cmp/${OHOS_ARCH}/include)
28+```
29+ 
30+### 准备三方库源码
31+ 
32+- 下载本仓库
33+ 
34+ ```shell
35+ git clone https://gitcode.com/CPF-ApplicationTPC/tpc_c_cplusplus.git --depth=1
36+ ```
37+ 
38+- 三方库目录结构
39+ 
40+ ```shell
41+ tpc_c_cplusplus/community/cmp #三方库cmp的目录结构如下
42+ ├── docs #三方库相关文档的文件夹
43+ ├── HPKBUILD #构建脚本
44+ ├── HPKCHECK #测试脚本
45+ ├── SHA512SUM #三方库校验文件
46+ ├── OAT.xml #OAT开源审查文本文件
47+ ├── README.OpenSource #说明三方库源码的下载地址,版本,license等信息
48+ ├── README_zh.md #三方库简介
49+ ```
50+ 
51+## 应用中使用三方库
52+ 
53+- 在IDE的cpp目录下新增thirdparty目录,将编译产物 `lycium/usr/cmp/<abi>/` 下的 `include/` 与 `lib/` 拷贝进去,形成 `cpp/thirdparty/cmp/<abi>/{include,lib}`(动态库名字带版本号和不带版本号的都需要;`share/`、`cmake/` 等非头文件/库内容可以不拷),如下图所示:
54+ 
55+ &nbsp;
56+ 
57+ &nbsp;![thirdparty_install_dir](pic/cmp_install_dir.png)
58+ 
59+## 编译工程
60+ 
61+- 在lycium目录下编译三方库
62+ 
63+ 编译环境的搭建参考[准备三方库构建环境](../../../lycium/README.md#1编译环境准备)
64+ 
65+ ```shell
66+ cd lycium
67+ ./build.sh cmp
68+ ```
69+ 
70+- 三方库头文件及生成的库
71+ 
72+ 在lycium目录下会生成usr目录,该目录下存在已编译完成的32位和64位三方库
73+ 
74+ ```shell
75+ cmp/armeabi-v7a cmp/arm64-v8a cmp/x86_64
76+ ```
77+ 
78+- [测试三方库](#测试三方库)
79+ 
80+## 测试三方库
81+ 
82+- 上游未提供可独立交叉编译的测试套件,本库交付的是自撰的消费者冒烟用例与符号级探针,已随 `HPKCHECK` 下发设备执行。
83+ 
84+- 进入构建目录运行冒烟用例(`arm64-v8a` 为构建64位的目录,`armeabi-v7a` 为构建32位的目录),执行结果如图所示:
85+ 
86+```shell
87+ cd /data/tpc_c_cplusplus/thirdparty/cmp/cmp-v20-arm64-v8a-build/
88+ ./harness_smoke/cmp_smoke
89+```
90+ 
91+&nbsp;![arm64](pic/arm64.png)
92+&nbsp;![armv7a](pic/armv7a.png)
93+&nbsp;![x86_64](pic/x86_64.png)
94+ 
95+## 运行效果
96+ 
97+本库已完成设备端加载与用例验证(设备端执行记录见 `docs/pic/` 截图);应用侧(HAP)集成后的运行效果截图后续补充。
98+ 
99+## 参考资料
100+ 
101+- [润和RK3568开发板标准系统快速上手](https://gitee.com/openharmony-sig/knowledge_demo_temp/tree/master/docs/rk3568_helloworld)
102+- [OpenHarmony三方库地址](https://gitee.com/openharmony-tpc)
103+- [OpenHarmony知识体系](https://gitee.com/openharmony-sig/knowledge)
104+- [通过DevEco Studio开发一个NAPI工程](https://gitee.com/openharmony-sig/knowledge_demo_temp/blob/master/docs/napi_study/docs/hello_napi.md)
105+- 上游源码:https://github.com/camgunz/cmp/archive/refs/tags/v20.tar.gz